Skip to content

Commit

Permalink
bug #26899 [Routing] Fix loading multiple class annotations for invok…
Browse files Browse the repository at this point in the history
…able classes (1ed)

This PR was merged into the 3.4 branch.

Discussion
----------

[Routing] Fix loading multiple class annotations for invokable classes

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        | -

The support for full route definition for invokable controllers as class annotation was introduced by
#2172, but that works with one route only, which is inconsistent with how `@Route` works at other places. This PR adds support for multiple class annotations for invokable controllers and fixes the inconsistency.

<!--
Write a short README entry for your feature/bugfix here (replace this comment block.)
This will help people understand your PR and can be used as a start of the Doc PR.
Additionally:
 - Bug fixes must be submitted against the lowest branch where they apply
   (lowest branches are regularly merged to upper ones so they get the fixes too).
 - Features and deprecations must be submitted against the master branch.
-->

Commits
-------

2a9c668 [Routing] Fix loading multiple class annotations for invokable classes
  • Loading branch information
fabpot committed Apr 17, 2018
2 parents baeb1bf + 2a9c668 commit 8f2132f
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 11 deletions.
13 changes: 9 additions & 4 deletions src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php
Expand Up @@ -119,10 +119,15 @@ public function load($class, $type = null)
}
}

if (0 === $collection->count() && $class->hasMethod('__invoke') && $annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) {
$globals['path'] = '';
$globals['name'] = '';
$this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke'));
if (0 === $collection->count() && $class->hasMethod('__invoke')) {
foreach ($this->reader->getClassAnnotations($class) as $annot) {
if ($annot instanceof $this->routeAnnotationClass) {
$globals['path'] = '';
$globals['name'] = '';

$this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke'));
}
}
}

return $collection;
Expand Down
Expand Up @@ -191,9 +191,9 @@ public function testInvokableClassRouteLoad()
);

$this->reader
->expects($this->exactly(2))
->method('getClassAnnotation')
->will($this->returnValue($this->getAnnotatedRoute($classRouteData)))
->expects($this->exactly(1))
->method('getClassAnnotations')
->will($this->returnValue(array($this->getAnnotatedRoute($classRouteData))))
;
$this->reader
->expects($this->once())
Expand All @@ -205,8 +205,49 @@ public function testInvokableClassRouteLoad()
$route = $routeCollection->get($classRouteData['name']);

$this->assertSame($classRouteData['path'], $route->getPath(), '->load preserves class route path');
$this->assertEquals(array_merge($classRouteData['schemes'], $classRouteData['schemes']), $route->getSchemes(), '->load preserves class route schemes');
$this->assertEquals(array_merge($classRouteData['methods'], $classRouteData['methods']), $route->getMethods(), '->load preserves class route methods');
$this->assertEquals($classRouteData['schemes'], $route->getSchemes(), '->load preserves class route schemes');
$this->assertEquals($classRouteData['methods'], $route->getMethods(), '->load preserves class route methods');
}

public function testInvokableClassMultipleRouteLoad()
{
$classRouteData1 = array(
'name' => 'route1',
'path' => '/1',
'schemes' => array('https'),
'methods' => array('GET'),
);

$classRouteData2 = array(
'name' => 'route2',
'path' => '/2',
'schemes' => array('https'),
'methods' => array('GET'),
);

$this->reader
->expects($this->exactly(1))
->method('getClassAnnotations')
->will($this->returnValue(array($this->getAnnotatedRoute($classRouteData1), $this->getAnnotatedRoute($classRouteData2))))
;
$this->reader
->expects($this->once())
->method('getMethodAnnotations')
->will($this->returnValue(array()))
;

$routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass');
$route = $routeCollection->get($classRouteData1['name']);

$this->assertSame($classRouteData1['path'], $route->getPath(), '->load preserves class route path');
$this->assertEquals($classRouteData1['schemes'], $route->getSchemes(), '->load preserves class route schemes');
$this->assertEquals($classRouteData1['methods'], $route->getMethods(), '->load preserves class route methods');

$route = $routeCollection->get($classRouteData2['name']);

$this->assertSame($classRouteData2['path'], $route->getPath(), '->load preserves class route path');
$this->assertEquals($classRouteData2['schemes'], $route->getSchemes(), '->load preserves class route schemes');
$this->assertEquals($classRouteData2['methods'], $route->getMethods(), '->load preserves class route methods');
}

public function testInvokableClassWithMethodRouteLoad()
Expand Down
Expand Up @@ -29,14 +29,20 @@ protected function setUp()

public function testLoad()
{
$this->reader->expects($this->exactly(4))->method('getClassAnnotation');
$this->reader->expects($this->exactly(3))->method('getClassAnnotation');

$this->reader
->expects($this->any())
->method('getMethodAnnotations')
->will($this->returnValue(array()))
;

$this->reader
->expects($this->any())
->method('getClassAnnotations')
->will($this->returnValue(array()))
;

$this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses');
}

Expand All @@ -45,7 +51,6 @@ public function testLoadIgnoresHiddenDirectories()
$this->expectAnnotationsToBeReadFrom(array(
'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass',
'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass',
'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\FooClass',
));

Expand All @@ -55,6 +60,12 @@ public function testLoadIgnoresHiddenDirectories()
->will($this->returnValue(array()))
;

$this->reader
->expects($this->any())
->method('getClassAnnotations')
->will($this->returnValue(array()))
;

$this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses');
}

Expand Down

0 comments on commit 8f2132f

Please sign in to comment.