Skip to content
This repository has been archived by the owner on Feb 24, 2023. It is now read-only.

Commit

Permalink
bug #728 Don't skip interfaces for auto-conversion (derrabus)
Browse files Browse the repository at this point in the history
This PR was merged into the 6.1.x-dev branch.

Discussion
----------

Don't skip interfaces for auto-conversion

This PR fixes a problem introduced by #727. Before said patch, configuring a param converter for an interface was possible. I've added a test to make sure that this use-case does not break again. In addition to that, I've simplified the code a bit.

Commits
-------

8ba95d0 Don't skip interfaces for auto-conversion
  • Loading branch information
fabpot committed May 17, 2021
2 parents 0cb9054 + 8ba95d0 commit d962626
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 21 deletions.
13 changes: 3 additions & 10 deletions src/EventListener/ParamConverterListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,19 +106,12 @@ private function autoConfigure(\ReflectionFunctionAbstract $r, Request $request,

private function getParamClassByType(?\ReflectionType $type): ?string
{
if (\PHP_VERSION_ID < 80000) {
return (null === $type || $type->isBuiltin() || !$type instanceof \ReflectionNamedType) ?
null : $type->getName();
if (null === $type) {
return null;
}

foreach ($type instanceof \ReflectionUnionType ? $type->getTypes() : [$type] as $type) {
if (null === $type || $type->isBuiltin() || !$type instanceof \ReflectionNamedType) {
continue;
}

$class = new \ReflectionClass($type->getName());

if (!$class->isInterface() && !$class->isAbstract()) {
if (!$type->isBuiltin()) {
return $type->getName();
}
}
Expand Down
10 changes: 10 additions & 0 deletions tests/EventListener/Fixture/InvokableControllerWithUnion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener\Fixture;

final class InvokableControllerWithUnion
{
public function __invoke(int | \DateTime | string $date)
{
}
}
48 changes: 37 additions & 11 deletions tests/EventListener/ParamConverterListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,24 @@

namespace Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener;

use PHPUnit\Framework\TestCase;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\EventListener\ParamConverterListener;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterManager;
use Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener\Fixture\FooControllerNullableParameter;
use Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener\Fixture\InvokableControllerWithUnion;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class ParamConverterListenerTest extends \PHPUnit\Framework\TestCase
class ParamConverterListenerTest extends TestCase
{
/**
* @dataProvider getControllerWithNoArgsFixtures
*/
public function testRequestIsSkipped($controllerCallable)
{
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
$kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock();
$request = new Request();

$listener = new ParamConverterListener($this->getParamConverterManager($request, []));
Expand All @@ -46,7 +50,7 @@ public function getControllerWithNoArgsFixtures()
*/
public function testAutoConvert($controllerCallable)
{
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
$kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock();
$request = new Request([], [], ['date' => '2014-03-14 09:00:00']);

$converter = new ParamConverter(['name' => 'date', 'class' => 'DateTime']);
Expand All @@ -57,13 +61,26 @@ public function testAutoConvert($controllerCallable)
$listener->onKernelController($event);
}

public function testAutoConvertInterface()
{
$kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock();
$request = new Request([], [], ['date' => '2014-03-14 09:00:00']);

$converter = new ParamConverter(['name' => 'date', 'class' => 'DateTimeInterface']);

$listener = new ParamConverterListener($this->getParamConverterManager($request, ['date' => $converter]));
$event = new ControllerEvent($kernel, new InvokableControllerWithInterface(), $request, null);

$listener->onKernelController($event);
}

/**
* @dataProvider settingOptionalParamProvider
* @requires PHP 7.1
*/
public function testSettingOptionalParam($function, $isOptional)
{
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
$kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock();
$request = new Request();

$converter = new ParamConverter(['name' => 'param', 'class' => 'DateTime']);
Expand Down Expand Up @@ -97,7 +114,7 @@ public function settingOptionalParamProvider()
*/
public function testNoAutoConvert($controllerCallable)
{
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
$kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock();
$request = new Request([], [], ['date' => '2014-03-14 09:00:00']);

$listener = new ParamConverterListener($this->getParamConverterManager($request, []), false);
Expand All @@ -106,17 +123,19 @@ public function testNoAutoConvert($controllerCallable)
$listener->onKernelController($event);
}

public function getControllerWithArgsFixtures()
public function getControllerWithArgsFixtures(): iterable
{
return [
[[new TestController(), 'dateAction']],
[new InvokableController()],
];
yield [[new TestController(), 'dateAction']];
yield [new InvokableController()];

if (80000 <= \PHP_VERSION_ID) {
yield [new InvokableControllerWithUnion()];
}
}

private function getParamConverterManager(Request $request, $configurations)
{
$manager = $this->getMockBuilder('Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterManager')->getMock();
$manager = $this->getMockBuilder(ParamConverterManager::class)->getMock();
$manager
->expects($this->once())
->method('apply')
Expand Down Expand Up @@ -151,3 +170,10 @@ public function __invoke(\DateTime $date)
{
}
}

class InvokableControllerWithInterface
{
public function __invoke(\DateTimeInterface $date)
{
}
}

0 comments on commit d962626

Please sign in to comment.