vendor/symfony/ux-twig-component/src/DependencyInjection/TwigComponentExtension.php line 60

  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  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\UX\TwigComponent\DependencyInjection;
  11. use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
  12. use Symfony\Component\Config\Definition\Builder\TreeBuilder;
  13. use Symfony\Component\Config\Definition\ConfigurationInterface;
  14. use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
  15. use Symfony\Component\Config\FileLocator;
  16. use Symfony\Component\DependencyInjection\Argument\AbstractArgument;
  17. use Symfony\Component\DependencyInjection\ChildDefinition;
  18. use Symfony\Component\DependencyInjection\ContainerBuilder;
  19. use Symfony\Component\DependencyInjection\Exception\LogicException;
  20. use Symfony\Component\DependencyInjection\Extension\Extension;
  21. use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
  22. use Symfony\Component\DependencyInjection\Parameter;
  23. use Symfony\Component\DependencyInjection\Reference;
  24. use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
  25. use Symfony\UX\TwigComponent\Command\TwigComponentDebugCommand;
  26. use Symfony\UX\TwigComponent\ComponentFactory;
  27. use Symfony\UX\TwigComponent\ComponentRenderer;
  28. use Symfony\UX\TwigComponent\ComponentRendererInterface;
  29. use Symfony\UX\TwigComponent\ComponentStack;
  30. use Symfony\UX\TwigComponent\ComponentTemplateFinder;
  31. use Symfony\UX\TwigComponent\DependencyInjection\Compiler\TwigComponentPass;
  32. use Symfony\UX\TwigComponent\Twig\ComponentExtension;
  33. use Symfony\UX\TwigComponent\Twig\ComponentLexer;
  34. use Symfony\UX\TwigComponent\Twig\TwigEnvironmentConfigurator;
  35. /**
  36.  * @author Kevin Bond <kevinbond@gmail.com>
  37.  *
  38.  * @internal
  39.  */
  40. final class TwigComponentExtension extends Extension implements ConfigurationInterface
  41. {
  42.     private const DEPRECATED_DEFAULT_KEY '__deprecated__use_old_naming_behavior';
  43.     public function load(array $configsContainerBuilder $container): void
  44.     {
  45.         $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../../config'));
  46.         if (!isset($container->getParameter('kernel.bundles')['TwigBundle'])) {
  47.             throw new LogicException('The TwigBundle is not registered in your application. Try running "composer require symfony/twig-bundle".');
  48.         }
  49.         $configuration $this->getConfiguration($configs$container);
  50.         $config $this->processConfiguration($configuration$configs);
  51.         $defaults $config['defaults'];
  52.         if ($defaults === [self::DEPRECATED_DEFAULT_KEY]) {
  53.             trigger_deprecation('symfony/ux-twig-component''2.13''Not setting the "twig_component.defaults" config option is deprecated. Check the documentation for an example configuration.');
  54.             $container->setParameter('ux.twig_component.legacy_autonaming'true);
  55.             $defaults = [];
  56.         }
  57.         $container->setParameter('ux.twig_component.component_defaults'$defaults);
  58.         $container->register('ux.twig_component.component_template_finder'ComponentTemplateFinder::class)
  59.             ->setArguments([
  60.                 new Reference('twig.loader'),
  61.                 $config['anonymous_template_directory'],
  62.             ]);
  63.         $container->setAlias(ComponentRendererInterface::class, 'ux.twig_component.component_renderer');
  64.         $container->registerAttributeForAutoconfiguration(
  65.             AsTwigComponent::class,
  66.             static function (ChildDefinition $definitionAsTwigComponent $attribute) {
  67.                 $definition->addTag('twig.component'array_filter($attribute->serviceConfig()));
  68.             }
  69.         );
  70.         $container->register('ux.twig_component.component_factory'ComponentFactory::class)
  71.             ->setArguments([
  72.                 new Reference('ux.twig_component.component_template_finder'),
  73.                 class_exists(AbstractArgument::class) ? new AbstractArgument(sprintf('Added in %s.'TwigComponentPass::class)) : null,
  74.                 new Reference('property_accessor'),
  75.                 new Reference('event_dispatcher'),
  76.                 class_exists(AbstractArgument::class) ? new AbstractArgument(sprintf('Added in %s.'TwigComponentPass::class)) : [],
  77.             ])
  78.         ;
  79.         $container->register('ux.twig_component.component_stack'ComponentStack::class);
  80.         $container->register('ux.twig_component.component_renderer'ComponentRenderer::class)
  81.             ->setArguments([
  82.                 new Reference('twig'),
  83.                 new Reference('event_dispatcher'),
  84.                 new Reference('ux.twig_component.component_factory'),
  85.                 new Reference('property_accessor'),
  86.                 new Reference('ux.twig_component.component_stack'),
  87.             ])
  88.         ;
  89.         $container->register('ux.twig_component.twig.component_extension'ComponentExtension::class)
  90.             ->addTag('twig.extension')
  91.             ->addTag('container.service_subscriber', ['key' => ComponentRenderer::class, 'id' => 'ux.twig_component.component_renderer'])
  92.         ;
  93.         $container->register('ux.twig_component.twig.lexer'ComponentLexer::class);
  94.         $container->register('ux.twig_component.twig.environment_configurator'TwigEnvironmentConfigurator::class)
  95.             ->setDecoratedService(new Reference('twig.configurator.environment'))
  96.             ->setArguments([new Reference('ux.twig_component.twig.environment_configurator.inner')]);
  97.         $container->register('ux.twig_component.command.debug'TwigComponentDebugCommand::class)
  98.             ->setArguments([
  99.                 new Parameter('twig.default_path'),
  100.                 new Reference('ux.twig_component.component_factory'),
  101.                 new Reference('twig'),
  102.                 class_exists(AbstractArgument::class) ? new AbstractArgument(sprintf('Added in %s.'TwigComponentPass::class)) : [],
  103.                 $config['anonymous_template_directory'],
  104.             ])
  105.             ->addTag('console.command')
  106.         ;
  107.         $container->setAlias('console.command.stimulus_component_debug''ux.twig_component.command.debug')
  108.             ->setDeprecated('symfony/ux-twig-component''2.13''%alias_id%');
  109.         if ($container->getParameter('kernel.debug')) {
  110.             $loader->load('debug.php');
  111.         }
  112.     }
  113.     public function getConfigTreeBuilder(): TreeBuilder
  114.     {
  115.         $treeBuilder = new TreeBuilder('twig_component');
  116.         $rootNode $treeBuilder->getRootNode();
  117.         \assert($rootNode instanceof ArrayNodeDefinition);
  118.         $rootNode
  119.             ->validate()
  120.             ->always(function ($v) {
  121.                 if (!isset($v['anonymous_template_directory'])) {
  122.                     trigger_deprecation('symfony/twig-component-bundle''2.13''Not setting the "twig_component.anonymous_template_directory" config option is deprecated. It will default to "components" in 3.0.');
  123.                     $v['anonymous_template_directory'] = null;
  124.                 }
  125.                 return $v;
  126.             })
  127.             ->end()
  128.             ->children()
  129.                 ->arrayNode('defaults')
  130.                     ->defaultValue([self::DEPRECATED_DEFAULT_KEY])
  131.                     ->useAttributeAsKey('namespace')
  132.                     ->validate()
  133.                         ->always(function ($v) {
  134.                             foreach ($v as $namespace => $defaults) {
  135.                                 if (!str_ends_with($namespace'\\')) {
  136.                                     throw new InvalidConfigurationException(sprintf('The twig_component.defaults namespace "%s" is invalid: it must end in a "\"'$namespace));
  137.                                 }
  138.                             }
  139.                             return $v;
  140.                         })
  141.                     ->end()
  142.                     ->arrayPrototype()
  143.                         ->beforeNormalization()
  144.                             ->ifString()
  145.                             ->then(function (string $v) {
  146.                                 return ['template_directory' => $v];
  147.                             })
  148.                         ->end()
  149.                         ->children()
  150.                             ->scalarNode('template_directory')
  151.                                 ->defaultValue('components')
  152.                             ->end()
  153.                             ->scalarNode('name_prefix')
  154.                                 ->defaultValue('')
  155.                             ->end()
  156.                         ->end()
  157.                     ->end()
  158.                 ->end()
  159.                 ->scalarNode('anonymous_template_directory')
  160.                     ->info('Defaults to `components`')
  161.                 ->end()
  162.                 ->scalarNode('controllers_json')
  163.                     ->defaultValue('%kernel.project_dir%/assets/controllers.json')
  164.                 ->end()
  165.             ->end();
  166.         return $treeBuilder;
  167.     }
  168.     public function getConfiguration(array $configContainerBuilder $container): ConfigurationInterface
  169.     {
  170.         return $this;
  171.     }
  172. }