Skip to content

Commit

Permalink
Replace request model to Yii Input HTTP (#599)
Browse files Browse the repository at this point in the history
  • Loading branch information
vjik committed Oct 8, 2023
1 parent 561265e commit 9e34dc7
Show file tree
Hide file tree
Showing 29 changed files with 177 additions and 102 deletions.
4 changes: 3 additions & 1 deletion blog-api/composer.json
Expand Up @@ -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",
Expand Down
13 changes: 13 additions & 0 deletions blog-api/config/common/di/hydrator.php
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

use Yiisoft\Hydrator\AttributeHandling\ResolverFactory\AttributeResolverFactoryInterface;
use Yiisoft\Hydrator\AttributeHandling\ResolverFactory\ContainerAttributeResolverFactory;
use Yiisoft\Hydrator\ObjectFactory\ContainerObjectFactory;
use Yiisoft\Hydrator\ObjectFactory\ObjectFactoryInterface;

return [
AttributeResolverFactoryInterface::class => ContainerAttributeResolverFactory::class,
ObjectFactoryInterface::class => ContainerObjectFactory::class,
];
6 changes: 2 additions & 4 deletions blog-api/config/common/di/router.php
Expand Up @@ -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);
Expand Down
15 changes: 13 additions & 2 deletions blog-api/config/web/di/middleware-dispatcher.php
Expand Up @@ -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),
],
],
];
8 changes: 7 additions & 1 deletion blog-api/config/web/params.php
Expand Up @@ -2,4 +2,10 @@

declare(strict_types=1);

return [];
return [
'yiisoft/input-http' => [
'requestInputParametersResolver' => [
'throwInputValidationException' => true,
],
],
];
19 changes: 13 additions & 6 deletions blog-api/src/Auth/AuthRequest.php
Expand Up @@ -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;

Expand All @@ -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(),
],
];
Expand Down
8 changes: 4 additions & 4 deletions blog-api/src/Blog/BlogController.php
Expand Up @@ -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(
Expand Down Expand Up @@ -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(
[
Expand Down Expand Up @@ -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),
Expand Down
39 changes: 27 additions & 12 deletions blog-api/src/Blog/EditPostRequest.php
Expand Up @@ -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;
Expand All @@ -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)) {
Expand Down
6 changes: 3 additions & 3 deletions blog-api/src/Middleware/ExceptionMiddleware.php
Expand Up @@ -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
{
Expand All @@ -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);
}
}
}
4 changes: 2 additions & 2 deletions blog-api/src/User/UserController.php
Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand Down
13 changes: 7 additions & 6 deletions blog-api/src/User/UserRequest.php
Expand Up @@ -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;
}
}
5 changes: 5 additions & 0 deletions blog/Makefile
Expand Up @@ -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
5 changes: 3 additions & 2 deletions blog/composer.json
Expand Up @@ -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",
Expand Down
13 changes: 13 additions & 0 deletions blog/config/common/di/hydrator.php
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

use Yiisoft\Hydrator\AttributeHandling\ResolverFactory\AttributeResolverFactoryInterface;
use Yiisoft\Hydrator\AttributeHandling\ResolverFactory\ContainerAttributeResolverFactory;
use Yiisoft\Hydrator\ObjectFactory\ContainerObjectFactory;
use Yiisoft\Hydrator\ObjectFactory\ObjectFactoryInterface;

return [
AttributeResolverFactoryInterface::class => ContainerAttributeResolverFactory::class,
ObjectFactoryInterface::class => ContainerObjectFactory::class,
];
6 changes: 2 additions & 4 deletions blog/config/common/di/router.php
Expand Up @@ -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')) {
Expand Down
2 changes: 1 addition & 1 deletion blog/config/common/routes/routes.php
Expand Up @@ -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'),

Expand Down
18 changes: 14 additions & 4 deletions blog/config/web/di/middleware-dispatcher.php
Expand Up @@ -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),
],
],
];

0 comments on commit 9e34dc7

Please sign in to comment.