PostListController   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 101
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 9
dl 0
loc 101
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 15 1
A get() 0 17 2
A search() 0 23 3
A isXmlHttpRequest() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Explicit Architecture POC,
7
 * which is created on top of the Symfony Demo application.
8
 *
9
 * (c) Herberto Graça <[email protected]>
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace Acme\App\Presentation\Web\Core\Component\Blog\Anonymous\PostList;
16
17
use Acme\App\Core\Component\Blog\Application\Query\FindLatestPostsQueryInterface;
18
use Acme\App\Core\Component\Blog\Application\Query\FindPostsBySearchRequestQueryInterface;
19
use Acme\App\Core\Port\Router\UrlGeneratorInterface;
20
use Acme\App\Core\Port\TemplateEngine\TemplateEngineInterface;
21
use Acme\App\Presentation\Web\Core\Port\Paginator\PaginatorFactoryInterface;
22
use Acme\App\Presentation\Web\Core\Port\Response\ResponseFactoryInterface;
23
use Psr\Http\Message\ResponseInterface;
24
use Psr\Http\Message\ServerRequestInterface;
25
26
/**
27
 * @author Ryan Weaver <[email protected]>
28
 * @author Javier Eguiluz <[email protected]>
29
 * @author Herberto Graca <[email protected]>
30
 */
31
class PostListController
32
{
33
    /**
34
     * @var PaginatorFactoryInterface
35
     */
36
    private $paginatorFactory;
37
38
    /**
39
     * @var UrlGeneratorInterface
40
     */
41
    private $urlGenerator;
42
43
    /**
44
     * @var TemplateEngineInterface
45
     */
46
    private $templateEngine;
47
48
    /**
49
     * @var ResponseFactoryInterface
50
     */
51
    private $responseFactory;
52
53
    /**
54
     * @var FindPostsBySearchRequestQueryInterface
55
     */
56
    private $findPostsBySearchRequestQuery;
57
58
    /**
59
     * @var FindLatestPostsQueryInterface
60
     */
61
    private $findLatestPostsQuery;
62
63
    public function __construct(
64
        PaginatorFactoryInterface $paginatorFactory,
65
        UrlGeneratorInterface $urlGenerator,
66
        TemplateEngineInterface $templateEngine,
67
        ResponseFactoryInterface $responseFactory,
68
        FindPostsBySearchRequestQueryInterface $findPostsBySearchRequestQuery,
69
        FindLatestPostsQueryInterface $findLatestPostsQuery
70
    ) {
71
        $this->paginatorFactory = $paginatorFactory;
72
        $this->urlGenerator = $urlGenerator;
73
        $this->templateEngine = $templateEngine;
74
        $this->responseFactory = $responseFactory;
75
        $this->findPostsBySearchRequestQuery = $findPostsBySearchRequestQuery;
76
        $this->findLatestPostsQuery = $findLatestPostsQuery;
77
    }
78
79
    /**
80
     * NOTE: For standard formats, Symfony will also automatically choose the best
81
     * Content-Type header for the response.
82
     *
83
     * @see https://symfony.com/doc/current/quick_tour/the_controller.html#using-formats
84
     */
85
    public function get(int $page, string $_format): ResponseInterface
86
    {
87
        $latestPosts = $this->findLatestPostsQuery->execute();
88
89
        // Every template name also has two extensions that specify the format and
90
        // engine for that template.
91
        // See https://symfony.com/doc/current/templating.html#template-suffix
92
93
        $response = $this->templateEngine->renderResponse(
94
            '@Blog/Anonymous/PostList/get.' . $_format . '.twig',
95
            $_format === 'xml'
96
                ? GetXmlViewModel::fromPostDtoList($this->paginatorFactory, $page, ...$latestPosts)
97
                : GetHtmlViewModel::fromPostDtoList($this->paginatorFactory, $page, ...$latestPosts)
98
        );
99
100
        return $response->withAddedHeader('Cache-Control', 's-maxage=10');
101
    }
102
103
    public function search(ServerRequestInterface $request): ResponseInterface
104
    {
105
        if (!$this->isXmlHttpRequest($request)) {
106
            return $this->templateEngine->renderResponse('@Blog/Anonymous/PostList/search.html.twig');
107
        }
108
109
        $query = $request->getQueryParams()['q'] ?? '';
110
        $limit = $request->getQueryParams()['l'] ?? 10;
111
        $foundPosts = $this->findPostsBySearchRequestQuery->execute($query, (int) $limit);
112
113
        $results = [];
114
        foreach ($foundPosts as $post) {
115
            $results[] = [
116
                'title' => htmlspecialchars($post->getTitle()),
117
                'date' => $post->getPublishedAt()->format('M d, Y'),
118
                'author' => htmlspecialchars($post->getFullName()),
119
                'summary' => htmlspecialchars($post->getSummary()),
120
                'url' => $this->urlGenerator->generateUrl('post', ['slug' => $post->getSlug()]),
121
            ];
122
        }
123
124
        return $this->responseFactory->respondJson($results);
125
    }
126
127
    private function isXmlHttpRequest(ServerRequestInterface $request): bool
128
    {
129
        return ($request->getHeader('X-Requested-With')[0] ?? '') === 'XMLHttpRequest';
130
    }
131
}
132