Skip to content

Commit

Permalink
fix: remove dependency on SensioFrameworkExtraBundle
Browse files Browse the repository at this point in the history
  • Loading branch information
ph-fritsche committed May 12, 2021
1 parent 50086c1 commit 172e1c9
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 115 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pitch_adr:
- { value: Bar, not: BadBar }
```

If [SensioFrameworkExtraBundle](https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/index.html) is installed,
If [Doctrine Annotations](https://github.com/doctrine/annotations/) is installed,
you can define extra rules for your controller methods per annotation:
```php
namespace App\Controller;
Expand All @@ -80,8 +80,8 @@ use Pitch\AdrBundle\Configuration\Graceful;
class MyController
{
/**
* @Graceful(not={LocallyBadException})
* @Graceful(LocallyGoodException, not={ButNotThisOne, OrThatOne})
* @Graceful(not={LocallyBadException::class})
* @Graceful(LocallyGoodException::class, not={ButNotThisOne::class, OrThatOne::class})
*/
public function __invoke(
Request $request
Expand Down
8 changes: 3 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,11 @@
},
"require-dev": {
"phpunit/phpunit": "^9",
"sensio/framework-extra-bundle": "^6",
"symfony/framework-bundle": "^5",
"squizlabs/php_codesniffer": "^3.2",
"symfony/yaml": "^5",
"mikey179/vfsstream": "^1.6"
},
"suggest": {
"sensio/framework-extra-bundle": "^6"
"mikey179/vfsstream": "^1.6",
"doctrine/annotations": "^1.12"
},
"scripts": {
"lint": "phpcs --standard=ruleset.xml src test",
Expand Down
80 changes: 1 addition & 79 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 28 additions & 13 deletions src/Configuration/ConfigurationAnnotation.php
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
<?php
namespace Pitch\AdrBundle\Configuration;

use ReflectionMethod;
use ReflectionNamedType;
use ReflectionProperty;
use ReflectionType;
use RuntimeException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;

abstract class ConfigurationAnnotation implements ConfigurationInterface
abstract class ConfigurationAnnotation
{
const ALLOW_ARRAY = false;
const ALIAS_NAME = null;

public function __construct(
array $values = []
) {
foreach ($values as $propertyName => $v) {
$setterName = 'set' . \ucwords($propertyName);
if (\method_exists($this, $setterName)) {
$reflMethod = new ReflectionMethod($this, $setterName);

$this->typecast(
$v,
$reflMethod->getNumberOfParameters() >= 1
? $reflMethod->getParameters()[0]->getType()
: null,
);

$this->$setterName($v);
} elseif (\property_exists($this, $propertyName)) {
$reflProp = new ReflectionProperty($this, $propertyName);

$this->typecast($v, $reflProp->getType());

$this->$propertyName = $v;
} else {
throw new RuntimeException(\sprintf(
Expand All @@ -28,13 +41,15 @@ public function __construct(
}
}

public function allowArray(): bool
{
return static::ALLOW_ARRAY;
}

public function getAliasName(): ?string
{
return static::ALIAS_NAME;
private function typecast(
&$value,
?ReflectionType $type,
) {
if ($type instanceof ReflectionNamedType
&& gettype($value) !== $type->getName()
&& !is_a($value, $type->getName())
) {
settype($value, $type->getName());
}
}
}
26 changes: 25 additions & 1 deletion src/EventSubscriber/ControllerSubscriber.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
<?php
namespace Pitch\AdrBundle\EventSubscriber;

use Doctrine\Common\Annotations\Reader;
use Pitch\AdrBundle\Action\ActionProxy;
use Pitch\AdrBundle\Configuration\Graceful;
use ReflectionMethod;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use Symfony\Component\HttpKernel\Event\ControllerEvent;

class ControllerSubscriber implements EventSubscriberInterface
{
private ?Reader $reader;
private array $globalGraceful;

public function __construct(
?Reader $reader,
?array $globalGraceful
) {
$this->reader = $reader;
$this->globalGraceful = \array_map(fn($g) => new Graceful($g), (array) $globalGraceful);
}

Expand All @@ -24,9 +30,27 @@ public static function getSubscribedEvents()
];
}

public function onKernelController(ControllerEvent $event)
{
$controller = $event->getController();

if (\is_object($controller)) {
$controller = [$controller, '__invoke'];
}

$reflMethod = new ReflectionMethod($controller[0], $controller[1]);

$annotations = $this->reader
? $this->reader->getMethodAnnotations($reflMethod)
: [];

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

public function onKernelControllerArguments(ControllerArgumentsEvent $event)
{
$graceful = (array) $event->getRequest()->attributes->get('_' . Graceful::ALIAS_NAME);

$graceful = (array) $event->getRequest()->attributes->get('_' . Graceful::class);

if (\count($this->globalGraceful) === 0 && \count($graceful) === 0) {
return;
Expand Down
11 changes: 0 additions & 11 deletions test/Configuration/ConfigurationAnnotationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,6 @@

class ConfigurationAnnotationTest extends \PHPUnit\Framework\TestCase
{
public function testConfigurationInterface()
{
$testClass = new class() extends ConfigurationAnnotation {
const ALIAS_NAME = 'foo';
const ALLOW_ARRAY = true;
};

$this->assertEquals($testClass::ALIAS_NAME, $testClass->getAliasName());
$this->assertEquals($testClass::ALLOW_ARRAY, $testClass->allowArray());
}

public function testConstructWithProperty()
{
$testClass = new class([
Expand Down
47 changes: 44 additions & 3 deletions test/EventSubscriber/ControllerSubscriberTest.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
<?php
namespace Pitch\AdrBundle\EventSubscriber;

use Doctrine\Common\Annotations\AnnotationReader;
use Pitch\AdrBundle\Action\ActionProxy;
use Pitch\AdrBundle\Configuration\Graceful;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use Symfony\Component\HttpKernel\Event\ControllerEvent;

class ControllerSubscriberTest extends EventSubscriberTest
{
public function testReadAnnotations()
{
$event = $this->getControllerEvent(new class {
/**
* @Graceful("Foo")
* @Graceful("Bar", not={"Baz"})
*/
public function __invoke()
{
}
});

// without Doctrine Annotations
$this->getSubscriberObject([], false)->onKernelController($event);
$this->assertEquals([], $event->getRequest()->attributes->get('_' . Graceful::class));

// with Doctrine Annotations
$this->getSubscriberObject([], true)->onKernelController($event);
$this->assertEquals([
new Graceful(['value' => 'Foo']),
new Graceful(['value' => 'Bar', 'not' => 'Baz']),
], $event->getRequest()->attributes->get('_' . Graceful::class));
}

public function provideGraceful(): array
{
return [
Expand Down Expand Up @@ -81,14 +107,25 @@ protected function getGracefulForArray(
return \array_map(fn($g) => new Graceful($g), $gracefulList);
}

protected function getControllerEvent(
callable $controller,
): ControllerEvent {
return new ControllerEvent(
$this->createMock(HttpKernelInterface::class),
$controller,
new Request(),
HttpKernelInterface::MASTER_REQUEST,
);
}

/**
* @param Graceful[] $controllerGraceful
*/
protected function getControllerArgumentsEvent(
array $controllerGraceful
): ControllerArgumentsEvent {
$request = new Request();
$request->attributes->set('_' . Graceful::ALIAS_NAME, $controllerGraceful);
$request->attributes->set('_' . Graceful::class, $controllerGraceful);

return new ControllerArgumentsEvent(
$this->createMock(HttpKernelInterface::class),
Expand All @@ -101,8 +138,12 @@ function () {
}

protected function getSubscriberObject(
array $globalGraceful = []
array $globalGraceful = [],
bool $reader = false,
): ControllerSubscriber {
return new ControllerSubscriber($globalGraceful);
return new ControllerSubscriber(
$reader ? new AnnotationReader() : null,
$globalGraceful,
);
}
}

0 comments on commit 172e1c9

Please sign in to comment.