Skip to content

Commit

Permalink
feat: support Graceful annotation per Attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
ph-fritsche committed May 12, 2021
1 parent 172e1c9 commit facba40
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 5 deletions.
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ use Pitch\AdrBundle\Configuration\Graceful;
class MyController
{
/**
* @Graceful(not={LocallyBadException::class})
* @Graceful(not=LocallyBadException::class)
* @Graceful(LocallyGoodException::class, not={ButNotThisOne::class, OrThatOne::class})
*/
public function __invoke(
Expand All @@ -91,6 +91,24 @@ class MyController
}
```

With PHP8 you can define extra rules per [Attribute](https://www.php.net/manual/en/language.attributes.overview.php):
```php
namespace App\Controller;

use Pitch\AdrBundle\Configuration\Graceful;

class MyController
{
#[Graceful(not: LocallyBadException::class)]
#[Graceful(LocallyGoodException::class, not: [ButNotThisOne::class, OrThatOne::class])]
public function __invoke(
Request $request
) {
/// ...
}
}
```

Rules are applied in the order of appearance, method rules after global rules.

Now you can just create a `App\Responder\MyGoodRuntimeExceptionHandler` as described above.
Expand Down
5 changes: 2 additions & 3 deletions src/Configuration/Graceful.php
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
<?php
namespace Pitch\AdrBundle\Configuration;

use Attribute;
use Doctrine\Common\Annotations\Annotation;
use Doctrine\Common\Annotations\Annotation\Target;

/**
* @Annotation
* @Target({"METHOD"})
*/
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
class Graceful extends ConfigurationAnnotation
{
const ALLOW_ARRAY = true;
const ALIAS_NAME = 'gracefulException';

public ?string $value = null;

public array $not = [];
Expand Down
17 changes: 16 additions & 1 deletion src/EventSubscriber/ControllerSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use Doctrine\Common\Annotations\Reader;
use Pitch\AdrBundle\Action\ActionProxy;
use Pitch\AdrBundle\Configuration\Graceful;
use ReflectionAttribute;
use ReflectionMethod;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
Expand Down Expand Up @@ -44,7 +45,21 @@ public function onKernelController(ControllerEvent $event)
? $this->reader->getMethodAnnotations($reflMethod)
: [];

$event->getRequest()->attributes->set('_' . Graceful::class, $annotations);
$attributes = PHP_MAJOR_VERSION >= 8
? \array_map(
function (ReflectionAttribute $a) {
$class = $a->getName();
$args = $a->getArguments();
if (isset($args[0]) && \is_array($args[0])) {
return $a->newInstance();
}
return new $class(['value' => $args[0], 'not' => $args['not']]);
},
$reflMethod->getAttributes(Graceful::class, ReflectionAttribute::IS_INSTANCEOF),
)
: [];

$event->getRequest()->attributes->set('_' . Graceful::class, [...$annotations, ...$attributes]);
}

public function onKernelControllerArguments(ControllerArgumentsEvent $event)
Expand Down
22 changes: 22 additions & 0 deletions test/EventSubscriber/ControllerSubscriberTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,28 @@ public function __invoke()
], $event->getRequest()->attributes->get('_' . Graceful::class));
}

public function testReadAttributes()
{
$event = $this->getControllerEvent(new class {
#[Graceful(['value' => 'Foo'])]
#[Graceful('Bar', not: 'Baz')]
public function __invoke()
{
}
});

$this->getSubscriberObject([], false)->onKernelController($event);
$this->assertEquals(
PHP_MAJOR_VERSION >= 8
? [
new Graceful(['value' => 'Foo']),
new Graceful(['value' => 'Bar', 'not' => 'Baz']),
]
: [],
$event->getRequest()->attributes->get('_' . Graceful::class)
);
}

public function provideGraceful(): array
{
return [
Expand Down

0 comments on commit facba40

Please sign in to comment.