6
6
use App \Model \Repository \AssignmentSolutions ;
7
7
use App \Model \Entity \Group ;
8
8
use App \Model \Entity \User ;
9
+ use App \V1Module \Router \MethodRoute ;
10
+ use Nette \Routing \RouteList ;
9
11
use Symfony \Component \Console \Command \Command ;
10
12
use Symfony \Component \Console \Input \InputArgument ;
11
13
use Symfony \Component \Console \Input \InputInterface ;
@@ -26,12 +28,85 @@ protected function configure(): void
26
28
27
29
protected function execute (InputInterface $ input , OutputInterface $ output ): int
28
30
{
29
- $ r = new AnnotationHelper ('App\V1Module\Presenters\UsersPresenter ' );
30
- $ data = $ r ->extractMethodData ('actionUpdateUiData ' );
31
- var_dump ($ data );
31
+ $ namespacePrefix = 'App\V1Module\Presenters \\' ;
32
+
33
+ $ routes = $ this ->getRoutes ();
34
+ foreach ($ routes as $ route ) {
35
+ $ metadata = $ this ->extractMetadata ($ route );
36
+ $ route = $ this ->extractRoute ($ route );
37
+
38
+ $ className = $ namespacePrefix . $ metadata ['class ' ];
39
+ $ annotationData = AnnotationHelper::extractAnnotationData ($ className , $ metadata ['method ' ]);
40
+ }
32
41
33
42
return Command::SUCCESS ;
34
43
}
44
+
45
+ function getRoutes (): array {
46
+ $ router = \App \V1Module \RouterFactory::createRouter ();
47
+
48
+ # find all route object using a queue
49
+ $ queue = [$ router ];
50
+ $ routes = [];
51
+ while (count ($ queue ) != 0 ) {
52
+ $ cursor = array_shift ($ queue );
53
+
54
+ if ($ cursor instanceof RouteList) {
55
+ foreach ($ cursor ->getRouters () as $ item ) {
56
+ # lists contain routes or nested lists
57
+ if ($ item instanceof RouteList) {
58
+ array_push ($ queue , $ item );
59
+ }
60
+ else {
61
+ # the first route is special and holds no useful information for annotation
62
+ if (get_parent_class ($ item ) !== MethodRoute::class)
63
+ continue ;
64
+
65
+ $ routes [] = $ this ->getPropertyValue ($ item , "route " );
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ return $ routes ;
72
+ }
73
+
74
+ private function extractRoute ($ routeObj ) {
75
+ $ mask = self ::getPropertyValue ($ routeObj , "mask " );
76
+ return $ mask ;
77
+ }
78
+
79
+ private function extractMetadata ($ routeObj ) {
80
+ $ metadata = self ::getPropertyValue ($ routeObj , "metadata " );
81
+ $ presenter = $ metadata ["presenter " ]["value " ];
82
+ $ action = $ metadata ["action " ]["value " ];
83
+
84
+ # if the name is empty, the method will be called 'actionDefault'
85
+ if ($ action === null )
86
+ $ action = "default " ;
87
+
88
+ return [
89
+ "class " => $ presenter . "Presenter " ,
90
+ "method " => "action " . ucfirst ($ action ),
91
+ ];
92
+ }
93
+
94
+ private static function getPropertyValue ($ object , string $ propertyName ): mixed
95
+ {
96
+ $ class = new \ReflectionClass ($ object );
97
+
98
+ do {
99
+ try {
100
+ $ property = $ class ->getProperty ($ propertyName );
101
+ } catch (\ReflectionException $ exception ) {
102
+ $ class = $ class ->getParentClass ();
103
+ $ property = null ;
104
+ }
105
+ } while ($ property === null && $ class !== null );
106
+
107
+ $ property ->setAccessible (true );
108
+ return $ property ->getValue ($ object );
109
+ }
35
110
}
36
111
37
112
enum HttpMethods: string {
@@ -58,14 +133,14 @@ public function __construct(
58
133
}
59
134
60
135
class AnnotationParameterData {
61
- public string $ dataType ;
136
+ public string | null $ dataType ;
62
137
public string $ name ;
63
- public string $ description ;
138
+ public string | null $ description ;
64
139
65
140
public function __construct (
66
- string $ dataType ,
141
+ string | null $ dataType ,
67
142
string $ name ,
68
- string $ description
143
+ string | null $ description
69
144
) {
70
145
$ this ->dataType = $ dataType ;
71
146
$ this ->name = $ name ;
@@ -74,25 +149,12 @@ public function __construct(
74
149
}
75
150
76
151
class AnnotationHelper {
77
- private string $ className ;
78
- private \ReflectionClass $ class ;
79
-
80
- /**
81
- * Constructor
82
- * @param string $className Name of the class.
83
- */
84
- public function __construct (
85
- string $ className
86
- ) {
87
- $ this ->className = $ className ;
88
- $ this ->class = new \ReflectionClass ($ this ->className );
152
+ private static function getMethod (string $ className , string $ methodName ): \ReflectionMethod {
153
+ $ class = new \ReflectionClass ($ className );
154
+ return $ class ->getMethod ($ methodName );
89
155
}
90
156
91
- public function getMethod (string $ methodName ): \ReflectionMethod {
92
- return $ this ->class ->getMethod ($ methodName );
93
- }
94
-
95
- function extractAnnotationHttpMethod (array $ annotations ): HttpMethods |null {
157
+ private static function extractAnnotationHttpMethod (array $ annotations ): HttpMethods |null {
96
158
# get string values of backed enumeration
97
159
$ cases = HttpMethods::cases ();
98
160
$ methods = [];
@@ -110,7 +172,7 @@ function extractAnnotationHttpMethod(array $annotations): HttpMethods|null {
110
172
return null ;
111
173
}
112
174
113
- function extractAnnotationQueryParams (array $ annotations ): array {
175
+ private static function extractAnnotationQueryParams (array $ annotations ): array {
114
176
$ queryParams = [];
115
177
foreach ($ annotations as $ annotation ) {
116
178
# assumed that all query parameters have a @param annotation
@@ -128,7 +190,7 @@ function extractAnnotationQueryParams(array $annotations): array {
128
190
return $ queryParams ;
129
191
}
130
192
131
- function extractBodyParams (array $ expressions ): array {
193
+ private static function extractBodyParams (array $ expressions ): array {
132
194
$ dict = [];
133
195
#sample: [ name="uiData", validation="array|null" ]
134
196
foreach ($ expressions as $ expression ) {
@@ -141,7 +203,7 @@ function extractBodyParams(array $expressions): array {
141
203
return $ dict ;
142
204
}
143
205
144
- function extractAnnotationBodyParams (array $ annotations ): array {
206
+ private static function extractAnnotationBodyParams (array $ annotations ): array {
145
207
$ bodyParams = [];
146
208
$ prefix = "@Param " ;
147
209
foreach ($ annotations as $ annotation ) {
@@ -151,7 +213,7 @@ function extractAnnotationBodyParams(array $annotations): array {
151
213
# remove '@Param(' from the start and ')' from the end
152
214
$ body = substr ($ annotation , strlen ($ prefix ) + 1 , -1 );
153
215
$ tokens = explode (", " , $ body );
154
- $ values = $ this -> extractBodyParams ($ tokens );
216
+ $ values = self :: extractBodyParams ($ tokens );
155
217
$ descriptor = new AnnotationParameterData ($ values ["validation " ],
156
218
$ values ["name " ], $ values ["description " ]);
157
219
$ bodyParams [] = $ descriptor ;
@@ -160,8 +222,8 @@ function extractAnnotationBodyParams(array $annotations): array {
160
222
return $ bodyParams ;
161
223
}
162
224
163
- function getMethodAnnotations (string $ methodName ): array {
164
- $ annotations = $ this -> getMethod ($ methodName )->getDocComment ();
225
+ private static function getMethodAnnotations (string $ className , string $ methodName ): array {
226
+ $ annotations = self :: getMethod ($ className , $ methodName )->getDocComment ();
165
227
$ lines = preg_split ("/ \r\n| \n| \r/ " , $ annotations );
166
228
167
229
# trims whitespace and asterisks
@@ -196,11 +258,12 @@ function getMethodAnnotations(string $methodName): array {
196
258
return $ merged ;
197
259
}
198
260
199
- public function extractMethodData ($ methodName ): AnnotationData {
200
- $ methodAnnotations = $ this ->getMethodAnnotations ($ methodName );
201
- $ httpMethod = $ this ->extractAnnotationHttpMethod ($ methodAnnotations );
202
- $ queryParams = $ this ->extractAnnotationQueryParams ($ methodAnnotations );
203
- $ bodyParams = $ this ->extractAnnotationBodyParams ($ methodAnnotations );
261
+ public static function extractAnnotationData (string $ className , string $ methodName ): AnnotationData {
262
+ $ methodAnnotations = self ::getMethodAnnotations ($ className , $ methodName );
263
+
264
+ $ httpMethod = self ::extractAnnotationHttpMethod ($ methodAnnotations );
265
+ $ queryParams = self ::extractAnnotationQueryParams ($ methodAnnotations );
266
+ $ bodyParams = self ::extractAnnotationBodyParams ($ methodAnnotations );
204
267
$ data = new AnnotationData ($ httpMethod , $ queryParams , $ bodyParams );
205
268
return $ data ;
206
269
}
0 commit comments