- <?php
- /*
-  * This file is part of the Symfony package.
-  *
-  * (c) Fabien Potencier <fabien@symfony.com>
-  *
-  * For the full copyright and license information, please view the LICENSE
-  * file that was distributed with this source code.
-  */
- namespace Symfony\Bridge\Doctrine\Form\ChoiceList;
- use Doctrine\Persistence\ObjectManager;
- use Symfony\Component\Form\ChoiceList\Loader\AbstractChoiceLoader;
- /**
-  * Loads choices using a Doctrine object manager.
-  *
-  * @author Bernhard Schussek <bschussek@gmail.com>
-  */
- class DoctrineChoiceLoader extends AbstractChoiceLoader
- {
-     private $manager;
-     private $class;
-     private $idReader;
-     private $objectLoader;
-     /**
-      * Creates a new choice loader.
-      *
-      * Optionally, an implementation of {@link EntityLoaderInterface} can be
-      * passed which optimizes the object loading for one of the Doctrine
-      * mapper implementations.
-      *
-      * @param string $class The class name of the loaded objects
-      */
-     public function __construct(ObjectManager $manager, string $class, IdReader $idReader = null, EntityLoaderInterface $objectLoader = null)
-     {
-         $classMetadata = $manager->getClassMetadata($class);
-         if ($idReader && !$idReader->isSingleId()) {
-             throw new \InvalidArgumentException(sprintf('The second argument `$idReader` of "%s" must be null when the query cannot be optimized because of composite id fields.', __METHOD__));
-         }
-         $this->manager = $manager;
-         $this->class = $classMetadata->getName();
-         $this->idReader = $idReader;
-         $this->objectLoader = $objectLoader;
-     }
-     /**
-      * {@inheritdoc}
-      */
-     protected function loadChoices(): iterable
-     {
-         return $this->objectLoader
-             ? $this->objectLoader->getEntities()
-             : $this->manager->getRepository($this->class)->findAll();
-     }
-     /**
-      * @internal to be remove in Symfony 6
-      */
-     protected function doLoadValuesForChoices(array $choices): array
-     {
-         // Optimize performance for single-field identifiers. We already
-         // know that the IDs are used as values
-         // Attention: This optimization does not check choices for existence
-         if ($this->idReader) {
-             trigger_deprecation('symfony/doctrine-bridge', '5.1', 'Not defining explicitly the IdReader as value callback when query can be optimized is deprecated. Don\'t pass the IdReader to "%s" or define the "choice_value" option instead.', __CLASS__);
-             // Maintain order and indices of the given objects
-             $values = [];
-             foreach ($choices as $i => $object) {
-                 if ($object instanceof $this->class) {
-                     $values[$i] = $this->idReader->getIdValue($object);
-                 }
-             }
-             return $values;
-         }
-         return parent::doLoadValuesForChoices($choices);
-     }
-     protected function doLoadChoicesForValues(array $values, ?callable $value): array
-     {
-         $legacy = $this->idReader && null === $value;
-         if ($legacy) {
-             trigger_deprecation('symfony/doctrine-bridge', '5.1', 'Not defining explicitly the IdReader as value callback when query can be optimized is deprecated. Don\'t pass the IdReader to "%s" or define the "choice_value" option instead.', __CLASS__);
-         }
-         $idReader = null;
-         if (\is_array($value) && $value[0] instanceof IdReader) {
-             $idReader = $value[0];
-         } elseif ($value instanceof \Closure && ($rThis = (new \ReflectionFunction($value))->getClosureThis()) instanceof IdReader) {
-             $idReader = $rThis;
-         } elseif ($legacy) {
-             $idReader = $this->idReader;
-         }
-         // Optimize performance in case we have an object loader and
-         // a single-field identifier
-         if ($idReader && $this->objectLoader) {
-             $objects = [];
-             $objectsById = [];
-             // Maintain order and indices from the given $values
-             // An alternative approach to the following loop is to add the
-             // "INDEX BY" clause to the Doctrine query in the loader,
-             // but I'm not sure whether that's doable in a generic fashion.
-             foreach ($this->objectLoader->getEntitiesByIds($idReader->getIdField(), $values) as $object) {
-                 $objectsById[$idReader->getIdValue($object)] = $object;
-             }
-             foreach ($values as $i => $id) {
-                 if (isset($objectsById[$id])) {
-                     $objects[$i] = $objectsById[$id];
-                 }
-             }
-             return $objects;
-         }
-         return parent::doLoadChoicesForValues($values, $value);
-     }
- }
-