8000 [DependencyInjection] Add ContainerBuilder::willBeAvailable() to help… · symfony/symfony@183d14e · GitHub
[go: up one dir, main page]

Skip to content

Commit 183d14e

Browse files
[DependencyInjection] Add ContainerBuilder::willBeAvailable() to help with conditional configuration
1 parent 22c2f1a commit 183d14e

File tree

12 files changed

+179
-120
lines changed

12 files changed

+179
-120
lines changed

src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
1515
use Symfony\Component\Config\Definition\ConfigurationInterface;
16-
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
1716

1817
/**
1918
* DebugExtension configuration structure.
@@ -51,21 +50,13 @@ public function getConfigTreeBuilder()
5150
->example('php://stderr, or tcp://%env(VAR_DUMPER_SERVER)% when using the "server:dump" command')
5251
->defaultNull()
5352
->end()
54-
->end()
55-
;
56-
57-
if (method_exists(HtmlDumper::class, 'setTheme')) {
58-
$rootNode
59-
->children()
60-
->enumNode('theme')
61-
->info('Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light"')
62-
->example('dark')
63-
->values(['dark', 'light'])
64-
->defaultValue('dark')
65-
->end()
53+
->enumNode('theme')
54+
->info('Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light"')
55+
->example('dark')
56+
->values(['dark', 'light'])
57+
->defaultValue('dark')
6658
->end()
6759
;
68-
}
6960

7061
return $treeBuilder;
7162
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 67 additions & 53 deletions
Large diffs are not rendered by default.

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 52 additions & 35 deletions
Large diffs are not rendered by default.

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ protected static function getBundleDefaultConfig()
443443
'mapping' => ['paths' => []],
444444
],
445445
'property_access' => [
446+
'enabled' => true,
446447
'magic_call' => false,
447448
'magic_get' => true,
448449
'magic_set' => true,

src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Bundle\SecurityBundle\DependencyInjection;
1313

14+
use Symfony\Bridge\Twig\Extension\LogoutUrlExtension;
1415
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AuthenticatorFactoryInterface;
1516
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FirewallListenerFactoryInterface;
1617
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\RememberMeFactory;
@@ -31,6 +32,7 @@
3132
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
3233
use Symfony\Component\DependencyInjection\Reference;
3334
use Symfony\Component\EventDispatcher\EventDispatcher;
35+
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
3436
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
3537
use Symfony\Component\PasswordHasher\Hasher\NativePasswordHasher;
3638
use Symfony\Component\PasswordHasher\Hasher\Pbkdf2PasswordHasher;
@@ -42,7 +44,6 @@
4244
use Symfony\Component\Security\Core\User\ChainUserProvider;
4345
use Symfony\Component\Security\Core\User\UserProviderInterface;
4446
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
45-
use Twig\Extension\AbstractExtension;
4647

4748
/**
4849
* SecurityExtension.
@@ -130,7 +131,7 @@ public function load(array $configs, ContainerBuilder $container)
130131
$loader->load('security_legacy.php');
131132
}
132133

133-
if (class_exists(AbstractExtension::class)) {
134+
if ($container::willBeAvailable('symfony/twig-bridge', LogoutUrlExtension::class, ['symfony/security-bundle'])) {
134135
$loader->load('templating_twig.php');
135136
}
136137

@@ -141,7 +142,7 @@ public function load(array $configs, ContainerBuilder $container)
141142
$loader->load('security_debug.php');
142143
}
143144

144-
if (!class_exists(\Symfony\Component\ExpressionLanguage\ExpressionLanguage::class)) {
145+
if (!$container::willBeAvailable('symfony/expression-language', ExpressionLanguage::class, ['symfony/security-bundle'])) {
145146
$container->removeDefinition('security.expression_language');
146147
$container->removeDefinition('security.access.expression_voter');
147148
}
@@ -969,8 +970,8 @@ private function createExpression(ContainerBuilder $container, string $expressio
969970
return $this->expressions[$id];
970971
}
971972

972-
if (!class_exists(\Symfony\Component\ExpressionLanguage\ExpressionLanguage::class)) {
973-
throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
973+
if (!$container::willBeAvailable('symfony/expression-language', ExpressionLanguage::class, ['symfony/security-bundle'])) {
974+
throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
974975
}
975976

976977
$container

src/Symfony/Bundle/SecurityBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"php": ">=7.2.5",
2020
"ext-xml": "*",
2121
"symfony/config": "^4.4|^5.0",
22-
"symfony/dependency-injection": "^5.2",
22+
"symfony/dependency-injection": "^5.3",
2323
"symfony/deprecation-contracts": "^2.1",
2424
"symfony/event-dispatcher": "^5.1",
2525
"symfony/http-kernel": "^5.0",

src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,14 @@
1111

1212
namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler;
1313

14+
use Symfony\Component\Asset\Packages;
1415
use Symfony\Component\DependencyInjection\Alias;
1516
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1617
use Symfony\Component\DependencyInjection\ContainerBuilder;
18+
use Symfony\Component\ExpressionLanguage\Expression;
19+
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
1720
use Symfony\Component\Workflow\Workflow;
21+
use Symfony\Component\Yaml\Yaml;
1822

1923
/**
2024
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
@@ -23,19 +27,19 @@ class ExtensionPass implements CompilerPassInterface
2327
{
2428
public function process(ContainerBuilder $container)
2529
{
26-
if (!class_exists(\Symfony\Component\Asset\Packages::class)) {
30+
if (!$container::willBeAvailable('symfony/asset', Packages::class, ['symfony/twig-bundle'])) {
2731
$container->removeDefinition('twig.extension.assets');
2832
}
2933

30-
if (!class_exists(\Symfony\Component\ExpressionLanguage\Expression::class)) {
34+
if (!$container::willBeAvailable('symfony/expression-language', Expression::class, ['symfony/twig-bundle'])) {
3135
$container->removeDefinition('twig.extension.expression');
3236
}
3337

34-
if (!interface_exists(\Symfony\Component\Routing\Generator\UrlGeneratorInterface::class)) {
38+
if (!$container::willBeAvailable('symfony/routing', UrlGeneratorInterface::class, ['symfony/twig-bundle'])) {
3539
$container->removeDefinition('twig.extension.routing');
3640
}
3741

38-
if (!class_exists(\Symfony\Component\Yaml\Yaml::class)) {
42+
if (!$container::willBeAvailable('symfony/yaml', Yaml::class, ['symfony/twig-bundle'])) {
3943
$container->removeDefinition('twig.extension.yaml');
4044
}
4145

@@ -111,7 +115,7 @@ public function process(ContainerBuilder $container)
111115
$container->getDefinition('twig.extension.expression')->addTag('twig.extension');
112116
}
113117

114-
if (!class_exists(Workflow::class) || !$container->has('workflow.registry')) {
118+
if (!$container::willBeAvailable('symfony/workflow', Workflow::class, ['symfony/twig-bundle']) || !$container->has('workflow.registry')) {
115119
$container->removeDefinition('workflow.twig_extension');
116120
} else {
117121
$container->getDefinition('workflow.twig_extension')->addTag('twig.extension');

src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\DependencyInjection\ContainerBuilder;
1818
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
1919
use Symfony\Component\DependencyInjection\Reference;
20+
use Symfony\Component\Form\Form;
2021
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
2122
use Symfony\Component\Mailer\Mailer;
2223
use Symfony\Component\Translation\Translator;
@@ -37,19 +38,19 @@ public function load(array $configs, ContainerBuilder $container)
3738
$loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
3839
10000 $loader->load('twig.php');
3940

40-
if (class_exists(\Symfony\Component\Form\Form::class)) {
41+
if ($container::willBeAvailable('symfony/form', Form::class, ['symfony/twig-bundle'])) {
4142
$loader->load('form.php');
4243
}
4344

44-
if (class_exists(Application::class)) {
45+
if ($container::willBeAvailable('symfony/console', Application::class, ['symfony/twig-bundle'])) {
4546
$loader->load('console.php');
4647
}
4748

48-
if (class_exists(Mailer::class)) {
49+
if ($container::willBeAvailable('symfony/mailer', Mailer::class, ['symfony/twig-bundle'])) {
4950
$loader->load('mailer.php');
5051
}
5152

52-
if (!class_exists(Translator::class)) {
53+
if (!$container::willBeAvailable('symfony/translation', Translator::class, ['symfony/twig-bundle'])) {
5354
$container->removeDefinition('twig.translation.extractor');
5455
}
5556

src/Symfony/Bundle/TwigBundle/composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"require-dev": {
2828
"symfony/asset": "^4.4|^5.0",
2929
"symfony/stopwatch": "^4.4|^5.0",
30-
"symfony/dependency-injection": "^5.2",
30+
"symfony/dependency-injection": "^5.3",
3131
"symfony/expression-language": "^4.4|^5.0",
3232
"symfony/finder": "^4.4|^5.0",
3333
"symfony/form": "^4.4|^5.0",
@@ -40,7 +40,7 @@
4040
"doctrine/cache": "~1.0"
4141
},
4242
"conflict": {
43-
"symfony/dependency-injection": "<5.2",
43+
"symfony/dependency-injection": "<5.3",
4444
"symfony/framework-bundle": "<5.0",
4545
"symfony/translation": "<5.0"
4646
},

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ CHANGELOG
88
* Add `%env(not:...)%` processor to negate boolean values
99
* Add support for loading autoconfiguration rules via the `#[Autoconfigure]` and `#[AutoconfigureTag]` attributes on PHP 8
1010
* Add autoconfigurable attributes
11+
* Add `ContainerBuilder::willBeAvailable()` to help with conditional configuration
1112

1213
5.2.0
1314
-----

src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ private function getExpressionLanguage(): ExpressionLanguage
198198
{
199199
if (null === $this->expressionLanguage) {
200200
if (!class_exists(ExpressionLanguage::class)) {
201-
throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
201+
throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
202202
}
203203

204204
$providers = $this->container->getExpressionLanguageProviders();

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\DependencyInjection;
1313

14+
use Composer\InstalledVersions;
1415
use Psr\Container\ContainerInterface as PsrContainerInterface;
1516
use Symfony\Component\Config\Resource\ClassExistenceResource;
1617
use Symfony\Component\Config\Resource\ComposerResource;
@@ -1467,6 +1468,34 @@ public function log(CompilerPassInterface $pass, string $message)
14671468
$this->getCompiler()->log($pass, $this->resolveEnvPlaceholders($message));
14681469
}
14691470

1471+
/**
1472+
* Checks whether a class is available and will remain available in the "no-dev" mode of Composer.
1473+
*
1474+
* When parent packages are provided and if any of them is in dev-only mode,
1475+
* the class will be considered available even if it is also in dev-only mode.
1476+
*/
1477+
final public static function willBeAvailable(string $package, string $class, array $parentPackages): bool
1478+
{
1479+
if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) {
1480+
return false;
1481+
}
1482+
1483+
if (!class_exists(InstalledVersions::class) || !InstalledVersions::isInstalled($package) || InstalledVersions::isInstalled($package, false)) {
1484+
return true;
1485+
}
1486+
1487+
// the package is installed but in dev-mode only, check if this applies to one of the parent packages too
1488+
1489+
$rootPackage = InstalledVersions::getRootPackage()['name'] ?? '';
1490+
foreach ($parentPackages as $parentPackage) {
1491+
if ($rootPackage === $parentPackage || (InstalledVersions::isInstalled($parentPackage) && !InstalledVersions::isInstalled($parentPackage, false))) {
1492+
return true;
1493+
}
1494+
}
1495+
1496+
return false;
1497+
}
1498+
14701499
/**
14711500
* Gets removed binding ids.
14721501
*

0 commit comments

Comments
 (0)
0