Skip to content

Commit

Permalink
feature #50335 [HttpKernel] Add optional $className param to `Contr…
Browse files Browse the repository at this point in the history
…ollerEvent::getAttributes()` (HypeMC)

This PR was merged into the 6.4 branch.

Discussion
----------

[HttpKernel] Add optional `$className` param to `ControllerEvent::getAttributes()`

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | -
| License       | MIT
| Doc PR        | -

A minor DX improvement since most of the time only one type of attribute is needed, eg:

```php
public function onKernelControllerArguments(ControllerArgumentsEvent $event)
{
    $attributes = $event->getAttributes(SomeAttribute::class);

    // ...
}
```

Commits
-------

a45cc65 [HttpKernel] Add optional $className param to ControllerEvent::getAttributes()
  • Loading branch information
fabpot committed Jun 3, 2023
2 parents ad0a032 + a45cc65 commit 08b5907
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 9 deletions.
5 changes: 5 additions & 0 deletions src/Symfony/Component/HttpKernel/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========

6.4
---

* Add optional `$className` parameter to `ControllerEvent::getAttributes()`

6.3
---

Expand Down
Expand Up @@ -94,10 +94,16 @@ public function getNamedArguments(): array
}

/**
* @return array<class-string, list<object>>
* @template T of class-string|null
*
* @param T $className
*
* @return array<class-string, list<object>>|list<object>
*
* @psalm-return (T is null ? array<class-string, list<object>> : list<object>)
*/
public function getAttributes(): array
public function getAttributes(string $className = null): array
{
return $this->controllerEvent->getAttributes();
return $this->controllerEvent->getAttributes($className);
}
}
14 changes: 10 additions & 4 deletions src/Symfony/Component/HttpKernel/Event/ControllerEvent.php
Expand Up @@ -79,12 +79,18 @@ public function setController(callable $controller, array $attributes = null): v
}

/**
* @return array<class-string, list<object>>
* @template T of class-string|null
*
* @param T $className
*
* @return array<class-string, list<object>>|list<object>
*
* @psalm-return (T is null ? array<class-string, list<object>> : list<object>)
*/
public function getAttributes(): array
public function getAttributes(string $className = null): array
{
if (isset($this->attributes)) {
return $this->attributes;
return null === $className ? $this->attributes : $this->attributes[$className] ?? [];
}

if (\is_array($this->controller) && method_exists(...$this->controller)) {
Expand All @@ -102,6 +108,6 @@ public function getAttributes(): array
}
}

return $this->attributes;
return null === $className ? $this->attributes : $this->attributes[$className] ?? [];
}
}
Expand Up @@ -17,6 +17,7 @@
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Bar;
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Baz;
use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\AttributeController;
use Symfony\Component\HttpKernel\Tests\TestHttpKernel;

Expand Down Expand Up @@ -51,6 +52,9 @@ public function testGetAttributes()
new Bar('class'),
new Bar('method'),
],
Baz::class => [
new Baz(),
],
];

$this->assertEquals($expected, $event->getAttributes());
Expand All @@ -61,4 +65,27 @@ public function testGetAttributes()
$this->assertEquals($expected, $event->getAttributes());
$this->assertSame($controllerEvent->getAttributes(), $event->getAttributes());
}

public function testGetAttributesByClassName()
{
$controller = new AttributeController();
$request = new Request();

$controllerEvent = new ControllerEvent(new TestHttpKernel(), $controller, $request, HttpKernelInterface::MAIN_REQUEST);

$event = new ControllerArgumentsEvent(new TestHttpKernel(), $controllerEvent, ['test'], new Request(), HttpKernelInterface::MAIN_REQUEST);

$expected = [
new Bar('class'),
new Bar('method'),
];

$this->assertEquals($expected, $event->getAttributes(Bar::class));

$expected[] = new Bar('foo');
$event->setController($controller, [Bar::class => $expected]);

$this->assertEquals($expected, $event->getAttributes(Bar::class));
$this->assertSame($controllerEvent->getAttributes(Bar::class), $event->getAttributes(Bar::class));
}
}
Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Bar;
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Baz;
use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\AttributeController;
use Symfony\Component\HttpKernel\Tests\TestHttpKernel;

Expand All @@ -33,16 +34,44 @@ public function testGetAttributes(callable $controller)
new Bar('class'),
new Bar('method'),
],
Baz::class => [
new Baz(),
],
];

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

/**
* @dataProvider provideGetAttributes
*/
public function testGetAttributesByClassName(callable $controller)
{
$event = new ControllerEvent(new TestHttpKernel(), $controller, new Request(), HttpKernelInterface::MAIN_REQUEST);

$expected = [
new Bar('class'),
new Bar('method'),
];

$this->assertEquals($expected, $event->getAttributes(Bar::class));
}

/**
* @dataProvider provideGetAttributes
*/
public function testGetAttributesByInvalidClassName(callable $controller)
{
$event = new ControllerEvent(new TestHttpKernel(), $controller, new Request(), HttpKernelInterface::MAIN_REQUEST);

$this->assertEquals([], $event->getAttributes(\stdClass::class));
}

public static function provideGetAttributes()
{
yield [[new AttributeController(), '__invoke']];
yield [new AttributeController()];
yield [(new AttributeController())->__invoke(...)];
yield [#[Bar('class'), Bar('method')] static function () {}];
yield [#[Bar('class'), Bar('method'), Baz] static function () {}];
}
}
17 changes: 17 additions & 0 deletions src/Symfony/Component/HttpKernel/Tests/Fixtures/Attribute/Baz.php
@@ -0,0 +1,17 @@
<?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\HttpKernel\Tests\Fixtures\Attribute;

#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::TARGET_FUNCTION | \Attribute::IS_REPEATABLE)]
class Baz
{
}
Expand Up @@ -12,12 +12,13 @@
namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller;

use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Bar;
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Baz;
use Symfony\Component\HttpKernel\Tests\Fixtures\Attribute\Foo;

#[Bar('class'), Undefined('class')]
class AttributeController
{
#[Bar('method'), Undefined('method')]
#[Bar('method'), Baz, Undefined('method')]
public function __invoke()
{
}
Expand Down

0 comments on commit 08b5907

Please sign in to comment.