vendor/sonata-project/admin-bundle/src/Form/ChoiceList/ModelChoiceLoader.php line 31

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of the Sonata Project package.
  5.  *
  6.  * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  7.  *
  8.  * For the full copyright and license information, please view the LICENSE
  9.  * file that was distributed with this source code.
  10.  */
  11. namespace Sonata\AdminBundle\Form\ChoiceList;
  12. use Doctrine\Common\Util\ClassUtils;
  13. use Sonata\AdminBundle\Model\ModelManagerInterface;
  14. use Sonata\Doctrine\Adapter\AdapterInterface;
  15. use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
  16. use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
  17. use Symfony\Component\Form\Exception\RuntimeException;
  18. use Symfony\Component\PropertyAccess\PropertyAccess;
  19. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  20. use Symfony\Component\PropertyAccess\PropertyPath;
  21. /**
  22.  * @final since sonata-project/admin-bundle 3.52
  23.  *
  24.  * @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
  25.  */
  26. class ModelChoiceLoader implements ChoiceLoaderInterface
  27. {
  28.     public $identifier;
  29.     /**
  30.      * @var \Sonata\AdminBundle\Model\ModelManagerInterface
  31.      */
  32.     private $modelManager;
  33.     /**
  34.      * @var string
  35.      */
  36.     private $class;
  37.     private $property;
  38.     private $query;
  39.     private $choices;
  40.     /**
  41.      * @var PropertyPath
  42.      */
  43.     private $propertyPath;
  44.     /**
  45.      * @var PropertyAccessorInterface
  46.      */
  47.     private $propertyAccessor;
  48.     private $choiceList;
  49.     /**
  50.      * @param string      $class
  51.      * @param string|null $property
  52.      * @param mixed|null  $query
  53.      * @param array       $choices
  54.      */
  55.     public function __construct(
  56.         ModelManagerInterface $modelManager,
  57.         $class,
  58.         $property null,
  59.         $query null,
  60.         $choices = [],
  61.         ?PropertyAccessorInterface $propertyAccessor null
  62.     ) {
  63.         $this->modelManager $modelManager;
  64.         $this->class $class;
  65.         $this->property $property;
  66.         $this->query $query;
  67.         $this->choices $choices;
  68.         $this->identifier $this->modelManager->getIdentifierFieldNames($this->class);
  69.         // The property option defines, which property (path) is used for
  70.         // displaying entities as strings
  71.         if ($property) {
  72.             $this->propertyPath = new PropertyPath($property);
  73.             $this->propertyAccessor $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
  74.         }
  75.     }
  76.     public function loadChoiceList($value null)
  77.     {
  78.         if (!$this->choiceList) {
  79.             if ($this->query) {
  80.                 $entities $this->modelManager->executeQuery($this->query);
  81.             } elseif (\is_array($this->choices) && \count($this->choices) > 0) {
  82.                 $entities $this->choices;
  83.             } else {
  84.                 $entities $this->modelManager->findBy($this->class);
  85.             }
  86.             $choices = [];
  87.             foreach ($entities as $key => $entity) {
  88.                 if ($this->propertyPath) {
  89.                     // If the property option was given, use it
  90.                     $valueObject $this->propertyAccessor->getValue($entity$this->propertyPath);
  91.                 } else {
  92.                     // Otherwise expect a __toString() method in the entity
  93.                     try {
  94.                         $valueObject = (string) $entity;
  95.                     } catch (\Exception $e) {
  96.                         throw new RuntimeException(sprintf('Unable to convert the entity "%s" to string, provide "property" option or implement "__toString()" method in your entity.'ClassUtils::getClass($entity)), 0$e);
  97.                     }
  98.                 }
  99.                 $id implode(AdapterInterface::ID_SEPARATOR$this->getIdentifierValues($entity));
  100.                 if (!\array_key_exists($valueObject$choices)) {
  101.                     $choices[$valueObject] = [];
  102.                 }
  103.                 $choices[$valueObject][] = $id;
  104.             }
  105.             $finalChoices = [];
  106.             foreach ($choices as $valueObject => $idx) {
  107.                 if (\count($idx) > 1) { // avoid issue with identical values ...
  108.                     foreach ($idx as $id) {
  109.                         $finalChoices[sprintf('%s (id: %s)'$valueObject$id)] = $id;
  110.                     }
  111.                 } else {
  112.                     $finalChoices[$valueObject] = current($idx);
  113.                 }
  114.             }
  115.             $this->choiceList = new ArrayChoiceList($finalChoices$value);
  116.         }
  117.         return $this->choiceList;
  118.     }
  119.     public function loadChoicesForValues(array $values$value null)
  120.     {
  121.         return $this->loadChoiceList($value)->getChoicesForValues($values);
  122.     }
  123.     public function loadValuesForChoices(array $choices$value null)
  124.     {
  125.         return $this->loadChoiceList($value)->getValuesForChoices($choices);
  126.     }
  127.     /**
  128.      * @param object $entity
  129.      */
  130.     private function getIdentifierValues($entity): array
  131.     {
  132.         try {
  133.             return $this->modelManager->getIdentifierValues($entity);
  134.         } catch (\Exception $e) {
  135.             throw new \InvalidArgumentException(sprintf('Unable to retrieve the identifier values for entity %s'ClassUtils::getClass($entity)), 0$e);
  136.         }
  137.     }
  138. }