vendor/symfony/form/ChoiceList/Factory/PropertyAccessDecorator.php line 154

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\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\Component\PropertyAccess\Exception\UnexpectedTypeException;
  15. use Symfony\Component\PropertyAccess\PropertyAccess;
  16. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  17. use Symfony\Component\PropertyAccess\PropertyPath;
  18. use Symfony\Component\PropertyAccess\PropertyPathInterface;
  19. /**
  20.  * Adds property path support to a choice list factory.
  21.  *
  22.  * Pass the decorated factory to the constructor:
  23.  *
  24.  *     $decorator = new PropertyAccessDecorator($factory);
  25.  *
  26.  * You can now pass property paths for generating choice values, labels, view
  27.  * indices, HTML attributes and for determining the preferred choices and the
  28.  * choice groups:
  29.  *
  30.  *     // extract values from the $value property
  31.  *     $list = $createListFromChoices($objects, 'value');
  32.  *
  33.  * @author Bernhard Schussek <[email protected]>
  34.  */
  35. class PropertyAccessDecorator implements ChoiceListFactoryInterface
  36. {
  37.     private $decoratedFactory;
  38.     private $propertyAccessor;
  39.     public function __construct(ChoiceListFactoryInterface $decoratedFactory, ?PropertyAccessorInterface $propertyAccessor null)
  40.     {
  41.         $this->decoratedFactory $decoratedFactory;
  42.         $this->propertyAccessor $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
  43.     }
  44.     /**
  45.      * Returns the decorated factory.
  46.      *
  47.      * @return ChoiceListFactoryInterface
  48.      */
  49.     public function getDecoratedFactory()
  50.     {
  51.         return $this->decoratedFactory;
  52.     }
  53.     /**
  54.      * {@inheritdoc}
  55.      *
  56.      * @param mixed $value
  57.      * @param mixed $filter
  58.      *
  59.      * @return ChoiceListInterface
  60.      */
  61.     public function createListFromChoices(iterable $choices$value null/* , $filter = null */)
  62.     {
  63.         $filter \func_num_args() > func_get_arg(2) : null;
  64.         if (\is_string($value)) {
  65.             $value = new PropertyPath($value);
  66.         }
  67.         if ($value instanceof PropertyPathInterface) {
  68.             $accessor $this->propertyAccessor;
  69.             $value = function ($choice) use ($accessor$value) {
  70.                 // The callable may be invoked with a non-object/array value
  71.                 // when such values are passed to
  72.                 // ChoiceListInterface::getValuesForChoices(). Handle this case
  73.                 // so that the call to getValue() doesn't break.
  74.                 return \is_object($choice) || \is_array($choice) ? $accessor->getValue($choice$value) : null;
  75.             };
  76.         }
  77.         if (\is_string($filter)) {
  78.             $filter = new PropertyPath($filter);
  79.         }
  80.         if ($filter instanceof PropertyPath) {
  81.             $accessor $this->propertyAccessor;
  82.             $filter = static function ($choice) use ($accessor$filter) {
  83.                 return (\is_object($choice) || \is_array($choice)) && $accessor->getValue($choice$filter);
  84.             };
  85.         }
  86.         return $this->decoratedFactory->createListFromChoices($choices$value$filter);
  87.     }
  88.     /**
  89.      * {@inheritdoc}
  90.      *
  91.      * @param mixed $value
  92.      * @param mixed $filter
  93.      *
  94.      * @return ChoiceListInterface
  95.      */
  96.     public function createListFromLoader(ChoiceLoaderInterface $loader$value null/* , $filter = null */)
  97.     {
  98.         $filter \func_num_args() > func_get_arg(2) : null;
  99.         if (\is_string($value)) {
  100.             $value = new PropertyPath($value);
  101.         }
  102.         if ($value instanceof PropertyPathInterface) {
  103.             $accessor $this->propertyAccessor;
  104.             $value = function ($choice) use ($accessor$value) {
  105.                 // The callable may be invoked with a non-object/array value
  106.                 // when such values are passed to
  107.                 // ChoiceListInterface::getValuesForChoices(). Handle this case
  108.                 // so that the call to getValue() doesn't break.
  109.                 return \is_object($choice) || \is_array($choice) ? $accessor->getValue($choice$value) : null;
  110.             };
  111.         }
  112.         if (\is_string($filter)) {
  113.             $filter = new PropertyPath($filter);
  114.         }
  115.         if ($filter instanceof PropertyPath) {
  116.             $accessor $this->propertyAccessor;
  117.             $filter = static function ($choice) use ($accessor$filter) {
  118.                 return (\is_object($choice) || \is_array($choice)) && $accessor->getValue($choice$filter);
  119.             };
  120.         }
  121.         return $this->decoratedFactory->createListFromLoader($loader$value$filter);
  122.     }
  123.     /**
  124.      * {@inheritdoc}
  125.      *
  126.      * @param mixed $preferredChoices
  127.      * @param mixed $label
  128.      * @param mixed $index
  129.      * @param mixed $groupBy
  130.      * @param mixed $attr
  131.      * @param mixed $labelTranslationParameters
  132.      *
  133.      * @return ChoiceListView
  134.      */
  135.     public function createView(ChoiceListInterface $list$preferredChoices null$label null$index null$groupBy null$attr null/* , $labelTranslationParameters = [] */)
  136.     {
  137.         $labelTranslationParameters \func_num_args() > func_get_arg(6) : [];
  138.         $accessor $this->propertyAccessor;
  139.         if (\is_string($label)) {
  140.             $label = new PropertyPath($label);
  141.         }
  142.         if ($label instanceof PropertyPathInterface) {
  143.             $label = function ($choice) use ($accessor$label) {
  144.                 return $accessor->getValue($choice$label);
  145.             };
  146.         }
  147.         if (\is_string($preferredChoices)) {
  148.             $preferredChoices = new PropertyPath($preferredChoices);
  149.         }
  150.         if ($preferredChoices instanceof PropertyPathInterface) {
  151.             $preferredChoices = function ($choice) use ($accessor$preferredChoices) {
  152.                 try {
  153.                     return $accessor->getValue($choice$preferredChoices);
  154.                 } catch (UnexpectedTypeException $e) {
  155.                     // Assume not preferred if not readable
  156.                     return false;
  157.                 }
  158.             };
  159.         }
  160.         if (\is_string($index)) {
  161.             $index = new PropertyPath($index);
  162.         }
  163.         if ($index instanceof PropertyPathInterface) {
  164.             $index = function ($choice) use ($accessor$index) {
  165.                 return $accessor->getValue($choice$index);
  166.             };
  167.         }
  168.         if (\is_string($groupBy)) {
  169.             $groupBy = new PropertyPath($groupBy);
  170.         }
  171.         if ($groupBy instanceof PropertyPathInterface) {
  172.             $groupBy = function ($choice) use ($accessor$groupBy) {
  173.                 try {
  174.                     return $accessor->getValue($choice$groupBy);
  175.                 } catch (UnexpectedTypeException $e) {
  176.                     // Don't group if path is not readable
  177.                     return null;
  178.                 }
  179.             };
  180.         }
  181.         if (\is_string($attr)) {
  182.             $attr = new PropertyPath($attr);
  183.         }
  184.         if ($attr instanceof PropertyPathInterface) {
  185.             $attr = function ($choice) use ($accessor$attr) {
  186.                 return $accessor->getValue($choice$attr);
  187.             };
  188.         }
  189.         if (\is_string($labelTranslationParameters)) {
  190.             $labelTranslationParameters = new PropertyPath($labelTranslationParameters);
  191.         }
  192.         if ($labelTranslationParameters instanceof PropertyPath) {
  193.             $labelTranslationParameters = static function ($choice) use ($accessor$labelTranslationParameters) {
  194.                 return $accessor->getValue($choice$labelTranslationParameters);
  195.             };
  196.         }
  197.         return $this->decoratedFactory->createView(
  198.             $list,
  199.             $preferredChoices,
  200.             $label,
  201.             $index,
  202.             $groupBy,
  203.             $attr,
  204.             $labelTranslationParameters
  205.         );
  206.     }
  207. }