From 929a569178a2db435116edaba1cf1fc28742f809 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Tue, 28 Mar 2023 00:28:41 +0300 Subject: [PATCH 1/2] Add an example how to deal with route attributes --- blog/autoload.php | 1 + blog/composer.json | 11 ++++++-- blog/config/common/routes/routes.php | 18 ++++++++++--- blog/src/Controller/SiteController.php | 37 ++++++++++++++++++++++++++ blog/watcher-build.php | 18 +++++++++++++ blog/watcher.php | 22 +++++++++++++++ 6 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 blog/watcher-build.php create mode 100644 blog/watcher.php diff --git a/blog/autoload.php b/blog/autoload.php index ccfe29cd..6632ee68 100644 --- a/blog/autoload.php +++ b/blog/autoload.php @@ -5,6 +5,7 @@ use Dotenv\Dotenv; require_once __DIR__ . '/vendor/autoload.php'; +require __DIR__ . '/vendor/attributes.php'; $dotenv = Dotenv::createImmutable(__DIR__); $dotenv->load(); diff --git a/blog/composer.json b/blog/composer.json index 4fa637eb..1243fb91 100644 --- a/blog/composer.json +++ b/blog/composer.json @@ -26,6 +26,7 @@ "doctrine/collections": "^1.6", "fakerphp/faker": "^1.14", "httpsoft/http-message": "^1.0.5", + "olvlvl/composer-attribute-collector": "dev-main", "php-http/guzzle7-adapter": "^1.0", "psr/container": "^2.0", "psr/http-factory": "^1.0", @@ -33,6 +34,7 @@ "psr/http-server-handler": "^1.0", "psr/http-server-middleware": "^1.0", "psr/log": "^3.0", + "spatie/file-system-watcher": "^1.1", "symfony/console": "^6.0", "vlucas/phpdotenv": "^5.3", "yiisoft/access": "^1.0", @@ -63,7 +65,7 @@ "yiisoft/rbac": "^1.0", "yiisoft/rbac-php": "^1.0", "yiisoft/rbac-rules-container": "^2.0", - "yiisoft/router": "^3.0", + "yiisoft/router": "dev-attributes as 3.0", "yiisoft/router-fastroute": "^3.0", "yiisoft/security": "^1.0", "yiisoft/session": "^2.0", @@ -152,10 +154,15 @@ "composer/installers": true, "composer/package-versions-deprecated": true, "infection/extension-installer": true, - "yiisoft/config": true + "yiisoft/config": true, + "olvlvl/composer-attribute-collector": true } }, "repositories": [ + { + "type": "git", + "url": "https://github.com/yiisoft/router" + }, { "type": "composer", "url": "https://asset-packagist.org" diff --git a/blog/config/common/routes/routes.php b/blog/config/common/routes/routes.php index d06a4a7a..3c325bc0 100644 --- a/blog/config/common/routes/routes.php +++ b/blog/config/common/routes/routes.php @@ -17,6 +17,7 @@ use App\Middleware\ApiDataWrapper; use App\User\Controller\ApiUserController; use App\User\Controller\UserController; +use olvlvl\ComposerAttributeCollector\Attributes; use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ServerRequestInterface; use Yiisoft\Auth\Middleware\Authentication; @@ -36,11 +37,22 @@ use Yiisoft\Yii\RateLimiter\LimitRequestsMiddleware; use Yiisoft\Yii\RateLimiter\Storage\StorageInterface; +$routes = []; +foreach (Attributes::findTargetMethods(Route::class) as $method) { + /** + * @var $attribute Route + */ + $attribute = $method->attribute; + $routes[] = $attribute + ->action([$method->class, $method->name]); +} + return [ + ...$routes, // Lonely pages of site - Route::get('/') - ->action([SiteController::class, 'index']) - ->name('site/index'), + //Route::get('/') + // ->action([SiteController::class, 'index']) + // ->name('site/index'), Route::methods([Method::GET, Method::POST], '/contact') ->action([ContactController::class, 'contact']) ->name('site/contact'), diff --git a/blog/src/Controller/SiteController.php b/blog/src/Controller/SiteController.php index 086730be..9e46c8d0 100644 --- a/blog/src/Controller/SiteController.php +++ b/blog/src/Controller/SiteController.php @@ -4,8 +4,12 @@ namespace App\Controller; +use App\Middleware\ApiDataWrapper; use Psr\Http\Message\ResponseInterface; +use Yiisoft\DataResponse\Middleware\FormatDataResponseAsJson; +use Yiisoft\DataResponse\Middleware\FormatDataResponseAsXml; use Yiisoft\Yii\View\ViewRenderer; +use Yiisoft\Router\Route; final class SiteController { @@ -14,8 +18,41 @@ public function __construct(private ViewRenderer $viewRenderer) $this->viewRenderer = $viewRenderer->withController($this); } + #[Route( + methods: ['GET'], + pattern: '/', + name: 'site/index', + )] public function index(): ResponseInterface { return $this->viewRenderer->render('index'); } + + #[Route( + methods: ['GET'], + pattern: '/json', + name: 'site/index.json', + middlewares: [ + FormatDataResponseAsJson::class, + ApiDataWrapper::class, + ], + )] + public function json(): ResponseInterface + { + return $this->viewRenderer->render('index'); + } + + #[Route( + methods: ['GET'], + pattern: '/xml', + name: 'site/index.xml', + middlewares: [ + FormatDataResponseAsXml::class, + ApiDataWrapper::class, + ], + )] + public function xml(): ResponseInterface + { + return $this->viewRenderer->render('index'); + } } diff --git a/blog/watcher-build.php b/blog/watcher-build.php new file mode 100644 index 00000000..324c1245 --- /dev/null +++ b/blog/watcher-build.php @@ -0,0 +1,18 @@ +onAnyChange(function (string $type, string $path) { + echo sprintf('File changed: "%s".', $path) . PHP_EOL; + echo 'Run watcher-build...' . PHP_EOL; + `php watcher-build.php`; + echo 'Dumped...' . PHP_EOL; + }) + ->start(); From 2388ef06701d9077053df797da4dc107772fdeed Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 27 Mar 2023 21:28:56 +0000 Subject: [PATCH 2/2] Apply fixes from StyleCI --- blog-api/config/web/di/application.php | 2 +- blog-api/src/Auth/AuthController.php | 13 ++++++++ blog-api/src/Auth/AuthRequest.php | 1 + blog-api/src/Blog/BlogController.php | 31 +++++++++++++++++++ blog-api/src/Blog/EditPostRequest.php | 1 + blog-api/src/Blog/PostFormatter.php | 1 + blog-api/src/Dto/ApiResponseData.php | 1 + blog-api/src/Formatter/PaginatorFormatter.php | 1 + blog-api/src/InfoController.php | 4 +++ blog-api/src/User/UserController.php | 11 +++++++ blog-api/src/User/UserFormatter.php | 1 + blog/config/common/routes/routes.php | 4 +-- blog/src/Controller/Actions/ApiInfo.php | 1 + .../src/User/Controller/ApiUserController.php | 4 +++ 14 files changed, 73 insertions(+), 3 deletions(-) diff --git a/blog-api/config/web/di/application.php b/blog-api/config/web/di/application.php index bc898db2..8128fae3 100644 --- a/blog-api/config/web/di/application.php +++ b/blog-api/config/web/di/application.php @@ -14,7 +14,7 @@ Yiisoft\Yii\Http\Application::class => [ '__construct()' => [ 'dispatcher' => DynamicReference::to(static function (Injector $injector) use ($params) { - return ($injector->make(MiddlewareDispatcher::class)) + return $injector->make(MiddlewareDispatcher::class) ->withMiddlewares($params['middlewares']); }), 'fallbackHandler' => Reference::to(NotFoundHandler::class), diff --git a/blog-api/src/Auth/AuthController.php b/blog-api/src/Auth/AuthController.php index 5aa01a48..d28d20d5 100644 --- a/blog-api/src/Auth/AuthController.php +++ b/blog-api/src/Auth/AuthController.php @@ -42,13 +42,17 @@ public function __construct( * path="/auth/", * summary="Authenticate by params", * description="", + * * @OA\Response( * response="200", * description="Success", + * * @OA\JsonContent( * allOf={ + * * @OA\Schema(ref="#/components/schemas/Response"), * @OA\Schema( + * * @OA\Property( * property="data", * type="object", @@ -58,15 +62,20 @@ public function __construct( * }, * ) * ), + * * @OA\Response( * response="400", * description="Bad request", + * * @OA\JsonContent(ref="#/components/schemas/BadResponse") * ), + * * @OA\RequestBody( * required=true, + * * @OA\MediaType( * mediaType="application/json", + * * @OA\Schema(ref="#/components/schemas/AuthRequest"), * ), * ), @@ -93,14 +102,18 @@ public function login(AuthRequest $request): ResponseInterface * summary="Logout", * description="", * security={{"ApiKey": {}}}, + * * @OA\Response( * response="200", * description="Success", + * * @OA\JsonContent(ref="#/components/schemas/Response") * ), + * * @OA\Response( * response="400", * description="Bad request", + * * @OA\JsonContent(ref="#/components/schemas/BadResponse") * ), * ) diff --git a/blog-api/src/Auth/AuthRequest.php b/blog-api/src/Auth/AuthRequest.php index b6d3415b..00496706 100644 --- a/blog-api/src/Auth/AuthRequest.php +++ b/blog-api/src/Auth/AuthRequest.php @@ -12,6 +12,7 @@ /** * @OA\Schema( * schema="AuthRequest", + * * @OA\Property(example="Opal1144", property="login", format="string"), * @OA\Property(example="Opal1144", property="password", format="string"), * ) diff --git a/blog-api/src/Blog/BlogController.php b/blog-api/src/Blog/BlogController.php index 13e27255..92c46baf 100644 --- a/blog-api/src/Blog/BlogController.php +++ b/blog-api/src/Blog/BlogController.php @@ -17,7 +17,9 @@ * name="blog", * description="Blog" * ) + * * @OA\Parameter( + * * @OA\Schema( * type="int", * example="2" @@ -55,22 +57,29 @@ public function __construct( * path="/blog/", * summary="Returns paginated blog posts", * description="", + * * @OA\Parameter(ref="#/components/parameters/PageRequest"), + * * @OA\Response( * response="200", * description="Success", + * * @OA\JsonContent( * allOf={ + * * @OA\Schema(ref="#/components/schemas/Response"), * @OA\Schema( + * * @OA\Property( * property="data", * type="object", * @OA\Property( * property="posts", * type="array", + * * @OA\Items(ref="#/components/schemas/Post") * ), + * * @OA\Property( * property="paginator", * type="object", @@ -105,19 +114,25 @@ public function index(PaginatorFormatter $paginatorFormatter, #[Query('page')] i * path="/blog/{id}", * summary="Returns a post with a given ID", * description="", + * * @OA\Parameter( + * * @OA\Schema(type="int", example="2"), * in="path", * name="id", * parameter="id" * ), + * * @OA\Response( * response="200", * description="Success", + * * @OA\JsonContent( * allOf={ + * * @OA\Schema(ref="#/components/schemas/Response"), * @OA\Schema( + * * @OA\Property( * property="data", * type="object", @@ -131,13 +146,17 @@ public function index(PaginatorFormatter $paginatorFormatter, #[Query('page')] i * }, * ) * ), + * * @OA\Response( * response="404", * description="Not found", + * * @OA\JsonContent( * allOf={ + * * @OA\Schema(ref="#/components/schemas/BadResponse"), * @OA\Schema( + * * @OA\Property(property="error_message", example="Entity not found"), * @OA\Property(property="error_code", nullable=true, example=404) * ), @@ -164,17 +183,22 @@ public function view(#[Route('id')] int $id): Response * summary="Creates a blog post", * description="", * security={{"ApiKey": {}}}, + * * @OA\Response( * response="200", * description="Success", + * * @OA\JsonContent( * ref="#/components/schemas/Response" * ) * ), + * * @OA\RequestBody( * required=true, + * * @OA\MediaType( * mediaType="application/json", + * * @OA\Schema(ref="#/components/schemas/EditPostRequest"), * ), * ), @@ -197,23 +221,30 @@ public function create(EditPostRequest $postRequest, UserRequest $userRequest): * summary="Updates a blog post with a given ID", * description="", * security={{"ApiKey": {}}}, + * * @OA\Parameter( + * * @OA\Schema(type="int", example="2"), * in="path", * name="id", * parameter="id" * ), + * * @OA\Response( * response="200", * description="Success", + * * @OA\JsonContent( * ref="#/components/schemas/Response" * ) * ), + * * @OA\RequestBody( * required=true, + * * @OA\MediaType( * mediaType="application/json", + * * @OA\Schema(ref="#/components/schemas/EditPostRequest"), * ), * ) diff --git a/blog-api/src/Blog/EditPostRequest.php b/blog-api/src/Blog/EditPostRequest.php index d5c8464d..375e02de 100644 --- a/blog-api/src/Blog/EditPostRequest.php +++ b/blog-api/src/Blog/EditPostRequest.php @@ -14,6 +14,7 @@ /** * @OA\Schema( * schema="EditPostRequest", + * * @OA\Property(example="Title post", property="title", format="string"), * @OA\Property(example="Text post", property="text", format="string"), * @OA\Property(example=1, property="status", format="int"), diff --git a/blog-api/src/Blog/PostFormatter.php b/blog-api/src/Blog/PostFormatter.php index 5363a030..3193d4bc 100644 --- a/blog-api/src/Blog/PostFormatter.php +++ b/blog-api/src/Blog/PostFormatter.php @@ -9,6 +9,7 @@ /** * @OA\Schema( * schema="Post", + * * @OA\Property(example="100", property="id", format="int"), * @OA\Property(example="Title", property="title", format="string"), * @OA\Property(example="Text", property="content", format="string"), diff --git a/blog-api/src/Dto/ApiResponseData.php b/blog-api/src/Dto/ApiResponseData.php index ba7492f4..65e85c9e 100644 --- a/blog-api/src/Dto/ApiResponseData.php +++ b/blog-api/src/Dto/ApiResponseData.php @@ -15,6 +15,7 @@ * allOf={ * @OA\Schema(ref="#/components/schemas/Response"), * @OA\Schema( + * * @OA\Property( * property="status", * example="failed", diff --git a/blog-api/src/Formatter/PaginatorFormatter.php b/blog-api/src/Formatter/PaginatorFormatter.php index 84221d5c..983c6eef 100644 --- a/blog-api/src/Formatter/PaginatorFormatter.php +++ b/blog-api/src/Formatter/PaginatorFormatter.php @@ -10,6 +10,7 @@ /** * @OA\Schema( * schema="Paginator", + * * @OA\Property(example="10", property="pageSize", format="int"), * @OA\Property(example="1", property="currentPage", format="int"), * @OA\Property(example="3", property="totalPages", format="int"), diff --git a/blog-api/src/InfoController.php b/blog-api/src/InfoController.php index c02fe1d7..3ce6fafb 100644 --- a/blog-api/src/InfoController.php +++ b/blog-api/src/InfoController.php @@ -22,13 +22,17 @@ public function __construct(private VersionProvider $versionProvider) * path="/", * summary="Returns info about the API", * description="", + * * @OA\Response( * response="200", * description="Success", + * * @OA\JsonContent( * allOf={ + * * @OA\Schema(ref="#/components/schemas/Response"), * @OA\Schema( + * * @OA\Property( * property="data", * type="object", diff --git a/blog-api/src/User/UserController.php b/blog-api/src/User/UserController.php index ee7ecf30..4baea2f6 100644 --- a/blog-api/src/User/UserController.php +++ b/blog-api/src/User/UserController.php @@ -42,19 +42,24 @@ public function __construct( * summary="Returns paginated users", * description="", * security={{"ApiKey": {}}}, + * * @OA\Response( * response="200", * description="Success", + * * @OA\JsonContent( * allOf={ + * * @OA\Schema(ref="#/components/schemas/Response"), * @OA\Schema( + * * @OA\Property( * property="data", * type="object", * @OA\Property( * property="users", * type="array", + * * @OA\Items(ref="#/components/schemas/User") * ), * ), @@ -86,19 +91,25 @@ public function list(): ResponseInterface * summary="Returns a user with a given ID", * description="", * security={{"ApiKey": {}}}, + * * @OA\Parameter( + * * @OA\Schema(type="int", example="2"), * in="path", * name="id", * parameter="id" * ), + * * @OA\Response( * response="200", * description="Success", + * * @OA\JsonContent( * allOf={ + * * @OA\Schema(ref="#/components/schemas/Response"), * @OA\Schema( + * * @OA\Property( * property="data", * type="object", diff --git a/blog-api/src/User/UserFormatter.php b/blog-api/src/User/UserFormatter.php index 4b44e09a..115280f4 100644 --- a/blog-api/src/User/UserFormatter.php +++ b/blog-api/src/User/UserFormatter.php @@ -9,6 +9,7 @@ /** * @OA\Schema( * schema="User", + * * @OA\Property(example="UserName", property="login", format="string"), * @OA\Property(example="13.12.2020 00:04:20", property="created_at", format="string"), * ) diff --git a/blog/config/common/routes/routes.php b/blog/config/common/routes/routes.php index 3c325bc0..16fa838b 100644 --- a/blog/config/common/routes/routes.php +++ b/blog/config/common/routes/routes.php @@ -113,7 +113,7 @@ // Blog routes Group::create('/blog') ->routes( - // Index + // Index Route::get('[/page{page:\d+}]') ->middleware( fn (HttpCache $httpCache, PostRepository $postRepository) => $httpCache->withLastModified(function (ServerRequestInterface $request, $params) use ($postRepository) { @@ -156,7 +156,7 @@ // Archive Group::create('/archive') ->routes( - // Index page + // Index page Route::get('') ->action([ArchiveController::class, 'index']) ->name('blog/archive/index'), diff --git a/blog/src/Controller/Actions/ApiInfo.php b/blog/src/Controller/Actions/ApiInfo.php index b2aad8e2..dc83f1c0 100644 --- a/blog/src/Controller/Actions/ApiInfo.php +++ b/blog/src/Controller/Actions/ApiInfo.php @@ -26,6 +26,7 @@ public function __construct(DataResponseFactoryInterface $responseFactory) /** * @OA\Get( * path="/api/info/v2", + * * @OA\Response(response="200", description="Get api version") * ) */ diff --git a/blog/src/User/Controller/ApiUserController.php b/blog/src/User/Controller/ApiUserController.php index 1f3bb769..9f0c4e55 100644 --- a/blog/src/User/Controller/ApiUserController.php +++ b/blog/src/User/Controller/ApiUserController.php @@ -28,6 +28,7 @@ public function __construct(private DataResponseFactoryInterface $responseFactor * @OA\Get( * path="/api/user", * tags={"user"}, + * * @OA\Response(response="200", description="Get users list") * ) */ @@ -52,12 +53,15 @@ public function index(UserRepository $userRepository): ResponseInterface * @OA\Get( * path="/api/user/{login}", * tags={"user"}, + * * @OA\Parameter( + * * @OA\Schema(type="string"), * in="path", * name="login", * parameter="login" * ), + * * @OA\Response(response="200", description="Get user info") * ) */