]> git.immae.eu Git - github/wallabag/wallabag.git/blob - src/Wallabag/CoreBundle/Controller/EntryController.php
Merge pull request #1583 from wallabag/v2-fix-delete
[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\Filter\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 // check for existing entry, if it exists, redirect to it with a message
52 $existingEntry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($entry->getUrl(), $this->getUser()->getId());
53
54 if (false !== $existingEntry) {
55 $this->get('session')->getFlashBag()->add(
56 'notice',
57 'Entry already saved on '.$existingEntry['createdAt']->format('d-m-Y')
58 );
59
60 return $this->redirect($this->generateUrl('view', array('id' => $existingEntry['id'])));
61 }
62
63 $this->updateEntry($entry);
64 $this->get('session')->getFlashBag()->add(
65 'notice',
66 'Entry saved'
67 );
68
69 return $this->redirect($this->generateUrl('homepage'));
70 }
71
72 return $this->render('WallabagCoreBundle:Entry:new_form.html.twig', array(
73 'form' => $form->createView(),
74 ));
75 }
76
77 /**
78 * @param Request $request
79 *
80 * @Route("/bookmarklet", name="bookmarklet")
81 *
82 * @return \Symfony\Component\HttpFoundation\Response
83 */
84 public function addEntryViaBookmarklet(Request $request)
85 {
86 $entry = new Entry($this->getUser());
87 $entry->setUrl($request->get('url'));
88 $this->updateEntry($entry);
89
90 return $this->redirect($this->generateUrl('homepage'));
91 }
92
93 /**
94 * @param Request $request
95 *
96 * @Route("/new", name="new")
97 *
98 * @return \Symfony\Component\HttpFoundation\Response
99 */
100 public function addEntryAction(Request $request)
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 '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 = 'Entry reloaded';
301 if (false === $this->updateEntry($entry)) {
302 $message = 'Failed to reload entry';
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 $this->get('session')->getFlashBag()->add(
331 'notice',
332 'Entry '.($entry->isArchived() ? 'archived' : 'unarchived')
333 );
334
335 return $this->redirect($request->headers->get('referer'));
336 }
337
338 /**
339 * Changes favorite status for an entry.
340 *
341 * @param Request $request
342 * @param Entry $entry
343 *
344 * @Route("/star/{id}", requirements={"id" = "\d+"}, name="star_entry")
345 *
346 * @return \Symfony\Component\HttpFoundation\RedirectResponse
347 */
348 public function toggleStarAction(Request $request, Entry $entry)
349 {
350 $this->checkUserAction($entry);
351
352 $entry->toggleStar();
353 $this->getDoctrine()->getManager()->flush();
354
355 $this->get('session')->getFlashBag()->add(
356 'notice',
357 'Entry '.($entry->isStarred() ? 'starred' : 'unstarred')
358 );
359
360 return $this->redirect($request->headers->get('referer'));
361 }
362
363 /**
364 * Deletes entry and redirect to the homepage or the last viewed page.
365 *
366 * @param Entry $entry
367 *
368 * @Route("/delete/{id}", requirements={"id" = "\d+"}, name="delete_entry")
369 *
370 * @return \Symfony\Component\HttpFoundation\RedirectResponse
371 */
372 public function deleteEntryAction(Request $request, Entry $entry)
373 {
374 $this->checkUserAction($entry);
375
376 // generates the view url for this entry to check for redirection later
377 // to avoid redirecting to the deleted entry. Ugh.
378 $url = $this->generateUrl(
379 'view',
380 array('id' => $entry->getId()),
381 UrlGeneratorInterface::ABSOLUTE_URL
382 );
383
384 $em = $this->getDoctrine()->getManager();
385 $em->remove($entry);
386 $em->flush();
387
388 $this->get('session')->getFlashBag()->add(
389 'notice',
390 'Entry deleted'
391 );
392
393 // don't redirect user to the deleted entry
394 return $this->redirect($url !== $request->headers->get('referer') ? $request->headers->get('referer') : $this->generateUrl('homepage'));
395 }
396
397 /**
398 * Check if the logged user can manage the given entry.
399 *
400 * @param Entry $entry
401 */
402 private function checkUserAction(Entry $entry)
403 {
404 if ($this->getUser()->getId() != $entry->getUser()->getId()) {
405 throw $this->createAccessDeniedException('You can not access this entry.');
406 }
407 }
408 }