Skip to content

Commit

Permalink
Add support for native PHP8 QueryParam, FileParam and RequestParam at…
Browse files Browse the repository at this point in the history
…tributes
  • Loading branch information
W0rma committed Aug 19, 2021
1 parent 3c9a2cb commit 9c91371
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 45 deletions.
28 changes: 28 additions & 0 deletions Controller/Annotations/FileParam.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
* Represents a file that must be present.
*
* @Annotation
* @NamedArgumentConstructor
* @Target("METHOD")
*
* @author Ener-Getick <egetick@gmail.com>
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class FileParam extends AbstractParam
{
/** @var bool */
Expand All @@ -39,6 +41,32 @@ class FileParam extends AbstractParam
/** @var bool */
public $map = false;

/**
* @param mixed $requirements
* @param mixed $default
*/
public function __construct(
string $name = '',
bool $strict = true,
$requirements = null,
bool $image = false,
bool $map = false,
?string $key = null,
$default = null,
string $description = '',
bool $nullable = false
) {
$this->strict = $strict;
$this->requirements = $requirements;
$this->image = $image;
$this->map = $map;
$this->name = $name;
$this->key = $key;
$this->default = $default;
$this->description = $description;
$this->nullable = $nullable;
}

/**
* {@inheritdoc}
*/
Expand Down
28 changes: 28 additions & 0 deletions Controller/Annotations/QueryParam.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,40 @@
* Represents a parameter that must be present in GET data.
*
* @Annotation
* @NamedArgumentConstructor
* @Target({"CLASS", "METHOD"})
*
* @author Alexander <iam.asm89@gmail.com>
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)]
class QueryParam extends AbstractScalarParam
{
/**
* @param mixed $requirements
* @param mixed $default
*/
public function __construct(
string $name = '',
?string $key = null,
$requirements = null,
$default = null,
array $incompatibles = [],
string $description = '',
bool $strict = false,
bool $map = false,
bool $nullable = false
) {
$this->name = $name;
$this->key = $key;
$this->requirements = $requirements;
$this->default = $default;
$this->incompatibles = $incompatibles;
$this->description = $description;
$this->strict = $strict;
$this->map = $map;
$this->nullable = $nullable;
}

/**
* {@inheritdoc}
*/
Expand Down
28 changes: 28 additions & 0 deletions Controller/Annotations/RequestParam.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,44 @@
* Represents a parameter that must be present in POST data.
*
* @Annotation
* @NamedArgumentConstructor
* @Target("METHOD")
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Boris Guéry <guery.b@gmail.com>
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class RequestParam extends AbstractScalarParam
{
/** @var bool */
public $strict = true;

/**
* @param mixed $requirements
* @param mixed $default
*/
public function __construct(
string $name = '',
?string $key = null,
$requirements = null,
$default = null,
string $description = '',
array $incompatibles = [],
bool $strict = false,
bool $map = false,
bool $nullable = false
) {
$this->name = $name;
$this->key = $key;
$this->requirements = $requirements;
$this->default = $default;
$this->description = $description;
$this->incompatibles = $incompatibles;
$this->strict = $strict;
$this->map = $map;
$this->nullable = $nullable;
}

/**
* {@inheritdoc}
*/
Expand Down
36 changes: 34 additions & 2 deletions Request/ParamReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,15 @@ public function read(\ReflectionClass $reflection, string $method): array
*/
public function getParamsFromMethod(\ReflectionMethod $method): array
{
$annotations = $this->annotationReader->getMethodAnnotations($method);
$annotations = [];
if (\PHP_VERSION_ID >= 80000) {
$annotations = $this->getParamsFromAttributes($method);
}

$annotations = array_merge(
$annotations,
$this->annotationReader->getMethodAnnotations($method) ?? []
);

return $this->getParamsFromAnnotationArray($annotations);
}
Expand All @@ -60,7 +68,15 @@ public function getParamsFromMethod(\ReflectionMethod $method): array
*/
public function getParamsFromClass(\ReflectionClass $class): array
{
$annotations = $this->annotationReader->getClassAnnotations($class);
$annotations = [];
if (\PHP_VERSION_ID >= 80000) {
$annotations = $this->getParamsFromAttributes($class);
}

$annotations = array_merge(
$annotations,
$this->annotationReader->getClassAnnotations($class) ?? []
);

return $this->getParamsFromAnnotationArray($annotations);
}
Expand All @@ -79,4 +95,20 @@ private function getParamsFromAnnotationArray(array $annotations): array

return $params;
}

/**
* @param \ReflectionClass|\ReflectionMethod $reflection
*
* @return ParamInterface[]
*/
private function getParamsFromAttributes($reflection): array
{
$params = [];
foreach ($reflection->getAttributes(ParamInterface::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
$param = $attribute->newInstance();
$params[$param->getName()] = $param;
}

return $params;
}
}
138 changes: 95 additions & 43 deletions Resources/doc/annotations-reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,63 +7,115 @@ Param fetcher
QueryParam
~~~~~~~~~~

.. code-block:: php
.. configuration-block::

use FOS\RestBundle\Controller\Annotations\QueryParam;
.. code-block:: php-annotations
/**
* @QueryParam(
* name="",
* key=null,
* requirements="",
* incompatibles={},
* default=null,
* description="",
* strict=false,
* map=false,
* nullable=false
* )
*/
use FOS\RestBundle\Controller\Annotations\QueryParam;
/**
* @QueryParam(
* name="",
* key=null,
* requirements="",
* incompatibles={},
* default=null,
* description="",
* strict=false,
* map=false,
* nullable=false
* )
*/
.. code-block:: php-attributes
use FOS\RestBundle\Controller\Annotations\QueryParam;
#[QueryParam(
name: '',
key: null,
requirements: '',
incompatibles = [],
default: null,
description: '',
strict: false,
map: false,
nullable: false
)]
RequestParam
~~~~~~~~~~~~

.. code-block:: php
.. configuration-block::

use FOS\RestBundle\Controller\Annotations\RequestParam;
.. code-block:: php-annotations
/**
* @RequestParam(
* name="",
* key=null,
* requirements="",
* default=null,
* description="",
* strict=true,
* map=false,
* nullable=false
* )
*/
use FOS\RestBundle\Controller\Annotations\RequestParam;
/**
* @RequestParam(
* name="",
* key=null,
* requirements="",
* default=null,
* description="",
* strict=true,
* map=false,
* nullable=false
* )
*/
.. code-block:: php-attributes
use FOS\RestBundle\Controller\Annotations\RequestParam;
#[RequestParam(
name: '',
key: null,
requirements: '',
default: null,
description: '',
strict: true,
map: false,
nullable: false
)]
FileParam
~~~~~~~~~

.. code-block:: php
.. configuration-block::

use FOS\RestBundle\Controller\Annotations\FileParam;
.. code-block:: php-annotations
/**
* @FileParam(
* name="",
* key=null,
* requirements={},
* default=null,
* description="",
* strict=true,
* nullable=false,
* image=false
* )
*/
use FOS\RestBundle\Controller\Annotations\FileParam;
/**
* @FileParam(
* name="",
* key=null,
* requirements={},
* default=null,
* description="",
* strict=true,
* nullable=false,
* image=false
* )
*/
.. code-block:: php-attributes
use FOS\RestBundle\Controller\Annotations\FileParam;
#[FileParam(
name: '',
key: null,
requirements: [],
default: null,
description: '',
strict: true,
nullable: false,
image: false
)]
View
----
Expand Down
10 changes: 10 additions & 0 deletions Tests/Fixtures/Controller/ParamsAnnotatedController.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,14 @@ class ParamsAnnotatedController
public function getArticlesAction(ParamFetcher $paramFetcher)
{
}

#[QueryParam(name: 'page', requirements: '\d+', default: '1', description: 'Page of the overview')]
#[RequestParam(name: 'byauthor', requirements: '[a-z]+', description: 'by author', incompatibles: ['search'], strict: true)]
#[QueryParam(name: 'filters', requirements: '\d+', default: '1', description: 'Page of the overview')]
#[FileParam(name: 'avatar', requirements: ['mimeTypes' => 'application/json'], image: true)]
#[FileParam(name: 'foo', strict: false)]
#[FileParam(name: 'bar', map: true)]
public function getArticlesAttributesAction(ParamFetcher $paramFetcher)
{
}
}
Loading

0 comments on commit 9c91371

Please sign in to comment.