Files
cheeper-ddd-cqrs-example/src/App/Controller/PostAuthorController.php
2022-08-07 19:36:34 +02:00

125 lines
4.8 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Controller;
use App\Dto\AuthorDto;
use Cheeper\Application\AuthorApplicationService;
use Cheeper\DomainModel\Author\AuthorAlreadyExists;
use Nelmio\ApiDocBundle\Annotation\Model;
use Ramsey\Uuid\Uuid;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Component\Validator\Constraints as Assert;
use function Safe\json_decode;
use OpenApi\Attributes as OA;
final class PostAuthorController extends AbstractController
{
public function __construct(
private readonly AuthorApplicationService $authorApplicationService,
private readonly ValidatorInterface $validator,
) {
}
#[Route("/authors", methods: [Request::METHOD_POST])]
#[OA\RequestBody(
required: true,
content: new OA\JsonContent(
properties: [
new OA\Property(property: "username", type: "string", nullable: false),
new OA\Property(property: "email", type: "string", nullable: false),
new OA\Property(property: "name", type: "string", nullable: true),
new OA\Property(property: "biography", type: "string", nullable: true),
new OA\Property(property: "location", type: "string", nullable: true),
new OA\Property(property: "website", type: "string", nullable: true),
new OA\Property(property: "birth_date", type: "string", nullable: true),
]
)
)]
#[OA\Response(
response: Response::HTTP_CREATED,
description: "Creates a new author",
content: new OA\JsonContent(
ref: new Model(type: AuthorDto::class)
)
)]
#[OA\Response(
response: Response::HTTP_BAD_REQUEST,
description: "When the data submitted is not valid",
content: new OA\JsonContent(
properties: [
new OA\Property(property: "type", type: "string"),
new OA\Property(property: "title", type: "string"),
new OA\Property(property: "detail", type: "string"),
new OA\Property(
property: "violations",
type: "array",
items: new OA\Items(
properties: [
new OA\Property(property: "propertyPath", type: "string"),
new OA\Property(property: "title", type: "string"),
new OA\Property(
property: "parameters",
properties: [
new OA\Property(property: "{{ field }}", type: "string", nullable: true),
new OA\Property(property: "{{ value }}", type: "string", nullable: true),
],
type: "object"
),
new OA\Property(property: "type", type: "string")
]
)
),
]
)
)]
#[OA\Response(
response: Response::HTTP_CONFLICT,
description: "When the author is already registered with the given username"
)]
public function __invoke(Request $request): Response
{
$constraint = new Assert\Collection([
'username' => [new Assert\NotBlank()],
'email' => [new Assert\NotBlank(), new Assert\Email()],
'name' => new Assert\Optional(),
'biography' => new Assert\Optional(),
'location' => new Assert\Optional(),
'website' => new Assert\Optional(new Assert\Url()),
'birth_date' => new Assert\Optional(new Assert\DateTime(format: "Y-m-d"))
]);
$data = json_decode($request->getContent(), true);
$violations = $this->validator->validate($data, $constraint);
if (count($violations) > 0) {
return $this->json($violations, Response::HTTP_BAD_REQUEST);
}
try {
$author = $this->authorApplicationService->signUp(
Uuid::uuid4()->toString(),
$data['username'],
$data['email'],
$data['name'],
$data['biography'],
$data['location'],
$data['website'],
$data['birth_date']
);
} catch (AuthorAlreadyExists) {
throw new HttpException(statusCode: Response::HTTP_CONFLICT);
}
return $this->json(
data: AuthorDto::assembleFrom($author),
status: Response::HTTP_CREATED
);
}
}