vendor/symfony/form/FormRegistry.php line 94

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;
  11. use Symfony\Component\Form\Exception\ExceptionInterface;
  12. use Symfony\Component\Form\Exception\InvalidArgumentException;
  13. use Symfony\Component\Form\Exception\LogicException;
  14. use Symfony\Component\Form\Exception\UnexpectedTypeException;
  15. /**
  16.  * The central registry of the Form component.
  17.  *
  18.  * @author Bernhard Schussek <[email protected]>
  19.  */
  20. class FormRegistry implements FormRegistryInterface
  21. {
  22.     /**
  23.      * Extensions.
  24.      *
  25.      * @var FormExtensionInterface[]
  26.      */
  27.     private $extensions = [];
  28.     /**
  29.      * @var ResolvedFormTypeInterface[]
  30.      */
  31.     private $types = [];
  32.     /**
  33.      * @var FormTypeGuesserInterface|false|null
  34.      */
  35.     private $guesser false;
  36.     /**
  37.      * @var ResolvedFormTypeFactoryInterface
  38.      */
  39.     private $resolvedTypeFactory;
  40.     private $checkedTypes = [];
  41.     /**
  42.      * @param FormExtensionInterface[] $extensions An array of FormExtensionInterface
  43.      *
  44.      * @throws UnexpectedTypeException if any extension does not implement FormExtensionInterface
  45.      */
  46.     public function __construct(array $extensionsResolvedFormTypeFactoryInterface $resolvedTypeFactory)
  47.     {
  48.         foreach ($extensions as $extension) {
  49.             if (!$extension instanceof FormExtensionInterface) {
  50.                 throw new UnexpectedTypeException($extension'Symfony\Component\Form\FormExtensionInterface');
  51.             }
  52.         }
  53.         $this->extensions $extensions;
  54.         $this->resolvedTypeFactory $resolvedTypeFactory;
  55.     }
  56.     /**
  57.      * {@inheritdoc}
  58.      */
  59.     public function getType($name)
  60.     {
  61.         if (!isset($this->types[$name])) {
  62.             $type null;
  63.             foreach ($this->extensions as $extension) {
  64.                 if ($extension->hasType($name)) {
  65.                     $type $extension->getType($name);
  66.                     break;
  67.                 }
  68.             }
  69.             if (!$type) {
  70.                 // Support fully-qualified class names
  71.                 if (!class_exists($name)) {
  72.                     throw new InvalidArgumentException(sprintf('Could not load type "%s": class does not exist.'$name));
  73.                 }
  74.                 if (!is_subclass_of($name'Symfony\Component\Form\FormTypeInterface')) {
  75.                     throw new InvalidArgumentException(sprintf('Could not load type "%s": class does not implement "Symfony\Component\Form\FormTypeInterface".'$name));
  76.                 }
  77.                 $type = new $name();
  78.             }
  79.             $this->types[$name] = $this->resolveType($type);
  80.         }
  81.         return $this->types[$name];
  82.     }
  83.     /**
  84.      * Wraps a type into a ResolvedFormTypeInterface implementation and connects it with its parent type.
  85.      */
  86.     private function resolveType(FormTypeInterface $type): ResolvedFormTypeInterface
  87.     {
  88.         $typeExtensions = [];
  89.         $parentType $type->getParent();
  90.         $fqcn = \get_class($type);
  91.         if (isset($this->checkedTypes[$fqcn])) {
  92.             $types implode(' > 'array_merge(array_keys($this->checkedTypes), [$fqcn]));
  93.             throw new LogicException(sprintf('Circular reference detected for form type "%s" (%s).'$fqcn$types));
  94.         }
  95.         $this->checkedTypes[$fqcn] = true;
  96.         try {
  97.             foreach ($this->extensions as $extension) {
  98.                 $typeExtensions array_merge(
  99.                     $typeExtensions,
  100.                     $extension->getTypeExtensions($fqcn)
  101.                 );
  102.             }
  103.             return $this->resolvedTypeFactory->createResolvedType(
  104.                 $type,
  105.                 $typeExtensions,
  106.                 $parentType $this->getType($parentType) : null
  107.             );
  108.         } finally {
  109.             unset($this->checkedTypes[$fqcn]);
  110.         }
  111.     }
  112.     /**
  113.      * {@inheritdoc}
  114.      */
  115.     public function hasType($name)
  116.     {
  117.         if (isset($this->types[$name])) {
  118.             return true;
  119.         }
  120.         try {
  121.             $this->getType($name);
  122.         } catch (ExceptionInterface $e) {
  123.             return false;
  124.         }
  125.         return true;
  126.     }
  127.     /**
  128.      * {@inheritdoc}
  129.      */
  130.     public function getTypeGuesser()
  131.     {
  132.         if (false === $this->guesser) {
  133.             $guessers = [];
  134.             foreach ($this->extensions as $extension) {
  135.                 $guesser $extension->getTypeGuesser();
  136.                 if ($guesser) {
  137.                     $guessers[] = $guesser;
  138.                 }
  139.             }
  140.             $this->guesser = !empty($guessers) ? new FormTypeGuesserChain($guessers) : null;
  141.         }
  142.         return $this->guesser;
  143.     }
  144.     /**
  145.      * {@inheritdoc}
  146.      */
  147.     public function getExtensions()
  148.     {
  149.         return $this->extensions;
  150.     }
  151. }