diff --git a/composer.json b/composer.json index e05d5e0..2ac85e3 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,8 @@ "ext-pdo": "*", "symfony/yaml": "6.3.*", "symfony/console": "6.3.*", - "nette/php-generator": "^4.1@dev" + "nette/php-generator": "^4.1@dev", + "zircote/swagger-php": "^4.0@dev" } , "require-dev": { diff --git a/composer.lock b/composer.lock index de1095d..bc6b7bc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1096fdd109424883860924610fef80fb", + "content-hash": "ec3f7bc17ec722b03a3bb4263c2ec7d2", "packages": [ { "name": "graham-campbell/result-type", @@ -406,6 +406,57 @@ }, "time": "2023-09-22T11:11:30+00:00" }, + { + "name": "psr/log", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, { "name": "symfony/console", "version": "6.3.x-dev", @@ -564,6 +615,70 @@ ], "time": "2024-04-18T09:32:20+00:00" }, + { + "name": "symfony/finder", + "version": "7.2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "0f7f413c4b46ff3312500439fb250cb63e89cf78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/0f7f413c4b46ff3312500439fb250cb63e89cf78", + "reference": "0f7f413c4b46ff3312500439fb250cb63e89cf78", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/7.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-07-25T06:25:26+00:00" + }, { "name": "symfony/polyfill-ctype", "version": "1.x-dev", @@ -1373,6 +1488,88 @@ } ], "time": "2023-11-12T22:52:03+00:00" + }, + { + "name": "zircote/swagger-php", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/zircote/swagger-php.git", + "reference": "e462ff5269ea0ec91070edd5d51dc7215bdea3b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/e462ff5269ea0ec91070edd5d51dc7215bdea3b6", + "reference": "e462ff5269ea0ec91070edd5d51dc7215bdea3b6", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.2", + "psr/log": "^1.1 || ^2.0 || ^3.0", + "symfony/deprecation-contracts": "^2 || ^3", + "symfony/finder": ">=2.2", + "symfony/yaml": ">=3.3" + }, + "require-dev": { + "composer/package-versions-deprecated": "^1.11", + "doctrine/annotations": "^1.7 || ^2.0", + "friendsofphp/php-cs-fixer": "^2.17 || ^3.47.1", + "phpstan/phpstan": "^1.6", + "phpunit/phpunit": ">=8", + "vimeo/psalm": "^4.23" + }, + "suggest": { + "doctrine/annotations": "^1.7 || ^2.0" + }, + "default-branch": true, + "bin": [ + "bin/openapi" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "OpenApi\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Robert Allen", + "email": "zircote@gmail.com" + }, + { + "name": "Bob Fanger", + "email": "bfanger@gmail.com", + "homepage": "https://bfanger.nl" + }, + { + "name": "Martin Rademacher", + "email": "mano@radebatz.net", + "homepage": "https://radebatz.net" + } + ], + "description": "swagger-php - Generate interactive documentation for your RESTful API using phpdoc annotations", + "homepage": "https://github.com/zircote/swagger-php/", + "keywords": [ + "api", + "json", + "rest", + "service discovery" + ], + "support": { + "issues": "https://github.com/zircote/swagger-php/issues", + "source": "https://github.com/zircote/swagger-php/tree/4.10.6" + }, + "time": "2024-07-26T03:04:43+00:00" } ], "packages-dev": [ diff --git a/src/EduFramework/Commands/CreateApiCommand.php b/src/EduFramework/Commands/CreateApiCommand.php index a26f27d..08f2b08 100644 --- a/src/EduFramework/Commands/CreateApiCommand.php +++ b/src/EduFramework/Commands/CreateApiCommand.php @@ -11,6 +11,7 @@ namespace Studoo\EduFramework\Commands; use Nette\PhpGenerator\PhpFile; +use PhpParser\Node\Expr\Array_; use Studoo\EduFramework\Commands\Exception\ControllerAlreadyExistsException; use Studoo\EduFramework\Commands\Exception\RouteAlreadyExistsException; use Studoo\EduFramework\Core\Controller\ControllerInterface; @@ -69,9 +70,11 @@ public function execute(InputInterface $input, OutputInterface $output): int //Format controller-name arg $namesCollection = $this->getNamesCollection($input->getArgument('controller-name')); //Generate route params in app/Config/routes.yaml - $this->generateRoute($namesCollection["uri"], $namesCollection["uri"], $namesCollection["className"]); + $router = $this->generateRoute($namesCollection["uri"], $namesCollection["uri"], $namesCollection["className"]); + // Generate openapi.php + $this->generateOpenApi(); //Generate Controller Class - $this->generateController($namesCollection["className"]); + $this->generateController($namesCollection["className"], $router); //Close command message $io->success("Controller successfully generated"); return Command::SUCCESS; @@ -106,10 +109,11 @@ private function getNamesCollection(string $arg): array /** * Fonction permettant de générer la classe PHP * @param string $className Nom de la classe + * @param array $router Route générée * @return void * @throws ControllerAlreadyExistsException */ - private function generateController(string $className): void + private function generateController(string $className, array $router): void { $filename = self::CONTROLLER_DIR . self::API_DIR . "$className.php"; @@ -127,12 +131,15 @@ private function generateController(string $className): void $namespace->addUse('Twig\Error\LoaderError'); $namespace->addUse('Twig\Error\RuntimeError'); $namespace->addUse('Twig\Error\SyntaxError'); + $namespace->addUse('OpenApi\Attributes'); //Generate ClassName $class = $namespace->addClass($className); //Add interface implementation $class->addImplement(ControllerInterface::class); //Create and design execute method $method = $class->addMethod('execute'); + $method->addAttribute('OpenApi\\Attributes\\Get', ['path' => $router['uri']]); + $method->addAttribute('OpenApi\\Attributes\\Response', ['response' => '200', 'description' => 'Mettre une description']); $method->setReturnType('string|null'); $method->addParameter('request')->setType('Studoo\EduFramework\Core\Controller\Request'); $method->setBody(<<<'CODE' @@ -153,13 +160,13 @@ private function generateController(string $className): void /** * Fonction permettant d'ajouter la route au fichier de configuration * Par défaut la méthode lors de la génération est GET - * @param string $name - * @param string $uri - * @param string $className - * @return void + * @param string $name Nom de la route + * @param string $uri URI de la route + * @param string $className Nom de la classe + * @return array $router Route générée * @throws RouteAlreadyExistsException */ - private function generateRoute(string $name, string $uri, string $className): void + private function generateRoute(string $name, string $uri, string $className): array { if (is_file(self::ROUTES_FILE_PATH) === false) { file_put_contents(self::ROUTES_FILE_PATH, ''); @@ -183,5 +190,22 @@ private function generateRoute(string $name, string $uri, string $className): vo ]; file_put_contents(self::ROUTES_FILE_PATH, Yaml::dump($router)); + + return $router[$indexName . $name]; + } + + private function generateOpenApi(): void + { + $filename = self::CONTROLLER_DIR . self::API_DIR . 'openapi.php'; + if (file_exists($filename) === true) { + return; + } + + $file = new PhpFile(); + $namespace = $file->addNamespace("Controller\api"); + $namespace->addUse('OpenApi\Attributes'); + $class = $namespace->addClass('openapi'); + $class->addAttribute('OpenApi\\Attributes\\Info', ['title' => 'My First API', 'version' => '0.1']); + file_put_contents($filename, $file); } }