psr/container >= 1.1 breaks Symfony on PHP 7.3

Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
This commit is contained in:
Arthur Schiwon 2022-03-09 20:36:22 +01:00
parent 9d28b8db4e
commit 8e91cf211f
No known key found for this signature in database
GPG key ID: 7424F1874854DF23
111 changed files with 771 additions and 2143 deletions

2
.gitignore vendored
View file

@ -9,3 +9,5 @@
build
/vendor/
.php_cs.cache
!/tests/integration/

View file

@ -1,6 +1,12 @@
{
"require": {
"php": ">=7.3"
},
"require-dev": {
"behat/behat": "^3.3",
"guzzlehttp/guzzle": "^7.0"
},
"conflict": {
"psr/container": ">=1.1"
}
}

View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "342c9ad15194753594ee6d6b8e1bb2fc",
"content-hash": "9ff9f72d6a7cf43bebb439d1db2825a4",
"packages": [],
"packages-dev": [
{
@ -531,22 +531,27 @@
},
{
"name": "psr/container",
"version": "1.1.2",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
@ -559,7 +564,7 @@
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
@ -573,9 +578,9 @@
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.2"
"source": "https://github.com/php-fig/container/tree/master"
},
"time": "2021-11-05T16:50:12+00:00"
"time": "2017-02-14T16:28:37+00:00"
},
{
"name": "psr/event-dispatcher",
@ -1011,41 +1016,39 @@
},
{
"name": "symfony/dependency-injection",
"version": "v5.4.5",
"version": "v5.2.12",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
"reference": "17f31bc13ef2b577d3c652d71af49d000cbd5894"
"reference": "2f0326ab0e142a3600b1b435cb3e852bc96264b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/17f31bc13ef2b577d3c652d71af49d000cbd5894",
"reference": "17f31bc13ef2b577d3c652d71af49d000cbd5894",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/2f0326ab0e142a3600b1b435cb3e852bc96264b6",
"reference": "2f0326ab0e142a3600b1b435cb3e852bc96264b6",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1.1",
"symfony/deprecation-contracts": "^2.1|^3",
"psr/container": "^1.0",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-php80": "^1.16",
"symfony/polyfill-php81": "^1.22",
"symfony/service-contracts": "^1.1.6|^2"
},
"conflict": {
"ext-psr": "<1.1|>=2",
"symfony/config": "<5.3",
"symfony/config": "<5.1",
"symfony/finder": "<4.4",
"symfony/proxy-manager-bridge": "<4.4",
"symfony/yaml": "<4.4.26"
"symfony/yaml": "<4.4"
},
"provide": {
"psr/container-implementation": "1.0",
"symfony/service-implementation": "1.0|2.0"
},
"require-dev": {
"symfony/config": "^5.3|^6.0",
"symfony/expression-language": "^4.4|^5.0|^6.0",
"symfony/yaml": "^4.4.26|^5.0|^6.0"
"symfony/config": "^5.1",
"symfony/expression-language": "^4.4|^5.0",
"symfony/yaml": "^4.4|^5.0"
},
"suggest": {
"symfony/config": "",
@ -1080,7 +1083,7 @@
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/dependency-injection/tree/v5.4.5"
"source": "https://github.com/symfony/dependency-injection/tree/v5.2.12"
},
"funding": [
{
@ -1096,7 +1099,7 @@
"type": "tidelift"
}
],
"time": "2022-02-24T09:30:07+00:00"
"time": "2021-07-23T15:54:19+00:00"
},
{
"name": "symfony/deprecation-contracts",
@ -1331,16 +1334,16 @@
},
{
"name": "symfony/filesystem",
"version": "v5.4.5",
"version": "v5.4.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "797680071ea8f71b94eb958680c50d0e002638f5"
"reference": "d53a45039974952af7f7ebc461ccdd4295e29440"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/797680071ea8f71b94eb958680c50d0e002638f5",
"reference": "797680071ea8f71b94eb958680c50d0e002638f5",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/d53a45039974952af7f7ebc461ccdd4295e29440",
"reference": "d53a45039974952af7f7ebc461ccdd4295e29440",
"shasum": ""
},
"require": {
@ -1375,7 +1378,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v5.4.5"
"source": "https://github.com/symfony/filesystem/tree/v5.4.6"
},
"funding": [
{
@ -1391,11 +1394,11 @@
"type": "tidelift"
}
],
"time": "2022-02-27T10:31:47+00:00"
"time": "2022-03-02T12:42:23+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.24.0",
"version": "v1.25.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@ -1457,7 +1460,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
},
"funding": [
{
@ -1477,7 +1480,7 @@
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.24.0",
"version": "v1.25.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
@ -1538,7 +1541,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0"
},
"funding": [
{
@ -1558,7 +1561,7 @@
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.24.0",
"version": "v1.25.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
@ -1622,7 +1625,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
},
"funding": [
{
@ -1642,7 +1645,7 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.24.0",
"version": "v1.25.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
@ -1705,7 +1708,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
},
"funding": [
{
@ -1725,7 +1728,7 @@
},
{
"name": "symfony/polyfill-php73",
"version": "v1.24.0",
"version": "v1.25.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
@ -1784,7 +1787,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php73/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0"
},
"funding": [
{
@ -1804,16 +1807,16 @@
},
{
"name": "symfony/polyfill-php80",
"version": "v1.24.0",
"version": "v1.25.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "57b712b08eddb97c762a8caa32c84e037892d2e9"
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9",
"reference": "57b712b08eddb97c762a8caa32c84e037892d2e9",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"shasum": ""
},
"require": {
@ -1867,7 +1870,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
},
"funding": [
{
@ -1883,11 +1886,11 @@
"type": "tidelift"
}
],
"time": "2021-09-13T13:58:33+00:00"
"time": "2022-03-04T08:16:47+00:00"
},
{
"name": "symfony/polyfill-php81",
"version": "v1.24.0",
"version": "v1.25.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
@ -1946,7 +1949,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0"
},
"funding": [
{
@ -1966,25 +1969,21 @@
},
{
"name": "symfony/service-contracts",
"version": "v2.5.0",
"version": "v2.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc"
"reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1",
"reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1",
"symfony/deprecation-contracts": "^2.1"
},
"conflict": {
"ext-psr": "<1.1|>=2"
"psr/container": "^1.0"
},
"suggest": {
"symfony/service-implementation": ""
@ -1992,7 +1991,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
"dev-master": "2.2-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -2029,7 +2028,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.5.0"
"source": "https://github.com/symfony/service-contracts/tree/master"
},
"funding": [
{
@ -2045,7 +2044,7 @@
"type": "tidelift"
}
],
"time": "2021-11-04T16:48:04+00:00"
"time": "2020-09-07T11:33:47+00:00"
},
{
"name": "symfony/string",
@ -2135,16 +2134,16 @@
},
{
"name": "symfony/translation",
"version": "v5.4.5",
"version": "v5.4.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "7e4d52d39e5d86f3f04bef46fa29a1091786bc73"
"reference": "a7ca9fdfffb0174209440c2ffa1dee228e15d95b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/7e4d52d39e5d86f3f04bef46fa29a1091786bc73",
"reference": "7e4d52d39e5d86f3f04bef46fa29a1091786bc73",
"url": "https://api.github.com/repos/symfony/translation/zipball/a7ca9fdfffb0174209440c2ffa1dee228e15d95b",
"reference": "a7ca9fdfffb0174209440c2ffa1dee228e15d95b",
"shasum": ""
},
"require": {
@ -2212,7 +2211,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v5.4.5"
"source": "https://github.com/symfony/translation/tree/v5.4.6"
},
"funding": [
{
@ -2228,7 +2227,7 @@
"type": "tidelift"
}
],
"time": "2022-02-09T15:49:12+00:00"
"time": "2022-03-02T12:56:28+00:00"
},
{
"name": "symfony/translation-contracts",
@ -2389,7 +2388,9 @@
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform": {
"php": ">=7.3"
},
"platform-dev": [],
"plugin-api-version": "2.2.0"
}

View file

@ -10,6 +10,7 @@ return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'ReturnTypeWillChange' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php',
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',

View file

@ -6,8 +6,8 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',

View file

@ -22,6 +22,8 @@ class ComposerAutoloaderInit2b078a63e93bc9e9825cefae96ca1eb3
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit2b078a63e93bc9e9825cefae96ca1eb3', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit2b078a63e93bc9e9825cefae96ca1eb3', 'loadClassLoader'));

View file

@ -7,8 +7,8 @@ namespace Composer\Autoload;
class ComposerStaticInit2b078a63e93bc9e9825cefae96ca1eb3
{
public static $files = array (
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
@ -206,6 +206,7 @@ class ComposerStaticInit2b078a63e93bc9e9825cefae96ca1eb3
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'ReturnTypeWillChange' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php',
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',

View file

@ -538,24 +538,29 @@
},
{
"name": "psr/container",
"version": "1.1.2",
"version_normalized": "1.1.2.0",
"version": "1.0.0",
"version_normalized": "1.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
"php": ">=5.3.0"
},
"time": "2021-11-05T16:50:12+00:00",
"time": "2017-02-14T16:28:37+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
@ -569,7 +574,7 @@
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
@ -583,7 +588,7 @@
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.2"
"source": "https://github.com/php-fig/container/tree/master"
},
"install-path": "../psr/container"
},
@ -1028,42 +1033,40 @@
},
{
"name": "symfony/dependency-injection",
"version": "v5.4.5",
"version_normalized": "5.4.5.0",
"version": "v5.2.12",
"version_normalized": "5.2.12.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
"reference": "17f31bc13ef2b577d3c652d71af49d000cbd5894"
"reference": "2f0326ab0e142a3600b1b435cb3e852bc96264b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/17f31bc13ef2b577d3c652d71af49d000cbd5894",
"reference": "17f31bc13ef2b577d3c652d71af49d000cbd5894",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/2f0326ab0e142a3600b1b435cb3e852bc96264b6",
"reference": "2f0326ab0e142a3600b1b435cb3e852bc96264b6",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1.1",
"symfony/deprecation-contracts": "^2.1|^3",
"psr/container": "^1.0",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-php80": "^1.16",
"symfony/polyfill-php81": "^1.22",
"symfony/service-contracts": "^1.1.6|^2"
},
"conflict": {
"ext-psr": "<1.1|>=2",
"symfony/config": "<5.3",
"symfony/config": "<5.1",
"symfony/finder": "<4.4",
"symfony/proxy-manager-bridge": "<4.4",
"symfony/yaml": "<4.4.26"
"symfony/yaml": "<4.4"
},
"provide": {
"psr/container-implementation": "1.0",
"symfony/service-implementation": "1.0|2.0"
},
"require-dev": {
"symfony/config": "^5.3|^6.0",
"symfony/expression-language": "^4.4|^5.0|^6.0",
"symfony/yaml": "^4.4.26|^5.0|^6.0"
"symfony/config": "^5.1",
"symfony/expression-language": "^4.4|^5.0",
"symfony/yaml": "^4.4|^5.0"
},
"suggest": {
"symfony/config": "",
@ -1072,7 +1075,7 @@
"symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
"symfony/yaml": ""
},
"time": "2022-02-24T09:30:07+00:00",
"time": "2021-07-23T15:54:19+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1100,7 +1103,7 @@
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/dependency-injection/tree/v5.4.5"
"source": "https://github.com/symfony/dependency-injection/tree/v5.2.12"
},
"funding": [
{
@ -1360,17 +1363,17 @@
},
{
"name": "symfony/filesystem",
"version": "v5.4.5",
"version_normalized": "5.4.5.0",
"version": "v5.4.6",
"version_normalized": "5.4.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "797680071ea8f71b94eb958680c50d0e002638f5"
"reference": "d53a45039974952af7f7ebc461ccdd4295e29440"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/797680071ea8f71b94eb958680c50d0e002638f5",
"reference": "797680071ea8f71b94eb958680c50d0e002638f5",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/d53a45039974952af7f7ebc461ccdd4295e29440",
"reference": "d53a45039974952af7f7ebc461ccdd4295e29440",
"shasum": ""
},
"require": {
@ -1379,7 +1382,7 @@
"symfony/polyfill-mbstring": "~1.8",
"symfony/polyfill-php80": "^1.16"
},
"time": "2022-02-27T10:31:47+00:00",
"time": "2022-03-02T12:42:23+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1407,7 +1410,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v5.4.5"
"source": "https://github.com/symfony/filesystem/tree/v5.4.6"
},
"funding": [
{
@ -1427,8 +1430,8 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.24.0",
"version_normalized": "1.24.0.0",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@ -1492,7 +1495,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
},
"funding": [
{
@ -1512,8 +1515,8 @@
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.24.0",
"version_normalized": "1.24.0.0",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
@ -1576,7 +1579,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0"
},
"funding": [
{
@ -1596,8 +1599,8 @@
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.24.0",
"version_normalized": "1.24.0.0",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
@ -1663,7 +1666,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
},
"funding": [
{
@ -1683,8 +1686,8 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.24.0",
"version_normalized": "1.24.0.0",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
@ -1749,7 +1752,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
},
"funding": [
{
@ -1769,8 +1772,8 @@
},
{
"name": "symfony/polyfill-php73",
"version": "v1.24.0",
"version_normalized": "1.24.0.0",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
@ -1831,7 +1834,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php73/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0"
},
"funding": [
{
@ -1851,23 +1854,23 @@
},
{
"name": "symfony/polyfill-php80",
"version": "v1.24.0",
"version_normalized": "1.24.0.0",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "57b712b08eddb97c762a8caa32c84e037892d2e9"
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9",
"reference": "57b712b08eddb97c762a8caa32c84e037892d2e9",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"time": "2021-09-13T13:58:33+00:00",
"time": "2022-03-04T08:16:47+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -1917,7 +1920,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
},
"funding": [
{
@ -1937,8 +1940,8 @@
},
{
"name": "symfony/polyfill-php81",
"version": "v1.24.0",
"version_normalized": "1.24.0.0",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
@ -1999,7 +2002,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0"
},
"funding": [
{
@ -2019,35 +2022,31 @@
},
{
"name": "symfony/service-contracts",
"version": "v2.5.0",
"version_normalized": "2.5.0.0",
"version": "v2.2.0",
"version_normalized": "2.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc"
"reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1",
"reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1",
"symfony/deprecation-contracts": "^2.1"
},
"conflict": {
"ext-psr": "<1.1|>=2"
"psr/container": "^1.0"
},
"suggest": {
"symfony/service-implementation": ""
},
"time": "2021-11-04T16:48:04+00:00",
"time": "2020-09-07T11:33:47+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
"dev-master": "2.2-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -2085,7 +2084,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.5.0"
"source": "https://github.com/symfony/service-contracts/tree/master"
},
"funding": [
{
@ -2194,17 +2193,17 @@
},
{
"name": "symfony/translation",
"version": "v5.4.5",
"version_normalized": "5.4.5.0",
"version": "v5.4.6",
"version_normalized": "5.4.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "7e4d52d39e5d86f3f04bef46fa29a1091786bc73"
"reference": "a7ca9fdfffb0174209440c2ffa1dee228e15d95b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/7e4d52d39e5d86f3f04bef46fa29a1091786bc73",
"reference": "7e4d52d39e5d86f3f04bef46fa29a1091786bc73",
"url": "https://api.github.com/repos/symfony/translation/zipball/a7ca9fdfffb0174209440c2ffa1dee228e15d95b",
"reference": "a7ca9fdfffb0174209440c2ffa1dee228e15d95b",
"shasum": ""
},
"require": {
@ -2243,7 +2242,7 @@
"symfony/config": "",
"symfony/yaml": ""
},
"time": "2022-02-09T15:49:12+00:00",
"time": "2022-03-02T12:56:28+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -2274,7 +2273,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v5.4.5"
"source": "https://github.com/symfony/translation/tree/v5.4.6"
},
"funding": [
{

View file

@ -5,7 +5,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => 'd3018a7656471a5b0c2d3ad2d01f0fa626d28c7e',
'reference' => 'cbc480eadc87e4f8dcb722ba76e7fe78903b9e60',
'name' => '__root__',
'dev' => true,
),
@ -16,7 +16,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => 'd3018a7656471a5b0c2d3ad2d01f0fa626d28c7e',
'reference' => 'cbc480eadc87e4f8dcb722ba76e7fe78903b9e60',
'dev_requirement' => false,
),
'behat/behat' => array(
@ -74,12 +74,12 @@
'dev_requirement' => true,
),
'psr/container' => array(
'pretty_version' => '1.1.2',
'version' => '1.1.2.0',
'pretty_version' => '1.0.0',
'version' => '1.0.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/container',
'aliases' => array(),
'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
'reference' => 'b7ce3b176482dbbc1245ebf52b181af44c2cf55f',
'dev_requirement' => true,
),
'psr/container-implementation' => array(
@ -182,12 +182,12 @@
'dev_requirement' => true,
),
'symfony/dependency-injection' => array(
'pretty_version' => 'v5.4.5',
'version' => '5.4.5.0',
'pretty_version' => 'v5.2.12',
'version' => '5.2.12.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/dependency-injection',
'aliases' => array(),
'reference' => '17f31bc13ef2b577d3c652d71af49d000cbd5894',
'reference' => '2f0326ab0e142a3600b1b435cb3e852bc96264b6',
'dev_requirement' => true,
),
'symfony/deprecation-contracts' => array(
@ -224,17 +224,17 @@
),
),
'symfony/filesystem' => array(
'pretty_version' => 'v5.4.5',
'version' => '5.4.5.0',
'pretty_version' => 'v5.4.6',
'version' => '5.4.6.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/filesystem',
'aliases' => array(),
'reference' => '797680071ea8f71b94eb958680c50d0e002638f5',
'reference' => 'd53a45039974952af7f7ebc461ccdd4295e29440',
'dev_requirement' => true,
),
'symfony/polyfill-ctype' => array(
'pretty_version' => 'v1.24.0',
'version' => '1.24.0.0',
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
'aliases' => array(),
@ -242,8 +242,8 @@
'dev_requirement' => true,
),
'symfony/polyfill-intl-grapheme' => array(
'pretty_version' => 'v1.24.0',
'version' => '1.24.0.0',
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme',
'aliases' => array(),
@ -251,8 +251,8 @@
'dev_requirement' => true,
),
'symfony/polyfill-intl-normalizer' => array(
'pretty_version' => 'v1.24.0',
'version' => '1.24.0.0',
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
'aliases' => array(),
@ -260,8 +260,8 @@
'dev_requirement' => true,
),
'symfony/polyfill-mbstring' => array(
'pretty_version' => 'v1.24.0',
'version' => '1.24.0.0',
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
@ -269,8 +269,8 @@
'dev_requirement' => true,
),
'symfony/polyfill-php73' => array(
'pretty_version' => 'v1.24.0',
'version' => '1.24.0.0',
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php73',
'aliases' => array(),
@ -278,17 +278,17 @@
'dev_requirement' => true,
),
'symfony/polyfill-php80' => array(
'pretty_version' => 'v1.24.0',
'version' => '1.24.0.0',
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
'aliases' => array(),
'reference' => '57b712b08eddb97c762a8caa32c84e037892d2e9',
'reference' => '4407588e0d3f1f52efb65fbe92babe41f37fe50c',
'dev_requirement' => true,
),
'symfony/polyfill-php81' => array(
'pretty_version' => 'v1.24.0',
'version' => '1.24.0.0',
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php81',
'aliases' => array(),
@ -296,12 +296,12 @@
'dev_requirement' => true,
),
'symfony/service-contracts' => array(
'pretty_version' => 'v2.5.0',
'version' => '2.5.0.0',
'pretty_version' => 'v2.2.0',
'version' => '2.2.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/service-contracts',
'aliases' => array(),
'reference' => '1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc',
'reference' => 'd15da7ba4957ffb8f1747218be9e1a121fd298a1',
'dev_requirement' => true,
),
'symfony/service-implementation' => array(
@ -320,12 +320,12 @@
'dev_requirement' => true,
),
'symfony/translation' => array(
'pretty_version' => 'v5.4.5',
'version' => '5.4.5.0',
'pretty_version' => 'v5.4.6',
'version' => '5.4.6.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/translation',
'aliases' => array(),
'reference' => '7e4d52d39e5d86f3f04bef46fa29a1091786bc73',
'reference' => 'a7ca9fdfffb0174209440c2ffa1dee228e15d95b',
'dev_requirement' => true,
),
'symfony/translation-contracts' => array(

View file

@ -0,0 +1,26 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 70300)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}

View file

@ -1,13 +1,5 @@
Container interface
==============
# PSR Container
This repository holds all interfaces related to [PSR-11 (Container Interface)][psr-url].
Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container.
The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist.
[psr-url]: https://www.php-fig.org/psr/psr-11/
[package-url]: https://packagist.org/packages/psr/container
[implementation-url]: https://packagist.org/providers/psr/container-implementation
This repository holds all interfaces/classes/traits related to [PSR-11](https://github.com/container-interop/fig-standards/blob/master/proposed/container.md).
Note that this is not a container implementation of its own. See the specification for more details.

View file

@ -8,15 +8,20 @@
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
"homepage": "http://www.php-fig.org/"
}
],
"require": {
"php": ">=7.4.0"
"php": ">=5.3.0"
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
}
}

View file

@ -1,12 +1,13 @@
<?php
/**
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
*/
namespace Psr\Container;
use Throwable;
/**
* Base interface representing a generic exception in a container.
*/
interface ContainerExceptionInterface extends Throwable
interface ContainerExceptionInterface
{
}

View file

@ -1,6 +1,7 @@
<?php
declare(strict_types=1);
/**
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
*/
namespace Psr\Container;
@ -19,7 +20,7 @@ interface ContainerInterface
*
* @return mixed Entry.
*/
public function get(string $id);
public function get($id);
/**
* Returns true if the container can return an entry for the given identifier.
@ -32,5 +33,5 @@ interface ContainerInterface
*
* @return bool
*/
public function has(string $id);
public function has($id);
}

View file

@ -1,4 +1,7 @@
<?php
/**
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
*/
namespace Psr\Container;

View file

@ -152,7 +152,7 @@ class Alias
/**
* Returns the Id of this alias.
*
* @return string
* @return string The alias id
*/
public function __toString()
{

View file

@ -31,7 +31,7 @@ trait ReferenceSetArgumentTrait
}
/**
* @return Reference[]
* @return Reference[] The values in the set
*/
public function getValues()
{

View file

@ -37,7 +37,7 @@ class ServiceLocator extends BaseServiceLocator
*
* @return mixed
*/
public function get(string $id)
public function get($id)
{
return isset($this->serviceMap[$id]) ? ($this->factory)(...$this->serviceMap[$id]) : parent::get($id);
}

View file

@ -1,27 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DependencyInjection\Attribute;
/**
* An attribute to tell under which index and priority a service class should be found in tagged iterators/locators.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
#[\Attribute(\Attribute::TARGET_CLASS)]
class AsTaggedItem
{
public function __construct(
public ?string $index = null,
public ?int $priority = null,
) {
}
}

View file

@ -1,34 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DependencyInjection\Attribute;
/**
* An attribute to tell how a base type should be autoconfigured.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
class Autoconfigure
{
public function __construct(
public ?array $tags = null,
public ?array $calls = null,
public ?array $bind = null,
public bool|string|null $lazy = null,
public ?bool $public = null,
public ?bool $shared = null,
public ?bool $autowire = null,
public ?array $properties = null,
public array|string|null $configurator = null,
) {
}
}

View file

@ -1,30 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DependencyInjection\Attribute;
/**
* An attribute to tell how a base type should be tagged.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
class AutoconfigureTag extends Autoconfigure
{
public function __construct(string $name = null, array $attributes = [])
{
parent::__construct(
tags: [
[$name ?? 0 => $attributes],
]
);
}
}

View file

@ -1,24 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DependencyInjection\Attribute;
#[\Attribute(\Attribute::TARGET_PARAMETER)]
class TaggedIterator
{
public function __construct(
public string $tag,
public ?string $indexAttribute = null,
public ?string $defaultIndexMethod = null,
public ?string $defaultPriorityMethod = null,
) {
}
}

View file

@ -1,24 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DependencyInjection\Attribute;
#[\Attribute(\Attribute::TARGET_PARAMETER)]
class TaggedLocator
{
public function __construct(
public string $tag,
public ?string $indexAttribute = null,
public ?string $defaultIndexMethod = null,
public ?string $defaultPriorityMethod = null,
) {
}
}

View file

@ -1,54 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DependencyInjection\Attribute;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
/**
* An attribute to tell how a dependency is used and hint named autowiring aliases.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
#[\Attribute(\Attribute::TARGET_PARAMETER)]
final class Target
{
/**
* @var string
*/
public $name;
public function __construct(string $name)
{
$this->name = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name))));
}
public static function parseName(\ReflectionParameter $parameter): string
{
if (80000 > \PHP_VERSION_ID || !$target = $parameter->getAttributes(self::class)[0] ?? null) {
return $parameter->name;
}
$name = $target->newInstance()->name;
if (!preg_match('/^[a-zA-Z_\x7f-\xff]/', $name)) {
if (($function = $parameter->getDeclaringFunction()) instanceof \ReflectionMethod) {
$function = $function->class.'::'.$function->name;
} else {
$function = $function->name;
}
throw new InvalidArgumentException(sprintf('Invalid #[Target] name "%s" on parameter "$%s" of "%s()": the first character must be a letter.', $name, $parameter->name, $function));
}
return $name;
}
}

View file

@ -1,26 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DependencyInjection\Attribute;
/**
* An attribute to tell under which environement this class should be registered as a service.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class When
{
public function __construct(
public string $env,
) {
}
}

View file

@ -1,32 +1,6 @@
CHANGELOG
=========
5.4
---
* Add `$defaultIndexMethod` and `$defaultPriorityMethod` to `TaggedIterator` and `TaggedLocator` attributes
* Add `service_closure()` to the PHP-DSL
* Add support for autoconfigurable attributes on methods, properties and parameters
* Make auto-aliases private by default
* Add support for autowiring union and intersection types
5.3
---
* Add `ServicesConfigurator::remove()` in the PHP-DSL
* Add `%env(not:...)%` processor to negate boolean values
* Add support for loading autoconfiguration rules via the `#[Autoconfigure]` and `#[AutoconfigureTag]` attributes on PHP 8
* Add `#[AsTaggedItem]` attribute for defining the index and priority of classes found in tagged iterators/locators
* Add autoconfigurable attributes
* Add support for autowiring tagged iterators and locators via attributes on PHP 8
* Add support for per-env configuration in XML and Yaml loaders
* Add `ContainerBuilder::willBeAvailable()` to help with conditional configuration
* Add support an integer return value for default_index_method
* Add `#[When(env: 'foo')]` to skip autoregistering a class when the env doesn't match
* Add `env()` and `EnvConfigurator` in the PHP-DSL
* Add support for `ConfigBuilder` in the `PhpFileLoader`
* Add `ContainerConfigurator::env()` to get the current environment
* Add `#[Target]` to tell how a dependency is used and hint named autowiring aliases
5.2.0
-----

View file

@ -61,7 +61,7 @@ class ChildDefinition extends Definition
*
* @param int|string $index
*
* @return mixed
* @return mixed The argument value
*
* @throws OutOfBoundsException When the argument does not exist
*/

View file

@ -12,7 +12,6 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\LogicException;
@ -70,7 +69,7 @@ abstract class AbstractRecursivePass implements CompilerPassInterface
*
* @param mixed $value
*
* @return mixed
* @return mixed The processed value
*/
protected function processValue($value, bool $isRoot = false)
{
@ -129,35 +128,25 @@ abstract class AbstractRecursivePass implements CompilerPassInterface
if ($factory) {
[$class, $method] = $factory;
if ('__construct' === $method) {
throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId));
}
if ($class instanceof Reference) {
$factoryDefinition = $this->container->findDefinition((string) $class);
while ((null === $class = $factoryDefinition->getClass()) && $factoryDefinition instanceof ChildDefinition) {
$factoryDefinition = $this->container->findDefinition($factoryDefinition->getParent());
}
$class = $this->container->findDefinition((string) $class)->getClass();
} elseif ($class instanceof Definition) {
$class = $class->getClass();
} elseif (null === $class) {
$class = $definition->getClass();
}
if ('__construct' === $method) {
throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId));
}
return $this->getReflectionMethod(new Definition($class), $method);
}
while ((null === $class = $definition->getClass()) && $definition instanceof ChildDefinition) {
$definition = $this->container->findDefinition($definition->getParent());
}
$class = $definition->getClass();
try {
if (!$r = $this->container->getReflectionClass($class)) {
if (null === $class) {
throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId));
}
throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
}
} catch (\ReflectionException $e) {
@ -185,11 +174,7 @@ abstract class AbstractRecursivePass implements CompilerPassInterface
return $this->getConstructor($definition, true);
}
while ((null === $class = $definition->getClass()) && $definition instanceof ChildDefinition) {
$definition = $this->container->findDefinition($definition->getParent());
}
if (null === $class) {
if (!$class = $definition->getClass()) {
throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId));
}
@ -198,10 +183,6 @@ abstract class AbstractRecursivePass implements CompilerPassInterface
}
if (!$r->hasMethod($method)) {
if ($r->hasMethod('__call') && ($r = $r->getMethod('__call')) && $r->isPublic()) {
return new \ReflectionMethod(static function (...$arguments) {}, '__invoke');
}
throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method));
}
@ -217,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. Try running "composer require symfony/expression-language".');
throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
}
$providers = $this->container->getExpressionLanguageProviders();

View file

@ -23,10 +23,6 @@ final class AliasDeprecatedPublicServicesPass extends AbstractRecursivePass
public function __construct(string $tagName = 'container.private')
{
if (0 < \func_num_args()) {
trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
}
$this->tagName = $tagName;
}

View file

@ -1,168 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
* @author Alexander M. Turek <me@derrabus.de>
*/
final class AttributeAutoconfigurationPass extends AbstractRecursivePass
{
private $classAttributeConfigurators = [];
private $methodAttributeConfigurators = [];
private $propertyAttributeConfigurators = [];
private $parameterAttributeConfigurators = [];
public function process(ContainerBuilder $container): void
{
if (80000 > \PHP_VERSION_ID || !$container->getAutoconfiguredAttributes()) {
return;
}
foreach ($container->getAutoconfiguredAttributes() as $attributeName => $callable) {
$callableReflector = new \ReflectionFunction(\Closure::fromCallable($callable));
if ($callableReflector->getNumberOfParameters() <= 2) {
$this->classAttributeConfigurators[$attributeName] = $callable;
continue;
}
$reflectorParameter = $callableReflector->getParameters()[2];
$parameterType = $reflectorParameter->getType();
$types = [];
if ($parameterType instanceof \ReflectionUnionType) {
foreach ($parameterType->getTypes() as $type) {
$types[] = $type->getName();
}
} elseif ($parameterType instanceof \ReflectionNamedType) {
$types[] = $parameterType->getName();
} else {
throw new LogicException(sprintf('Argument "$%s" of attribute autoconfigurator should have a type, use one or more of "\ReflectionClass|\ReflectionMethod|\ReflectionProperty|\ReflectionParameter|\Reflector" in "%s" on line "%d".', $reflectorParameter->getName(), $callableReflector->getFileName(), $callableReflector->getStartLine()));
}
try {
$attributeReflector = new \ReflectionClass($attributeName);
} catch (\ReflectionException $e) {
continue;
}
$targets = $attributeReflector->getAttributes(\Attribute::class)[0] ?? 0;
$targets = $targets ? $targets->getArguments()[0] ?? -1 : 0;
foreach (['class', 'method', 'property', 'parameter'] as $symbol) {
if (['Reflector'] !== $types) {
if (!\in_array('Reflection'.ucfirst($symbol), $types, true)) {
continue;
}
if (!($targets & \constant('Attribute::TARGET_'.strtoupper($symbol)))) {
throw new LogicException(sprintf('Invalid type "Reflection%s" on argument "$%s": attribute "%s" cannot target a '.$symbol.' in "%s" on line "%d".', ucfirst($symbol), $reflectorParameter->getName(), $attributeName, $callableReflector->getFileName(), $callableReflector->getStartLine()));
}
}
$this->{$symbol.'AttributeConfigurators'}[$attributeName] = $callable;
}
}
parent::process($container);
}
protected function processValue($value, bool $isRoot = false)
{
if (!$value instanceof Definition
|| !$value->isAutoconfigured()
|| $value->isAbstract()
|| $value->hasTag('container.ignore_attributes')
|| !($classReflector = $this->container->getReflectionClass($value->getClass(), false))
) {
return parent::processValue($value, $isRoot);
}
$instanceof = $value->getInstanceofConditionals();
$conditionals = $instanceof[$classReflector->getName()] ?? new ChildDefinition('');
if ($this->classAttributeConfigurators) {
foreach ($classReflector->getAttributes() as $attribute) {
if ($configurator = $this->classAttributeConfigurators[$attribute->getName()] ?? null) {
$configurator($conditionals, $attribute->newInstance(), $classReflector);
}
}
}
if ($this->parameterAttributeConfigurators) {
try {
$constructorReflector = $this->getConstructor($value, false);
} catch (RuntimeException $e) {
$constructorReflector = null;
}
if ($constructorReflector) {
foreach ($constructorReflector->getParameters() as $parameterReflector) {
foreach ($parameterReflector->getAttributes() as $attribute) {
if ($configurator = $this->parameterAttributeConfigurators[$attribute->getName()] ?? null) {
$configurator($conditionals, $attribute->newInstance(), $parameterReflector);
}
}
}
}
}
if ($this->methodAttributeConfigurators || $this->parameterAttributeConfigurators) {
foreach ($classReflector->getMethods(\ReflectionMethod::IS_PUBLIC) as $methodReflector) {
if ($methodReflector->isStatic() || $methodReflector->isConstructor() || $methodReflector->isDestructor()) {
continue;
}
if ($this->methodAttributeConfigurators) {
foreach ($methodReflector->getAttributes() as $attribute) {
if ($configurator = $this->methodAttributeConfigurators[$attribute->getName()] ?? null) {
$configurator($conditionals, $attribute->newInstance(), $methodReflector);
}
}
}
if ($this->parameterAttributeConfigurators) {
foreach ($methodReflector->getParameters() as $parameterReflector) {
foreach ($parameterReflector->getAttributes() as $attribute) {
if ($configurator = $this->parameterAttributeConfigurators[$attribute->getName()] ?? null) {
$configurator($conditionals, $attribute->newInstance(), $parameterReflector);
}
}
}
}
}
}
if ($this->propertyAttributeConfigurators) {
foreach ($classReflector->getProperties(\ReflectionProperty::IS_PUBLIC) as $propertyReflector) {
if ($propertyReflector->isStatic()) {
continue;
}
foreach ($propertyReflector->getAttributes() as $attribute) {
if ($configurator = $this->propertyAttributeConfigurators[$attribute->getName()] ?? null) {
$configurator($conditionals, $attribute->newInstance(), $propertyReflector);
}
}
}
}
if (!isset($instanceof[$classReflector->getName()]) && new ChildDefinition('') != $conditionals) {
$instanceof[$classReflector->getName()] = $conditionals;
$value->setInstanceofConditionals($instanceof);
}
return parent::processValue($value, $isRoot);
}
}

View file

@ -20,8 +20,6 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
*/
class AutoAliasServicePass implements CompilerPassInterface
{
private $privateAliases = [];
/**
* {@inheritdoc}
*/
@ -35,26 +33,9 @@ class AutoAliasServicePass implements CompilerPassInterface
$aliasId = $container->getParameterBag()->resolveValue($tag['format']);
if ($container->hasDefinition($aliasId) || $container->hasAlias($aliasId)) {
$alias = new Alias($aliasId, $container->getDefinition($serviceId)->isPublic());
$container->setAlias($serviceId, $alias);
if (!$alias->isPublic()) {
$alias->setPublic(true);
$this->privateAliases[] = $alias;
}
$container->setAlias($serviceId, new Alias($aliasId, true));
}
}
}
}
/**
* @internal to be removed in Symfony 6.0
*/
public function getPrivateAliases(): array
{
$privateAliases = $this->privateAliases;
$this->privateAliases = [];
return $privateAliases;
}
}

View file

@ -12,11 +12,6 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\Config\Resource\ClassExistenceResource;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
use Symfony\Component\DependencyInjection\Attribute\TaggedLocator;
use Symfony\Component\DependencyInjection\Attribute\Target;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
@ -34,26 +29,19 @@ class AutowirePass extends AbstractRecursivePass
{
private $types;
private $ambiguousServiceTypes;
private $autowiringAliases;
private $lastFailure;
private $throwOnAutowiringException;
private $decoratedClass;
private $decoratedId;
private $methodCalls;
private $defaultArgument;
private $getPreviousValue;
private $decoratedMethodIndex;
private $decoratedMethodArgumentIndex;
private $typesClone;
private $combinedAliases;
public function __construct(bool $throwOnAutowireException = true)
{
$this->throwOnAutowiringException = $throwOnAutowireException;
$this->defaultArgument = new class() {
public $value;
public $names;
};
}
/**
@ -61,8 +49,6 @@ class AutowirePass extends AbstractRecursivePass
*/
public function process(ContainerBuilder $container)
{
$this->populateCombinedAliases($container);
try {
$this->typesClone = clone $this;
parent::process($container);
@ -70,12 +56,10 @@ class AutowirePass extends AbstractRecursivePass
$this->decoratedClass = null;
$this->decoratedId = null;
$this->methodCalls = null;
$this->defaultArgument->names = null;
$this->getPreviousValue = null;
$this->decoratedMethodIndex = null;
$this->decoratedMethodArgumentIndex = null;
$this->typesClone = null;
$this->combinedAliases = [];
}
}
@ -103,7 +87,7 @@ class AutowirePass extends AbstractRecursivePass
private function doProcessValue($value, bool $isRoot = false)
{
if ($value instanceof TypedReference) {
if ($ref = $this->getAutowiredReference($value, true)) {
if ($ref = $this->getAutowiredReference($value)) {
return $ref;
}
if (ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) {
@ -139,8 +123,7 @@ class AutowirePass extends AbstractRecursivePass
array_unshift($this->methodCalls, [$constructor, $value->getArguments()]);
}
$checkAttributes = 80000 <= \PHP_VERSION_ID && !$value->hasTag('container.ignore_attributes');
$this->methodCalls = $this->autowireCalls($reflectionClass, $isRoot, $checkAttributes);
$this->methodCalls = $this->autowireCalls($reflectionClass, $isRoot);
if ($constructor) {
[, $arguments] = array_shift($this->methodCalls);
@ -157,7 +140,7 @@ class AutowirePass extends AbstractRecursivePass
return $value;
}
private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot, bool $checkAttributes): array
private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot): array
{
$this->decoratedId = null;
$this->decoratedClass = null;
@ -167,9 +150,8 @@ class AutowirePass extends AbstractRecursivePass
$this->decoratedClass = $this->container->findDefinition($this->decoratedId)->getClass();
}
$patchedIndexes = [];
foreach ($this->methodCalls as $i => $call) {
$this->decoratedMethodIndex = $i;
[$method, $arguments] = $call;
if ($method instanceof \ReflectionFunctionAbstract) {
@ -186,48 +168,24 @@ class AutowirePass extends AbstractRecursivePass
}
}
$arguments = $this->autowireMethod($reflectionMethod, $arguments, $checkAttributes, $i);
$arguments = $this->autowireMethod($reflectionMethod, $arguments);
if ($arguments !== $call[1]) {
$this->methodCalls[$i][1] = $arguments;
$patchedIndexes[] = $i;
}
}
// use named arguments to skip complex default values
foreach ($patchedIndexes as $i) {
$namedArguments = null;
$arguments = $this->methodCalls[$i][1];
foreach ($arguments as $j => $value) {
if ($namedArguments && !$value instanceof $this->defaultArgument) {
unset($arguments[$j]);
$arguments[$namedArguments[$j]] = $value;
}
if ($namedArguments || !$value instanceof $this->defaultArgument) {
continue;
}
if (\PHP_VERSION_ID >= 80100 && (\is_array($value->value) ? $value->value : \is_object($value->value))) {
unset($arguments[$j]);
$namedArguments = $value->names;
} else {
$arguments[$j] = $value->value;
}
}
$this->methodCalls[$i][1] = $arguments;
}
return $this->methodCalls;
}
/**
* Autowires the constructor or a method.
*
* @return array The autowired arguments
*
* @throws AutowiringFailedException
*/
private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments, bool $checkAttributes, int $methodIndex): array
private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments): array
{
$class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId;
$method = $reflectionMethod->name;
@ -235,37 +193,14 @@ class AutowirePass extends AbstractRecursivePass
if ($reflectionMethod->isVariadic()) {
array_pop($parameters);
}
$this->defaultArgument->names = new \ArrayObject();
foreach ($parameters as $index => $parameter) {
$this->defaultArgument->names[$index] = $parameter->name;
if (\array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
continue;
}
$type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true);
if ($checkAttributes) {
foreach ($parameter->getAttributes() as $attribute) {
if (TaggedIterator::class === $attribute->getName()) {
$attribute = $attribute->newInstance();
$arguments[$index] = new TaggedIteratorArgument($attribute->tag, $attribute->indexAttribute, $attribute->defaultIndexMethod, false, $attribute->defaultPriorityMethod);
break;
}
if (TaggedLocator::class === $attribute->getName()) {
$attribute = $attribute->newInstance();
$arguments[$index] = new ServiceLocatorArgument(new TaggedIteratorArgument($attribute->tag, $attribute->indexAttribute, $attribute->defaultIndexMethod, true, $attribute->defaultPriorityMethod));
break;
}
}
if ('' !== ($arguments[$index] ?? '')) {
continue;
}
}
if (!$type) {
if (isset($arguments[$index])) {
continue;
@ -277,8 +212,7 @@ class AutowirePass extends AbstractRecursivePass
// be false when isOptional() returns true. If the
// argument *is* optional, allow it to be missing
if ($parameter->isOptional()) {
--$index;
break;
continue;
}
$type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false);
$type = $type ? sprintf('is type-hinted "%s"', ltrim($type, '\\')) : 'has no type-hint';
@ -287,19 +221,17 @@ class AutowirePass extends AbstractRecursivePass
}
// specifically pass the default value
$arguments[$index] = clone $this->defaultArgument;
$arguments[$index]->value = $parameter->getDefaultValue();
$arguments[$index] = $parameter->getDefaultValue();
continue;
}
$getValue = function () use ($type, $parameter, $class, $method) {
if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, Target::parseName($parameter)), true)) {
if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $parameter->name))) {
$failureMessage = $this->createTypeNotFoundMessageCallback($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method));
if ($parameter->isDefaultValueAvailable()) {
$value = clone $this->defaultArgument;
$value->value = $parameter->getDefaultValue();
$value = $parameter->getDefaultValue();
} elseif (!$parameter->allowsNull()) {
throw new AutowiringFailedException($this->currentId, $failureMessage);
}
@ -320,7 +252,6 @@ class AutowirePass extends AbstractRecursivePass
} else {
$arguments[$index] = new TypedReference($this->decoratedId, $this->decoratedClass);
$this->getPreviousValue = $getValue;
$this->decoratedMethodIndex = $methodIndex;
$this->decoratedMethodArgumentIndex = $index;
continue;
@ -332,7 +263,8 @@ class AutowirePass extends AbstractRecursivePass
if ($parameters && !isset($arguments[++$index])) {
while (0 <= --$index) {
if (!$arguments[$index] instanceof $this->defaultArgument) {
$parameter = $parameters[$index];
if (!$parameter->isDefaultValueAvailable() || $parameter->getDefaultValue() !== $arguments[$index]) {
break;
}
unset($arguments[$index]);
@ -349,7 +281,7 @@ class AutowirePass extends AbstractRecursivePass
/**
* Returns a reference to the service matching the given type, if any.
*/
private function getAutowiredReference(TypedReference $reference, bool $filterType): ?TypedReference
private function getAutowiredReference(TypedReference $reference): ?TypedReference
{
$this->lastFailure = null;
$type = $reference->getType();
@ -358,25 +290,13 @@ class AutowirePass extends AbstractRecursivePass
return $reference;
}
if ($filterType && false !== $m = strpbrk($type, '&|')) {
$types = array_diff(explode($m[0], $type), ['int', 'string', 'array', 'bool', 'float', 'iterable', 'object', 'callable', 'null']);
sort($types);
$type = implode($m[0], $types);
}
if (null !== $name = $reference->getName()) {
if ($this->container->has($alias = $type.' $'.$name) && !$this->container->findDefinition($alias)->isAbstract()) {
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
}
if (null !== ($alias = $this->combinedAliases[$alias] ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
}
if ($this->container->has($name) && !$this->container->findDefinition($name)->isAbstract()) {
foreach ($this->container->getAliases() + $this->combinedAliases as $id => $alias) {
foreach ($this->container->getAliases() as $id => $alias) {
if ($name === (string) $alias && str_starts_with($id, $type.' $')) {
return new TypedReference($name, $type, $reference->getInvalidBehavior());
}
@ -388,10 +308,6 @@ class AutowirePass extends AbstractRecursivePass
return new TypedReference($type, $type, $reference->getInvalidBehavior());
}
if (null !== ($alias = $this->combinedAliases[$type] ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
}
return null;
}
@ -402,15 +318,10 @@ class AutowirePass extends AbstractRecursivePass
{
$this->types = [];
$this->ambiguousServiceTypes = [];
$this->autowiringAliases = [];
foreach ($container->getDefinitions() as $id => $definition) {
$this->populateAvailableType($container, $id, $definition);
}
foreach ($container->getAliases() as $id => $alias) {
$this->populateAutowiringAlias($id);
}
}
/**
@ -434,8 +345,6 @@ class AutowirePass extends AbstractRecursivePass
do {
$this->set($reflectionClass->name, $id);
} while ($reflectionClass = $reflectionClass->getParentClass());
$this->populateAutowiringAlias($id);
}
/**
@ -525,10 +434,6 @@ class AutowirePass extends AbstractRecursivePass
}
$servicesAndAliases = $container->getServiceIds();
if (null !== ($autowiringAliases = $this->autowiringAliases[$type] ?? null) && !isset($autowiringAliases[''])) {
return sprintf(' Available autowiring aliases for this %s are: "$%s".', class_exists($type, false) ? 'class' : 'interface', implode('", "$', $autowiringAliases));
}
if (!$container->has($type) && false !== $key = array_search(strtolower($type), array_map('strtolower', $servicesAndAliases))) {
return sprintf(' Did you mean "%s"?', $servicesAndAliases[$key]);
} elseif (isset($this->ambiguousServiceTypes[$type])) {
@ -567,59 +472,4 @@ class AutowirePass extends AbstractRecursivePass
return null;
}
private function populateAutowiringAlias(string $id): void
{
if (!preg_match('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^((?&V)(?:\\\\(?&V))*+)(?: \$((?&V)))?$/', $id, $m)) {
return;
}
$type = $m[2];
$name = $m[3] ?? '';
if (class_exists($type, false) || interface_exists($type, false)) {
$this->autowiringAliases[$type][$name] = $name;
}
}
private function populateCombinedAliases(ContainerBuilder $container): void
{
$this->combinedAliases = [];
$reverseAliases = [];
foreach ($container->getAliases() as $id => $alias) {
if (!preg_match('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^((?&V)(?:\\\\(?&V))*+)(?: \$((?&V)))?$/', $id, $m)) {
continue;
}
$type = $m[2];
$name = $m[3] ?? '';
$reverseAliases[(string) $alias][$name][] = $type;
}
foreach ($reverseAliases as $alias => $names) {
foreach ($names as $name => $types) {
if (2 > $count = \count($types)) {
continue;
}
sort($types);
$i = 1 << $count;
// compute the powerset of the list of types
while ($i--) {
$set = [];
for ($j = 0; $j < $count; ++$j) {
if ($i & (1 << $j)) {
$set[] = $types[$j];
}
}
if (2 <= \count($set)) {
$this->combinedAliases[implode('&', $set).('' === $name ? '' : ' $'.$name)] = $alias;
$this->combinedAliases[implode('|', $set).('' === $name ? '' : ' $'.$name)] = $alias;
}
}
}
}
}
}

View file

@ -39,13 +39,7 @@ class CheckArgumentsValidityPass extends AbstractRecursivePass
}
$i = 0;
$hasNamedArgs = false;
foreach ($value->getArguments() as $k => $v) {
if (\PHP_VERSION_ID >= 80000 && preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) {
$hasNamedArgs = true;
continue;
}
if ($k !== $i++) {
if (!\is_int($k)) {
$msg = sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k);
@ -63,27 +57,11 @@ class CheckArgumentsValidityPass extends AbstractRecursivePass
throw new RuntimeException($msg);
}
}
if ($hasNamedArgs) {
$msg = sprintf('Invalid constructor argument for service "%s": cannot use positional argument after named argument. Check your service definition.', $this->currentId);
$value->addError($msg);
if ($this->throwExceptions) {
throw new RuntimeException($msg);
}
break;
}
}
foreach ($value->getMethodCalls() as $methodCall) {
$i = 0;
$hasNamedArgs = false;
foreach ($methodCall[1] as $k => $v) {
if (\PHP_VERSION_ID >= 80000 && preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) {
$hasNamedArgs = true;
continue;
}
if ($k !== $i++) {
if (!\is_int($k)) {
$msg = sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k);
@ -101,16 +79,6 @@ class CheckArgumentsValidityPass extends AbstractRecursivePass
throw new RuntimeException($msg);
}
}
if ($hasNamedArgs) {
$msg = sprintf('Invalid argument for method call "%s" of service "%s": cannot use positional argument after named argument. Check your service definition.', $methodCall[0], $this->currentId);
$value->addError($msg);
if ($this->throwExceptions) {
throw new RuntimeException($msg);
}
break;
}
}
}

View file

@ -44,7 +44,7 @@ class CheckDefinitionValidityPass implements CompilerPassInterface
}
// non-synthetic, non-abstract service has class
if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass() && !$definition->hasTag('container.service_locator') && (!$definition->getFactory() || !preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id))) {
if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass() && (!$definition->getFactory() || !preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id))) {
if ($definition->getFactory()) {
throw new RuntimeException(sprintf('Please add the class to service "%s" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.', $id));
}

View file

@ -210,10 +210,6 @@ final class CheckTypeDeclarationsPass extends AbstractRecursivePass
$class = null;
if ($value instanceof Definition) {
if ($value->getFactory()) {
return;
}
$class = $value->getClass();
if ($class && isset(self::BUILTIN_TYPES[strtolower($class)])) {

View file

@ -32,7 +32,9 @@ class Compiler
}
/**
* @return PassConfig
* Returns the PassConfig.
*
* @return PassConfig The PassConfig instance
*/
public function getPassConfig()
{
@ -40,13 +42,18 @@ class Compiler
}
/**
* @return ServiceReferenceGraph
* Returns the ServiceReferenceGraph.
*
* @return ServiceReferenceGraph The ServiceReferenceGraph instance
*/
public function getServiceReferenceGraph()
{
return $this->serviceReferenceGraph;
}
/**
* Adds a pass to the PassConfig.
*/
public function addPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0)
{
$this->passConfig->addPass($pass, $type, $priority);
@ -65,7 +72,9 @@ class Compiler
}
/**
* @return array
* Returns the log.
*
* @return array Log array
*/
public function getLog()
{

View file

@ -31,10 +31,6 @@ class DecoratorServicePass extends AbstractRecursivePass
public function __construct(?string $innerId = '.inner')
{
if (0 < \func_num_args()) {
trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
}
$this->innerId = $innerId;
}
@ -73,11 +69,13 @@ class DecoratorServicePass extends AbstractRecursivePass
if ($container->hasAlias($inner)) {
$alias = $container->getAlias($inner);
$public = $alias->isPublic();
$private = $alias->isPrivate();
$container->setAlias($renamedId, new Alias((string) $alias, false));
$decoratedDefinition = $container->findDefinition($alias);
} elseif ($container->hasDefinition($inner)) {
$decoratedDefinition = $container->getDefinition($inner);
$public = $decoratedDefinition->isPublic();
$private = $decoratedDefinition->isPrivate();
$decoratedDefinition->setPublic(false);
$container->setDefinition($renamedId, $decoratedDefinition);
$decoratingDefinitions[$inner] = $decoratedDefinition;
@ -86,6 +84,7 @@ class DecoratorServicePass extends AbstractRecursivePass
continue;
} elseif (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
$public = $definition->isPublic();
$private = $definition->isPrivate();
$decoratedDefinition = null;
} else {
throw new ServiceNotFoundException($inner, $id);

View file

@ -110,7 +110,7 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass
protected function processValue($value, bool $isRoot = false)
{
if ($value instanceof ArgumentInterface) {
// References found in ArgumentInterface::getValues() are not inlineable
// Reference found in ArgumentInterface::getValues() are not inlineable
return $value;
}
@ -176,7 +176,7 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass
$srcId = $edge->getSourceNode()->getId();
$this->connectedIds[$srcId] = true;
if ($edge->isWeak() || $edge->isLazy()) {
return !$this->connectedIds[$id] = true;
return false;
}
}
@ -198,7 +198,9 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass
$srcIds = [];
$srcCount = 0;
$isReferencedByConstructor = false;
foreach ($this->graph->getNode($id)->getInEdges() as $edge) {
$isReferencedByConstructor = $isReferencedByConstructor || $edge->isReferencedByConstructor();
$srcId = $edge->getSourceNode()->getId();
$this->connectedIds[$srcId] = true;
if ($edge->isWeak() || $edge->isLazy()) {

View file

@ -79,6 +79,10 @@ class MergeExtensionConfigurationPass implements CompilerPassInterface
$container->getParameterBag()->mergeEnvPlaceholders($resolvingBag);
}
if ($configAvailable) {
BaseNode::resetPlaceholders();
}
throw $e;
}
@ -91,6 +95,10 @@ class MergeExtensionConfigurationPass implements CompilerPassInterface
$container->getParameterBag()->add($parameters);
}
if ($configAvailable) {
BaseNode::resetPlaceholders();
}
$container->addDefinitions($definitions);
$container->addAliases($aliases);
}

View file

@ -42,8 +42,6 @@ class PassConfig
$this->beforeOptimizationPasses = [
100 => [
new ResolveClassPass(),
new RegisterAutoconfigureAttributesPass(),
new AttributeAutoconfigurationPass(),
new ResolveInstanceofConditionalsPass(),
new RegisterEnvVarProcessorsPass(),
],
@ -51,7 +49,7 @@ class PassConfig
];
$this->optimizationPasses = [[
$autoAliasServicePass = new AutoAliasServicePass(),
new AutoAliasServicePass(),
new ValidateEnvPlaceholdersPass(),
new ResolveDecoratorStackPass(),
new ResolveChildDefinitionsPass(),
@ -66,7 +64,6 @@ class PassConfig
new DecoratorServicePass(),
new CheckDefinitionValidityPass(),
new AutowirePass(false),
new ServiceLocatorTagPass(),
new ResolveTaggedIteratorArgumentPass(),
new ResolveServiceSubscribersPass(),
new ResolveReferencesToAliasesPass(),
@ -79,7 +76,7 @@ class PassConfig
$this->removingPasses = [[
new RemovePrivateAliasesPass(),
(new ReplaceAliasByActualDefinitionPass())->setAutoAliasServicePass($autoAliasServicePass),
new ReplaceAliasByActualDefinitionPass(),
new RemoveAbstractDefinitionsPass(),
new RemoveUnusedDefinitionsPass(),
new AnalyzeServiceReferencesPass(),

View file

@ -12,7 +12,6 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\Attribute\AsTaggedItem;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
@ -57,10 +56,8 @@ trait PriorityTaggedServiceTrait
foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
$defaultPriority = null;
$defaultIndex = null;
$definition = $container->getDefinition($serviceId);
$class = $definition->getClass();
$class = $container->getDefinition($serviceId)->getClass();
$class = $container->getParameterBag()->resolveValue($class) ?: null;
$checkTaggedItem = !$definition->hasTag(80000 <= \PHP_VERSION_ID && $definition->isAutoconfigured() ? 'container.ignore_attributes' : $tagName);
foreach ($attributes as $attribute) {
$index = $priority = null;
@ -68,7 +65,7 @@ trait PriorityTaggedServiceTrait
if (isset($attribute['priority'])) {
$priority = $attribute['priority'];
} elseif (null === $defaultPriority && $defaultPriorityMethod && $class) {
$defaultPriority = PriorityTaggedServiceUtil::getDefault($container, $serviceId, $class, $defaultPriorityMethod, $tagName, 'priority', $checkTaggedItem);
$defaultPriority = PriorityTaggedServiceUtil::getDefaultPriority($container, $serviceId, $class, $defaultPriorityMethod, $tagName);
}
$priority = $priority ?? $defaultPriority ?? $defaultPriority = 0;
@ -80,7 +77,7 @@ trait PriorityTaggedServiceTrait
if (null !== $indexAttribute && isset($attribute[$indexAttribute])) {
$index = $attribute[$indexAttribute];
} elseif (null === $defaultIndex && $defaultPriorityMethod && $class) {
$defaultIndex = PriorityTaggedServiceUtil::getDefault($container, $serviceId, $class, $defaultIndexMethod ?? 'getDefaultName', $tagName, $indexAttribute, $checkTaggedItem);
$defaultIndex = PriorityTaggedServiceUtil::getDefaultIndex($container, $serviceId, $class, $defaultIndexMethod ?? 'getDefaultName', $tagName, $indexAttribute);
}
$index = $index ?? $defaultIndex ?? $defaultIndex = $serviceId;
@ -117,30 +114,22 @@ trait PriorityTaggedServiceTrait
class PriorityTaggedServiceUtil
{
/**
* @return string|int|null
* Gets the index defined by the default index method.
*/
public static function getDefault(ContainerBuilder $container, string $serviceId, string $class, string $defaultMethod, string $tagName, ?string $indexAttribute, bool $checkTaggedItem)
public static function getDefaultIndex(ContainerBuilder $container, string $serviceId, string $class, string $defaultIndexMethod, string $tagName, ?string $indexAttribute): ?string
{
if (!($r = $container->getReflectionClass($class)) || (!$checkTaggedItem && !$r->hasMethod($defaultMethod))) {
return null;
}
if ($checkTaggedItem && !$r->hasMethod($defaultMethod)) {
foreach ($r->getAttributes(AsTaggedItem::class) as $attribute) {
return 'priority' === $indexAttribute ? $attribute->newInstance()->priority : $attribute->newInstance()->index;
}
if (!($r = $container->getReflectionClass($class)) || !$r->hasMethod($defaultIndexMethod)) {
return null;
}
if (null !== $indexAttribute) {
$service = $class !== $serviceId ? sprintf('service "%s"', $serviceId) : 'on the corresponding service';
$message = [sprintf('Either method "%s::%s()" should ', $class, $defaultMethod), sprintf(' or tag "%s" on %s is missing attribute "%s".', $tagName, $service, $indexAttribute)];
$message = [sprintf('Either method "%s::%s()" should ', $class, $defaultIndexMethod), sprintf(' or tag "%s" on %s is missing attribute "%s".', $tagName, $service, $indexAttribute)];
} else {
$message = [sprintf('Method "%s::%s()" should ', $class, $defaultMethod), '.'];
$message = [sprintf('Method "%s::%s()" should ', $class, $defaultIndexMethod), '.'];
}
if (!($rm = $r->getMethod($defaultMethod))->isStatic()) {
if (!($rm = $r->getMethod($defaultIndexMethod))->isStatic()) {
throw new InvalidArgumentException(implode('be static', $message));
}
@ -148,24 +137,38 @@ class PriorityTaggedServiceUtil
throw new InvalidArgumentException(implode('be public', $message));
}
$default = $rm->invoke(null);
$defaultIndex = $rm->invoke(null);
if ('priority' === $indexAttribute) {
if (!\is_int($default)) {
throw new InvalidArgumentException(implode(sprintf('return int (got "%s")', get_debug_type($default)), $message));
}
return $default;
if (!\is_string($defaultIndex)) {
throw new InvalidArgumentException(implode(sprintf('return a string (got "%s")', get_debug_type($defaultIndex)), $message));
}
if (\is_int($default)) {
$default = (string) $default;
return $defaultIndex;
}
/**
* Gets the priority defined by the default priority method.
*/
public static function getDefaultPriority(ContainerBuilder $container, string $serviceId, string $class, string $defaultPriorityMethod, string $tagName): ?int
{
if (!($r = $container->getReflectionClass($class)) || !$r->hasMethod($defaultPriorityMethod)) {
return null;
}
if (!\is_string($default)) {
throw new InvalidArgumentException(implode(sprintf('return string|int (got "%s")', get_debug_type($default)), $message));
if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) {
throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be static or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, $tagName, $serviceId));
}
return $default;
if (!$rm->isPublic()) {
throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be public or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, $tagName, $serviceId));
}
$defaultPriority = $rm->invoke(null);
if (!\is_int($defaultPriority)) {
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer (got "%s") or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, get_debug_type($defaultPriority), $tagName, $serviceId));
}
return $defaultPriority;
}
}

View file

@ -1,91 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
/**
* Reads #[Autoconfigure] attributes on definitions that are autoconfigured
* and don't have the "container.ignore_attributes" tag.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
final class RegisterAutoconfigureAttributesPass implements CompilerPassInterface
{
private static $registerForAutoconfiguration;
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
if (80000 > \PHP_VERSION_ID) {
return;
}
foreach ($container->getDefinitions() as $id => $definition) {
if ($this->accept($definition) && $class = $container->getReflectionClass($definition->getClass(), false)) {
$this->processClass($container, $class);
}
}
}
public function accept(Definition $definition): bool
{
return 80000 <= \PHP_VERSION_ID && $definition->isAutoconfigured() && !$definition->hasTag('container.ignore_attributes');
}
public function processClass(ContainerBuilder $container, \ReflectionClass $class)
{
foreach ($class->getAttributes(Autoconfigure::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
self::registerForAutoconfiguration($container, $class, $attribute);
}
}
private static function registerForAutoconfiguration(ContainerBuilder $container, \ReflectionClass $class, \ReflectionAttribute $attribute)
{
if (self::$registerForAutoconfiguration) {
return (self::$registerForAutoconfiguration)($container, $class, $attribute);
}
$parseDefinitions = new \ReflectionMethod(YamlFileLoader::class, 'parseDefinitions');
$parseDefinitions->setAccessible(true);
$yamlLoader = $parseDefinitions->getDeclaringClass()->newInstanceWithoutConstructor();
self::$registerForAutoconfiguration = static function (ContainerBuilder $container, \ReflectionClass $class, \ReflectionAttribute $attribute) use ($parseDefinitions, $yamlLoader) {
$attribute = (array) $attribute->newInstance();
foreach ($attribute['tags'] ?? [] as $i => $tag) {
if (\is_array($tag) && [0] === array_keys($tag)) {
$attribute['tags'][$i] = [$class->name => $tag[0]];
}
}
$parseDefinitions->invoke(
$yamlLoader,
[
'services' => [
'_instanceof' => [
$class->name => [$container->registerForAutoconfiguration($class->name)] + $attribute,
],
],
],
$class->getFileName()
);
};
return (self::$registerForAutoconfiguration)($container, $class, $attribute);
}
}

View file

@ -28,10 +28,6 @@ class RegisterReverseContainerPass implements CompilerPassInterface
public function __construct(bool $beforeRemoving, string $serviceId = 'reverse_container', string $tagName = 'container.reversible')
{
if (1 < \func_num_args()) {
trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
}
$this->beforeRemoving = $beforeRemoving;
$this->serviceId = $serviceId;
$this->tagName = $tagName;

View file

@ -12,14 +12,12 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Psr\Container\ContainerInterface as PsrContainerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\TypedReference;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Contracts\Service\ServiceProviderInterface;
use Symfony\Contracts\Service\ServiceSubscriberInterface;
@ -68,11 +66,11 @@ class RegisterServiceSubscribersPass extends AbstractRecursivePass
throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $this->currentId, ServiceSubscriberInterface::class));
}
$class = $r->name;
$replaceDeprecatedSession = $this->container->has('.session.deprecated') && $r->isSubclassOf(AbstractController::class);
$subscriberMap = [];
foreach ($class::getSubscribedServices() as $key => $type) {
if (!\is_string($type) || !preg_match('/(?(DEFINE)(?<cn>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))(?(DEFINE)(?<fqcn>(?&cn)(?:\\\\(?&cn))*+))^\??(?&fqcn)(?:(?:\|(?&fqcn))*+|(?:&(?&fqcn))*+)$/', $type)) {
if (!\is_string($type) || !preg_match('/^\??[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $type)) {
throw new InvalidArgumentException(sprintf('"%s::getSubscribedServices()" must return valid PHP types for service "%s" key "%s", "%s" returned.', $class, $this->currentId, $key, \is_string($type) ? $type : get_debug_type($type)));
}
if ($optionalBehavior = '?' === $type[0]) {
@ -87,11 +85,6 @@ class RegisterServiceSubscribersPass extends AbstractRecursivePass
if (!$autowire) {
throw new InvalidArgumentException(sprintf('Service "%s" misses a "container.service_subscriber" tag with "key"/"id" attributes corresponding to entry "%s" as returned by "%s::getSubscribedServices()".', $this->currentId, $key, $class));
}
if ($replaceDeprecatedSession && SessionInterface::class === $type) {
// This prevents triggering the deprecation when building the container
// Should be removed in Symfony 6.0
$type = '.session.deprecated';
}
$serviceMap[$key] = new Reference($type);
}

View file

@ -25,19 +25,6 @@ use Symfony\Component\DependencyInjection\Reference;
class ReplaceAliasByActualDefinitionPass extends AbstractRecursivePass
{
private $replacements;
private $autoAliasServicePass;
/**
* @internal to be removed in Symfony 6.0
*
* @return $this
*/
public function setAutoAliasServicePass(AutoAliasServicePass $autoAliasServicePass): self
{
$this->autoAliasServicePass = $autoAliasServicePass;
return $this;
}
/**
* Process the Container to replace aliases with service definitions.
@ -49,25 +36,15 @@ class ReplaceAliasByActualDefinitionPass extends AbstractRecursivePass
// First collect all alias targets that need to be replaced
$seenAliasTargets = [];
$replacements = [];
$privateAliases = $this->autoAliasServicePass ? $this->autoAliasServicePass->getPrivateAliases() : [];
foreach ($privateAliases as $target) {
$target->setDeprecated('symfony/dependency-injection', '5.4', 'Accessing the "%alias_id%" service directly from the container is deprecated, use dependency injection instead.');
}
foreach ($container->getAliases() as $definitionId => $target) {
$targetId = (string) $target;
// Special case: leave this target alone
if ('service_container' === $targetId) {
continue;
}
// Check if target needs to be replaced
// Check if target needs to be replaces
if (isset($replacements[$targetId])) {
$container->setAlias($definitionId, $replacements[$targetId])->setPublic($target->isPublic());
if ($target->isDeprecated()) {
$container->getAlias($definitionId)->setDeprecated(...array_values($target->getDeprecation('%alias_id%')));
}
}
// No need to process the same target twice
if (isset($seenAliasTargets[$targetId])) {
@ -92,10 +69,6 @@ class ReplaceAliasByActualDefinitionPass extends AbstractRecursivePass
$container->setDefinition($definitionId, $definition);
$container->removeDefinition($targetId);
$replacements[$targetId] = $definitionId;
if ($target->isPublic() && $target->isDeprecated()) {
$definition->addTag('container.private', $target->getDeprecation('%service_id%'));
}
}
$this->replacements = $replacements;

View file

@ -14,7 +14,6 @@ namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\Attribute\Target;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
@ -126,7 +125,7 @@ class ResolveBindingsPass extends AbstractRecursivePass
$this->unusedBindings[$bindingId] = [$key, $this->currentId, $bindingType, $file];
}
if (preg_match('/^(?:(?:array|bool|float|int|string|iterable|([^ $]++)) )\$/', $key, $m)) {
if (preg_match('/^(?:(?:array|bool|float|int|string|([^ $]++)) )\$/', $key, $m)) {
$bindingNames[substr($key, \strlen($m[0]))] = $binding;
}
@ -134,11 +133,6 @@ class ResolveBindingsPass extends AbstractRecursivePass
continue;
}
if (is_subclass_of($m[1], \UnitEnum::class)) {
$bindingNames[substr($key, \strlen($m[0]))] = $binding;
continue;
}
if (null !== $bindingValue && !$bindingValue instanceof Reference && !$bindingValue instanceof Definition && !$bindingValue instanceof TaggedIteratorArgument && !$bindingValue instanceof ServiceLocatorArgument) {
throw new InvalidArgumentException(sprintf('Invalid value for binding key "%s" for service "%s": expected "%s", "%s", "%s", "%s" or null, "%s" given.', $key, $this->currentId, Reference::class, Definition::class, TaggedIteratorArgument::class, ServiceLocatorArgument::class, get_debug_type($bindingValue)));
}
@ -183,16 +177,15 @@ class ResolveBindingsPass extends AbstractRecursivePass
}
$typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter);
$name = Target::parseName($parameter);
if ($typeHint && \array_key_exists($k = ltrim($typeHint, '\\').' $'.$name, $bindings)) {
if ($typeHint && \array_key_exists($k = ltrim($typeHint, '\\').' $'.$parameter->name, $bindings)) {
$arguments[$key] = $this->getBindingValue($bindings[$k]);
continue;
}
if (\array_key_exists('$'.$name, $bindings)) {
$arguments[$key] = $this->getBindingValue($bindings['$'.$name]);
if (\array_key_exists('$'.$parameter->name, $bindings)) {
$arguments[$key] = $this->getBindingValue($bindings['$'.$parameter->name]);
continue;
}
@ -203,7 +196,7 @@ class ResolveBindingsPass extends AbstractRecursivePass
continue;
}
if (isset($bindingNames[$name]) || isset($bindingNames[$parameter->name])) {
if (isset($bindingNames[$parameter->name])) {
$bindingKey = array_search($binding, $bindings, true);
$argumentType = substr($bindingKey, 0, strpos($bindingKey, ' '));
$this->errorMessages[] = sprintf('Did you forget to add the type "%s" to argument "$%s" of method "%s::%s()"?', $argumentType, $parameter->name, $reflectionMethod->class, $reflectionMethod->name);

View file

@ -115,8 +115,6 @@ class ResolveChildDefinitionsPass extends AbstractRecursivePass
$def->setBindings($definition->getBindings() + $parentDef->getBindings());
$def->setSynthetic($definition->isSynthetic());
// overwrite with values specified in the decorator
$changes = $definition->getChanges();
if (isset($changes['class'])) {

View file

@ -28,10 +28,6 @@ class ResolveDecoratorStackPass implements CompilerPassInterface
public function __construct(string $tag = 'container.stack')
{
if (0 < \func_num_args()) {
trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
}
$this->tag = $tag;
}

View file

@ -28,10 +28,6 @@ class ResolveHotPathPass extends AbstractRecursivePass
public function __construct(string $tagName = 'container.hot_path')
{
if (0 < \func_num_args()) {
trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
}
$this->tagName = $tagName;
}

View file

@ -29,10 +29,6 @@ class ResolveNoPreloadPass extends AbstractRecursivePass
public function __construct(string $tagName = 'container.no_preload')
{
if (0 < \func_num_args()) {
trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
}
$this->tagName = $tagName;
}

View file

@ -14,7 +14,6 @@ namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
@ -48,19 +47,14 @@ final class ServiceLocatorTagPass extends AbstractRecursivePass
$value->setClass(ServiceLocator::class);
}
$services = $value->getArguments()[0] ?? null;
if ($services instanceof TaggedIteratorArgument) {
$services = $this->findAndSortTaggedServices($services, $this->container);
}
if (!\is_array($services)) {
$arguments = $value->getArguments();
if (!isset($arguments[0]) || !\is_array($arguments[0])) {
throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set.', $this->currentId));
}
$i = 0;
foreach ($services as $k => $v) {
foreach ($arguments[0] as $k => $v) {
if ($v instanceof ServiceClosureArgument) {
continue;
}
@ -69,18 +63,18 @@ final class ServiceLocatorTagPass extends AbstractRecursivePass
}
if ($i === $k) {
unset($services[$k]);
unset($arguments[0][$k]);
$k = (string) $v;
++$i;
} elseif (\is_int($k)) {
$i = null;
}
$services[$k] = new ServiceClosureArgument($v);
$arguments[0][$k] = new ServiceClosureArgument($v);
}
ksort($services);
ksort($arguments[0]);
$value->setArgument(0, $services);
$value->setArguments($arguments);
$id = '.service_locator.'.ContainerBuilder::hash($value);
@ -108,6 +102,7 @@ final class ServiceLocatorTagPass extends AbstractRecursivePass
}
$refMap[$id] = new ServiceClosureArgument($ref);
}
ksort($refMap);
$locator = (new Definition(ServiceLocator::class))
->addArgument($refMap)

View file

@ -51,7 +51,7 @@ class ServiceReferenceGraphNode
/**
* Checks if the value of this node is an Alias.
*
* @return bool
* @return bool True if the value is an Alias instance
*/
public function isAlias()
{
@ -61,7 +61,7 @@ class ServiceReferenceGraphNode
/**
* Checks if the value of this node is a Definition.
*
* @return bool
* @return bool True if the value is a Definition instance
*/
public function isDefinition()
{
@ -101,7 +101,7 @@ class ServiceReferenceGraphNode
/**
* Returns the value of this Node.
*
* @return mixed
* @return mixed The value
*/
public function getValue()
{

View file

@ -48,42 +48,46 @@ class ValidateEnvPlaceholdersPass implements CompilerPassInterface
$defaultBag = new ParameterBag($resolvingBag->all());
$envTypes = $resolvingBag->getProvidedTypes();
foreach ($resolvingBag->getEnvPlaceholders() + $resolvingBag->getUnusedEnvPlaceholders() as $env => $placeholders) {
$values = [];
if (false === $i = strpos($env, ':')) {
$default = $defaultBag->has("env($env)") ? $defaultBag->get("env($env)") : self::TYPE_FIXTURES['string'];
$defaultType = null !== $default ? get_debug_type($default) : 'string';
$values[$defaultType] = $default;
} else {
$prefix = substr($env, 0, $i);
foreach ($envTypes[$prefix] ?? ['string'] as $type) {
$values[$type] = self::TYPE_FIXTURES[$type] ?? null;
try {
foreach ($resolvingBag->getEnvPlaceholders() + $resolvingBag->getUnusedEnvPlaceholders() as $env => $placeholders) {
$values = [];
if (false === $i = strpos($env, ':')) {
$default = $defaultBag->has("env($env)") ? $defaultBag->get("env($env)") : self::TYPE_FIXTURES['string'];
$defaultType = null !== $default ? get_debug_type($default) : 'string';
$values[$defaultType] = $default;
} else {
$prefix = substr($env, 0, $i);
foreach ($envTypes[$prefix] ?? ['string'] as $type) {
$values[$type] = self::TYPE_FIXTURES[$type] ?? null;
}
}
foreach ($placeholders as $placeholder) {
BaseNode::setPlaceholder($placeholder, $values);
}
}
foreach ($placeholders as $placeholder) {
BaseNode::setPlaceholder($placeholder, $values);
$processor = new Processor();
foreach ($extensions as $name => $extension) {
if (!($extension instanceof ConfigurationExtensionInterface || $extension instanceof ConfigurationInterface)
|| !$config = array_filter($container->getExtensionConfig($name))
) {
// this extension has no semantic configuration or was not called
continue;
}
$config = $resolvingBag->resolveValue($config);
if ($extension instanceof ConfigurationInterface) {
$configuration = $extension;
} elseif (null === $configuration = $extension->getConfiguration($config, $container)) {
continue;
}
$this->extensionConfig[$name] = $processor->processConfiguration($configuration, $config);
}
}
$processor = new Processor();
foreach ($extensions as $name => $extension) {
if (!($extension instanceof ConfigurationExtensionInterface || $extension instanceof ConfigurationInterface)
|| !$config = array_filter($container->getExtensionConfig($name))
) {
// this extension has no semantic configuration or was not called
continue;
}
$config = $resolvingBag->resolveValue($config);
if ($extension instanceof ConfigurationInterface) {
$configuration = $extension;
} elseif (null === $configuration = $extension->getConfiguration($config, $container)) {
continue;
}
$this->extensionConfig[$name] = $processor->processConfiguration($configuration, $config);
} finally {
BaseNode::resetPlaceholders();
}
$resolvingBag->clearUnusedEnvPlaceholders();

View file

@ -37,6 +37,9 @@ class ContainerParametersResource implements ResourceInterface
return 'container_parameters_'.md5(serialize($this->parameters));
}
/**
* @return array Tracked parameters
*/
public function getParameters(): array
{
return $this->parameters;

View file

@ -97,7 +97,7 @@ class Container implements ContainerInterface, ResetInterface
/**
* Gets the service container parameter bag.
*
* @return ParameterBagInterface
* @return ParameterBagInterface A ParameterBagInterface instance
*/
public function getParameterBag()
{
@ -107,7 +107,7 @@ class Container implements ContainerInterface, ResetInterface
/**
* Gets a parameter.
*
* @return array|bool|string|int|float|\UnitEnum|null
* @return array|bool|string|int|float|null
*
* @throws InvalidArgumentException if the parameter is not defined
*/
@ -117,7 +117,7 @@ class Container implements ContainerInterface, ResetInterface
}
/**
* @return bool
* @return bool The presence of parameter in container
*/
public function hasParameter(string $name)
{
@ -127,8 +127,8 @@ class Container implements ContainerInterface, ResetInterface
/**
* Sets a parameter.
*
* @param string $name The parameter name
* @param array|bool|string|int|float|\UnitEnum|null $value The parameter value
* @param string $name The parameter name
* @param array|bool|string|int|float|null $value The parameter value
*/
public function setParameter(string $name, $value)
{
@ -184,9 +184,9 @@ class Container implements ContainerInterface, ResetInterface
*
* @param string $id The service identifier
*
* @return bool
* @return bool true if the service is defined, false otherwise
*/
public function has(string $id)
public function has($id)
{
if (isset($this->aliases[$id])) {
$id = $this->aliases[$id];
@ -204,7 +204,7 @@ class Container implements ContainerInterface, ResetInterface
/**
* Gets a service.
*
* @return object|null
* @return object|null The associated service
*
* @throws ServiceCircularReferenceException When a circular reference is detected
* @throws ServiceNotFoundException When the service is not defined
@ -212,7 +212,7 @@ class Container implements ContainerInterface, ResetInterface
*
* @see Reference
*/
public function get(string $id, int $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1)
public function get($id, int $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1)
{
return $this->services[$id]
?? $this->services[$id = $this->aliases[$id] ?? $id]
@ -277,7 +277,7 @@ class Container implements ContainerInterface, ResetInterface
/**
* Returns true if the given service has actually been initialized.
*
* @return bool
* @return bool true if service has already been initialized, false otherwise
*/
public function initialized(string $id)
{
@ -314,7 +314,7 @@ class Container implements ContainerInterface, ResetInterface
/**
* Gets all service ids.
*
* @return string[]
* @return string[] An array of all defined service ids
*/
public function getServiceIds()
{
@ -334,7 +334,7 @@ class Container implements ContainerInterface, ResetInterface
/**
* Camelizes a string.
*
* @return string
* @return string The camelized string
*/
public static function camelize(string $id)
{
@ -344,7 +344,7 @@ class Container implements ContainerInterface, ResetInterface
/**
* A string to underscore.
*
* @return string
* @return string The underscored string
*/
public static function underscore(string $id)
{
@ -362,7 +362,7 @@ class Container implements ContainerInterface, ResetInterface
/**
* Fetches a variable from the environment.
*
* @return mixed
* @return mixed The value to use for the provided environment variable name
*
* @throws EnvNotFoundException When the environment variable is not found and has no default value
*/

View file

@ -11,7 +11,6 @@
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;
@ -27,7 +26,6 @@ use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceLocator;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Attribute\Target;
use Symfony\Component\DependencyInjection\Compiler\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
@ -55,33 +53,30 @@ use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
class ContainerBuilder extends Container implements TaggedContainerInterface
{
/**
* @var array<string, ExtensionInterface>
* @var ExtensionInterface[]
*/
private $extensions = [];
/**
* @var array<string, ExtensionInterface>
* @var ExtensionInterface[]
*/
private $extensionsByNs = [];
/**
* @var array<string, Definition>
* @var Definition[]
*/
private $definitions = [];
/**
* @var array<string, Alias>
* @var Alias[]
*/
private $aliasDefinitions = [];
/**
* @var array<string, ResourceInterface>
* @var ResourceInterface[]
*/
private $resources = [];
/**
* @var array<string, array<array<string, mixed>>>
*/
private $extensionConfigs = [];
/**
@ -89,9 +84,6 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
*/
private $compiler;
/**
* @var bool
*/
private $trackResources;
/**
@ -129,24 +121,10 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
*/
private $vendors;
/**
* @var array<string, ChildDefinition>
*/
private $autoconfiguredInstanceof = [];
/**
* @var array<string, callable>
*/
private $autoconfiguredAttributes = [];
/**
* @var array<string, bool>
*/
private $removedIds = [];
/**
* @var array<int, bool>
*/
private $removedBindingIds = [];
private const INTERNAL_TYPES = [
@ -174,7 +152,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
}
/**
* @var array<string, \ReflectionClass>
* @var \ReflectionClass[] a list of class reflectors
*/
private $classReflectors;
@ -192,7 +170,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Checks if resources are tracked.
*
* @return bool
* @return bool true If resources are tracked, false otherwise
*/
public function isTrackingResources()
{
@ -219,7 +197,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Returns an extension by alias or namespace.
*
* @return ExtensionInterface
* @return ExtensionInterface An extension instance
*
* @throws LogicException if the extension is not registered
*/
@ -239,7 +217,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Returns all registered extensions.
*
* @return array<string, ExtensionInterface>
* @return ExtensionInterface[] An array of ExtensionInterface
*/
public function getExtensions()
{
@ -249,7 +227,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Checks if we have an extension.
*
* @return bool
* @return bool If the extension exists
*/
public function hasExtension(string $name)
{
@ -259,7 +237,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Returns an array of resources loaded to build this configuration.
*
* @return ResourceInterface[]
* @return ResourceInterface[] An array of resources
*/
public function getResources()
{
@ -287,7 +265,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Sets the resources for this configuration.
*
* @param array<string, ResourceInterface> $resources
* @param ResourceInterface[] $resources An array of resources
*
* @return $this
*/
@ -432,8 +410,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Loads the configuration for an extension.
*
* @param string $extension The extension alias or namespace
* @param array<string, mixed>|null $values An array of values that customizes the extension
* @param string $extension The extension alias or namespace
* @param array $values An array of values that customizes the extension
*
* @return $this
*
@ -446,9 +424,13 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
throw new BadMethodCallException('Cannot load from an extension on a compiled container.');
}
if (\func_num_args() < 2) {
$values = [];
}
$namespace = $this->getExtension($extension)->getAlias();
$this->extensionConfigs[$namespace][] = $values ?? [];
$this->extensionConfigs[$namespace][] = $values;
return $this;
}
@ -473,7 +455,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Returns the compiler pass config which can then be modified.
*
* @return PassConfig
* @return PassConfig The compiler pass config
*/
public function getCompilerPassConfig()
{
@ -483,7 +465,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Returns the compiler.
*
* @return Compiler
* @return Compiler The compiler
*/
public function getCompiler()
{
@ -527,15 +509,17 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
*
* @param string $id The service identifier
*
* @return bool
* @return bool true if the service is defined, false otherwise
*/
public function has(string $id)
public function has($id)
{
$id = (string) $id;
return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id);
}
/**
* @return object|null
* @return object|null The associated service
*
* @throws InvalidArgumentException when no definitions are available
* @throws ServiceCircularReferenceException When a circular reference is detected
@ -544,9 +528,9 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
*
* @see Reference
*/
public function get(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
public function get($id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
{
if ($this->isCompiled() && isset($this->removedIds[$id]) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $invalidBehavior) {
if ($this->isCompiled() && isset($this->removedIds[$id = (string) $id]) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $invalidBehavior) {
return parent::get($id);
}
@ -682,20 +666,12 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
$this->autoconfiguredInstanceof[$interface] = $childDefinition;
}
foreach ($container->getAutoconfiguredAttributes() as $attribute => $configurator) {
if (isset($this->autoconfiguredAttributes[$attribute])) {
throw new InvalidArgumentException(sprintf('"%s" has already been autoconfigured and merge() does not support merging autoconfiguration for the same attribute.', $attribute));
}
$this->autoconfiguredAttributes[$attribute] = $configurator;
}
}
/**
* Returns the configuration array for the given extension.
*
* @return array<array<string, mixed>>
* @return array An array of configuration
*/
public function getExtensionConfig(string $name)
{
@ -708,8 +684,6 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Prepends a config array to the configs of the given extension.
*
* @param array<string, mixed> $config
*/
public function prependExtensionConfig(string $name, array $config)
{
@ -792,7 +766,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Gets removed service or alias ids.
*
* @return array<string, bool>
* @return array
*/
public function getRemovedIds()
{
@ -801,8 +775,6 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Adds the service aliases.
*
* @param array<string, string|Alias> $aliases
*/
public function addAliases(array $aliases)
{
@ -813,8 +785,6 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Sets the service aliases.
*
* @param array<string, string|Alias> $aliases
*/
public function setAliases(array $aliases)
{
@ -846,7 +816,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
}
if ($alias === (string) $id) {
throw new InvalidArgumentException(sprintf('An alias cannot reference itself, got a circular reference on "%s".', $alias));
throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias));
}
unset($this->definitions[$alias], $this->removedIds[$alias]);
@ -863,7 +833,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
}
/**
* @return bool
* @return bool true if the alias exists, false otherwise
*/
public function hasAlias(string $id)
{
@ -871,7 +841,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
}
/**
* @return array<string, Alias>
* @return Alias[] An array of aliases
*/
public function getAliases()
{
@ -879,7 +849,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
}
/**
* @return Alias
* @return Alias An Alias instance
*
* @throws InvalidArgumentException if the alias does not exist
*/
@ -898,7 +868,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
* This methods allows for simple registration of service definition
* with a fluid interface.
*
* @return Definition
* @return Definition A Definition instance
*/
public function register(string $id, string $class = null)
{
@ -911,7 +881,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
* This method implements a shortcut for using setDefinition() with
* an autowired definition.
*
* @return Definition
* @return Definition The created definition
*/
public function autowire(string $id, string $class = null)
{
@ -921,7 +891,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Adds the service definitions.
*
* @param array<string, Definition> $definitions
* @param Definition[] $definitions An array of service definitions
*/
public function addDefinitions(array $definitions)
{
@ -933,7 +903,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Sets the service definitions.
*
* @param array<string, Definition> $definitions
* @param Definition[] $definitions An array of service definitions
*/
public function setDefinitions(array $definitions)
{
@ -944,7 +914,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Gets all service definitions.
*
* @return array<string, Definition>
* @return Definition[] An array of Definition instances
*/
public function getDefinitions()
{
@ -954,7 +924,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Sets a service definition.
*
* @return Definition
* @return Definition the service definition
*
* @throws BadMethodCallException When this ContainerBuilder is compiled
*/
@ -976,7 +946,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Returns true if a service definition exists under the given identifier.
*
* @return bool
* @return bool true if the service definition exists, false otherwise
*/
public function hasDefinition(string $id)
{
@ -986,7 +956,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Gets a service definition.
*
* @return Definition
* @return Definition A Definition instance
*
* @throws ServiceNotFoundException if the service definition does not exist
*/
@ -1004,7 +974,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
*
* The method "unaliases" recursively to return a Definition instance.
*
* @return Definition
* @return Definition A Definition instance
*
* @throws ServiceNotFoundException if the service definition does not exist
*/
@ -1031,7 +1001,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Creates a service for a service definition.
*
* @return mixed
* @return mixed The service described by the service definition
*
* @throws RuntimeException When the factory definition is incomplete
* @throws RuntimeException When the service is a synthetic service
@ -1159,7 +1129,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Replaces service references by the real service instance and evaluates expressions.
*
* @param mixed $value
* @param mixed $value A value
*
* @return mixed The same value with all service references replaced by
* the real service instances and all expressions evaluated
@ -1253,7 +1223,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
* }
* }
*
* @return array<string, array> An array of tags with the tagged service as key, holding a list of attribute arrays
* @return array An array of tags with the tagged service as key, holding a list of attribute arrays
*/
public function findTaggedServiceIds(string $name, bool $throwOnAbstract = false)
{
@ -1274,22 +1244,22 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Returns all tags the defined services use.
*
* @return string[]
* @return array An array of tags
*/
public function findTags()
{
$tags = [];
foreach ($this->getDefinitions() as $id => $definition) {
$tags[] = array_keys($definition->getTags());
$tags = array_merge(array_keys($definition->getTags()), $tags);
}
return array_unique(array_merge([], ...$tags));
return array_unique($tags);
}
/**
* Returns all tags not queried by findTaggedServiceIds.
*
* @return string[]
* @return string[] An array of tags
*/
public function findUnusedTags()
{
@ -1323,24 +1293,6 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
return $this->autoconfiguredInstanceof[$interface];
}
/**
* Registers an attribute that will be used for autoconfiguring annotated classes.
*
* The third argument passed to the callable is the reflector of the
* class/method/property/parameter that the attribute targets. Using one or many of
* \ReflectionClass|\ReflectionMethod|\ReflectionProperty|\ReflectionParameter as a type-hint
* for this argument allows filtering which attributes should be passed to the callable.
*
* @template T
*
* @param class-string<T> $attributeClass
* @param callable(ChildDefinition, T, \Reflector): void $configurator
*/
public function registerAttributeForAutoconfiguration(string $attributeClass, callable $configurator): void
{
$this->autoconfiguredAttributes[$attributeClass] = $configurator;
}
/**
* Registers an autowiring alias that only binds to a specific argument name.
*
@ -1351,7 +1303,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
*/
public function registerAliasForArgument(string $id, string $type, string $name = null): Alias
{
$name = (new Target($name ?? $id))->name;
$name = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name ?? $id))));
if (!preg_match('/^[a-zA-Z_\x7f-\xff]/', $name)) {
throw new InvalidArgumentException(sprintf('Invalid argument name "%s" for service "%s": the first character must be a letter.', $name, $id));
@ -1363,21 +1315,13 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
/**
* Returns an array of ChildDefinition[] keyed by interface.
*
* @return array<string, ChildDefinition>
* @return ChildDefinition[]
*/
public function getAutoconfiguredInstanceof()
{
return $this->autoconfiguredInstanceof;
}
/**
* @return array<string, callable>
*/
public function getAutoconfiguredAttributes(): array
{
return $this->autoconfiguredAttributes;
}
/**
* Resolves env parameter placeholders in a string or an array.
*
@ -1413,7 +1357,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
return $result;
}
if (!\is_string($value) || 38 > \strlen($value) || !preg_match('/env[_(]/i', $value)) {
if (!\is_string($value) || 38 > \strlen($value)) {
return $value;
}
$envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders;
@ -1476,51 +1420,9 @@ 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
{
$skipDeprecation = 3 < \func_num_args() && func_get_arg(3);
$hasRuntimeApi = class_exists(InstalledVersions::class);
if (!$hasRuntimeApi && !$skipDeprecation) {
trigger_deprecation('symfony/dependency-injection', '5.4', 'Calling "%s" when dependencies have been installed with Composer 1 is deprecated. Consider upgrading to Composer 2.', __METHOD__);
}
if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) {
return false;
}
if (!$hasRuntimeApi || !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'] ?? '';
if ('symfony/symfony' === $rootPackage) {
return true;
}
foreach ($parentPackages as $parentPackage) {
if ($rootPackage === $parentPackage || (InstalledVersions::isInstalled($parentPackage) && !InstalledVersions::isInstalled($parentPackage, false))) {
return true;
}
}
return false;
}
/**
* Gets removed binding ids.
*
* @return array<int, bool>
*
* @internal
*/
public function getRemovedBindingIds(): array
@ -1548,8 +1450,6 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
*
* @param mixed $value An array of conditionals to return
*
* @return string[]
*
* @internal
*/
public static function getServiceConditionals($value): array
@ -1572,8 +1472,6 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
*
* @param mixed $value An array of conditionals to return
*
* @return string[]
*
* @internal
*/
public static function getInitializedConditionals($value): array

View file

@ -41,29 +41,31 @@ interface ContainerInterface extends PsrContainerInterface
* @param string $id The service identifier
* @param int $invalidBehavior The behavior when the service does not exist
*
* @return object|null
* @return object|null The associated service
*
* @throws ServiceCircularReferenceException When a circular reference is detected
* @throws ServiceNotFoundException When the service is not defined
*
* @see Reference
*/
public function get(string $id, int $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE);
public function get($id, int $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE);
/**
* @return bool
* @param string $id The service identifier
*
* @return bool true if the service is defined, false otherwise
*/
public function has(string $id);
public function has($id);
/**
* Check for whether or not a service has been initialized.
*
* @return bool
* @return bool true if the service has been initialized, false otherwise
*/
public function initialized(string $id);
/**
* @return array|bool|string|int|float|\UnitEnum|null
* @return array|bool|string|int|float|null
*
* @throws InvalidArgumentException if the parameter is not defined
*/
@ -77,8 +79,8 @@ interface ContainerInterface extends PsrContainerInterface
/**
* Sets a parameter.
*
* @param string $name The parameter name
* @param array|bool|string|int|float|\UnitEnum|null $value The parameter value
* @param string $name The parameter name
* @param array|bool|string|int|float|null $value The parameter value
*/
public function setParameter(string $name, $value);
}

View file

@ -72,7 +72,7 @@ class Definition
/**
* Returns all changes tracked for the Definition object.
*
* @return array
* @return array An array of changes for this Definition
*/
public function getChanges()
{
@ -146,7 +146,7 @@ class Definition
if (null === $id) {
$this->decoratedService = null;
} else {
$this->decoratedService = [$id, $renamedId, $priority];
$this->decoratedService = [$id, $renamedId, (int) $priority];
if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
$this->decoratedService[] = $invalidBehavior;
@ -183,7 +183,7 @@ class Definition
/**
* Gets the service class.
*
* @return string|null
* @return string|null The service class
*/
public function getClass()
{
@ -265,15 +265,15 @@ class Definition
public function replaceArgument($index, $argument)
{
if (0 === \count($this->arguments)) {
throw new OutOfBoundsException(sprintf('Cannot replace arguments for class "%s" if none have been configured yet.', $this->class));
throw new OutOfBoundsException('Cannot replace arguments if none have been configured yet.');
}
if (\is_int($index) && ($index < 0 || $index > \count($this->arguments) - 1)) {
throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d] of the arguments of class "%s".', $index, \count($this->arguments) - 1, $this->class));
throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, \count($this->arguments) - 1));
}
if (!\array_key_exists($index, $this->arguments)) {
throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist in class "%s".', $index, $this->class));
throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist.', $index));
}
$this->arguments[$index] = $argument;
@ -299,7 +299,7 @@ class Definition
/**
* Gets the arguments to pass to the service constructor/factory method.
*
* @return array
* @return array The array of arguments
*/
public function getArguments()
{
@ -311,14 +311,14 @@ class Definition
*
* @param int|string $index
*
* @return mixed
* @return mixed The argument value
*
* @throws OutOfBoundsException When the argument does not exist
*/
public function getArgument($index)
{
if (!\array_key_exists($index, $this->arguments)) {
throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist in class "%s".', $index, $this->class));
throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist.', $index));
}
return $this->arguments[$index];
@ -395,7 +395,7 @@ class Definition
/**
* Gets the methods to call after service initialization.
*
* @return array
* @return array An array of method calls
*/
public function getMethodCalls()
{
@ -463,7 +463,7 @@ class Definition
/**
* Returns all tags.
*
* @return array
* @return array An array of tags
*/
public function getTags()
{
@ -473,7 +473,7 @@ class Definition
/**
* Gets a tag by name.
*
* @return array
* @return array An array of attributes
*/
public function getTag(string $name)
{
@ -543,7 +543,7 @@ class Definition
/**
* Gets the file to require before creating the service.
*
* @return string|null
* @return string|null The full pathname to include
*/
public function getFile()
{
@ -812,7 +812,7 @@ class Definition
/**
* Gets the configurator to call after the service is fully initialized.
*
* @return string|array|null
* @return callable|array|null
*/
public function getConfigurator()
{
@ -846,7 +846,7 @@ class Definition
/**
* Gets bindings.
*
* @return BoundArgument[]
* @return array|BoundArgument[]
*/
public function getBindings()
{

View file

@ -21,7 +21,7 @@ interface DumperInterface
/**
* Dumps the service container.
*
* @return string|array
* @return string|array The representation of the service container
*/
public function dump(array $options = []);
}

View file

@ -54,7 +54,7 @@ class GraphvizDumper extends Dumper
* * node.definition: The default options for services that are defined via service definition instances
* * node.missing: The default options for missing services
*
* @return string
* @return string The dot representation of the service container
*/
public function dump(array $options = [])
{
@ -130,22 +130,23 @@ class GraphvizDumper extends Dumper
$lazyEdge = $lazy || $this->container->getDefinition((string) $argument)->isLazy();
}
$edges[] = [['name' => $name, 'required' => $required, 'to' => $argument, 'lazy' => $lazyEdge]];
$edges[] = ['name' => $name, 'required' => $required, 'to' => $argument, 'lazy' => $lazyEdge];
} elseif ($argument instanceof ArgumentInterface) {
$edges[] = $this->findEdges($id, $argument->getValues(), $required, $name, true);
$edges = array_merge($edges, $this->findEdges($id, $argument->getValues(), $required, $name, true));
} elseif ($argument instanceof Definition) {
$edges[] = $this->findEdges($id, $argument->getArguments(), $required, '');
$edges[] = $this->findEdges($id, $argument->getProperties(), false, '');
$edges = array_merge($edges,
$this->findEdges($id, $argument->getArguments(), $required, ''),
$this->findEdges($id, $argument->getProperties(), false, '')
);
foreach ($argument->getMethodCalls() as $call) {
$edges[] = $this->findEdges($id, $call[1], false, $call[0].'()');
$edges = array_merge($edges, $this->findEdges($id, $call[1], false, $call[0].'()'));
}
} elseif (\is_array($argument)) {
$edges[] = $this->findEdges($id, $argument, $required, $name, $lazy);
$edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name, $lazy));
}
}
return array_merge([], ...$edges);
return $edges;
}
private function findNodes(): array

View file

@ -62,9 +62,6 @@ class PhpDumper extends Dumper
*/
public const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_';
/**
* @var \SplObjectStorage<Definition, Variable>|null
*/
private $definitionVariables;
private $referenceVariables;
private $variableCount;
@ -222,7 +219,7 @@ class PhpDumper extends Dumper
}
$code =
$this->startClass($options['class'], $baseClass, $this->inlineFactories && $proxyClasses).
$this->startClass($options['class'], $baseClass).
$this->addServices($services).
$this->addDeprecatedAliases().
$this->addDefaultParametersMethod()
@ -286,15 +283,14 @@ EOF;
$code .= $this->endClass();
if ($this->inlineFactories && $proxyClasses) {
$files['proxy-classes.php'] = "<?php\n\n";
if ($this->inlineFactories) {
foreach ($proxyClasses as $c) {
$files['proxy-classes.php'] .= $c;
$code .= $c;
}
}
$files[$options['class'].'.php'] = $code;
$preloadedFiles[$options['class'].'.php'] = $options['class'].'.php';
$hash = ucfirst(strtr(ContainerBuilder::hash($files), '._', 'xx'));
$code = [];
@ -314,9 +310,7 @@ EOF;
$autoloadFile = trim($this->export($autoloadFile), '()\\');
$preloadedFiles = array_reverse($preloadedFiles);
if ('' !== $preloadedFiles = implode("';\nrequire __DIR__.'/", $preloadedFiles)) {
$preloadedFiles = "require __DIR__.'/$preloadedFiles';\n";
}
$preloadedFiles = implode("';\nrequire __DIR__.'/", $preloadedFiles);
$code[$options['class'].'.preload.php'] = <<<EOF
<?php
@ -331,8 +325,8 @@ if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) {
}
require $autoloadFile;
(require __DIR__.'/{$options['class']}.php')->set(\\Container{$hash}\\{$options['class']}::class, null);
$preloadedFiles
require __DIR__.'/$preloadedFiles';
\$classes = [];
EOF;
@ -341,14 +335,14 @@ EOF;
if (!$class || str_contains($class, '$') || \in_array($class, ['int', 'float', 'string', 'bool', 'resource', 'object', 'array', 'null', 'callable', 'iterable', 'mixed', 'void'], true)) {
continue;
}
if (!(class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) || ((new \ReflectionClass($class))->isUserDefined() && !\in_array($class, ['Attribute', 'JsonException', 'ReturnTypeWillChange', 'Stringable', 'UnhandledMatchError', 'ValueError'], true))) {
if (!(class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) || (new \ReflectionClass($class))->isUserDefined()) {
$code[$options['class'].'.preload.php'] .= sprintf("\$classes[] = '%s';\n", $class);
}
}
$code[$options['class'].'.preload.php'] .= <<<'EOF'
$preloaded = Preloader::preload($classes);
Preloader::preload($classes);
EOF;
}
@ -745,8 +739,8 @@ EOF;
$calls = '';
foreach ($definition->getMethodCalls() as $k => $call) {
$arguments = [];
foreach ($call[1] as $i => $value) {
$arguments[] = (\is_string($i) ? $i.': ' : '').$this->dumpValue($value);
foreach ($call[1] as $value) {
$arguments[] = $this->dumpValue($value);
}
$witherAssignation = '';
@ -1138,8 +1132,8 @@ EOTXT
}
$arguments = [];
foreach ($definition->getArguments() as $i => $value) {
$arguments[] = (\is_string($i) ? $i.': ' : '').$this->dumpValue($value);
foreach ($definition->getArguments() as $value) {
$arguments[] = $this->dumpValue($value);
}
if (null !== $definition->getFactory()) {
@ -1182,7 +1176,7 @@ EOTXT
return $return.sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments)).$tail;
}
private function startClass(string $class, string $baseClass, bool $hasProxyClasses): string
private function startClass(string $class, string $baseClass): string
{
$namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
@ -1242,7 +1236,7 @@ EOF;
$code .= $this->addMethodMap();
$code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : '';
$code .= $this->addAliases();
$code .= $this->addInlineRequires($hasProxyClasses);
$code .= $this->addInlineRequires();
$code .= <<<EOF
}
@ -1454,12 +1448,15 @@ EOF;
return $code;
}
private function addInlineRequires(bool $hasProxyClasses): string
private function addInlineRequires(): string
{
$lineage = [];
$hotPathServices = $this->hotPathTag && $this->inlineRequires ? $this->container->findTaggedServiceIds($this->hotPathTag) : [];
if (!$this->hotPathTag || !$this->inlineRequires) {
return '';
}
foreach ($hotPathServices as $id => $tags) {
$lineage = [];
foreach ($this->container->findTaggedServiceIds($this->hotPathTag) as $id => $tags) {
$definition = $this->container->getDefinition($id);
if ($this->getProxyDumper()->isProxyCandidate($definition)) {
@ -1484,10 +1481,6 @@ EOF;
}
}
if ($hasProxyClasses) {
$code .= "\n include_once __DIR__.'/proxy-classes.php';";
}
return $code ? sprintf("\n \$this->privates['service_container'] = function () {%s\n };\n", $code) : '';
}
@ -1504,11 +1497,10 @@ EOF;
if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) {
throw new InvalidArgumentException(sprintf('Parameter name cannot use env parameters: "%s".', $resolvedKey));
}
$hasEnum = false;
$export = $this->exportParameters([$value], '', 12, $hasEnum);
$export = $this->exportParameters([$value]);
$export = explode('0 => ', substr(rtrim($export, " ]\n"), 2, -1), 2);
if ($hasEnum || preg_match("/\\\$this->(?:getEnv\('(?:[-.\w]*+:)*+\w++'\)|targetDir\.'')/", $export[1])) {
if (preg_match("/\\\$this->(?:getEnv\('(?:[-.\w]*+:)*+\w++'\)|targetDir\.'')/", $export[1])) {
$dynamicPhp[$key] = sprintf('%scase %s: $value = %s; break;', $export[0], $this->export($key), $export[1]);
} else {
$php[] = sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]);
@ -1519,7 +1511,7 @@ EOF;
$code = <<<'EOF'
/**
* @return array|bool|float|int|string|\UnitEnum|null
* @return array|bool|float|int|string|null
*/
public function getParameter(string $name)
{
@ -1612,12 +1604,12 @@ EOF;
/**
* @throws InvalidArgumentException
*/
private function exportParameters(array $parameters, string $path = '', int $indent = 12, bool &$hasEnum = false): string
private function exportParameters(array $parameters, string $path = '', int $indent = 12): string
{
$php = [];
foreach ($parameters as $key => $value) {
if (\is_array($value)) {
$value = $this->exportParameters($value, $path.'/'.$key, $indent + 4, $hasEnum);
$value = $this->exportParameters($value, $path.'/'.$key, $indent + 4);
} elseif ($value instanceof ArgumentInterface) {
throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain special arguments. "%s" found in "%s".', get_debug_type($value), $path.'/'.$key));
} elseif ($value instanceof Variable) {
@ -1628,9 +1620,6 @@ EOF;
throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain references to other services (reference to service "%s" found in "%s").', $value, $path.'/'.$key));
} elseif ($value instanceof Expression) {
throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path.'/'.$key));
} elseif ($value instanceof \UnitEnum) {
$hasEnum = true;
$value = sprintf('\%s::%s', \get_class($value), $value->name);
} else {
$value = $this->export($value);
}
@ -1762,7 +1751,7 @@ EOF;
$returnedType = '';
if ($value instanceof TypedReference) {
$returnedType = sprintf(': %s\%s', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $value->getInvalidBehavior() ? '' : '?', str_replace(['|', '&'], ['|\\', '&\\'], $value->getType()));
$returnedType = sprintf(': %s\%s', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $value->getInvalidBehavior() ? '' : '?', $value->getType());
}
$code = sprintf('return %s;', $code);

View file

@ -34,10 +34,10 @@ final class Preloader
$classes[] = sprintf("\$classes[] = %s;\n", var_export($item, true));
}
file_put_contents($file, sprintf("\n\$classes = [];\n%s\$preloaded = Preloader::preload(\$classes, \$preloaded);\n", implode('', $classes)), \FILE_APPEND);
file_put_contents($file, sprintf("\n\$classes = [];\n%sPreloader::preload(\$classes);\n", implode('', $classes)), \FILE_APPEND);
}
public static function preload(array $classes, array $preloaded = []): array
public static function preload(array $classes): void
{
set_error_handler(function ($t, $m, $f, $l) {
if (error_reporting() & $t) {
@ -50,6 +50,7 @@ final class Preloader
});
$prev = [];
$preloaded = [];
try {
while ($prev !== $classes) {
@ -64,8 +65,6 @@ final class Preloader
} finally {
restore_error_handler();
}
return $preloaded;
}
private static function doPreload(string $class, array &$preloaded): void
@ -77,10 +76,6 @@ final class Preloader
$preloaded[$class] = true;
try {
if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) {
return;
}
$r = new \ReflectionClass($class);
if ($r->isInternal()) {

View file

@ -40,7 +40,7 @@ class XmlDumper extends Dumper
/**
* Dumps the service container as an XML string.
*
* @return string
* @return string An xml string representing of the service container
*/
public function dump(array $options = [])
{
@ -143,7 +143,7 @@ class XmlDumper extends Dumper
$tag->appendChild($this->document->createTextNode($name));
}
foreach ($attributes as $key => $value) {
$tag->setAttribute($key, $value ?? '');
$tag->setAttribute($key, $value);
}
$service->appendChild($tag);
}
@ -268,7 +268,7 @@ class XmlDumper extends Dumper
private function convertParameters(array $parameters, string $type, \DOMElement $parent, string $keyAttribute = 'key')
{
$withKeys = !array_is_list($parameters);
$withKeys = array_keys($parameters) !== range(0, \count($parameters) - 1);
foreach ($parameters as $key => $value) {
$element = $this->document->createElement($type);
if ($withKeys) {

View file

@ -42,7 +42,7 @@ class YamlDumper extends Dumper
/**
* Dumps the service container as an YAML string.
*
* @return string
* @return string A YAML string representing of the service container
*/
public function dump(array $options = [])
{

View file

@ -41,7 +41,6 @@ class EnvVarProcessor implements EnvVarProcessorInterface
return [
'base64' => 'string',
'bool' => 'bool',
'not' => 'bool',
'const' => 'bool|int|float|string|array',
'csv' => 'array',
'file' => 'string',
@ -192,10 +191,8 @@ class EnvVarProcessor implements EnvVarProcessorInterface
return (string) $env;
}
if (\in_array($prefix, ['bool', 'not'], true)) {
$env = (bool) (filter_var($env, \FILTER_VALIDATE_BOOLEAN) ?: filter_var($env, \FILTER_VALIDATE_INT) ?: filter_var($env, \FILTER_VALIDATE_FLOAT));
return 'not' === $prefix ? !$env : $env;
if ('bool' === $prefix) {
return (bool) (filter_var($env, \FILTER_VALIDATE_BOOLEAN) ?: filter_var($env, \FILTER_VALIDATE_INT) ?: filter_var($env, \FILTER_VALIDATE_FLOAT));
}
if ('int' === $prefix) {
@ -258,8 +255,10 @@ class EnvVarProcessor implements EnvVarProcessorInterface
'fragment' => null,
];
// remove the '/' separator
$parsedEnv['path'] = '/' === ($parsedEnv['path'] ?? '/') ? '' : substr($parsedEnv['path'], 1);
if (null !== $parsedEnv['path']) {
// remove the '/' separator
$parsedEnv['path'] = '/' === $parsedEnv['path'] ? null : substr($parsedEnv['path'], 1);
}
return $parsedEnv;
}
@ -272,17 +271,11 @@ class EnvVarProcessor implements EnvVarProcessorInterface
}
if ('resolve' === $prefix) {
return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name, $getEnv) {
return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name) {
if (!isset($match[1])) {
return '%';
}
if (str_starts_with($match[1], 'env(') && str_ends_with($match[1], ')') && 'env()' !== $match[1]) {
$value = $getEnv(substr($match[1], 4, -1));
} else {
$value = $this->container->getParameter($match[1]);
}
$value = $this->container->getParameter($match[1]);
if (!is_scalar($value)) {
throw new RuntimeException(sprintf('Parameter "%s" found when resolving env var "%s" must be scalar, "%s" given.', $match[1], $name, get_debug_type($value)));
}

View file

@ -24,7 +24,7 @@ interface ConfigurationExtensionInterface
/**
* Returns extension configuration.
*
* @return ConfigurationInterface|null
* @return ConfigurationInterface|null The configuration or null
*/
public function getConfiguration(array $config, ContainerBuilder $container);
}

View file

@ -60,7 +60,7 @@ abstract class Extension implements ExtensionInterface, ConfigurationExtensionIn
*
* This can be overridden in a sub-class to specify the alias manually.
*
* @return string
* @return string The alias
*
* @throws BadMethodCallException When the extension name does not follow conventions
*/
@ -124,7 +124,7 @@ abstract class Extension implements ExtensionInterface, ConfigurationExtensionIn
}
/**
* @return bool
* @return bool Whether the configuration is enabled
*
* @throws InvalidArgumentException When the config is not enableable
*/

View file

@ -30,7 +30,7 @@ interface ExtensionInterface
/**
* Returns the namespace to be used for this extension (XML namespace).
*
* @return string
* @return string The XML namespace
*/
public function getNamespace();
@ -46,7 +46,7 @@ interface ExtensionInterface
*
* This alias is also the mandatory prefix to use when using YAML.
*
* @return string
* @return string The alias
*/
public function getAlias();
}

View file

@ -1,4 +1,4 @@
Copyright (c) 2004-2022 Fabien Potencier
Copyright (c) 2004-2021 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -70,8 +70,6 @@ class ProxyHelper
}
}
sort($types);
return $types ? implode($glue, $types) : null;
}
}

View file

@ -25,10 +25,9 @@ class ClosureLoader extends Loader
{
private $container;
public function __construct(ContainerBuilder $container, string $env = null)
public function __construct(ContainerBuilder $container)
{
$this->container = $container;
parent::__construct($env);
}
/**
@ -36,7 +35,7 @@ class ClosureLoader extends Loader
*/
public function load($resource, string $type = null)
{
return $resource($this->container, $this->env);
$resource($this->container);
}
/**

View file

@ -11,10 +11,8 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use Symfony\Component\Config\Loader\ParamConfigurator;
use Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Parameter;
@ -78,9 +76,7 @@ abstract class AbstractConfigurator
}
if ($value instanceof ReferenceConfigurator) {
$reference = new Reference($value->id, $value->invalidBehavior);
return $value instanceof ClosureReferenceConfigurator ? new ServiceClosureArgument($reference) : $reference;
return new Reference($value->id, $value->invalidBehavior);
}
if ($value instanceof InlineServiceConfigurator) {
@ -90,10 +86,6 @@ abstract class AbstractConfigurator
return $def;
}
if ($value instanceof ParamConfigurator) {
return (string) $value;
}
if ($value instanceof self) {
throw new InvalidArgumentException(sprintf('"%s()" can be used only at the root of service configuration files.', $value::FACTORY));
}

View file

@ -32,8 +32,8 @@ abstract class AbstractServiceConfigurator extends AbstractConfigurator
{
// default tags should be added last
foreach ($this->defaultTags as $name => $attributes) {
foreach ($attributes as $attribute) {
$this->definition->addTag($name, $attribute);
foreach ($attributes as $attributes) {
$this->definition->addTag($name, $attributes);
}
}
$this->defaultTags = [];
@ -81,16 +81,6 @@ abstract class AbstractServiceConfigurator extends AbstractConfigurator
return $this->parent->get($id);
}
/**
* Removes an already defined service definition or alias.
*/
final public function remove(string $id): ServicesConfigurator
{
$this->__destruct();
return $this->parent->remove($id);
}
/**
* Registers a stack of decorator services.
*

View file

@ -1,16 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
class ClosureReferenceConfigurator extends ReferenceConfigurator
{
}

View file

@ -11,7 +11,6 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use Symfony\Component\Config\Loader\ParamConfigurator;
use Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
@ -36,16 +35,14 @@ class ContainerConfigurator extends AbstractConfigurator
private $path;
private $file;
private $anonymousCount = 0;
private $env;
public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path, string $file, string $env = null)
public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path, string $file)
{
$this->container = $container;
$this->loader = $loader;
$this->instanceof = &$instanceof;
$this->path = $path;
$this->file = $file;
$this->env = $env;
}
final public function extension(string $namespace, array $config)
@ -74,14 +71,6 @@ class ContainerConfigurator extends AbstractConfigurator
return new ServicesConfigurator($this->container, $this->loader, $this->instanceof, $this->path, $this->anonymousCount);
}
/**
* Get the current environment to be able to write conditional configuration.
*/
final public function env(): ?string
{
return $this->env;
}
/**
* @return static
*/
@ -98,9 +87,9 @@ class ContainerConfigurator extends AbstractConfigurator
/**
* Creates a parameter.
*/
function param(string $name): ParamConfigurator
function param(string $name): string
{
return new ParamConfigurator($name);
return '%'.$name.'%';
}
/**
@ -174,9 +163,9 @@ function tagged_iterator(string $tag, string $indexAttribute = null, string $def
/**
* Creates a service locator by tag name.
*/
function tagged_locator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, string $defaultPriorityMethod = null): ServiceLocatorArgument
function tagged_locator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null): ServiceLocatorArgument
{
return new ServiceLocatorArgument(new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, true, $defaultPriorityMethod));
return new ServiceLocatorArgument(new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, true));
}
/**
@ -194,19 +183,3 @@ function abstract_arg(string $description): AbstractArgument
{
return new AbstractArgument($description);
}
/**
* Creates an environment variable reference.
*/
function env(string $name): EnvConfigurator
{
return new EnvConfigurator($name);
}
/**
* Creates a closure service reference.
*/
function service_closure(string $serviceId): ClosureReferenceConfigurator
{
return new ClosureReferenceConfigurator($serviceId);
}

View file

@ -1,224 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use Symfony\Component\Config\Loader\ParamConfigurator;
class EnvConfigurator extends ParamConfigurator
{
/**
* @var string[]
*/
private $stack;
public function __construct(string $name)
{
$this->stack = explode(':', $name);
}
public function __toString(): string
{
return '%env('.implode(':', $this->stack).')%';
}
/**
* @return $this
*/
public function __call(string $name, array $arguments): self
{
$processor = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1_\2', $name));
$this->custom($processor, ...$arguments);
return $this;
}
/**
* @return $this
*/
public function custom(string $processor, ...$args): self
{
array_unshift($this->stack, $processor, ...$args);
return $this;
}
/**
* @return $this
*/
public function base64(): self
{
array_unshift($this->stack, 'base64');
return $this;
}
/**
* @return $this
*/
public function bool(): self
{
array_unshift($this->stack, 'bool');
return $this;
}
/**
* @return $this
*/
public function not(): self
{
array_unshift($this->stack, 'not');
return $this;
}
/**
* @return $this
*/
public function const(): self
{
array_unshift($this->stack, 'const');
return $this;
}
/**
* @return $this
*/
public function csv(): self
{
array_unshift($this->stack, 'csv');
return $this;
}
/**
* @return $this
*/
public function file(): self
{
array_unshift($this->stack, 'file');
return $this;
}
/**
* @return $this
*/
public function float(): self
{
array_unshift($this->stack, 'float');
return $this;
}
/**
* @return $this
*/
public function int(): self
{
array_unshift($this->stack, 'int');
return $this;
}
/**
* @return $this
*/
public function json(): self
{
array_unshift($this->stack, 'json');
return $this;
}
/**
* @return $this
*/
public function key(string $key): self
{
array_unshift($this->stack, 'key', $key);
return $this;
}
/**
* @return $this
*/
public function url(): self
{
array_unshift($this->stack, 'url');
return $this;
}
/**
* @return $this
*/
public function queryString(): self
{
array_unshift($this->stack, 'query_string');
return $this;
}
/**
* @return $this
*/
public function resolve(): self
{
array_unshift($this->stack, 'resolve');
return $this;
}
/**
* @return $this
*/
public function default(string $fallbackParam): self
{
array_unshift($this->stack, 'default', $fallbackParam);
return $this;
}
/**
* @return $this
*/
public function string(): self
{
array_unshift($this->stack, 'string');
return $this;
}
/**
* @return $this
*/
public function trim(): self
{
array_unshift($this->stack, 'trim');
return $this;
}
/**
* @return $this
*/
public function require(): self
{
array_unshift($this->stack, 'require');
return $this;
}
}

View file

@ -12,8 +12,6 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\ExpressionLanguage\Expression;
/**
* @author Nicolas Grekas <p@tchwork.com>
@ -36,10 +34,6 @@ class ParametersConfigurator extends AbstractConfigurator
*/
final public function set(string $name, $value): self
{
if ($value instanceof Expression) {
throw new InvalidArgumentException(sprintf('Using an expression in parameter "%s" is not allowed.', $name));
}
$this->container->setParameter($name, static::processValue($value, true));
return $this;

View file

@ -45,7 +45,6 @@ class ServiceConfigurator extends AbstractServiceConfigurator
private $instanceof;
private $allowParent;
private $path;
private $destructed = false;
public function __construct(ContainerBuilder $container, array $instanceof, bool $allowParent, ServicesConfigurator $parent, Definition $definition, ?string $id, array $defaultTags, string $path = null)
{
@ -59,11 +58,6 @@ class ServiceConfigurator extends AbstractServiceConfigurator
public function __destruct()
{
if ($this->destructed) {
return;
}
$this->destructed = true;
parent::__destruct();
$this->container->removeBindings($this->id);

View file

@ -96,19 +96,6 @@ class ServicesConfigurator extends AbstractConfigurator
return null !== $class ? $configurator->class($class) : $configurator;
}
/**
* Removes an already defined service definition or alias.
*
* @return $this
*/
final public function remove(string $id): self
{
$this->container->removeDefinition($id);
$this->container->removeAlias($id);
return $this;
}
/**
* Creates an alias.
*/

View file

@ -12,8 +12,10 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Loader\Configurator\DefaultsConfigurator;
use Symfony\Component\DependencyInjection\Loader\Configurator\InstanceofConfigurator;
use Symfony\Component\DependencyInjection\Reference;
trait BindTrait
{
@ -32,6 +34,9 @@ trait BindTrait
final public function bind(string $nameOrFqcn, $valueOrRef): self
{
$valueOrRef = static::processValue($valueOrRef, true);
if (!preg_match('/^(?:(?:array|bool|float|int|string|iterable)[ \t]*+)?\$/', $nameOrFqcn) && !$valueOrRef instanceof Reference) {
throw new InvalidArgumentException(sprintf('Invalid binding for service "%s": named arguments must start with a "$", and FQCN must map to references. Neither applies to binding "%s".', $this->id, $nameOrFqcn));
}
$bindings = $this->definition->getBindings();
$type = $this instanceof DefaultsConfigurator ? BoundArgument::DEFAULTS_BINDING : ($this instanceof InstanceofConfigurator ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING);
$bindings[$nameOrFqcn] = new BoundArgument($valueOrRef, true, $type, $this->path ?? null);

View file

@ -38,8 +38,6 @@ class DirectoryLoader extends FileLoader
$this->import($dir, null, false, $path);
}
}
return null;
}
/**

View file

@ -17,9 +17,7 @@ use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Config\Resource\GlobResource;
use Symfony\Component\DependencyInjection\Attribute\When;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\RegisterAutoconfigureAttributesPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
@ -40,11 +38,11 @@ abstract class FileLoader extends BaseFileLoader
protected $singlyImplemented = [];
protected $autoRegisterAliasesForSinglyImplementedInterfaces = true;
public function __construct(ContainerBuilder $container, FileLocatorInterface $locator, string $env = null)
public function __construct(ContainerBuilder $container, FileLocatorInterface $locator)
{
$this->container = $container;
parent::__construct($locator, $env);
parent::__construct($locator);
}
/**
@ -52,7 +50,7 @@ abstract class FileLoader extends BaseFileLoader
*
* @param bool|string $ignoreErrors Whether errors should be ignored; pass "not_found" to ignore only when the loaded resource is not found
*/
public function import($resource, string $type = null, $ignoreErrors = false, string $sourceResource = null, $exclude = null)
public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null, $exclude = null)
{
$args = \func_get_args();
@ -63,7 +61,7 @@ abstract class FileLoader extends BaseFileLoader
}
try {
return parent::import(...$args);
parent::import(...$args);
} catch (LoaderLoadException $e) {
if (!$ignoreNotFound || !($prev = $e->getPrevious()) instanceof FileLocatorFileNotFoundException) {
throw $e;
@ -79,8 +77,6 @@ abstract class FileLoader extends BaseFileLoader
throw $e;
}
}
return null;
}
/**
@ -91,7 +87,7 @@ abstract class FileLoader extends BaseFileLoader
* @param string $resource The directory to look for classes, glob-patterns allowed
* @param string|string[]|null $exclude A globbed path of files to exclude or an array of globbed paths of files to exclude
*/
public function registerClasses(Definition $prototype, string $namespace, string $resource, $exclude = null)
public function registerClasses(Definition $prototype, $namespace, $resource, $exclude = null)
{
if (!str_ends_with($namespace, '\\')) {
throw new InvalidArgumentException(sprintf('Namespace prefix must end with a "\\": "%s".', $namespace));
@ -100,27 +96,11 @@ abstract class FileLoader extends BaseFileLoader
throw new InvalidArgumentException(sprintf('Namespace is not a valid PSR-4 prefix: "%s".', $namespace));
}
$autoconfigureAttributes = new RegisterAutoconfigureAttributesPass();
$autoconfigureAttributes = $autoconfigureAttributes->accept($prototype) ? $autoconfigureAttributes : null;
$classes = $this->findClasses($namespace, $resource, (array) $exclude, $autoconfigureAttributes);
$classes = $this->findClasses($namespace, $resource, (array) $exclude);
// prepare for deep cloning
$serializedPrototype = serialize($prototype);
foreach ($classes as $class => $errorMessage) {
if (null === $errorMessage && $autoconfigureAttributes && $this->env) {
$r = $this->container->getReflectionClass($class);
$attribute = null;
foreach ($r->getAttributes(When::class) as $attribute) {
if ($this->env === $attribute->newInstance()->env) {
$attribute = null;
break;
}
}
if (null !== $attribute) {
continue;
}
}
if (interface_exists($class, false)) {
$this->interfaces[] = $class;
} else {
@ -154,8 +134,10 @@ abstract class FileLoader extends BaseFileLoader
/**
* Registers a definition in the container with its instanceof-conditionals.
*
* @param string $id
*/
protected function setDefinition(string $id, Definition $definition)
protected function setDefinition($id, Definition $definition)
{
$this->container->removeBindings($id);
@ -169,7 +151,7 @@ abstract class FileLoader extends BaseFileLoader
}
}
private function findClasses(string $namespace, string $pattern, array $excludePatterns, ?RegisterAutoconfigureAttributesPass $autoconfigureAttributes): array
private function findClasses(string $namespace, string $pattern, array $excludePatterns): array
{
$parameterBag = $this->container->getParameterBag();
@ -227,10 +209,6 @@ abstract class FileLoader extends BaseFileLoader
if ($r->isInstantiable() || $r->isInterface()) {
$classes[$class] = null;
}
if ($autoconfigureAttributes && !$r->isInstantiable()) {
$autoconfigureAttributes->processClass($this->container, $r);
}
}
// track only for new & removed files

View file

@ -28,8 +28,6 @@ class GlobFileLoader extends FileLoader
}
$this->container->addResource($globResource);
return null;
}
/**

View file

@ -44,14 +44,6 @@ class IniFileLoader extends FileLoader
$this->container->setParameter($key, $this->phpize($value));
}
}
if ($this->env && \is_array($result['parameters@'.$this->env] ?? null)) {
foreach ($result['parameters@'.$this->env] as $key => $value) {
$this->container->setParameter($key, $this->phpize($value));
}
}
return null;
}
/**

View file

@ -11,16 +11,6 @@
namespace Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\Config\Builder\ConfigBuilderGenerator;
use Symfony\Component\Config\Builder\ConfigBuilderGeneratorInterface;
use Symfony\Component\Config\Builder\ConfigBuilderInterface;
use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\DependencyInjection\Attribute\When;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
/**
@ -34,18 +24,11 @@ use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigura
class PhpFileLoader extends FileLoader
{
protected $autoRegisterAliasesForSinglyImplementedInterfaces = false;
private $generator;
public function __construct(ContainerBuilder $container, FileLocatorInterface $locator, string $env = null, ConfigBuilderGeneratorInterface $generator = null)
{
parent::__construct($container, $locator, $env);
$this->generator = $generator;
}
/**
* {@inheritdoc}
*/
public function load($resource, string $type = null)
public function load($resource, $type = null)
{
// the container and loader variables are exposed to the included file below
$container = $this->container;
@ -56,22 +39,20 @@ class PhpFileLoader extends FileLoader
$this->container->fileExists($path);
// the closure forbids access to the private scope in the included file
$load = \Closure::bind(function ($path, $env) use ($container, $loader, $resource, $type) {
$load = \Closure::bind(function ($path) use ($container, $loader, $resource, $type) {
return include $path;
}, $this, ProtectedPhpFileLoader::class);
try {
$callback = $load($path, $this->env);
$callback = $load($path);
if (\is_object($callback) && \is_callable($callback)) {
$this->executeCallback($callback, new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource, $this->env), $path);
$callback(new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource), $this->container, $this);
}
} finally {
$this->instanceof = [];
$this->registerAliasesForSinglyImplementedInterfaces();
}
return null;
}
/**
@ -89,118 +70,6 @@ class PhpFileLoader extends FileLoader
return 'php' === $type;
}
/**
* Resolve the parameters to the $callback and execute it.
*/
private function executeCallback(callable $callback, ContainerConfigurator $containerConfigurator, string $path)
{
if (!$callback instanceof \Closure) {
$callback = \Closure::fromCallable($callback);
}
$arguments = [];
$configBuilders = [];
$r = new \ReflectionFunction($callback);
if (\PHP_VERSION_ID >= 80000) {
$attribute = null;
foreach ($r->getAttributes(When::class) as $attribute) {
if ($this->env === $attribute->newInstance()->env) {
$attribute = null;
break;
}
}
if (null !== $attribute) {
return;
}
}
foreach ($r->getParameters() as $parameter) {
$reflectionType = $parameter->getType();
if (!$reflectionType instanceof \ReflectionNamedType) {
throw new \InvalidArgumentException(sprintf('Could not resolve argument "$%s" for "%s". You must typehint it (for example with "%s" or "%s").', $parameter->getName(), $path, ContainerConfigurator::class, ContainerBuilder::class));
}
$type = $reflectionType->getName();
switch ($type) {
case ContainerConfigurator::class:
$arguments[] = $containerConfigurator;
break;
case ContainerBuilder::class:
$arguments[] = $this->container;
break;
case FileLoader::class:
case self::class:
$arguments[] = $this;
break;
default:
try {
$configBuilder = $this->configBuilder($type);
} catch (InvalidArgumentException|\LogicException $e) {
throw new \InvalidArgumentException(sprintf('Could not resolve argument "%s" for "%s".', $type.' $'.$parameter->getName(), $path), 0, $e);
}
$configBuilders[] = $configBuilder;
$arguments[] = $configBuilder;
}
}
// Force load ContainerConfigurator to make env(), param() etc available.
class_exists(ContainerConfigurator::class);
$callback(...$arguments);
/** @var ConfigBuilderInterface $configBuilder */
foreach ($configBuilders as $configBuilder) {
$containerConfigurator->extension($configBuilder->getExtensionAlias(), $configBuilder->toArray());
}
}
/**
* @param string $namespace FQCN string for a class implementing ConfigBuilderInterface
*/
private function configBuilder(string $namespace): ConfigBuilderInterface
{
if (!class_exists(ConfigBuilderGenerator::class)) {
throw new \LogicException('You cannot use the config builder as the Config component is not installed. Try running "composer require symfony/config".');
}
if (null === $this->generator) {
throw new \LogicException('You cannot use the ConfigBuilders without providing a class implementing ConfigBuilderGeneratorInterface.');
}
// If class exists and implements ConfigBuilderInterface
if (class_exists($namespace) && is_subclass_of($namespace, ConfigBuilderInterface::class)) {
return new $namespace();
}
// If it does not start with Symfony\Config\ we dont know how to handle this
if ('Symfony\\Config\\' !== substr($namespace, 0, 15)) {
throw new InvalidArgumentException(sprintf('Could not find or generate class "%s".', $namespace));
}
// Try to get the extension alias
$alias = Container::underscore(substr($namespace, 15, -6));
if (false !== strpos($alias, '\\')) {
throw new InvalidArgumentException('You can only use "root" ConfigBuilders from "Symfony\\Config\\" namespace. Nested classes like "Symfony\\Config\\Framework\\CacheConfig" cannot be used.');
}
if (!$this->container->hasExtension($alias)) {
$extensions = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getAlias(); }, $this->container->getExtensions()));
throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s". Looked for namespace "%s", found "%s".', $namespace, $alias, $extensions ? implode('", "', $extensions) : 'none'));
}
$extension = $this->container->getExtension($alias);
if (!$extension instanceof ConfigurationExtensionInterface) {
throw new \LogicException(sprintf('You cannot use the config builder for "%s" because the extension does not implement "%s".', $namespace, ConfigurationExtensionInterface::class));
}
$configuration = $extension->getConfiguration([], $this->container);
$loader = $this->generator->build($configuration);
return $loader();
}
}
/**

View file

@ -51,44 +51,23 @@ class XmlFileLoader extends FileLoader
$this->container->fileExists($path);
$this->loadXml($xml, $path);
if ($this->env) {
$xpath = new \DOMXPath($xml);
$xpath->registerNamespace('container', self::NS);
foreach ($xpath->query(sprintf('//container:when[@env="%s"]', $this->env)) ?: [] as $root) {
$env = $this->env;
$this->env = null;
try {
$this->loadXml($xml, $path, $root);
} finally {
$this->env = $env;
}
}
}
return null;
}
private function loadXml(\DOMDocument $xml, string $path, \DOMNode $root = null): void
{
$defaults = $this->getServiceDefaults($xml, $path, $root);
$defaults = $this->getServiceDefaults($xml, $path);
// anonymous services
$this->processAnonymousServices($xml, $path, $root);
$this->processAnonymousServices($xml, $path);
// imports
$this->parseImports($xml, $path, $root);
$this->parseImports($xml, $path);
// parameters
$this->parseParameters($xml, $path, $root);
$this->parseParameters($xml, $path);
// extensions
$this->loadFromExtensions($xml, $root);
$this->loadFromExtensions($xml);
// services
try {
$this->parseDefinitions($xml, $path, $defaults, $root);
$this->parseDefinitions($xml, $path, $defaults);
} finally {
$this->instanceof = [];
$this->registerAliasesForSinglyImplementedInterfaces();
@ -111,19 +90,19 @@ class XmlFileLoader extends FileLoader
return 'xml' === $type;
}
private function parseParameters(\DOMDocument $xml, string $file, \DOMNode $root = null)
private function parseParameters(\DOMDocument $xml, string $file)
{
if ($parameters = $this->getChildren($root ?? $xml->documentElement, 'parameters')) {
if ($parameters = $this->getChildren($xml->documentElement, 'parameters')) {
$this->container->getParameterBag()->add($this->getArgumentsAsPhp($parameters[0], 'parameter', $file));
}
}
private function parseImports(\DOMDocument $xml, string $file, \DOMNode $root = null)
private function parseImports(\DOMDocument $xml, string $file)
{
$xpath = new \DOMXPath($xml);
$xpath->registerNamespace('container', self::NS);
if (false === $imports = $xpath->query('.//container:imports/container:import', $root)) {
if (false === $imports = $xpath->query('//container:imports/container:import')) {
return;
}
@ -134,19 +113,19 @@ class XmlFileLoader extends FileLoader
}
}
private function parseDefinitions(\DOMDocument $xml, string $file, Definition $defaults, \DOMNode $root = null)
private function parseDefinitions(\DOMDocument $xml, string $file, Definition $defaults)
{
$xpath = new \DOMXPath($xml);
$xpath->registerNamespace('container', self::NS);
if (false === $services = $xpath->query('.//container:services/container:service|.//container:services/container:prototype|.//container:services/container:stack', $root)) {
if (false === $services = $xpath->query('//container:services/container:service|//container:services/container:prototype|//container:services/container:stack')) {
return;
}
$this->setCurrentDir(\dirname($file));
$this->instanceof = [];
$this->isLoadingInstanceof = true;
$instanceof = $xpath->query('.//container:services/container:instanceof', $root);
$instanceof = $xpath->query('//container:services/container:instanceof');
foreach ($instanceof as $service) {
$this->setDefinition((string) $service->getAttribute('id'), $this->parseDefinition($service, $file, new Definition()));
}
@ -192,12 +171,12 @@ class XmlFileLoader extends FileLoader
}
}
private function getServiceDefaults(\DOMDocument $xml, string $file, \DOMNode $root = null): Definition
private function getServiceDefaults(\DOMDocument $xml, string $file): Definition
{
$xpath = new \DOMXPath($xml);
$xpath->registerNamespace('container', self::NS);
if (null === $defaultsNode = $xpath->query('.//container:services/container:defaults', $root)->item(0)) {
if (null === $defaultsNode = $xpath->query('//container:services/container:defaults')->item(0)) {
return new Definition();
}
@ -214,7 +193,7 @@ class XmlFileLoader extends FileLoader
if ($alias = $service->getAttribute('alias')) {
$this->validateAlias($service, $file);
$this->container->setAlias($service->getAttribute('id'), $alias = new Alias($alias));
$this->container->setAlias((string) $service->getAttribute('id'), $alias = new Alias($alias));
if ($publicAttr = $service->getAttribute('public')) {
$alias->setPublic(XmlUtils::phpize($publicAttr));
} elseif ($defaults->getChanges()['public'] ?? false) {
@ -352,7 +331,7 @@ class XmlFileLoader extends FileLoader
}
if ('' === $tagName && '' === $tagName = $tag->getAttribute('name')) {
throw new InvalidArgumentException(sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', $service->getAttribute('id'), $file));
throw new InvalidArgumentException(sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', (string) $service->getAttribute('id'), $file));
}
$definition->addTag($tagName, $parameters);
@ -382,7 +361,7 @@ class XmlFileLoader extends FileLoader
} elseif ('null' === $decorationOnInvalid) {
$invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
} else {
throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration-on-invalid" on service "%s". Did you mean "exception", "ignore" or "null" in "%s"?', $decorationOnInvalid, $service->getAttribute('id'), $file));
throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration-on-invalid" on service "%s". Did you mean "exception", "ignore" or "null" in "%s"?', $decorationOnInvalid, (string) $service->getAttribute('id'), $file));
}
$renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null;
@ -415,7 +394,7 @@ class XmlFileLoader extends FileLoader
/**
* Processes anonymous services.
*/
private function processAnonymousServices(\DOMDocument $xml, string $file, \DOMNode $root = null)
private function processAnonymousServices(\DOMDocument $xml, string $file)
{
$definitions = [];
$count = 0;
@ -425,7 +404,7 @@ class XmlFileLoader extends FileLoader
$xpath->registerNamespace('container', self::NS);
// anonymous services as arguments/properties
if (false !== $nodes = $xpath->query('.//container:argument[@type="service"][not(@id)]|.//container:property[@type="service"][not(@id)]|.//container:bind[not(@id)]|.//container:factory[not(@service)]|.//container:configurator[not(@service)]', $root)) {
if (false !== $nodes = $xpath->query('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]|//container:bind[not(@id)]|//container:factory[not(@service)]|//container:configurator[not(@service)]')) {
foreach ($nodes as $node) {
if ($services = $this->getChildren($node, 'service')) {
// give it a unique name
@ -444,7 +423,7 @@ class XmlFileLoader extends FileLoader
}
// anonymous services "in the wild"
if (false !== $nodes = $xpath->query('.//container:services/container:service[not(@id)]', $root)) {
if (false !== $nodes = $xpath->query('//container:services/container:service[not(@id)]')) {
foreach ($nodes as $node) {
throw new InvalidArgumentException(sprintf('Top-level services must have "id" attribute, none found in "%s" at line %d.', $file, $node->getLineNo()));
}

View file

@ -13,6 +13,7 @@ namespace Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
@ -126,31 +127,9 @@ class YamlFileLoader extends FileLoader
// empty file
if (null === $content) {
return null;
return;
}
$this->loadContent($content, $path);
// per-env configuration
if ($this->env && isset($content['when@'.$this->env])) {
if (!\is_array($content['when@'.$this->env])) {
throw new InvalidArgumentException(sprintf('The "when@%s" key should contain an array in "%s". Check your YAML syntax.', $this->env, $path));
}
$env = $this->env;
$this->env = null;
try {
$this->loadContent($content['when@'.$env], $path);
} finally {
$this->env = $env;
}
}
return null;
}
private function loadContent(array $content, string $path)
{
// imports
$this->parseImports($content, $path);
@ -411,9 +390,6 @@ class YamlFileLoader extends FileLoader
];
}
$definition = isset($service[0]) && $service[0] instanceof Definition ? array_shift($service) : null;
$return = null === $definition ? $return : true;
$this->checkDefinition($id, $service, $file);
if (isset($service['alias'])) {
@ -448,9 +424,7 @@ class YamlFileLoader extends FileLoader
return $return ? $alias : $this->container->setAlias($id, $alias);
}
if (null !== $definition) {
// no-op
} elseif ($this->isLoadingInstanceof) {
if ($this->isLoadingInstanceof) {
$definition = new ChildDefinition('');
} elseif (isset($service['parent'])) {
if ('' !== $service['parent'] && '@' === $service['parent'][0]) {
@ -654,8 +628,7 @@ class YamlFileLoader extends FileLoader
if (isset($defaults['bind']) || isset($service['bind'])) {
// deep clone, to avoid multiple process of the same instance in the passes
$bindings = $definition->getBindings();
$bindings += isset($defaults['bind']) ? unserialize(serialize($defaults['bind'])) : [];
$bindings = isset($defaults['bind']) ? unserialize(serialize($defaults['bind'])) : [];
if (isset($service['bind'])) {
if (!\is_array($service['bind'])) {
@ -709,7 +682,7 @@ class YamlFileLoader extends FileLoader
*
* @throws InvalidArgumentException When errors occur
*
* @return string|array|Reference
* @return string|array|Reference A parsed callable
*/
private function parseCallable($callable, string $parameter, string $id, string $file)
{
@ -743,7 +716,7 @@ class YamlFileLoader extends FileLoader
/**
* Loads a YAML file.
*
* @return array|null
* @return array The file content
*
* @throws InvalidArgumentException when the given file is not a local file or when it does not exist
*/
@ -790,7 +763,7 @@ class YamlFileLoader extends FileLoader
}
foreach ($content as $namespace => $data) {
if (\in_array($namespace, ['imports', 'parameters', 'services']) || 0 === strpos($namespace, 'when@')) {
if (\in_array($namespace, ['imports', 'parameters', 'services'])) {
continue;
}
@ -804,7 +777,9 @@ class YamlFileLoader extends FileLoader
}
/**
* @return mixed
* Resolves services.
*
* @return array|string|Reference|ArgumentInterface
*/
private function resolveServices($value, string $file, bool $isParameter = false)
{
@ -900,10 +875,6 @@ class YamlFileLoader extends FileLoader
$value[$k] = $this->resolveServices($v, $file, $isParameter);
}
} elseif (\is_string($value) && str_starts_with($value, '@=')) {
if ($isParameter) {
throw new InvalidArgumentException(sprintf('Using expressions in parameters is not allowed in "%s".', $file));
}
if (!class_exists(Expression::class)) {
throw new \LogicException('The "@=" expression syntax cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
}
@ -935,7 +906,7 @@ class YamlFileLoader extends FileLoader
private function loadFromExtensions(array $content)
{
foreach ($content as $namespace => $values) {
if (\in_array($namespace, ['imports', 'parameters', 'services']) || 0 === strpos($namespace, 'when@')) {
if (\in_array($namespace, ['imports', 'parameters', 'services'])) {
continue;
}

View file

@ -37,31 +37,9 @@
<xsd:element name="services" type="services" />
<xsd:group ref="foreign" />
</xsd:sequence>
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="when" type="when" />
</xsd:sequence>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="when">
<xsd:sequence>
<xsd:group ref="foreign" />
<xsd:sequence minOccurs="0">
<xsd:element name="imports" type="imports" />
<xsd:group ref="foreign" />
</xsd:sequence>
<xsd:sequence minOccurs="0">
<xsd:element name="parameters" type="parameters" />
<xsd:group ref="foreign" />
</xsd:sequence>
<xsd:sequence minOccurs="0">
<xsd:element name="services" type="services" />
<xsd:group ref="foreign" />
</xsd:sequence>
</xsd:sequence>
<xsd:attribute name="env" type="xsd:string" use="required" />
</xsd:complexType>
<xsd:group name="foreign">
<xsd:sequence>
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />

View file

@ -26,7 +26,7 @@ class Parameter
}
/**
* @return string
* @return string The parameter key
*/
public function __toString()
{

View file

@ -36,9 +36,9 @@ class ContainerBag extends FrozenParameterBag implements ContainerBagInterface
/**
* {@inheritdoc}
*
* @return array|bool|string|int|float|\UnitEnum|null
* @return array|bool|string|int|float|null
*/
public function get(string $name)
public function get($name)
{
return $this->container->getParameter($name);
}
@ -48,7 +48,7 @@ class ContainerBag extends FrozenParameterBag implements ContainerBagInterface
*
* @return bool
*/
public function has(string $name)
public function has($name)
{
return $this->container->hasParameter($name);
}

View file

@ -24,7 +24,7 @@ interface ContainerBagInterface extends ContainerInterface
/**
* Gets the service container parameters.
*
* @return array
* @return array An array of parameters
*/
public function all();

View file

@ -109,7 +109,7 @@ class ParameterBag implements ParameterBagInterface
*/
public function has(string $name)
{
return \array_key_exists($name, $this->parameters);
return \array_key_exists((string) $name, $this->parameters);
}
/**
@ -151,7 +151,7 @@ class ParameterBag implements ParameterBagInterface
* @param mixed $value A value
* @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
*
* @return mixed
* @return mixed The resolved value
*
* @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
* @throws ParameterCircularReferenceException if a circular reference if detected
@ -180,7 +180,7 @@ class ParameterBag implements ParameterBagInterface
*
* @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
*
* @return mixed
* @return mixed The resolved string
*
* @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
* @throws ParameterCircularReferenceException if a circular reference if detected

View file

@ -24,28 +24,28 @@ interface ParameterBagInterface
/**
* Clears all parameters.
*
* @throws LogicException if the ParameterBagInterface cannot be cleared
* @throws LogicException if the ParameterBagInterface can not be cleared
*/
public function clear();
/**
* Adds parameters to the service container parameters.
*
* @throws LogicException if the parameter cannot be added
* @throws LogicException if the parameter can not be added
*/
public function add(array $parameters);
/**
* Gets the service container parameters.
*
* @return array
* @return array An array of parameters
*/
public function all();
/**
* Gets a service container parameter.
*
* @return array|bool|string|int|float|\UnitEnum|null
* @return array|bool|string|int|float|null
*
* @throws ParameterNotFoundException if the parameter is not defined
*/
@ -59,16 +59,16 @@ interface ParameterBagInterface
/**
* Sets a service container parameter.
*
* @param array|bool|string|int|float|\UnitEnum|null $value The parameter value
* @param array|bool|string|int|float|null $value The parameter value
*
* @throws LogicException if the parameter cannot be set
* @throws LogicException if the parameter can not be set
*/
public function set(string $name, $value);
/**
* Returns true if a parameter name is defined.
*
* @return bool
* @return bool true if the parameter name is defined, false otherwise
*/
public function has(string $name);

View file

@ -28,7 +28,7 @@ class Reference
}
/**
* @return string
* @return string The service identifier
*/
public function __toString()
{

View file

@ -38,7 +38,7 @@ class ServiceLocator implements ServiceProviderInterface
*
* @return mixed
*/
public function get(string $id)
public function get($id)
{
if (!$this->externalId) {
return $this->doGet($id);

View file

@ -23,7 +23,7 @@ interface TaggedContainerInterface extends ContainerInterface
*
* @param string $name The tag name
*
* @return array
* @return array An array of tags
*/
public function findTaggedServiceIds(string $name);
}

View file

@ -17,16 +17,15 @@
],
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1.1",
"symfony/deprecation-contracts": "^2.1|^3",
"psr/container": "^1.0",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-php80": "^1.16",
"symfony/polyfill-php81": "^1.22",
"symfony/service-contracts": "^1.1.6|^2"
},
"require-dev": {
"symfony/yaml": "^4.4.26|^5.0|^6.0",
"symfony/config": "^5.3|^6.0",
"symfony/expression-language": "^4.4|^5.0|^6.0"
"symfony/yaml": "^4.4|^5.0",
"symfony/config": "^5.1",
"symfony/expression-language": "^4.4|^5.0"
},
"suggest": {
"symfony/yaml": "",
@ -36,11 +35,10 @@
"symfony/proxy-manager-bridge": "Generate service proxies to lazy load them"
},
"conflict": {
"ext-psr": "<1.1|>=2",
"symfony/config": "<5.3",
"symfony/config": "<5.1",
"symfony/finder": "<4.4",
"symfony/proxy-manager-bridge": "<4.4",
"symfony/yaml": "<4.4.26"
"symfony/yaml": "<4.4"
},
"provide": {
"psr/container-implementation": "1.0",

View file

@ -100,6 +100,16 @@ final class Php80
public static function str_ends_with(string $haystack, string $needle): bool
{
return '' === $needle || ('' !== $haystack && 0 === substr_compare($haystack, $needle, -\strlen($needle)));
if ('' === $needle || $needle === $haystack) {
return true;
}
if ('' === $haystack) {
return false;
}
$needleLength = \strlen($needle);
return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength);
}
}

View file

@ -0,0 +1,103 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Polyfill\Php80;
/**
* @author Fedonyuk Anton <info@ensostudio.ru>
*
* @internal
*/
class PhpToken implements \Stringable
{
/**
* @var int
*/
public $id;
/**
* @var string
*/
public $text;
/**
* @var int
*/
public $line;
/**
* @var int
*/
public $pos;
public function __construct(int $id, string $text, int $line = -1, int $position = -1)
{
$this->id = $id;
$this->text = $text;
$this->line = $line;
$this->pos = $position;
}
public function getTokenName(): ?string
{
if ('UNKNOWN' === $name = token_name($this->id)) {
$name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text;
}
return $name;
}
/**
* @param int|string|array $kind
*/
public function is($kind): bool
{
foreach ((array) $kind as $value) {
if (\in_array($value, [$this->id, $this->text], true)) {
return true;
}
}
return false;
}
public function isIgnorable(): bool
{
return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true);
}
public function __toString(): string
{
return (string) $this->text;
}
/**
* @return static[]
*/
public static function tokenize(string $code, int $flags = 0): array
{
$line = 1;
$position = 0;
$tokens = token_get_all($code, $flags);
foreach ($tokens as $index => $token) {
if (\is_string($token)) {
$id = \ord($token);
$text = $token;
} else {
[$id, $text, $line] = $token;
}
$tokens[$index] = new static($id, $text, $line, $position);
$position += \strlen($text);
}
return $tokens;
}
}

View file

@ -0,0 +1,7 @@
<?php
if (\PHP_VERSION_ID < 80000 && \extension_loaded('tokenizer')) {
class PhpToken extends Symfony\Polyfill\Php80\PhpToken
{
}
}

Some files were not shown because too many files have changed in this diff Show more