123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- <?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\Component\Form\Console\Descriptor;
- use Symfony\Component\Console\Descriptor\DescriptorInterface;
- use Symfony\Component\Console\Input\ArrayInput;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Style\OutputStyle;
- use Symfony\Component\Console\Style\SymfonyStyle;
- use Symfony\Component\Form\ResolvedFormTypeInterface;
- use Symfony\Component\Form\Util\OptionsResolverWrapper;
- use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector;
- use Symfony\Component\OptionsResolver\Exception\NoConfigurationException;
- use Symfony\Component\OptionsResolver\OptionsResolver;
- /**
- * @author Yonel Ceruto <yonelceruto@gmail.com>
- *
- * @internal
- */
- abstract class Descriptor implements DescriptorInterface
- {
- /** @var OutputStyle */
- protected $output;
- protected $type;
- protected $ownOptions = [];
- protected $overriddenOptions = [];
- protected $parentOptions = [];
- protected $extensionOptions = [];
- protected $requiredOptions = [];
- protected $parents = [];
- protected $extensions = [];
- /**
- * {@inheritdoc}
- */
- public function describe(OutputInterface $output, $object, array $options = [])
- {
- $this->output = $output instanceof OutputStyle ? $output : new SymfonyStyle(new ArrayInput([]), $output);
- switch (true) {
- case null === $object:
- $this->describeDefaults($options);
- break;
- case $object instanceof ResolvedFormTypeInterface:
- $this->describeResolvedFormType($object, $options);
- break;
- case $object instanceof OptionsResolver:
- $this->describeOption($object, $options);
- break;
- default:
- throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_debug_type($object)));
- }
- }
- abstract protected function describeDefaults(array $options);
- abstract protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = []);
- abstract protected function describeOption(OptionsResolver $optionsResolver, array $options);
- protected function collectOptions(ResolvedFormTypeInterface $type)
- {
- $this->parents = [];
- $this->extensions = [];
- if (null !== $type->getParent()) {
- $optionsResolver = clone $this->getParentOptionsResolver($type->getParent());
- } else {
- $optionsResolver = new OptionsResolver();
- }
- $type->getInnerType()->configureOptions($ownOptionsResolver = new OptionsResolverWrapper());
- $this->ownOptions = array_diff($ownOptionsResolver->getDefinedOptions(), $optionsResolver->getDefinedOptions());
- $overriddenOptions = array_intersect(array_merge($ownOptionsResolver->getDefinedOptions(), $ownOptionsResolver->getUndefinedOptions()), $optionsResolver->getDefinedOptions());
- $this->parentOptions = [];
- foreach ($this->parents as $class => $parentOptions) {
- $this->overriddenOptions[$class] = array_intersect($overriddenOptions, $parentOptions);
- $this->parentOptions[$class] = array_diff($parentOptions, $overriddenOptions);
- }
- $type->getInnerType()->configureOptions($optionsResolver);
- $this->collectTypeExtensionsOptions($type, $optionsResolver);
- $this->extensionOptions = [];
- foreach ($this->extensions as $class => $extensionOptions) {
- $this->overriddenOptions[$class] = array_intersect($overriddenOptions, $extensionOptions);
- $this->extensionOptions[$class] = array_diff($extensionOptions, $overriddenOptions);
- }
- $this->overriddenOptions = array_filter($this->overriddenOptions);
- $this->parentOptions = array_filter($this->parentOptions);
- $this->extensionOptions = array_filter($this->extensionOptions);
- $this->requiredOptions = $optionsResolver->getRequiredOptions();
- $this->parents = array_keys($this->parents);
- $this->extensions = array_keys($this->extensions);
- }
- protected function getOptionDefinition(OptionsResolver $optionsResolver, string $option)
- {
- $definition = [];
- if ($info = $optionsResolver->getInfo($option)) {
- $definition = [
- 'info' => $info,
- ];
- }
- $definition += [
- 'required' => $optionsResolver->isRequired($option),
- 'deprecated' => $optionsResolver->isDeprecated($option),
- ];
- $introspector = new OptionsResolverIntrospector($optionsResolver);
- $map = [
- 'default' => 'getDefault',
- 'lazy' => 'getLazyClosures',
- 'allowedTypes' => 'getAllowedTypes',
- 'allowedValues' => 'getAllowedValues',
- 'normalizers' => 'getNormalizers',
- 'deprecation' => 'getDeprecation',
- ];
- foreach ($map as $key => $method) {
- try {
- $definition[$key] = $introspector->{$method}($option);
- } catch (NoConfigurationException $e) {
- // noop
- }
- }
- if (isset($definition['deprecation']) && isset($definition['deprecation']['message']) && \is_string($definition['deprecation']['message'])) {
- $definition['deprecationMessage'] = strtr($definition['deprecation']['message'], ['%name%' => $option]);
- $definition['deprecationPackage'] = $definition['deprecation']['package'];
- $definition['deprecationVersion'] = $definition['deprecation']['version'];
- }
- return $definition;
- }
- protected function filterOptionsByDeprecated(ResolvedFormTypeInterface $type)
- {
- $deprecatedOptions = [];
- $resolver = $type->getOptionsResolver();
- foreach ($resolver->getDefinedOptions() as $option) {
- if ($resolver->isDeprecated($option)) {
- $deprecatedOptions[] = $option;
- }
- }
- $filterByDeprecated = function (array $options) use ($deprecatedOptions) {
- foreach ($options as $class => $opts) {
- if ($deprecated = array_intersect($deprecatedOptions, $opts)) {
- $options[$class] = $deprecated;
- } else {
- unset($options[$class]);
- }
- }
- return $options;
- };
- $this->ownOptions = array_intersect($deprecatedOptions, $this->ownOptions);
- $this->overriddenOptions = $filterByDeprecated($this->overriddenOptions);
- $this->parentOptions = $filterByDeprecated($this->parentOptions);
- $this->extensionOptions = $filterByDeprecated($this->extensionOptions);
- }
- private function getParentOptionsResolver(ResolvedFormTypeInterface $type): OptionsResolver
- {
- $this->parents[$class = \get_class($type->getInnerType())] = [];
- if (null !== $type->getParent()) {
- $optionsResolver = clone $this->getParentOptionsResolver($type->getParent());
- } else {
- $optionsResolver = new OptionsResolver();
- }
- $inheritedOptions = $optionsResolver->getDefinedOptions();
- $type->getInnerType()->configureOptions($optionsResolver);
- $this->parents[$class] = array_diff($optionsResolver->getDefinedOptions(), $inheritedOptions);
- $this->collectTypeExtensionsOptions($type, $optionsResolver);
- return $optionsResolver;
- }
- private function collectTypeExtensionsOptions(ResolvedFormTypeInterface $type, OptionsResolver $optionsResolver)
- {
- foreach ($type->getTypeExtensions() as $extension) {
- $inheritedOptions = $optionsResolver->getDefinedOptions();
- $extension->configureOptions($optionsResolver);
- $this->extensions[\get_class($extension)] = array_diff($optionsResolver->getDefinedOptions(), $inheritedOptions);
- }
- }
- }
|