Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\HttpKernel\Fragment; Chris@0: Chris@17: use Symfony\Component\HttpFoundation\RequestStack; Chris@0: use Symfony\Component\HttpFoundation\Response; Chris@0: use Symfony\Component\HttpFoundation\StreamedResponse; Chris@0: use Symfony\Component\HttpKernel\Controller\ControllerReference; Chris@0: Chris@0: /** Chris@0: * Renders a URI that represents a resource fragment. Chris@0: * Chris@0: * This class handles the rendering of resource fragments that are included into Chris@0: * a main resource. The handling of the rendering is managed by specialized renderers. Chris@0: * Chris@0: * @author Fabien Potencier Chris@0: * Chris@0: * @see FragmentRendererInterface Chris@0: */ Chris@0: class FragmentHandler Chris@0: { Chris@0: private $debug; Chris@17: private $renderers = []; Chris@0: private $requestStack; Chris@0: Chris@0: /** Chris@0: * @param RequestStack $requestStack The Request stack that controls the lifecycle of requests Chris@0: * @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances Chris@0: * @param bool $debug Whether the debug mode is enabled or not Chris@0: */ Chris@17: public function __construct(RequestStack $requestStack, array $renderers = [], $debug = false) Chris@0: { Chris@0: $this->requestStack = $requestStack; Chris@0: foreach ($renderers as $renderer) { Chris@0: $this->addRenderer($renderer); Chris@0: } Chris@0: $this->debug = $debug; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Adds a renderer. Chris@0: */ Chris@0: public function addRenderer(FragmentRendererInterface $renderer) Chris@0: { Chris@0: $this->renderers[$renderer->getName()] = $renderer; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Renders a URI and returns the Response content. Chris@0: * Chris@0: * Available options: Chris@0: * Chris@0: * * ignore_errors: true to return an empty string in case of an error Chris@0: * Chris@0: * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance Chris@0: * @param string $renderer The renderer name Chris@0: * @param array $options An array of options Chris@0: * Chris@0: * @return string|null The Response content or null when the Response is streamed Chris@0: * Chris@0: * @throws \InvalidArgumentException when the renderer does not exist Chris@0: * @throws \LogicException when no master request is being handled Chris@0: */ Chris@17: public function render($uri, $renderer = 'inline', array $options = []) Chris@0: { Chris@0: if (!isset($options['ignore_errors'])) { Chris@0: $options['ignore_errors'] = !$this->debug; Chris@0: } Chris@0: Chris@0: if (!isset($this->renderers[$renderer])) { Chris@0: throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer)); Chris@0: } Chris@0: Chris@0: if (!$request = $this->requestStack->getCurrentRequest()) { Chris@0: throw new \LogicException('Rendering a fragment can only be done when handling a Request.'); Chris@0: } Chris@0: Chris@0: return $this->deliver($this->renderers[$renderer]->render($uri, $request, $options)); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Delivers the Response as a string. Chris@0: * Chris@0: * When the Response is a StreamedResponse, the content is streamed immediately Chris@0: * instead of being returned. Chris@0: * Chris@0: * @return string|null The Response content or null when the Response is streamed Chris@0: * Chris@0: * @throws \RuntimeException when the Response is not successful Chris@0: */ Chris@0: protected function deliver(Response $response) Chris@0: { Chris@0: if (!$response->isSuccessful()) { Chris@0: throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->requestStack->getCurrentRequest()->getUri(), $response->getStatusCode())); Chris@0: } Chris@0: Chris@0: if (!$response instanceof StreamedResponse) { Chris@0: return $response->getContent(); Chris@0: } Chris@0: Chris@0: $response->sendContent(); Chris@0: } Chris@0: }