vendor/sonata-project/block-bundle/src/Block/BlockRenderer.php line 85

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of the Sonata Project package.
  5.  *
  6.  * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  7.  *
  8.  * For the full copyright and license information, please view the LICENSE
  9.  * file that was distributed with this source code.
  10.  */
  11. namespace Sonata\BlockBundle\Block;
  12. use Psr\Log\LoggerInterface;
  13. use Sonata\BlockBundle\Exception\Strategy\StrategyManagerInterface;
  14. use Symfony\Component\HttpFoundation\Response;
  15. /**
  16.  * Handles the execution and rendering of a block.
  17.  *
  18.  * This function render a block and make sure the cacheable information are correctly retrieved
  19.  * and set to the upper response (container can have child blocks, so the smallest ttl from a child
  20.  * must be used in the container).
  21.  *
  22.  * @final since sonata-project/block-bundle 3.0
  23.  */
  24. class BlockRenderer implements BlockRendererInterface
  25. {
  26.     /**
  27.      * @var BlockServiceManagerInterface
  28.      */
  29.     protected $blockServiceManager;
  30.     /**
  31.      * @var StrategyManagerInterface
  32.      */
  33.     protected $exceptionStrategyManager;
  34.     /**
  35.      * @var LoggerInterface|null
  36.      */
  37.     protected $logger;
  38.     /**
  39.      * @var bool
  40.      */
  41.     protected $debug;
  42.     /**
  43.      * This property hold the last response available from the child or sibling block
  44.      * The cacheable attributes must be cascaded to the parent.
  45.      *
  46.      * @var Response|null
  47.      */
  48.     private $lastResponse;
  49.     /**
  50.      * @param BlockServiceManagerInterface $blockServiceManager      Block service manager
  51.      * @param StrategyManagerInterface     $exceptionStrategyManager Exception strategy manager
  52.      * @param LoggerInterface              $logger                   Logger class
  53.      * @param bool                         $debug                    Whether in debug mode or not
  54.      */
  55.     public function __construct(BlockServiceManagerInterface $blockServiceManagerStrategyManagerInterface $exceptionStrategyManagerLoggerInterface $logger null$debug false)
  56.     {
  57.         $this->blockServiceManager $blockServiceManager;
  58.         $this->exceptionStrategyManager $exceptionStrategyManager;
  59.         $this->logger $logger;
  60.         $this->debug $debug;
  61.     }
  62.     public function render(BlockContextInterface $blockContextResponse $response null)
  63.     {
  64.         $block $blockContext->getBlock();
  65.         if ($this->logger) {
  66.             $this->logger->info(sprintf('[cms::renderBlock] block.id=%d, block.type=%s '$block->getId(), $block->getType()));
  67.         }
  68.         try {
  69.             $service $this->blockServiceManager->get($block);
  70.             $service->load($block);
  71.             $response $service->execute($blockContext$this->createResponse($blockContext$response));
  72.             if (!$response instanceof Response) {
  73.                 $response null;
  74.                 throw new \RuntimeException('A block service must return a Response object');
  75.             }
  76.             $response $this->addMetaInformation($response$blockContext$service);
  77.         } catch (\Exception $exception) {
  78.             if ($this->logger) {
  79.                 $this->logger->error(sprintf(
  80.                     '[cms::renderBlock] block.id=%d - error while rendering block - %s',
  81.                     $block->getId(),
  82.                     $exception->getMessage()
  83.                 ), compact('exception'));
  84.             }
  85.             // reseting the state object
  86.             $this->lastResponse null;
  87.             $response $this->exceptionStrategyManager->handleException($exception$blockContext->getBlock(), $response);
  88.         }
  89.         return $response;
  90.     }
  91.     /**
  92.      * @return Response
  93.      */
  94.     protected function createResponse(BlockContextInterface $blockContextResponse $response null)
  95.     {
  96.         if (null === $response) {
  97.             $response = new Response();
  98.         }
  99.         // set the ttl from the block instance, this can be changed by the BlockService
  100.         if (($ttl $blockContext->getBlock()->getTtl()) > 0) {
  101.             $response->setTtl($ttl);
  102.         }
  103.         return $response;
  104.     }
  105.     /**
  106.      * This method is responsible to cascade ttl to the parent block.
  107.      *
  108.      * @return Response
  109.      */
  110.     protected function addMetaInformation(Response $responseBlockContextInterface $blockContextBlockServiceInterface $service)
  111.     {
  112.         // a response exists, use it
  113.         if ($this->lastResponse && $this->lastResponse->isCacheable()) {
  114.             $response->setTtl($this->lastResponse->getTtl());
  115.             $response->setPublic();
  116.         } elseif ($this->lastResponse) { // not cacheable
  117.             $response->setPrivate();
  118.             $response->setTtl(0);
  119.             $response->headers->removeCacheControlDirective('s-maxage');
  120.             $response->headers->removeCacheControlDirective('maxage');
  121.         }
  122.         // no more children available in the stack, reseting the state object
  123.         if (!$blockContext->getBlock()->hasParent()) {
  124.             $this->lastResponse null;
  125.         } else { // contains a parent so storing the response
  126.             $this->lastResponse $response;
  127.         }
  128.         return $response;
  129.     }
  130. }