From 35e12d2f786b3d845165b03405951016481f816b Mon Sep 17 00:00:00 2001 From: Joris Langlois Date: Mon, 13 Jul 2020 17:47:30 +0200 Subject: [PATCH 1/2] add a publish endpoint --- config/routes.yaml | 7 +++ config/services/bus.yaml | 1 + config/services/command_handlers.yaml | 5 +- .../Controller/ArticleController.php | 53 ++++++++++++++---- src/Application/Controller/Endpoint.php | 2 + src/Domain/Command/EditArticle.php | 55 +++++++++++++++++++ src/Domain/Command/Handler/EditArticle.php | 35 ++++++++++++ src/Domain/Command/Handler/PublishArticle.php | 17 +----- src/Domain/Command/Handler/ReadArticle.php | 21 ++++++- src/Domain/Command/PublishArticle.php | 14 +++-- src/Domain/Command/ReadArticle.php | 16 ++++-- src/Domain/Model/Article.php | 8 +++ 12 files changed, 194 insertions(+), 40 deletions(-) create mode 100644 src/Domain/Command/EditArticle.php create mode 100644 src/Domain/Command/Handler/EditArticle.php diff --git a/config/routes.yaml b/config/routes.yaml index cb3cdc8..b497256 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -15,6 +15,13 @@ create_article: methods: [POST] controller: App\Application\Controller\ArticleController::create +edit_article: + path: /articles/{id} + methods: [PATCH] + controller: App\Application\Controller\ArticleController::update + requirements: + id: '[\d]+' + publish_article: path: /articles/{id}/publish methods: [PATCH] diff --git a/config/services/bus.yaml b/config/services/bus.yaml index f6408e2..7319027 100644 --- a/config/services/bus.yaml +++ b/config/services/bus.yaml @@ -6,3 +6,4 @@ services: - '@App\Domain\Command\Handler\ListArticles' - '@App\Domain\Command\Handler\WriteArticle' - '@App\Domain\Command\Handler\PublishArticle' + - '@App\Domain\Command\Handler\EditArticle' diff --git a/config/services/command_handlers.yaml b/config/services/command_handlers.yaml index 81e8308..cc0afd2 100644 --- a/config/services/command_handlers.yaml +++ b/config/services/command_handlers.yaml @@ -18,4 +18,7 @@ services: App\Domain\Command\Handler\PublishArticle: arguments: - '@Doctrine\ORM\EntityManagerInterface' - - '@App\Application\Repository\ArticleRepository' + + App\Domain\Command\Handler\EditArticle: + arguments: + - '@Doctrine\ORM\EntityManagerInterface' diff --git a/src/Application/Controller/ArticleController.php b/src/Application/Controller/ArticleController.php index 7c348ac..69b49f1 100644 --- a/src/Application/Controller/ArticleController.php +++ b/src/Application/Controller/ArticleController.php @@ -6,6 +6,7 @@ use App\Application\JsonDefinition\Article as ArticleDefinition; use App\Domain\Command as Command; use App\Domain\Command\Bus\CommandBus; +use App\Domain\Exception\ResourceNotFoundException; use Exception; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\JsonResponse; @@ -32,7 +33,6 @@ public function __construct( $this->formFactory = $formFactory; } - // @todo add swager doc here public function list(): JsonResponse { try { @@ -57,12 +57,14 @@ public function list(): JsonResponse return new JsonResponse($definitions); } - // @todo add swager doc here public function read(string $slug): JsonResponse { try { $article = $this->bus->executeCommand(new Command\ReadArticle($slug)); } + catch (ResourceNotFoundException $exception) { + return new JsonResponse(null, Response::HTTP_NOT_FOUND); + } catch (Exception $exception) { return new JsonResponse( ["error" => $exception->getMessage()], @@ -70,14 +72,9 @@ public function read(string $slug): JsonResponse ); } - if (null === $article) { - return new JsonResponse(null, Response::HTTP_NOT_FOUND); - } - return new JsonResponse(new ArticleDefinition($article)); } - // @todo add swager doc here public function create(Request $request): JsonResponse { $createArticle = new Command\WriteArticle(); @@ -87,7 +84,6 @@ public function create(Request $request): JsonResponse if (!$form->isSubmitted() || !$form->isValid()) { return new JsonResponse( - // @TODO improve this to have clearer error output $form->getErrors(true)->__toString(), Response::HTTP_BAD_REQUEST ); @@ -108,11 +104,48 @@ public function create(Request $request): JsonResponse ); } - // @todo add swager doc here + public function update(Request $request, int $id): JsonResponse + { + try { + $article = $this->bus->executeCommand(new Command\ReadArticle($id)); + $editArticle = new Command\EditArticle($article); + + $form = $this->formFactory->create(ArticleType::class, $editArticle); + $form->submit($request->request->all(), false); + + if (!$form->isSubmitted() || !$form->isValid()) { + return new JsonResponse( + $form->getErrors(true)->__toString(), + Response::HTTP_BAD_REQUEST + ); + } + + $editedArticle = $this->bus->executeCommand($editArticle); + } + catch (ResourceNotFoundException $exception) { + return new JsonResponse(null, Response::HTTP_NOT_FOUND); + } + catch (Exception $exception) { + return new JsonResponse( + ["error" => $exception->getMessage()], + Response::HTTP_INTERNAL_SERVER_ERROR + ); + } + + return new JsonResponse( + new ArticleDefinition($editedArticle), + Response::HTTP_CREATED + ); + } + public function publish(int $id): JsonResponse { try { - $article = $this->bus->executeCommand(new Command\PublishArticle($id)); + $article = $this->bus->executeCommand(new Command\ReadArticle($id)); + $this->bus->executeCommand(new Command\PublishArticle($article)); + } + catch (ResourceNotFoundException $exception) { + return new JsonResponse(null, Response::HTTP_NOT_FOUND); } catch (Exception $exception) { return new JsonResponse( diff --git a/src/Application/Controller/Endpoint.php b/src/Application/Controller/Endpoint.php index adcdbde..587089d 100644 --- a/src/Application/Controller/Endpoint.php +++ b/src/Application/Controller/Endpoint.php @@ -12,4 +12,6 @@ public function list(): JsonResponse; public function read(string $slug): JsonResponse; public function create(Request $request): JsonResponse; + + public function update(Request $request, int $id): JsonResponse; } diff --git a/src/Domain/Command/EditArticle.php b/src/Domain/Command/EditArticle.php new file mode 100644 index 0000000..42fd50f --- /dev/null +++ b/src/Domain/Command/EditArticle.php @@ -0,0 +1,55 @@ +article = $article; + $this->title = $article->getTitle(); + $this->content = $article->getContent(); + } + + public function getArticle(): Article + { + return $this->article; + } + + public function getTitle(): string + { + return $this->title; + } + + public function setTitle(string $title) + { + $this->title = $title; + } + + public function getContent(): string + { + return $this->content; + } + + public function setContent(string $content) + { + $this->content = $content; + } +} diff --git a/src/Domain/Command/Handler/EditArticle.php b/src/Domain/Command/Handler/EditArticle.php new file mode 100644 index 0000000..709e5e1 --- /dev/null +++ b/src/Domain/Command/Handler/EditArticle.php @@ -0,0 +1,35 @@ +manager = $manager; + } + + public function __invoke(EditArticleCommand $command): Article + { + $article = $command->getArticle(); + $article->edit( + $command->getTitle(), + $command->getContent() + ); + + $this->manager->persist($article); + $this->manager->flush(); + + return $article; + } +} diff --git a/src/Domain/Command/Handler/PublishArticle.php b/src/Domain/Command/Handler/PublishArticle.php index b389819..9f015f0 100644 --- a/src/Domain/Command/Handler/PublishArticle.php +++ b/src/Domain/Command/Handler/PublishArticle.php @@ -5,7 +5,6 @@ use App\Domain\Model\Article; use App\Domain\Command\PublishArticle as PublishArticleCommand; use App\Domain\Exception\ResourceNotFoundException; -use App\Domain\Repository\ArticleRepository; use Doctrine\Common\Persistence\ObjectManager; class PublishArticle @@ -15,17 +14,10 @@ class PublishArticle */ private $manager; - /** - * @var ArticleRepository - */ - private $repository; - public function __construct( - ObjectManager $manager, - ArticleRepository $repository + ObjectManager $manager ) { $this->manager = $manager; - $this->repository = $repository; } /** @@ -33,12 +25,7 @@ public function __construct( */ public function __invoke(PublishArticleCommand $command): Article { - $article = $this->repository->find($command->getId()); - - if (null === $article) { - throw new ResourceNotFoundException(); - } - + $article = $command->getArticle(); $article->publish(); $this->manager->persist($article); diff --git a/src/Domain/Command/Handler/ReadArticle.php b/src/Domain/Command/Handler/ReadArticle.php index 9a89e82..e399eba 100644 --- a/src/Domain/Command/Handler/ReadArticle.php +++ b/src/Domain/Command/Handler/ReadArticle.php @@ -2,8 +2,9 @@ namespace App\Domain\Command\Handler; -use App\Domain\Model\Article; use App\Domain\Command\ReadArticle as ReadArticleCommand; +use App\Domain\Exception\ResourceNotFoundException; +use App\Domain\Model\Article; use App\Domain\Repository\ArticleRepository; class ReadArticle @@ -18,8 +19,22 @@ public function __construct(ArticleRepository $repository) $this->repository = $repository; } - public function __invoke(ReadArticleCommand $command): ?Article + /** + * @throws ResourceNotFoundException + */ + public function __invoke(ReadArticleCommand $command): Article { - return $this->repository->findOneBySlug($command->getSlug()); + $id = $command->getId(); + + $article = is_numeric($id) + ? $this->repository->findOneById($id) + : $this->repository->findOneBySlug($id) + ; + + if ($article === null) { + throw new ResourceNotFoundException(); + } + + return $article; } } diff --git a/src/Domain/Command/PublishArticle.php b/src/Domain/Command/PublishArticle.php index 8d9c782..d67d32d 100644 --- a/src/Domain/Command/PublishArticle.php +++ b/src/Domain/Command/PublishArticle.php @@ -2,20 +2,22 @@ namespace App\Domain\Command; +use App\Domain\Model\Article; + class PublishArticle { /** - * @var int + * @var Article */ - private $id; + private $article; - public function __construct(int $id) + public function __construct(Article $article) { - $this->id = $id; + $this->article = $article; } - public function getId(): int + public function getArticle(): Article { - return $this->id; + return $this->article; } } diff --git a/src/Domain/Command/ReadArticle.php b/src/Domain/Command/ReadArticle.php index ee69c92..d47c82a 100644 --- a/src/Domain/Command/ReadArticle.php +++ b/src/Domain/Command/ReadArticle.php @@ -5,17 +5,23 @@ class ReadArticle { /** - * @var string + * @var int|string */ private $slug; - public function __construct(string $slug) + /** + * @param int|string + */ + public function __construct($id) { - $this->slug = $slug; + $this->id = $id; } - public function getSlug(): string + /** + * @return int|string + */ + public function getId() { - return $this->slug; + return $this->id; } } diff --git a/src/Domain/Model/Article.php b/src/Domain/Model/Article.php index 06c6904..ca246ed 100644 --- a/src/Domain/Model/Article.php +++ b/src/Domain/Model/Article.php @@ -51,6 +51,14 @@ public static function write(string $title, string $content, string $slug): self return new self($title, $content, $slug); } + public function edit(string $title, string $content): self + { + $this->title = $title; + $this->content = $content; + + return $this; + } + public function publish(): self { $this->draft = false; From e78715da2fd23c962417ec30c9c3642b4aa9fede Mon Sep 17 00:00:00 2001 From: Joris Langlois Date: Thu, 16 Jul 2020 10:56:32 +0200 Subject: [PATCH 2/2] fixed the way entities are fetched --- config/services/command_handlers.yaml | 2 ++ .../Controller/ArticleController.php | 4 ++-- src/Domain/Command/EditArticle.php | 10 ++++---- src/Domain/Command/Handler/EditArticle.php | 23 ++++++++++++++++--- src/Domain/Command/Handler/PublishArticle.php | 19 ++++++++++++--- src/Domain/Command/PublishArticle.php | 14 +++++------ 6 files changed, 51 insertions(+), 21 deletions(-) diff --git a/config/services/command_handlers.yaml b/config/services/command_handlers.yaml index cc0afd2..df32674 100644 --- a/config/services/command_handlers.yaml +++ b/config/services/command_handlers.yaml @@ -18,7 +18,9 @@ services: App\Domain\Command\Handler\PublishArticle: arguments: - '@Doctrine\ORM\EntityManagerInterface' + - '@App\Application\Repository\ArticleRepository' App\Domain\Command\Handler\EditArticle: arguments: - '@Doctrine\ORM\EntityManagerInterface' + - '@App\Application\Repository\ArticleRepository' diff --git a/src/Application/Controller/ArticleController.php b/src/Application/Controller/ArticleController.php index 69b49f1..48466e0 100644 --- a/src/Application/Controller/ArticleController.php +++ b/src/Application/Controller/ArticleController.php @@ -141,8 +141,8 @@ public function update(Request $request, int $id): JsonResponse public function publish(int $id): JsonResponse { try { - $article = $this->bus->executeCommand(new Command\ReadArticle($id)); - $this->bus->executeCommand(new Command\PublishArticle($article)); + $publishArticle = new Command\PublishArticle($id); + $article = $this->bus->executeCommand($publishArticle); } catch (ResourceNotFoundException $exception) { return new JsonResponse(null, Response::HTTP_NOT_FOUND); diff --git a/src/Domain/Command/EditArticle.php b/src/Domain/Command/EditArticle.php index 42fd50f..ac3c924 100644 --- a/src/Domain/Command/EditArticle.php +++ b/src/Domain/Command/EditArticle.php @@ -7,9 +7,9 @@ class EditArticle { /** - * @var Article + * @var int */ - private $article; + private $id; /** * @var string @@ -23,14 +23,14 @@ class EditArticle public function __construct(Article $article) { - $this->article = $article; + $this->id = $article->getId(); $this->title = $article->getTitle(); $this->content = $article->getContent(); } - public function getArticle(): Article + public function getId(): int { - return $this->article; + return $this->id; } public function getTitle(): string diff --git a/src/Domain/Command/Handler/EditArticle.php b/src/Domain/Command/Handler/EditArticle.php index 709e5e1..16db557 100644 --- a/src/Domain/Command/Handler/EditArticle.php +++ b/src/Domain/Command/Handler/EditArticle.php @@ -2,8 +2,10 @@ namespace App\Domain\Command\Handler; -use App\Domain\Model\Article; use App\Domain\Command\EditArticle as EditArticleCommand; +use App\Domain\Exception\ResourceNotFoundException; +use App\Domain\Model\Article; +use App\Domain\Repository\ArticleRepository; use Doctrine\Common\Persistence\ObjectManager; class EditArticle @@ -13,15 +15,30 @@ class EditArticle */ private $manager; + /** + * @var ArticleRepository + */ + private $repository; + public function __construct( - ObjectManager $manager + ObjectManager $manager, + ArticleRepository $repository ) { $this->manager = $manager; + $this->repository = $repository; } + /** + * @throws ResourceNotFoundException + */ public function __invoke(EditArticleCommand $command): Article { - $article = $command->getArticle(); + $article = $this->repository->findOneById($command->getId()); + + if ($article === null) { + throw new ResourceNotFoundException(); + } + $article->edit( $command->getTitle(), $command->getContent() diff --git a/src/Domain/Command/Handler/PublishArticle.php b/src/Domain/Command/Handler/PublishArticle.php index 9f015f0..431c935 100644 --- a/src/Domain/Command/Handler/PublishArticle.php +++ b/src/Domain/Command/Handler/PublishArticle.php @@ -2,9 +2,10 @@ namespace App\Domain\Command\Handler; -use App\Domain\Model\Article; use App\Domain\Command\PublishArticle as PublishArticleCommand; use App\Domain\Exception\ResourceNotFoundException; +use App\Domain\Model\Article; +use App\Domain\Repository\ArticleRepository; use Doctrine\Common\Persistence\ObjectManager; class PublishArticle @@ -14,10 +15,17 @@ class PublishArticle */ private $manager; + /** + * @var ArticleRepository + */ + private $repository; + public function __construct( - ObjectManager $manager + ObjectManager $manager, + ArticleRepository $repository ) { $this->manager = $manager; + $this->repository = $repository; } /** @@ -25,7 +33,12 @@ public function __construct( */ public function __invoke(PublishArticleCommand $command): Article { - $article = $command->getArticle(); + $article = $this->repository->findOneById($command->getId()); + + if ($article === null) { + throw new ResourceNotFoundException(); + } + $article->publish(); $this->manager->persist($article); diff --git a/src/Domain/Command/PublishArticle.php b/src/Domain/Command/PublishArticle.php index d67d32d..8d9c782 100644 --- a/src/Domain/Command/PublishArticle.php +++ b/src/Domain/Command/PublishArticle.php @@ -2,22 +2,20 @@ namespace App\Domain\Command; -use App\Domain\Model\Article; - class PublishArticle { /** - * @var Article + * @var int */ - private $article; + private $id; - public function __construct(Article $article) + public function __construct(int $id) { - $this->article = $article; + $this->id = $id; } - public function getArticle(): Article + public function getId(): int { - return $this->article; + return $this->id; } }