├── CHANGELOG.md ├── CacheWarmer ├── AbstractPhpFileCacheWarmer.php ├── CachePoolClearerCacheWarmer.php ├── ConfigBuilderCacheWarmer.php ├── RouterCacheWarmer.php ├── SerializerCacheWarmer.php ├── TranslationsCacheWarmer.php └── ValidatorCacheWarmer.php ├── Command ├── AboutCommand.php ├── AbstractConfigCommand.php ├── AssetsInstallCommand.php ├── BuildDebugContainerTrait.php ├── CacheClearCommand.php ├── CachePoolClearCommand.php ├── CachePoolDeleteCommand.php ├── CachePoolInvalidateTagsCommand.php ├── CachePoolListCommand.php ├── CachePoolPruneCommand.php ├── CacheWarmupCommand.php ├── ConfigDebugCommand.php ├── ConfigDumpReferenceCommand.php ├── ContainerDebugCommand.php ├── ContainerLintCommand.php ├── DebugAutowiringCommand.php ├── EventDispatcherDebugCommand.php ├── RouterDebugCommand.php ├── RouterMatchCommand.php ├── SecretsDecryptToLocalCommand.php ├── SecretsEncryptFromLocalCommand.php ├── SecretsGenerateKeysCommand.php ├── SecretsListCommand.php ├── SecretsRemoveCommand.php ├── SecretsRevealCommand.php ├── SecretsSetCommand.php ├── TranslationDebugCommand.php ├── TranslationExtractCommand.php ├── TranslationUpdateCommand.php ├── WorkflowDumpCommand.php ├── XliffLintCommand.php └── YamlLintCommand.php ├── Console ├── Application.php ├── Descriptor │ ├── Descriptor.php │ ├── JsonDescriptor.php │ ├── MarkdownDescriptor.php │ ├── TextDescriptor.php │ └── XmlDescriptor.php └── Helper │ └── DescriptorHelper.php ├── Controller ├── AbstractController.php ├── ControllerResolver.php ├── RedirectController.php └── TemplateController.php ├── DataCollector ├── AbstractDataCollector.php ├── RouterDataCollector.php └── TemplateAwareDataCollectorInterface.php ├── DependencyInjection ├── Compiler │ ├── AddDebugLogProcessorPass.php │ ├── AssetsContextPass.php │ ├── ContainerBuilderDebugDumpPass.php │ ├── ErrorLoggerCompilerPass.php │ ├── ProfilerPass.php │ ├── RemoveUnusedSessionMarshallingHandlerPass.php │ ├── TestServiceContainerRealRefPass.php │ ├── TestServiceContainerWeakRefPass.php │ ├── TranslationLintCommandPass.php │ ├── TranslationUpdateCommandPass.php │ └── UnusedTagsPass.php ├── Configuration.php ├── FrameworkExtension.php └── VirtualRequestStackPass.php ├── EventListener ├── ConsoleProfilerListener.php └── SuggestMissingPackageSubscriber.php ├── FrameworkBundle.php ├── HttpCache └── HttpCache.php ├── Kernel └── MicroKernelTrait.php ├── KernelBrowser.php ├── LICENSE ├── README.md ├── Resources ├── bin │ └── check-unused-known-tags.php └── config │ ├── asset_mapper.php │ ├── assets.php │ ├── cache.php │ ├── cache_debug.php │ ├── collectors.php │ ├── console.php │ ├── debug.php │ ├── debug_prod.php │ ├── error_renderer.php │ ├── esi.php │ ├── form.php │ ├── form_csrf.php │ ├── form_debug.php │ ├── fragment_listener.php │ ├── fragment_renderer.php │ ├── html_sanitizer.php │ ├── http_client.php │ ├── http_client_debug.php │ ├── identity_translator.php │ ├── json_streamer.php │ ├── lock.php │ ├── mailer.php │ ├── mailer_debug.php │ ├── mailer_transports.php │ ├── mailer_webhook.php │ ├── messenger.php │ ├── messenger_debug.php │ ├── mime_type.php │ ├── notifier.php │ ├── notifier_debug.php │ ├── notifier_transports.php │ ├── notifier_webhook.php │ ├── object_mapper.php │ ├── process.php │ ├── profiling.php │ ├── property_access.php │ ├── property_info.php │ ├── rate_limiter.php │ ├── remote_event.php │ ├── request.php │ ├── routing.php │ ├── routing │ ├── errors.php │ ├── errors.xml │ ├── webhook.php │ └── webhook.xml │ ├── scheduler.php │ ├── schema │ └── symfony-1.0.xsd │ ├── secrets.php │ ├── security_csrf.php │ ├── semaphore.php │ ├── serializer.php │ ├── serializer_debug.php │ ├── services.php │ ├── session.php │ ├── ssi.php │ ├── test.php │ ├── translation.php │ ├── translation_debug.php │ ├── translation_providers.php │ ├── type_info.php │ ├── uid.php │ ├── validator.php │ ├── validator_debug.php │ ├── web.php │ ├── web_link.php │ ├── webhook.php │ ├── workflow.php │ └── workflow_debug.php ├── Routing ├── Attribute │ └── AsRoutingConditionService.php ├── AttributeRouteControllerLoader.php ├── DelegatingLoader.php ├── RedirectableCompiledUrlMatcher.php ├── RouteLoaderInterface.php └── Router.php ├── Secrets ├── AbstractVault.php ├── DotenvVault.php └── SodiumVault.php ├── Test ├── BrowserKitAssertionsTrait.php ├── DomCrawlerAssertionsTrait.php ├── HttpClientAssertionsTrait.php ├── KernelTestCase.php ├── MailerAssertionsTrait.php ├── NotificationAssertionsTrait.php ├── TestBrowserToken.php ├── TestContainer.php ├── WebTestAssertionsTrait.php └── WebTestCase.php ├── Translation └── Translator.php └── composer.json /CacheWarmer/AbstractPhpFileCacheWarmer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; 13 | 14 | use Symfony\Component\Cache\Adapter\ArrayAdapter; 15 | use Symfony\Component\Cache\Adapter\NullAdapter; 16 | use Symfony\Component\Cache\Adapter\PhpArrayAdapter; 17 | use Symfony\Component\Config\Resource\ClassExistenceResource; 18 | use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; 19 | 20 | abstract class AbstractPhpFileCacheWarmer implements CacheWarmerInterface 21 | { 22 | /** 23 | * @param string $phpArrayFile The PHP file where metadata are cached 24 | */ 25 | public function __construct( 26 | private string $phpArrayFile, 27 | ) { 28 | } 29 | 30 | public function isOptional(): bool 31 | { 32 | return true; 33 | } 34 | 35 | public function warmUp(string $cacheDir, ?string $buildDir = null): array 36 | { 37 | $arrayAdapter = new ArrayAdapter(); 38 | 39 | spl_autoload_register([ClassExistenceResource::class, 'throwOnRequiredClass']); 40 | try { 41 | if (!$this->doWarmUp($cacheDir, $arrayAdapter, $buildDir)) { 42 | return []; 43 | } 44 | } finally { 45 | spl_autoload_unregister([ClassExistenceResource::class, 'throwOnRequiredClass']); 46 | } 47 | 48 | // the ArrayAdapter stores the values serialized 49 | // to avoid mutation of the data after it was written to the cache 50 | // so here we un-serialize the values first 51 | $values = array_map(fn ($val) => null !== $val ? unserialize($val) : null, $arrayAdapter->getValues()); 52 | 53 | return $this->warmUpPhpArrayAdapter(new PhpArrayAdapter($this->phpArrayFile, new NullAdapter()), $values); 54 | } 55 | 56 | /** 57 | * @return string[] A list of classes to preload on PHP 7.4+ 58 | */ 59 | protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values): array 60 | { 61 | return $phpArrayAdapter->warmUp($values); 62 | } 63 | 64 | /** 65 | * @internal 66 | */ 67 | final protected function ignoreAutoloadException(string $class, \Exception $exception): void 68 | { 69 | try { 70 | ClassExistenceResource::throwOnRequiredClass($class, $exception); 71 | } catch (\ReflectionException) { 72 | } 73 | } 74 | 75 | /** 76 | * @return bool false if there is nothing to warm-up 77 | */ 78 | abstract protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter, ?string $buildDir = null): bool; 79 | } 80 | -------------------------------------------------------------------------------- /CacheWarmer/CachePoolClearerCacheWarmer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; 13 | 14 | use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; 15 | use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; 16 | 17 | /** 18 | * Clears the cache pools when warming up the cache. 19 | * 20 | * Do not use in production! 21 | * 22 | * @author Teoh Han Hui 23 | * 24 | * @internal 25 | */ 26 | final class CachePoolClearerCacheWarmer implements CacheWarmerInterface 27 | { 28 | /** 29 | * @param string[] $pools 30 | */ 31 | public function __construct( 32 | private Psr6CacheClearer $poolClearer, 33 | private array $pools = [], 34 | ) { 35 | } 36 | 37 | public function warmUp(string $cacheDir, ?string $buildDir = null): array 38 | { 39 | foreach ($this->pools as $pool) { 40 | if ($this->poolClearer->hasPool($pool)) { 41 | $this->poolClearer->clearPool($pool); 42 | } 43 | } 44 | 45 | return []; 46 | } 47 | 48 | public function isOptional(): bool 49 | { 50 | // optional cache warmers are not run when handling the request 51 | return false; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /CacheWarmer/ConfigBuilderCacheWarmer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; 13 | 14 | use Psr\Log\LoggerInterface; 15 | use Symfony\Component\Config\Builder\ConfigBuilderGenerator; 16 | use Symfony\Component\Config\Builder\ConfigBuilderGeneratorInterface; 17 | use Symfony\Component\Config\Definition\ConfigurationInterface; 18 | use Symfony\Component\DependencyInjection\Container; 19 | use Symfony\Component\DependencyInjection\ContainerBuilder; 20 | use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; 21 | use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; 22 | use Symfony\Component\DependencyInjection\ParameterBag\ContainerBag; 23 | use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; 24 | use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; 25 | use Symfony\Component\HttpKernel\Kernel; 26 | use Symfony\Component\HttpKernel\KernelInterface; 27 | 28 | /** 29 | * Generate all config builders. 30 | * 31 | * @author Tobias Nyholm 32 | * 33 | * @final since Symfony 7.1 34 | */ 35 | class ConfigBuilderCacheWarmer implements CacheWarmerInterface 36 | { 37 | public function __construct( 38 | private KernelInterface $kernel, 39 | private ?LoggerInterface $logger = null, 40 | ) { 41 | } 42 | 43 | public function warmUp(string $cacheDir, ?string $buildDir = null): array 44 | { 45 | if (!$buildDir) { 46 | return []; 47 | } 48 | 49 | $generator = new ConfigBuilderGenerator($buildDir); 50 | 51 | if ($this->kernel instanceof Kernel) { 52 | /** @var ContainerBuilder $container */ 53 | $container = \Closure::bind(function (Kernel $kernel) { 54 | $containerBuilder = $kernel->getContainerBuilder(); 55 | $kernel->prepareContainer($containerBuilder); 56 | 57 | return $containerBuilder; 58 | }, null, $this->kernel)($this->kernel); 59 | 60 | $extensions = $container->getExtensions(); 61 | } else { 62 | $extensions = []; 63 | foreach ($this->kernel->getBundles() as $bundle) { 64 | $extension = $bundle->getContainerExtension(); 65 | if (null !== $extension) { 66 | $extensions[] = $extension; 67 | } 68 | } 69 | } 70 | 71 | foreach ($extensions as $extension) { 72 | try { 73 | $this->dumpExtension($extension, $generator); 74 | } catch (\Exception $e) { 75 | $this->logger?->warning('Failed to generate ConfigBuilder for extension {extensionClass}: '.$e->getMessage(), ['exception' => $e, 'extensionClass' => $extension::class]); 76 | } 77 | } 78 | 79 | // No need to preload anything 80 | return []; 81 | } 82 | 83 | private function dumpExtension(ExtensionInterface $extension, ConfigBuilderGeneratorInterface $generator): void 84 | { 85 | $configuration = null; 86 | if ($extension instanceof ConfigurationInterface) { 87 | $configuration = $extension; 88 | } elseif ($extension instanceof ConfigurationExtensionInterface) { 89 | $container = $this->kernel->getContainer(); 90 | $configuration = $extension->getConfiguration([], new ContainerBuilder($container instanceof Container ? new ContainerBag($container) : new ParameterBag())); 91 | } 92 | 93 | if (!$configuration) { 94 | return; 95 | } 96 | 97 | $generator->build($configuration); 98 | } 99 | 100 | public function isOptional(): bool 101 | { 102 | return false; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /CacheWarmer/RouterCacheWarmer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; 13 | 14 | use Psr\Container\ContainerInterface; 15 | use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; 16 | use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; 17 | use Symfony\Component\Routing\RouterInterface; 18 | use Symfony\Contracts\Service\ServiceSubscriberInterface; 19 | 20 | /** 21 | * Generates the router matcher and generator classes. 22 | * 23 | * @author Fabien Potencier 24 | * 25 | * @final 26 | */ 27 | class RouterCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface 28 | { 29 | /** 30 | * As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. 31 | */ 32 | public function __construct( 33 | private ContainerInterface $container, 34 | ) { 35 | } 36 | 37 | public function warmUp(string $cacheDir, ?string $buildDir = null): array 38 | { 39 | if (!$buildDir) { 40 | return []; 41 | } 42 | 43 | $router = $this->container->get('router'); 44 | 45 | if ($router instanceof WarmableInterface) { 46 | return $router->warmUp($cacheDir, $buildDir); 47 | } 48 | 49 | throw new \LogicException(\sprintf('The router "%s" cannot be warmed up because it does not implement "%s".', get_debug_type($router), WarmableInterface::class)); 50 | } 51 | 52 | public function isOptional(): bool 53 | { 54 | return true; 55 | } 56 | 57 | public static function getSubscribedServices(): array 58 | { 59 | return [ 60 | 'router' => RouterInterface::class, 61 | ]; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /CacheWarmer/SerializerCacheWarmer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; 13 | 14 | use Symfony\Component\Cache\Adapter\ArrayAdapter; 15 | use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; 16 | use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; 17 | use Symfony\Component\Serializer\Mapping\Loader\LoaderChain; 18 | use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface; 19 | use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; 20 | use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; 21 | 22 | /** 23 | * Warms up XML and YAML serializer metadata. 24 | * 25 | * @author Titouan Galopin 26 | * 27 | * @final since Symfony 7.1 28 | */ 29 | class SerializerCacheWarmer extends AbstractPhpFileCacheWarmer 30 | { 31 | /** 32 | * @param LoaderInterface[] $loaders The serializer metadata loaders 33 | * @param string $phpArrayFile The PHP file where metadata are cached 34 | */ 35 | public function __construct( 36 | private array $loaders, 37 | string $phpArrayFile, 38 | ) { 39 | parent::__construct($phpArrayFile); 40 | } 41 | 42 | protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter, ?string $buildDir = null): bool 43 | { 44 | if (!$buildDir) { 45 | return false; 46 | } 47 | if (!$this->loaders) { 48 | return true; 49 | } 50 | 51 | $metadataFactory = new CacheClassMetadataFactory(new ClassMetadataFactory(new LoaderChain($this->loaders)), $arrayAdapter); 52 | 53 | foreach ($this->extractSupportedLoaders($this->loaders) as $loader) { 54 | foreach ($loader->getMappedClasses() as $mappedClass) { 55 | try { 56 | $metadataFactory->getMetadataFor($mappedClass); 57 | } catch (\Exception $e) { 58 | $this->ignoreAutoloadException($mappedClass, $e); 59 | } 60 | } 61 | } 62 | 63 | return true; 64 | } 65 | 66 | /** 67 | * @param LoaderInterface[] $loaders 68 | * 69 | * @return XmlFileLoader[]|YamlFileLoader[] 70 | */ 71 | private function extractSupportedLoaders(array $loaders): array 72 | { 73 | $supportedLoaders = []; 74 | 75 | foreach ($loaders as $loader) { 76 | if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) { 77 | $supportedLoaders[] = $loader; 78 | } elseif ($loader instanceof LoaderChain) { 79 | $supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getLoaders())); 80 | } 81 | } 82 | 83 | return $supportedLoaders; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /CacheWarmer/TranslationsCacheWarmer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; 13 | 14 | use Psr\Container\ContainerInterface; 15 | use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; 16 | use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; 17 | use Symfony\Contracts\Service\ServiceSubscriberInterface; 18 | use Symfony\Contracts\Translation\TranslatorInterface; 19 | 20 | /** 21 | * Generates the catalogues for translations. 22 | * 23 | * @author Xavier Leune 24 | * 25 | * @final since Symfony 7.1 26 | */ 27 | class TranslationsCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface 28 | { 29 | private TranslatorInterface $translator; 30 | 31 | /** 32 | * As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. 33 | */ 34 | public function __construct( 35 | private ContainerInterface $container, 36 | ) { 37 | } 38 | 39 | public function warmUp(string $cacheDir, ?string $buildDir = null): array 40 | { 41 | $this->translator ??= $this->container->get('translator'); 42 | 43 | if ($this->translator instanceof WarmableInterface) { 44 | return $this->translator->warmUp($cacheDir, $buildDir); 45 | } 46 | 47 | return []; 48 | } 49 | 50 | public function isOptional(): bool 51 | { 52 | return true; 53 | } 54 | 55 | public static function getSubscribedServices(): array 56 | { 57 | return [ 58 | 'translator' => TranslatorInterface::class, 59 | ]; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /CacheWarmer/ValidatorCacheWarmer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; 13 | 14 | use Symfony\Component\Cache\Adapter\ArrayAdapter; 15 | use Symfony\Component\Cache\Adapter\PhpArrayAdapter; 16 | use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; 17 | use Symfony\Component\Validator\Mapping\Loader\LoaderChain; 18 | use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; 19 | use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; 20 | use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; 21 | use Symfony\Component\Validator\ValidatorBuilder; 22 | 23 | /** 24 | * Warms up XML and YAML validator metadata. 25 | * 26 | * @author Titouan Galopin 27 | * 28 | * @final since Symfony 7.1 29 | */ 30 | class ValidatorCacheWarmer extends AbstractPhpFileCacheWarmer 31 | { 32 | /** 33 | * @param string $phpArrayFile The PHP file where metadata are cached 34 | */ 35 | public function __construct( 36 | private ValidatorBuilder $validatorBuilder, 37 | string $phpArrayFile, 38 | ) { 39 | parent::__construct($phpArrayFile); 40 | } 41 | 42 | protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter, ?string $buildDir = null): bool 43 | { 44 | if (!$buildDir) { 45 | return false; 46 | } 47 | 48 | $loaders = $this->validatorBuilder->getLoaders(); 49 | $metadataFactory = new LazyLoadingMetadataFactory(new LoaderChain($loaders), $arrayAdapter); 50 | 51 | foreach ($this->extractSupportedLoaders($loaders) as $loader) { 52 | foreach ($loader->getMappedClasses() as $mappedClass) { 53 | try { 54 | if ($metadataFactory->hasMetadataFor($mappedClass)) { 55 | $metadataFactory->getMetadataFor($mappedClass); 56 | } 57 | } catch (\Exception $e) { 58 | $this->ignoreAutoloadException($mappedClass, $e); 59 | } 60 | } 61 | } 62 | 63 | return true; 64 | } 65 | 66 | /** 67 | * @return string[] A list of classes to preload on PHP 7.4+ 68 | */ 69 | protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values): array 70 | { 71 | // make sure we don't cache null values 72 | $values = array_filter($values, fn ($val) => null !== $val); 73 | 74 | return parent::warmUpPhpArrayAdapter($phpArrayAdapter, $values); 75 | } 76 | 77 | /** 78 | * @param LoaderInterface[] $loaders 79 | * 80 | * @return XmlFileLoader[]|YamlFileLoader[] 81 | */ 82 | private function extractSupportedLoaders(array $loaders): array 83 | { 84 | $supportedLoaders = []; 85 | 86 | foreach ($loaders as $loader) { 87 | if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) { 88 | $supportedLoaders[] = $loader; 89 | } elseif ($loader instanceof LoaderChain) { 90 | $supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getLoaders())); 91 | } 92 | } 93 | 94 | return $supportedLoaders; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Command/BuildDebugContainerTrait.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Component\Config\ConfigCache; 15 | use Symfony\Component\Config\FileLocator; 16 | use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; 17 | use Symfony\Component\DependencyInjection\ContainerBuilder; 18 | use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; 19 | use Symfony\Component\HttpKernel\KernelInterface; 20 | 21 | /** 22 | * @internal 23 | * 24 | * @author Robin Chalas 25 | * @author Nicolas Grekas 26 | */ 27 | trait BuildDebugContainerTrait 28 | { 29 | protected ContainerBuilder $container; 30 | 31 | /** 32 | * Loads the ContainerBuilder from the cache. 33 | * 34 | * @throws \LogicException 35 | */ 36 | protected function getContainerBuilder(KernelInterface $kernel): ContainerBuilder 37 | { 38 | if (isset($this->container)) { 39 | return $this->container; 40 | } 41 | 42 | if (!$kernel->isDebug() || !$kernel->getContainer()->getParameter('debug.container.dump') || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) { 43 | $buildContainer = \Closure::bind(function () { 44 | $this->initializeBundles(); 45 | 46 | return $this->buildContainer(); 47 | }, $kernel, $kernel::class); 48 | $container = $buildContainer(); 49 | $container->getCompilerPassConfig()->setRemovingPasses([]); 50 | $container->getCompilerPassConfig()->setAfterRemovingPasses([]); 51 | $container->compile(); 52 | } else { 53 | $buildContainer = \Closure::bind(function () { 54 | $containerBuilder = $this->getContainerBuilder(); 55 | $this->prepareContainer($containerBuilder); 56 | 57 | return $containerBuilder; 58 | }, $kernel, $kernel::class); 59 | $container = $buildContainer(); 60 | (new XmlFileLoader($container, new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump')); 61 | $locatorPass = new ServiceLocatorTagPass(); 62 | $locatorPass->process($container); 63 | 64 | $container->getCompilerPassConfig()->setBeforeOptimizationPasses([]); 65 | $container->getCompilerPassConfig()->setOptimizationPasses([]); 66 | $container->getCompilerPassConfig()->setBeforeRemovingPasses([]); 67 | } 68 | 69 | return $this->container = $container; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Command/CachePoolDeleteCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Component\Console\Attribute\AsCommand; 15 | use Symfony\Component\Console\Command\Command; 16 | use Symfony\Component\Console\Completion\CompletionInput; 17 | use Symfony\Component\Console\Completion\CompletionSuggestions; 18 | use Symfony\Component\Console\Input\InputArgument; 19 | use Symfony\Component\Console\Input\InputInterface; 20 | use Symfony\Component\Console\Output\OutputInterface; 21 | use Symfony\Component\Console\Style\SymfonyStyle; 22 | use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; 23 | 24 | /** 25 | * Delete an item from a cache pool. 26 | * 27 | * @author Pierre du Plessis 28 | */ 29 | #[AsCommand(name: 'cache:pool:delete', description: 'Delete an item from a cache pool')] 30 | final class CachePoolDeleteCommand extends Command 31 | { 32 | /** 33 | * @param string[]|null $poolNames 34 | */ 35 | public function __construct( 36 | private Psr6CacheClearer $poolClearer, 37 | private ?array $poolNames = null, 38 | ) { 39 | parent::__construct(); 40 | } 41 | 42 | protected function configure(): void 43 | { 44 | $this 45 | ->setDefinition([ 46 | new InputArgument('pool', InputArgument::REQUIRED, 'The cache pool from which to delete an item'), 47 | new InputArgument('key', InputArgument::REQUIRED, 'The cache key to delete from the pool'), 48 | ]) 49 | ->setHelp(<<<'EOF' 50 | The %command.name% deletes an item from a given cache pool. 51 | 52 | %command.full_name% 53 | EOF 54 | ) 55 | ; 56 | } 57 | 58 | protected function execute(InputInterface $input, OutputInterface $output): int 59 | { 60 | $io = new SymfonyStyle($input, $output); 61 | $pool = $input->getArgument('pool'); 62 | $key = $input->getArgument('key'); 63 | $cachePool = $this->poolClearer->getPool($pool); 64 | 65 | if (!$cachePool->hasItem($key)) { 66 | $io->note(\sprintf('Cache item "%s" does not exist in cache pool "%s".', $key, $pool)); 67 | 68 | return 0; 69 | } 70 | 71 | if (!$cachePool->deleteItem($key)) { 72 | throw new \Exception(\sprintf('Cache item "%s" could not be deleted.', $key)); 73 | } 74 | 75 | $io->success(\sprintf('Cache item "%s" was successfully deleted.', $key)); 76 | 77 | return 0; 78 | } 79 | 80 | public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void 81 | { 82 | if (\is_array($this->poolNames) && $input->mustSuggestArgumentValuesFor('pool')) { 83 | $suggestions->suggestValues($this->poolNames); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Command/CachePoolInvalidateTagsCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Component\Console\Attribute\AsCommand; 15 | use Symfony\Component\Console\Command\Command; 16 | use Symfony\Component\Console\Completion\CompletionInput; 17 | use Symfony\Component\Console\Completion\CompletionSuggestions; 18 | use Symfony\Component\Console\Input\InputArgument; 19 | use Symfony\Component\Console\Input\InputInterface; 20 | use Symfony\Component\Console\Input\InputOption; 21 | use Symfony\Component\Console\Output\OutputInterface; 22 | use Symfony\Component\Console\Style\SymfonyStyle; 23 | use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; 24 | use Symfony\Contracts\Cache\TagAwareCacheInterface; 25 | use Symfony\Contracts\Service\ServiceProviderInterface; 26 | 27 | /** 28 | * @author Kevin Bond 29 | */ 30 | #[AsCommand(name: 'cache:pool:invalidate-tags', description: 'Invalidate cache tags for all or a specific pool')] 31 | final class CachePoolInvalidateTagsCommand extends Command 32 | { 33 | private array $poolNames; 34 | 35 | public function __construct( 36 | private ServiceProviderInterface $pools, 37 | ) { 38 | parent::__construct(); 39 | 40 | $this->poolNames = array_keys($pools->getProvidedServices()); 41 | } 42 | 43 | protected function configure(): void 44 | { 45 | $this 46 | ->addArgument('tags', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'The tags to invalidate') 47 | ->addOption('pool', 'p', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The pools to invalidate on') 48 | ->setHelp(<<<'EOF' 49 | The %command.name% command invalidates tags from taggable pools. By default, all pools 50 | have the passed tags invalidated. Pass --pool=my_pool to invalidate tags on a specific pool. 51 | 52 | php %command.full_name% tag1 tag2 53 | php %command.full_name% tag1 tag2 --pool=cache2 --pool=cache1 54 | EOF) 55 | ; 56 | } 57 | 58 | protected function execute(InputInterface $input, OutputInterface $output): int 59 | { 60 | $io = new SymfonyStyle($input, $output); 61 | $pools = $input->getOption('pool') ?: $this->poolNames; 62 | $tags = $input->getArgument('tags'); 63 | $tagList = implode(', ', $tags); 64 | $errors = false; 65 | 66 | foreach ($pools as $name) { 67 | $io->comment(\sprintf('Invalidating tag(s): %s from pool %s.', $tagList, $name)); 68 | 69 | try { 70 | $pool = $this->pools->get($name); 71 | } catch (ServiceNotFoundException) { 72 | $io->error(\sprintf('Pool "%s" not found.', $name)); 73 | $errors = true; 74 | 75 | continue; 76 | } 77 | 78 | if (!$pool instanceof TagAwareCacheInterface) { 79 | $io->error(\sprintf('Pool "%s" is not taggable.', $name)); 80 | $errors = true; 81 | 82 | continue; 83 | } 84 | 85 | if (!$pool->invalidateTags($tags)) { 86 | $io->error(\sprintf('Cache tag(s) "%s" could not be invalidated for pool "%s".', $tagList, $name)); 87 | $errors = true; 88 | } 89 | } 90 | 91 | if ($errors) { 92 | $io->error('Done but with errors.'); 93 | 94 | return 1; 95 | } 96 | 97 | $io->success('Successfully invalidated cache tags.'); 98 | 99 | return 0; 100 | } 101 | 102 | public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void 103 | { 104 | if ($input->mustSuggestOptionValuesFor('pool')) { 105 | $suggestions->suggestValues($this->poolNames); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Command/CachePoolListCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Component\Console\Attribute\AsCommand; 15 | use Symfony\Component\Console\Command\Command; 16 | use Symfony\Component\Console\Input\InputInterface; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | use Symfony\Component\Console\Style\SymfonyStyle; 19 | 20 | /** 21 | * List available cache pools. 22 | * 23 | * @author Tobias Nyholm 24 | */ 25 | #[AsCommand(name: 'cache:pool:list', description: 'List available cache pools')] 26 | final class CachePoolListCommand extends Command 27 | { 28 | /** 29 | * @param string[] $poolNames 30 | */ 31 | public function __construct( 32 | private array $poolNames, 33 | ) { 34 | parent::__construct(); 35 | } 36 | 37 | protected function configure(): void 38 | { 39 | $this 40 | ->setHelp(<<<'EOF' 41 | The %command.name% command lists all available cache pools. 42 | EOF 43 | ) 44 | ; 45 | } 46 | 47 | protected function execute(InputInterface $input, OutputInterface $output): int 48 | { 49 | $io = new SymfonyStyle($input, $output); 50 | 51 | $io->table(['Pool name'], array_map(fn ($pool) => [$pool], $this->poolNames)); 52 | 53 | return 0; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Command/CachePoolPruneCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Component\Cache\PruneableInterface; 15 | use Symfony\Component\Console\Attribute\AsCommand; 16 | use Symfony\Component\Console\Command\Command; 17 | use Symfony\Component\Console\Input\InputInterface; 18 | use Symfony\Component\Console\Output\OutputInterface; 19 | use Symfony\Component\Console\Style\SymfonyStyle; 20 | 21 | /** 22 | * Cache pool pruner command. 23 | * 24 | * @author Rob Frawley 2nd 25 | */ 26 | #[AsCommand(name: 'cache:pool:prune', description: 'Prune cache pools')] 27 | final class CachePoolPruneCommand extends Command 28 | { 29 | /** 30 | * @param iterable $pools 31 | */ 32 | public function __construct( 33 | private iterable $pools, 34 | ) { 35 | parent::__construct(); 36 | } 37 | 38 | protected function configure(): void 39 | { 40 | $this 41 | ->setHelp(<<<'EOF' 42 | The %command.name% command deletes all expired items from all pruneable pools. 43 | 44 | %command.full_name% 45 | EOF 46 | ) 47 | ; 48 | } 49 | 50 | protected function execute(InputInterface $input, OutputInterface $output): int 51 | { 52 | $io = new SymfonyStyle($input, $output); 53 | 54 | foreach ($this->pools as $name => $pool) { 55 | $io->comment(\sprintf('Pruning cache pool: %s', $name)); 56 | $pool->prune(); 57 | } 58 | 59 | $io->success('Successfully pruned cache pool(s).'); 60 | 61 | return 0; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Command/CacheWarmupCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Component\Console\Attribute\AsCommand; 15 | use Symfony\Component\Console\Command\Command; 16 | use Symfony\Component\Console\Input\InputInterface; 17 | use Symfony\Component\Console\Input\InputOption; 18 | use Symfony\Component\Console\Output\OutputInterface; 19 | use Symfony\Component\Console\Style\SymfonyStyle; 20 | use Symfony\Component\DependencyInjection\Dumper\Preloader; 21 | use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate; 22 | use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; 23 | 24 | /** 25 | * Warmup the cache. 26 | * 27 | * @author Fabien Potencier 28 | * 29 | * @final 30 | */ 31 | #[AsCommand(name: 'cache:warmup', description: 'Warm up an empty cache')] 32 | class CacheWarmupCommand extends Command 33 | { 34 | public function __construct( 35 | private CacheWarmerAggregate $cacheWarmer, 36 | ) { 37 | parent::__construct(); 38 | } 39 | 40 | protected function configure(): void 41 | { 42 | $this 43 | ->setDefinition([ 44 | new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), 45 | ]) 46 | ->setHelp(<<<'EOF' 47 | The %command.name% command warms up the cache. 48 | 49 | Before running this command, the cache must be empty. 50 | 51 | EOF 52 | ) 53 | ; 54 | } 55 | 56 | protected function execute(InputInterface $input, OutputInterface $output): int 57 | { 58 | $io = new SymfonyStyle($input, $output); 59 | 60 | $kernel = $this->getApplication()->getKernel(); 61 | $io->comment(\sprintf('Warming up the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); 62 | 63 | if (!$input->getOption('no-optional-warmers')) { 64 | $this->cacheWarmer->enableOptionalWarmers(); 65 | } 66 | $cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir'); 67 | 68 | if ($kernel instanceof WarmableInterface) { 69 | $kernel->warmUp($cacheDir); 70 | } 71 | 72 | $preload = $this->cacheWarmer->warmUp($cacheDir); 73 | 74 | $buildDir = $kernel->getContainer()->getParameter('kernel.build_dir'); 75 | if ($preload && $cacheDir === $buildDir && file_exists($preloadFile = $buildDir.'/'.$kernel->getContainer()->getParameter('kernel.container_class').'.preload.php')) { 76 | Preloader::append($preloadFile, $preload); 77 | } 78 | 79 | $io->success(\sprintf('Cache for the "%s" environment (debug=%s) was successfully warmed.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); 80 | 81 | return 0; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Command/RouterMatchCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Component\Console\Attribute\AsCommand; 15 | use Symfony\Component\Console\Command\Command; 16 | use Symfony\Component\Console\Input\ArrayInput; 17 | use Symfony\Component\Console\Input\InputArgument; 18 | use Symfony\Component\Console\Input\InputInterface; 19 | use Symfony\Component\Console\Input\InputOption; 20 | use Symfony\Component\Console\Output\OutputInterface; 21 | use Symfony\Component\Console\Style\SymfonyStyle; 22 | use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; 23 | use Symfony\Component\Routing\Matcher\TraceableUrlMatcher; 24 | use Symfony\Component\Routing\RouterInterface; 25 | 26 | /** 27 | * A console command to test route matching. 28 | * 29 | * @author Fabien Potencier 30 | * 31 | * @final 32 | */ 33 | #[AsCommand(name: 'router:match', description: 'Help debug routes by simulating a path info match')] 34 | class RouterMatchCommand extends Command 35 | { 36 | /** 37 | * @param iterable $expressionLanguageProviders 38 | */ 39 | public function __construct( 40 | private RouterInterface $router, 41 | private iterable $expressionLanguageProviders = [], 42 | ) { 43 | parent::__construct(); 44 | } 45 | 46 | protected function configure(): void 47 | { 48 | $this 49 | ->setDefinition([ 50 | new InputArgument('path_info', InputArgument::REQUIRED, 'A path info'), 51 | new InputOption('method', null, InputOption::VALUE_REQUIRED, 'Set the HTTP method'), 52 | new InputOption('scheme', null, InputOption::VALUE_REQUIRED, 'Set the URI scheme (usually http or https)'), 53 | new InputOption('host', null, InputOption::VALUE_REQUIRED, 'Set the URI host'), 54 | ]) 55 | ->setHelp(<<<'EOF' 56 | The %command.name% shows which routes match a given request and which don't and for what reason: 57 | 58 | php %command.full_name% /foo 59 | 60 | or 61 | 62 | php %command.full_name% /foo --method POST --scheme https --host symfony.com --verbose 63 | 64 | EOF 65 | ) 66 | ; 67 | } 68 | 69 | protected function execute(InputInterface $input, OutputInterface $output): int 70 | { 71 | $io = new SymfonyStyle($input, $output); 72 | 73 | $context = $this->router->getContext(); 74 | if (null !== $method = $input->getOption('method')) { 75 | $context->setMethod($method); 76 | } 77 | if (null !== $scheme = $input->getOption('scheme')) { 78 | $context->setScheme($scheme); 79 | } 80 | if (null !== $host = $input->getOption('host')) { 81 | $context->setHost($host); 82 | } 83 | 84 | $matcher = new TraceableUrlMatcher($this->router->getRouteCollection(), $context); 85 | foreach ($this->expressionLanguageProviders as $provider) { 86 | $matcher->addExpressionLanguageProvider($provider); 87 | } 88 | 89 | $traces = $matcher->getTraces($input->getArgument('path_info')); 90 | 91 | $io->newLine(); 92 | 93 | $matches = false; 94 | foreach ($traces as $trace) { 95 | if (TraceableUrlMatcher::ROUTE_ALMOST_MATCHES == $trace['level']) { 96 | $io->text(\sprintf('Route "%s" almost matches but %s', $trace['name'], lcfirst($trace['log']))); 97 | } elseif (TraceableUrlMatcher::ROUTE_MATCHES == $trace['level']) { 98 | $io->success(\sprintf('Route "%s" matches', $trace['name'])); 99 | 100 | $routerDebugCommand = $this->getApplication()->find('debug:router'); 101 | $routerDebugCommand->run(new ArrayInput(['name' => $trace['name']]), $output); 102 | 103 | $matches = true; 104 | } elseif ($input->getOption('verbose')) { 105 | $io->text(\sprintf('Route "%s" does not match: %s', $trace['name'], $trace['log'])); 106 | } 107 | } 108 | 109 | if (!$matches) { 110 | $io->error(\sprintf('None of the routes match the path "%s"', $input->getArgument('path_info'))); 111 | 112 | return 1; 113 | } 114 | 115 | return 0; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Command/SecretsDecryptToLocalCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; 15 | use Symfony\Component\Console\Attribute\AsCommand; 16 | use Symfony\Component\Console\Command\Command; 17 | use Symfony\Component\Console\Input\InputInterface; 18 | use Symfony\Component\Console\Input\InputOption; 19 | use Symfony\Component\Console\Output\ConsoleOutputInterface; 20 | use Symfony\Component\Console\Output\OutputInterface; 21 | use Symfony\Component\Console\Style\SymfonyStyle; 22 | 23 | /** 24 | * @author Nicolas Grekas 25 | * 26 | * @internal 27 | */ 28 | #[AsCommand(name: 'secrets:decrypt-to-local', description: 'Decrypt all secrets and stores them in the local vault')] 29 | final class SecretsDecryptToLocalCommand extends Command 30 | { 31 | public function __construct( 32 | private AbstractVault $vault, 33 | private ?AbstractVault $localVault = null, 34 | ) { 35 | parent::__construct(); 36 | } 37 | 38 | protected function configure(): void 39 | { 40 | $this 41 | ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force overriding of secrets that already exist in the local vault') 42 | ->setHelp(<<<'EOF' 43 | The %command.name% command decrypts all secrets and copies them in the local vault. 44 | 45 | %command.full_name% 46 | 47 | When the --force option is provided, secrets that already exist in the local vault are overridden. 48 | 49 | %command.full_name% --force 50 | EOF 51 | ) 52 | ; 53 | } 54 | 55 | protected function execute(InputInterface $input, OutputInterface $output): int 56 | { 57 | $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); 58 | 59 | if (null === $this->localVault) { 60 | $io->error('The local vault is disabled.'); 61 | 62 | return 1; 63 | } 64 | 65 | $secrets = $this->vault->list(true); 66 | 67 | $io->comment(\sprintf('%d secret%s found in the vault.', \count($secrets), 1 !== \count($secrets) ? 's' : '')); 68 | 69 | $skipped = 0; 70 | if (!$input->getOption('force')) { 71 | foreach ($this->localVault->list() as $k => $v) { 72 | if (isset($secrets[$k])) { 73 | ++$skipped; 74 | unset($secrets[$k]); 75 | } 76 | } 77 | } 78 | 79 | if ($skipped > 0) { 80 | $io->warning([ 81 | \sprintf('%d secret%s already overridden in the local vault and will be skipped.', $skipped, 1 !== $skipped ? 's are' : ' is'), 82 | 'Use the --force flag to override these.', 83 | ]); 84 | } 85 | 86 | $hadErrors = false; 87 | foreach ($secrets as $k => $v) { 88 | if (null === $v) { 89 | $io->error($this->vault->getLastMessage() ?? \sprintf('Secret "%s" has been skipped as there was an error reading it.', $k)); 90 | $hadErrors = true; 91 | continue; 92 | } 93 | 94 | $this->localVault->seal($k, $v); 95 | $io->note($this->localVault->getLastMessage()); 96 | } 97 | 98 | if ($hadErrors) { 99 | return 1; 100 | } 101 | 102 | return 0; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Command/SecretsEncryptFromLocalCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; 15 | use Symfony\Component\Console\Attribute\AsCommand; 16 | use Symfony\Component\Console\Command\Command; 17 | use Symfony\Component\Console\Input\InputInterface; 18 | use Symfony\Component\Console\Output\ConsoleOutputInterface; 19 | use Symfony\Component\Console\Output\OutputInterface; 20 | use Symfony\Component\Console\Style\SymfonyStyle; 21 | 22 | /** 23 | * @author Nicolas Grekas 24 | * 25 | * @internal 26 | */ 27 | #[AsCommand(name: 'secrets:encrypt-from-local', description: 'Encrypt all local secrets to the vault')] 28 | final class SecretsEncryptFromLocalCommand extends Command 29 | { 30 | public function __construct( 31 | private AbstractVault $vault, 32 | private ?AbstractVault $localVault = null, 33 | ) { 34 | parent::__construct(); 35 | } 36 | 37 | protected function configure(): void 38 | { 39 | $this 40 | ->setHelp(<<<'EOF' 41 | The %command.name% command encrypts all locally overridden secrets to the vault. 42 | 43 | %command.full_name% 44 | EOF 45 | ) 46 | ; 47 | } 48 | 49 | protected function execute(InputInterface $input, OutputInterface $output): int 50 | { 51 | $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); 52 | 53 | if (null === $this->localVault) { 54 | $io->error('The local vault is disabled.'); 55 | 56 | return 1; 57 | } 58 | 59 | foreach ($this->vault->list(true) as $name => $value) { 60 | $localValue = $this->localVault->reveal($name); 61 | 62 | if (null !== $localValue && $value !== $localValue) { 63 | $this->vault->seal($name, $localValue); 64 | } elseif (null !== $message = $this->localVault->getLastMessage()) { 65 | $io->error($message); 66 | 67 | return 1; 68 | } 69 | } 70 | 71 | return 0; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Command/SecretsGenerateKeysCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; 15 | use Symfony\Component\Console\Attribute\AsCommand; 16 | use Symfony\Component\Console\Command\Command; 17 | use Symfony\Component\Console\Input\InputInterface; 18 | use Symfony\Component\Console\Input\InputOption; 19 | use Symfony\Component\Console\Output\ConsoleOutputInterface; 20 | use Symfony\Component\Console\Output\OutputInterface; 21 | use Symfony\Component\Console\Style\SymfonyStyle; 22 | 23 | /** 24 | * @author Tobias Schultze 25 | * @author Jérémy Derussé 26 | * @author Nicolas Grekas 27 | * 28 | * @internal 29 | */ 30 | #[AsCommand(name: 'secrets:generate-keys', description: 'Generate new encryption keys')] 31 | final class SecretsGenerateKeysCommand extends Command 32 | { 33 | public function __construct( 34 | private AbstractVault $vault, 35 | private ?AbstractVault $localVault = null, 36 | ) { 37 | parent::__construct(); 38 | } 39 | 40 | protected function configure(): void 41 | { 42 | $this 43 | ->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.') 44 | ->addOption('rotate', 'r', InputOption::VALUE_NONE, 'Re-encrypt existing secrets with the newly generated keys.') 45 | ->setHelp(<<<'EOF' 46 | The %command.name% command generates a new encryption key. 47 | 48 | %command.full_name% 49 | 50 | If encryption keys already exist, the command must be called with 51 | the --rotate option in order to override those keys and re-encrypt 52 | existing secrets. 53 | 54 | %command.full_name% --rotate 55 | EOF 56 | ) 57 | ; 58 | } 59 | 60 | protected function execute(InputInterface $input, OutputInterface $output): int 61 | { 62 | $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); 63 | $vault = $input->getOption('local') ? $this->localVault : $this->vault; 64 | 65 | if (null === $vault) { 66 | $io->success('The local vault is disabled.'); 67 | 68 | return 1; 69 | } 70 | 71 | if (!$input->getOption('rotate')) { 72 | if ($vault->generateKeys()) { 73 | $io->success($vault->getLastMessage()); 74 | 75 | if ($this->vault === $vault) { 76 | $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️'); 77 | } 78 | 79 | return 0; 80 | } 81 | 82 | $io->warning($vault->getLastMessage()); 83 | 84 | return 1; 85 | } 86 | 87 | $secrets = []; 88 | foreach ($vault->list(true) as $name => $value) { 89 | if (null === $value) { 90 | $io->error($vault->getLastMessage()); 91 | 92 | return 1; 93 | } 94 | 95 | $secrets[$name] = $value; 96 | } 97 | 98 | if (!$vault->generateKeys(true)) { 99 | $io->warning($vault->getLastMessage()); 100 | 101 | return 1; 102 | } 103 | 104 | $io->success($vault->getLastMessage()); 105 | 106 | if ($secrets) { 107 | foreach ($secrets as $name => $value) { 108 | $vault->seal($name, $value); 109 | } 110 | 111 | $io->comment('Existing secrets have been rotated to the new keys.'); 112 | } 113 | 114 | if ($this->vault === $vault) { 115 | $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️'); 116 | } 117 | 118 | return 0; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Command/SecretsListCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; 15 | use Symfony\Component\Console\Attribute\AsCommand; 16 | use Symfony\Component\Console\Command\Command; 17 | use Symfony\Component\Console\Helper\Dumper; 18 | use Symfony\Component\Console\Input\InputInterface; 19 | use Symfony\Component\Console\Input\InputOption; 20 | use Symfony\Component\Console\Output\ConsoleOutputInterface; 21 | use Symfony\Component\Console\Output\OutputInterface; 22 | use Symfony\Component\Console\Style\SymfonyStyle; 23 | 24 | /** 25 | * @author Tobias Schultze 26 | * @author Jérémy Derussé 27 | * @author Nicolas Grekas 28 | * 29 | * @internal 30 | */ 31 | #[AsCommand(name: 'secrets:list', description: 'List all secrets')] 32 | final class SecretsListCommand extends Command 33 | { 34 | public function __construct( 35 | private AbstractVault $vault, 36 | private ?AbstractVault $localVault = null, 37 | ) { 38 | parent::__construct(); 39 | } 40 | 41 | protected function configure(): void 42 | { 43 | $this 44 | ->addOption('reveal', 'r', InputOption::VALUE_NONE, 'Display decrypted values alongside names') 45 | ->setHelp(<<<'EOF' 46 | The %command.name% command list all stored secrets. 47 | 48 | %command.full_name% 49 | 50 | When the option --reveal is provided, the decrypted secrets are also displayed. 51 | 52 | %command.full_name% --reveal 53 | EOF 54 | ) 55 | ; 56 | } 57 | 58 | protected function execute(InputInterface $input, OutputInterface $output): int 59 | { 60 | $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); 61 | 62 | $io->comment('Use "%env()%" to reference a secret in a config file.'); 63 | 64 | if (!$reveal = $input->getOption('reveal')) { 65 | $io->comment(\sprintf('To reveal the secrets run php %s %s --reveal', $_SERVER['PHP_SELF'], $this->getName())); 66 | } 67 | 68 | $secrets = $this->vault->list($reveal); 69 | $localSecrets = $this->localVault?->list($reveal); 70 | 71 | $rows = []; 72 | 73 | $dump = new Dumper($output); 74 | $dump = fn ($v) => null === $v ? '******' : $dump($v); 75 | 76 | foreach ($secrets as $name => $value) { 77 | $rows[$name] = [$name, $dump($value)]; 78 | } 79 | 80 | if (null !== $message = $this->vault->getLastMessage()) { 81 | $io->comment($message); 82 | } 83 | 84 | foreach ($localSecrets ?? [] as $name => $value) { 85 | if (isset($rows[$name])) { 86 | $rows[$name][] = $dump($value); 87 | } 88 | } 89 | 90 | if (null !== $this->localVault && null !== $message = $this->localVault->getLastMessage()) { 91 | $io->comment($message); 92 | } 93 | 94 | (new SymfonyStyle($input, $output)) 95 | ->table(['Secret', 'Value'] + (null !== $localSecrets ? [2 => 'Local Value'] : []), $rows); 96 | 97 | $io->comment("Local values override secret values.\nUse secrets:set --local to define them."); 98 | 99 | return 0; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Command/SecretsRemoveCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; 15 | use Symfony\Component\Console\Attribute\AsCommand; 16 | use Symfony\Component\Console\Command\Command; 17 | use Symfony\Component\Console\Completion\CompletionInput; 18 | use Symfony\Component\Console\Completion\CompletionSuggestions; 19 | use Symfony\Component\Console\Input\InputArgument; 20 | use Symfony\Component\Console\Input\InputInterface; 21 | use Symfony\Component\Console\Input\InputOption; 22 | use Symfony\Component\Console\Output\ConsoleOutputInterface; 23 | use Symfony\Component\Console\Output\OutputInterface; 24 | use Symfony\Component\Console\Style\SymfonyStyle; 25 | 26 | /** 27 | * @author Jérémy Derussé 28 | * @author Nicolas Grekas 29 | * 30 | * @internal 31 | */ 32 | #[AsCommand(name: 'secrets:remove', description: 'Remove a secret from the vault')] 33 | final class SecretsRemoveCommand extends Command 34 | { 35 | public function __construct( 36 | private AbstractVault $vault, 37 | private ?AbstractVault $localVault = null, 38 | ) { 39 | parent::__construct(); 40 | } 41 | 42 | protected function configure(): void 43 | { 44 | $this 45 | ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret') 46 | ->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.') 47 | ->setHelp(<<<'EOF' 48 | The %command.name% command removes a secret from the vault. 49 | 50 | %command.full_name% 51 | EOF 52 | ) 53 | ; 54 | } 55 | 56 | protected function execute(InputInterface $input, OutputInterface $output): int 57 | { 58 | $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); 59 | $vault = $input->getOption('local') ? $this->localVault : $this->vault; 60 | 61 | if (null === $vault) { 62 | $io->success('The local vault is disabled.'); 63 | 64 | return 1; 65 | } 66 | 67 | if ($vault->remove($name = $input->getArgument('name'))) { 68 | $io->success($vault->getLastMessage() ?? 'Secret was removed from the vault.'); 69 | } else { 70 | $io->comment($vault->getLastMessage() ?? 'Secret was not found in the vault.'); 71 | } 72 | 73 | if ($this->vault === $vault && null !== $this->localVault->reveal($name)) { 74 | $io->comment('Note that this secret is overridden in the local vault.'); 75 | } 76 | 77 | return 0; 78 | } 79 | 80 | public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void 81 | { 82 | if (!$input->mustSuggestArgumentValuesFor('name')) { 83 | return; 84 | } 85 | 86 | $vaultKeys = array_keys($this->vault->list(false)); 87 | if ($input->getOption('local')) { 88 | if (null === $this->localVault) { 89 | return; 90 | } 91 | $vaultKeys = array_intersect($vaultKeys, array_keys($this->localVault->list(false))); 92 | } 93 | 94 | $suggestions->suggestValues($vaultKeys); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Command/SecretsRevealCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; 15 | use Symfony\Component\Console\Attribute\AsCommand; 16 | use Symfony\Component\Console\Command\Command; 17 | use Symfony\Component\Console\Input\InputArgument; 18 | use Symfony\Component\Console\Input\InputInterface; 19 | use Symfony\Component\Console\Output\ConsoleOutputInterface; 20 | use Symfony\Component\Console\Output\OutputInterface; 21 | use Symfony\Component\Console\Style\SymfonyStyle; 22 | 23 | /** 24 | * @internal 25 | */ 26 | #[AsCommand(name: 'secrets:reveal', description: 'Reveal the value of a secret')] 27 | final class SecretsRevealCommand extends Command 28 | { 29 | public function __construct( 30 | private readonly AbstractVault $vault, 31 | private readonly ?AbstractVault $localVault = null, 32 | ) { 33 | parent::__construct(); 34 | } 35 | 36 | protected function configure(): void 37 | { 38 | $this 39 | ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret to reveal', null, fn () => array_keys($this->vault->list())) 40 | ->setHelp(<<<'EOF' 41 | The %command.name% command reveals a stored secret. 42 | 43 | %command.full_name% 44 | EOF 45 | ) 46 | ; 47 | } 48 | 49 | protected function execute(InputInterface $input, OutputInterface $output): int 50 | { 51 | $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); 52 | 53 | $secrets = $this->vault->list(true); 54 | $localSecrets = $this->localVault?->list(true); 55 | 56 | $name = (string) $input->getArgument('name'); 57 | 58 | if (null !== $localSecrets && \array_key_exists($name, $localSecrets)) { 59 | $io->writeln($localSecrets[$name]); 60 | } else { 61 | if (!\array_key_exists($name, $secrets)) { 62 | $io->error(\sprintf('The secret "%s" does not exist.', $name)); 63 | 64 | return self::INVALID; 65 | } 66 | 67 | $io->writeln($secrets[$name]); 68 | } 69 | 70 | return self::SUCCESS; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Command/TranslationUpdateCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Component\Translation\Extractor\ExtractorInterface; 15 | use Symfony\Component\Translation\Reader\TranslationReaderInterface; 16 | use Symfony\Component\Translation\Writer\TranslationWriterInterface; 17 | 18 | class TranslationUpdateCommand extends TranslationExtractCommand 19 | { 20 | public function __construct( 21 | private TranslationWriterInterface $writer, 22 | private TranslationReaderInterface $reader, 23 | private ExtractorInterface $extractor, 24 | private string $defaultLocale, 25 | private ?string $defaultTransPath = null, 26 | private ?string $defaultViewsPath = null, 27 | private array $transPaths = [], 28 | private array $codePaths = [], 29 | private array $enabledLocales = [], 30 | ) { 31 | trigger_deprecation('symfony/framework-bundle', '7.3', 'The "%s" class is deprecated, use "%s" instead.', __CLASS__, TranslationExtractCommand::class); 32 | parent::__construct($writer, $reader, $extractor, $defaultLocale, $defaultTransPath, $defaultViewsPath, $transPaths, $codePaths, $enabledLocales); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Command/XliffLintCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Component\Console\Attribute\AsCommand; 15 | use Symfony\Component\Translation\Command\XliffLintCommand as BaseLintCommand; 16 | 17 | /** 18 | * Validates XLIFF files syntax and outputs encountered errors. 19 | * 20 | * @author Grégoire Pineau 21 | * @author Robin Chalas 22 | * @author Javier Eguiluz 23 | * 24 | * @final 25 | */ 26 | #[AsCommand(name: 'lint:xliff', description: 'Lint an XLIFF file and outputs encountered errors')] 27 | class XliffLintCommand extends BaseLintCommand 28 | { 29 | public function __construct() 30 | { 31 | $directoryIteratorProvider = function ($directory, $default) { 32 | if (!is_dir($directory)) { 33 | $directory = $this->getApplication()->getKernel()->locateResource($directory); 34 | } 35 | 36 | return $default($directory); 37 | }; 38 | 39 | $isReadableProvider = fn ($fileOrDirectory, $default) => str_starts_with($fileOrDirectory, '@') || $default($fileOrDirectory); 40 | 41 | parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); 42 | } 43 | 44 | protected function configure(): void 45 | { 46 | parent::configure(); 47 | 48 | $this->setHelp($this->getHelp().<<<'EOF' 49 | 50 | Or find all files in a bundle: 51 | 52 | php %command.full_name% @AcmeDemoBundle 53 | 54 | EOF 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Command/YamlLintCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Command; 13 | 14 | use Symfony\Component\Console\Attribute\AsCommand; 15 | use Symfony\Component\Yaml\Command\LintCommand as BaseLintCommand; 16 | 17 | /** 18 | * Validates YAML files syntax and outputs encountered errors. 19 | * 20 | * @author Grégoire Pineau 21 | * @author Robin Chalas 22 | * 23 | * @final 24 | */ 25 | #[AsCommand(name: 'lint:yaml', description: 'Lint a YAML file and outputs encountered errors')] 26 | class YamlLintCommand extends BaseLintCommand 27 | { 28 | public function __construct() 29 | { 30 | $directoryIteratorProvider = function ($directory, $default) { 31 | if (!is_dir($directory)) { 32 | $directory = $this->getApplication()->getKernel()->locateResource($directory); 33 | } 34 | 35 | return $default($directory); 36 | }; 37 | 38 | $isReadableProvider = fn ($fileOrDirectory, $default) => str_starts_with($fileOrDirectory, '@') || $default($fileOrDirectory); 39 | 40 | parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); 41 | } 42 | 43 | protected function configure(): void 44 | { 45 | parent::configure(); 46 | 47 | $this->setHelp($this->getHelp().<<<'EOF' 48 | 49 | Or find all files in a bundle: 50 | 51 | php %command.full_name% @AcmeDemoBundle 52 | 53 | EOF 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Console/Helper/DescriptorHelper.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Console\Helper; 13 | 14 | use Symfony\Bundle\FrameworkBundle\Console\Descriptor\JsonDescriptor; 15 | use Symfony\Bundle\FrameworkBundle\Console\Descriptor\MarkdownDescriptor; 16 | use Symfony\Bundle\FrameworkBundle\Console\Descriptor\TextDescriptor; 17 | use Symfony\Bundle\FrameworkBundle\Console\Descriptor\XmlDescriptor; 18 | use Symfony\Component\Console\Helper\DescriptorHelper as BaseDescriptorHelper; 19 | use Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter; 20 | 21 | /** 22 | * @author Jean-François Simon 23 | * 24 | * @internal 25 | */ 26 | class DescriptorHelper extends BaseDescriptorHelper 27 | { 28 | public function __construct(?FileLinkFormatter $fileLinkFormatter = null) 29 | { 30 | $this 31 | ->register('txt', new TextDescriptor($fileLinkFormatter)) 32 | ->register('xml', new XmlDescriptor()) 33 | ->register('json', new JsonDescriptor()) 34 | ->register('md', new MarkdownDescriptor()) 35 | ; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Controller/ControllerResolver.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Controller; 13 | 14 | use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver; 15 | 16 | /** 17 | * @author Fabien Potencier 18 | * 19 | * @final 20 | */ 21 | class ControllerResolver extends ContainerControllerResolver 22 | { 23 | protected function instantiateController(string $class): object 24 | { 25 | $controller = parent::instantiateController($class); 26 | 27 | if ($controller instanceof AbstractController) { 28 | if (null === $previousContainer = $controller->setContainer($this->container)) { 29 | throw new \LogicException(\sprintf('"%s" has no container set, did you forget to define it as a service subscriber?', $class)); 30 | } 31 | 32 | $controller->setContainer($previousContainer); 33 | } 34 | 35 | return $controller; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Controller/TemplateController.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Controller; 13 | 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Twig\Environment; 16 | 17 | /** 18 | * TemplateController. 19 | * 20 | * @author Fabien Potencier 21 | * 22 | * @final 23 | */ 24 | class TemplateController 25 | { 26 | public function __construct( 27 | private ?Environment $twig = null, 28 | ) { 29 | } 30 | 31 | /** 32 | * Renders a template. 33 | * 34 | * @param string $template The template name 35 | * @param int|null $maxAge Max age for client caching 36 | * @param int|null $sharedAge Max age for shared (proxy) caching 37 | * @param bool|null $private Whether or not caching should apply for client caches only 38 | * @param array $context The context (arguments) of the template 39 | * @param int $statusCode The HTTP status code to return with the response (200 "OK" by default) 40 | * @param array $headers The HTTP headers to add to the response 41 | */ 42 | public function templateAction(string $template, ?int $maxAge = null, ?int $sharedAge = null, ?bool $private = null, array $context = [], int $statusCode = 200, array $headers = []): Response 43 | { 44 | if (null === $this->twig) { 45 | throw new \LogicException('You cannot use the TemplateController if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); 46 | } 47 | 48 | $response = new Response($this->twig->render($template, $context), $statusCode); 49 | 50 | if ($maxAge) { 51 | $response->setMaxAge($maxAge); 52 | } 53 | 54 | if (null !== $sharedAge) { 55 | $response->setSharedMaxAge($sharedAge); 56 | } 57 | 58 | if ($private) { 59 | $response->setPrivate(); 60 | } elseif (false === $private || (null === $private && (null !== $maxAge || null !== $sharedAge))) { 61 | $response->setPublic(); 62 | } 63 | 64 | foreach ($headers as $key => $value) { 65 | $response->headers->set($key, $value); 66 | } 67 | 68 | return $response; 69 | } 70 | 71 | /** 72 | * @param int $statusCode The HTTP status code (200 "OK" by default) 73 | */ 74 | public function __invoke(string $template, ?int $maxAge = null, ?int $sharedAge = null, ?bool $private = null, array $context = [], int $statusCode = 200, array $headers = []): Response 75 | { 76 | return $this->templateAction($template, $maxAge, $sharedAge, $private, $context, $statusCode, $headers); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /DataCollector/AbstractDataCollector.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DataCollector; 13 | 14 | use Symfony\Component\HttpKernel\DataCollector\DataCollector; 15 | 16 | /** 17 | * @author Laurent VOULLEMIER 18 | */ 19 | abstract class AbstractDataCollector extends DataCollector implements TemplateAwareDataCollectorInterface 20 | { 21 | public function getName(): string 22 | { 23 | return static::class; 24 | } 25 | 26 | public static function getTemplate(): ?string 27 | { 28 | return null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DataCollector/RouterDataCollector.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DataCollector; 13 | 14 | use Symfony\Bundle\FrameworkBundle\Controller\RedirectController; 15 | use Symfony\Component\HttpFoundation\Request; 16 | use Symfony\Component\HttpKernel\DataCollector\RouterDataCollector as BaseRouterDataCollector; 17 | 18 | /** 19 | * @author Fabien Potencier 20 | * 21 | * @final 22 | */ 23 | class RouterDataCollector extends BaseRouterDataCollector 24 | { 25 | public function guessRoute(Request $request, mixed $controller): string 26 | { 27 | if (\is_array($controller)) { 28 | $controller = $controller[0]; 29 | } 30 | 31 | if ($controller instanceof RedirectController && $request->attributes->has('_route')) { 32 | return $request->attributes->get('_route'); 33 | } 34 | 35 | return parent::guessRoute($request, $controller); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /DataCollector/TemplateAwareDataCollectorInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DataCollector; 13 | 14 | use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; 15 | 16 | /** 17 | * @author Laurent VOULLEMIER 18 | */ 19 | interface TemplateAwareDataCollectorInterface extends DataCollectorInterface 20 | { 21 | public static function getTemplate(): ?string; 22 | } 23 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/AddDebugLogProcessorPass.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; 13 | 14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 15 | use Symfony\Component\DependencyInjection\ContainerBuilder; 16 | use Symfony\Component\DependencyInjection\Reference; 17 | 18 | class AddDebugLogProcessorPass implements CompilerPassInterface 19 | { 20 | public function process(ContainerBuilder $container): void 21 | { 22 | if (!$container->hasDefinition('profiler')) { 23 | return; 24 | } 25 | if (!$container->hasDefinition('monolog.logger_prototype')) { 26 | return; 27 | } 28 | if (!$container->hasDefinition('debug.log_processor')) { 29 | return; 30 | } 31 | 32 | $container->getDefinition('monolog.logger_prototype') 33 | ->setConfigurator([new Reference('debug.debug_logger_configurator'), 'pushDebugLogger']); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/AssetsContextPass.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; 13 | 14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 15 | use Symfony\Component\DependencyInjection\ContainerBuilder; 16 | use Symfony\Component\DependencyInjection\Definition; 17 | use Symfony\Component\DependencyInjection\Reference; 18 | 19 | class AssetsContextPass implements CompilerPassInterface 20 | { 21 | public function process(ContainerBuilder $container): void 22 | { 23 | if (!$container->hasDefinition('assets.context')) { 24 | return; 25 | } 26 | 27 | if (!$container->hasDefinition('router.request_context')) { 28 | $container->setParameter('asset.request_context.base_path', $container->getParameter('asset.request_context.base_path') ?? ''); 29 | $container->setParameter('asset.request_context.secure', $container->getParameter('asset.request_context.secure') ?? false); 30 | 31 | return; 32 | } 33 | 34 | $context = $container->getDefinition('assets.context'); 35 | 36 | if (null === $container->getParameter('asset.request_context.base_path')) { 37 | $context->replaceArgument(1, (new Definition('string'))->setFactory([new Reference('router.request_context'), 'getBaseUrl'])); 38 | } 39 | 40 | if (null === $container->getParameter('asset.request_context.secure')) { 41 | $context->replaceArgument(2, (new Definition('bool'))->setFactory([new Reference('router.request_context'), 'isSecure'])); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; 13 | 14 | use Symfony\Component\Config\ConfigCache; 15 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 16 | use Symfony\Component\DependencyInjection\ContainerBuilder; 17 | use Symfony\Component\DependencyInjection\Dumper\XmlDumper; 18 | 19 | /** 20 | * Dumps the ContainerBuilder to a cache file so that it can be used by 21 | * debugging tools such as the debug:container console command. 22 | * 23 | * @author Ryan Weaver 24 | * @author Fabien Potencier 25 | */ 26 | class ContainerBuilderDebugDumpPass implements CompilerPassInterface 27 | { 28 | public function process(ContainerBuilder $container): void 29 | { 30 | if (!$container->getParameter('debug.container.dump')) { 31 | return; 32 | } 33 | 34 | $cache = new ConfigCache($container->getParameter('debug.container.dump'), true); 35 | if (!$cache->isFresh()) { 36 | $cache->write((new XmlDumper($container))->dump(), $container->getResources()); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/ErrorLoggerCompilerPass.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; 13 | 14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 15 | use Symfony\Component\DependencyInjection\ContainerBuilder; 16 | use Symfony\Component\DependencyInjection\Reference; 17 | 18 | /** 19 | * @internal 20 | */ 21 | class ErrorLoggerCompilerPass implements CompilerPassInterface 22 | { 23 | public function process(ContainerBuilder $container): void 24 | { 25 | if (!$container->hasDefinition('debug.error_handler_configurator')) { 26 | return; 27 | } 28 | 29 | $definition = $container->getDefinition('debug.error_handler_configurator'); 30 | if ($container->hasDefinition('monolog.logger.php')) { 31 | $definition->replaceArgument(0, new Reference('monolog.logger.php')); 32 | } 33 | if ($container->hasDefinition('monolog.logger.deprecation')) { 34 | $definition->replaceArgument(5, new Reference('monolog.logger.deprecation')); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/ProfilerPass.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; 13 | 14 | use Symfony\Bundle\FrameworkBundle\DataCollector\TemplateAwareDataCollectorInterface; 15 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 16 | use Symfony\Component\DependencyInjection\ContainerBuilder; 17 | use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; 18 | use Symfony\Component\DependencyInjection\Reference; 19 | 20 | /** 21 | * Adds tagged data_collector services to profiler service. 22 | * 23 | * @author Fabien Potencier 24 | */ 25 | class ProfilerPass implements CompilerPassInterface 26 | { 27 | public function process(ContainerBuilder $container): void 28 | { 29 | if (false === $container->hasDefinition('profiler')) { 30 | return; 31 | } 32 | 33 | $definition = $container->getDefinition('profiler'); 34 | 35 | $collectors = new \SplPriorityQueue(); 36 | $order = \PHP_INT_MAX; 37 | foreach ($container->findTaggedServiceIds('data_collector', true) as $id => $attributes) { 38 | $priority = $attributes[0]['priority'] ?? 0; 39 | $template = null; 40 | 41 | $collectorClass = $container->findDefinition($id)->getClass(); 42 | if (isset($attributes[0]['template']) || is_subclass_of($collectorClass, TemplateAwareDataCollectorInterface::class)) { 43 | $idForTemplate = $attributes[0]['id'] ?? $collectorClass; 44 | if (!$idForTemplate) { 45 | throw new InvalidArgumentException(\sprintf('Data collector service "%s" must have an id attribute in order to specify a template.', $id)); 46 | } 47 | $template = [$idForTemplate, $attributes[0]['template'] ?? $collectorClass::getTemplate()]; 48 | } 49 | 50 | $collectors->insert([$id, $template], [$priority, --$order]); 51 | } 52 | 53 | $templates = []; 54 | foreach ($collectors as $collector) { 55 | $definition->addMethodCall('add', [new Reference($collector[0])]); 56 | $templates[$collector[0]] = $collector[1]; 57 | } 58 | 59 | $container->setParameter('data_collector.templates', $templates); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; 13 | 14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 15 | use Symfony\Component\DependencyInjection\ContainerBuilder; 16 | 17 | /** 18 | * @author Ahmed TAILOULOUTE 19 | */ 20 | class RemoveUnusedSessionMarshallingHandlerPass implements CompilerPassInterface 21 | { 22 | public function process(ContainerBuilder $container): void 23 | { 24 | if (!$container->hasDefinition('session.marshalling_handler')) { 25 | return; 26 | } 27 | 28 | $isMarshallerDecorated = false; 29 | 30 | foreach ($container->getDefinitions() as $definition) { 31 | $decorated = $definition->getDecoratedService(); 32 | if (null !== $decorated && 'session.marshaller' === $decorated[0]) { 33 | $isMarshallerDecorated = true; 34 | 35 | break; 36 | } 37 | } 38 | 39 | if (!$isMarshallerDecorated) { 40 | $container->removeDefinition('session.marshalling_handler'); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/TestServiceContainerRealRefPass.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; 13 | 14 | use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; 15 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 16 | use Symfony\Component\DependencyInjection\ContainerBuilder; 17 | use Symfony\Component\DependencyInjection\Reference; 18 | 19 | /** 20 | * @author Nicolas Grekas 21 | */ 22 | class TestServiceContainerRealRefPass implements CompilerPassInterface 23 | { 24 | public function process(ContainerBuilder $container): void 25 | { 26 | if (!$container->hasDefinition('test.private_services_locator')) { 27 | return; 28 | } 29 | 30 | $privateContainer = $container->getDefinition('test.private_services_locator'); 31 | $definitions = $container->getDefinitions(); 32 | $privateServices = $privateContainer->getArgument(0); 33 | $renamedIds = []; 34 | 35 | foreach ($privateServices as $id => $argument) { 36 | if (isset($definitions[$target = (string) $argument->getValues()[0]])) { 37 | $argument->setValues([new Reference($target)]); 38 | if ($id !== $target) { 39 | $renamedIds[$id] = $target; 40 | } 41 | if ($inner = $definitions[$target]->getTag('container.decorator')[0]['inner'] ?? null) { 42 | $renamedIds[$id] = $inner; 43 | } 44 | } else { 45 | unset($privateServices[$id]); 46 | } 47 | } 48 | 49 | foreach ($container->getAliases() as $id => $target) { 50 | while ($container->hasAlias($target = (string) $target)) { 51 | $target = $container->getAlias($target); 52 | } 53 | 54 | if ($definitions[$target]->hasTag('container.private')) { 55 | $privateServices[$id] = new ServiceClosureArgument(new Reference($target)); 56 | } 57 | 58 | $renamedIds[$id] = $target; 59 | } 60 | 61 | $privateContainer->replaceArgument(0, $privateServices); 62 | 63 | if ($container->hasDefinition('test.service_container') && $renamedIds) { 64 | $container->getDefinition('test.service_container')->setArgument(2, $renamedIds); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; 13 | 14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 15 | use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; 16 | use Symfony\Component\DependencyInjection\ContainerBuilder; 17 | use Symfony\Component\DependencyInjection\Reference; 18 | 19 | /** 20 | * @author Nicolas Grekas 21 | */ 22 | class TestServiceContainerWeakRefPass implements CompilerPassInterface 23 | { 24 | public function process(ContainerBuilder $container): void 25 | { 26 | if (!$container->hasDefinition('test.private_services_locator')) { 27 | return; 28 | } 29 | 30 | $privateServices = []; 31 | $definitions = $container->getDefinitions(); 32 | 33 | foreach ($definitions as $id => $definition) { 34 | if ($id && '.' !== $id[0] && (!$definition->isPublic() || $definition->isPrivate() || $definition->hasTag('container.private')) && !$definition->hasErrors() && !$definition->isAbstract()) { 35 | $privateServices[$id] = new Reference($id, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE); 36 | } 37 | } 38 | 39 | $aliases = $container->getAliases(); 40 | 41 | foreach ($aliases as $id => $alias) { 42 | if ($id && '.' !== $id[0] && (!$alias->isPublic() || $alias->isPrivate())) { 43 | while (isset($aliases[$target = (string) $alias])) { 44 | $alias = $aliases[$target]; 45 | } 46 | if (isset($definitions[$target]) && !$definitions[$target]->hasErrors() && !$definitions[$target]->isAbstract()) { 47 | $privateServices[$id] = new Reference($target, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE); 48 | } 49 | } 50 | } 51 | 52 | if ($privateServices) { 53 | $id = (string) ServiceLocatorTagPass::register($container, $privateServices); 54 | $container->setDefinition('test.private_services_locator', $container->getDefinition($id))->setPublic(true); 55 | $container->removeDefinition($id); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/TranslationLintCommandPass.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; 13 | 14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 15 | use Symfony\Component\DependencyInjection\ContainerBuilder; 16 | use Symfony\Component\Translation\TranslatorBagInterface; 17 | use Symfony\Contracts\Translation\TranslatorInterface; 18 | 19 | final class TranslationLintCommandPass implements CompilerPassInterface 20 | { 21 | public function process(ContainerBuilder $container): void 22 | { 23 | if (!$container->hasDefinition('console.command.translation_lint') || !$container->has('translator')) { 24 | return; 25 | } 26 | 27 | $translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass()); 28 | 29 | if (!is_subclass_of($translatorClass, TranslatorInterface::class) || !is_subclass_of($translatorClass, TranslatorBagInterface::class)) { 30 | $container->removeDefinition('console.command.translation_lint'); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/TranslationUpdateCommandPass.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; 13 | 14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 15 | use Symfony\Component\DependencyInjection\ContainerBuilder; 16 | 17 | class TranslationUpdateCommandPass implements CompilerPassInterface 18 | { 19 | public function process(ContainerBuilder $container): void 20 | { 21 | if (!$container->hasDefinition('console.command.translation_extract')) { 22 | return; 23 | } 24 | 25 | $translationWriterClass = $container->getParameterBag()->resolveValue($container->findDefinition('translation.writer')->getClass()); 26 | 27 | if (!method_exists($translationWriterClass, 'getFormats')) { 28 | $container->removeDefinition('console.command.translation_extract'); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DependencyInjection/VirtualRequestStackPass.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; 13 | 14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 15 | use Symfony\Component\DependencyInjection\ContainerBuilder; 16 | use Symfony\Component\DependencyInjection\Reference; 17 | 18 | class VirtualRequestStackPass implements CompilerPassInterface 19 | { 20 | public function process(ContainerBuilder $container): void 21 | { 22 | if ($container->has('.virtual_request_stack')) { 23 | return; 24 | } 25 | 26 | if ($container->hasDefinition('debug.event_dispatcher')) { 27 | $container->getDefinition('debug.event_dispatcher')->replaceArgument(3, new Reference('request_stack', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); 28 | } 29 | 30 | if ($container->hasDefinition('debug.log_processor')) { 31 | $container->getDefinition('debug.log_processor')->replaceArgument(0, new Reference('request_stack')); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /EventListener/SuggestMissingPackageSubscriber.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\EventListener; 13 | 14 | use Symfony\Component\Console\ConsoleEvents; 15 | use Symfony\Component\Console\Event\ConsoleErrorEvent; 16 | use Symfony\Component\Console\Exception\CommandNotFoundException; 17 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; 18 | 19 | /** 20 | * Suggests a package, that should be installed (via composer), 21 | * if the package is missing, and the input command namespace can be mapped to a Symfony bundle. 22 | * 23 | * @author Przemysław Bogusz 24 | * 25 | * @internal 26 | */ 27 | final class SuggestMissingPackageSubscriber implements EventSubscriberInterface 28 | { 29 | private const PACKAGES = [ 30 | 'doctrine' => [ 31 | 'fixtures' => ['DoctrineFixturesBundle', 'doctrine/doctrine-fixtures-bundle --dev'], 32 | 'mongodb' => ['DoctrineMongoDBBundle', 'doctrine/mongodb-odm-bundle'], 33 | '_default' => ['Doctrine ORM', 'symfony/orm-pack'], 34 | ], 35 | 'make' => [ 36 | '_default' => ['MakerBundle', 'symfony/maker-bundle --dev'], 37 | ], 38 | 'server' => [ 39 | '_default' => ['Debug Bundle', 'symfony/debug-bundle --dev'], 40 | ], 41 | ]; 42 | 43 | public function onConsoleError(ConsoleErrorEvent $event): void 44 | { 45 | if (!$event->getError() instanceof CommandNotFoundException) { 46 | return; 47 | } 48 | 49 | [$namespace, $command] = explode(':', $event->getInput()->getFirstArgument()) + [1 => '']; 50 | 51 | if (!isset(self::PACKAGES[$namespace])) { 52 | return; 53 | } 54 | 55 | if (isset(self::PACKAGES[$namespace][$command])) { 56 | $suggestion = self::PACKAGES[$namespace][$command]; 57 | $exact = true; 58 | } else { 59 | $suggestion = self::PACKAGES[$namespace]['_default']; 60 | $exact = false; 61 | } 62 | 63 | $error = $event->getError(); 64 | 65 | if ($error->getAlternatives() && !$exact) { 66 | return; 67 | } 68 | 69 | $message = \sprintf("%s\n\nYou may be looking for a command provided by the \"%s\" which is currently not installed. Try running \"composer require %s\".", $error->getMessage(), $suggestion[0], $suggestion[1]); 70 | $event->setError(new CommandNotFoundException($message)); 71 | } 72 | 73 | public static function getSubscribedEvents(): array 74 | { 75 | return [ 76 | ConsoleEvents::ERROR => ['onConsoleError', 0], 77 | ]; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /HttpCache/HttpCache.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\HttpCache; 13 | 14 | use Symfony\Component\HttpFoundation\Request; 15 | use Symfony\Component\HttpFoundation\Response; 16 | use Symfony\Component\HttpKernel\HttpCache\Esi; 17 | use Symfony\Component\HttpKernel\HttpCache\HttpCache as BaseHttpCache; 18 | use Symfony\Component\HttpKernel\HttpCache\Store; 19 | use Symfony\Component\HttpKernel\HttpCache\StoreInterface; 20 | use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; 21 | use Symfony\Component\HttpKernel\KernelInterface; 22 | 23 | /** 24 | * Manages HTTP cache objects in a Container. 25 | * 26 | * @author Fabien Potencier 27 | */ 28 | class HttpCache extends BaseHttpCache 29 | { 30 | protected ?string $cacheDir = null; 31 | 32 | private ?StoreInterface $store = null; 33 | private array $options; 34 | 35 | /** 36 | * @param $cache The cache directory (default used if null) or the storage instance 37 | */ 38 | public function __construct( 39 | protected KernelInterface $kernel, 40 | string|StoreInterface|null $cache = null, 41 | private ?SurrogateInterface $surrogate = null, 42 | ?array $options = null, 43 | ) { 44 | $this->options = $options ?? []; 45 | 46 | if ($cache instanceof StoreInterface) { 47 | $this->store = $cache; 48 | } else { 49 | $this->cacheDir = $cache; 50 | } 51 | 52 | if (null === $options && $kernel->isDebug()) { 53 | $this->options = ['debug' => true]; 54 | } 55 | 56 | if ($this->options['debug'] ?? false) { 57 | $this->options += ['stale_if_error' => 0]; 58 | } 59 | 60 | parent::__construct($kernel, $this->createStore(), $this->createSurrogate(), array_merge($this->options, $this->getOptions())); 61 | } 62 | 63 | protected function forward(Request $request, bool $catch = false, ?Response $entry = null): Response 64 | { 65 | $this->getKernel()->boot(); 66 | $this->getKernel()->getContainer()->set('cache', $this); 67 | 68 | return parent::forward($request, $catch, $entry); 69 | } 70 | 71 | /** 72 | * Returns an array of options to customize the Cache configuration. 73 | */ 74 | protected function getOptions(): array 75 | { 76 | return []; 77 | } 78 | 79 | protected function createSurrogate(): SurrogateInterface 80 | { 81 | return $this->surrogate ?? new Esi(); 82 | } 83 | 84 | protected function createStore(): StoreInterface 85 | { 86 | return $this->store ?? new Store($this->cacheDir ?: $this->kernel->getCacheDir().'/http_cache'); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2004-present Fabien Potencier 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FrameworkBundle 2 | =============== 3 | 4 | FrameworkBundle provides a tight integration between Symfony components and the 5 | Symfony full-stack framework. 6 | 7 | Sponsor 8 | ------- 9 | 10 | Help Symfony by [sponsoring][1] its development! 11 | 12 | Resources 13 | --------- 14 | 15 | * [Contributing](https://symfony.com/doc/current/contributing/index.html) 16 | * [Report issues](https://github.com/symfony/symfony/issues) and 17 | [send Pull Requests](https://github.com/symfony/symfony/pulls) 18 | in the [main Symfony repository](https://github.com/symfony/symfony) 19 | 20 | [1]: https://symfony.com/sponsor 21 | -------------------------------------------------------------------------------- /Resources/bin/check-unused-known-tags.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | if ('cli' !== \PHP_SAPI) { 13 | throw new Exception('This script must be run from the command line.'); 14 | } 15 | 16 | require dirname(__DIR__, 6).'/vendor/autoload.php'; 17 | 18 | use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\UnusedTagsPassUtils; 19 | 20 | $target = dirname(__DIR__, 2).'/DependencyInjection/Compiler/UnusedTagsPass.php'; 21 | $contents = file_get_contents($target); 22 | $contents = preg_replace('{private const KNOWN_TAGS = \[(.+?)\];}sm', "private const KNOWN_TAGS = [\n '".implode("',\n '", UnusedTagsPassUtils::getDefinedTags())."',\n ];", $contents); 23 | file_put_contents($target, $contents); 24 | -------------------------------------------------------------------------------- /Resources/config/assets.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Asset\Context\RequestStackContext; 15 | use Symfony\Component\Asset\Package; 16 | use Symfony\Component\Asset\Packages; 17 | use Symfony\Component\Asset\PathPackage; 18 | use Symfony\Component\Asset\UrlPackage; 19 | use Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy; 20 | use Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy; 21 | use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy; 22 | 23 | return static function (ContainerConfigurator $container) { 24 | $container->parameters() 25 | ->set('asset.request_context.base_path', null) 26 | ->set('asset.request_context.secure', null) 27 | ; 28 | 29 | $container->services() 30 | ->set('assets.packages', Packages::class) 31 | ->args([ 32 | service('assets._default_package'), 33 | tagged_iterator('assets.package', 'package'), 34 | ]) 35 | 36 | ->alias(Packages::class, 'assets.packages') 37 | 38 | ->set('assets.empty_package', Package::class) 39 | ->args([ 40 | service('assets.empty_version_strategy'), 41 | ]) 42 | 43 | ->alias('assets._default_package', 'assets.empty_package') 44 | 45 | ->set('assets.context', RequestStackContext::class) 46 | ->args([ 47 | service('request_stack'), 48 | param('asset.request_context.base_path'), 49 | param('asset.request_context.secure'), 50 | ]) 51 | 52 | ->set('assets.path_package', PathPackage::class) 53 | ->abstract() 54 | ->args([ 55 | abstract_arg('base path'), 56 | abstract_arg('version strategy'), 57 | service('assets.context'), 58 | ]) 59 | 60 | ->set('assets.url_package', UrlPackage::class) 61 | ->abstract() 62 | ->args([ 63 | abstract_arg('base URLs'), 64 | abstract_arg('version strategy'), 65 | service('assets.context'), 66 | ]) 67 | 68 | ->set('assets.static_version_strategy', StaticVersionStrategy::class) 69 | ->abstract() 70 | ->args([ 71 | abstract_arg('version'), 72 | abstract_arg('format'), 73 | ]) 74 | 75 | ->set('assets.empty_version_strategy', EmptyVersionStrategy::class) 76 | 77 | ->set('assets.json_manifest_version_strategy', JsonManifestVersionStrategy::class) 78 | ->abstract() 79 | ->args([ 80 | abstract_arg('manifest path'), 81 | service('http_client')->nullOnInvalid(), 82 | false, 83 | ]) 84 | ; 85 | }; 86 | -------------------------------------------------------------------------------- /Resources/config/cache_debug.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Bundle\FrameworkBundle\CacheWarmer\CachePoolClearerCacheWarmer; 15 | use Symfony\Component\Cache\DataCollector\CacheDataCollector; 16 | 17 | return static function (ContainerConfigurator $container) { 18 | $container->services() 19 | // DataCollector (public to prevent inlining, made private in CacheCollectorPass) 20 | ->set('data_collector.cache', CacheDataCollector::class) 21 | ->public() 22 | ->tag('data_collector', [ 23 | 'template' => '@WebProfiler/Collector/cache.html.twig', 24 | 'id' => 'cache', 25 | 'priority' => 275, 26 | ]) 27 | 28 | // CacheWarmer used in dev to clear cache pool 29 | ->set('cache_pool_clearer.cache_warmer', CachePoolClearerCacheWarmer::class) 30 | ->args([ 31 | service('cache.system_clearer'), 32 | [ 33 | 'cache.validator', 34 | 'cache.serializer', 35 | ], 36 | ]) 37 | ->tag('kernel.cache_warmer', ['priority' => 64]) 38 | ; 39 | }; 40 | -------------------------------------------------------------------------------- /Resources/config/collectors.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Bundle\FrameworkBundle\DataCollector\RouterDataCollector; 15 | use Symfony\Component\Console\DataCollector\CommandDataCollector; 16 | use Symfony\Component\HttpKernel\DataCollector\AjaxDataCollector; 17 | use Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector; 18 | use Symfony\Component\HttpKernel\DataCollector\EventDataCollector; 19 | use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector; 20 | use Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector; 21 | use Symfony\Component\HttpKernel\DataCollector\MemoryDataCollector; 22 | use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; 23 | use Symfony\Component\HttpKernel\DataCollector\TimeDataCollector; 24 | use Symfony\Component\HttpKernel\KernelEvents; 25 | 26 | return static function (ContainerConfigurator $container) { 27 | $container->services() 28 | ->set('data_collector.config', ConfigDataCollector::class) 29 | ->call('setKernel', [service('kernel')->ignoreOnInvalid()]) 30 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/config.html.twig', 'id' => 'config', 'priority' => -255]) 31 | 32 | ->set('data_collector.request', RequestDataCollector::class) 33 | ->args([ 34 | service('.virtual_request_stack')->ignoreOnInvalid(), 35 | ]) 36 | ->tag('kernel.event_subscriber') 37 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/request.html.twig', 'id' => 'request', 'priority' => 335]) 38 | 39 | ->set('data_collector.request.session_collector', \Closure::class) 40 | ->factory([\Closure::class, 'fromCallable']) 41 | ->args([[service('data_collector.request'), 'collectSessionUsage']]) 42 | 43 | ->set('data_collector.ajax', AjaxDataCollector::class) 44 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/ajax.html.twig', 'id' => 'ajax', 'priority' => 315]) 45 | 46 | ->set('data_collector.exception', ExceptionDataCollector::class) 47 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/exception.html.twig', 'id' => 'exception', 'priority' => 305]) 48 | 49 | ->set('data_collector.events', EventDataCollector::class) 50 | ->args([ 51 | tagged_iterator('event_dispatcher.dispatcher', 'name'), 52 | service('.virtual_request_stack')->ignoreOnInvalid(), 53 | ]) 54 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/events.html.twig', 'id' => 'events', 'priority' => 290]) 55 | 56 | ->set('data_collector.logger', LoggerDataCollector::class) 57 | ->args([ 58 | service('logger')->ignoreOnInvalid(), 59 | \sprintf('%s/%s', param('kernel.build_dir'), param('kernel.container_class')), 60 | service('.virtual_request_stack')->ignoreOnInvalid(), 61 | ]) 62 | ->tag('monolog.logger', ['channel' => 'profiler']) 63 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/logger.html.twig', 'id' => 'logger', 'priority' => 300]) 64 | 65 | ->set('data_collector.time', TimeDataCollector::class) 66 | ->args([ 67 | service('kernel')->ignoreOnInvalid(), 68 | service('debug.stopwatch')->ignoreOnInvalid(), 69 | ]) 70 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/time.html.twig', 'id' => 'time', 'priority' => 330]) 71 | 72 | ->set('data_collector.memory', MemoryDataCollector::class) 73 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/memory.html.twig', 'id' => 'memory', 'priority' => 325]) 74 | 75 | ->set('data_collector.router', RouterDataCollector::class) 76 | ->tag('kernel.event_listener', ['event' => KernelEvents::CONTROLLER, 'method' => 'onKernelController']) 77 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/router.html.twig', 'id' => 'router', 'priority' => 285]) 78 | 79 | ->set('.data_collector.command', CommandDataCollector::class) 80 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/command.html.twig', 'id' => 'command', 'priority' => 335]) 81 | ; 82 | }; 83 | -------------------------------------------------------------------------------- /Resources/config/debug.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\HttpKernel\Controller\ArgumentResolver\NotTaggedControllerValueResolver; 15 | use Symfony\Component\HttpKernel\Controller\TraceableArgumentResolver; 16 | use Symfony\Component\HttpKernel\Controller\TraceableControllerResolver; 17 | use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher; 18 | 19 | return static function (ContainerConfigurator $container) { 20 | $container->services() 21 | ->set('debug.event_dispatcher', TraceableEventDispatcher::class) 22 | ->decorate('event_dispatcher') 23 | ->args([ 24 | service('debug.event_dispatcher.inner'), 25 | service('debug.stopwatch'), 26 | service('logger')->nullOnInvalid(), 27 | service('.virtual_request_stack')->nullOnInvalid(), 28 | service('profiler.is_disabled_state_checker')->nullOnInvalid(), 29 | ]) 30 | ->tag('monolog.logger', ['channel' => 'event']) 31 | ->tag('kernel.reset', ['method' => 'reset']) 32 | 33 | ->set('debug.controller_resolver', TraceableControllerResolver::class) 34 | ->decorate('controller_resolver') 35 | ->args([ 36 | service('debug.controller_resolver.inner'), 37 | service('debug.stopwatch'), 38 | ]) 39 | 40 | ->set('debug.argument_resolver', TraceableArgumentResolver::class) 41 | ->decorate('argument_resolver') 42 | ->args([ 43 | service('debug.argument_resolver.inner'), 44 | service('debug.stopwatch'), 45 | ]) 46 | 47 | ->set('argument_resolver.not_tagged_controller', NotTaggedControllerValueResolver::class) 48 | ->args([abstract_arg('Controller argument, set in FrameworkExtension')]) 49 | ->tag('controller.argument_value_resolver', ['priority' => -200]) 50 | ; 51 | }; 52 | -------------------------------------------------------------------------------- /Resources/config/debug_prod.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter; 15 | use Symfony\Component\HttpKernel\Debug\ErrorHandlerConfigurator; 16 | use Symfony\Component\HttpKernel\EventListener\DebugHandlersListener; 17 | 18 | return static function (ContainerConfigurator $container) { 19 | $container->parameters()->set('debug.error_handler.throw_at', -1); 20 | 21 | $container->services() 22 | ->set('debug.error_handler_configurator', ErrorHandlerConfigurator::class) 23 | ->public() 24 | ->args([ 25 | service('logger')->nullOnInvalid(), 26 | null, // Log levels map for enabled error levels 27 | param('debug.error_handler.throw_at'), 28 | param('kernel.debug'), 29 | param('kernel.debug'), 30 | null, // Deprecation logger if different from the one above 31 | ]) 32 | ->tag('monolog.logger', ['channel' => 'php']) 33 | 34 | ->set('debug.debug_handlers_listener', DebugHandlersListener::class) 35 | ->args([null, param('kernel.runtime_mode.web')]) 36 | ->tag('kernel.event_subscriber') 37 | 38 | ->set('debug.file_link_formatter', FileLinkFormatter::class) 39 | ->args([param('debug.file_link_format')]) 40 | 41 | ->alias(FileLinkFormatter::class, 'debug.file_link_formatter') 42 | ; 43 | }; 44 | -------------------------------------------------------------------------------- /Resources/config/error_renderer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('error_handler.error_renderer.html', HtmlErrorRenderer::class) 19 | ->args([ 20 | inline_service() 21 | ->factory([HtmlErrorRenderer::class, 'isDebug']) 22 | ->args([ 23 | service('request_stack'), 24 | param('kernel.debug'), 25 | ]), 26 | param('kernel.charset'), 27 | service('debug.file_link_formatter')->nullOnInvalid(), 28 | param('kernel.project_dir'), 29 | inline_service() 30 | ->factory([HtmlErrorRenderer::class, 'getAndCleanOutputBuffer']) 31 | ->args([service('request_stack')]), 32 | service('logger')->nullOnInvalid(), 33 | ]) 34 | 35 | ->alias('error_renderer.html', 'error_handler.error_renderer.html') 36 | ->alias('error_renderer', 'error_renderer.html') 37 | ; 38 | }; 39 | -------------------------------------------------------------------------------- /Resources/config/esi.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\HttpKernel\EventListener\SurrogateListener; 15 | use Symfony\Component\HttpKernel\HttpCache\Esi; 16 | 17 | return static function (ContainerConfigurator $container) { 18 | $container->services() 19 | ->set('esi', Esi::class) 20 | 21 | ->set('esi_listener', SurrogateListener::class) 22 | ->args([service('esi')->ignoreOnInvalid()]) 23 | ->tag('kernel.event_subscriber') 24 | ; 25 | }; 26 | -------------------------------------------------------------------------------- /Resources/config/form_csrf.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('form.type_extension.csrf', FormTypeCsrfExtension::class) 19 | ->args([ 20 | service('security.csrf.token_manager'), 21 | param('form.type_extension.csrf.enabled'), 22 | param('form.type_extension.csrf.field_name'), 23 | service('translator')->nullOnInvalid(), 24 | param('validator.translation_domain'), 25 | service('form.server_params'), 26 | param('form.type_extension.csrf.field_attr'), 27 | param('.form.type_extension.csrf.token_id'), 28 | ]) 29 | ->tag('form.type_extension') 30 | ; 31 | }; 32 | -------------------------------------------------------------------------------- /Resources/config/form_debug.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Form\Extension\DataCollector\FormDataCollector; 15 | use Symfony\Component\Form\Extension\DataCollector\FormDataExtractor; 16 | use Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeFactoryDataCollectorProxy; 17 | use Symfony\Component\Form\Extension\DataCollector\Type\DataCollectorTypeExtension; 18 | use Symfony\Component\Form\ResolvedFormTypeFactory; 19 | 20 | return static function (ContainerConfigurator $container) { 21 | $container->services() 22 | ->set('form.resolved_type_factory', ResolvedTypeFactoryDataCollectorProxy::class) 23 | ->args([ 24 | inline_service(ResolvedFormTypeFactory::class), 25 | service('data_collector.form'), 26 | ]) 27 | 28 | ->set('form.type_extension.form.data_collector', DataCollectorTypeExtension::class) 29 | ->args([service('data_collector.form')]) 30 | ->tag('form.type_extension') 31 | 32 | ->set('data_collector.form.extractor', FormDataExtractor::class) 33 | 34 | ->set('data_collector.form', FormDataCollector::class) 35 | ->args([service('data_collector.form.extractor')]) 36 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/form.html.twig', 'id' => 'form', 'priority' => 310]) 37 | ; 38 | }; 39 | -------------------------------------------------------------------------------- /Resources/config/fragment_listener.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\HttpKernel\EventListener\FragmentListener; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('fragment.listener', FragmentListener::class) 19 | ->args([service('uri_signer'), param('fragment.path')]) 20 | ->tag('kernel.event_subscriber') 21 | ; 22 | }; 23 | -------------------------------------------------------------------------------- /Resources/config/fragment_renderer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler; 15 | use Symfony\Component\HttpKernel\Fragment\EsiFragmentRenderer; 16 | use Symfony\Component\HttpKernel\Fragment\FragmentUriGenerator; 17 | use Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface; 18 | use Symfony\Component\HttpKernel\Fragment\HIncludeFragmentRenderer; 19 | use Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer; 20 | use Symfony\Component\HttpKernel\Fragment\SsiFragmentRenderer; 21 | 22 | return static function (ContainerConfigurator $container) { 23 | $container->parameters() 24 | ->set('fragment.renderer.hinclude.global_template', null) 25 | ->set('fragment.path', '/_fragment') 26 | ; 27 | 28 | $container->services() 29 | ->set('fragment.handler', LazyLoadingFragmentHandler::class) 30 | ->args([ 31 | abstract_arg('fragment renderer locator'), 32 | service('request_stack'), 33 | param('kernel.debug'), 34 | ]) 35 | 36 | ->set('fragment.uri_generator', FragmentUriGenerator::class) 37 | ->args([param('fragment.path'), service('uri_signer'), service('request_stack')]) 38 | ->alias(FragmentUriGeneratorInterface::class, 'fragment.uri_generator') 39 | 40 | ->set('fragment.renderer.inline', InlineFragmentRenderer::class) 41 | ->args([service('http_kernel'), service('event_dispatcher')]) 42 | ->call('setFragmentPath', [param('fragment.path')]) 43 | ->tag('kernel.fragment_renderer', ['alias' => 'inline']) 44 | 45 | ->set('fragment.renderer.hinclude', HIncludeFragmentRenderer::class) 46 | ->args([ 47 | service('twig')->nullOnInvalid(), 48 | service('uri_signer'), 49 | param('fragment.renderer.hinclude.global_template'), 50 | ]) 51 | ->call('setFragmentPath', [param('fragment.path')]) 52 | 53 | ->set('fragment.renderer.esi', EsiFragmentRenderer::class) 54 | ->args([ 55 | service('esi')->nullOnInvalid(), 56 | service('fragment.renderer.inline'), 57 | service('uri_signer'), 58 | ]) 59 | ->call('setFragmentPath', [param('fragment.path')]) 60 | ->tag('kernel.fragment_renderer', ['alias' => 'esi']) 61 | 62 | ->set('fragment.renderer.ssi', SsiFragmentRenderer::class) 63 | ->args([ 64 | service('ssi')->nullOnInvalid(), 65 | service('fragment.renderer.inline'), 66 | service('uri_signer'), 67 | ]) 68 | ->call('setFragmentPath', [param('fragment.path')]) 69 | ->tag('kernel.fragment_renderer', ['alias' => 'ssi']) 70 | ; 71 | }; 72 | -------------------------------------------------------------------------------- /Resources/config/html_sanitizer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\HtmlSanitizer\HtmlSanitizer; 15 | use Symfony\Component\HtmlSanitizer\HtmlSanitizerConfig; 16 | use Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface; 17 | 18 | return static function (ContainerConfigurator $container) { 19 | $container->services() 20 | ->set('html_sanitizer.config.default', HtmlSanitizerConfig::class) 21 | ->call('allowSafeElements', [], true) 22 | 23 | ->set('html_sanitizer.sanitizer.default', HtmlSanitizer::class) 24 | ->args([service('html_sanitizer.config.default')]) 25 | ->tag('html_sanitizer', ['sanitizer' => 'default']) 26 | 27 | ->alias('html_sanitizer', 'html_sanitizer.sanitizer.default') 28 | ->alias(HtmlSanitizerInterface::class, 'html_sanitizer') 29 | ; 30 | }; 31 | -------------------------------------------------------------------------------- /Resources/config/http_client.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Http\Client\HttpAsyncClient; 15 | use Psr\Http\Client\ClientInterface; 16 | use Psr\Http\Message\ResponseFactoryInterface; 17 | use Psr\Http\Message\StreamFactoryInterface; 18 | use Symfony\Component\HttpClient\HttpClient; 19 | use Symfony\Component\HttpClient\HttplugClient; 20 | use Symfony\Component\HttpClient\Messenger\PingWebhookMessageHandler; 21 | use Symfony\Component\HttpClient\Psr18Client; 22 | use Symfony\Component\HttpClient\Retry\GenericRetryStrategy; 23 | use Symfony\Component\HttpClient\UriTemplateHttpClient; 24 | use Symfony\Contracts\HttpClient\HttpClientInterface; 25 | 26 | return static function (ContainerConfigurator $container) { 27 | $container->services() 28 | ->set('http_client.transport', HttpClientInterface::class) 29 | ->factory([HttpClient::class, 'create']) 30 | ->args([ 31 | [], // default options 32 | abstract_arg('max host connections'), 33 | ]) 34 | ->call('setLogger', [service('logger')->ignoreOnInvalid()]) 35 | ->tag('monolog.logger', ['channel' => 'http_client']) 36 | ->tag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore']) 37 | 38 | ->set('http_client', HttpClientInterface::class) 39 | ->factory('current') 40 | ->args([[service('http_client.transport')]]) 41 | ->tag('http_client.client') 42 | ->tag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore']) 43 | 44 | ->alias(HttpClientInterface::class, 'http_client') 45 | 46 | ->set('psr18.http_client', Psr18Client::class) 47 | ->args([ 48 | service('http_client'), 49 | service(ResponseFactoryInterface::class)->ignoreOnInvalid(), 50 | service(StreamFactoryInterface::class)->ignoreOnInvalid(), 51 | ]) 52 | 53 | ->alias(ClientInterface::class, 'psr18.http_client') 54 | 55 | ->set('httplug.http_client', HttplugClient::class) 56 | ->args([ 57 | service('http_client'), 58 | service(ResponseFactoryInterface::class)->ignoreOnInvalid(), 59 | service(StreamFactoryInterface::class)->ignoreOnInvalid(), 60 | ]) 61 | 62 | ->alias(HttpAsyncClient::class, 'httplug.http_client') 63 | 64 | ->set('http_client.abstract_retry_strategy', GenericRetryStrategy::class) 65 | ->abstract() 66 | ->args([ 67 | abstract_arg('http codes'), 68 | abstract_arg('delay ms'), 69 | abstract_arg('multiplier'), 70 | abstract_arg('max delay ms'), 71 | abstract_arg('jitter'), 72 | ]) 73 | 74 | ->set('http_client.uri_template', UriTemplateHttpClient::class) 75 | ->decorate('http_client', null, 7) // Between TraceableHttpClient (5) and RetryableHttpClient (10) 76 | ->args([ 77 | service('.inner'), 78 | service('http_client.uri_template_expander')->nullOnInvalid(), 79 | abstract_arg('default vars'), 80 | ]) 81 | 82 | ->set('http_client.uri_template_expander.guzzle', \Closure::class) 83 | ->factory([\Closure::class, 'fromCallable']) 84 | ->args([ 85 | [\GuzzleHttp\UriTemplate\UriTemplate::class, 'expand'], 86 | ]) 87 | 88 | ->set('http_client.uri_template_expander.rize', \Closure::class) 89 | ->factory([\Closure::class, 'fromCallable']) 90 | ->args([ 91 | [inline_service(\Rize\UriTemplate::class), 'expand'], 92 | ]) 93 | 94 | ->set('http_client.messenger.ping_webhook_handler', PingWebhookMessageHandler::class) 95 | ->args([ 96 | service('http_client'), 97 | ]) 98 | ->tag('messenger.message_handler') 99 | ; 100 | }; 101 | -------------------------------------------------------------------------------- /Resources/config/http_client_debug.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\HttpClient\DataCollector\HttpClientDataCollector; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('data_collector.http_client', HttpClientDataCollector::class) 19 | ->tag('data_collector', [ 20 | 'template' => '@WebProfiler/Collector/http_client.html.twig', 21 | 'id' => 'http_client', 22 | 'priority' => 250, 23 | ]) 24 | ; 25 | }; 26 | -------------------------------------------------------------------------------- /Resources/config/identity_translator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Translation\IdentityTranslator; 15 | use Symfony\Contracts\Translation\TranslatorInterface; 16 | 17 | return static function (ContainerConfigurator $container) { 18 | $container->services() 19 | ->set('translator', IdentityTranslator::class) 20 | ->alias(TranslatorInterface::class, 'translator') 21 | 22 | ->set('identity_translator', IdentityTranslator::class) 23 | ; 24 | }; 25 | -------------------------------------------------------------------------------- /Resources/config/lock.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Lock\LockFactory; 15 | use Symfony\Component\Lock\Store\CombinedStore; 16 | use Symfony\Component\Lock\Strategy\ConsensusStrategy; 17 | 18 | return static function (ContainerConfigurator $container) { 19 | $container->services() 20 | ->set('lock.store.combined.abstract', CombinedStore::class)->abstract() 21 | ->args([abstract_arg('List of stores'), service('lock.strategy.majority')]) 22 | 23 | ->set('lock.strategy.majority', ConsensusStrategy::class) 24 | 25 | ->set('lock.factory.abstract', LockFactory::class)->abstract() 26 | ->args([abstract_arg('Store')]) 27 | ->call('setLogger', [service('logger')->ignoreOnInvalid()]) 28 | ->tag('monolog.logger', ['channel' => 'lock']) 29 | ; 30 | }; 31 | -------------------------------------------------------------------------------- /Resources/config/mailer_debug.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Mailer\DataCollector\MessageDataCollector; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('mailer.data_collector', MessageDataCollector::class) 19 | ->args([ 20 | service('mailer.message_logger_listener'), 21 | ]) 22 | ->tag('data_collector', [ 23 | 'template' => '@WebProfiler/Collector/mailer.html.twig', 24 | 'id' => 'mailer', 25 | ]) 26 | ; 27 | }; 28 | -------------------------------------------------------------------------------- /Resources/config/mailer_transports.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Mailer\Bridge\AhaSend\Transport\AhaSendTransportFactory; 15 | use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory; 16 | use Symfony\Component\Mailer\Bridge\Azure\Transport\AzureTransportFactory; 17 | use Symfony\Component\Mailer\Bridge\Brevo\Transport\BrevoTransportFactory; 18 | use Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory; 19 | use Symfony\Component\Mailer\Bridge\Infobip\Transport\InfobipTransportFactory; 20 | use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; 21 | use Symfony\Component\Mailer\Bridge\MailerSend\Transport\MailerSendTransportFactory; 22 | use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; 23 | use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; 24 | use Symfony\Component\Mailer\Bridge\Mailomat\Transport\MailomatTransportFactory; 25 | use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; 26 | use Symfony\Component\Mailer\Bridge\Mailtrap\Transport\MailtrapTransportFactory; 27 | use Symfony\Component\Mailer\Bridge\Postal\Transport\PostalTransportFactory; 28 | use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; 29 | use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory; 30 | use Symfony\Component\Mailer\Bridge\Scaleway\Transport\ScalewayTransportFactory; 31 | use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; 32 | use Symfony\Component\Mailer\Bridge\Sweego\Transport\SweegoTransportFactory; 33 | use Symfony\Component\Mailer\Transport\AbstractTransportFactory; 34 | use Symfony\Component\Mailer\Transport\NativeTransportFactory; 35 | use Symfony\Component\Mailer\Transport\NullTransportFactory; 36 | use Symfony\Component\Mailer\Transport\SendmailTransportFactory; 37 | use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory; 38 | 39 | return static function (ContainerConfigurator $container) { 40 | $container->services() 41 | ->set('mailer.transport_factory.abstract', AbstractTransportFactory::class) 42 | ->abstract() 43 | ->args([ 44 | service('event_dispatcher'), 45 | service('http_client')->ignoreOnInvalid(), 46 | service('logger')->ignoreOnInvalid(), 47 | ]) 48 | ->tag('monolog.logger', ['channel' => 'mailer']); 49 | 50 | $factories = [ 51 | 'ahasend' => AhaSendTransportFactory::class, 52 | 'amazon' => SesTransportFactory::class, 53 | 'azure' => AzureTransportFactory::class, 54 | 'brevo' => BrevoTransportFactory::class, 55 | 'gmail' => GmailTransportFactory::class, 56 | 'infobip' => InfobipTransportFactory::class, 57 | 'mailchimp' => MandrillTransportFactory::class, 58 | 'mailersend' => MailerSendTransportFactory::class, 59 | 'mailgun' => MailgunTransportFactory::class, 60 | 'mailjet' => MailjetTransportFactory::class, 61 | 'mailomat' => MailomatTransportFactory::class, 62 | 'mailpace' => MailPaceTransportFactory::class, 63 | 'native' => NativeTransportFactory::class, 64 | 'null' => NullTransportFactory::class, 65 | 'postal' => PostalTransportFactory::class, 66 | 'postmark' => PostmarkTransportFactory::class, 67 | 'mailtrap' => MailtrapTransportFactory::class, 68 | 'resend' => ResendTransportFactory::class, 69 | 'scaleway' => ScalewayTransportFactory::class, 70 | 'sendgrid' => SendgridTransportFactory::class, 71 | 'sendmail' => SendmailTransportFactory::class, 72 | 'smtp' => EsmtpTransportFactory::class, 73 | 'sweego' => SweegoTransportFactory::class, 74 | ]; 75 | 76 | foreach ($factories as $name => $class) { 77 | $container->services() 78 | ->set('mailer.transport_factory.'.$name, $class) 79 | ->parent('mailer.transport_factory.abstract') 80 | ->tag('mailer.transport_factory'); 81 | } 82 | }; 83 | -------------------------------------------------------------------------------- /Resources/config/messenger_debug.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Messenger\DataCollector\MessengerDataCollector; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('data_collector.messenger', MessengerDataCollector::class) 19 | ->tag('data_collector', [ 20 | 'template' => '@WebProfiler/Collector/messenger.html.twig', 21 | 'id' => 'messenger', 22 | 'priority' => 100, 23 | ]) 24 | ; 25 | }; 26 | -------------------------------------------------------------------------------- /Resources/config/mime_type.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Mime\MimeTypeGuesserInterface; 15 | use Symfony\Component\Mime\MimeTypes; 16 | use Symfony\Component\Mime\MimeTypesInterface; 17 | 18 | return static function (ContainerConfigurator $container) { 19 | $container->services() 20 | ->set('mime_types', MimeTypes::class) 21 | ->call('setDefault', [service('mime_types')]) 22 | 23 | ->alias(MimeTypesInterface::class, 'mime_types') 24 | ->alias(MimeTypeGuesserInterface::class, 'mime_types') 25 | ; 26 | }; 27 | -------------------------------------------------------------------------------- /Resources/config/notifier_debug.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Notifier\DataCollector\NotificationDataCollector; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('notifier.data_collector', NotificationDataCollector::class) 19 | ->args([service('notifier.notification_logger_listener')]) 20 | ->tag('data_collector', ['template' => '@WebProfiler/Collector/notifier.html.twig', 'id' => 'notifier']) 21 | ; 22 | }; 23 | -------------------------------------------------------------------------------- /Resources/config/notifier_webhook.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Notifier\Bridge\Smsbox\Webhook\SmsboxRequestParser; 15 | use Symfony\Component\Notifier\Bridge\Sweego\Webhook\SweegoRequestParser; 16 | use Symfony\Component\Notifier\Bridge\Twilio\Webhook\TwilioRequestParser; 17 | use Symfony\Component\Notifier\Bridge\Vonage\Webhook\VonageRequestParser; 18 | 19 | return static function (ContainerConfigurator $container) { 20 | $container->services() 21 | ->set('notifier.webhook.request_parser.smsbox', SmsboxRequestParser::class) 22 | ->alias(SmsboxRequestParser::class, 'notifier.webhook.request_parser.smsbox') 23 | 24 | ->set('notifier.webhook.request_parser.sweego', SweegoRequestParser::class) 25 | ->alias(SweegoRequestParser::class, 'notifier.webhook.request_parser.sweego') 26 | 27 | ->set('notifier.webhook.request_parser.twilio', TwilioRequestParser::class) 28 | ->alias(TwilioRequestParser::class, 'notifier.webhook.request_parser.twilio') 29 | 30 | ->set('notifier.webhook.request_parser.vonage', VonageRequestParser::class) 31 | ->alias(VonageRequestParser::class, 'notifier.webhook.request_parser.vonage') 32 | ; 33 | }; 34 | -------------------------------------------------------------------------------- /Resources/config/object_mapper.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\ObjectMapper\Metadata\ObjectMapperMetadataFactoryInterface; 15 | use Symfony\Component\ObjectMapper\Metadata\ReflectionObjectMapperMetadataFactory; 16 | use Symfony\Component\ObjectMapper\ObjectMapper; 17 | use Symfony\Component\ObjectMapper\ObjectMapperInterface; 18 | 19 | return static function (ContainerConfigurator $container) { 20 | $container->services() 21 | ->set('object_mapper.metadata_factory', ReflectionObjectMapperMetadataFactory::class) 22 | ->alias(ObjectMapperMetadataFactoryInterface::class, 'object_mapper.metadata_factory') 23 | 24 | ->set('object_mapper', ObjectMapper::class) 25 | ->args([ 26 | service('object_mapper.metadata_factory'), 27 | service('property_accessor')->ignoreOnInvalid(), 28 | tagged_locator('object_mapper.transform_callable'), 29 | tagged_locator('object_mapper.condition_callable'), 30 | ]) 31 | ->alias(ObjectMapperInterface::class, 'object_mapper') 32 | ; 33 | }; 34 | -------------------------------------------------------------------------------- /Resources/config/process.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Process\Messenger\RunProcessMessageHandler; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container 18 | ->services() 19 | ->set('process.messenger.process_message_handler', RunProcessMessageHandler::class) 20 | ->tag('messenger.message_handler') 21 | ; 22 | }; 23 | -------------------------------------------------------------------------------- /Resources/config/profiling.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Bundle\FrameworkBundle\EventListener\ConsoleProfilerListener; 15 | use Symfony\Bundle\FrameworkBundle\FrameworkBundle; 16 | use Symfony\Component\HttpKernel\Debug\VirtualRequestStack; 17 | use Symfony\Component\HttpKernel\EventListener\ProfilerListener; 18 | use Symfony\Component\HttpKernel\Profiler\FileProfilerStorage; 19 | use Symfony\Component\HttpKernel\Profiler\Profiler; 20 | use Symfony\Component\HttpKernel\Profiler\ProfilerStateChecker; 21 | 22 | return static function (ContainerConfigurator $container) { 23 | $container->services() 24 | ->set('profiler', Profiler::class) 25 | ->public() 26 | ->args([service('profiler.storage'), service('logger')->nullOnInvalid()]) 27 | ->tag('monolog.logger', ['channel' => 'profiler']) 28 | ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.4']) 29 | 30 | ->set('profiler.storage', FileProfilerStorage::class) 31 | ->args([param('profiler.storage.dsn')]) 32 | 33 | ->set('profiler_listener', ProfilerListener::class) 34 | ->args([ 35 | service('profiler'), 36 | service('request_stack'), 37 | null, 38 | param('profiler_listener.only_exceptions'), 39 | param('profiler_listener.only_main_requests'), 40 | ]) 41 | ->tag('kernel.event_subscriber') 42 | 43 | ->set('console_profiler_listener', ConsoleProfilerListener::class) 44 | ->args([ 45 | service('.lazy_profiler'), 46 | service('.virtual_request_stack'), 47 | service('debug.stopwatch'), 48 | param('kernel.runtime_mode.cli'), 49 | service('router')->nullOnInvalid(), 50 | ]) 51 | ->tag('kernel.event_subscriber') 52 | 53 | ->set('.lazy_profiler', Profiler::class) 54 | ->factory('current') 55 | ->args([[service('profiler')]]) 56 | ->lazy() 57 | 58 | ->set('.virtual_request_stack', VirtualRequestStack::class) 59 | ->args([service('request_stack')]) 60 | ->public() 61 | 62 | ->set('profiler.state_checker', ProfilerStateChecker::class) 63 | ->args([ 64 | service_locator(['profiler' => service('profiler')->ignoreOnUninitialized()]), 65 | inline_service('bool')->factory([FrameworkBundle::class, 'considerProfilerEnabled']), 66 | ]) 67 | 68 | ->set('profiler.is_disabled_state_checker', 'Closure') 69 | ->factory(['Closure', 'fromCallable']) 70 | ->args([[service('profiler.state_checker'), 'isProfilerDisabled']]) 71 | ; 72 | }; 73 | -------------------------------------------------------------------------------- /Resources/config/property_access.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\PropertyAccess\PropertyAccessor; 15 | use Symfony\Component\PropertyAccess\PropertyAccessorInterface; 16 | use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface; 17 | use Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface; 18 | 19 | return static function (ContainerConfigurator $container) { 20 | $container->services() 21 | ->set('property_accessor', PropertyAccessor::class) 22 | ->args([ 23 | abstract_arg('magic methods allowed, set by the extension'), 24 | abstract_arg('throw exceptions, set by the extension'), 25 | service('cache.property_access')->ignoreOnInvalid(), 26 | service(PropertyReadInfoExtractorInterface::class)->nullOnInvalid(), 27 | service(PropertyWriteInfoExtractorInterface::class)->nullOnInvalid(), 28 | ]) 29 | 30 | ->alias(PropertyAccessorInterface::class, 'property_accessor') 31 | ; 32 | }; 33 | -------------------------------------------------------------------------------- /Resources/config/property_info.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\PropertyInfo\Extractor\ConstructorExtractor; 15 | use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; 16 | use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; 17 | use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; 18 | use Symfony\Component\PropertyInfo\PropertyInfoCacheExtractor; 19 | use Symfony\Component\PropertyInfo\PropertyInfoExtractor; 20 | use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; 21 | use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface; 22 | use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; 23 | use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface; 24 | use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; 25 | use Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface; 26 | 27 | return static function (ContainerConfigurator $container) { 28 | $container->services() 29 | ->set('property_info', PropertyInfoExtractor::class) 30 | ->args([[], [], [], [], []]) 31 | 32 | ->alias(PropertyAccessExtractorInterface::class, 'property_info') 33 | ->alias(PropertyDescriptionExtractorInterface::class, 'property_info') 34 | ->alias(PropertyInfoExtractorInterface::class, 'property_info') 35 | ->alias(PropertyTypeExtractorInterface::class, 'property_info') 36 | ->alias(PropertyListExtractorInterface::class, 'property_info') 37 | ->alias(PropertyInitializableExtractorInterface::class, 'property_info') 38 | 39 | ->set('property_info.cache', PropertyInfoCacheExtractor::class) 40 | ->decorate('property_info') 41 | ->args([service('property_info.cache.inner'), service('cache.property_info')]) 42 | 43 | // Extractor 44 | ->set('property_info.reflection_extractor', ReflectionExtractor::class) 45 | ->tag('property_info.list_extractor', ['priority' => -1000]) 46 | ->tag('property_info.type_extractor', ['priority' => -1002]) 47 | ->tag('property_info.constructor_extractor', ['priority' => -1002]) 48 | ->tag('property_info.access_extractor', ['priority' => -1000]) 49 | ->tag('property_info.initializable_extractor', ['priority' => -1000]) 50 | 51 | ->alias(PropertyReadInfoExtractorInterface::class, 'property_info.reflection_extractor') 52 | ->alias(PropertyWriteInfoExtractorInterface::class, 'property_info.reflection_extractor') 53 | 54 | ->set('property_info.constructor_extractor', ConstructorExtractor::class) 55 | ->args([[]]) 56 | ->tag('property_info.type_extractor', ['priority' => -999]) 57 | ; 58 | }; 59 | -------------------------------------------------------------------------------- /Resources/config/rate_limiter.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\RateLimiter\RateLimiterFactory; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('cache.rate_limiter') 19 | ->parent('cache.app') 20 | ->tag('cache.pool') 21 | 22 | ->set('limiter', RateLimiterFactory::class) 23 | ->abstract() 24 | ->args([ 25 | abstract_arg('config'), 26 | abstract_arg('storage'), 27 | null, 28 | ]) 29 | ; 30 | }; 31 | -------------------------------------------------------------------------------- /Resources/config/remote_event.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\RemoteEvent\Messenger\ConsumeRemoteEventHandler; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('remote_event.messenger.handler', ConsumeRemoteEventHandler::class) 19 | ->args([ 20 | tagged_locator('remote_event.consumer', 'consumer'), 21 | ]) 22 | ->tag('messenger.message_handler') 23 | ; 24 | }; 25 | -------------------------------------------------------------------------------- /Resources/config/request.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('request.add_request_formats_listener', AddRequestFormatsListener::class) 19 | ->args([abstract_arg('formats')]) 20 | ->tag('kernel.event_subscriber') 21 | ; 22 | }; 23 | -------------------------------------------------------------------------------- /Resources/config/routing/errors.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; 13 | use Symfony\Component\Routing\Loader\XmlFileLoader; 14 | 15 | return function (RoutingConfigurator $routes): void { 16 | foreach (debug_backtrace() as $trace) { 17 | if (isset($trace['object']) && $trace['object'] instanceof XmlFileLoader && 'doImport' === $trace['function']) { 18 | if (__DIR__ === dirname(realpath($trace['args'][3]))) { 19 | trigger_deprecation('symfony/routing', '7.3', 'The "errors.xml" routing configuration file is deprecated, import "errors.php" instead.'); 20 | 21 | break; 22 | } 23 | } 24 | } 25 | 26 | $routes->add('_preview_error', '/{code}.{_format}') 27 | ->controller('error_controller::preview') 28 | ->defaults(['_format' => 'html']) 29 | ->requirements(['code' => '\d+']) 30 | ; 31 | }; 32 | -------------------------------------------------------------------------------- /Resources/config/routing/errors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Resources/config/routing/webhook.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; 13 | use Symfony\Component\Routing\Loader\XmlFileLoader; 14 | 15 | return function (RoutingConfigurator $routes): void { 16 | foreach (debug_backtrace() as $trace) { 17 | if (isset($trace['object']) && $trace['object'] instanceof XmlFileLoader && 'doImport' === $trace['function']) { 18 | if (__DIR__ === dirname(realpath($trace['args'][3]))) { 19 | trigger_deprecation('symfony/routing', '7.3', 'The "webhook.xml" routing configuration file is deprecated, import "webhook.php" instead.'); 20 | 21 | break; 22 | } 23 | } 24 | } 25 | 26 | $routes->add('_webhook_controller', '/{type}') 27 | ->controller('webhook.controller::handle') 28 | ->requirements(['type' => '.+']) 29 | ; 30 | }; 31 | -------------------------------------------------------------------------------- /Resources/config/routing/webhook.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Resources/config/scheduler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Scheduler\EventListener\DispatchSchedulerEventListener; 15 | use Symfony\Component\Scheduler\Messenger\SchedulerTransportFactory; 16 | use Symfony\Component\Scheduler\Messenger\Serializer\Normalizer\SchedulerTriggerNormalizer; 17 | use Symfony\Component\Scheduler\Messenger\ServiceCallMessageHandler; 18 | 19 | return static function (ContainerConfigurator $container) { 20 | $container->services() 21 | ->set('scheduler.messenger.service_call_message_handler', ServiceCallMessageHandler::class) 22 | ->args([ 23 | tagged_locator('scheduler.task'), 24 | ]) 25 | ->tag('messenger.message_handler') 26 | ->set('scheduler.messenger_transport_factory', SchedulerTransportFactory::class) 27 | ->args([ 28 | tagged_locator('scheduler.schedule_provider', 'name'), 29 | service('clock'), 30 | ]) 31 | ->tag('messenger.transport_factory') 32 | ->set('scheduler.event_listener', DispatchSchedulerEventListener::class) 33 | ->args([ 34 | tagged_locator('scheduler.schedule_provider', 'name'), 35 | service('event_dispatcher'), 36 | ]) 37 | ->tag('kernel.event_subscriber') 38 | ->set('serializer.normalizer.scheduler_trigger', SchedulerTriggerNormalizer::class) 39 | ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -880]) 40 | ; 41 | }; 42 | -------------------------------------------------------------------------------- /Resources/config/secrets.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault; 15 | use Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault; 16 | use Symfony\Component\DependencyInjection\StaticEnvVarLoader; 17 | 18 | return static function (ContainerConfigurator $container) { 19 | $container->services() 20 | ->set('secrets.vault', SodiumVault::class) 21 | ->args([ 22 | abstract_arg('Secret dir, set in FrameworkExtension'), 23 | service('secrets.decryption_key')->ignoreOnInvalid(), 24 | abstract_arg('Secret env var, set in FrameworkExtension'), 25 | ]) 26 | 27 | ->set('secrets.env_var_loader', StaticEnvVarLoader::class) 28 | ->args([service('secrets.vault')]) 29 | ->tag('container.env_var_loader') 30 | 31 | ->set('secrets.decryption_key') 32 | ->parent('container.env') 33 | ->args([abstract_arg('Decryption env var, set in FrameworkExtension')]) 34 | 35 | ->set('secrets.local_vault', DotenvVault::class) 36 | ->args([abstract_arg('.env file path, set in FrameworkExtension')]) 37 | ; 38 | }; 39 | -------------------------------------------------------------------------------- /Resources/config/security_csrf.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Bridge\Twig\Extension\CsrfExtension; 15 | use Symfony\Bridge\Twig\Extension\CsrfRuntime; 16 | use Symfony\Component\Security\Csrf\CsrfTokenManager; 17 | use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; 18 | use Symfony\Component\Security\Csrf\SameOriginCsrfTokenManager; 19 | use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface; 20 | use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator; 21 | use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage; 22 | use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface; 23 | 24 | return static function (ContainerConfigurator $container) { 25 | $container->services() 26 | ->set('security.csrf.token_generator', UriSafeTokenGenerator::class) 27 | 28 | ->alias(TokenGeneratorInterface::class, 'security.csrf.token_generator') 29 | 30 | ->set('security.csrf.token_storage', SessionTokenStorage::class) 31 | ->args([service('request_stack')]) 32 | 33 | ->alias(TokenStorageInterface::class, 'security.csrf.token_storage') 34 | 35 | ->set('security.csrf.token_manager', CsrfTokenManager::class) 36 | ->args([ 37 | service('security.csrf.token_generator'), 38 | service('security.csrf.token_storage'), 39 | service('request_stack')->ignoreOnInvalid(), 40 | ]) 41 | 42 | ->alias(CsrfTokenManagerInterface::class, 'security.csrf.token_manager') 43 | 44 | ->set('twig.runtime.security_csrf', CsrfRuntime::class) 45 | ->args([service('security.csrf.token_manager')]) 46 | ->tag('twig.runtime') 47 | 48 | ->set('twig.extension.security_csrf', CsrfExtension::class) 49 | ->tag('twig.extension') 50 | 51 | ->set('security.csrf.same_origin_token_manager', SameOriginCsrfTokenManager::class) 52 | ->decorate('security.csrf.token_manager') 53 | ->args([ 54 | service('request_stack'), 55 | service('logger')->nullOnInvalid(), 56 | service('.inner'), 57 | abstract_arg('framework.csrf_protection.stateless_token_ids'), 58 | abstract_arg('framework.csrf_protection.check_header'), 59 | abstract_arg('framework.csrf_protection.cookie_name'), 60 | ]) 61 | ->tag('monolog.logger', ['channel' => 'request']) 62 | ->tag('kernel.event_listener', ['event' => 'kernel.response', 'method' => 'onKernelResponse']) 63 | ; 64 | }; 65 | -------------------------------------------------------------------------------- /Resources/config/semaphore.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Semaphore\SemaphoreFactory; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('semaphore.factory.abstract', SemaphoreFactory::class)->abstract() 19 | ->args([abstract_arg('Store')]) 20 | ->call('setLogger', [service('logger')->ignoreOnInvalid()]) 21 | ->tag('monolog.logger', ['channel' => 'semaphore']) 22 | ; 23 | }; 24 | -------------------------------------------------------------------------------- /Resources/config/serializer_debug.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Serializer\DataCollector\SerializerDataCollector; 15 | use Symfony\Component\Serializer\Debug\TraceableSerializer; 16 | 17 | return static function (ContainerConfigurator $container) { 18 | $container->services() 19 | ->set('debug.serializer', TraceableSerializer::class) 20 | ->decorate('serializer') 21 | ->args([ 22 | service('debug.serializer.inner'), 23 | service('serializer.data_collector'), 24 | 'default', 25 | ]) 26 | 27 | ->set('serializer.data_collector', SerializerDataCollector::class) 28 | ->tag('data_collector', [ 29 | 'template' => '@WebProfiler/Collector/serializer.html.twig', 30 | 'id' => 'serializer', 31 | ]) 32 | ; 33 | }; 34 | -------------------------------------------------------------------------------- /Resources/config/ssi.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\HttpKernel\EventListener\SurrogateListener; 15 | use Symfony\Component\HttpKernel\HttpCache\Ssi; 16 | 17 | return static function (ContainerConfigurator $container) { 18 | $container->services() 19 | ->set('ssi', Ssi::class) 20 | 21 | ->set('ssi_listener', SurrogateListener::class) 22 | ->args([service('ssi')->ignoreOnInvalid()]) 23 | ->tag('kernel.event_subscriber') 24 | ; 25 | }; 26 | -------------------------------------------------------------------------------- /Resources/config/test.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Bundle\FrameworkBundle\KernelBrowser; 15 | use Symfony\Bundle\FrameworkBundle\Test\TestContainer; 16 | use Symfony\Component\BrowserKit\CookieJar; 17 | use Symfony\Component\BrowserKit\History; 18 | use Symfony\Component\DependencyInjection\ServiceLocator; 19 | use Symfony\Component\HttpKernel\EventListener\SessionListener; 20 | 21 | return static function (ContainerConfigurator $container) { 22 | $container->parameters()->set('test.client.parameters', []); 23 | 24 | $container->services() 25 | ->set('test.client', KernelBrowser::class) 26 | ->args([ 27 | service('kernel'), 28 | param('test.client.parameters'), 29 | service('test.client.history'), 30 | service('test.client.cookiejar'), 31 | ]) 32 | ->share(false) 33 | ->public() 34 | 35 | ->set('test.client.history', History::class)->share(false) 36 | ->set('test.client.cookiejar', CookieJar::class)->share(false) 37 | 38 | ->set('test.session.listener', SessionListener::class) 39 | ->args([ 40 | service_locator([ 41 | 'session_factory' => service('session.factory')->ignoreOnInvalid(), 42 | ]), 43 | param('kernel.debug'), 44 | param('session.storage.options'), 45 | ]) 46 | ->tag('kernel.event_subscriber') 47 | 48 | ->set('test.service_container', TestContainer::class) 49 | ->args([ 50 | service('kernel'), 51 | 'test.private_services_locator', 52 | ]) 53 | ->public() 54 | 55 | ->set('test.private_services_locator', ServiceLocator::class) 56 | ->args([abstract_arg('callable collection')]) 57 | ->public() 58 | ; 59 | }; 60 | -------------------------------------------------------------------------------- /Resources/config/translation_debug.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Translation\DataCollector\TranslationDataCollector; 15 | use Symfony\Component\Translation\DataCollectorTranslator; 16 | 17 | return static function (ContainerConfigurator $container) { 18 | $container->services() 19 | ->set('translator.data_collector', DataCollectorTranslator::class) 20 | ->args([service('translator.data_collector.inner')]) 21 | 22 | ->set('data_collector.translation', TranslationDataCollector::class) 23 | ->args([service('translator.data_collector')]) 24 | ->tag('data_collector', [ 25 | 'template' => '@WebProfiler/Collector/translation.html.twig', 26 | 'id' => 'translation', 27 | 'priority' => 275, 28 | ]) 29 | ; 30 | }; 31 | -------------------------------------------------------------------------------- /Resources/config/translation_providers.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Translation\Bridge\Crowdin\CrowdinProviderFactory; 15 | use Symfony\Component\Translation\Bridge\Loco\LocoProviderFactory; 16 | use Symfony\Component\Translation\Bridge\Lokalise\LokaliseProviderFactory; 17 | use Symfony\Component\Translation\Bridge\Phrase\PhraseProviderFactory; 18 | use Symfony\Component\Translation\Provider\NullProviderFactory; 19 | use Symfony\Component\Translation\Provider\TranslationProviderCollection; 20 | use Symfony\Component\Translation\Provider\TranslationProviderCollectionFactory; 21 | 22 | return static function (ContainerConfigurator $container) { 23 | $container->services() 24 | ->set('translation.provider_collection', TranslationProviderCollection::class) 25 | ->factory([service('translation.provider_collection_factory'), 'fromConfig']) 26 | ->args([ 27 | [], // Providers 28 | ]) 29 | 30 | ->set('translation.provider_collection_factory', TranslationProviderCollectionFactory::class) 31 | ->args([ 32 | tagged_iterator('translation.provider_factory'), 33 | [], // Enabled locales 34 | ]) 35 | 36 | ->set('translation.provider_factory.null', NullProviderFactory::class) 37 | ->tag('translation.provider_factory') 38 | 39 | ->set('translation.provider_factory.crowdin', CrowdinProviderFactory::class) 40 | ->args([ 41 | service('http_client'), 42 | service('logger'), 43 | param('kernel.default_locale'), 44 | service('translation.loader.xliff'), 45 | service('translation.dumper.xliff'), 46 | ]) 47 | ->tag('translation.provider_factory') 48 | 49 | ->set('translation.provider_factory.loco', LocoProviderFactory::class) 50 | ->args([ 51 | service('http_client'), 52 | service('logger'), 53 | param('kernel.default_locale'), 54 | service('translation.loader.xliff'), 55 | service('translator'), 56 | ]) 57 | ->tag('translation.provider_factory') 58 | 59 | ->set('translation.provider_factory.lokalise', LokaliseProviderFactory::class) 60 | ->args([ 61 | service('http_client'), 62 | service('logger'), 63 | param('kernel.default_locale'), 64 | service('translation.loader.xliff'), 65 | ]) 66 | ->tag('translation.provider_factory') 67 | 68 | ->set('translation.provider_factory.phrase', PhraseProviderFactory::class) 69 | ->args([ 70 | service('http_client'), 71 | service('logger'), 72 | service('translation.loader.xliff'), 73 | service('translation.dumper.xliff'), 74 | service('cache.app'), 75 | param('kernel.default_locale'), 76 | ]) 77 | ->tag('translation.provider_factory') 78 | ; 79 | }; 80 | -------------------------------------------------------------------------------- /Resources/config/type_info.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\TypeInfo\TypeContext\TypeContextFactory; 15 | use Symfony\Component\TypeInfo\TypeResolver\ReflectionParameterTypeResolver; 16 | use Symfony\Component\TypeInfo\TypeResolver\ReflectionPropertyTypeResolver; 17 | use Symfony\Component\TypeInfo\TypeResolver\ReflectionReturnTypeResolver; 18 | use Symfony\Component\TypeInfo\TypeResolver\ReflectionTypeResolver; 19 | use Symfony\Component\TypeInfo\TypeResolver\TypeResolver; 20 | use Symfony\Component\TypeInfo\TypeResolver\TypeResolverInterface; 21 | 22 | return static function (ContainerConfigurator $container) { 23 | $container->services() 24 | // type context 25 | ->set('type_info.type_context_factory', TypeContextFactory::class) 26 | ->args([service('type_info.resolver.string')->nullOnInvalid()]) 27 | 28 | // type resolvers 29 | ->set('type_info.resolver', TypeResolver::class) 30 | ->args([service_locator([ 31 | \ReflectionType::class => service('type_info.resolver.reflection_type'), 32 | \ReflectionParameter::class => service('type_info.resolver.reflection_parameter'), 33 | \ReflectionProperty::class => service('type_info.resolver.reflection_property'), 34 | \ReflectionFunctionAbstract::class => service('type_info.resolver.reflection_return'), 35 | ])]) 36 | ->alias(TypeResolverInterface::class, 'type_info.resolver') 37 | 38 | ->set('type_info.resolver.reflection_type', ReflectionTypeResolver::class) 39 | ->args([service('type_info.type_context_factory')]) 40 | 41 | ->set('type_info.resolver.reflection_parameter', ReflectionParameterTypeResolver::class) 42 | ->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')]) 43 | 44 | ->set('type_info.resolver.reflection_property', ReflectionPropertyTypeResolver::class) 45 | ->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')]) 46 | 47 | ->set('type_info.resolver.reflection_return', ReflectionReturnTypeResolver::class) 48 | ->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')]) 49 | ; 50 | }; 51 | -------------------------------------------------------------------------------- /Resources/config/uid.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Uid\Factory\NameBasedUuidFactory; 15 | use Symfony\Component\Uid\Factory\RandomBasedUuidFactory; 16 | use Symfony\Component\Uid\Factory\TimeBasedUuidFactory; 17 | use Symfony\Component\Uid\Factory\UlidFactory; 18 | use Symfony\Component\Uid\Factory\UuidFactory; 19 | 20 | return static function (ContainerConfigurator $container) { 21 | $container->services() 22 | ->set('ulid.factory', UlidFactory::class) 23 | ->alias(UlidFactory::class, 'ulid.factory') 24 | 25 | ->set('uuid.factory', UuidFactory::class) 26 | ->alias(UuidFactory::class, 'uuid.factory') 27 | 28 | ->set('name_based_uuid.factory', NameBasedUuidFactory::class) 29 | ->factory([service('uuid.factory'), 'nameBased']) 30 | ->args([abstract_arg('Please set the "framework.uid.name_based_uuid_namespace" configuration option to use the "name_based_uuid.factory" service')]) 31 | ->alias(NameBasedUuidFactory::class, 'name_based_uuid.factory') 32 | 33 | ->set('random_based_uuid.factory', RandomBasedUuidFactory::class) 34 | ->factory([service('uuid.factory'), 'randomBased']) 35 | ->alias(RandomBasedUuidFactory::class, 'random_based_uuid.factory') 36 | 37 | ->set('time_based_uuid.factory', TimeBasedUuidFactory::class) 38 | ->factory([service('uuid.factory'), 'timeBased']) 39 | ->alias(TimeBasedUuidFactory::class, 'time_based_uuid.factory') 40 | ; 41 | }; 42 | -------------------------------------------------------------------------------- /Resources/config/validator_debug.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Validator\DataCollector\ValidatorDataCollector; 15 | use Symfony\Component\Validator\Validator\TraceableValidator; 16 | 17 | return static function (ContainerConfigurator $container) { 18 | $container->services() 19 | ->set('debug.validator', TraceableValidator::class) 20 | ->decorate('validator', null, 255) 21 | ->args([ 22 | service('debug.validator.inner'), 23 | service('profiler.is_disabled_state_checker')->nullOnInvalid(), 24 | ]) 25 | ->tag('kernel.reset', [ 26 | 'method' => 'reset', 27 | ]) 28 | 29 | ->set('data_collector.validator', ValidatorDataCollector::class) 30 | ->args([ 31 | service('debug.validator'), 32 | ]) 33 | ->tag('data_collector', [ 34 | 'template' => '@WebProfiler/Collector/validator.html.twig', 35 | 'id' => 'validator', 36 | 'priority' => 320, 37 | ]) 38 | ; 39 | }; 40 | -------------------------------------------------------------------------------- /Resources/config/web_link.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener; 15 | use Symfony\Component\WebLink\HttpHeaderSerializer; 16 | 17 | return static function (ContainerConfigurator $container) { 18 | $container->services() 19 | 20 | ->set('web_link.http_header_serializer', HttpHeaderSerializer::class) 21 | ->alias(HttpHeaderSerializer::class, 'web_link.http_header_serializer') 22 | 23 | ->set('web_link.add_link_header_listener', AddLinkHeaderListener::class) 24 | ->args([ 25 | service('web_link.http_header_serializer'), 26 | ]) 27 | ->tag('kernel.event_subscriber') 28 | ; 29 | }; 30 | -------------------------------------------------------------------------------- /Resources/config/webhook.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Webhook\Client\RequestParser; 15 | use Symfony\Component\Webhook\Controller\WebhookController; 16 | use Symfony\Component\Webhook\Messenger\SendWebhookHandler; 17 | use Symfony\Component\Webhook\Server\HeadersConfigurator; 18 | use Symfony\Component\Webhook\Server\HeaderSignatureConfigurator; 19 | use Symfony\Component\Webhook\Server\JsonBodyConfigurator; 20 | use Symfony\Component\Webhook\Server\NativeJsonPayloadSerializer; 21 | use Symfony\Component\Webhook\Server\SerializerPayloadSerializer; 22 | use Symfony\Component\Webhook\Server\Transport; 23 | 24 | return static function (ContainerConfigurator $container) { 25 | $container->services() 26 | ->set('webhook.transport', Transport::class) 27 | ->args([ 28 | service('http_client'), 29 | service('webhook.headers_configurator'), 30 | service('webhook.body_configurator.json'), 31 | service('webhook.signer'), 32 | ]) 33 | 34 | ->set('webhook.headers_configurator', HeadersConfigurator::class) 35 | 36 | ->set('webhook.body_configurator.json', JsonBodyConfigurator::class) 37 | ->args([ 38 | abstract_arg('payload serializer'), 39 | ]) 40 | 41 | ->set('webhook.payload_serializer.json', NativeJsonPayloadSerializer::class) 42 | 43 | ->set('webhook.payload_serializer.serializer', SerializerPayloadSerializer::class) 44 | ->args([ 45 | service('serializer'), 46 | ]) 47 | 48 | ->set('webhook.signer', HeaderSignatureConfigurator::class) 49 | 50 | ->set('webhook.messenger.send_handler', SendWebhookHandler::class) 51 | ->args([ 52 | service('webhook.transport'), 53 | ]) 54 | ->tag('messenger.message_handler') 55 | 56 | ->set('webhook.request_parser', RequestParser::class) 57 | ->alias(RequestParser::class, 'webhook.request_parser') 58 | 59 | ->set('webhook.controller', WebhookController::class) 60 | ->public() 61 | ->args([ 62 | abstract_arg('user defined parsers'), 63 | abstract_arg('message bus'), 64 | ]) 65 | ; 66 | }; 67 | -------------------------------------------------------------------------------- /Resources/config/workflow.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Workflow\EventListener\ExpressionLanguage; 15 | use Symfony\Component\Workflow\MarkingStore\MethodMarkingStore; 16 | use Symfony\Component\Workflow\Registry; 17 | use Symfony\Component\Workflow\StateMachine; 18 | use Symfony\Component\Workflow\Workflow; 19 | 20 | return static function (ContainerConfigurator $container) { 21 | $container->services() 22 | ->set('workflow.abstract', Workflow::class) 23 | ->args([ 24 | abstract_arg('workflow definition'), 25 | abstract_arg('marking store'), 26 | service('event_dispatcher')->ignoreOnInvalid(), 27 | abstract_arg('workflow name'), 28 | abstract_arg('events to dispatch'), 29 | ]) 30 | ->abstract() 31 | ->set('state_machine.abstract', StateMachine::class) 32 | ->args([ 33 | abstract_arg('workflow definition'), 34 | abstract_arg('marking store'), 35 | service('event_dispatcher')->ignoreOnInvalid(), 36 | abstract_arg('workflow name'), 37 | abstract_arg('events to dispatch'), 38 | ]) 39 | ->abstract() 40 | ->set('workflow.marking_store.method', MethodMarkingStore::class) 41 | ->abstract() 42 | ->set('workflow.registry', Registry::class) 43 | ->alias(Registry::class, 'workflow.registry') 44 | ->set('workflow.security.expression_language', ExpressionLanguage::class) 45 | ; 46 | }; 47 | -------------------------------------------------------------------------------- /Resources/config/workflow_debug.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\DependencyInjection\Loader\Configurator; 13 | 14 | use Symfony\Component\Workflow\DataCollector\WorkflowDataCollector; 15 | 16 | return static function (ContainerConfigurator $container) { 17 | $container->services() 18 | ->set('data_collector.workflow', WorkflowDataCollector::class) 19 | ->tag('data_collector', [ 20 | 'template' => '@WebProfiler/Collector/workflow.html.twig', 21 | 'id' => 'workflow', 22 | ]) 23 | ->args([ 24 | tagged_iterator('workflow', 'name'), 25 | service('event_dispatcher'), 26 | service('debug.file_link_formatter'), 27 | ]) 28 | ; 29 | }; 30 | -------------------------------------------------------------------------------- /Routing/Attribute/AsRoutingConditionService.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Routing\Attribute; 13 | 14 | use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; 15 | 16 | /** 17 | * Service tag to autoconfigure routing condition services. 18 | * 19 | * You can tag a service: 20 | * 21 | * #[AsRoutingConditionService('foo')] 22 | * class SomeFooService 23 | * { 24 | * public function bar(): bool 25 | * { 26 | * // ... 27 | * } 28 | * } 29 | * 30 | * Then you can use the tagged service in the routing condition: 31 | * 32 | * class PageController 33 | * { 34 | * #[Route('/page', condition: "service('foo').bar()")] 35 | * public function page(): Response 36 | * { 37 | * // ... 38 | * } 39 | * } 40 | */ 41 | #[\Attribute(\Attribute::TARGET_CLASS)] 42 | class AsRoutingConditionService extends AutoconfigureTag 43 | { 44 | /** 45 | * @param string|null $alias The alias of the service to use it in routing condition expressions 46 | * @param int $priority Defines a priority that allows the routing condition service to override a service with the same alias 47 | */ 48 | public function __construct( 49 | ?string $alias = null, 50 | int $priority = 0, 51 | ) { 52 | parent::__construct('routing.condition_service', ['alias' => $alias, 'priority' => $priority]); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Routing/AttributeRouteControllerLoader.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Routing; 13 | 14 | use Symfony\Component\Routing\Loader\AttributeClassLoader; 15 | use Symfony\Component\Routing\Route; 16 | 17 | /** 18 | * AttributeRouteControllerLoader is an implementation of AttributeClassLoader 19 | * that sets the '_controller' default based on the class and method names. 20 | * 21 | * @author Fabien Potencier 22 | * @author Alexandre Daubois 23 | */ 24 | class AttributeRouteControllerLoader extends AttributeClassLoader 25 | { 26 | /** 27 | * Configures the _controller default parameter of a given Route instance. 28 | */ 29 | protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $attr): void 30 | { 31 | if ('__invoke' === $method->getName()) { 32 | $route->setDefault('_controller', $class->getName()); 33 | } else { 34 | $route->setDefault('_controller', $class->getName().'::'.$method->getName()); 35 | } 36 | } 37 | 38 | /** 39 | * Makes the default route name more sane by removing common keywords. 40 | */ 41 | protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method): string 42 | { 43 | $name = preg_replace('/(bundle|controller)_/', '_', parent::getDefaultRouteName($class, $method)); 44 | 45 | if (str_ends_with($method->name, 'Action') || str_ends_with($method->name, '_action')) { 46 | $name = preg_replace('/action(_\d+)?$/', '\\1', $name); 47 | } 48 | 49 | return str_replace('__', '_', $name); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Routing/DelegatingLoader.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Routing; 13 | 14 | use Symfony\Component\Config\Exception\LoaderLoadException; 15 | use Symfony\Component\Config\Loader\DelegatingLoader as BaseDelegatingLoader; 16 | use Symfony\Component\Config\Loader\LoaderResolverInterface; 17 | use Symfony\Component\Routing\RouteCollection; 18 | 19 | /** 20 | * DelegatingLoader delegates route loading to other loaders using a loader resolver. 21 | * 22 | * This implementation resolves the _controller attribute from the short notation 23 | * to the fully-qualified form (from a:b:c to class::method). 24 | * 25 | * @author Fabien Potencier 26 | * 27 | * @final 28 | */ 29 | class DelegatingLoader extends BaseDelegatingLoader 30 | { 31 | private bool $loading = false; 32 | 33 | public function __construct( 34 | LoaderResolverInterface $resolver, 35 | private array $defaultOptions = [], 36 | private array $defaultRequirements = [], 37 | ) { 38 | parent::__construct($resolver); 39 | } 40 | 41 | public function load(mixed $resource, ?string $type = null): RouteCollection 42 | { 43 | if ($this->loading) { 44 | // This can happen if a fatal error occurs in parent::load(). 45 | // Here is the scenario: 46 | // - while routes are being loaded by parent::load() below, a fatal error 47 | // occurs (e.g. parse error in a controller while loading annotations); 48 | // - PHP abruptly empties the stack trace, bypassing all catch/finally blocks; 49 | // it then calls the registered shutdown functions; 50 | // - the ErrorHandler catches the fatal error and re-injects it for rendering 51 | // thanks to HttpKernel->terminateWithException() (that calls handleException()); 52 | // - at this stage, if we try to load the routes again, we must prevent 53 | // the fatal error from occurring a second time, 54 | // otherwise the PHP process would be killed immediately; 55 | // - while rendering the exception page, the router can be required 56 | // (by e.g. the web profiler that needs to generate a URL); 57 | // - this handles the case and prevents the second fatal error 58 | // by triggering an exception beforehand. 59 | 60 | throw new LoaderLoadException($resource, null, 0, null, $type); 61 | } 62 | $this->loading = true; 63 | 64 | try { 65 | $collection = parent::load($resource, $type); 66 | } finally { 67 | $this->loading = false; 68 | } 69 | 70 | foreach ($collection->all() as $route) { 71 | if ($this->defaultOptions) { 72 | $route->setOptions($route->getOptions() + $this->defaultOptions); 73 | } 74 | if ($this->defaultRequirements) { 75 | $route->setRequirements($route->getRequirements() + $this->defaultRequirements); 76 | } 77 | if (!\is_string($controller = $route->getDefault('_controller'))) { 78 | continue; 79 | } 80 | 81 | if (str_contains($controller, '::')) { 82 | continue; 83 | } 84 | 85 | $route->setDefault('_controller', $controller); 86 | } 87 | 88 | return $collection; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Routing/RedirectableCompiledUrlMatcher.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Routing; 13 | 14 | use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; 15 | use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; 16 | 17 | /** 18 | * @author Fabien Potencier 19 | * 20 | * @internal 21 | */ 22 | class RedirectableCompiledUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface 23 | { 24 | public function redirect(string $path, string $route, ?string $scheme = null): array 25 | { 26 | return [ 27 | '_controller' => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirectAction', 28 | 'path' => $path, 29 | 'permanent' => true, 30 | 'scheme' => $scheme, 31 | 'httpPort' => $this->context->getHttpPort(), 32 | 'httpsPort' => $this->context->getHttpsPort(), 33 | '_route' => $route, 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Routing/RouteLoaderInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Routing; 13 | 14 | /** 15 | * Marker interface for service route loaders. 16 | */ 17 | interface RouteLoaderInterface 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /Secrets/AbstractVault.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Secrets; 13 | 14 | /** 15 | * @author Nicolas Grekas 16 | */ 17 | abstract class AbstractVault 18 | { 19 | protected ?string $lastMessage = null; 20 | 21 | public function getLastMessage(): ?string 22 | { 23 | return $this->lastMessage; 24 | } 25 | 26 | abstract public function generateKeys(bool $override = false): bool; 27 | 28 | abstract public function seal(string $name, string $value): void; 29 | 30 | abstract public function reveal(string $name): ?string; 31 | 32 | abstract public function remove(string $name): bool; 33 | 34 | abstract public function list(bool $reveal = false): array; 35 | 36 | protected function validateName(string $name): void 37 | { 38 | if (!preg_match('/^\w++$/D', $name)) { 39 | throw new \LogicException(\sprintf('Invalid secret name "%s": only "word" characters are allowed.', $name)); 40 | } 41 | } 42 | 43 | protected function getPrettyPath(string $path): string 44 | { 45 | return str_replace(getcwd().\DIRECTORY_SEPARATOR, '', $path); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Secrets/DotenvVault.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Secrets; 13 | 14 | /** 15 | * @author Nicolas Grekas 16 | */ 17 | class DotenvVault extends AbstractVault 18 | { 19 | public function __construct( 20 | private string $dotenvFile, 21 | ) { 22 | $this->dotenvFile = strtr($dotenvFile, '/', \DIRECTORY_SEPARATOR); 23 | } 24 | 25 | public function generateKeys(bool $override = false): bool 26 | { 27 | $this->lastMessage = 'The dotenv vault doesn\'t encrypt secrets thus doesn\'t need keys.'; 28 | 29 | return false; 30 | } 31 | 32 | public function seal(string $name, string $value): void 33 | { 34 | $this->lastMessage = null; 35 | $this->validateName($name); 36 | $v = str_replace("'", "'\\''", $value); 37 | 38 | $content = is_file($this->dotenvFile) ? file_get_contents($this->dotenvFile) : ''; 39 | $content = preg_replace("/^$name=((\\\\'|'[^']++')++|.*)/m", "$name='$v'", $content, -1, $count); 40 | 41 | if (!$count) { 42 | $content .= "$name='$v'\n"; 43 | } 44 | 45 | file_put_contents($this->dotenvFile, $content); 46 | 47 | $this->lastMessage = \sprintf('Secret "%s" %s in "%s".', $name, $count ? 'added' : 'updated', $this->getPrettyPath($this->dotenvFile)); 48 | } 49 | 50 | public function reveal(string $name): ?string 51 | { 52 | $this->lastMessage = null; 53 | $this->validateName($name); 54 | $v = $_ENV[$name] ?? (str_starts_with($name, 'HTTP_') ? null : ($_SERVER[$name] ?? null)); 55 | 56 | if ('' === ($v ?? '')) { 57 | $this->lastMessage = \sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); 58 | 59 | return null; 60 | } 61 | 62 | return $v; 63 | } 64 | 65 | public function remove(string $name): bool 66 | { 67 | $this->lastMessage = null; 68 | $this->validateName($name); 69 | 70 | $content = is_file($this->dotenvFile) ? file_get_contents($this->dotenvFile) : ''; 71 | $content = preg_replace("/^$name=((\\\\'|'[^']++')++|.*)\n?/m", '', $content, -1, $count); 72 | 73 | if ($count) { 74 | file_put_contents($this->dotenvFile, $content); 75 | $this->lastMessage = \sprintf('Secret "%s" removed from file "%s".', $name, $this->getPrettyPath($this->dotenvFile)); 76 | 77 | return true; 78 | } 79 | 80 | $this->lastMessage = \sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); 81 | 82 | return false; 83 | } 84 | 85 | public function list(bool $reveal = false): array 86 | { 87 | $this->lastMessage = null; 88 | $secrets = []; 89 | 90 | foreach ($_ENV as $k => $v) { 91 | if ('' !== ($v ?? '') && preg_match('/^\w+$/D', $k)) { 92 | $secrets[$k] = $reveal ? $v : null; 93 | } 94 | } 95 | 96 | foreach ($_SERVER as $k => $v) { 97 | if ('' !== ($v ?? '') && preg_match('/^\w+$/D', $k)) { 98 | $secrets[$k] = $reveal ? $v : null; 99 | } 100 | } 101 | 102 | return $secrets; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Test/NotificationAssertionsTrait.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Test; 13 | 14 | use PHPUnit\Framework\Constraint\LogicalNot; 15 | use Symfony\Component\Notifier\Event\MessageEvent; 16 | use Symfony\Component\Notifier\Event\NotificationEvents; 17 | use Symfony\Component\Notifier\Message\MessageInterface; 18 | use Symfony\Component\Notifier\Test\Constraint as NotifierConstraint; 19 | 20 | /** 21 | * @author Smaïne Milianni 22 | */ 23 | trait NotificationAssertionsTrait 24 | { 25 | public static function assertNotificationCount(int $count, ?string $transportName = null, string $message = ''): void 26 | { 27 | self::assertThat(self::getNotificationEvents(), new NotifierConstraint\NotificationCount($count, $transportName), $message); 28 | } 29 | 30 | public static function assertQueuedNotificationCount(int $count, ?string $transportName = null, string $message = ''): void 31 | { 32 | self::assertThat(self::getNotificationEvents(), new NotifierConstraint\NotificationCount($count, $transportName, true), $message); 33 | } 34 | 35 | public static function assertNotificationIsQueued(MessageEvent $event, string $message = ''): void 36 | { 37 | self::assertThat($event, new NotifierConstraint\NotificationIsQueued(), $message); 38 | } 39 | 40 | public static function assertNotificationIsNotQueued(MessageEvent $event, string $message = ''): void 41 | { 42 | self::assertThat($event, new LogicalNot(new NotifierConstraint\NotificationIsQueued()), $message); 43 | } 44 | 45 | public static function assertNotificationSubjectContains(MessageInterface $notification, string $text, string $message = ''): void 46 | { 47 | self::assertThat($notification, new NotifierConstraint\NotificationSubjectContains($text), $message); 48 | } 49 | 50 | public static function assertNotificationSubjectNotContains(MessageInterface $notification, string $text, string $message = ''): void 51 | { 52 | self::assertThat($notification, new LogicalNot(new NotifierConstraint\NotificationSubjectContains($text)), $message); 53 | } 54 | 55 | public static function assertNotificationTransportIsEqual(MessageInterface $notification, ?string $transportName = null, string $message = ''): void 56 | { 57 | self::assertThat($notification, new NotifierConstraint\NotificationTransportIsEqual($transportName), $message); 58 | } 59 | 60 | public static function assertNotificationTransportIsNotEqual(MessageInterface $notification, ?string $transportName = null, string $message = ''): void 61 | { 62 | self::assertThat($notification, new LogicalNot(new NotifierConstraint\NotificationTransportIsEqual($transportName)), $message); 63 | } 64 | 65 | /** 66 | * @return MessageEvent[] 67 | */ 68 | public static function getNotifierEvents(?string $transportName = null): array 69 | { 70 | return self::getNotificationEvents()->getEvents($transportName); 71 | } 72 | 73 | public static function getNotifierEvent(int $index = 0, ?string $transportName = null): ?MessageEvent 74 | { 75 | return self::getNotifierEvents($transportName)[$index] ?? null; 76 | } 77 | 78 | /** 79 | * @return MessageInterface[] 80 | */ 81 | public static function getNotifierMessages(?string $transportName = null): array 82 | { 83 | return self::getNotificationEvents()->getMessages($transportName); 84 | } 85 | 86 | public static function getNotifierMessage(int $index = 0, ?string $transportName = null): ?MessageInterface 87 | { 88 | return self::getNotifierMessages($transportName)[$index] ?? null; 89 | } 90 | 91 | public static function getNotificationEvents(): NotificationEvents 92 | { 93 | $container = static::getContainer(); 94 | if ($container->has('notifier.notification_logger_listener')) { 95 | return $container->get('notifier.notification_logger_listener')->getEvents(); 96 | } 97 | 98 | static::fail('A client must have Notifier enabled to make notifications assertions. Did you forget to require symfony/notifier?'); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Test/TestBrowserToken.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Test; 13 | 14 | use Symfony\Component\Security\Core\Authentication\Token\AbstractToken; 15 | use Symfony\Component\Security\Core\User\UserInterface; 16 | 17 | /** 18 | * A very limited token that is used to login in tests using the KernelBrowser. 19 | * 20 | * @author Wouter de Jong 21 | */ 22 | class TestBrowserToken extends AbstractToken 23 | { 24 | public function __construct( 25 | array $roles = [], 26 | ?UserInterface $user = null, 27 | private string $firewallName = 'main', 28 | ) { 29 | parent::__construct($roles); 30 | 31 | if (null !== $user) { 32 | $this->setUser($user); 33 | } 34 | } 35 | 36 | public function getFirewallName(): string 37 | { 38 | return $this->firewallName; 39 | } 40 | 41 | public function getCredentials(): mixed 42 | { 43 | return null; 44 | } 45 | 46 | public function __serialize(): array 47 | { 48 | return [$this->firewallName, parent::__serialize()]; 49 | } 50 | 51 | public function __unserialize(array $data): void 52 | { 53 | [$this->firewallName, $parentData] = $data; 54 | 55 | parent::__unserialize($parentData); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Test/TestContainer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Test; 13 | 14 | use Psr\Container\ContainerInterface; 15 | use Symfony\Component\DependencyInjection\Container; 16 | use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; 17 | use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; 18 | use Symfony\Component\HttpKernel\KernelInterface; 19 | 20 | /** 21 | * A special container used in tests. This gives access to both public and 22 | * private services. The container will not include private services that have 23 | * been inlined or removed. Private services will be removed when they are not 24 | * used by other services. 25 | * 26 | * @author Nicolas Grekas 27 | * 28 | * @internal 29 | */ 30 | class TestContainer extends Container 31 | { 32 | public function __construct( 33 | private KernelInterface $kernel, 34 | private string $privateServicesLocatorId, 35 | private array $renamedIds = [], 36 | ) { 37 | } 38 | 39 | public function compile(): void 40 | { 41 | $this->getPublicContainer()->compile(); 42 | } 43 | 44 | public function isCompiled(): bool 45 | { 46 | return $this->getPublicContainer()->isCompiled(); 47 | } 48 | 49 | public function getParameterBag(): ParameterBagInterface 50 | { 51 | return $this->getPublicContainer()->getParameterBag(); 52 | } 53 | 54 | public function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null 55 | { 56 | return $this->getPublicContainer()->getParameter($name); 57 | } 58 | 59 | public function hasParameter(string $name): bool 60 | { 61 | return $this->getPublicContainer()->hasParameter($name); 62 | } 63 | 64 | public function setParameter(string $name, mixed $value): void 65 | { 66 | $this->getPublicContainer()->setParameter($name, $value); 67 | } 68 | 69 | public function set(string $id, mixed $service): void 70 | { 71 | $container = $this->getPublicContainer(); 72 | $renamedId = $this->renamedIds[$id] ?? $id; 73 | 74 | try { 75 | $container->set($renamedId, $service); 76 | } catch (InvalidArgumentException $e) { 77 | if (!str_starts_with($e->getMessage(), "The \"$renamedId\" service is private")) { 78 | throw $e; 79 | } 80 | if (isset($container->privates[$renamedId])) { 81 | throw new InvalidArgumentException(\sprintf('The "%s" service is already initialized, you cannot replace it.', $id)); 82 | } 83 | $container->privates[$renamedId] = $service; 84 | } 85 | } 86 | 87 | public function has(string $id): bool 88 | { 89 | return $this->getPublicContainer()->has($id) || $this->getPrivateContainer()->has($id); 90 | } 91 | 92 | public function get(string $id, int $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE): ?object 93 | { 94 | return $this->getPrivateContainer()->has($id) ? $this->getPrivateContainer()->get($id) : $this->getPublicContainer()->get($id, $invalidBehavior); 95 | } 96 | 97 | public function initialized(string $id): bool 98 | { 99 | return $this->getPublicContainer()->initialized($id); 100 | } 101 | 102 | public function reset(): void 103 | { 104 | // ignore the call 105 | } 106 | 107 | public function getServiceIds(): array 108 | { 109 | return $this->getPublicContainer()->getServiceIds(); 110 | } 111 | 112 | public function getRemovedIds(): array 113 | { 114 | return $this->getPublicContainer()->getRemovedIds(); 115 | } 116 | 117 | private function getPublicContainer(): Container 118 | { 119 | return $this->kernel->getContainer() ?? throw new \LogicException('Cannot access the container on a non-booted kernel. Did you forget to boot it?'); 120 | } 121 | 122 | private function getPrivateContainer(): ContainerInterface 123 | { 124 | return $this->getPublicContainer()->get($this->privateServicesLocatorId); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Test/WebTestAssertionsTrait.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Test; 13 | 14 | trait WebTestAssertionsTrait 15 | { 16 | use BrowserKitAssertionsTrait; 17 | use DomCrawlerAssertionsTrait; 18 | use HttpClientAssertionsTrait; 19 | } 20 | -------------------------------------------------------------------------------- /Test/WebTestCase.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Test; 13 | 14 | use Symfony\Bundle\FrameworkBundle\KernelBrowser; 15 | use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; 16 | 17 | /** 18 | * WebTestCase is the base class for functional tests. 19 | * 20 | * @author Fabien Potencier 21 | */ 22 | abstract class WebTestCase extends KernelTestCase 23 | { 24 | use WebTestAssertionsTrait; 25 | 26 | protected function tearDown(): void 27 | { 28 | parent::tearDown(); 29 | self::getClient(null); 30 | } 31 | 32 | /** 33 | * Creates a KernelBrowser. 34 | * 35 | * @param array $options An array of options to pass to the createKernel method 36 | * @param array $server An array of server parameters 37 | */ 38 | protected static function createClient(array $options = [], array $server = []): KernelBrowser 39 | { 40 | if (static::$booted) { 41 | throw new \LogicException(\sprintf('Booting the kernel before calling "%s()" is not supported, the kernel should only be booted once.', __METHOD__)); 42 | } 43 | 44 | $kernel = static::bootKernel($options); 45 | 46 | try { 47 | $client = $kernel->getContainer()->get('test.client'); 48 | } catch (ServiceNotFoundException) { 49 | if (class_exists(KernelBrowser::class)) { 50 | throw new \LogicException('You cannot create the client used in functional tests if the "framework.test" config is not set to true.'); 51 | } 52 | throw new \LogicException('You cannot create the client used in functional tests if the BrowserKit component is not available. Try running "composer require symfony/browser-kit".'); 53 | } 54 | 55 | $client->setServerParameters($server); 56 | 57 | return self::getClient($client); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony/framework-bundle", 3 | "type": "symfony-bundle", 4 | "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", 5 | "keywords": [], 6 | "homepage": "https://symfony.com", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Fabien Potencier", 11 | "email": "fabien@symfony.com" 12 | }, 13 | { 14 | "name": "Symfony Community", 15 | "homepage": "https://symfony.com/contributors" 16 | } 17 | ], 18 | "require": { 19 | "php": ">=8.2", 20 | "composer-runtime-api": ">=2.1", 21 | "ext-xml": "*", 22 | "symfony/cache": "^6.4|^7.0", 23 | "symfony/config": "^7.3", 24 | "symfony/dependency-injection": "^7.2", 25 | "symfony/deprecation-contracts": "^2.5|^3", 26 | "symfony/error-handler": "^7.3", 27 | "symfony/event-dispatcher": "^6.4|^7.0", 28 | "symfony/http-foundation": "^7.3", 29 | "symfony/http-kernel": "^7.2", 30 | "symfony/polyfill-mbstring": "~1.0", 31 | "symfony/filesystem": "^7.1", 32 | "symfony/finder": "^6.4|^7.0", 33 | "symfony/routing": "^6.4|^7.0" 34 | }, 35 | "require-dev": { 36 | "doctrine/persistence": "^1.3|^2|^3", 37 | "dragonmantank/cron-expression": "^3.1", 38 | "seld/jsonlint": "^1.10", 39 | "symfony/asset": "^6.4|^7.0", 40 | "symfony/asset-mapper": "^6.4|^7.0", 41 | "symfony/browser-kit": "^6.4|^7.0", 42 | "symfony/console": "^6.4|^7.0", 43 | "symfony/clock": "^6.4|^7.0", 44 | "symfony/css-selector": "^6.4|^7.0", 45 | "symfony/dom-crawler": "^6.4|^7.0", 46 | "symfony/dotenv": "^6.4|^7.0", 47 | "symfony/polyfill-intl-icu": "~1.0", 48 | "symfony/form": "^6.4|^7.0", 49 | "symfony/expression-language": "^6.4|^7.0", 50 | "symfony/html-sanitizer": "^6.4|^7.0", 51 | "symfony/http-client": "^6.4|^7.0", 52 | "symfony/lock": "^6.4|^7.0", 53 | "symfony/mailer": "^6.4|^7.0", 54 | "symfony/messenger": "^6.4|^7.0", 55 | "symfony/mime": "^6.4|^7.0", 56 | "symfony/notifier": "^6.4|^7.0", 57 | "symfony/object-mapper": "^v7.3.0-beta2", 58 | "symfony/process": "^6.4|^7.0", 59 | "symfony/rate-limiter": "^6.4|^7.0", 60 | "symfony/scheduler": "^6.4.4|^7.0.4", 61 | "symfony/security-bundle": "^6.4|^7.0", 62 | "symfony/semaphore": "^6.4|^7.0", 63 | "symfony/serializer": "^7.2.5", 64 | "symfony/stopwatch": "^6.4|^7.0", 65 | "symfony/string": "^6.4|^7.0", 66 | "symfony/translation": "^7.3", 67 | "symfony/twig-bundle": "^6.4|^7.0", 68 | "symfony/type-info": "^7.1", 69 | "symfony/validator": "^6.4|^7.0", 70 | "symfony/workflow": "^7.3", 71 | "symfony/yaml": "^6.4|^7.0", 72 | "symfony/property-info": "^6.4|^7.0", 73 | "symfony/json-streamer": "7.3.*", 74 | "symfony/uid": "^6.4|^7.0", 75 | "symfony/web-link": "^6.4|^7.0", 76 | "symfony/webhook": "^7.2", 77 | "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", 78 | "twig/twig": "^3.12" 79 | }, 80 | "conflict": { 81 | "doctrine/persistence": "<1.3", 82 | "phpdocumentor/reflection-docblock": "<3.2.2", 83 | "phpdocumentor/type-resolver": "<1.4.0", 84 | "symfony/asset": "<6.4", 85 | "symfony/asset-mapper": "<6.4", 86 | "symfony/clock": "<6.4", 87 | "symfony/console": "<6.4", 88 | "symfony/dotenv": "<6.4", 89 | "symfony/dom-crawler": "<6.4", 90 | "symfony/http-client": "<6.4", 91 | "symfony/form": "<6.4", 92 | "symfony/json-streamer": ">=7.4", 93 | "symfony/lock": "<6.4", 94 | "symfony/mailer": "<6.4", 95 | "symfony/messenger": "<6.4", 96 | "symfony/mime": "<6.4", 97 | "symfony/object-mapper": ">=7.4", 98 | "symfony/property-info": "<6.4", 99 | "symfony/property-access": "<6.4", 100 | "symfony/runtime": "<6.4.13|>=7.0,<7.1.6", 101 | "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", 102 | "symfony/security-csrf": "<7.2", 103 | "symfony/security-core": "<6.4", 104 | "symfony/serializer": "<7.2.5", 105 | "symfony/stopwatch": "<6.4", 106 | "symfony/translation": "<7.3", 107 | "symfony/twig-bridge": "<6.4", 108 | "symfony/twig-bundle": "<6.4", 109 | "symfony/validator": "<6.4", 110 | "symfony/web-profiler-bundle": "<6.4", 111 | "symfony/webhook": "<7.2", 112 | "symfony/workflow": "<7.3.0-beta2" 113 | }, 114 | "autoload": { 115 | "psr-4": { "Symfony\\Bundle\\FrameworkBundle\\": "" }, 116 | "exclude-from-classmap": [ 117 | "/Tests/" 118 | ] 119 | }, 120 | "minimum-stability": "dev" 121 | } 122 | --------------------------------------------------------------------------------