vendor/symfony/form/ChoiceList/Factory/CachingFactoryDecorator.php line 178

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\ChoiceList\Factory;
  11. use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
  12. use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
  13. use Symfony\Component\Form\ChoiceList\View\ChoiceListView;
  14. use Symfony\Contracts\Service\ResetInterface;
  15. /**
  16.  * Caches the choice lists created by the decorated factory.
  17.  *
  18.  * To cache a list based on its options, arguments must be decorated
  19.  * by a {@see Cache\AbstractStaticOption} implementation.
  20.  *
  21.  * @author Bernhard Schussek <bschussek@gmail.com>
  22.  * @author Jules Pietri <jules@heahprod.com>
  23.  */
  24. class CachingFactoryDecorator implements ChoiceListFactoryInterfaceResetInterface
  25. {
  26.     private $decoratedFactory;
  27.     /**
  28.      * @var ChoiceListInterface[]
  29.      */
  30.     private $lists = [];
  31.     /**
  32.      * @var ChoiceListView[]
  33.      */
  34.     private $views = [];
  35.     /**
  36.      * Generates a SHA-256 hash for the given value.
  37.      *
  38.      * Optionally, a namespace string can be passed. Calling this method will
  39.      * the same values, but different namespaces, will return different hashes.
  40.      *
  41.      * @param mixed $value The value to hash
  42.      *
  43.      * @return string The SHA-256 hash
  44.      *
  45.      * @internal
  46.      */
  47.     public static function generateHash($valuestring $namespace ''): string
  48.     {
  49.         if (\is_object($value)) {
  50.             $value spl_object_hash($value);
  51.         } elseif (\is_array($value)) {
  52.             array_walk_recursive($value, function (&$v) {
  53.                 if (\is_object($v)) {
  54.                     $v spl_object_hash($v);
  55.                 }
  56.             });
  57.         }
  58.         return hash('sha256'$namespace.':'.serialize($value));
  59.     }
  60.     public function __construct(ChoiceListFactoryInterface $decoratedFactory)
  61.     {
  62.         $this->decoratedFactory $decoratedFactory;
  63.     }
  64.     /**
  65.      * Returns the decorated factory.
  66.      *
  67.      * @return ChoiceListFactoryInterface
  68.      */
  69.     public function getDecoratedFactory()
  70.     {
  71.         return $this->decoratedFactory;
  72.     }
  73.     /**
  74.      * {@inheritdoc}
  75.      *
  76.      * @param mixed $value
  77.      * @param mixed $filter
  78.      */
  79.     public function createListFromChoices(iterable $choices$value null/* , $filter = null */)
  80.     {
  81.         $filter = \func_num_args() > func_get_arg(2) : null;
  82.         if ($choices instanceof \Traversable) {
  83.             $choices iterator_to_array($choices);
  84.         }
  85.         $cache true;
  86.         // Only cache per value and filter when needed. The value is not validated on purpose.
  87.         // The decorated factory may decide which values to accept and which not.
  88.         if ($value instanceof Cache\ChoiceValue) {
  89.             $value $value->getOption();
  90.         } elseif ($value) {
  91.             $cache false;
  92.         }
  93.         if ($filter instanceof Cache\ChoiceFilter) {
  94.             $filter $filter->getOption();
  95.         } elseif ($filter) {
  96.             $cache false;
  97.         }
  98.         if (!$cache) {
  99.             return $this->decoratedFactory->createListFromChoices($choices$value$filter);
  100.         }
  101.         $hash self::generateHash([$choices$value$filter], 'fromChoices');
  102.         if (!isset($this->lists[$hash])) {
  103.             $this->lists[$hash] = $this->decoratedFactory->createListFromChoices($choices$value$filter);
  104.         }
  105.         return $this->lists[$hash];
  106.     }
  107.     /**
  108.      * {@inheritdoc}
  109.      *
  110.      * @param mixed $value
  111.      * @param mixed $filter
  112.      */
  113.     public function createListFromLoader(ChoiceLoaderInterface $loader$value null/* , $filter = null */)
  114.     {
  115.         $filter = \func_num_args() > func_get_arg(2) : null;
  116.         $cache true;
  117.         if ($loader instanceof Cache\ChoiceLoader) {
  118.             $loader $loader->getOption();
  119.         } else {
  120.             $cache false;
  121.         }
  122.         if ($value instanceof Cache\ChoiceValue) {
  123.             $value $value->getOption();
  124.         } elseif ($value) {
  125.             $cache false;
  126.         }
  127.         if ($filter instanceof Cache\ChoiceFilter) {
  128.             $filter $filter->getOption();
  129.         } elseif ($filter) {
  130.             $cache false;
  131.         }
  132.         if (!$cache) {
  133.             return $this->decoratedFactory->createListFromLoader($loader$value$filter);
  134.         }
  135.         $hash self::generateHash([$loader$value$filter], 'fromLoader');
  136.         if (!isset($this->lists[$hash])) {
  137.             $this->lists[$hash] = $this->decoratedFactory->createListFromLoader($loader$value$filter);
  138.         }
  139.         return $this->lists[$hash];
  140.     }
  141.     /**
  142.      * {@inheritdoc}
  143.      *
  144.      * @param mixed $preferredChoices
  145.      * @param mixed $label
  146.      * @param mixed $index
  147.      * @param mixed $groupBy
  148.      * @param mixed $attr
  149.      * @param mixed $labelTranslationParameters
  150.      */
  151.     public function createView(ChoiceListInterface $list$preferredChoices null$label null$index null$groupBy null$attr null/* , $labelTranslationParameters = [] */)
  152.     {
  153.         $labelTranslationParameters = \func_num_args() > func_get_arg(6) : [];
  154.         $cache true;
  155.         if ($preferredChoices instanceof Cache\PreferredChoice) {
  156.             $preferredChoices $preferredChoices->getOption();
  157.         } elseif ($preferredChoices) {
  158.             $cache false;
  159.         }
  160.         if ($label instanceof Cache\ChoiceLabel) {
  161.             $label $label->getOption();
  162.         } elseif (null !== $label) {
  163.             $cache false;
  164.         }
  165.         if ($index instanceof Cache\ChoiceFieldName) {
  166.             $index $index->getOption();
  167.         } elseif ($index) {
  168.             $cache false;
  169.         }
  170.         if ($groupBy instanceof Cache\GroupBy) {
  171.             $groupBy $groupBy->getOption();
  172.         } elseif ($groupBy) {
  173.             $cache false;
  174.         }
  175.         if ($attr instanceof Cache\ChoiceAttr) {
  176.             $attr $attr->getOption();
  177.         } elseif ($attr) {
  178.             $cache false;
  179.         }
  180.         if ($labelTranslationParameters instanceof Cache\ChoiceTranslationParameters) {
  181.             $labelTranslationParameters $labelTranslationParameters->getOption();
  182.         } elseif ([] !== $labelTranslationParameters) {
  183.             $cache false;
  184.         }
  185.         if (!$cache) {
  186.             return $this->decoratedFactory->createView(
  187.                 $list,
  188.                 $preferredChoices,
  189.                 $label,
  190.                 $index,
  191.                 $groupBy,
  192.                 $attr,
  193.                 $labelTranslationParameters
  194.             );
  195.         }
  196.         $hash self::generateHash([$list$preferredChoices$label$index$groupBy$attr$labelTranslationParameters]);
  197.         if (!isset($this->views[$hash])) {
  198.             $this->views[$hash] = $this->decoratedFactory->createView(
  199.                 $list,
  200.                 $preferredChoices,
  201.                 $label,
  202.                 $index,
  203.                 $groupBy,
  204.                 $attr,
  205.                 $labelTranslationParameters
  206.             );
  207.         }
  208.         return $this->views[$hash];
  209.     }
  210.     public function reset()
  211.     {
  212.         $this->lists = [];
  213.         $this->views = [];
  214.         Cache\AbstractStaticOption::reset();
  215.     }
  216. }