Skip to content

Commit

Permalink
Merge pull request #2325 from W0rma/route-attributes
Browse files Browse the repository at this point in the history
Add support for native PHP8 Route attributes
  • Loading branch information
GuilhemN authored Aug 18, 2021
2 parents 557bf3d + a00028e commit 5fed474
Show file tree
Hide file tree
Showing 23 changed files with 235 additions and 0 deletions.
1 change: 1 addition & 0 deletions Controller/Annotations/Copy.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*
* @author Maximilian Bosch <maximilian.bosch.27@gmail.com>
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Copy extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Delete.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @NamedArgumentConstructor
* @Target("METHOD")
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Delete extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Get.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @NamedArgumentConstructor
* @Target("METHOD")
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Get extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Head.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @NamedArgumentConstructor
* @Target("METHOD")
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Head extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Link.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @NamedArgumentConstructor
* @Target("METHOD")
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Link extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Lock.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*
* @author Maximilian Bosch <maximilian.bosch.27@gmail.com>
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Lock extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Mkcol.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*
* @author Maximilian Bosch <maximilian.bosch.27@gmail.com>
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Mkcol extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Move.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*
* @author Maximilian Bosch <maximilian.bosch.27@gmail.com>
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Move extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @NamedArgumentConstructor
* @Target("METHOD")
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Options extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Patch.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @NamedArgumentConstructor
* @Target("METHOD")
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Patch extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @NamedArgumentConstructor
* @Target("METHOD")
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Post extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/PropFind.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*
* @author Maximilian Bosch <maximilian.bosch.27@gmail.com>
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class PropFind extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/PropPatch.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*
* @author Maximilian Bosch <maximilian.bosch.27@gmail.com>
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class PropPatch extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Put.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @NamedArgumentConstructor
* @Target("METHOD")
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Put extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* @NamedArgumentConstructor
* @Target({"CLASS", "METHOD"})
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)]
class Route extends BaseRoute
{
public function __construct(
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Unlink.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @NamedArgumentConstructor
* @Target("METHOD")
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Unlink extends Route
{
public function getMethod()
Expand Down
1 change: 1 addition & 0 deletions Controller/Annotations/Unlock.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*
* @author Maximilian Bosch <maximilian.bosch.27@gmail.com>
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Unlock extends Route
{
public function getMethod()
Expand Down
40 changes: 40 additions & 0 deletions Resources/doc/annotations-reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,44 @@ to define routes limited to a specific HTTP method: ``@Delete``, ``@Get``,
``@Unlock``, ``@PropFind``, ``@PropPatch``, ``@Move``, ``@Mkcol``, ``@Copy``.
All of them have the same options as ``@Route``.

Example:

.. configuration-block::

.. code-block:: php-annotations
// src/Controller/BlogController.php
namespace App\Controller;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
class BlogController extends AbstractFOSRestController
{
/**
* @Rest\Get("/blog", name="blog_list")
*/
public function list()
{
// ...
}
}
.. code-block:: php-attributes
// src/Controller/BlogController.php
namespace App\Controller;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
class BlogController extends AbstractFOSRestController
{
#[Rest\Get('/blog', name: 'blog_list')]
public function list()
{
// ...
}
}
.. _`@Route Symfony annotation`: https://symfony.com/doc/current/routing.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

/*
* This file is part of the FOSRestBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FOS\RestBundle\Tests\Functional\Bundle\TestBundle\Controller;

use FOS\RestBundle\Controller\AbstractFOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\View\View;
use Symfony\Component\HttpFoundation\Request;

/**
* Controller to test native PHP8 Route attributes.
*/
#[Rest\Route('/products')]
class RouteAttributesController extends AbstractFOSRestController
{
/**
* @return View view instance
*
* @Rest\View()
*/
#[Rest\Get(path: '/{page}', name: 'product_list', requirements: ['page' => '\d+'], defaults: ['_format' => 'json'])]
public function listAction(int $page)
{
$view = $this->view([
['name' => 'product1'],
['name' => 'product2'],
]);

return $view;
}

/**
* @return View view instance
*
* @Rest\View()
*/
#[Rest\Post(path: '', name: 'product_create')]
public function createAction(Request $request)
{
$view = $this->view([
'name' => 'product1',
], 201);

return $view;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,6 @@ test_allowed_methods2:
path: /allowed-methods
methods: ['POST', 'PUT']
defaults: { _controller: FOS\RestBundle\Tests\Functional\Bundle\TestBundle\Controller\AllowedMethodsController::indexAction }

test_route_attributes:
resource: FOS\RestBundle\Tests\Functional\Bundle\TestBundle\Controller\RouteAttributesController
80 changes: 80 additions & 0 deletions Tests/Functional/RouteAttributesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

/*
* This file is part of the FOSRestBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FOS\RestBundle\Tests\Functional;

/**
* @requires PHP 8
*/
class RouteAttributesTest extends WebTestCase
{
private const TEST_CASE = 'RouteAttributes';
private static $client;

public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
static::$client = static::createClient(['test_case' => self::TEST_CASE]);
}

public static function tearDownAfterClass(): void
{
self::deleteTmpDir(self::TEST_CASE);
parent::tearDownAfterClass();
}

public function testGet()
{
static::$client->request(
'GET',
'/products/1',
[],
[],
['HTTP_ACCEPT' => 'application/json']
);

$this->assertSame(200, static::$client->getResponse()->getStatusCode());
$this->assertJsonStringEqualsJsonString(
'[{"name": "product1"},{"name": "product2"}]',
static::$client->getResponse()->getContent()
);
}

public function testPost()
{
static::$client->request(
'POST',
'/products',
[],
[],
['HTTP_ACCEPT' => 'application/json']
);

$this->assertSame(201, static::$client->getResponse()->getStatusCode());
$this->assertJsonStringEqualsJsonString(
'{"name": "product1"}',
static::$client->getResponse()->getContent()
);
}

public function testInvalidQueryParameter()
{
static::$client->request(
'GET',
'/products/foo',
[],
[],
['HTTP_ACCEPT' => 'application/json']
);

$this->assertSame(404, static::$client->getResponse()->getStatusCode());
}
}
18 changes: 18 additions & 0 deletions Tests/Functional/app/RouteAttributes/bundles.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

/*
* This file is part of the FOSRestBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

return [
new \Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new \Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new \FOS\RestBundle\FOSRestBundle(),
new \FOS\RestBundle\Tests\Functional\Bundle\TestBundle\TestBundle(),
new \Symfony\Bundle\TwigBundle\TwigBundle(),
];
22 changes: 22 additions & 0 deletions Tests/Functional/app/RouteAttributes/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
imports:
- { resource: ../config/default.yml }
- { resource: ../config/sensio_framework_extra.yml }

framework:
serializer:
enabled: true

fos_rest:
view:
view_response_listener: 'force'
formats:
xml: true
json: true
body_listener: true
format_listener:
rules:
- { path: ^/, priorities: [ json, xml ], fallback_format: ~, prefer_extension: true }

twig:
exception_controller: ~
strict_variables: '%kernel.debug%'

0 comments on commit 5fed474

Please sign in to comment.