From 9e34dc7a54861f84ae9aee6b162c3067d6fd3d17 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sun, 8 Oct 2023 15:18:14 +0300 Subject: [PATCH] Replace request model to Yii Input HTTP (#599) --- blog-api/composer.json | 4 +- blog-api/config/common/di/hydrator.php | 13 +++++++ blog-api/config/common/di/router.php | 6 +-- .../config/web/di/middleware-dispatcher.php | 15 ++++++- blog-api/config/web/params.php | 8 +++- blog-api/src/Auth/AuthRequest.php | 19 ++++++--- blog-api/src/Blog/BlogController.php | 8 ++-- blog-api/src/Blog/EditPostRequest.php | 39 +++++++++++++------ .../src/Middleware/ExceptionMiddleware.php | 6 +-- blog-api/src/User/UserController.php | 4 +- blog-api/src/User/UserRequest.php | 13 ++++--- blog/Makefile | 5 +++ blog/composer.json | 5 ++- blog/config/common/di/hydrator.php | 13 +++++++ blog/config/common/di/router.php | 6 +-- blog/config/common/routes/routes.php | 2 +- blog/config/web/di/middleware-dispatcher.php | 18 +++++++-- blog/src/Auth/Controller/AuthController.php | 10 ++--- blog/src/Auth/Controller/SignupController.php | 4 +- blog/src/Auth/Form/LoginForm.php | 10 ++--- blog/src/Auth/Form/SignupForm.php | 5 +-- blog/src/Blog/Archive/ArchiveController.php | 10 ++--- blog/src/Blog/BlogController.php | 4 +- blog/src/Blog/CommentController.php | 4 +- blog/src/Blog/Post/PostController.php | 9 ++--- blog/src/Contact/ContactController.php | 11 +++--- blog/src/Contact/ContactForm.php | 5 ++- blog/src/Contact/ContactMailer.php | 7 +--- blog/src/User/Controller/UserController.php | 16 ++++---- 29 files changed, 177 insertions(+), 102 deletions(-) create mode 100644 blog-api/config/common/di/hydrator.php create mode 100644 blog/config/common/di/hydrator.php diff --git a/blog-api/composer.json b/blog-api/composer.json index 3eacedb2c..2338ba771 100644 --- a/blog-api/composer.json +++ b/blog-api/composer.json @@ -49,11 +49,13 @@ "yiisoft/factory": "^1.0", "yiisoft/files": "^2.0", "yiisoft/http": "^1.2", + "yiisoft/hydrator-validator": "dev-master", "yiisoft/injector": "^1.0", + "yiisoft/input-http": "dev-master", "yiisoft/log": "^2.0", "yiisoft/log-target-file": "^3.0", + "yiisoft/middleware-dispatcher": "^5.1", "yiisoft/request-body-parser": "^1.1", - "yiisoft/request-model": "dev-master", "yiisoft/router": "^3.0", "yiisoft/router-fastroute": "^3.0", "yiisoft/security": "^1.0", diff --git a/blog-api/config/common/di/hydrator.php b/blog-api/config/common/di/hydrator.php new file mode 100644 index 000000000..1561583dc --- /dev/null +++ b/blog-api/config/common/di/hydrator.php @@ -0,0 +1,13 @@ + ContainerAttributeResolverFactory::class, + ObjectFactoryInterface::class => ContainerObjectFactory::class, +]; diff --git a/blog-api/config/common/di/router.php b/blog-api/config/common/di/router.php index 864373441..0df551e05 100644 --- a/blog-api/config/common/di/router.php +++ b/blog-api/config/common/di/router.php @@ -34,12 +34,10 @@ ->middleware(ExceptionMiddleware::class) ->middleware(RequestBodyParser::class) ->addGroup( - Group::create() - ->routes(...$config->get('routes')) + Group::create('/{_language}')->routes(...$config->get('app-routes')), ) ->addGroup( - Group::create('/{_language}') - ->routes(...$config->get('app-routes')) + Group::create()->routes(...$config->get('routes')), ); return new RouteCollection($collector); diff --git a/blog-api/config/web/di/middleware-dispatcher.php b/blog-api/config/web/di/middleware-dispatcher.php index f2b303927..c9e2a1599 100644 --- a/blog-api/config/web/di/middleware-dispatcher.php +++ b/blog-api/config/web/di/middleware-dispatcher.php @@ -6,9 +6,20 @@ * @var array $params */ +use Yiisoft\Definitions\Reference; +use Yiisoft\Input\Http\HydratorAttributeParametersResolver; +use Yiisoft\Input\Http\Request\Catcher\RequestCatcherParametersResolver; +use Yiisoft\Input\Http\RequestInputParametersResolver; +use Yiisoft\Middleware\Dispatcher\CompositeParametersResolver; use Yiisoft\Middleware\Dispatcher\ParametersResolverInterface; -use Yiisoft\RequestModel\HandlerParametersResolver; return [ - ParametersResolverInterface::class => HandlerParametersResolver::class, + ParametersResolverInterface::class => [ + 'class' => CompositeParametersResolver::class, + '__construct()' => [ + Reference::to(RequestCatcherParametersResolver::class), + Reference::to(HydratorAttributeParametersResolver::class), + Reference::to(RequestInputParametersResolver::class), + ], + ], ]; diff --git a/blog-api/config/web/params.php b/blog-api/config/web/params.php index 0dae23dee..2b3b65847 100644 --- a/blog-api/config/web/params.php +++ b/blog-api/config/web/params.php @@ -2,4 +2,10 @@ declare(strict_types=1); -return []; +return [ + 'yiisoft/input-http' => [ + 'requestInputParametersResolver' => [ + 'throwInputValidationException' => true, + ], + ], +]; diff --git a/blog-api/src/Auth/AuthRequest.php b/blog-api/src/Auth/AuthRequest.php index 004967063..49e764266 100644 --- a/blog-api/src/Auth/AuthRequest.php +++ b/blog-api/src/Auth/AuthRequest.php @@ -5,7 +5,8 @@ namespace App\Auth; use OpenApi\Annotations as OA; -use Yiisoft\RequestModel\RequestModel; +use Yiisoft\Input\Http\Attribute\Parameter\Body; +use Yiisoft\Input\Http\RequestInputInterface; use Yiisoft\Validator\Rule\Required; use Yiisoft\Validator\RulesProviderInterface; @@ -17,25 +18,31 @@ * @OA\Property(example="Opal1144", property="password", format="string"), * ) */ -final class AuthRequest extends RequestModel implements RulesProviderInterface +final class AuthRequest implements RequestInputInterface, RulesProviderInterface { + #[Body('login')] + private string $login = ''; + + #[Body('password')] + private string $password = ''; + public function getLogin(): string { - return (string) $this->getAttributeValue('body.login'); + return $this->login; } public function getPassword(): string { - return (string) $this->getAttributeValue('body.password'); + return $this->password; } public function getRules(): array { return [ - 'body.login' => [ + 'login' => [ new Required(), ], - 'body.password' => [ + 'password' => [ new Required(), ], ]; diff --git a/blog-api/src/Blog/BlogController.php b/blog-api/src/Blog/BlogController.php index 92c46baf0..7ca829180 100644 --- a/blog-api/src/Blog/BlogController.php +++ b/blog-api/src/Blog/BlogController.php @@ -9,8 +9,8 @@ use OpenApi\Annotations as OA; use Psr\Http\Message\ResponseInterface as Response; use Yiisoft\DataResponse\DataResponseFactoryInterface; -use Yiisoft\RequestModel\Attribute\Query; -use Yiisoft\RequestModel\Attribute\Route; +use Yiisoft\Input\Http\Attribute\Parameter\Query; +use Yiisoft\Hydrator\Temp\RouteArgument; /** * @OA\Tag( @@ -165,7 +165,7 @@ public function index(PaginatorFormatter $paginatorFormatter, #[Query('page')] i * ), * ) */ - public function view(#[Route('id')] int $id): Response + public function view(#[RouteArgument('id')] int $id): Response { return $this->responseFactory->createResponse( [ @@ -250,7 +250,7 @@ public function create(EditPostRequest $postRequest, UserRequest $userRequest): * ) * ) */ - public function update(EditPostRequest $postRequest, #[Route('id')] int $id): Response + public function update(EditPostRequest $postRequest, #[RouteArgument('id')] int $id): Response { $post = $this->postBuilder->build( $this->blogService->getPost($id), diff --git a/blog-api/src/Blog/EditPostRequest.php b/blog-api/src/Blog/EditPostRequest.php index 375e02ded..61d1f9770 100644 --- a/blog-api/src/Blog/EditPostRequest.php +++ b/blog-api/src/Blog/EditPostRequest.php @@ -5,7 +5,10 @@ namespace App\Blog; use OpenApi\Annotations as OA; -use Yiisoft\RequestModel\RequestModel; +use Yiisoft\Hydrator\Validator\Attribute\Validate; +use Yiisoft\Input\Http\AbstractInput; +use Yiisoft\Input\Http\Attribute\Parameter\Body; +use Yiisoft\Hydrator\Temp\RouteArgument; use Yiisoft\Validator\Result; use Yiisoft\Validator\Rule\Length; use Yiisoft\Validator\Rule\Required; @@ -20,41 +23,53 @@ * @OA\Property(example=1, property="status", format="int"), * ) */ -final class EditPostRequest extends RequestModel implements RulesProviderInterface +final class EditPostRequest extends AbstractInput implements RulesProviderInterface { + #[RouteArgument('id')] + private int $id; + + #[Body('title')] + #[Validate(new Required())] + private string $title = ''; + + #[Body('text')] + #[Validate(new Required())] + private string $text = ''; + + #[Body('status')] + #[Validate(new Required())] + private int $status; + public function getId(): int { - return (int) $this->getAttributeValue('router.id'); + return $this->id; } public function getTitle(): string { - return (string) $this->getAttributeValue('body.title'); + return $this->title; } public function getText(): string { - return (string) $this->getAttributeValue('body.text'); + return $this->text; } public function getStatus(): PostStatus { - return PostStatus::from($this->getAttributeValue('body.status')); + return PostStatus::from($this->status); } public function getRules(): array { return [ - 'body.title' => [ - new Required(), + 'title' => [ new Length(min: 5, max: 255), ], - 'body.text' => [ - new Required(), + 'text' => [ new Length(min: 5, max: 1000), ], - 'body.status' => [ - new Required(), + 'status' => [ static function ($value): Result { $result = new Result(); if (!PostStatus::isValid($value)) { diff --git a/blog-api/src/Middleware/ExceptionMiddleware.php b/blog-api/src/Middleware/ExceptionMiddleware.php index 5e3a50214..c64128112 100644 --- a/blog-api/src/Middleware/ExceptionMiddleware.php +++ b/blog-api/src/Middleware/ExceptionMiddleware.php @@ -11,7 +11,7 @@ use Psr\Http\Server\RequestHandlerInterface; use Yiisoft\DataResponse\DataResponseFactoryInterface; use Yiisoft\Http\Status; -use Yiisoft\RequestModel\RequestValidationException; +use Yiisoft\Input\Http\InputValidationException; final class ExceptionMiddleware implements MiddlewareInterface { @@ -28,8 +28,8 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface return $handler->handle($request); } catch (ApplicationException $e) { return $this->dataResponseFactory->createResponse($e->getMessage(), $e->getCode()); - } catch (RequestValidationException $e) { - return $this->dataResponseFactory->createResponse($e->getFirstError(), Status::BAD_REQUEST); + } catch (InputValidationException $e) { + return $this->dataResponseFactory->createResponse($e->getResult()->getErrorMessages()[0], Status::BAD_REQUEST); } } } diff --git a/blog-api/src/User/UserController.php b/blog-api/src/User/UserController.php index 4baea2f64..c02bbf4e3 100644 --- a/blog-api/src/User/UserController.php +++ b/blog-api/src/User/UserController.php @@ -9,7 +9,7 @@ use OpenApi\Annotations as OA; use Psr\Http\Message\ResponseInterface; use Yiisoft\DataResponse\DataResponseFactoryInterface; -use Yiisoft\RequestModel\Attribute\Route; +use Yiisoft\Hydrator\Temp\RouteArgument; /** * @OA\Tag( @@ -125,7 +125,7 @@ public function list(): ResponseInterface * ), * ) */ - public function get(#[Route('id')] int $id): ResponseInterface + public function get(#[RouteArgument('id')] int $id): ResponseInterface { /** * @var User $user diff --git a/blog-api/src/User/UserRequest.php b/blog-api/src/User/UserRequest.php index 08c715aa5..3f3825461 100644 --- a/blog-api/src/User/UserRequest.php +++ b/blog-api/src/User/UserRequest.php @@ -5,15 +5,16 @@ namespace App\User; use Yiisoft\Auth\Middleware\Authentication; -use Yiisoft\RequestModel\RequestModel; +use Yiisoft\Input\Http\Attribute\Parameter\Request; +use Yiisoft\Input\Http\RequestInputInterface; -final class UserRequest extends RequestModel +final class UserRequest implements RequestInputInterface { + #[Request(Authentication::class)] + private User $user; + public function getUser(): User { - /** - * @var User $identity - */ - return $this->getAttributeValue('attributes.' . Authentication::class); + return $this->user; } } diff --git a/blog/Makefile b/blog/Makefile index 33a99f1ff..148afab89 100644 --- a/blog/Makefile +++ b/blog/Makefile @@ -17,3 +17,8 @@ npm-update: yii3: docker-compose run php ./yii $(filter-out $@, $(MAKECMDGOALS)) + +test: + docker-compose run php ./vendor/bin/codecept run +psalm: + docker-compose run php ./vendor/bin/psalm diff --git a/blog/composer.json b/blog/composer.json index 7fd7fec3e..7912305a8 100644 --- a/blog/composer.json +++ b/blog/composer.json @@ -50,19 +50,20 @@ "yiisoft/di": "^1.2", "yiisoft/error-handler": "^3.0", "yiisoft/factory": "^1.0", - "yiisoft/form": "^1.0@dev", + "yiisoft/form": "dev-input", "yiisoft/html": "^3.0", "yiisoft/http": "^1.2", "yiisoft/injector": "^1.0", + "yiisoft/input-http": "dev-master", "yiisoft/log": "^2.0", "yiisoft/log-target-file": "^3.0", "yiisoft/mailer": "^5.0", "yiisoft/mailer-symfony": "^3.0", + "yiisoft/middleware-dispatcher": "^5.2", "yiisoft/rate-limiter": "dev-master", "yiisoft/rbac": "^1.0", "yiisoft/rbac-php": "^1.0", "yiisoft/rbac-rules-container": "^2.0", - "yiisoft/request-model": "dev-master", "yiisoft/router": "^3.0", "yiisoft/router-fastroute": "^3.0", "yiisoft/security": "^1.0", diff --git a/blog/config/common/di/hydrator.php b/blog/config/common/di/hydrator.php new file mode 100644 index 000000000..1561583dc --- /dev/null +++ b/blog/config/common/di/hydrator.php @@ -0,0 +1,13 @@ + ContainerAttributeResolverFactory::class, + ObjectFactoryInterface::class => ContainerObjectFactory::class, +]; diff --git a/blog/config/common/di/router.php b/blog/config/common/di/router.php index 3cbc11477..0f7be58c0 100644 --- a/blog/config/common/di/router.php +++ b/blog/config/common/di/router.php @@ -33,12 +33,10 @@ ->middleware(CsrfMiddleware::class) ->middleware(FormatDataResponse::class) ->addGroup( - Group::create() - ->routes(...$config->get('routes')) + Group::create('/{_language}')->routes(...$config->get('app-routes')), ) ->addGroup( - Group::create('/{_language}') - ->routes(...$config->get('app-routes')) + Group::create()->routes(...$config->get('routes')), ); if (!str_starts_with(getenv('YII_ENV') ?: '', 'prod')) { diff --git a/blog/config/common/routes/routes.php b/blog/config/common/routes/routes.php index 0d5156aec..342b7861c 100644 --- a/blog/config/common/routes/routes.php +++ b/blog/config/common/routes/routes.php @@ -58,7 +58,7 @@ ->middleware(fn ( ResponseFactoryInterface $responseFactory, StorageInterface $storage - ) => new LimitRequestsMiddleware(new Counter($storage, 5, 5), $responseFactory)) + ) => new LimitRequestsMiddleware(new Counter($storage, 10, 10), $responseFactory)) ->action([SignupController::class, 'signup']) ->name('auth/signup'), diff --git a/blog/config/web/di/middleware-dispatcher.php b/blog/config/web/di/middleware-dispatcher.php index fd505727d..7c06f71f2 100644 --- a/blog/config/web/di/middleware-dispatcher.php +++ b/blog/config/web/di/middleware-dispatcher.php @@ -2,14 +2,24 @@ declare(strict_types=1); +use Yiisoft\Definitions\Reference; +use Yiisoft\Input\Http\HydratorAttributeParametersResolver; +use Yiisoft\Input\Http\Request\Catcher\RequestCatcherParametersResolver; +use Yiisoft\Input\Http\RequestInputParametersResolver; +use Yiisoft\Middleware\Dispatcher\CompositeParametersResolver; +use Yiisoft\Middleware\Dispatcher\ParametersResolverInterface; /** * @var array $params */ -use Yiisoft\Middleware\Dispatcher\ParametersResolverInterface; -use Yiisoft\RequestModel\HandlerParametersResolver; - return [ - ParametersResolverInterface::class => HandlerParametersResolver::class, + ParametersResolverInterface::class => [ + 'class' => CompositeParametersResolver::class, + '__construct()' => [ + Reference::to(RequestCatcherParametersResolver::class), + Reference::to(HydratorAttributeParametersResolver::class), + Reference::to(RequestInputParametersResolver::class), + ], + ], ]; diff --git a/blog/src/Auth/Controller/AuthController.php b/blog/src/Auth/Controller/AuthController.php index da26e7823..3dfb3ca57 100644 --- a/blog/src/Auth/Controller/AuthController.php +++ b/blog/src/Auth/Controller/AuthController.php @@ -9,11 +9,11 @@ use App\Service\WebControllerService; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use Yiisoft\Form\FormHydrator; use Yiisoft\Http\Method; use Yiisoft\Translator\TranslatorInterface; use Yiisoft\User\Login\Cookie\CookieLogin; use Yiisoft\User\Login\Cookie\CookieLoginIdentityInterface; -use Yiisoft\Validator\ValidatorInterface; use Yiisoft\Yii\View\ViewRenderer; final class AuthController @@ -29,7 +29,7 @@ public function __construct( public function login( ServerRequestInterface $request, TranslatorInterface $translator, - ValidatorInterface $validator, + FormHydrator $formHydrator, CookieLogin $cookieLogin ): ResponseInterface { if (!$this->authService->isGuest()) { @@ -41,10 +41,8 @@ public function login( if ( $request->getMethod() === Method::POST - && $loginForm->load(is_array($body) ? $body : []) - && $validator - ->validate($loginForm) - ->isValid() + && $formHydrator->populate($loginForm, $body) + && $loginForm->isValid() ) { $identity = $this->authService->getIdentity(); diff --git a/blog/src/Auth/Controller/SignupController.php b/blog/src/Auth/Controller/SignupController.php index 97cf232bb..2e0f5a8af 100644 --- a/blog/src/Auth/Controller/SignupController.php +++ b/blog/src/Auth/Controller/SignupController.php @@ -9,6 +9,7 @@ use App\Service\WebControllerService; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use Yiisoft\Form\FormHydrator; use Yiisoft\Http\Method; use Yiisoft\Yii\View\ViewRenderer; @@ -22,6 +23,7 @@ public function __construct(private WebControllerService $webService, private Vi public function signup( AuthService $authService, ServerRequestInterface $request, + FormHydrator $formHydrator, SignupForm $signupForm ): ResponseInterface { if (!$authService->isGuest()) { @@ -29,7 +31,7 @@ public function signup( } if ($request->getMethod() === Method::POST - && $signupForm->load($request->getParsedBody()) + && $formHydrator->populate($signupForm, $request->getParsedBody()) && $signupForm->signup() ) { return $this->redirectToMain(); diff --git a/blog/src/Auth/Form/LoginForm.php b/blog/src/Auth/Form/LoginForm.php index 985c9d529..71f9a31c3 100644 --- a/blog/src/Auth/Form/LoginForm.php +++ b/blog/src/Auth/Form/LoginForm.php @@ -18,9 +18,10 @@ final class LoginForm extends FormModel implements RulesProviderInterface private string $password = ''; private bool $rememberMe = false; - public function __construct(private AuthService $authService, private TranslatorInterface $translator) - { - parent::__construct(); + public function __construct( + private AuthService $authService, + private TranslatorInterface $translator, + ) { } public function getAttributeLabels(): array @@ -54,9 +55,6 @@ private function passwordRules(): array $result = new Result(); if (!$this->authService->login($this->login, $this->password)) { - $this - ->getFormErrors() - ->addError('login', ''); $result->addError($this->translator->translate('validator.invalid.login.password')); } diff --git a/blog/src/Auth/Form/SignupForm.php b/blog/src/Auth/Form/SignupForm.php index 30984ef2a..9c7dad67f 100644 --- a/blog/src/Auth/Form/SignupForm.php +++ b/blog/src/Auth/Form/SignupForm.php @@ -13,7 +13,6 @@ use Yiisoft\Validator\Rule\Length; use Yiisoft\Validator\Rule\Required; use Yiisoft\Validator\RulesProviderInterface; -use Yiisoft\Validator\ValidatorInterface; final class SignupForm extends FormModel implements RulesProviderInterface { @@ -22,11 +21,9 @@ final class SignupForm extends FormModel implements RulesProviderInterface private string $passwordVerify = ''; public function __construct( - private ValidatorInterface $validator, private TranslatorInterface $translator, private UserRepository $userRepository, ) { - parent::__construct(); } public function getAttributeLabels(): array @@ -55,7 +52,7 @@ public function getPassword(): string public function signup(): false|User { - if ($this->validator->validate($this)->isValid()) { + if ($this->isValid()) { $user = new User($this->getLogin(), $this->getPassword()); $this->userRepository->save($user); diff --git a/blog/src/Blog/Archive/ArchiveController.php b/blog/src/Blog/Archive/ArchiveController.php index 004c20606..080c9ecb5 100644 --- a/blog/src/Blog/Archive/ArchiveController.php +++ b/blog/src/Blog/Archive/ArchiveController.php @@ -7,7 +7,7 @@ use App\Blog\Tag\TagRepository; use Psr\Http\Message\ResponseInterface as Response; use Yiisoft\Data\Paginator\OffsetPaginator; -use Yiisoft\RequestModel\Attribute\Route; +use Yiisoft\Hydrator\Temp\RouteArgument; use Yiisoft\Yii\View\ViewRenderer; final class ArchiveController @@ -29,9 +29,9 @@ public function index(ArchiveRepository $archiveRepo): Response public function monthlyArchive( TagRepository $tagRepository, ArchiveRepository $archiveRepo, - #[Route('page')] int $pageNum = 1, - #[Route('year')] int $year = 0, - #[Route('month')] int $month = 0, + #[RouteArgument('page')] int $pageNum = 1, + #[RouteArgument('year')] int $year = 0, + #[RouteArgument('month')] int $month = 0, ): Response { $dataReader = $archiveRepo->getMonthlyArchive($year, $month); $paginator = (new OffsetPaginator($dataReader)) @@ -51,7 +51,7 @@ public function monthlyArchive( return $this->viewRenderer->render('monthly-archive', $data); } - public function yearlyArchive(ArchiveRepository $archiveRepo, #[Route('year')] int $year = 0): Response + public function yearlyArchive(ArchiveRepository $archiveRepo, #[RouteArgument('year')] int $year = 0): Response { $data = [ 'year' => $year, diff --git a/blog/src/Blog/BlogController.php b/blog/src/Blog/BlogController.php index 011795095..18552ddb8 100644 --- a/blog/src/Blog/BlogController.php +++ b/blog/src/Blog/BlogController.php @@ -9,7 +9,7 @@ use App\Blog\Tag\TagRepository; use Psr\Http\Message\ResponseInterface as Response; use Yiisoft\Data\Paginator\OffsetPaginator; -use Yiisoft\RequestModel\Attribute\Route; +use Yiisoft\Hydrator\Temp\RouteArgument; use Yiisoft\User\CurrentUser; use Yiisoft\Yii\View\ViewRenderer; @@ -31,7 +31,7 @@ public function index( TagRepository $tagRepository, ArchiveRepository $archiveRepo, CurrentUser $currentUser, - #[Route('page')] $pageNum = 1, + #[RouteArgument('page')] $pageNum = 1, ): Response { $dataReader = $postRepository->findAllPreloaded(); $paginator = (new OffsetPaginator($dataReader)) diff --git a/blog/src/Blog/CommentController.php b/blog/src/Blog/CommentController.php index 303cc420c..5b218791e 100644 --- a/blog/src/Blog/CommentController.php +++ b/blog/src/Blog/CommentController.php @@ -7,7 +7,7 @@ use App\Blog\Comment\CommentService; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Yiisoft\RequestModel\Attribute\Route; +use Yiisoft\Hydrator\Temp\RouteArgument; use Yiisoft\Yii\View\ViewRenderer; final class CommentController @@ -19,7 +19,7 @@ public function __construct(ViewRenderer $viewRenderer) $this->viewRenderer = $viewRenderer->withControllerName('blog/comments'); } - public function index(Request $request, CommentService $service, #[Route('next')] ?string $next): Response + public function index(Request $request, CommentService $service, #[RouteArgument('next')] ?string $next): Response { $paginator = $service->getFeedPaginator(); if ($next !== null) { diff --git a/blog/src/Blog/Post/PostController.php b/blog/src/Blog/Post/PostController.php index e5e43130d..a4f3e15fc 100644 --- a/blog/src/Blog/Post/PostController.php +++ b/blog/src/Blog/Post/PostController.php @@ -9,6 +9,7 @@ use App\User\UserService; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; +use Yiisoft\Form\FormHydrator; use Yiisoft\Http\Method; use Yiisoft\Router\CurrentRoute; use Yiisoft\Validator\ValidatorInterface; @@ -37,7 +38,7 @@ public function index(CurrentRoute $currentRoute, PostRepository $postRepository return $this->viewRenderer->render('index', ['item' => $item, 'canEdit' => $canEdit, 'slug' => $slug]); } - public function add(Request $request, ValidatorInterface $validator): Response + public function add(Request $request, FormHydrator $formHydrator): Response { $parameters = [ 'title' => 'Add post', @@ -48,15 +49,13 @@ public function add(Request $request, ValidatorInterface $validator): Response if ($request->getMethod() === Method::POST) { $form = new PostForm(); - if ($form->load($parameters['body']) && $validator - ->validate($form) - ->isValid()) { + if ($formHydrator->populate($form, $parameters['body']) && $form->isValid()) { $this->postService->savePost($this->userService->getUser(), new Post(), $form); return $this->webService->getRedirectResponse('blog/index'); } - $parameters['errors'] = $form->getFormErrors(); + $parameters['errors'] = $form->getValidationResult()->getErrorMessagesIndexedByAttribute(); } return $this->viewRenderer->render('__form', $parameters); diff --git a/blog/src/Contact/ContactController.php b/blog/src/Contact/ContactController.php index 180ac097d..60761c7f6 100644 --- a/blog/src/Contact/ContactController.php +++ b/blog/src/Contact/ContactController.php @@ -7,11 +7,11 @@ use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use Yiisoft\Form\FormHydrator; use Yiisoft\Http\Header; use Yiisoft\Http\Method; use Yiisoft\Http\Status; use Yiisoft\Router\UrlGeneratorInterface; -use Yiisoft\Validator\ValidatorInterface; use Yiisoft\Yii\View\ViewRenderer; final class ContactController @@ -28,14 +28,15 @@ public function __construct( } public function contact( - ValidatorInterface $validator, + FormHydrator $formHydrator, ServerRequestInterface $request ): ResponseInterface { $body = $request->getParsedBody(); $form = new ContactForm(); - if (($request->getMethod() === Method::POST) && $form->load((array) $body) && $validator - ->validate($form) - ->isValid()) { + if (($request->getMethod() === Method::POST) + && $formHydrator->populate($form, $body) + && $form->isValid() + ) { $this->mailer->send($form, $request); return $this->responseFactory diff --git a/blog/src/Contact/ContactForm.php b/blog/src/Contact/ContactForm.php index ec76a96d0..9703c8e07 100644 --- a/blog/src/Contact/ContactForm.php +++ b/blog/src/Contact/ContactForm.php @@ -5,6 +5,7 @@ namespace App\Contact; use Yiisoft\Form\FormModel; +use Yiisoft\Input\Http\Attribute\Parameter\UploadedFiles; use Yiisoft\Validator\Rule\Email; use Yiisoft\Validator\Rule\Required; use Yiisoft\Validator\RulesProviderInterface; @@ -15,7 +16,9 @@ final class ContactForm extends FormModel implements RulesProviderInterface private string $email = ''; private string $subject = ''; private string $body = ''; - private ?array $attachFiles = null; + + #[UploadedFiles('ContactForm.attachFiles')] + private array $attachFiles = []; public function getAttributeLabels(): array { diff --git a/blog/src/Contact/ContactMailer.php b/blog/src/Contact/ContactMailer.php index 6212bf70d..1ae3b5d9f 100644 --- a/blog/src/Contact/ContactMailer.php +++ b/blog/src/Contact/ContactMailer.php @@ -5,9 +5,7 @@ namespace App\Contact; use Exception; -use Psr\Http\Message\ServerRequestInterface; use Psr\Log\LoggerInterface; -use Yiisoft\Form\FormModelInterface; use Yiisoft\Mailer\File; use Yiisoft\Mailer\MailerInterface; use Yiisoft\Mailer\MessageBodyTemplate; @@ -28,7 +26,7 @@ public function __construct( $this->mailer = $this->mailer->withTemplate(new MessageBodyTemplate(__DIR__ . '/mail/')); } - public function send(FormModelInterface $form, ServerRequestInterface $request): void + public function send(ContactForm $form): void { $message = $this->mailer ->compose( @@ -42,8 +40,7 @@ public function send(FormModelInterface $form, ServerRequestInterface $request): ->withSender($this->sender) ->withTo($this->to); - $attachFiles = $request->getUploadedFiles(); - foreach ($attachFiles as $attachFile) { + foreach ($form->getAttributeValue('attachFiles') as $attachFile) { foreach ($attachFile as $file) { if ($file[0]?->getError() === UPLOAD_ERR_OK) { $message = $message->withAttached( diff --git a/blog/src/User/Controller/UserController.php b/blog/src/User/Controller/UserController.php index 60d9a2927..99ec5edc3 100644 --- a/blog/src/User/Controller/UserController.php +++ b/blog/src/User/Controller/UserController.php @@ -9,9 +9,9 @@ use Psr\Http\Message\ResponseInterface as Response; use Yiisoft\Data\Paginator\OffsetPaginator; use Yiisoft\Data\Reader\Sort; -use Yiisoft\RequestModel\Attribute\Body; -use Yiisoft\RequestModel\Attribute\Query; -use Yiisoft\RequestModel\Attribute\Route; +use Yiisoft\Input\Http\Attribute\Parameter\Body; +use Yiisoft\Input\Http\Attribute\Parameter\Query; +use Yiisoft\Hydrator\Temp\RouteArgument; use Yiisoft\Yii\View\ViewRenderer; final class UserController @@ -26,14 +26,14 @@ public function __construct(private ViewRenderer $viewRenderer) public function index( UserRepository $userRepository, #[Body] ?array $body, - #[Query] array $sortOrder, - #[Route('page')] int $page = 1, - #[Route('pagesize')] int $pageSize = null, + #[Query('sort')] ?string $sortOrder = null, + #[RouteArgument('page')] int $page = 1, + #[RouteArgument('pagesize')] int $pageSize = null, ): Response { $dataReader = $userRepository ->findAll() ->withSort(Sort::only(['id', 'login']) - ->withOrderString($sortOrder['sort'] ?? 'id')); + ->withOrderString($sortOrder ?? 'id')); if ($pageSize === null) { $pageSize = (int) ($body['pageSize'] ?? OffSetPaginator::DEFAULT_PAGE_SIZE); @@ -46,7 +46,7 @@ public function index( } public function profile( - #[Route('login')] string $login, + #[RouteArgument('login')] string $login, ResponseFactoryInterface $responseFactory, UserRepository $userRepository ): Response {