[DependencyInjection] Add ContainerBuilder::willBeAvailable() to help with conditional configuration
This commit is contained in:
parent
e872db4a1c
commit
47c471e2c4
@ -13,7 +13,6 @@ namespace Symfony\Bundle\DebugBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
|
||||
|
||||
/**
|
||||
* DebugExtension configuration structure.
|
||||
@ -51,21 +50,13 @@ class Configuration implements ConfigurationInterface
|
||||
->example('php://stderr, or tcp://%env(VAR_DUMPER_SERVER)% when using the "server:dump" command')
|
||||
->defaultNull()
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
|
||||
if (method_exists(HtmlDumper::class, 'setTheme')) {
|
||||
$rootNode
|
||||
->children()
|
||||
->enumNode('theme')
|
||||
->info('Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light"')
|
||||
->example('dark')
|
||||
->values(['dark', 'light'])
|
||||
->defaultValue('dark')
|
||||
->end()
|
||||
->enumNode('theme')
|
||||
->info('Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light"')
|
||||
->example('dark')
|
||||
->values(['dark', 'light'])
|
||||
->defaultValue('dark')
|
||||
->end()
|
||||
;
|
||||
}
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ use Symfony\Component\Config\Definition\Builder\NodeBuilder;
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\HttpClient\HttpClient;
|
||||
@ -30,6 +31,7 @@ use Symfony\Component\Lock\Store\SemaphoreStore;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
use Symfony\Component\Notifier\Notifier;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessor;
|
||||
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
|
||||
use Symfony\Component\RateLimiter\Policy\TokenBucketLimiter;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
@ -108,8 +110,19 @@ class Configuration implements ConfigurationInterface
|
||||
->end()
|
||||
;
|
||||
|
||||
$willBeAvailable = static function (string $package, string $class, string $parentPackage = null) {
|
||||
$parentPackages = (array) $parentPackage;
|
||||
$parentPackages[] = 'symfony/framework-bundle';
|
||||
|
||||
return ContainerBuilder::willBeAvailable($package, $class, $parentPackages);
|
||||
};
|
||||
|
||||
$enableIfStandalone = static function (string $package, string $class) use ($willBeAvailable) {
|
||||
return !class_exists(FullStack::class) && $willBeAvailable($package, $class) ? 'canBeDisabled' : 'canBeEnabled';
|
||||
};
|
||||
|
||||
$this->addCsrfSection($rootNode);
|
||||
$this->addFormSection($rootNode);
|
||||
$this->addFormSection($rootNode, $enableIfStandalone);
|
||||
$this->addHttpCacheSection($rootNode);
|
||||
$this->addEsiSection($rootNode);
|
||||
$this->addSsiSection($rootNode);
|
||||
@ -119,25 +132,25 @@ class Configuration implements ConfigurationInterface
|
||||
$this->addRouterSection($rootNode);
|
||||
$this->addSessionSection($rootNode);
|
||||
$this->addRequestSection($rootNode);
|
||||
$this->addAssetsSection($rootNode);
|
||||
$this->addTranslatorSection($rootNode);
|
||||
$this->addValidationSection($rootNode);
|
||||
$this->addAnnotationsSection($rootNode);
|
||||
$this->addSerializerSection($rootNode);
|
||||
$this->addPropertyAccessSection($rootNode);
|
||||
$this->addPropertyInfoSection($rootNode);
|
||||
$this->addCacheSection($rootNode);
|
||||
$this->addAssetsSection($rootNode, $enableIfStandalone);
|
||||
$this->addTranslatorSection($rootNode, $enableIfStandalone);
|
||||
$this->addValidationSection($rootNode, $enableIfStandalone, $willBeAvailable);
|
||||
$this->addAnnotationsSection($rootNode, $willBeAvailable);
|
||||
$this->addSerializerSection($rootNode, $enableIfStandalone, $willBeAvailable);
|
||||
$this->addPropertyAccessSection($rootNode, $willBeAvailable);
|
||||
$this->addPropertyInfoSection($rootNode, $enableIfStandalone);
|
||||
$this->addCacheSection($rootNode, $willBeAvailable);
|
||||
$this->addPhpErrorsSection($rootNode);
|
||||
$this->addWebLinkSection($rootNode);
|
||||
$this->addLockSection($rootNode);
|
||||
$this->addMessengerSection($rootNode);
|
||||
$this->addWebLinkSection($rootNode, $enableIfStandalone);
|
||||
$this->addLockSection($rootNode, $enableIfStandalone);
|
||||
$this->addMessengerSection($rootNode, $enableIfStandalone);
|
||||
$this->addRobotsIndexSection($rootNode);
|
||||
$this->addHttpClientSection($rootNode);
|
||||
$this->addMailerSection($rootNode);
|
||||
$this->addHttpClientSection($rootNode, $enableIfStandalone);
|
||||
$this->addMailerSection($rootNode, $enableIfStandalone);
|
||||
$this->addSecretsSection($rootNode);
|
||||
$this->addNotifierSection($rootNode);
|
||||
$this->addRateLimiterSection($rootNode);
|
||||
$this->addUidSection($rootNode);
|
||||
$this->addNotifierSection($rootNode, $enableIfStandalone);
|
||||
$this->addRateLimiterSection($rootNode, $enableIfStandalone);
|
||||
$this->addUidSection($rootNode, $enableIfStandalone);
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
@ -176,13 +189,13 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addFormSection(ArrayNodeDefinition $rootNode)
|
||||
private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('form')
|
||||
->info('form configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(Form::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/form', Form::class)}()
|
||||
->children()
|
||||
->arrayNode('csrf_protection')
|
||||
->treatFalseLike(['enabled' => false])
|
||||
@ -675,13 +688,13 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addAssetsSection(ArrayNodeDefinition $rootNode)
|
||||
private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('assets')
|
||||
->info('assets configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(Package::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/asset', Package::class)}()
|
||||
->fixXmlConfig('base_url')
|
||||
->children()
|
||||
->scalarNode('version_strategy')->defaultNull()->end()
|
||||
@ -763,13 +776,13 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addTranslatorSection(ArrayNodeDefinition $rootNode)
|
||||
private function addTranslatorSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('translator')
|
||||
->info('translator configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(Translator::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/translation', Translator::class)}()
|
||||
->fixXmlConfig('fallback')
|
||||
->fixXmlConfig('path')
|
||||
->fixXmlConfig('enabled_locale')
|
||||
@ -816,16 +829,16 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addValidationSection(ArrayNodeDefinition $rootNode)
|
||||
private function addValidationSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone, callable $willBeAvailable)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('validation')
|
||||
->info('validation configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(Validation::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/validator', Validation::class)}()
|
||||
->children()
|
||||
->scalarNode('cache')->end()
|
||||
->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end()
|
||||
->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && $willBeAvailable('doctrine/annotations', Annotation::class, 'symfony/validator') ? 'defaultTrue' : 'defaultFalse'}()->end()
|
||||
->arrayNode('static_method')
|
||||
->defaultValue(['loadValidatorMetadata'])
|
||||
->prototype('scalar')->end()
|
||||
@ -906,15 +919,15 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addAnnotationsSection(ArrayNodeDefinition $rootNode)
|
||||
private function addAnnotationsSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('annotations')
|
||||
->info('annotation configuration')
|
||||
->{class_exists(Annotation::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$willBeAvailable('doctrine/annotations', Annotation::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->children()
|
||||
->scalarNode('cache')->defaultValue(interface_exists(Cache::class) ? 'php_array' : 'none')->end()
|
||||
->scalarNode('cache')->defaultValue($willBeAvailable('doctrine/cache', Cache::class, 'doctrine/annotation') ? 'php_array' : 'none')->end()
|
||||
->scalarNode('file_cache_dir')->defaultValue('%kernel.cache_dir%/annotations')->end()
|
||||
->booleanNode('debug')->defaultValue($this->debug)->end()
|
||||
->end()
|
||||
@ -923,15 +936,15 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addSerializerSection(ArrayNodeDefinition $rootNode)
|
||||
private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone, $willBeAvailable)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('serializer')
|
||||
->info('serializer configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(Serializer::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/serializer', Serializer::class)}()
|
||||
->children()
|
||||
->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end()
|
||||
->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && $willBeAvailable('doctrine/annotations', Annotation::class, 'symfony/serializer') ? 'defaultTrue' : 'defaultFalse'}()->end()
|
||||
->scalarNode('name_converter')->end()
|
||||
->scalarNode('circular_reference_handler')->end()
|
||||
->scalarNode('max_depth_handler')->end()
|
||||
@ -950,13 +963,14 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addPropertyAccessSection(ArrayNodeDefinition $rootNode)
|
||||
private function addPropertyAccessSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('property_access')
|
||||
->addDefaultsIfNotSet()
|
||||
->info('Property access configuration')
|
||||
->{$willBeAvailable('symfony/property-access', PropertyAccessor::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->children()
|
||||
->booleanNode('magic_call')->defaultFalse()->end()
|
||||
->booleanNode('magic_get')->defaultTrue()->end()
|
||||
@ -969,19 +983,19 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addPropertyInfoSection(ArrayNodeDefinition $rootNode)
|
||||
private function addPropertyInfoSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('property_info')
|
||||
->info('Property info configuration')
|
||||
->{!class_exists(FullStack::class) && interface_exists(PropertyInfoExtractorInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/property-info', PropertyInfoExtractorInterface::class)}()
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
}
|
||||
|
||||
private function addCacheSection(ArrayNodeDefinition $rootNode)
|
||||
private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
@ -1008,7 +1022,7 @@ class Configuration implements ConfigurationInterface
|
||||
->scalarNode('default_psr6_provider')->end()
|
||||
->scalarNode('default_redis_provider')->defaultValue('redis://localhost')->end()
|
||||
->scalarNode('default_memcached_provider')->defaultValue('memcached://localhost')->end()
|
||||
->scalarNode('default_pdo_provider')->defaultValue(class_exists(Connection::class) ? 'database_connection' : null)->end()
|
||||
->scalarNode('default_pdo_provider')->defaultValue($willBeAvailable('doctrine/dbal', Connection::class) ? 'database_connection' : null)->end()
|
||||
->arrayNode('pools')
|
||||
->useAttributeAsKey('name')
|
||||
->prototype('array')
|
||||
@ -1117,13 +1131,13 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addLockSection(ArrayNodeDefinition $rootNode)
|
||||
private function addLockSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('lock')
|
||||
->info('Lock configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(Lock::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/lock', Lock::class)}()
|
||||
->beforeNormalization()
|
||||
->ifString()->then(function ($v) { return ['enabled' => true, 'resources' => $v]; })
|
||||
->end()
|
||||
@ -1179,25 +1193,25 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addWebLinkSection(ArrayNodeDefinition $rootNode)
|
||||
private function addWebLinkSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('web_link')
|
||||
->info('web links configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(HttpHeaderSerializer::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/weblink', HttpHeaderSerializer::class)}()
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
}
|
||||
|
||||
private function addMessengerSection(ArrayNodeDefinition $rootNode)
|
||||
private function addMessengerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('messenger')
|
||||
->info('Messenger configuration')
|
||||
->{!class_exists(FullStack::class) && interface_exists(MessageBusInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/messenger', MessageBusInterface::class)}()
|
||||
->fixXmlConfig('transport')
|
||||
->fixXmlConfig('bus', 'buses')
|
||||
->validate()
|
||||
@ -1392,13 +1406,13 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addHttpClientSection(ArrayNodeDefinition $rootNode)
|
||||
private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('http_client')
|
||||
->info('HTTP Client configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(HttpClient::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/http-client', HttpClient::class)}()
|
||||
->fixXmlConfig('scoped_client')
|
||||
->beforeNormalization()
|
||||
->always(function ($config) {
|
||||
@ -1728,13 +1742,13 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addMailerSection(ArrayNodeDefinition $rootNode)
|
||||
private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('mailer')
|
||||
->info('Mailer configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(Mailer::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/mailer', Mailer::class)}()
|
||||
->validate()
|
||||
->ifTrue(function ($v) { return isset($v['dsn']) && \count($v['transports']); })
|
||||
->thenInvalid('"dsn" and "transports" cannot be used together.')
|
||||
@ -1784,13 +1798,13 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addNotifierSection(ArrayNodeDefinition $rootNode)
|
||||
private function addNotifierSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('notifier')
|
||||
->info('Notifier configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(Notifier::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/notifier', Notifier::class)}()
|
||||
->fixXmlConfig('chatter_transport')
|
||||
->children()
|
||||
->arrayNode('chatter_transports')
|
||||
@ -1833,13 +1847,13 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addRateLimiterSection(ArrayNodeDefinition $rootNode)
|
||||
private function addRateLimiterSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('rate_limiter')
|
||||
->info('Rate limiter configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(TokenBucketLimiter::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/rate-limiter', TokenBucketLimiter::class)}()
|
||||
->fixXmlConfig('limiter')
|
||||
->beforeNormalization()
|
||||
->ifTrue(function ($v) { return \is_array($v) && !isset($v['limiters']) && !isset($v['limiter']); })
|
||||
@ -1901,13 +1915,13 @@ class Configuration implements ConfigurationInterface
|
||||
;
|
||||
}
|
||||
|
||||
private function addUidSection(ArrayNodeDefinition $rootNode)
|
||||
private function addUidSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
|
||||
{
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('uid')
|
||||
->info('Uid configuration')
|
||||
->{class_exists(UuidFactory::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->{$enableIfStandalone('symfony/uid', UuidFactory::class)}()
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->enumNode('default_uuid_version')
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection;
|
||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||
use Doctrine\Common\Annotations\Reader;
|
||||
use Http\Client\HttpClient;
|
||||
use phpDocumentor\Reflection\DocBlockFactoryInterface;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use Psr\Container\ContainerInterface as PsrContainerInterface;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface;
|
||||
@ -63,6 +64,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\Form\FormTypeExtensionInterface;
|
||||
use Symfony\Component\Form\FormTypeGuesserInterface;
|
||||
use Symfony\Component\Form\FormTypeInterface;
|
||||
@ -149,6 +151,7 @@ use Symfony\Component\RateLimiter\RateLimiterFactory;
|
||||
use Symfony\Component\RateLimiter\Storage\CacheStorage;
|
||||
use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
|
||||
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Serializer\Encoder\DecoderInterface;
|
||||
@ -167,6 +170,7 @@ use Symfony\Component\Uid\UuidV4;
|
||||
use Symfony\Component\Validator\ConstraintValidatorInterface;
|
||||
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
|
||||
use Symfony\Component\Validator\ObjectInitializerInterface;
|
||||
use Symfony\Component\Validator\Validation;
|
||||
use Symfony\Component\WebLink\HttpHeaderSerializer;
|
||||
use Symfony\Component\Workflow;
|
||||
use Symfony\Component\Workflow\WorkflowInterface;
|
||||
@ -200,6 +204,7 @@ class FrameworkExtension extends Extension
|
||||
private $mailerConfigEnabled = false;
|
||||
private $httpClientConfigEnabled = false;
|
||||
private $notifierConfigEnabled = false;
|
||||
private $propertyAccessConfigEnabled = false;
|
||||
private $lockConfigEnabled = false;
|
||||
|
||||
/**
|
||||
@ -216,7 +221,7 @@ class FrameworkExtension extends Extension
|
||||
$loader->load('fragment_renderer.php');
|
||||
$loader->load('error_renderer.php');
|
||||
|
||||
if (interface_exists(PsrEventDispatcherInterface::class)) {
|
||||
if (ContainerBuilder::willBeAvailable('psr/event-dispatcher', PsrEventDispatcherInterface::class, ['symfony/framework-bundle'])) {
|
||||
$container->setAlias(PsrEventDispatcherInterface::class, 'event_dispatcher');
|
||||
}
|
||||
|
||||
@ -256,11 +261,11 @@ class FrameworkExtension extends Extension
|
||||
}
|
||||
|
||||
// If the slugger is used but the String component is not available, we should throw an error
|
||||
if (!interface_exists(SluggerInterface::class)) {
|
||||
if (!ContainerBuilder::willBeAvailable('symfony/string', SluggerInterface::class, ['symfony/framework-bundle'])) {
|
||||
$container->register('slugger', 'stdClass')
|
||||
->addError('You cannot use the "slugger" service since the String component is not installed. Try running "composer require symfony/string".');
|
||||
} else {
|
||||
if (!interface_exists(LocaleAwareInterface::class)) {
|
||||
if (!ContainerBuilder::willBeAvailable('symfony/translation', LocaleAwareInterface::class, ['symfony/framework-bundle'])) {
|
||||
$container->register('slugger', 'stdClass')
|
||||
->addError('You cannot use the "slugger" service since the Translation contracts are not installed. Try running "composer require symfony/translation".');
|
||||
}
|
||||
@ -329,19 +334,19 @@ class FrameworkExtension extends Extension
|
||||
}
|
||||
|
||||
if (null === $config['csrf_protection']['enabled']) {
|
||||
$config['csrf_protection']['enabled'] = $this->sessionConfigEnabled && !class_exists(FullStack::class) && interface_exists(CsrfTokenManagerInterface::class);
|
||||
$config['csrf_protection']['enabled'] = $this->sessionConfigEnabled && !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/security-csrf', CsrfTokenManagerInterface::class, ['symfony/framework-bundle']);
|
||||
}
|
||||
$this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader);
|
||||
|
||||
if ($this->isConfigEnabled($container, $config['form'])) {
|
||||
if (!class_exists(\Symfony\Component\Form\Form::class)) {
|
||||
if (!class_exists(Form::class)) {
|
||||
throw new LogicException('Form support cannot be enabled as the Form component is not installed. Try running "composer require symfony/form".');
|
||||
}
|
||||
|
||||
$this->formConfigEnabled = true;
|
||||
$this->registerFormConfiguration($config, $container, $loader);
|
||||
|
||||
if (class_exists(\Symfony\Component\Validator\Validation::class)) {
|
||||
if (ContainerBuilder::willBeAvailable('symfony/validator', Validation::class, ['symfony/framework-bundle', 'symfony/form'])) {
|
||||
$config['validation']['enabled'] = true;
|
||||
} else {
|
||||
$container->setParameter('validator.translation_domain', 'validators');
|
||||
@ -469,7 +474,7 @@ class FrameworkExtension extends Extension
|
||||
'Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController',
|
||||
]);
|
||||
|
||||
if (class_exists(MimeTypes::class)) {
|
||||
if (ContainerBuilder::willBeAvailable('symfony/mime', MimeTypes::class, ['symfony/framework-bundle'])) {
|
||||
$loader->load('mime_type.php');
|
||||
}
|
||||
|
||||
@ -602,7 +607,7 @@ class FrameworkExtension extends Extension
|
||||
$container->setParameter('form.type_extension.csrf.enabled', false);
|
||||
}
|
||||
|
||||
if (!class_exists(Translator::class)) {
|
||||
if (!ContainerBuilder::willBeAvailable('symfony/translation', Translator::class, ['symfony/framework-bundle', 'symfony/form'])) {
|
||||
$container->removeDefinition('form.type_extension.upload.validator');
|
||||
}
|
||||
if (!method_exists(CachingFactoryDecorator::class, 'reset')) {
|
||||
@ -986,7 +991,7 @@ class FrameworkExtension extends Extension
|
||||
$container->getDefinition('routing.loader')->replaceArgument(2, ['_locale' => $enabledLocales]);
|
||||
}
|
||||
|
||||
if (!class_exists(ExpressionLanguage::class)) {
|
||||
if (!ContainerBuilder::willBeAvailable('symfony/expression-language', ExpressionLanguage::class, ['symfony/framework-bundle', 'symfony/routing'])) {
|
||||
$container->removeDefinition('router.expression_language_provider');
|
||||
}
|
||||
|
||||
@ -1225,18 +1230,18 @@ class FrameworkExtension extends Extension
|
||||
$dirs = [];
|
||||
$transPaths = [];
|
||||
$nonExistingDirs = [];
|
||||
if (class_exists(\Symfony\Component\Validator\Validation::class)) {
|
||||
$r = new \ReflectionClass(\Symfony\Component\Validator\Validation::class);
|
||||
if (ContainerBuilder::willBeAvailable('symfony/validator', Validation::class, ['symfony/framework-bundle', 'symfony/translation'])) {
|
||||
$r = new \ReflectionClass(Validation::class);
|
||||
|
||||
$dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations';
|
||||
}
|
||||
if (class_exists(\Symfony\Component\Form\Form::class)) {
|
||||
$r = new \ReflectionClass(\Symfony\Component\Form\Form::class);
|
||||
if (ContainerBuilder::willBeAvailable('symfony/form', Form::class, ['symfony/framework-bundle', 'symfony/translation'])) {
|
||||
$r = new \ReflectionClass(Form::class);
|
||||
|
||||
$dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations';
|
||||
}
|
||||
if (class_exists(\Symfony\Component\Security\Core\Exception\AuthenticationException::class)) {
|
||||
$r = new \ReflectionClass(\Symfony\Component\Security\Core\Exception\AuthenticationException::class);
|
||||
if (ContainerBuilder::willBeAvailable('symfony/security-core', AuthenticationException::class, ['symfony/framework-bundle', 'symfony/translation'])) {
|
||||
$r = new \ReflectionClass(AuthenticationException::class);
|
||||
|
||||
$dirs[] = $transPaths[] = \dirname($r->getFileName(), 2).'/Resources/translations';
|
||||
}
|
||||
@ -1336,7 +1341,7 @@ class FrameworkExtension extends Extension
|
||||
return;
|
||||
}
|
||||
|
||||
if (!class_exists(\Symfony\Component\Validator\Validation::class)) {
|
||||
if (!class_exists(Validation::class)) {
|
||||
throw new LogicException('Validation support cannot be enabled as the Validator component is not installed. Try running "composer require symfony/validator".');
|
||||
}
|
||||
|
||||
@ -1403,8 +1408,8 @@ class FrameworkExtension extends Extension
|
||||
$files['yaml' === $extension ? 'yml' : $extension][] = $path;
|
||||
};
|
||||
|
||||
if (interface_exists(\Symfony\Component\Form\FormInterface::class)) {
|
||||
$reflClass = new \ReflectionClass(\Symfony\Component\Form\FormInterface::class);
|
||||
if (ContainerBuilder::willBeAvailable('symfony/form', Form::class, ['symfony/framework-bundle', 'symfony/validator'])) {
|
||||
$reflClass = new \ReflectionClass(Form::class);
|
||||
$fileRecorder('xml', \dirname($reflClass->getFileName()).'/Resources/config/validation.xml');
|
||||
}
|
||||
|
||||
@ -1466,7 +1471,7 @@ class FrameworkExtension extends Extension
|
||||
}
|
||||
|
||||
if (!class_exists(\Doctrine\Common\Annotations\Annotation::class)) {
|
||||
throw new LogicException('Annotations cannot be enabled as the Doctrine Annotation library is not installed.');
|
||||
throw new LogicException('Annotations cannot be enabled as the Doctrine Annotation library is not installed. Try running "composer require doctrine/annotations".');
|
||||
}
|
||||
|
||||
$loader->load('annotations.php');
|
||||
@ -1478,7 +1483,7 @@ class FrameworkExtension extends Extension
|
||||
|
||||
if ('none' !== $config['cache']) {
|
||||
if (!class_exists(\Doctrine\Common\Cache\CacheProvider::class)) {
|
||||
throw new LogicException('Annotations cannot be enabled as the Doctrine Cache library is not installed.');
|
||||
throw new LogicException('Annotations cannot be cached as the Doctrine Cache library is not installed. Try running "composer require doctrine/cache".');
|
||||
}
|
||||
|
||||
$cacheService = $config['cache'];
|
||||
@ -1521,7 +1526,7 @@ class FrameworkExtension extends Extension
|
||||
|
||||
private function registerPropertyAccessConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader)
|
||||
{
|
||||
if (!class_exists(PropertyAccessor::class)) {
|
||||
if (!$this->propertyAccessConfigEnabled = $this->isConfigEnabled($container, $config)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1570,7 +1575,7 @@ class FrameworkExtension extends Extension
|
||||
throw new InvalidArgumentException(sprintf('Invalid value "%s" set as "decryption_env_var": only "word" characters are allowed.', $config['decryption_env_var']));
|
||||
}
|
||||
|
||||
if (class_exists(LazyString::class)) {
|
||||
if (ContainerBuilder::willBeAvailable('symfony/string', LazyString::class, ['symfony/framework-bundle'])) {
|
||||
$container->getDefinition('secrets.decryption_key')->replaceArgument(1, $config['decryption_env_var']);
|
||||
} else {
|
||||
$container->getDefinition('secrets.vault')->replaceArgument(1, "%env({$config['decryption_env_var']})%");
|
||||
@ -1610,7 +1615,7 @@ class FrameworkExtension extends Extension
|
||||
|
||||
$chainLoader = $container->getDefinition('serializer.mapping.chain_loader');
|
||||
|
||||
if (!class_exists(PropertyAccessor::class)) {
|
||||
if (!$this->propertyAccessConfigEnabled) {
|
||||
$container->removeAlias('serializer.property_accessor');
|
||||
$container->removeDefinition('serializer.normalizer.object');
|
||||
}
|
||||
@ -1619,7 +1624,7 @@ class FrameworkExtension extends Extension
|
||||
$container->removeDefinition('serializer.encoder.yaml');
|
||||
}
|
||||
|
||||
if (!class_exists(UnwrappingDenormalizer::class) || !class_exists(PropertyAccessor::class)) {
|
||||
if (!class_exists(UnwrappingDenormalizer::class) || !$this->propertyAccessConfigEnabled) {
|
||||
$container->removeDefinition('serializer.denormalizer.unwrapping');
|
||||
}
|
||||
|
||||
@ -1703,7 +1708,7 @@ class FrameworkExtension extends Extension
|
||||
|
||||
$loader->load('property_info.php');
|
||||
|
||||
if (interface_exists(\phpDocumentor\Reflection\DocBlockFactoryInterface::class)) {
|
||||
if (ContainerBuilder::willBeAvailable('phpdocumentor/reflection-docblock', DocBlockFactoryInterface::class, ['symfony/framework-bundle', 'symfony/property-info'])) {
|
||||
$definition = $container->register('property_info.php_doc_extractor', 'Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor');
|
||||
$definition->addTag('property_info.description_extractor', ['priority' => -1000]);
|
||||
$definition->addTag('property_info.type_extractor', ['priority' => -1001]);
|
||||
@ -1784,19 +1789,19 @@ class FrameworkExtension extends Extension
|
||||
|
||||
$loader->load('messenger.php');
|
||||
|
||||
if (class_exists(AmqpTransportFactory::class)) {
|
||||
if (ContainerBuilder::willBeAvailable('symfony/amqp-messenger', AmqpTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'])) {
|
||||
$container->getDefinition('messenger.transport.amqp.factory')->addTag('messenger.transport_factory');
|
||||
}
|
||||
|
||||
if (class_exists(RedisTransportFactory::class)) {
|
||||
if (ContainerBuilder::willBeAvailable('symfony/redis-messenger', RedisTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'])) {
|
||||
$container->getDefinition('messenger.transport.redis.factory')->addTag('messenger.transport_factory');
|
||||
}
|
||||
|
||||
if (class_exists(AmazonSqsTransportFactory::class)) {
|
||||
if (ContainerBuilder::willBeAvailable('symfony/amazon-sqs-messenger', AmazonSqsTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'])) {
|
||||
$container->getDefinition('messenger.transport.sqs.factory')->addTag('messenger.transport_factory');
|
||||
}
|
||||
|
||||
if (class_exists(BeanstalkdTransportFactory::class)) {
|
||||
if (ContainerBuilder::willBeAvailable('symfony/beanstalkd-messenger', BeanstalkdTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'])) {
|
||||
$container->getDefinition('messenger.transport.beanstalkd.factory')->addTag('messenger.transport_factory');
|
||||
}
|
||||
|
||||
@ -2070,12 +2075,12 @@ class FrameworkExtension extends Extension
|
||||
unset($options['retry_failed']);
|
||||
$container->getDefinition('http_client')->setArguments([$options, $config['max_host_connections'] ?? 6]);
|
||||
|
||||
if (!$hasPsr18 = interface_exists(ClientInterface::class)) {
|
||||
if (!$hasPsr18 = ContainerBuilder::willBeAvailable('psr/http-client', ClientInterface::class, ['symfony/framework-bundle', 'symfony/http-client'])) {
|
||||
$container->removeDefinition('psr18.http_client');
|
||||
$container->removeAlias(ClientInterface::class);
|
||||
}
|
||||
|
||||
if (!interface_exists(HttpClient::class)) {
|
||||
if (!ContainerBuilder::willBeAvailable('php-http/httplug', HttpClient::class, ['symfony/framework-bundle', 'symfony/http-client'])) {
|
||||
$container->removeDefinition(HttpClient::class);
|
||||
}
|
||||
|
||||
@ -2205,7 +2210,9 @@ class FrameworkExtension extends Extension
|
||||
];
|
||||
|
||||
foreach ($classToServices as $class => $service) {
|
||||
if (!class_exists($class)) {
|
||||
$package = substr($service, \strlen('mailer.transport_factory.'));
|
||||
|
||||
if (!ContainerBuilder::willBeAvailable(sprintf('symfony/%s-mailer', 'gmail' === $package ? 'google' : $package), $class, ['symfony/framework-bundle', 'symfony/mailer'])) {
|
||||
$container->removeDefinition($service);
|
||||
}
|
||||
}
|
||||
@ -2302,16 +2309,26 @@ class FrameworkExtension extends Extension
|
||||
ClickatellTransportFactory::class => 'notifier.transport_factory.clickatell',
|
||||
];
|
||||
|
||||
$parentPackages = ['symfony/framework-bundle', 'symfony/notifier'];
|
||||
|
||||
foreach ($classToServices as $class => $service) {
|
||||
if (!class_exists($class)) {
|
||||
switch ($package = substr($service, \strlen('notifier.transport_factory.'))) {
|
||||
case 'freemobile': $package = 'free-mobile'; break;
|
||||
case 'googlechat': $package = 'google-chat'; break;
|
||||
case 'linkedin': $package = 'linked-in'; break;
|
||||
case 'ovhcloud': $package = 'ovh-cloud'; break;
|
||||
case 'rocketchat': $package = 'rocket-chat'; break;
|
||||
}
|
||||
|
||||
if (!ContainerBuilder::willBeAvailable(sprintf('symfony/%s-notifier', $package), $class, $parentPackages)) {
|
||||
$container->removeDefinition($service);
|
||||
}
|
||||
}
|
||||
|
||||
if (class_exists(MercureTransportFactory::class) && class_exists(MercureBundle::class)) {
|
||||
if (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, $parentPackages) && ContainerBuilder::willBeAvailable('symfony/mercure-bundle', MercureBundle::class, $parentPackages)) {
|
||||
$container->getDefinition($classToServices[MercureTransportFactory::class])
|
||||
->replaceArgument('$publisherLocator', new ServiceLocatorArgument(new TaggedIteratorArgument('mercure.publisher', null, null, true)));
|
||||
} elseif (class_exists(MercureTransportFactory::class)) {
|
||||
} elseif (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, $parentPackages)) {
|
||||
$container->removeDefinition($classToServices[MercureTransportFactory::class]);
|
||||
}
|
||||
|
||||
|
@ -443,6 +443,7 @@ class ConfigurationTest extends TestCase
|
||||
'mapping' => ['paths' => []],
|
||||
],
|
||||
'property_access' => [
|
||||
'enabled' => true,
|
||||
'magic_call' => false,
|
||||
'magic_get' => true,
|
||||
'magic_set' => true,
|
||||
@ -566,7 +567,7 @@ class ConfigurationTest extends TestCase
|
||||
'limiters' => [],
|
||||
],
|
||||
'uid' => [
|
||||
'enabled' => class_exists(UuidFactory::class),
|
||||
'enabled' => !class_exists(FullStack::class) && class_exists(UuidFactory::class),
|
||||
'default_uuid_version' => 6,
|
||||
'name_based_uuid_version' => 5,
|
||||
'time_based_uuid_version' => 6,
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Bundle\SecurityBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Bridge\Twig\Extension\LogoutUrlExtension;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AuthenticatorFactoryInterface;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FirewallListenerFactoryInterface;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\RememberMeFactory;
|
||||
@ -31,6 +32,7 @@ use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\PasswordHasher\Hasher\NativePasswordHasher;
|
||||
use Symfony\Component\PasswordHasher\Hasher\Pbkdf2PasswordHasher;
|
||||
@ -42,7 +44,6 @@ use Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder;
|
||||
use Symfony\Component\Security\Core\User\ChainUserProvider;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
|
||||
/**
|
||||
* SecurityExtension.
|
||||
@ -130,7 +131,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
||||
$loader->load('security_legacy.php');
|
||||
}
|
||||
|
||||
if (class_exists(AbstractExtension::class)) {
|
||||
if ($container::willBeAvailable('symfony/twig-bridge', LogoutUrlExtension::class, ['symfony/security-bundle'])) {
|
||||
$loader->load('templating_twig.php');
|
||||
}
|
||||
|
||||
@ -141,7 +142,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
||||
$loader->load('security_debug.php');
|
||||
}
|
||||
|
||||
if (!class_exists(\Symfony\Component\ExpressionLanguage\ExpressionLanguage::class)) {
|
||||
if (!$container::willBeAvailable('symfony/expression-language', ExpressionLanguage::class, ['symfony/security-bundle'])) {
|
||||
$container->removeDefinition('security.expression_language');
|
||||
$container->removeDefinition('security.access.expression_voter');
|
||||
}
|
||||
@ -982,8 +983,8 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
||||
return $this->expressions[$id];
|
||||
}
|
||||
|
||||
if (!class_exists(\Symfony\Component\ExpressionLanguage\ExpressionLanguage::class)) {
|
||||
throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
|
||||
if (!$container::willBeAvailable('symfony/expression-language', ExpressionLanguage::class, ['symfony/security-bundle'])) {
|
||||
throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
|
||||
}
|
||||
|
||||
$container
|
||||
|
@ -19,7 +19,7 @@
|
||||
"php": ">=7.2.5",
|
||||
"ext-xml": "*",
|
||||
"symfony/config": "^4.4|^5.0",
|
||||
"symfony/dependency-injection": "^5.2",
|
||||
"symfony/dependency-injection": "^5.3",
|
||||
"symfony/deprecation-contracts": "^2.1",
|
||||
"symfony/event-dispatcher": "^5.1",
|
||||
"symfony/http-kernel": "^5.0",
|
||||
|
@ -11,10 +11,14 @@
|
||||
|
||||
namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\Asset\Packages;
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Workflow\Workflow;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
@ -23,19 +27,19 @@ class ExtensionPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!class_exists(\Symfony\Component\Asset\Packages::class)) {
|
||||
if (!$container::willBeAvailable('symfony/asset', Packages::class, ['symfony/twig-bundle'])) {
|
||||
$container->removeDefinition('twig.extension.assets');
|
||||
}
|
||||
|
||||
if (!class_exists(\Symfony\Component\ExpressionLanguage\Expression::class)) {
|
||||
if (!$container::willBeAvailable('symfony/expression-language', Expression::class, ['symfony/twig-bundle'])) {
|
||||
$container->removeDefinition('twig.extension.expression');
|
||||
}
|
||||
|
||||
if (!interface_exists(\Symfony\Component\Routing\Generator\UrlGeneratorInterface::class)) {
|
||||
if (!$container::willBeAvailable('symfony/routing', UrlGeneratorInterface::class, ['symfony/twig-bundle'])) {
|
||||
$container->removeDefinition('twig.extension.routing');
|
||||
}
|
||||
|
||||
if (!class_exists(\Symfony\Component\Yaml\Yaml::class)) {
|
||||
if (!$container::willBeAvailable('symfony/yaml', Yaml::class, ['symfony/twig-bundle'])) {
|
||||
$container->removeDefinition('twig.extension.yaml');
|
||||
}
|
||||
|
||||
@ -111,7 +115,7 @@ class ExtensionPass implements CompilerPassInterface
|
||||
$container->getDefinition('twig.extension.expression')->addTag('twig.extension');
|
||||
}
|
||||
|
||||
if (!class_exists(Workflow::class) || !$container->has('workflow.registry')) {
|
||||
if (!$container::willBeAvailable('symfony/workflow', Workflow::class, ['symfony/twig-bundle']) || !$container->has('workflow.registry')) {
|
||||
$container->removeDefinition('workflow.twig_extension');
|
||||
} else {
|
||||
$container->getDefinition('workflow.twig_extension')->addTag('twig.extension');
|
||||
|
@ -17,6 +17,7 @@ use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
use Symfony\Component\Translation\Translator;
|
||||
@ -37,19 +38,19 @@ class TwigExtension extends Extension
|
||||
$loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
$loader->load('twig.php');
|
||||
|
||||
if (class_exists(\Symfony\Component\Form\Form::class)) {
|
||||
if ($container::willBeAvailable('symfony/form', Form::class, ['symfony/twig-bundle'])) {
|
||||
$loader->load('form.php');
|
||||
}
|
||||
|
||||
if (class_exists(Application::class)) {
|
||||
if ($container::willBeAvailable('symfony/console', Application::class, ['symfony/twig-bundle'])) {
|
||||
$loader->load('console.php');
|
||||
}
|
||||
|
||||
if (class_exists(Mailer::class)) {
|
||||
if ($container::willBeAvailable('symfony/mailer', Mailer::class, ['symfony/twig-bundle'])) {
|
||||
$loader->load('mailer.php');
|
||||
}
|
||||
|
||||
if (!class_exists(Translator::class)) {
|
||||
if (!$container::willBeAvailable('symfony/translation', Translator::class, ['symfony/twig-bundle'])) {
|
||||
$container->removeDefinition('twig.translation.extractor');
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
"require-dev": {
|
||||
"symfony/asset": "^4.4|^5.0",
|
||||
"symfony/stopwatch": "^4.4|^5.0",
|
||||
"symfony/dependency-injection": "^5.2",
|
||||
"symfony/dependency-injection": "^5.3",
|
||||
"symfony/expression-language": "^4.4|^5.0",
|
||||
"symfony/finder": "^4.4|^5.0",
|
||||
"symfony/form": "^4.4|^5.0",
|
||||
@ -40,7 +40,7 @@
|
||||
"doctrine/cache": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/dependency-injection": "<5.2",
|
||||
"symfony/dependency-injection": "<5.3",
|
||||
"symfony/framework-bundle": "<5.0",
|
||||
"symfony/translation": "<5.0"
|
||||
},
|
||||
|
@ -9,6 +9,7 @@ CHANGELOG
|
||||
* Add support for loading autoconfiguration rules via the `#[Autoconfigure]` and `#[AutoconfigureTag]` attributes on PHP 8
|
||||
* Add autoconfigurable attributes
|
||||
* Add support for per-env configuration in loaders
|
||||
* Add `ContainerBuilder::willBeAvailable()` to help with conditional configuration
|
||||
|
||||
5.2.0
|
||||
-----
|
||||
|
@ -198,7 +198,7 @@ abstract class AbstractRecursivePass implements CompilerPassInterface
|
||||
{
|
||||
if (null === $this->expressionLanguage) {
|
||||
if (!class_exists(ExpressionLanguage::class)) {
|
||||
throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
|
||||
throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
|
||||
}
|
||||
|
||||
$providers = $this->container->getExpressionLanguageProviders();
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\DependencyInjection;
|
||||
|
||||
use Composer\InstalledVersions;
|
||||
use Psr\Container\ContainerInterface as PsrContainerInterface;
|
||||
use Symfony\Component\Config\Resource\ClassExistenceResource;
|
||||
use Symfony\Component\Config\Resource\ComposerResource;
|
||||
@ -1467,6 +1468,34 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
$this->getCompiler()->log($pass, $this->resolveEnvPlaceholders($message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a class is available and will remain available in the "no-dev" mode of Composer.
|
||||
*
|
||||
* When parent packages are provided and if any of them is in dev-only mode,
|
||||
* the class will be considered available even if it is also in dev-only mode.
|
||||
*/
|
||||
final public static function willBeAvailable(string $package, string $class, array $parentPackages): bool
|
||||
{
|
||||
if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!class_exists(InstalledVersions::class) || !InstalledVersions::isInstalled($package) || InstalledVersions::isInstalled($package, false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// the package is installed but in dev-mode only, check if this applies to one of the parent packages too
|
||||
|
||||
$rootPackage = InstalledVersions::getRootPackage()['name'] ?? '';
|
||||
foreach ($parentPackages as $parentPackage) {
|
||||
if ($rootPackage === $parentPackage || (InstalledVersions::isInstalled($parentPackage) && !InstalledVersions::isInstalled($parentPackage, false))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets removed binding ids.
|
||||
*
|
||||
|
Reference in New Issue
Block a user