registerForAutoconfiguration(SingletonInterface::class)->addTag('typo3.singleton'); $containerBuilder->registerForAutoconfiguration(LoggerAwareInterface::class)->addTag('psr.logger_aware'); $containerBuilder->registerForAutoconfiguration(FileSystemPublisherInterface::class)->addTag('asset.filesystem_publisher'); // Services, to be read from container-aware dispatchers (on demand), therefore marked 'public' $containerBuilder->registerForAutoconfiguration(MiddlewareInterface::class)->addTag('typo3.middleware'); $containerBuilder->registerForAutoconfiguration(RequestHandlerInterface::class)->addTag('typo3.request_handler'); // Icon providers are resolved via the container by IconFactory (on demand), therefore marked 'public' $containerBuilder->registerForAutoconfiguration(IconProviderInterface::class)->addTag('icon.provider'); $containerBuilder->registerAttributeForAutoconfiguration( AsEventListener::class, static function (ChildDefinition $definition, AsEventListener $attribute, \Reflector $reflector): void { $definition->addTag( AsEventListener::TAG_NAME, [ 'identifier' => $attribute->identifier, 'event' => $attribute->event, 'method' => $attribute->method ?? ($reflector instanceof \ReflectionMethod ? $reflector->getName() : null), 'before' => $attribute->before, 'after' => $attribute->after, ] ); } ); $containerBuilder->registerAttributeForAutoconfiguration( AsMessageHandler::class, static function (ChildDefinition $definition, AsMessageHandler $attribute, \Reflector $reflector): void { $definition->addTag( 'messenger.message_handler', [ 'bus' => $attribute->bus, 'fromTransport' => $attribute->fromTransport, 'handles' => $attribute->handles, 'method' => $attribute->method ?? ($reflector instanceof \ReflectionMethod ? $reflector->getName() : null), 'priority' => $attribute->priority, ] ); } ); $containerBuilder->registerAttributeForAutoconfiguration( AsCommand::class, static function (ChildDefinition $definition, AsCommand $attribute): void { $commands = explode('|', $attribute->name); $hidden = false; $name = array_shift($commands); if ($name === '') { // Symfony AsCommand attribute encodes hidden flag as an empty command name $hidden = true; $name = array_shift($commands); } if ($name === null) { // This happens in case no name and no aliases are given // @todo Throw exception return; } $definition->addTag( 'console.command', [ 'command' => $name, 'description' => $attribute->description, 'hidden' => $hidden, // The `schedulable` flag is not configurable via symfony attribute parameters, use sane defaults. // It can be overridden by using the Attribute #[AsNonSchedulableCommand] on a class. 'schedulable' => true, ] ); foreach ($commands as $name) { $definition->addTag( 'console.command', [ 'command' => $name, 'hidden' => $hidden, 'alias' => true, ] ); } } ); // notice: static method references cannot be analyzed this way, those are // resolved during runtime in `AllowedCallableAssertion` using reflection $containerBuilder->registerAttributeForAutoconfiguration( AsAllowedCallable::class, static function (ChildDefinition $definition, AsAllowedCallable $attribute, \Reflector $reflector): void { // @todo user functions are `'ClassName->methodName'`, class-based `__invoke()` is not supported yet if (!$reflector instanceof \ReflectionMethod) { return; } $definition->addTag(AsAllowedCallable::TAG_NAME, [ 'method' => $reflector->getName(), ]); } ); $containerBuilder->registerAttributeForAutoconfiguration( UpgradeWizard::class, static function (ChildDefinition $definition, UpgradeWizard $attribute): void { $definition->addTag(UpgradeWizard::TAG_NAME, ['identifier' => $attribute->identifier]); }, ); $containerBuilder->registerAttributeForAutoconfiguration( AsFileRenderer::class, static function (ChildDefinition $definition, AsFileRenderer $attribute): void { $definition->addTag(AsFileRenderer::TAG_NAME, ['priority' => $attribute->priority]); }, ); $containerBuilder->registerAttributeForAutoconfiguration( AsModuleAccessGate::class, static function (ChildDefinition $definition, AsModuleAccessGate $attribute): void { $definition->addTag(AsModuleAccessGate::TAG_NAME, [ 'identifier' => $attribute->identifier, 'before' => implode(',', $attribute->before), 'after' => implode(',', $attribute->after), ]); }, ); $containerBuilder->addCompilerPass(new DependencyInjection\SingletonPass('typo3.singleton')); $containerBuilder->addCompilerPass(new DependencyInjection\LoggerAwarePass('psr.logger_aware')); $containerBuilder->addCompilerPass(new DependencyInjection\LoggerInterfacePass()); $containerBuilder->addCompilerPass(new DependencyInjection\MfaProviderPass('mfa.provider')); $containerBuilder->addCompilerPass(new DependencyInjection\FileRendererPass(AsFileRenderer::TAG_NAME)); $containerBuilder->addCompilerPass(new DependencyInjection\SoftReferenceParserPass('softreference.parser')); $containerBuilder->addCompilerPass(new DependencyInjection\ListenerProviderPass('event.listener')); $containerBuilder->addCompilerPass(new DependencyInjection\PublicServicePass('typo3.middleware')); $containerBuilder->addCompilerPass(new DependencyInjection\PublicServicePass('typo3.request_handler')); $containerBuilder->addCompilerPass(new DependencyInjection\PublicServicePass('icon.provider')); $containerBuilder->addCompilerPass(new DependencyInjection\ConsoleCommandPass('console.command')); $containerBuilder->addCompilerPass(new DependencyInjection\MessageHandlerPass('messenger.message_handler')); $containerBuilder->addCompilerPass(new DependencyInjection\MessengerMiddlewarePass('messenger.middleware')); $containerBuilder->addCompilerPass(new DependencyInjection\AssetFileSystemPublisherPass('asset.filesystem_publisher')); $containerBuilder->addCompilerPass(new DependencyInjection\AllowedCallablePass(AsAllowedCallable::TAG_NAME)); $containerBuilder->addCompilerPass(new DependencyInjection\AutowireInjectMethodsPass()); };