vendor/symfony/form/AbstractRendererEngine.php line 82

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  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 <bschussek@gmail.com>
  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$themes$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] = (bool) $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 $view$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 $blockNameHierarchy$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 $blockNameHierarchy$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.      * @param string   $cacheKey  The cache key of the form view
  113.      * @param FormView $view      The form view for finding the applying themes
  114.      * @param string   $blockName The name of the block to load
  115.      *
  116.      * @return bool True if the resource could be loaded, false otherwise
  117.      */
  118.     abstract protected function loadResourceForBlockName($cacheKeyFormView $view$blockName);
  119.     /**
  120.      * Loads the cache with the resource for a specific level of a block hierarchy.
  121.      *
  122.      * @see getResourceForBlockHierarchy()
  123.      */
  124.     private function loadResourceForBlockNameHierarchy(string $cacheKeyFormView $view, array $blockNameHierarchyint $hierarchyLevel): bool
  125.     {
  126.         $blockName $blockNameHierarchy[$hierarchyLevel];
  127.         // Try to find a template for that block
  128.         if ($this->loadResourceForBlockName($cacheKey$view$blockName)) {
  129.             // If loadTemplateForBlock() returns true, it was able to populate the
  130.             // cache. The only missing thing is to set the hierarchy level at which
  131.             // the template was found.
  132.             $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel;
  133.             return true;
  134.         }
  135.         if ($hierarchyLevel 0) {
  136.             $parentLevel $hierarchyLevel 1;
  137.             $parentBlockName $blockNameHierarchy[$parentLevel];
  138.             // The next two if statements contain slightly duplicated code. This is by intention
  139.             // and tries to avoid execution of unnecessary checks in order to increase performance.
  140.             if (isset($this->resources[$cacheKey][$parentBlockName])) {
  141.                 // It may happen that the parent block is already loaded, but its level is not.
  142.                 // In this case, the parent block must have been loaded by loadResourceForBlock(),
  143.                 // which does not check the hierarchy of the block. Subsequently the block must have
  144.                 // been found directly on the parent level.
  145.                 if (!isset($this->resourceHierarchyLevels[$cacheKey][$parentBlockName])) {
  146.                     $this->resourceHierarchyLevels[$cacheKey][$parentBlockName] = $parentLevel;
  147.                 }
  148.                 // Cache the shortcuts for further accesses
  149.                 $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName];
  150.                 $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName];
  151.                 return true;
  152.             }
  153.             if ($this->loadResourceForBlockNameHierarchy($cacheKey$view$blockNameHierarchy$parentLevel)) {
  154.                 // Cache the shortcuts for further accesses
  155.                 $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName];
  156.                 $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName];
  157.                 return true;
  158.             }
  159.         }
  160.         // Cache the result for further accesses
  161.         $this->resources[$cacheKey][$blockName] = false;
  162.         $this->resourceHierarchyLevels[$cacheKey][$blockName] = false;
  163.         return false;
  164.     }
  165. }