]> Raphaël G. Git Repositories - blogbundle/blob - Controller/ArticleController.php
Use entity id as last resort sorting parameter
[blogbundle] / Controller / ArticleController.php
1 <?php declare(strict_types=1);
2
3 /*
4 * This file is part of the Rapsys BlogBundle package.
5 *
6 * (c) Raphaël Gertz <symfony@rapsys.eu>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Rapsys\BlogBundle\Controller;
13
14 use Symfony\Component\HttpFoundation\Request;
15 use Symfony\Component\HttpFoundation\Response;
16
17 use Rapsys\BlogBundle\Entity\Article;
18 use Rapsys\BlogBundle\Entity\Keyword;
19
20 /**
21 * {@inheritdoc}
22 */
23 class ArticleController extends AbstractController {
24 /**
25 * The article index
26 *
27 * Display articles
28 *
29 * @param Request $request The request instance
30 * @return Response The rendered view
31 */
32 public function index(Request $request): Response {
33 //With not enough articles
34 if (($this->count = $this->doctrine->getRepository(Article::class)->findCountAsInt()) < $this->page * $this->limit) {
35 //Throw 404
36 throw $this->createNotFoundException($this->translator->trans('Unable to find articles'));
37 }
38
39 //Get articles
40 if ($this->context['articles'] = $this->doctrine->getRepository(Article::class)->findAllAsArray($this->page, $this->limit)) {
41 //Set modified
42 $this->modified = max(array_map(function ($v) { return $v['modified']; }, $this->context['articles']));
43 //Without keywords
44 } else {
45 //Set empty modified
46 $this->modified = new \DateTime('-1 year');
47 }
48
49 //Create response
50 $response = new Response();
51
52 //With logged user
53 if ($this->checker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
54 //Set last modified
55 $response->setLastModified(new \DateTime('-1 year'));
56
57 //Set as private
58 $response->setPrivate();
59 //Without logged user
60 } else {
61 //Set etag
62 //XXX: only for public to force revalidation by last modified
63 $response->setEtag(md5(serialize($this->context['articles'])));
64
65 //Set last modified
66 $response->setLastModified($this->modified);
67
68 //Set as public
69 $response->setPublic();
70
71 //Without role and modification
72 if ($response->isNotModified($request)) {
73 //Return 304 response
74 return $response;
75 }
76 }
77
78 //Set keywords
79 $this->context['head']['keywords'] = implode(
80 ', ',
81 //Use closure to extract each unique article keywords sorted
82 (function ($t) {
83 //Return array
84 $r = [];
85
86 //Iterate on articles
87 foreach($t as $a) {
88 //Non empty keywords
89 if (!empty($a['keywords'])) {
90 //Iterate on keywords
91 foreach($a['keywords'] as $k) {
92 //Set keyword
93 $r[$k['title']] = $k['title'];
94 }
95 }
96 }
97
98 //Sort array
99 sort($r);
100
101 //Return array
102 return $r;
103 })($this->context['articles'])
104 );
105
106 //Set title
107 $this->context['title'] = $this->translator->trans('Articles list');
108
109 //Set description
110 $this->context['description'] = $this->translator->trans('Welcome to raphaël\'s developer diary article listing');
111
112 //Render the view
113 return $this->render('@RapsysBlog/article/index.html.twig', $this->context, $response);
114 }
115
116 /**
117 * The article view
118 *
119 * Display article and keywords
120 *
121 * @param Request $request The request instance
122 * @param integer $id The article id
123 * @param ?string $slug The article slug
124 * @return Response The rendered view
125 */
126 public function view(Request $request, int $id, ?string $slug): Response {
127 //Without article
128 if (empty($this->context['article'] = $this->doctrine->getRepository(Article::class)->findByIdAsArray($id))) {
129 //Throw 404
130 throw $this->createNotFoundException($this->translator->trans('Unable to find article: %id%', ['%id%' => $id]));
131 }
132
133 //With invalid slug
134 if ($slug !== $this->context['article']['slug']) {
135 //Redirect on correctly spelled article
136 return $this->redirectToRoute('rapsys_blog_article_view', ['id' => $this->context['article']['id'], 'slug' => $this->context['article']['slug']], Response::HTTP_MOVED_PERMANENTLY);
137 }
138
139 //Set modified
140 $this->modified = $this->context['article']['modified'];
141
142 //Create response
143 $response = new Response();
144
145 //With logged user
146 if ($this->checker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
147 //Set last modified
148 $response->setLastModified(new \DateTime('-1 year'));
149
150 //Set as private
151 $response->setPrivate();
152 //Without logged user
153 } else {
154 //Set etag
155 //XXX: only for public to force revalidation by last modified
156 $response->setEtag(md5(serialize($this->context['article'])));
157
158 //Set last modified
159 $response->setLastModified($this->modified);
160
161 //Set as public
162 $response->setPublic();
163
164 //Without role and modification
165 if ($response->isNotModified($request)) {
166 //Return 304 response
167 return $response;
168 }
169 }
170
171 //Set keywords
172 $this->context['head']['keywords'] = implode(
173 ', ',
174 //Use closure to extract each unique article keywords sorted
175 (function ($a) {
176 //Return array
177 $r = [];
178
179 //Non empty keywords
180 if (!empty($a['keywords'])) {
181 //Iterate on keywords
182 foreach($a['keywords'] as $k) {
183 //Set keyword
184 $r[$k['title']] = $k['title'];
185 }
186 }
187
188 //Sort array
189 sort($r);
190
191 //Return array
192 return $r;
193 })($this->context['article'])
194 );
195
196 //Set title
197 $this->context['title'] = $this->context['article']['title'];
198
199 //Set description
200 $this->context['description'] = $this->context['article']['description'];
201
202 //Render the view
203 return $this->render('@RapsysBlog/article/view.html.twig', $this->context, $response);
204 }
205 }