]> git.immae.eu Git - github/wallabag/wallabag.git/blob - src/Wallabag/CoreBundle/Controller/EntryController.php
Improve pagination when user has lot of entries
[github/wallabag/wallabag.git] / src / Wallabag / CoreBundle / Controller / EntryController.php
1 <?php
2
3 namespace Wallabag\CoreBundle\Controller;
4
5 use Pagerfanta\Adapter\DoctrineORMAdapter;
6 use Pagerfanta\Pagerfanta;
7 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
8 use Symfony\Bundle\FrameworkBundle\Controller\Controller;
9 use Symfony\Component\HttpFoundation\Request;
10 use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
11 use Wallabag\CoreBundle\Entity\Entry;
12 use Wallabag\CoreBundle\Form\Type\EntryFilterType;
13 use Wallabag\CoreBundle\Form\Type\EditEntryType;
14 use Wallabag\CoreBundle\Form\Type\NewEntryType;
15
16 class EntryController extends Controller
17 {
18 /**
19 * @param Entry $entry
20 */
21 private function updateEntry(Entry $entry)
22 {
23 try {
24 $entry = $this->get('wallabag_core.content_proxy')->updateEntry($entry, $entry->getUrl());
25 $em = $this->getDoctrine()->getManager();
26 $em->persist($entry);
27 $em->flush();
28 } catch (\Exception $e) {
29 return false;
30 }
31
32 return true;
33 }
34
35 /**
36 * @param Request $request
37 *
38 * @Route("/new-entry", name="new_entry")
39 *
40 * @return \Symfony\Component\HttpFoundation\Response
41 */
42 public function addEntryFormAction(Request $request)
43 {
44 $entry = new Entry($this->getUser());
45
46 $form = $this->createForm(NewEntryType::class, $entry);
47
48 $form->handleRequest($request);
49
50 if ($form->isValid()) {
51 $existingEntry = $this->checkIfEntryAlreadyExists($entry);
52
53 if (false !== $existingEntry) {
54 $this->get('session')->getFlashBag()->add(
55 'notice',
56 $this->get('translator')->trans('flashes.entry.notice.entry_already_saved', array('%date%' => $existingEntry->getCreatedAt()->format('d-m-Y')))
57 );
58
59 return $this->redirect($this->generateUrl('view', array('id' => $existingEntry->getId())));
60 }
61
62 $this->updateEntry($entry);
63 $this->get('session')->getFlashBag()->add(
64 'notice',
65 'flashes.entry.notice.entry_saved'
66 );
67
68 return $this->redirect($this->generateUrl('homepage'));
69 }
70
71 return $this->render('WallabagCoreBundle:Entry:new_form.html.twig', array(
72 'form' => $form->createView(),
73 ));
74 }
75
76 /**
77 * @param Request $request
78 *
79 * @Route("/bookmarklet", name="bookmarklet")
80 *
81 * @return \Symfony\Component\HttpFoundation\Response
82 */
83 public function addEntryViaBookmarkletAction(Request $request)
84 {
85 $entry = new Entry($this->getUser());
86 $entry->setUrl($request->get('url'));
87
88 if (false === $this->checkIfEntryAlreadyExists($entry)) {
89 $this->updateEntry($entry);
90 }
91
92 return $this->redirect($this->generateUrl('homepage'));
93 }
94
95 /**
96 * @Route("/new", name="new")
97 *
98 * @return \Symfony\Component\HttpFoundation\Response
99 */
100 public function addEntryAction()
101 {
102 return $this->render('WallabagCoreBundle:Entry:new.html.twig');
103 }
104
105 /**
106 * Edit an entry content.
107 *
108 * @param Request $request
109 * @param Entry $entry
110 *
111 * @Route("/edit/{id}", requirements={"id" = "\d+"}, name="edit")
112 *
113 * @return \Symfony\Component\HttpFoundation\Response
114 */
115 public function editEntryAction(Request $request, Entry $entry)
116 {
117 $this->checkUserAction($entry);
118
119 $form = $this->createForm(EditEntryType::class, $entry);
120
121 $form->handleRequest($request);
122
123 if ($form->isValid()) {
124 $em = $this->getDoctrine()->getManager();
125 $em->persist($entry);
126 $em->flush();
127
128 $this->get('session')->getFlashBag()->add(
129 'notice',
130 'flashes.entry.notice.entry_updated'
131 );
132
133 return $this->redirect($this->generateUrl('view', array('id' => $entry->getId())));
134 }
135
136 return $this->render('WallabagCoreBundle:Entry:edit.html.twig', array(
137 'form' => $form->createView(),
138 ));
139 }
140
141 /**
142 * Shows all entries for current user.
143 *
144 * @param Request $request
145 * @param int $page
146 *
147 * @Route("/all/list/{page}", name="all", defaults={"page" = "1"})
148 *
149 * @return \Symfony\Component\HttpFoundation\Response
150 */
151 public function showAllAction(Request $request, $page)
152 {
153 return $this->showEntries('all', $request, $page);
154 }
155
156 /**
157 * Shows unread entries for current user.
158 *
159 * @param Request $request
160 * @param int $page
161 *
162 * @Route("/unread/list/{page}", name="unread", defaults={"page" = "1"})
163 *
164 * @return \Symfony\Component\HttpFoundation\Response
165 */
166 public function showUnreadAction(Request $request, $page)
167 {
168 // load the quickstart if no entry in database
169 if ($page == 1 && $this->get('wallabag_core.entry_repository')->countAllEntriesByUsername($this->getUser()->getId()) == 0) {
170 return $this->redirect($this->generateUrl('quickstart'));
171 }
172
173 return $this->showEntries('unread', $request, $page);
174 }
175
176 /**
177 * Shows read entries for current user.
178 *
179 * @param Request $request
180 * @param int $page
181 *
182 * @Route("/archive/list/{page}", name="archive", defaults={"page" = "1"})
183 *
184 * @return \Symfony\Component\HttpFoundation\Response
185 */
186 public function showArchiveAction(Request $request, $page)
187 {
188 return $this->showEntries('archive', $request, $page);
189 }
190
191 /**
192 * Shows starred entries for current user.
193 *
194 * @param Request $request
195 * @param int $page
196 *
197 * @Route("/starred/list/{page}", name="starred", defaults={"page" = "1"})
198 *
199 * @return \Symfony\Component\HttpFoundation\Response
200 */
201 public function showStarredAction(Request $request, $page)
202 {
203 return $this->showEntries('starred', $request, $page);
204 }
205
206 /**
207 * Global method to retrieve entries depending on the given type
208 * It returns the response to be send.
209 *
210 * @param string $type Entries type: unread, starred or archive
211 * @param Request $request
212 * @param int $page
213 *
214 * @return \Symfony\Component\HttpFoundation\Response
215 */
216 private function showEntries($type, Request $request, $page)
217 {
218 $repository = $this->get('wallabag_core.entry_repository');
219
220 switch ($type) {
221 case 'starred':
222 $qb = $repository->getBuilderForStarredByUser($this->getUser()->getId());
223 break;
224
225 case 'archive':
226 $qb = $repository->getBuilderForArchiveByUser($this->getUser()->getId());
227 break;
228
229 case 'unread':
230 $qb = $repository->getBuilderForUnreadByUser($this->getUser()->getId());
231 break;
232
233 case 'all':
234 $qb = $repository->getBuilderForAllByUser($this->getUser()->getId());
235 break;
236
237 default:
238 throw new \InvalidArgumentException(sprintf('Type "%s" is not implemented.', $type));
239 }
240
241 $form = $this->createForm(EntryFilterType::class);
242
243 if ($request->query->has($form->getName())) {
244 // manually bind values from the request
245 $form->submit($request->query->get($form->getName()));
246
247 // build the query from the given form object
248 $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $qb);
249 }
250
251 $pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
252 $entries = new Pagerfanta($pagerAdapter);
253
254 $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage());
255 $entries->setCurrentPage($page);
256
257 return $this->render(
258 'WallabagCoreBundle:Entry:entries.html.twig',
259 array(
260 'form' => $form->createView(),
261 'entries' => $entries,
262 'currentPage' => $page,
263 )
264 );
265 }
266
267 /**
268 * Shows entry content.
269 *
270 * @param Entry $entry
271 *
272 * @Route("/view/{id}", requirements={"id" = "\d+"}, name="view")
273 *
274 * @return \Symfony\Component\HttpFoundation\Response
275 */
276 public function viewAction(Entry $entry)
277 {
278 $this->checkUserAction($entry);
279
280 return $this->render(
281 'WallabagCoreBundle:Entry:entry.html.twig',
282 array('entry' => $entry)
283 );
284 }
285
286 /**
287 * Reload an entry.
288 * Refetch content from the website and make it readable again.
289 *
290 * @param Entry $entry
291 *
292 * @Route("/reload/{id}", requirements={"id" = "\d+"}, name="reload_entry")
293 *
294 * @return \Symfony\Component\HttpFoundation\RedirectResponse
295 */
296 public function reloadAction(Entry $entry)
297 {
298 $this->checkUserAction($entry);
299
300 $message = 'flashes.entry.notice.entry_reloaded';
301 if (false === $this->updateEntry($entry)) {
302 $message = 'flashes.entry.notice.entry_reload_failed';
303 }
304
305 $this->get('session')->getFlashBag()->add(
306 'notice',
307 $message
308 );
309
310 return $this->redirect($this->generateUrl('view', array('id' => $entry->getId())));
311 }
312
313 /**
314 * Changes read status for an entry.
315 *
316 * @param Request $request
317 * @param Entry $entry
318 *
319 * @Route("/archive/{id}", requirements={"id" = "\d+"}, name="archive_entry")
320 *
321 * @return \Symfony\Component\HttpFoundation\RedirectResponse
322 */
323 public function toggleArchiveAction(Request $request, Entry $entry)
324 {
325 $this->checkUserAction($entry);
326
327 $entry->toggleArchive();
328 $this->getDoctrine()->getManager()->flush();
329
330 $message = 'flashes.entry.notice.entry_unarchived';
331 if ($entry->isArchived()) {
332 $message = 'flashes.entry.notice.entry_archived';
333 }
334
335 $this->get('session')->getFlashBag()->add(
336 'notice',
337 $message
338 );
339
340 return $this->redirect($request->headers->get('referer'));
341 }
342
343 /**
344 * Changes favorite status for an entry.
345 *
346 * @param Request $request
347 * @param Entry $entry
348 *
349 * @Route("/star/{id}", requirements={"id" = "\d+"}, name="star_entry")
350 *
351 * @return \Symfony\Component\HttpFoundation\RedirectResponse
352 */
353 public function toggleStarAction(Request $request, Entry $entry)
354 {
355 $this->checkUserAction($entry);
356
357 $entry->toggleStar();
358 $this->getDoctrine()->getManager()->flush();
359
360 $message = 'flashes.entry.notice.entry_unstarred';
361 if ($entry->isStarred()) {
362 $message = 'flashes.entry.notice.entry_starred';
363 }
364
365 $this->get('session')->getFlashBag()->add(
366 'notice',
367 $message
368 );
369
370 return $this->redirect($request->headers->get('referer'));
371 }
372
373 /**
374 * Deletes entry and redirect to the homepage or the last viewed page.
375 *
376 * @param Entry $entry
377 *
378 * @Route("/delete/{id}", requirements={"id" = "\d+"}, name="delete_entry")
379 *
380 * @return \Symfony\Component\HttpFoundation\RedirectResponse
381 */
382 public function deleteEntryAction(Request $request, Entry $entry)
383 {
384 $this->checkUserAction($entry);
385
386 // generates the view url for this entry to check for redirection later
387 // to avoid redirecting to the deleted entry. Ugh.
388 $url = $this->generateUrl(
389 'view',
390 array('id' => $entry->getId()),
391 UrlGeneratorInterface::ABSOLUTE_URL
392 );
393
394 $em = $this->getDoctrine()->getManager();
395 $em->remove($entry);
396 $em->flush();
397
398 $this->get('session')->getFlashBag()->add(
399 'notice',
400 'flashes.entry.notice.entry_deleted'
401 );
402
403 // don't redirect user to the deleted entry
404 return $this->redirect($url !== $request->headers->get('referer') ? $request->headers->get('referer') : $this->generateUrl('homepage'));
405 }
406
407 /**
408 * Check if the logged user can manage the given entry.
409 *
410 * @param Entry $entry
411 */
412 private function checkUserAction(Entry $entry)
413 {
414 if ($this->getUser()->getId() != $entry->getUser()->getId()) {
415 throw $this->createAccessDeniedException('You can not access this entry.');
416 }
417 }
418
419 /**
420 * Check for existing entry, if it exists, redirect to it with a message.
421 *
422 * @param $entry
423 *
424 * @return array|bool
425 */
426 private function checkIfEntryAlreadyExists($entry)
427 {
428 return $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($entry->getUrl(), $this->getUser()->getId());
429 }
430 }