vendor/symfony/form/AbstractRendererEngine.php line 84

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