Skip to content

Commit d25e6fb

Browse files
committed
[HttpKernel] Add optional $className param to ControllerEvent::getAttributes()
1 parent 398830c commit d25e6fb

File tree

7 files changed

+108
-23
lines changed

7 files changed

+108
-23
lines changed

src/Symfony/Component/HttpKernel/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ CHANGELOG
1515
* Add `#[MapQueryString]` to map and validate request query string from `Request::$query->all()` to typed objects
1616
* Add `#[MapQueryParameter]` to map and validate individual query parameters to controller arguments
1717
* Collect data from every event dispatcher
18+
* Add optional `$className` parameter to `ControllerEvent::getAttributes()`
1819

1920
6.2
2021
---

src/Symfony/Component/HttpKernel/Event/ControllerArgumentsEvent.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,16 @@ public function getNamedArguments(): array
9494
}
9595

9696
/**
97-
* @return array<class-string, list<object>>
97+
* @template T of class-string|null
98+
*
99+
* @param T $className
100+
*
101+
* @return array<class-string, list<object>>|list<object>
102+
*
103+
* @psalm-return (T is null ? array<class-string, list<object>> : list<object>)
98104
*/
99-
public function getAttributes(): array
105+
public function getAttributes(string $className = null): array
100106
{
101-
return $this->controllerEvent->getAttributes();
107+
return $this->controllerEvent->getAttributes($className);
102108
}
103109
}

src/Symfony/Component/HttpKernel/Event/ControllerEvent.php

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -79,29 +79,33 @@ public function setController(callable $controller, array $attributes = null): v
7979
}
8080

8181
/**
82-
* @return array<class-string, list<object>>
82+
* @template T of class-string|null
83+
*
84+
* @param T $className
85+
*
86+
* @return array<class-string, list<object>>|list<object>
87+
*
88+
* @psalm-return (T is null ? array<class-string, list<object>> : list<object>)
8389
*/
84-
public function getAttributes(): array
90+
public function getAttributes(string $className = null): array
8591
{
86-
if (isset($this->attributes)) {
87-
return $this->attributes;
88-
}
89-
90-
if (\is_array($this->controller) && method_exists(...$this->controller)) {
91-
$class = new \ReflectionClass($this->controller[0]);
92-
} elseif (\is_string($this->controller) && false !== $i = strpos($this->controller, '::')) {
93-
$class = new \ReflectionClass(substr($this->controller, 0, $i));
94-
} else {
95-
$class = str_contains($this->controllerReflector->name, '{closure}') ? null : (\PHP_VERSION_ID >= 80111 ? $this->controllerReflector->getClosureCalledClass() : $this->controllerReflector->getClosureScopeClass());
96-
}
97-
$this->attributes = [];
92+
if (!isset($this->attributes)) {
93+
if (\is_array($this->controller) && method_exists(...$this->controller)) {
94+
$class = new \ReflectionClass($this->controller[0]);
95+
} elseif (\is_string($this->controller) && false !== $i = strpos($this->controller, '::')) {
96+
$class = new \ReflectionClass(substr($this->controller, 0, $i));
97+
} else {
98+
$class = str_contains($this->controllerReflector->name, '{closure}') ? null : (\PHP_VERSION_ID >= 80111 ? $this->controllerReflector->getClosureCalledClass() : $this->controllerReflector->getClosureScopeClass());
99+
}
100+
$this->attributes = [];
98101

99-
foreach (array_merge($class?->getAttributes() ?? [], $this->controllerReflector->getAttributes()) as $attribute) {
100-
if (class_exists($attribute->getName())) {
101-
$this->attributes[$attribute->getName()][] = $attribute->newInstance();
102+
foreach (array_merge($class?->getAttributes() ?? [], $this->controllerReflector->getAttributes()) as $attribute) {
103+
if (class_exists($attribute->getName())) {
104+
$this->attributes[$attribute->getName()][] = $attribute->newInstance();
105+
}
102106
}
103107
}
104108

105-
return $this->attributes;
109+
return null === $className ? $this->attributes : $this->attributes[$className] ?? [];
106110
}
107111
}

src/Symfony/Component/HttpKernel/Tests/Event/ControllerArgumentsEventTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\HttpKernel\Event\ControllerEvent;
1818
use Symfony\Component\HttpKernel\HttpKernelInterface;
1919
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Bar;
20+
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Baz;
2021
use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\AttributeController;
2122
use Symfony\Component\HttpKernel\Tests\TestHttpKernel;
2223

@@ -51,6 +52,9 @@ public function testGetAttributes()
5152
new Bar('class'),
5253
new Bar('method'),
5354
],
55+
Baz::class => [
56+
new Baz(),
57+
],
5458
];
5559

5660
$this->assertEquals($expected, $event->getAttributes());
@@ -61,4 +65,27 @@ public function testGetAttributes()
6165
$this->assertEquals($expected, $event->getAttributes());
6266
$this->assertSame($controllerEvent->getAttributes(), $event->getAttributes());
6367
}
68+
69+
public function testGetAttributesByClassName()
70+
{
71+
$controller = new AttributeController();
72+
$request = new Request();
73+
74+
$controllerEvent = new ControllerEvent(new TestHttpKernel(), $controller, $request, HttpKernelInterface::MAIN_REQUEST);
75+
76+
$event = new ControllerArgumentsEvent(new TestHttpKernel(), $controllerEvent, ['test'], new Request(), HttpKernelInterface::MAIN_REQUEST);
77+
78+
$expected = [
79+
new Bar('class'),
80+
new Bar('method'),
81+
];
82+
83+
$this->assertEquals($expected, $event->getAttributes(Bar::class));
84+
85+
$expected[] = new Bar('foo');
86+
$event->setController($controller, [Bar::class => $expected]);
87+
88+
$this->assertEquals($expected, $event->getAttributes(Bar::class));
89+
$this->assertSame($controllerEvent->getAttributes(Bar::class), $event->getAttributes(Bar::class));
90+
}
6491
}

src/Symfony/Component/HttpKernel/Tests/Event/ControllerEventTest.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\HttpKernel\Event\ControllerEvent;
1717
use Symfony\Component\HttpKernel\HttpKernelInterface;
1818
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Bar;
19+
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Baz;
1920
use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\AttributeController;
2021
use Symfony\Component\HttpKernel\Tests\TestHttpKernel;
2122

@@ -33,16 +34,44 @@ public function testGetAttributes(callable $controller)
3334
new Bar('class'),
3435
new Bar('method'),
3536
],
37+
Baz::class => [
38+
new Baz(),
39+
],
3640
];
3741

3842
$this->assertEquals($expected, $event->getAttributes());
3943
}
4044

45+
/**
46+
* @dataProvider provideGetAttributes
47+
*/
48+
public function testGetAttributesByClassName(callable $controller)
49+
{
50+
$event = new ControllerEvent(new TestHttpKernel(), $controller, new Request(), HttpKernelInterface::MAIN_REQUEST);
51+
52+
$expected = [
53+
new Bar('class'),
54+
new Bar('method'),
55+
];
56+
57+
$this->assertEquals($expected, $event->getAttributes(Bar::class));
58+
}
59+
60+
/**
61+
* @dataProvider provideGetAttributes
62+
*/
63+
public function testGetAttributesByInvalidClassName(callable $controller)
64+
{
65+
$event = new ControllerEvent(new TestHttpKernel(), $controller, new Request(), HttpKernelInterface::MAIN_REQUEST);
66+
67+
$this->assertEquals([], $event->getAttributes(\stdClass::class));
68+
}
69+
4170
public static function provideGetAttributes()
4271
{
4372
yield [[new AttributeController(), '__invoke']];
4473
yield [new AttributeController()];
4574
yield [(new AttributeController())->__invoke(...)];
46-
yield [#[Bar('class'), Bar('method')] static function () {}];
75+
yield [#[Bar('class'), Bar('method'), Baz] static function () {}];
4776
}
4877
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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\HttpKernel\Tests\Fixtures\Attribute;
13+
14+
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::TARGET_FUNCTION | \Attribute::IS_REPEATABLE)]
15+
class Baz
16+
{
17+
}

src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/AttributeController.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller;
1313

1414
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Bar;
15+
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Baz;
1516
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Foo;
1617

1718
#[Bar('class'), Undefined('class')]
1819
class AttributeController
1920
{
20-
#[Bar('method'), Undefined('method')]
21+
#[Bar('method'), Baz, Undefined('method')]
2122
public function __invoke()
2223
{
2324
}

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