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

Open in your IDE?
  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 $configs, ContainerBuilder $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 $definition, AsTwigComponent $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 $config, ContainerBuilder $container): ConfigurationInterface
  169. {
  170. return $this;
  171. }
  172. }