22
33namespace App \Console ;
44
5- use App \Helpers \Swagger \FileBuilder ;
5+ use App \Helpers \Swagger \TempAnnotationFileBuilder ;
66use App \Helpers \Swagger \AnnotationHelper ;
77use App \V1Module \Router \MethodRoute ;
88use Nette \Routing \RouteList ;
99use Symfony \Component \Console \Command \Command ;
1010use Symfony \Component \Console \Input \InputInterface ;
1111use Symfony \Component \Console \Output \OutputInterface ;
12+ use Exception ;
13+ use ReflectionException ;
14+ use ReflectionClass ;
1215
1316class SwaggerAnnotator extends Command
1417{
@@ -25,52 +28,59 @@ protected function configure(): void
2528
2629 protected function execute (InputInterface $ input , OutputInterface $ output ): int
2730 {
28- # create a temporary file containing transpiled annotations usable by the external library (Swagger-PHP)
29- $ fileBuilder = new FileBuilder (self ::$ autogeneratedAnnotationFilePath );
30- $ fileBuilder ->startClass ('__Autogenerated_Annotation_Controller__ ' , '1.0 ' , 'ReCodEx API ' );
31-
32- # get all routes of the api
33- $ routes = $ this ->getRoutes ();
34- foreach ($ routes as $ routeObj ) {
35- # extract class and method names of the endpoint
36- $ metadata = $ this ->extractMetadata ($ routeObj );
37- $ route = $ this ->extractRoute ($ routeObj );
38- $ className = self ::$ presenterNamespace . $ metadata ['class ' ];
39-
40- # extract data from the existing annotations
41- $ annotationData = AnnotationHelper::extractAnnotationData ($ className , $ metadata ['method ' ], $ route );
42-
43- # add an empty method to the file with the transpiled annotations
44- $ fileBuilder ->addAnnotatedMethod ($ metadata ['method ' ], $ annotationData ->toSwaggerAnnotations ($ route ));
45- }
46- $ fileBuilder ->endClass ();
31+ try {
32+ // create a temporary file containing transpiled annotations usable by the external library (Swagger-PHP)
33+ $ fileBuilder = new TempAnnotationFileBuilder (self ::$ autogeneratedAnnotationFilePath );
34+ $ fileBuilder ->startClass ('__Autogenerated_Annotation_Controller__ ' , '1.0 ' , 'ReCodEx API ' );
35+
36+ // get all routes of the api
37+ $ routes = $ this ->getRoutes ();
38+ foreach ($ routes as $ routeObj ) {
39+ // extract class and method names of the endpoint
40+ $ metadata = $ this ->extractMetadata ($ routeObj );
41+ $ route = $ this ->extractRoute ($ routeObj );
42+ $ className = self ::$ presenterNamespace . $ metadata ['class ' ];
43+
44+ // extract data from the existing annotations
45+ $ annotationData = AnnotationHelper::extractAnnotationData ($ className , $ metadata ['method ' ], $ route );
46+
47+ // add an empty method to the file with the transpiled annotations
48+ $ fileBuilder ->addAnnotatedMethod ($ metadata ['method ' ], $ annotationData ->toSwaggerAnnotations ($ route ));
49+ }
50+ $ fileBuilder ->endClass ();
51+
52+ return Command::SUCCESS ;
53+ } catch (Exception $ e ) {
54+ $ output ->writeln ("Error in SwaggerAnnotator: {$ e ->getMessage ()}" );
4755
48- return Command::SUCCESS ;
56+ return Command::FAILURE ;
57+ }
4958 }
5059
5160 /**
5261 * Finds all route objects of the API
5362 * @return array Returns an array of all found route objects.
5463 */
55- function getRoutes (): array {
64+ private function getRoutes (): array
65+ {
5666 $ router = \App \V1Module \RouterFactory::createRouter ();
5767
58- # find all route object using a queue
68+ // find all route object using a queue
5969 $ queue = [$ router ];
6070 $ routes = [];
6171 while (count ($ queue ) != 0 ) {
6272 $ cursor = array_shift ($ queue );
6373
6474 if ($ cursor instanceof RouteList) {
6575 foreach ($ cursor ->getRouters () as $ item ) {
66- # lists contain routes or nested lists
76+ // lists contain routes or nested lists
6777 if ($ item instanceof RouteList) {
6878 array_push ($ queue , $ item );
69- }
70- else {
71- # the first route is special and holds no useful information for annotation
72- if (get_parent_class ($ item ) !== MethodRoute::class)
79+ } else {
80+ // the first route is special and holds no useful information for annotation
81+ if (get_parent_class ($ item ) !== MethodRoute::class) {
7382 continue ;
83+ }
7484
7585 $ routes [] = $ this ->getPropertyValue ($ item , "route " );
7686 }
@@ -85,10 +95,11 @@ function getRoutes(): array {
8595 * Extracts the route string from a route object. Replaces '<..>' in the route with '{...}'.
8696 * @param mixed $routeObj
8797 */
88- private function extractRoute ($ routeObj ): string {
98+ private function extractRoute ($ routeObj ): string
99+ {
89100 $ mask = self ::getPropertyValue ($ routeObj , "mask " );
90101
91- # sample: replaces '/users/<id>' with '/users/{id}'
102+ // sample: replaces '/users/<id>' with '/users/{id}'
92103 $ mask = str_replace (["< " , "> " ], ["{ " , "} " ], $ mask );
93104 return "/ " . $ mask ;
94105 }
@@ -98,14 +109,16 @@ private function extractRoute($routeObj): string {
98109 * @param mixed $routeObj The route object representing the endpoint.
99110 * @return string[] Returns a dictionary [ "class" => ..., "method" => ...]
100111 */
101- private function extractMetadata ($ routeObj ) {
112+ private function extractMetadata ($ routeObj )
113+ {
102114 $ metadata = self ::getPropertyValue ($ routeObj , "metadata " );
103115 $ presenter = $ metadata ["presenter " ]["value " ];
104116 $ action = $ metadata ["action " ]["value " ];
105117
106- # if the name is empty, the method will be called 'actionDefault'
107- if ($ action === null )
118+ // if the name is empty, the method will be called 'actionDefault'
119+ if ($ action === null ) {
108120 $ action = "default " ;
121+ }
109122
110123 return [
111124 "class " => $ presenter . "Presenter " ,
@@ -122,12 +135,12 @@ private function extractMetadata($routeObj) {
122135 */
123136 private static function getPropertyValue ($ object , string $ propertyName ): mixed
124137 {
125- $ class = new \ ReflectionClass ($ object );
138+ $ class = new ReflectionClass ($ object );
126139
127140 do {
128141 try {
129142 $ property = $ class ->getProperty ($ propertyName );
130- } catch (\ ReflectionException $ exception ) {
143+ } catch (ReflectionException $ exception ) {
131144 $ class = $ class ->getParentClass ();
132145 $ property = null ;
133146 }
0 commit comments