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

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\Argument\ServiceLocatorArgument;
  18. use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
  19. use Symfony\Component\DependencyInjection\ChildDefinition;
  20. use Symfony\Component\DependencyInjection\ContainerBuilder;
  21. use Symfony\Component\DependencyInjection\ContainerInterface;
  22. use Symfony\Component\DependencyInjection\Exception\LogicException;
  23. use Symfony\Component\DependencyInjection\Extension\Extension;
  24. use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
  25. use Symfony\Component\DependencyInjection\Parameter;
  26. use Symfony\Component\DependencyInjection\Reference;
  27. use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
  28. use Symfony\UX\TwigComponent\CacheWarmer\TwigComponentCacheWarmer;
  29. use Symfony\UX\TwigComponent\Command\TwigComponentDebugCommand;
  30. use Symfony\UX\TwigComponent\ComponentFactory;
  31. use Symfony\UX\TwigComponent\ComponentProperties;
  32. use Symfony\UX\TwigComponent\ComponentRenderer;
  33. use Symfony\UX\TwigComponent\ComponentRendererInterface;
  34. use Symfony\UX\TwigComponent\ComponentStack;
  35. use Symfony\UX\TwigComponent\ComponentTemplateFinder;
  36. use Symfony\UX\TwigComponent\DependencyInjection\Compiler\TwigComponentPass;
  37. use Symfony\UX\TwigComponent\Twig\ComponentExtension;
  38. use Symfony\UX\TwigComponent\Twig\ComponentLexer;
  39. use Symfony\UX\TwigComponent\Twig\ComponentRuntime;
  40. use Symfony\UX\TwigComponent\Twig\TwigEnvironmentConfigurator;
  41. /**
  42. * @author Kevin Bond <kevinbond@gmail.com>
  43. *
  44. * @internal
  45. */
  46. final class TwigComponentExtension extends Extension implements ConfigurationInterface
  47. {
  48. private const DEPRECATED_DEFAULT_KEY = '__deprecated__use_old_naming_behavior';
  49. public function load(array $configs, ContainerBuilder $container): void
  50. {
  51. $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../../config'));
  52. if (!isset($container->getParameter('kernel.bundles')['TwigBundle'])) {
  53. throw new LogicException('The TwigBundle is not registered in your application. Try running "composer require symfony/twig-bundle".');
  54. }
  55. $configuration = $this->getConfiguration($configs, $container);
  56. $config = $this->processConfiguration($configuration, $configs);
  57. $defaults = $config['defaults'];
  58. if ($defaults === [self::DEPRECATED_DEFAULT_KEY]) {
  59. 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.');
  60. $container->setParameter('ux.twig_component.legacy_autonaming', true);
  61. $defaults = [];
  62. }
  63. $container->setParameter('ux.twig_component.component_defaults', $defaults);
  64. $container->register('ux.twig_component.component_template_finder', ComponentTemplateFinder::class)
  65. ->setArguments([
  66. new Reference('twig.loader'),
  67. $config['anonymous_template_directory'],
  68. ]);
  69. $container->setAlias(ComponentRendererInterface::class, 'ux.twig_component.component_renderer');
  70. $container->registerAttributeForAutoconfiguration(
  71. AsTwigComponent::class,
  72. static function (ChildDefinition $definition, AsTwigComponent $attribute) {
  73. $definition->addTag('twig.component', array_filter($attribute->serviceConfig()));
  74. }
  75. );
  76. $container->register('ux.twig_component.component_factory', ComponentFactory::class)
  77. ->setArguments([
  78. new Reference('ux.twig_component.component_template_finder'),
  79. new AbstractArgument(\sprintf('Added in %s.', TwigComponentPass::class)),
  80. new Reference('property_accessor'),
  81. new Reference('event_dispatcher'),
  82. new AbstractArgument(\sprintf('Added in %s.', TwigComponentPass::class)),
  83. ])
  84. ->addTag('kernel.reset', ['method' => 'reset'])
  85. ;
  86. $container->register('ux.twig_component.component_stack', ComponentStack::class);
  87. $container->register('ux.twig_component.component_properties', ComponentProperties::class)
  88. ->setArguments([
  89. new Reference('property_accessor'),
  90. new AbstractArgument(\sprintf('Added in %s.', TwigComponentPass::class)),
  91. new Reference('cache.ux.twig_component', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
  92. ])
  93. ;
  94. $container->register('ux.twig_component.component_renderer', ComponentRenderer::class)
  95. ->setArguments([
  96. new Reference('twig'),
  97. new Reference('event_dispatcher'),
  98. new Reference('ux.twig_component.component_factory'),
  99. new Reference('ux.twig_component.component_properties'),
  100. new Reference('ux.twig_component.component_stack'),
  101. ])
  102. ->addTag('kernel.reset', ['method' => 'reset'])
  103. ;
  104. $container->register('ux.twig_component.twig.component_extension', ComponentExtension::class)
  105. ->addTag('twig.extension')
  106. ;
  107. $container->register('ux.twig_component.twig.component_runtime', ComponentRuntime::class)
  108. ->setArguments([
  109. new Reference('ux.twig_component.component_renderer'),
  110. new ServiceLocatorArgument(new TaggedIteratorArgument('ux.twig_component.twig_renderer', indexAttribute: 'key', needsIndexes: true)),
  111. ])
  112. ->addTag('twig.runtime')
  113. ;
  114. $container->register('ux.twig_component.twig.lexer', ComponentLexer::class);
  115. $container->register('ux.twig_component.twig.environment_configurator', TwigEnvironmentConfigurator::class)
  116. ->setDecoratedService(new Reference('twig.configurator.environment'))
  117. ->setArguments([new Reference('ux.twig_component.twig.environment_configurator.inner')]);
  118. $container->register('ux.twig_component.command.debug', TwigComponentDebugCommand::class)
  119. ->setArguments([
  120. new Parameter('twig.default_path'),
  121. new Reference('ux.twig_component.component_factory'),
  122. new Reference('twig'),
  123. new AbstractArgument(\sprintf('Added in %s.', TwigComponentPass::class)),
  124. $config['anonymous_template_directory'],
  125. ])
  126. ->addTag('console.command')
  127. ;
  128. $container->setAlias('console.command.stimulus_component_debug', 'ux.twig_component.command.debug')
  129. ->setDeprecated('symfony/ux-twig-component', '2.13', '%alias_id%');
  130. if ($container->getParameter('kernel.debug') && $config['profiler']) {
  131. $loader->load('debug.php');
  132. }
  133. $loader->load('cache.php');
  134. $container->register('ux.twig_component.cache_warmer', TwigComponentCacheWarmer::class)
  135. ->setArguments([new Reference(\Psr\Container\ContainerInterface::class)])
  136. ->addTag('kernel.cache_warmer')
  137. ->addTag('container.service_subscriber', ['id' => 'ux.twig_component.component_properties'])
  138. ;
  139. }
  140. public function getConfigTreeBuilder(): TreeBuilder
  141. {
  142. $treeBuilder = new TreeBuilder('twig_component');
  143. $rootNode = $treeBuilder->getRootNode();
  144. \assert($rootNode instanceof ArrayNodeDefinition);
  145. $rootNode
  146. ->validate()
  147. ->always(function ($v) {
  148. if (!isset($v['anonymous_template_directory'])) {
  149. 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.');
  150. $v['anonymous_template_directory'] = null;
  151. }
  152. return $v;
  153. })
  154. ->end()
  155. ->children()
  156. ->arrayNode('defaults')
  157. ->defaultValue([self::DEPRECATED_DEFAULT_KEY])
  158. ->useAttributeAsKey('namespace')
  159. ->validate()
  160. ->always(function ($v) {
  161. foreach ($v as $namespace => $defaults) {
  162. if (!str_ends_with($namespace, '\\')) {
  163. throw new InvalidConfigurationException(\sprintf('The twig_component.defaults namespace "%s" is invalid: it must end in a "\".', $namespace));
  164. }
  165. }
  166. return $v;
  167. })
  168. ->end()
  169. ->arrayPrototype()
  170. ->beforeNormalization()
  171. ->ifString()
  172. ->then(function (string $v) {
  173. return ['template_directory' => $v];
  174. })
  175. ->end()
  176. ->children()
  177. ->scalarNode('template_directory')
  178. ->defaultValue('components')
  179. ->end()
  180. ->scalarNode('name_prefix')
  181. ->defaultValue('')
  182. ->end()
  183. ->end()
  184. ->end()
  185. ->end()
  186. ->scalarNode('anonymous_template_directory')
  187. ->info('Defaults to `components`')
  188. ->end()
  189. ->booleanNode('profiler')
  190. ->info('Enables the profiler for Twig Component (in debug mode)')
  191. ->defaultValue('%kernel.debug%')
  192. ->end()
  193. ->scalarNode('controllers_json')
  194. ->setDeprecated('symfony/ux-twig-component', '2.18', 'The "twig_component.controllers_json" config option is deprecated, and will be removed in 3.0.')
  195. ->defaultNull()
  196. ->end()
  197. ->end();
  198. return $treeBuilder;
  199. }
  200. public function getConfiguration(array $config, ContainerBuilder $container): ConfigurationInterface
  201. {
  202. return $this;
  203. }
  204. }