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

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 Sonata\AdminBundle\Model\ModelManagerInterface;
  13. use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
  14. use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
  15. use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
  16. use Symfony\Component\Form\Exception\InvalidArgumentException;
  17. use Symfony\Component\Form\Exception\TransformationFailedException;
  18. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  19. /**
  20.  * @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
  21.  */
  22. final class ModelChoiceLoader implements ChoiceLoaderInterface
  23. {
  24.     private ?ChoiceListInterface $choiceList null;
  25.     /**
  26.      * @param ModelManagerInterface<object> $modelManager
  27.      * @param object[]|null                 $choices
  28.      *
  29.      * @phpstan-param class-string $class
  30.      */
  31.     public function __construct(
  32.         private ModelManagerInterface $modelManager,
  33.         private PropertyAccessorInterface $propertyAccessor,
  34.         private string $class,
  35.         private ?string $property null,
  36.         private ?object $query null,
  37.         private ?array $choices null,
  38.     ) {
  39.         if (null !== $query && !$this->modelManager->supportsQuery($query)) {
  40.             throw new InvalidArgumentException('The model manager does not support the query.');
  41.         }
  42.     }
  43.     public function loadChoiceList($value null): ChoiceListInterface
  44.     {
  45.         if (null === $this->choiceList) {
  46.             if (null !== $this->query) {
  47.                 $entities $this->modelManager->executeQuery($this->query);
  48.             } elseif (\is_array($this->choices)) {
  49.                 $entities $this->choices;
  50.             } else {
  51.                 $entities $this->modelManager->findBy($this->class);
  52.             }
  53.             $choices = [];
  54.             foreach ($entities as $model) {
  55.                 if (null !== $this->property) {
  56.                     // If the property option was given, use it
  57.                     $valueObject $this->propertyAccessor->getValue($model$this->property);
  58.                 } elseif (method_exists($model'__toString')) {
  59.                     // Otherwise expect a __toString() method in the entity
  60.                     $valueObject = (string) $model;
  61.                 } else {
  62.                     throw new TransformationFailedException(\sprintf(
  63.                         'Unable to convert the model "%s" to string, provide "property" option'
  64.                         .' or implement "__toString()" method in your model.',
  65.                         $this->class
  66.                     ));
  67.                 }
  68.                 if (!\array_key_exists($valueObject$choices)) {
  69.                     $choices[$valueObject] = [];
  70.                 }
  71.                 $identifier $this->modelManager->getNormalizedIdentifier($model);
  72.                 if (null === $identifier) {
  73.                     throw new TransformationFailedException(\sprintf(
  74.                         'No identifier was found for the model "%s".',
  75.                         $this->class
  76.                     ));
  77.                 }
  78.                 $choices[$valueObject][] = $identifier;
  79.             }
  80.             $finalChoices = [];
  81.             foreach ($choices as $valueObject => $idx) {
  82.                 if (\count($idx) > 1) { // avoid issue with identical values ...
  83.                     foreach ($idx as $id) {
  84.                         $finalChoices[\sprintf('%s (id: %s)'$valueObject$id)] = $id;
  85.                     }
  86.                 } else {
  87.                     $finalChoices[$valueObject] = current($idx);
  88.                 }
  89.             }
  90.             $this->choiceList = new ArrayChoiceList($finalChoices$value);
  91.         }
  92.         return $this->choiceList;
  93.     }
  94.     public function loadChoicesForValues(array $values$value null): array
  95.     {
  96.         return $this->loadChoiceList($value)->getChoicesForValues($values);
  97.     }
  98.     public function loadValuesForChoices(array $choices$value null): array
  99.     {
  100.         return $this->loadChoiceList($value)->getValuesForChoices($choices);
  101.     }
  102. }