Skip to content

Commit 519d967

Browse files
authored
Merge pull request #2327 from W0rma/param-attributes
Add support for native PHP8 QueryParam, FileParam and RequestParam attributes
2 parents 9a17f71 + cb42f25 commit 519d967

File tree

8 files changed

+298
-51
lines changed

8 files changed

+298
-51
lines changed

Controller/Annotations/FileParam.php

+28
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
* Represents a file that must be present.
2222
*
2323
* @Annotation
24+
* @NamedArgumentConstructor
2425
* @Target("METHOD")
2526
*
2627
* @author Ener-Getick <[email protected]>
2728
*/
29+
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
2830
class FileParam extends AbstractParam
2931
{
3032
/** @var bool */
@@ -39,6 +41,32 @@ class FileParam extends AbstractParam
3941
/** @var bool */
4042
public $map = false;
4143

44+
/**
45+
* @param mixed $requirements
46+
* @param mixed $default
47+
*/
48+
public function __construct(
49+
string $name = '',
50+
bool $strict = true,
51+
$requirements = null,
52+
bool $image = false,
53+
bool $map = false,
54+
?string $key = null,
55+
$default = null,
56+
string $description = '',
57+
bool $nullable = false
58+
) {
59+
$this->strict = $strict;
60+
$this->requirements = $requirements;
61+
$this->image = $image;
62+
$this->map = $map;
63+
$this->name = $name;
64+
$this->key = $key;
65+
$this->default = $default;
66+
$this->description = $description;
67+
$this->nullable = $nullable;
68+
}
69+
4270
/**
4371
* {@inheritdoc}
4472
*/

Controller/Annotations/QueryParam.php

+30
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,42 @@
1717
* Represents a parameter that must be present in GET data.
1818
*
1919
* @Annotation
20+
* @NamedArgumentConstructor
2021
* @Target({"CLASS", "METHOD"})
2122
*
2223
* @author Alexander <[email protected]>
2324
*/
25+
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)]
2426
class QueryParam extends AbstractScalarParam
2527
{
28+
/**
29+
* @param mixed $requirements
30+
* @param mixed $default
31+
*/
32+
public function __construct(
33+
string $name = '',
34+
?string $key = null,
35+
$requirements = null,
36+
$default = null,
37+
array $incompatibles = [],
38+
string $description = '',
39+
bool $strict = false,
40+
bool $map = false,
41+
bool $nullable = false,
42+
bool $allowBlank = true
43+
) {
44+
$this->name = $name;
45+
$this->key = $key;
46+
$this->requirements = $requirements;
47+
$this->default = $default;
48+
$this->incompatibles = $incompatibles;
49+
$this->description = $description;
50+
$this->strict = $strict;
51+
$this->map = $map;
52+
$this->nullable = $nullable;
53+
$this->allowBlank = $allowBlank;
54+
}
55+
2656
/**
2757
* {@inheritdoc}
2858
*/

Controller/Annotations/RequestParam.php

+30
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,46 @@
1717
* Represents a parameter that must be present in POST data.
1818
*
1919
* @Annotation
20+
* @NamedArgumentConstructor
2021
* @Target("METHOD")
2122
*
2223
* @author Jordi Boggiano <[email protected]>
2324
* @author Boris Guéry <[email protected]>
2425
*/
26+
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
2527
class RequestParam extends AbstractScalarParam
2628
{
2729
/** @var bool */
2830
public $strict = true;
2931

32+
/**
33+
* @param mixed $requirements
34+
* @param mixed $default
35+
*/
36+
public function __construct(
37+
string $name = '',
38+
?string $key = null,
39+
$requirements = null,
40+
$default = null,
41+
string $description = '',
42+
array $incompatibles = [],
43+
bool $strict = false,
44+
bool $map = false,
45+
bool $nullable = false,
46+
bool $allowBlank = true
47+
) {
48+
$this->name = $name;
49+
$this->key = $key;
50+
$this->requirements = $requirements;
51+
$this->default = $default;
52+
$this->description = $description;
53+
$this->incompatibles = $incompatibles;
54+
$this->strict = $strict;
55+
$this->map = $map;
56+
$this->nullable = $nullable;
57+
$this->allowBlank = $allowBlank;
58+
}
59+
3060
/**
3161
* {@inheritdoc}
3262
*/

Request/ParamReader.php

+42-3
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@
2323
*/
2424
final class ParamReader implements ParamReaderInterface
2525
{
26+
/**
27+
* @var Reader|null
28+
*/
2629
private $annotationReader;
2730

28-
public function __construct(Reader $annotationReader)
31+
public function __construct(?Reader $annotationReader = null)
2932
{
3033
$this->annotationReader = $annotationReader;
3134
}
@@ -50,7 +53,17 @@ public function read(\ReflectionClass $reflection, string $method): array
5053
*/
5154
public function getParamsFromMethod(\ReflectionMethod $method): array
5255
{
53-
$annotations = $this->annotationReader->getMethodAnnotations($method);
56+
$annotations = [];
57+
if (\PHP_VERSION_ID >= 80000) {
58+
$annotations = $this->getParamsFromAttributes($method);
59+
}
60+
61+
if (null !== $this->annotationReader) {
62+
$annotations = array_merge(
63+
$annotations,
64+
$this->annotationReader->getMethodAnnotations($method) ?? []
65+
);
66+
}
5467

5568
return $this->getParamsFromAnnotationArray($annotations);
5669
}
@@ -60,7 +73,17 @@ public function getParamsFromMethod(\ReflectionMethod $method): array
6073
*/
6174
public function getParamsFromClass(\ReflectionClass $class): array
6275
{
63-
$annotations = $this->annotationReader->getClassAnnotations($class);
76+
$annotations = [];
77+
if (\PHP_VERSION_ID >= 80000) {
78+
$annotations = $this->getParamsFromAttributes($class);
79+
}
80+
81+
if (null !== $this->annotationReader) {
82+
$annotations = array_merge(
83+
$annotations,
84+
$this->annotationReader->getClassAnnotations($class) ?? []
85+
);
86+
}
6487

6588
return $this->getParamsFromAnnotationArray($annotations);
6689
}
@@ -79,4 +102,20 @@ private function getParamsFromAnnotationArray(array $annotations): array
79102

80103
return $params;
81104
}
105+
106+
/**
107+
* @param \ReflectionClass|\ReflectionMethod $reflection
108+
*
109+
* @return ParamInterface[]
110+
*/
111+
private function getParamsFromAttributes($reflection): array
112+
{
113+
$params = [];
114+
foreach ($reflection->getAttributes(ParamInterface::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
115+
$param = $attribute->newInstance();
116+
$params[$param->getName()] = $param;
117+
}
118+
119+
return $params;
120+
}
82121
}

Resources/config/request.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<service id="FOS\RestBundle\Request\ParamFetcherInterface" alias="fos_rest.request.param_fetcher" />
1717

1818
<service id="fos_rest.request.param_fetcher.reader" class="FOS\RestBundle\Request\ParamReader" public="false">
19-
<argument type="service" id="annotation_reader"/>
19+
<argument type="service" id="annotation_reader" on-invalid="null"/>
2020
</service>
2121

2222
</services>

Resources/doc/annotations-reference.rst

+110-47
Original file line numberDiff line numberDiff line change
@@ -7,63 +7,126 @@ Param fetcher
77
QueryParam
88
~~~~~~~~~~
99

10-
.. code-block:: php
11-
12-
use FOS\RestBundle\Controller\Annotations\QueryParam;
13-
14-
/**
15-
* @QueryParam(
16-
* name="",
17-
* key=null,
18-
* requirements="",
19-
* incompatibles={},
20-
* default=null,
21-
* description="",
22-
* strict=false,
23-
* map=false,
24-
* nullable=false
25-
* )
26-
*/
10+
.. tabs::
11+
12+
.. tab:: Annotations
13+
14+
.. code-block:: php
15+
16+
use FOS\RestBundle\Controller\Annotations\QueryParam;
17+
18+
/**
19+
* @QueryParam(
20+
* name="",
21+
* key=null,
22+
* requirements="",
23+
* incompatibles={},
24+
* default=null,
25+
* description="",
26+
* strict=false,
27+
* map=false,
28+
* nullable=false
29+
* )
30+
*/
31+
32+
.. tab:: Attributes
33+
34+
.. code-block:: php
35+
36+
use FOS\RestBundle\Controller\Annotations\QueryParam;
37+
38+
#[QueryParam(
39+
name: '',
40+
key: null,
41+
requirements: '',
42+
incompatibles: [],
43+
default: null,
44+
description: '',
45+
strict: false,
46+
map: false,
47+
nullable: false
48+
)]
2749
2850
RequestParam
2951
~~~~~~~~~~~~
3052

31-
.. code-block:: php
53+
.. tabs::
3254

33-
use FOS\RestBundle\Controller\Annotations\RequestParam;
55+
.. tab:: Annotations
3456

35-
/**
36-
* @RequestParam(
37-
* name="",
38-
* key=null,
39-
* requirements="",
40-
* default=null,
41-
* description="",
42-
* strict=true,
43-
* map=false,
44-
* nullable=false
45-
* )
46-
*/
57+
.. code-block:: php
58+
59+
use FOS\RestBundle\Controller\Annotations\RequestParam;
60+
61+
/**
62+
* @RequestParam(
63+
* name="",
64+
* key=null,
65+
* requirements="",
66+
* default=null,
67+
* description="",
68+
* strict=true,
69+
* map=false,
70+
* nullable=false
71+
* )
72+
*/
73+
74+
.. tab:: Attributes
75+
76+
.. code-block:: php
77+
78+
use FOS\RestBundle\Controller\Annotations\RequestParam;
79+
80+
#[RequestParam(
81+
name: '',
82+
key: null,
83+
requirements: '',
84+
default: null,
85+
description: '',
86+
strict: true,
87+
map: false,
88+
nullable: false
89+
)]
4790
4891
FileParam
4992
~~~~~~~~~
5093

51-
.. code-block:: php
52-
53-
use FOS\RestBundle\Controller\Annotations\FileParam;
54-
55-
/**
56-
* @FileParam(
57-
* name="",
58-
* key=null,
59-
* requirements={},
60-
* default=null,
61-
* description="",
62-
* strict=true,
63-
* nullable=false,
64-
* image=false
65-
* )
66-
*/
94+
.. tabs::
95+
96+
.. tab:: Annotations
97+
98+
.. code-block:: php
99+
100+
use FOS\RestBundle\Controller\Annotations\FileParam;
101+
102+
/**
103+
* @FileParam(
104+
* name="",
105+
* key=null,
106+
* requirements={},
107+
* default=null,
108+
* description="",
109+
* strict=true,
110+
* nullable=false,
111+
* image=false
112+
* )
113+
*/
114+
.. tab:: Attributes
115+
116+
.. code-block:: php
117+
118+
use FOS\RestBundle\Controller\Annotations\FileParam;
119+
120+
#[FileParam(
121+
name: '',
122+
key: null,
123+
requirements: [],
124+
default: null,
125+
description: '',
126+
strict: true,
127+
nullable: false,
128+
image: false
129+
)]
67130
68131
View
69132
----

0 commit comments

Comments
 (0)