Skip to content

Commit

Permalink
Merge branch '6.4' into 7.0
Browse files Browse the repository at this point in the history
* 6.4:
  Fix RequestPayloadValueResolver handling error with no ExpectedTypes
  [Mime] Fix serializing uninitialized RawMessage::$message to null
  [Notifer][Smsapi] Set messageId of SentMessage
  [DX] Use Symfony "dark-mode"-responsive logo in README
  support lazy evaluated exception messages with Xdebug 3
  Provide more precise phpdoc for FileLocatorInterface::locate
  [DependencyInjection] #[Autowire] attribute should have precedence over bindings
  • Loading branch information
nicolas-grekas committed Jan 30, 2024
2 parents 9f203a7 + 6871811 commit e915c66
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 3 deletions.
8 changes: 8 additions & 0 deletions Compiler/ResolveBindingsPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\Attribute\Target;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
Expand Down Expand Up @@ -184,6 +185,13 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
if (\array_key_exists($parameter->name, $arguments) && '' !== $arguments[$parameter->name]) {
continue;
}
if (
$value->isAutowired()
&& !$value->hasTag('container.ignore_attributes')
&& $parameter->getAttributes(Autowire::class, \ReflectionAttribute::IS_INSTANCEOF)
) {
continue;
}

$typeHint = ltrim(ProxyHelper::exportType($parameter) ?? '', '?');

Expand Down
4 changes: 1 addition & 3 deletions Exception/AutowiringFailedException.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ public function __construct(string $serviceId, string|\Closure $message = '', in
{
$this->serviceId = $serviceId;

if ($message instanceof \Closure
&& (\function_exists('xdebug_is_enabled') ? xdebug_is_enabled() : \function_exists('xdebug_info'))
) {
if ($message instanceof \Closure && \function_exists('xdebug_is_enabled') && xdebug_is_enabled()) {
$message = $message();
}

Expand Down
62 changes: 62 additions & 0 deletions Tests/Compiler/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Psr\Container\ContainerInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\ChildDefinition;
Expand Down Expand Up @@ -50,6 +51,7 @@
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedLocatorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod;
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedLocatorConsumerWithDefaultPriorityMethod;
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedLocatorConsumerWithoutIndex;
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedLocatorConsumerWithServiceSubscriber;
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService1;
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService2;
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService3;
Expand Down Expand Up @@ -1118,6 +1120,66 @@ public function testTaggedIteratorAndLocatorWithExclude()
$this->assertTrue($locator->has(AutoconfiguredService2::class));
$this->assertFalse($locator->has(TaggedConsumerWithExclude::class));
}

public function testAutowireAttributeHasPriorityOverBindings()
{
$container = new ContainerBuilder();
$container->register(FooTagClass::class)
->setPublic(true)
->addTag('foo_bar', ['key' => 'tagged_service'])
;
$container->register(TaggedLocatorConsumerWithServiceSubscriber::class)
->setBindings([
'$locator' => new BoundArgument(new Reference('service_container'), false),
])
->setPublic(true)
->setAutowired(true)
->addTag('container.service_subscriber')
;
$container->register('subscribed_service', \stdClass::class)
->setPublic(true)
;

$container->compile();

/** @var TaggedLocatorConsumerWithServiceSubscriber $s */
$s = $container->get(TaggedLocatorConsumerWithServiceSubscriber::class);

self::assertInstanceOf(ContainerInterface::class, $subscriberLocator = $s->getContainer());
self::assertTrue($subscriberLocator->has('subscribed_service'));
self::assertNotSame($subscriberLocator, $taggedLocator = $s->getLocator());
self::assertInstanceOf(ContainerInterface::class, $taggedLocator);
self::assertTrue($taggedLocator->has('tagged_service'));
}

public function testBindingsWithAutowireAttributeAndAutowireFalse()
{
$container = new ContainerBuilder();
$container->register(FooTagClass::class)
->setPublic(true)
->addTag('foo_bar', ['key' => 'tagged_service'])
;
$container->register(TaggedLocatorConsumerWithServiceSubscriber::class)
->setBindings([
'$locator' => new BoundArgument(new Reference('service_container'), false),
])
->setPublic(true)
->setAutowired(false)
->addTag('container.service_subscriber')
;
$container->register('subscribed_service', \stdClass::class)
->setPublic(true)
;

$container->compile();

/** @var TaggedLocatorConsumerWithServiceSubscriber $s */
$s = $container->get(TaggedLocatorConsumerWithServiceSubscriber::class);

self::assertNull($s->getContainer());
self::assertInstanceOf(ContainerInterface::class, $taggedLocator = $s->getLocator());
self::assertSame($container, $taggedLocator);
}
}

class ServiceSubscriberStub implements ServiceSubscriberInterface
Expand Down
51 changes: 51 additions & 0 deletions Tests/Fixtures/TaggedLocatorConsumerWithServiceSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?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\Tests\Fixtures;

use Psr\Container\ContainerInterface;
use Symfony\Component\DependencyInjection\Attribute\TaggedLocator;
use Symfony\Contracts\Service\Attribute\Required;
use Symfony\Contracts\Service\ServiceSubscriberInterface;

final class TaggedLocatorConsumerWithServiceSubscriber implements ServiceSubscriberInterface
{
private ?ContainerInterface $container = null;

public function __construct(
#[TaggedLocator('foo_bar', indexAttribute: 'key')]
private ContainerInterface $locator,
) {
}

public function getLocator(): ContainerInterface
{
return $this->locator;
}

public function getContainer(): ?ContainerInterface
{
return $this->container;
}

#[Required]
public function setContainer(ContainerInterface $container): void
{
$this->container = $container;
}

public static function getSubscribedServices(): array
{
return [
'subscribed_service',
];
}
}

0 comments on commit e915c66

Please sign in to comment.