vendor/symfony/form/AbstractRendererEngine.php line 87

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <[email protected]>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Form;
  11. /**
  12.  * Default implementation of {@link FormRendererEngineInterface}.
  13.  *
  14.  * @author Bernhard Schussek <[email protected]>
  15.  */
  16. abstract class AbstractRendererEngine implements FormRendererEngineInterface
  17. {
  18.     /**
  19.      * The variable in {@link FormView} used as cache key.
  20.      */
  21.     public const CACHE_KEY_VAR 'cache_key';
  22.     /**
  23.      * @var array
  24.      */
  25.     protected $defaultThemes;
  26.     /**
  27.      * @var array[]
  28.      */
  29.     protected $themes = [];
  30.     /**
  31.      * @var bool[]
  32.      */
  33.     protected $useDefaultThemes = [];
  34.     /**
  35.      * @var array[]
  36.      */
  37.     protected $resources = [];
  38.     /**
  39.      * @var array<array<int|false>>
  40.      */
  41.     private $resourceHierarchyLevels = [];
  42.     /**
  43.      * Creates a new renderer engine.
  44.      *
  45.      * @param array $defaultThemes The default themes. The type of these
  46.      *                             themes is open to the implementation.
  47.      */
  48.     public function __construct(array $defaultThemes = [])
  49.     {
  50.         $this->defaultThemes $defaultThemes;
  51.     }
  52.     /**
  53.      * {@inheritdoc}
  54.      */
  55.     public function setTheme(FormView $view$themesbool $useDefaultThemes true)
  56.     {
  57.         $cacheKey $view->vars[self::CACHE_KEY_VAR];
  58.         // Do not cast, as casting turns objects into arrays of properties
  59.         $this->themes[$cacheKey] = \is_array($themes) ? $themes : [$themes];
  60.         $this->useDefaultThemes[$cacheKey] = $useDefaultThemes;
  61.         // Unset instead of resetting to an empty array, in order to allow
  62.         // implementations (like TwigRendererEngine) to check whether $cacheKey
  63.         // is set at all.
  64.         unset($this->resources[$cacheKey], $this->resourceHierarchyLevels[$cacheKey]);
  65.     }
  66.     /**
  67.      * {@inheritdoc}
  68.      */
  69.     public function getResourceForBlockName(FormView $viewstring $blockName)
  70.     {
  71.         $cacheKey $view->vars[self::CACHE_KEY_VAR];
  72.         if (!isset($this->resources[$cacheKey][$blockName])) {
  73.             $this->loadResourceForBlockName($cacheKey$view$blockName);
  74.         }
  75.         return $this->resources[$cacheKey][$blockName];
  76.     }
  77.     /**
  78.      * {@inheritdoc}
  79.      */
  80.     public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchyint $hierarchyLevel)
  81.     {
  82.         $cacheKey $view->vars[self::CACHE_KEY_VAR];
  83.         $blockName $blockNameHierarchy[$hierarchyLevel];
  84.         if (!isset($this->resources[$cacheKey][$blockName])) {
  85.             $this->loadResourceForBlockNameHierarchy($cacheKey$view$blockNameHierarchy$hierarchyLevel);
  86.         }
  87.         return $this->resources[$cacheKey][$blockName];
  88.     }
  89.     /**
  90.      * {@inheritdoc}
  91.      */
  92.     public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchyint $hierarchyLevel)
  93.     {
  94.         $cacheKey $view->vars[self::CACHE_KEY_VAR];
  95.         $blockName $blockNameHierarchy[$hierarchyLevel];
  96.         if (!isset($this->resources[$cacheKey][$blockName])) {
  97.             $this->loadResourceForBlockNameHierarchy($cacheKey$view$blockNameHierarchy$hierarchyLevel);
  98.         }
  99.         // If $block was previously rendered loaded with loadTemplateForBlock(), the template
  100.         // is cached but the hierarchy level is not. In this case, we know that the  block
  101.         // exists at this very hierarchy level, so we can just set it.
  102.         if (!isset($this->resourceHierarchyLevels[$cacheKey][$blockName])) {
  103.             $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel;
  104.         }
  105.         return $this->resourceHierarchyLevels[$cacheKey][$blockName];
  106.     }
  107.     /**
  108.      * Loads the cache with the resource for a given block name.
  109.      *
  110.      * @see getResourceForBlock()
  111.      *
  112.      * @return bool True if the resource could be loaded, false otherwise
  113.      */
  114.     abstract protected function loadResourceForBlockName(string $cacheKeyFormView $viewstring $blockName);
  115.     /**
  116.      * Loads the cache with the resource for a specific level of a block hierarchy.
  117.      *
  118.      * @see getResourceForBlockHierarchy()
  119.      */
  120.     private function loadResourceForBlockNameHierarchy(string $cacheKeyFormView $view, array $blockNameHierarchyint $hierarchyLevel): bool
  121.     {
  122.         $blockName $blockNameHierarchy[$hierarchyLevel];
  123.         // Try to find a template for that block
  124.         if ($this->loadResourceForBlockName($cacheKey$view$blockName)) {
  125.             // If loadTemplateForBlock() returns true, it was able to populate the
  126.             // cache. The only missing thing is to set the hierarchy level at which
  127.             // the template was found.
  128.             $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel;
  129.             return true;
  130.         }
  131.         if ($hierarchyLevel 0) {
  132.             $parentLevel $hierarchyLevel 1;
  133.             $parentBlockName $blockNameHierarchy[$parentLevel];
  134.             // The next two if statements contain slightly duplicated code. This is by intention
  135.             // and tries to avoid execution of unnecessary checks in order to increase performance.
  136.             if (isset($this->resources[$cacheKey][$parentBlockName])) {
  137.                 // It may happen that the parent block is already loaded, but its level is not.
  138.                 // In this case, the parent block must have been loaded by loadResourceForBlock(),
  139.                 // which does not check the hierarchy of the block. Subsequently the block must have
  140.                 // been found directly on the parent level.
  141.                 if (!isset($this->resourceHierarchyLevels[$cacheKey][$parentBlockName])) {
  142.                     $this->resourceHierarchyLevels[$cacheKey][$parentBlockName] = $parentLevel;
  143.                 }
  144.                 // Cache the shortcuts for further accesses
  145.                 $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName];
  146.                 $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName];
  147.                 return true;
  148.             }
  149.             if ($this->loadResourceForBlockNameHierarchy($cacheKey$view$blockNameHierarchy$parentLevel)) {
  150.                 // Cache the shortcuts for further accesses
  151.                 $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName];
  152.                 $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName];
  153.                 return true;
  154.             }
  155.         }
  156.         // Cache the result for further accesses
  157.         $this->resources[$cacheKey][$blockName] = false;
  158.         $this->resourceHierarchyLevels[$cacheKey][$blockName] = false;
  159.         return false;
  160.     }
  161. }