Skip to content

Commit 5fa830d

Browse files
kbondnicolas-grekas
authored andcommitted
[DependencyInjection] add #[AutowireLocator] attribute
1 parent ff654da commit 5fa830d

18 files changed

+214
-61
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Attribute;
13+
14+
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
15+
use Symfony\Component\DependencyInjection\ContainerInterface;
16+
use Symfony\Component\DependencyInjection\Reference;
17+
18+
#[\Attribute(\Attribute::TARGET_PARAMETER)]
19+
class AutowireLocator extends Autowire
20+
{
21+
public function __construct(string ...$serviceIds)
22+
{
23+
$values = [];
24+
25+
foreach ($serviceIds as $key => $serviceId) {
26+
if ($nullable = str_starts_with($serviceId, '?')) {
27+
$serviceId = substr($serviceId, 1);
28+
}
29+
30+
if (is_numeric($key)) {
31+
$key = $serviceId;
32+
}
33+
34+
$values[$key] = new Reference(
35+
$serviceId,
36+
$nullable ? ContainerInterface::IGNORE_ON_INVALID_REFERENCE : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE,
37+
);
38+
}
39+
40+
parent::__construct(new ServiceLocatorArgument($values));
41+
}
42+
}

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* Allow using `#[Target]` with no arguments to state that a parameter must match a named autowiring alias
88
* Deprecate `ContainerAwareInterface` and `ContainerAwareTrait`, use dependency injection instead
99
* Add `defined` env var processor that returns `true` for defined and neither null nor empty env vars
10+
* Add `#[AutowireLocator]` attribute
1011

1112
6.3
1213
---
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests\Attribute;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
16+
use Symfony\Component\DependencyInjection\Attribute\AutowireLocator;
17+
use Symfony\Component\DependencyInjection\ContainerInterface;
18+
use Symfony\Component\DependencyInjection\Reference;
19+
20+
class AutowireLocatorTest extends TestCase
21+
{
22+
public function testSimpleLocator()
23+
{
24+
$locator = new AutowireLocator('foo', 'bar');
25+
26+
$this->assertEquals(
27+
new ServiceLocatorArgument(['foo' => new Reference('foo'), 'bar' => new Reference('bar')]),
28+
$locator->value,
29+
);
30+
}
31+
32+
public function testComplexLocator()
33+
{
34+
$locator = new AutowireLocator(
35+
'?qux',
36+
foo: 'bar',
37+
bar: '?baz',
38+
);
39+
40+
$this->assertEquals(
41+
new ServiceLocatorArgument([
42+
'qux' => new Reference('qux', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
43+
'foo' => new Reference('bar'),
44+
'bar' => new Reference('baz', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
45+
]),
46+
$locator->value,
47+
);
48+
}
49+
}

src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php

Lines changed: 68 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,24 @@
3232
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutoconfiguredInterface2;
3333
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutoconfiguredService1;
3434
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutoconfiguredService2;
35+
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutowireLocatorConsumer;
3536
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarTagClass;
3637
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooBarTaggedClass;
3738
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooBarTaggedForDefaultPriorityClass;
3839
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooTagClass;
39-
use Symfony\Component\DependencyInjection\Tests\Fixtures\IteratorConsumer;
40-
use Symfony\Component\DependencyInjection\Tests\Fixtures\IteratorConsumerWithDefaultIndexMethod;
41-
use Symfony\Component\DependencyInjection\Tests\Fixtures\IteratorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod;
42-
use Symfony\Component\DependencyInjection\Tests\Fixtures\IteratorConsumerWithDefaultPriorityMethod;
43-
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumer;
44-
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerConsumer;
45-
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerFactory;
46-
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerWithDefaultIndexMethod;
47-
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod;
48-
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerWithDefaultPriorityMethod;
49-
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerWithoutIndex;
5040
use Symfony\Component\DependencyInjection\Tests\Fixtures\StaticMethodTag;
5141
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedConsumerWithExclude;
42+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedIteratorConsumer;
43+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedIteratorConsumerWithDefaultIndexMethod;
44+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedIteratorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod;
45+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedIteratorConsumerWithDefaultPriorityMethod;
46+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedLocatorConsumer;
47+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedLocatorConsumerConsumer;
48+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedLocatorConsumerFactory;
49+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedLocatorConsumerWithDefaultIndexMethod;
50+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedLocatorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod;
51+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedLocatorConsumerWithDefaultPriorityMethod;
52+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedLocatorConsumerWithoutIndex;
5253
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService1;
5354
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService2;
5455
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService3;
@@ -388,6 +389,30 @@ public function testTaggedServiceWithIndexAttributeAndDefaultMethod()
388389
$this->assertSame(['bar_tab_class_with_defaultmethod' => $container->get(BarTagClass::class), 'foo' => $container->get(FooTagClass::class)], $param);
389390
}
390391

392+
public function testLocatorConfiguredViaAttribute()
393+
{
394+
$container = new ContainerBuilder();
395+
$container->register(BarTagClass::class)
396+
->setPublic(true)
397+
;
398+
$container->register(FooTagClass::class)
399+
->setPublic(true)
400+
;
401+
$container->register(AutowireLocatorConsumer::class)
402+
->setAutowired(true)
403+
->setPublic(true)
404+
;
405+
406+
$container->compile();
407+
408+
/** @var AutowireLocatorConsumer $s */
409+
$s = $container->get(AutowireLocatorConsumer::class);
410+
411+
self::assertSame($container->get(BarTagClass::class), $s->locator->get(BarTagClass::class));
412+
self::assertSame($container->get(FooTagClass::class), $s->locator->get('with_key'));
413+
self::assertFalse($s->locator->has('nullable'));
414+
}
415+
391416
public function testTaggedServiceWithIndexAttributeAndDefaultMethodConfiguredViaAttribute()
392417
{
393418
$container = new ContainerBuilder();
@@ -399,14 +424,14 @@ public function testTaggedServiceWithIndexAttributeAndDefaultMethodConfiguredVia
399424
->setPublic(true)
400425
->addTag('foo_bar', ['foo' => 'foo'])
401426
;
402-
$container->register(IteratorConsumer::class)
427+
$container->register(TaggedIteratorConsumer::class)
403428
->setAutowired(true)
404429
->setPublic(true)
405430
;
406431

407432
$container->compile();
408433

409-
$s = $container->get(IteratorConsumer::class);
434+
$s = $container->get(TaggedIteratorConsumer::class);
410435

411436
$param = iterator_to_array($s->getParam()->getIterator());
412437
$this->assertSame(['bar_tab_class_with_defaultmethod' => $container->get(BarTagClass::class), 'foo' => $container->get(FooTagClass::class)], $param);
@@ -423,14 +448,14 @@ public function testTaggedIteratorWithDefaultIndexMethodConfiguredViaAttribute()
423448
->setPublic(true)
424449
->addTag('foo_bar')
425450
;
426-
$container->register(IteratorConsumerWithDefaultIndexMethod::class)
451+
$container->register(TaggedIteratorConsumerWithDefaultIndexMethod::class)
427452
->setAutowired(true)
428453
->setPublic(true)
429454
;
430455

431456
$container->compile();
432457

433-
$s = $container->get(IteratorConsumerWithDefaultIndexMethod::class);
458+
$s = $container->get(TaggedIteratorConsumerWithDefaultIndexMethod::class);
434459

435460
$param = iterator_to_array($s->getParam()->getIterator());
436461
$this->assertSame(['bar_tag_class' => $container->get(BarTagClass::class), 'foo_tag_class' => $container->get(FooTagClass::class)], $param);
@@ -447,14 +472,14 @@ public function testTaggedIteratorWithDefaultPriorityMethodConfiguredViaAttribut
447472
->setPublic(true)
448473
->addTag('foo_bar')
449474
;
450-
$container->register(IteratorConsumerWithDefaultPriorityMethod::class)
475+
$container->register(TaggedIteratorConsumerWithDefaultPriorityMethod::class)
451476
->setAutowired(true)
452477
->setPublic(true)
453478
;
454479

455480
$container->compile();
456481

457-
$s = $container->get(IteratorConsumerWithDefaultPriorityMethod::class);
482+
$s = $container->get(TaggedIteratorConsumerWithDefaultPriorityMethod::class);
458483

459484
$param = iterator_to_array($s->getParam()->getIterator());
460485
$this->assertSame([0 => $container->get(FooTagClass::class), 1 => $container->get(BarTagClass::class)], $param);
@@ -471,14 +496,14 @@ public function testTaggedIteratorWithDefaultIndexMethodAndWithDefaultPriorityMe
471496
->setPublic(true)
472497
->addTag('foo_bar')
473498
;
474-
$container->register(IteratorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod::class)
499+
$container->register(TaggedIteratorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod::class)
475500
->setAutowired(true)
476501
->setPublic(true)
477502
;
478503

479504
$container->compile();
480505

481-
$s = $container->get(IteratorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod::class);
506+
$s = $container->get(TaggedIteratorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod::class);
482507

483508
$param = iterator_to_array($s->getParam()->getIterator());
484509
$this->assertSame(['foo_tag_class' => $container->get(FooTagClass::class), 'bar_tag_class' => $container->get(BarTagClass::class)], $param);
@@ -495,15 +520,15 @@ public function testTaggedLocatorConfiguredViaAttribute()
495520
->setPublic(true)
496521
->addTag('foo_bar', ['foo' => 'foo'])
497522
;
498-
$container->register(LocatorConsumer::class)
523+
$container->register(TaggedLocatorConsumer::class)
499524
->setAutowired(true)
500525
->setPublic(true)
501526
;
502527

503528
$container->compile();
504529

505-
/** @var LocatorConsumer $s */
506-
$s = $container->get(LocatorConsumer::class);
530+
/** @var TaggedLocatorConsumer $s */
531+
$s = $container->get(TaggedLocatorConsumer::class);
507532

508533
$locator = $s->getLocator();
509534
self::assertSame($container->get(BarTagClass::class), $locator->get('bar_tab_class_with_defaultmethod'));
@@ -521,15 +546,15 @@ public function testTaggedLocatorConfiguredViaAttributeWithoutIndex()
521546
->setPublic(true)
522547
->addTag('foo_bar')
523548
;
524-
$container->register(LocatorConsumerWithoutIndex::class)
549+
$container->register(TaggedLocatorConsumerWithoutIndex::class)
525550
->setAutowired(true)
526551
->setPublic(true)
527552
;
528553

529554
$container->compile();
530555

531-
/** @var LocatorConsumerWithoutIndex $s */
532-
$s = $container->get(LocatorConsumerWithoutIndex::class);
556+
/** @var TaggedLocatorConsumerWithoutIndex $s */
557+
$s = $container->get(TaggedLocatorConsumerWithoutIndex::class);
533558

534559
$locator = $s->getLocator();
535560
self::assertSame($container->get(BarTagClass::class), $locator->get(BarTagClass::class));
@@ -547,15 +572,15 @@ public function testTaggedLocatorWithDefaultIndexMethodConfiguredViaAttribute()
547572
->setPublic(true)
548573
->addTag('foo_bar')
549574
;
550-
$container->register(LocatorConsumerWithDefaultIndexMethod::class)
575+
$container->register(TaggedLocatorConsumerWithDefaultIndexMethod::class)
551576
->setAutowired(true)
552577
->setPublic(true)
553578
;
554579

555580
$container->compile();
556581

557-
/** @var LocatorConsumerWithoutIndex $s */
558-
$s = $container->get(LocatorConsumerWithDefaultIndexMethod::class);
582+
/** @var TaggedLocatorConsumerWithoutIndex $s */
583+
$s = $container->get(TaggedLocatorConsumerWithDefaultIndexMethod::class);
559584

560585
$locator = $s->getLocator();
561586
self::assertSame($container->get(BarTagClass::class), $locator->get('bar_tag_class'));
@@ -573,15 +598,15 @@ public function testTaggedLocatorWithDefaultPriorityMethodConfiguredViaAttribute
573598
->setPublic(true)
574599
->addTag('foo_bar')
575600
;
576-
$container->register(LocatorConsumerWithDefaultPriorityMethod::class)
601+
$container->register(TaggedLocatorConsumerWithDefaultPriorityMethod::class)
577602
->setAutowired(true)
578603
->setPublic(true)
579604
;
580605

581606
$container->compile();
582607

583-
/** @var LocatorConsumerWithoutIndex $s */
584-
$s = $container->get(LocatorConsumerWithDefaultPriorityMethod::class);
608+
/** @var TaggedLocatorConsumerWithoutIndex $s */
609+
$s = $container->get(TaggedLocatorConsumerWithDefaultPriorityMethod::class);
585610

586611
$locator = $s->getLocator();
587612

@@ -602,15 +627,15 @@ public function testTaggedLocatorWithDefaultIndexMethodAndWithDefaultPriorityMet
602627
->setPublic(true)
603628
->addTag('foo_bar')
604629
;
605-
$container->register(LocatorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod::class)
630+
$container->register(TaggedLocatorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod::class)
606631
->setAutowired(true)
607632
->setPublic(true)
608633
;
609634

610635
$container->compile();
611636

612-
/** @var LocatorConsumerWithoutIndex $s */
613-
$s = $container->get(LocatorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod::class);
637+
/** @var TaggedLocatorConsumerWithoutIndex $s */
638+
$s = $container->get(TaggedLocatorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod::class);
614639

615640
$locator = $s->getLocator();
616641

@@ -629,18 +654,18 @@ public function testNestedDefinitionWithAutoconfiguredConstructorArgument()
629654
->setPublic(true)
630655
->addTag('foo_bar', ['foo' => 'foo'])
631656
;
632-
$container->register(LocatorConsumerConsumer::class)
657+
$container->register(TaggedLocatorConsumerConsumer::class)
633658
->setPublic(true)
634659
->setArguments([
635-
(new Definition(LocatorConsumer::class))
660+
(new Definition(TaggedLocatorConsumer::class))
636661
->setAutowired(true),
637662
])
638663
;
639664

640665
$container->compile();
641666

642-
/** @var LocatorConsumerConsumer $s */
643-
$s = $container->get(LocatorConsumerConsumer::class);
667+
/** @var TaggedLocatorConsumerConsumer $s */
668+
$s = $container->get(TaggedLocatorConsumerConsumer::class);
644669

645670
$locator = $s->getLocatorConsumer()->getLocator();
646671
self::assertSame($container->get(FooTagClass::class), $locator->get('foo'));
@@ -653,17 +678,17 @@ public function testFactoryWithAutoconfiguredArgument()
653678
->setPublic(true)
654679
->addTag('foo_bar', ['key' => 'my_service'])
655680
;
656-
$container->register(LocatorConsumerFactory::class);
657-
$container->register(LocatorConsumer::class)
681+
$container->register(TaggedLocatorConsumerFactory::class);
682+
$container->register(TaggedLocatorConsumer::class)
658683
->setPublic(true)
659684
->setAutowired(true)
660-
->setFactory(new Reference(LocatorConsumerFactory::class))
685+
->setFactory(new Reference(TaggedLocatorConsumerFactory::class))
661686
;
662687

663688
$container->compile();
664689

665-
/** @var LocatorConsumer $s */
666-
$s = $container->get(LocatorConsumer::class);
690+
/** @var TaggedLocatorConsumer $s */
691+
$s = $container->get(TaggedLocatorConsumer::class);
667692

668693
$locator = $s->getLocator();
669694
self::assertSame($container->get(FooTagClass::class), $locator->get('my_service'));

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy