From 5572ebe561a7ea21465c38f6c2ea0fa882a8082d Mon Sep 17 00:00:00 2001 From: OStefan2001 Date: Thu, 13 Aug 2026 11:32:18 +0300 Subject: [PATCH 1/3] 404 page with authors and fixture updated with git account for Gabi DJ --- src/App/src/Fixture/articles_cleaned.json | 44 +++++++++---------- src/App/templates/error/404.html.twig | 11 +++++ .../src/Handler/GetAuthorResourceHandler.php | 19 +++++++- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/App/src/Fixture/articles_cleaned.json b/src/App/src/Fixture/articles_cleaned.json index 7529fd29..f4cffb16 100644 --- a/src/App/src/Fixture/articles_cleaned.json +++ b/src/App/src/Fixture/articles_cleaned.json @@ -527,7 +527,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -541,7 +541,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -555,7 +555,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -569,7 +569,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -583,7 +583,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -597,7 +597,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": true, "opengraph_img": null, @@ -611,7 +611,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": true, "opengraph_img": null, @@ -625,7 +625,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -639,7 +639,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -653,7 +653,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -681,7 +681,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": true, "opengraph_img": null, @@ -709,7 +709,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -723,7 +723,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -762,7 +762,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -1461,7 +1461,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -1500,7 +1500,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -1624,7 +1624,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -1695,7 +1695,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -1882,7 +1882,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -1925,7 +1925,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -1983,7 +1983,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, @@ -2014,7 +2014,7 @@ "post_status": "publish", "author": { "display_name": "Gabi DJ", - "github": "" + "github": "gabidj/gabidj" }, "isObsolete": false, "opengraph_img": null, diff --git a/src/App/templates/error/404.html.twig b/src/App/templates/error/404.html.twig index ac2eccd7..ba1b0ca4 100644 --- a/src/App/templates/error/404.html.twig +++ b/src/App/templates/error/404.html.twig @@ -28,6 +28,17 @@ {% endfor %} {% endif %} + + {% if authors is defined and authors|length > 0 %} +
+ {% for author in authors %} + + {{ author.name }} + + {% endfor %} +
+ {% endif %} {% endblock %} diff --git a/src/Blog/src/Handler/GetAuthorResourceHandler.php b/src/Blog/src/Handler/GetAuthorResourceHandler.php index 374dde14..24e1cded 100644 --- a/src/Blog/src/Handler/GetAuthorResourceHandler.php +++ b/src/Blog/src/Handler/GetAuthorResourceHandler.php @@ -4,8 +4,10 @@ namespace Light\Blog\Handler; +use Fig\Http\Message\StatusCodeInterface; use Laminas\Diactoros\Response\HtmlResponse; use Light\App\Helper\Paginator; +use Light\Blog\Entity\Author; use Light\Blog\Repository\AuthorRepository; use Light\Blog\Repository\CategoryRepository; use Light\Blog\Repository\PostRepository; @@ -28,10 +30,10 @@ public function handle(ServerRequestInterface $request): ResponseInterface { $authorSlug = $request->getAttribute('slug'); $author = $this->authorRepository->getAuthorResource($authorSlug); - $categories = $this->categoryRepository->getCategories(); if (! $author) { - return new HtmlResponse('Author not found', 404); + return $this->notFound($this->authorRepository->getAuthorsWithPublishedPosts()); } + $categories = $this->categoryRepository->getCategories(); $queryParams = $request->getQueryParams(); $params = Paginator::getParams($queryParams, 'posts.postDate'); @@ -49,4 +51,17 @@ public function handle(ServerRequestInterface $request): ResponseInterface ]) ); } + + /** + * @param Author[] $authors + */ + private function notFound(array $authors): HtmlResponse + { + return new HtmlResponse( + $this->template->render('error::404', [ + 'authors' => $authors, + ]), + StatusCodeInterface::STATUS_NOT_FOUND + ); + } } From b3505d9f08403d72b49908901df8e98b1d384c93 Mon Sep 17 00:00:00 2001 From: OStefan2001 Date: Thu, 13 Aug 2026 11:52:40 +0300 Subject: [PATCH 2/3] test added --- .../Handler/GetAuthorResourceHandlerTest.php | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 test/Unit/Blog/Handler/GetAuthorResourceHandlerTest.php diff --git a/test/Unit/Blog/Handler/GetAuthorResourceHandlerTest.php b/test/Unit/Blog/Handler/GetAuthorResourceHandlerTest.php new file mode 100644 index 00000000..f294f1b1 --- /dev/null +++ b/test/Unit/Blog/Handler/GetAuthorResourceHandlerTest.php @@ -0,0 +1,98 @@ +createStub(Author::class); + $categories = [$this->createStub(Category::class)]; + + $query = $this->createStub(Query::class); + $query->method('getResult')->willReturn([]); + + $paginator = $this->createStub(DoctrinePaginator::class); + $paginator->method('count')->willReturn(0); + $paginator->method('getQuery')->willReturn($query); + + $authorRepository = $this->createMock(AuthorRepository::class); + $authorRepository->expects($this->once())->method('getAuthorResource')->willReturn($author); + $authorRepository->expects($this->never())->method('getAuthorsWithPublishedPosts'); + + $categoryRepository = $this->createMock(CategoryRepository::class); + $categoryRepository->expects($this->once())->method('getCategories')->willReturn($categories); + + $postRepository = $this->createMock(PostRepository::class); + $postRepository->expects($this->exactly(2))->method('getArticleByAuthor')->willReturn($paginator); + + $template = $this->createMock(TemplateRendererInterface::class); + $template->expects($this->once())->method('render') + ->willReturnCallback(function (string $name, mixed $parameters = []) use ($author, $categories): string { + $this->assertSame('page::author-resource', $name); + $this->assertIsArray($parameters); + $this->assertSame($author, $parameters['author']); + $this->assertSame($categories, $parameters['categories']); + + return ''; + }); + + $handler = new GetAuthorResourceHandler($template, $authorRepository, $postRepository, $categoryRepository); + $response = $handler->handle((new ServerRequest())->withAttribute('slug', 'gabi')); + + $this->assertSame(200, $response->getStatusCode()); + $this->assertSame('', (string) $response->getBody()); + } + + /** + * @throws Exception + */ + public function testHandleReturnsNotFoundWhenAuthorDoesNotExist(): void + { + $authors = [$this->createStub(Author::class)]; + + $authorRepository = $this->createMock(AuthorRepository::class); + $authorRepository->expects($this->once())->method('getAuthorResource')->willReturn(null); + $authorRepository->expects($this->once())->method('getAuthorsWithPublishedPosts')->willReturn($authors); + + $categoryRepository = $this->createMock(CategoryRepository::class); + $categoryRepository->expects($this->never())->method('getCategories'); + + $postRepository = $this->createMock(PostRepository::class); + $postRepository->expects($this->never())->method('getArticleByAuthor'); + + $template = $this->createMock(TemplateRendererInterface::class); + $template->expects($this->once())->method('render') + ->willReturnCallback(function (string $name, mixed $parameters = []) use ($authors): string { + $this->assertSame('error::404', $name); + $this->assertIsArray($parameters); + $this->assertSame($authors, $parameters['authors']); + + return ''; + }); + + $handler = new GetAuthorResourceHandler($template, $authorRepository, $postRepository, $categoryRepository); + $response = $handler->handle((new ServerRequest())->withAttribute('slug', 'adminxx')); + + $this->assertSame(404, $response->getStatusCode()); + $this->assertSame('', (string) $response->getBody()); + } +} From 3562379147ee67509aba069b155a1391e1812ea3 Mon Sep 17 00:00:00 2001 From: OStefan2001 Date: Thu, 13 Aug 2026 13:05:16 +0300 Subject: [PATCH 3/3] add git accounts --- src/App/src/Fixture/articles_cleaned.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/App/src/Fixture/articles_cleaned.json b/src/App/src/Fixture/articles_cleaned.json index f4cffb16..0a228ce5 100644 --- a/src/App/src/Fixture/articles_cleaned.json +++ b/src/App/src/Fixture/articles_cleaned.json @@ -883,7 +883,7 @@ "post_status": "publish", "author": { "display_name": "SergiuB", - "github": "" + "github": "kakapiciu" }, "isObsolete": false, "opengraph_img": null, @@ -2056,7 +2056,7 @@ "post_status": "publish", "author": { "display_name": "kakapiciu", - "github": "sergiu@rospace.com" + "github": "kakapiciu" }, "isObsolete": false, "opengraph_img": null, @@ -2070,7 +2070,7 @@ "post_status": "publish", "author": { "display_name": "kakapiciu", - "github": "sergiu@rospace.com" + "github": "kakapiciu" }, "isObsolete": false, "opengraph_img": null, @@ -2434,7 +2434,7 @@ "post_status": "publish", "author": { "display_name": "n3vrax", - "github": "" + "github": "n3vrax" }, "isObsolete": false, "opengraph_img": null, @@ -2448,7 +2448,7 @@ "post_status": "publish", "author": { "display_name": "n3vrax", - "github": "" + "github": "n3vrax" }, "isObsolete": false, "opengraph_img": null, @@ -2525,7 +2525,7 @@ "post_status": "publish", "author": { "display_name": "kakapiciu", - "github": "sergiu@rospace.com" + "github": "kakapiciu" }, "isObsolete": false, "opengraph_img": null,