Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
return $this->container;
}

if (!$kernel->isDebug() || !$kernel->getContainer()->getParameter('debug.container.dump') || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) {
$file = $kernel->isDebug() ? $kernel->getContainer()->getParameter('debug.container.dump') : false;

if (!$file || !(new ConfigCache($file, true))->isFresh()) {

Check failure on line 44 in src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php

View workflow job for this annotation

GitHub Actions / Psalm

InvalidArgument

src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php:44:41: InvalidArgument: Argument 1 of Symfony\Component\Config\ConfigCache::__construct expects string, but UnitEnum|non-empty-array<array-key, mixed>|non-empty-scalar provided (see https://psalm.dev/004)
$buildContainer = \Closure::bind(function () {
$this->initializeBundles();

Expand All @@ -57,13 +59,17 @@
return $containerBuilder;
}, $kernel, $kernel::class);
$container = $buildContainer();
(new XmlFileLoader($container, new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump'));
$locatorPass = new ServiceLocatorTagPass();
$locatorPass->process($container);

$container->getCompilerPassConfig()->setBeforeOptimizationPasses([]);
$container->getCompilerPassConfig()->setOptimizationPasses([]);
$container->getCompilerPassConfig()->setBeforeRemovingPasses([]);
if (str_ends_with($file, '.xml') && is_file(substr_replace($file, '.ser', -4))) {

Check failure on line 63 in src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php

View workflow job for this annotation

GitHub Actions / Psalm

InvalidArgument

src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php:63:31: InvalidArgument: Argument 1 of str_ends_with expects string, but UnitEnum|non-empty-array<array-key, mixed>|non-empty-scalar provided (see https://psalm.dev/004)
$dumpedContainer = unserialize(file_get_contents(substr_replace($file, '.ser', -4)));
$container->setDefinitions($dumpedContainer->getDefinitions());
$container->setAliases($dumpedContainer->getAliases());
$container->__construct($dumpedContainer->getParameterBag());
} else {
(new XmlFileLoader($container, new FileLocator()))->load($file);
$locatorPass = new ServiceLocatorTagPass();
$locatorPass->process($container);
}
}

return $this->container = $container;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,10 @@ private function getContainerBuilder(): ContainerBuilder
}

$kernel = $this->getApplication()->getKernel();
$kernelContainer = $kernel->getContainer();
$container = $kernel->getContainer();
$file = $container->isDebug() ? $container->getParameter('debug.container.dump') : false;

if (!$kernel->isDebug() || !$kernelContainer->getParameter('debug.container.dump') || !(new ConfigCache($kernelContainer->getParameter('debug.container.dump'), true))->isFresh()) {
if (!$file || !(new ConfigCache($file, true))->isFresh()) {
if (!$kernel instanceof Kernel) {
throw new RuntimeException(\sprintf('This command does not support the application kernel: "%s" does not extend "%s".', get_debug_type($kernel), Kernel::class));
}
Expand All @@ -93,12 +94,17 @@ private function getContainerBuilder(): ContainerBuilder
}, $kernel, $kernel::class);
$container = $buildContainer();
} else {
if (!$kernelContainer instanceof Container) {
throw new RuntimeException(\sprintf('This command does not support the application container: "%s" does not extend "%s".', get_debug_type($kernelContainer), Container::class));
if (str_ends_with($file, '.xml') && is_file(substr_replace($file, '.ser', -4))) {
$container = unserialize(file_get_contents(substr_replace($file, '.ser', -4)));
} else {
(new XmlFileLoader($container = new ContainerBuilder(new EnvPlaceholderParameterBag()), new FileLocator()))->load($file);
}

(new XmlFileLoader($container = new ContainerBuilder($parameterBag = new EnvPlaceholderParameterBag()), new FileLocator()))->load($kernelContainer->getParameter('debug.container.dump'));
if (!$container instanceof ContainerBuilder) {
throw new RuntimeException(\sprintf('This command does not support the application container: "%s" is not a "%s".', get_debug_type($container), ContainerBuilder::class));
}

$parameterBag = $container->getParameterBag();
$refl = new \ReflectionProperty($parameterBag, 'resolved');
$refl->setValue($parameterBag, true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@

use Symfony\Component\Config\ConfigCache;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ResolveEnvPlaceholdersPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\XmlDumper;
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use Symfony\Component\Filesystem\Filesystem;

/**
* Dumps the ContainerBuilder to a cache file so that it can be used by
Expand All @@ -31,9 +34,38 @@
return;
}

$cache = new ConfigCache($container->getParameter('debug.container.dump'), true);
if (!$cache->isFresh()) {
$cache->write((new XmlDumper($container))->dump(), $container->getResources());
$file = $container->getParameter('debug.container.dump');
$cache = new ConfigCache($file, true);

Check failure on line 38 in src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php

View workflow job for this annotation

GitHub Actions / Psalm

InvalidArgument

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php:38:34: InvalidArgument: Argument 1 of Symfony\Component\Config\ConfigCache::__construct expects string, but UnitEnum|array<array-key, mixed>|null|scalar provided (see https://psalm.dev/004)
if ($cache->isFresh()) {
return;
}
$cache->write((new XmlDumper($container))->dump(), $container->getResources());

if (!str_ends_with($file, '.xml')) {

Check failure on line 44 in src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php

View workflow job for this annotation

GitHub Actions / Psalm

InvalidArgument

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php:44:28: InvalidArgument: Argument 1 of str_ends_with expects string, but UnitEnum|array<array-key, mixed>|null|scalar provided (see https://psalm.dev/004)
return;
}

$file = substr_replace($file, '.ser', -4);

try {
$dump = new ContainerBuilder(clone $container->getParameterBag());
$dump->setDefinitions(unserialize(serialize($container->getDefinitions())));
$dump->setAliases($container->getAliases());

if (($bag = $container->getParameterBag()) instanceof EnvPlaceholderParameterBag) {
(new ResolveEnvPlaceholdersPass(null))->process($dump);
$dump->__construct(new EnvPlaceholderParameterBag($container->resolveEnvPlaceholders($bag->all())));
}

$fs = new Filesystem();
$fs->dumpFile($file, serialize($dump));

Check failure on line 61 in src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php

View workflow job for this annotation

GitHub Actions / Psalm

InvalidArgument

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php:61:27: InvalidArgument: Argument 1 of Symfony\Component\Filesystem\Filesystem::dumpFile expects string, but array<array-key, string> provided (see https://psalm.dev/004)
$fs->chmod($file, 0666, umask());
} catch (\Throwable $e) {
$container->getCompiler()->log($this, $e->getMessage());
// ignore serialization and file-system errors
if (file_exists($file)) {

Check failure on line 66 in src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php

View workflow job for this annotation

GitHub Actions / Psalm

InvalidArgument

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php:66:29: InvalidArgument: Argument 1 of file_exists expects string, but array<array-key, string> provided (see https://psalm.dev/004)
@unlink($file);

Check failure on line 67 in src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php

View workflow job for this annotation

GitHub Actions / Psalm

InvalidArgument

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php:67:25: InvalidArgument: Argument 1 of unlink expects string, but array<array-key, string> provided (see https://psalm.dev/004)
}
}
}
}
16 changes: 16 additions & 0 deletions src/Symfony/Component/DependencyInjection/Alias.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,20 @@ public function __toString(): string
{
return $this->id;
}

public function __serialize(): array
{
$data = [];
foreach ((array) $this as $k => $v) {
if (!$v) {
continue;
}
if (false !== $i = strrpos($k, "\0")) {
$k = substr($k, 1 + $i);
}
$data[$k] = $v;
}

return $data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
*/
final class AbstractArgument
{
use ArgumentTrait;

private string $text;
private string $context = '';

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?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\Argument;

/**
* Helps reduce the size of the dumped container when using php-serialize.
*
* @internal
*/
trait ArgumentTrait
{
public function __serialize(): array
{
$data = [];
foreach ((array) $this as $k => $v) {
if (null === $v) {
continue;
}
if (false !== $i = strrpos($k, "\0")) {
$k = substr($k, 1 + $i);
}
$data[$k] = $v;
}

return $data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,29 @@
*/
final class BoundArgument implements ArgumentInterface
{
use ArgumentTrait;

public const SERVICE_BINDING = 0;
public const DEFAULTS_BINDING = 1;
public const INSTANCEOF_BINDING = 2;

private static int $sequence = 0;

private mixed $value = null;
private ?int $identifier = null;
private ?bool $used = null;
private int $type = 0;
private ?string $file = null;

public function __construct(
private mixed $value,
mixed $value,
bool $trackUsage = true,
private int $type = 0,
private ?string $file = null,
int $type = 0,
?string $file = null,
) {
$this->value = $value;
$this->type = $type;
$this->file = $file;
if ($trackUsage) {
$this->identifier = ++self::$sequence;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
class IteratorArgument implements ArgumentInterface
{
use ArgumentTrait;

private array $values;

public function __construct(array $values)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
*/
class ServiceClosureArgument implements ArgumentInterface
{
use ArgumentTrait;

private array $values;

public function __construct(mixed $value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@

namespace Symfony\Component\DependencyInjection\Argument;

use Symfony\Component\DependencyInjection\Loader\Configurator\Traits\ArgumentTrait;

/**
* Represents a closure acting as a service locator.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
class ServiceLocatorArgument implements ArgumentInterface
{
use ArgumentTrait;

private array $values;
private ?TaggedIteratorArgument $taggedIteratorArgument = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
*/
class TaggedIteratorArgument extends IteratorArgument
{
private mixed $indexAttribute;
private ?string $defaultIndexMethod;
private ?string $defaultPriorityMethod;
private mixed $indexAttribute = null;
private ?string $defaultIndexMethod = null;
private ?string $defaultPriorityMethod = null;

/**
* @param string $tag The name of the tag identifying the target services
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,35 @@ class ResolveEnvPlaceholdersPass extends AbstractRecursivePass
{
protected bool $skipScalars = false;

/**
* @param string|true|null $format A sprintf() format returning the replacement for each env var name or
* null to resolve back to the original "%env(VAR)%" format or
* true to resolve to the actual values of the referenced env vars
*/
public function __construct(
private string|bool|null $format = true,
) {
}

protected function processValue(mixed $value, bool $isRoot = false): mixed
{
if (\is_string($value)) {
return $this->container->resolveEnvPlaceholders($value, true);
return $this->container->resolveEnvPlaceholders($value, $this->format);
}
if ($value instanceof Definition) {
$changes = $value->getChanges();
if (isset($changes['class'])) {
$value->setClass($this->container->resolveEnvPlaceholders($value->getClass(), true));
$value->setClass($this->container->resolveEnvPlaceholders($value->getClass(), $this->format));
}
if (isset($changes['file'])) {
$value->setFile($this->container->resolveEnvPlaceholders($value->getFile(), true));
$value->setFile($this->container->resolveEnvPlaceholders($value->getFile(), $this->format));
}
}

$value = parent::processValue($value, $isRoot);

if ($value && \is_array($value) && !$isRoot) {
$value = array_combine($this->container->resolveEnvPlaceholders(array_keys($value), true), $value);
$value = array_combine($this->container->resolveEnvPlaceholders(array_keys($value), $this->format), $value);
}

return $value;
Expand Down
16 changes: 16 additions & 0 deletions src/Symfony/Component/DependencyInjection/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -820,4 +820,20 @@ public function hasErrors(): bool
{
return (bool) $this->errors;
}

public function __serialize(): array
{
$data = [];
foreach ((array) $this as $k => $v) {
if (false !== $i = strrpos($k, "\0")) {
$k = substr($k, 1 + $i);
}
if (!$v xor 'shared' === $k) {
continue;
}
$data[$k] = $v;
}

return $data;
}
}
18 changes: 17 additions & 1 deletion src/Symfony/Component/DependencyInjection/Reference.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ public function __toString(): string
*/
public function getInvalidBehavior(): int
{
return $this->invalidBehavior;
return $this->invalidBehavior ??= ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
}

public function __serialize(): array
{
$data = [];
foreach ((array) $this as $k => $v) {
if (false !== $i = strrpos($k, "\0")) {
$k = substr($k, 1 + $i);
}
if ('invalidBehavior' === $k && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $v) {
continue;
}
$data[$k] = $v;
}

return $data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ public static function getSubscribedServices(): array
'autowired' => new ServiceClosureArgument(new TypedReference('service.id', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'autowired', [new Autowire(service: 'service.id')])),
'autowired.nullable' => new ServiceClosureArgument(new TypedReference('service.id', 'stdClass', ContainerInterface::IGNORE_ON_INVALID_REFERENCE, 'autowired.nullable', [new Autowire(service: 'service.id')])),
'autowired.parameter' => new ServiceClosureArgument('foobar'),
'autowire.decorated' => new ServiceClosureArgument(new Reference('.service_locator.oNVewcO.inner', ContainerInterface::NULL_ON_INVALID_REFERENCE)),
'autowire.decorated' => new ServiceClosureArgument(new Reference('.service_locator.Di.wrC8.inner', ContainerInterface::NULL_ON_INVALID_REFERENCE)),
'target' => new ServiceClosureArgument(new TypedReference('stdClass', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'target', [new Target('someTarget')])),
];
$this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0));
Expand Down
Loading