diff --git a/Argument/LazyClosure.php b/Argument/LazyClosure.php index 3e8718643..3dcc34e4f 100644 --- a/Argument/LazyClosure.php +++ b/Argument/LazyClosure.php @@ -12,7 +12,6 @@ namespace Symfony\Component\DependencyInjection\Argument; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Reference; diff --git a/Compiler/CheckCircularReferencesPass.php b/Compiler/CheckCircularReferencesPass.php index 7adb0b4d8..8a7c11383 100644 --- a/Compiler/CheckCircularReferencesPass.php +++ b/Compiler/CheckCircularReferencesPass.php @@ -62,7 +62,7 @@ private function checkOutEdges(array $edges): void continue; } - $isLeaf = !!$node->getValue(); + $isLeaf = (bool) $node->getValue(); $isConcrete = !$edge->isLazy() && !$edge->isWeak(); // Skip already checked lazy services if they are still lazy. Will not gain any new information. diff --git a/Compiler/ResolveBindingsPass.php b/Compiler/ResolveBindingsPass.php index 4fca2081b..b2c6f6ef7 100644 --- a/Compiler/ResolveBindingsPass.php +++ b/Compiler/ResolveBindingsPass.php @@ -228,7 +228,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed foreach ($names as $key => $name) { if (\array_key_exists($name, $arguments) && (0 === $key || \array_key_exists($key - 1, $arguments))) { - if (!array_key_exists($key, $arguments)) { + if (!\array_key_exists($key, $arguments)) { $arguments[$key] = $arguments[$name]; } unset($arguments[$name]); diff --git a/ContainerBuilder.php b/ContainerBuilder.php index e978cac41..e9970a26c 100644 --- a/ContainerBuilder.php +++ b/ContainerBuilder.php @@ -824,7 +824,7 @@ public function compile(bool $resolveEnvPlaceholders = false): void if ($bag instanceof EnvPlaceholderParameterBag) { if ($resolveEnvPlaceholders) { - $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); + $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($this->escapeParameters($bag->all()), true)); } $this->envPlaceholders = $bag->getEnvPlaceholders(); @@ -1175,7 +1175,7 @@ private function createService(Definition $definition, array &$inlineServices, b if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) { $r = new \ReflectionClass($factory[0]); - if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) { + if (0 < strpos($r->getDocComment() ?: '', "\n * @deprecated ")) { trigger_deprecation('', '', 'The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name); } } @@ -1192,7 +1192,7 @@ private function createService(Definition $definition, array &$inlineServices, b $service = $r->getConstructor() ? $r->newInstanceArgs($arguments) : $r->newInstance(); } - if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) { + if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment() ?: '', "\n * @deprecated ")) { trigger_deprecation('', '', 'The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name); } } @@ -1777,4 +1777,18 @@ private function inVendors(string $path): bool return $this->pathsInVendor[$path] = false; } + + private function escapeParameters(array $parameters): array + { + $params = []; + foreach ($parameters as $k => $v) { + $params[$k] = match (true) { + \is_array($v) => $this->escapeParameters($v), + \is_string($v) => str_replace('%', '%%', $v), + default => $v, + }; + } + + return $params; + } } diff --git a/Dumper/PhpDumper.php b/Dumper/PhpDumper.php index 9568ad26b..fb2d45f92 100644 --- a/Dumper/PhpDumper.php +++ b/Dumper/PhpDumper.php @@ -527,7 +527,7 @@ private function collectLineage(string $class, array &$lineage): void return; } $file = $r->getFileName(); - if (str_ends_with($file, ') : eval()\'d code')) { + if ($file && str_ends_with($file, ') : eval()\'d code')) { $file = substr($file, 0, strrpos($file, '(', -17)); } if (!$file || $this->doExport($file) === $exportedFile = $this->export($file)) { @@ -574,12 +574,13 @@ private function generateProxyClasses(): array continue; } do { - $file = $r->getFileName(); - if (str_ends_with($file, ') : eval()\'d code')) { - $file = substr($file, 0, strrpos($file, '(', -17)); - } - if (is_file($file)) { - $this->container->addResource(new FileResource($file)); + if ($file = $r->getFileName()) { + if (str_ends_with($file, ') : eval()\'d code')) { + $file = substr($file, 0, strrpos($file, '(', -17)); + } + if (is_file($file)) { + $this->container->addResource(new FileResource($file)); + } } $r = $r->getParentClass() ?: null; } while ($r?->isUserDefined()); diff --git a/Loader/XmlFileLoader.php b/Loader/XmlFileLoader.php index f59698066..eed874cd9 100644 --- a/Loader/XmlFileLoader.php +++ b/Loader/XmlFileLoader.php @@ -339,7 +339,11 @@ private function parseDefinition(\DOMElement $service, string $file, Definition } foreach ($this->getChildren($service, 'call') as $call) { - $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument', $file), XmlUtils::phpize($call->getAttribute('returns-clone'))); + $definition->addMethodCall( + $call->getAttribute('method'), + $this->getArgumentsAsPhp($call, 'argument', $file), + XmlUtils::phpize($call->getAttribute('returns-clone')) ?: false + ); } $tags = $this->getChildren($service, 'tag'); diff --git a/Tests/Argument/LazyClosureTest.php b/Tests/Argument/LazyClosureTest.php index 9652a86fd..e1b5c2a90 100644 --- a/Tests/Argument/LazyClosureTest.php +++ b/Tests/Argument/LazyClosureTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\DependencyInjection\Tests\Argument; -use InvalidArgumentException; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Argument\LazyClosure; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -23,7 +22,7 @@ public function testMagicGetThrows() { $closure = new LazyClosure(fn () => null); - $this->expectException(InvalidArgumentException::class); + $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Cannot read property "foo" from a lazy closure.'); $closure->foo; @@ -34,7 +33,7 @@ public function testThrowsWhenNotUsingInterface() $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('Cannot create adapter for service "foo" because "Symfony\Component\DependencyInjection\Tests\Argument\LazyClosureTest" is not an interface.'); - LazyClosure::getCode('foo', [new \stdClass(), 'bar'], LazyClosureTest::class, new ContainerBuilder(), 'foo'); + LazyClosure::getCode('foo', [new \stdClass(), 'bar'], self::class, new ContainerBuilder(), 'foo'); } public function testThrowsOnNonFunctionalInterface() @@ -62,5 +61,6 @@ public function foo(); interface NonFunctionalInterface { public function foo(); + public function bar(); } diff --git a/Tests/ContainerBuilderTest.php b/Tests/ContainerBuilderTest.php index 73be8aaed..04a8cb01d 100644 --- a/Tests/ContainerBuilderTest.php +++ b/Tests/ContainerBuilderTest.php @@ -892,6 +892,7 @@ public function testCompileWithResolveEnv() $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)% %env(DUMMY_SERVER_VAR)% %env(HTTP_DUMMY_VAR)%'); $container->setParameter('foo', '%env(FOO)%'); $container->setParameter('baz', '%foo%'); + $container->setParameter('qux', '%%quux%%'); $container->setParameter('env(HTTP_DUMMY_VAR)', '123'); $container->register('teatime', 'stdClass') ->setProperty('foo', '%env(DUMMY_ENV_VAR)%') @@ -1136,7 +1137,7 @@ public function testAddObjectResource() $this->assertCount(1, $resources); - /* @var FileResource $resource */ + /** @var FileResource $resource */ $resource = end($resources); $this->assertInstanceOf(FileResource::class, $resource); diff --git a/Tests/Loader/XmlFileLoaderTest.php b/Tests/Loader/XmlFileLoaderTest.php index 1b4361411..f962fa106 100644 --- a/Tests/Loader/XmlFileLoaderTest.php +++ b/Tests/Loader/XmlFileLoaderTest.php @@ -1280,7 +1280,7 @@ public function testStaticConstructor() public function testStaticConstructorWithFactoryThrows() { $container = new ContainerBuilder(); - $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath . '/xml')); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); $this->expectException(LogicException::class); $this->expectExceptionMessage('The "static_constructor" service cannot declare a factory as well as a constructor.'); @@ -1341,7 +1341,7 @@ public function testUnknownConstantAsKey() public function testDeprecatedTagged() { $container = new ContainerBuilder(); - $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath . '/xml')); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); $this->expectUserDeprecationMessage(\sprintf('Since symfony/dependency-injection 7.2: Type "tagged" is deprecated for tag , use "tagged_iterator" instead in "%s/xml%sservices_with_deprecated_tagged.xml".', self::$fixturesPath, \DIRECTORY_SEPARATOR));