]>
Commit | Line | Data |
---|---|---|
4d85d7e9 J |
1 | <?php |
2 | ||
3 | namespace Wallabag\CoreBundle\Controller; | |
4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | |
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | |
0c83fd59 | 7 | use Symfony\Component\HttpFoundation\JsonResponse; |
98568055 | 8 | use Symfony\Component\HttpFoundation\RedirectResponse; |
619cc453 | 9 | use Symfony\Component\HttpFoundation\Request; |
bb0c78f4 | 10 | use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; |
4d85d7e9 | 11 | use Wallabag\CoreBundle\Entity\Config; |
f19f9f62 | 12 | use Wallabag\CoreBundle\Entity\TaggingRule; |
bf6c0346 TC |
13 | use Wallabag\CoreBundle\Event\Activity\Actions\User\UserDeletedEvent; |
14 | use Wallabag\CoreBundle\Event\Activity\Actions\User\UserEditedEvent; | |
5c895a7f | 15 | use Wallabag\CoreBundle\Form\Type\ConfigType; |
d9085c63 | 16 | use Wallabag\CoreBundle\Form\Type\ChangePasswordType; |
0c83fd59 | 17 | use Wallabag\CoreBundle\Form\Type\RssType; |
619cc453 JB |
18 | use Wallabag\CoreBundle\Form\Type\TaggingRuleType; |
19 | use Wallabag\CoreBundle\Form\Type\UserInformationType; | |
0c83fd59 | 20 | use Wallabag\CoreBundle\Tools\Utils; |
bf6c0346 TC |
21 | use Wallabag\FederationBundle\Form\Type\AccountType; |
22 | use Wallabag\UserBundle\Entity\User; | |
4d85d7e9 J |
23 | |
24 | class ConfigController extends Controller | |
25 | { | |
26 | /** | |
27 | * @param Request $request | |
28 | * | |
29 | * @Route("/config", name="config") | |
4d85d7e9 J |
30 | */ |
31 | public function indexAction(Request $request) | |
32 | { | |
d9085c63 | 33 | $em = $this->getDoctrine()->getManager(); |
4d85d7e9 | 34 | $config = $this->getConfig(); |
fcb1fba5 | 35 | $userManager = $this->container->get('fos_user.user_manager'); |
c0d9eba0 | 36 | $user = $this->getUser(); |
4d85d7e9 | 37 | |
32da2a70 | 38 | // handle basic config detail (this form is defined as a service) |
4094ea47 | 39 | $configForm = $this->createForm(ConfigType::class, $config, ['action' => $this->generateUrl('config')]); |
d9085c63 | 40 | $configForm->handleRequest($request); |
4d85d7e9 | 41 | |
21e7ccef | 42 | if ($configForm->isSubmitted() && $configForm->isValid()) { |
4d85d7e9 J |
43 | $em->persist($config); |
44 | $em->flush(); | |
45 | ||
ece4718f NL |
46 | $request->getSession()->set('_locale', $config->getLanguage()); |
47 | ||
32da2a70 J |
48 | // switch active theme |
49 | $activeTheme = $this->get('liip_theme.active_theme'); | |
50 | $activeTheme->setName($config->getTheme()); | |
51 | ||
4d85d7e9 J |
52 | $this->get('session')->getFlashBag()->add( |
53 | 'notice', | |
4204a06b | 54 | 'flashes.config.notice.config_saved' |
4d85d7e9 J |
55 | ); |
56 | ||
57 | return $this->redirect($this->generateUrl('config')); | |
58 | } | |
59 | ||
d9085c63 | 60 | // handle changing password |
4094ea47 | 61 | $pwdForm = $this->createForm(ChangePasswordType::class, null, ['action' => $this->generateUrl('config').'#set4']); |
d9085c63 J |
62 | $pwdForm->handleRequest($request); |
63 | ||
21e7ccef | 64 | if ($pwdForm->isSubmitted() && $pwdForm->isValid()) { |
a4f42c59 | 65 | if ($this->get('craue_config')->get('demo_mode_enabled') && $this->get('craue_config')->get('demo_mode_username') === $user->getUsername()) { |
4204a06b | 66 | $message = 'flashes.config.notice.password_not_updated_demo'; |
6c9f50a6 | 67 | } else { |
4204a06b | 68 | $message = 'flashes.config.notice.password_updated'; |
b6c00b0b | 69 | |
d8d56448 NL |
70 | $user->setPlainPassword($pwdForm->get('new_password')->getData()); |
71 | $userManager->updateUser($user, true); | |
6c9f50a6 | 72 | } |
d9085c63 | 73 | |
b6c00b0b JB |
74 | $this->get('session')->getFlashBag()->add('notice', $message); |
75 | ||
c7a4f74f | 76 | return $this->redirect($this->generateUrl('config').'#set4'); |
d9085c63 J |
77 | } |
78 | ||
c0d9eba0 | 79 | // handle changing user information |
4094ea47 JB |
80 | $userForm = $this->createForm(UserInformationType::class, $user, [ |
81 | 'validation_groups' => ['Profile'], | |
33fe61f9 | 82 | 'action' => $this->generateUrl('config').'#set3', |
4094ea47 | 83 | ]); |
c0d9eba0 J |
84 | $userForm->handleRequest($request); |
85 | ||
21e7ccef | 86 | if ($userForm->isSubmitted() && $userForm->isValid()) { |
fcb1fba5 | 87 | $userManager->updateUser($user, true); |
c0d9eba0 | 88 | |
bf6c0346 TC |
89 | $this->get('event_dispatcher')->dispatch(UserEditedEvent::NAME, new UserEditedEvent($user->getAccount())); |
90 | ||
91 | $this->get('session')->getFlashBag()->add( | |
92 | 'notice', | |
93 | 'flashes.config.notice.user_updated' | |
94 | ); | |
95 | ||
96 | return $this->redirect($this->generateUrl('config').'#set3'); | |
97 | } | |
98 | ||
99 | // handle account information | |
100 | $account = $user->getAccount(); | |
101 | $accountForm = $this->createForm(AccountType::class, $account, [ | |
102 | 'action' => $this->generateUrl('config').'#set3', | |
103 | ]); | |
104 | $accountForm->handleRequest($request); | |
105 | ||
106 | if ($accountForm->isSubmitted() && $accountForm->isValid()) { | |
107 | ||
108 | $avatar = $account->getAvatar(); | |
109 | $banner = $account->getBanner(); | |
110 | ||
111 | if (null !== $avatar) { | |
112 | $avatarFileName = md5(uniqid('', true)) . '.' . $avatar->guessExtension(); | |
113 | ||
114 | $avatar->move( | |
115 | $this->getParameter('media_directory') . '/avatar', | |
116 | $avatarFileName | |
117 | ); | |
118 | $account->setAvatar($avatarFileName); | |
119 | } | |
120 | ||
121 | if (null != $banner) { | |
122 | $bannerFileName = md5(uniqid('', true)) . '.' . $banner->guessExtension(); | |
123 | ||
124 | $banner->move( | |
125 | $this->get('media_directory') . '/banner', | |
126 | $bannerFileName | |
127 | ); | |
128 | $account->setBanner($bannerFileName); | |
129 | } | |
130 | ||
131 | $this->get('event_dispatcher')->dispatch(UserEditedEvent::NAME, new UserEditedEvent($user)); | |
132 | ||
c0d9eba0 J |
133 | $this->get('session')->getFlashBag()->add( |
134 | 'notice', | |
4204a06b | 135 | 'flashes.config.notice.user_updated' |
c0d9eba0 J |
136 | ); |
137 | ||
c7a4f74f | 138 | return $this->redirect($this->generateUrl('config').'#set3'); |
c0d9eba0 J |
139 | } |
140 | ||
0c83fd59 | 141 | // handle rss information |
4094ea47 | 142 | $rssForm = $this->createForm(RssType::class, $config, ['action' => $this->generateUrl('config').'#set2']); |
0c83fd59 J |
143 | $rssForm->handleRequest($request); |
144 | ||
21e7ccef | 145 | if ($rssForm->isSubmitted() && $rssForm->isValid()) { |
0c83fd59 J |
146 | $em->persist($config); |
147 | $em->flush(); | |
148 | ||
149 | $this->get('session')->getFlashBag()->add( | |
150 | 'notice', | |
4204a06b | 151 | 'flashes.config.notice.rss_updated' |
0c83fd59 J |
152 | ); |
153 | ||
c7a4f74f | 154 | return $this->redirect($this->generateUrl('config').'#set2'); |
0c83fd59 J |
155 | } |
156 | ||
f19f9f62 KG |
157 | // handle tagging rule |
158 | $taggingRule = new TaggingRule(); | |
bf3dc999 JB |
159 | $action = $this->generateUrl('config').'#set5'; |
160 | ||
161 | if ($request->query->has('tagging-rule')) { | |
162 | $taggingRule = $this->getDoctrine() | |
163 | ->getRepository('WallabagCoreBundle:TaggingRule') | |
164 | ->find($request->query->get('tagging-rule')); | |
165 | ||
166 | if ($this->getUser()->getId() !== $taggingRule->getConfig()->getUser()->getId()) { | |
167 | return $this->redirect($action); | |
168 | } | |
169 | ||
170 | $action = $this->generateUrl('config').'?tagging-rule='.$taggingRule->getId().'#set5'; | |
171 | } | |
172 | ||
173 | $newTaggingRule = $this->createForm(TaggingRuleType::class, $taggingRule, ['action' => $action]); | |
f19f9f62 KG |
174 | $newTaggingRule->handleRequest($request); |
175 | ||
21e7ccef | 176 | if ($newTaggingRule->isSubmitted() && $newTaggingRule->isValid()) { |
f19f9f62 KG |
177 | $taggingRule->setConfig($config); |
178 | $em->persist($taggingRule); | |
179 | $em->flush(); | |
180 | ||
181 | $this->get('session')->getFlashBag()->add( | |
182 | 'notice', | |
4204a06b | 183 | 'flashes.config.notice.tagging_rules_updated' |
f19f9f62 KG |
184 | ); |
185 | ||
c7a4f74f | 186 | return $this->redirect($this->generateUrl('config').'#set5'); |
f19f9f62 KG |
187 | } |
188 | ||
4094ea47 JB |
189 | return $this->render('WallabagCoreBundle:Config:index.html.twig', [ |
190 | 'form' => [ | |
0c83fd59 J |
191 | 'config' => $configForm->createView(), |
192 | 'rss' => $rssForm->createView(), | |
193 | 'pwd' => $pwdForm->createView(), | |
194 | 'user' => $userForm->createView(), | |
f19f9f62 | 195 | 'new_tagging_rule' => $newTaggingRule->createView(), |
bf6c0346 | 196 | 'account' => $accountForm->createView(), |
4094ea47 JB |
197 | ], |
198 | 'rss' => [ | |
0c83fd59 J |
199 | 'username' => $user->getUsername(), |
200 | 'token' => $config->getRssToken(), | |
4094ea47 | 201 | ], |
63e40f2d | 202 | 'twofactor_auth' => $this->getParameter('twofactor_auth'), |
be9d693e | 203 | 'wallabag_url' => $this->getParameter('domain_name'), |
25203e50 | 204 | 'enabled_users' => $this->get('wallabag_user.user_repository') |
bb0c78f4 | 205 | ->getSumEnabledUsers(), |
4094ea47 | 206 | ]); |
4d85d7e9 J |
207 | } |
208 | ||
0c83fd59 J |
209 | /** |
210 | * @param Request $request | |
211 | * | |
212 | * @Route("/generate-token", name="generate_token") | |
213 | * | |
98568055 | 214 | * @return RedirectResponse|JsonResponse |
0c83fd59 J |
215 | */ |
216 | public function generateTokenAction(Request $request) | |
217 | { | |
218 | $config = $this->getConfig(); | |
219 | $config->setRssToken(Utils::generateToken()); | |
220 | ||
221 | $em = $this->getDoctrine()->getManager(); | |
222 | $em->persist($config); | |
223 | $em->flush(); | |
224 | ||
225 | if ($request->isXmlHttpRequest()) { | |
4094ea47 | 226 | return new JsonResponse(['token' => $config->getRssToken()]); |
0c83fd59 J |
227 | } |
228 | ||
c7a4f74f JB |
229 | $this->get('session')->getFlashBag()->add( |
230 | 'notice', | |
4204a06b | 231 | 'flashes.config.notice.rss_token_updated' |
c7a4f74f JB |
232 | ); |
233 | ||
234 | return $this->redirect($this->generateUrl('config').'#set2'); | |
0c83fd59 J |
235 | } |
236 | ||
52e423f3 KG |
237 | /** |
238 | * Deletes a tagging rule and redirect to the config homepage. | |
239 | * | |
240 | * @param TaggingRule $rule | |
241 | * | |
242 | * @Route("/tagging-rule/delete/{id}", requirements={"id" = "\d+"}, name="delete_tagging_rule") | |
243 | * | |
98568055 | 244 | * @return RedirectResponse |
52e423f3 | 245 | */ |
5f8a7857 | 246 | public function deleteTaggingRuleAction(TaggingRule $rule) |
52e423f3 | 247 | { |
8799bde0 | 248 | $this->validateRuleAction($rule); |
52e423f3 KG |
249 | |
250 | $em = $this->getDoctrine()->getManager(); | |
251 | $em->remove($rule); | |
252 | $em->flush(); | |
253 | ||
254 | $this->get('session')->getFlashBag()->add( | |
255 | 'notice', | |
4204a06b | 256 | 'flashes.config.notice.tagging_rules_deleted' |
52e423f3 KG |
257 | ); |
258 | ||
c7a4f74f | 259 | return $this->redirect($this->generateUrl('config').'#set5'); |
52e423f3 KG |
260 | } |
261 | ||
bf3dc999 JB |
262 | /** |
263 | * Edit a tagging rule. | |
264 | * | |
265 | * @param TaggingRule $rule | |
266 | * | |
267 | * @Route("/tagging-rule/edit/{id}", requirements={"id" = "\d+"}, name="edit_tagging_rule") | |
268 | * | |
269 | * @return RedirectResponse | |
270 | */ | |
271 | public function editTaggingRuleAction(TaggingRule $rule) | |
8799bde0 JB |
272 | { |
273 | $this->validateRuleAction($rule); | |
274 | ||
275 | return $this->redirect($this->generateUrl('config').'?tagging-rule='.$rule->getId().'#set5'); | |
276 | } | |
277 | ||
206bade5 JB |
278 | /** |
279 | * Remove all annotations OR tags OR entries for the current user. | |
280 | * | |
281 | * @Route("/reset/{type}", requirements={"id" = "annotations|tags|entries"}, name="config_reset") | |
282 | * | |
283 | * @return RedirectResponse | |
284 | */ | |
285 | public function resetAction($type) | |
286 | { | |
206bade5 JB |
287 | switch ($type) { |
288 | case 'annotations': | |
191564b7 JB |
289 | $this->getDoctrine() |
290 | ->getRepository('WallabagAnnotationBundle:Annotation') | |
291 | ->removeAllByUserId($this->getUser()->getId()); | |
206bade5 JB |
292 | break; |
293 | ||
294 | case 'tags': | |
191564b7 JB |
295 | $this->removeAllTagsByUserId($this->getUser()->getId()); |
296 | break; | |
206bade5 | 297 | |
191564b7 | 298 | case 'entries': |
6da1aebc | 299 | // SQLite doesn't care about cascading remove, so we need to manually remove associated stuff |
191564b7 | 300 | // otherwise they won't be removed ... |
7ab5eb95 | 301 | if ($this->get('doctrine')->getConnection()->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\SqlitePlatform) { |
191564b7 | 302 | $this->getDoctrine()->getRepository('WallabagAnnotationBundle:Annotation')->removeAllByUserId($this->getUser()->getId()); |
206bade5 JB |
303 | } |
304 | ||
8c61fd12 | 305 | // manually remove tags to avoid orphan tag |
f71e55ac JB |
306 | $this->removeAllTagsByUserId($this->getUser()->getId()); |
307 | ||
25203e50 | 308 | $this->get('wallabag_core.entry_repository')->removeAllByUserId($this->getUser()->getId()); |
6da1aebc TC |
309 | break; |
310 | case 'archived': | |
7ab5eb95 | 311 | if ($this->get('doctrine')->getConnection()->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\SqlitePlatform) { |
6da1aebc TC |
312 | $this->removeAnnotationsForArchivedByUserId($this->getUser()->getId()); |
313 | } | |
314 | ||
315 | // manually remove tags to avoid orphan tag | |
316 | $this->removeTagsForArchivedByUserId($this->getUser()->getId()); | |
317 | ||
25203e50 | 318 | $this->get('wallabag_core.entry_repository')->removeArchivedByUserId($this->getUser()->getId()); |
6da1aebc | 319 | break; |
206bade5 JB |
320 | } |
321 | ||
322 | $this->get('session')->getFlashBag()->add( | |
323 | 'notice', | |
324 | 'flashes.config.notice.'.$type.'_reset' | |
325 | ); | |
326 | ||
327 | return $this->redirect($this->generateUrl('config').'#set3'); | |
328 | } | |
329 | ||
191564b7 | 330 | /** |
e682a70f | 331 | * Remove all tags for given tags and a given user and cleanup orphan tags. |
191564b7 | 332 | * |
e682a70f NL |
333 | * @param array $tags |
334 | * @param int $userId | |
191564b7 | 335 | */ |
e682a70f | 336 | private function removeAllTagsByStatusAndUserId($tags, $userId) |
191564b7 | 337 | { |
191564b7 JB |
338 | if (empty($tags)) { |
339 | return; | |
340 | } | |
341 | ||
25203e50 | 342 | $this->get('wallabag_core.entry_repository') |
191564b7 | 343 | ->removeTags($userId, $tags); |
f71e55ac | 344 | |
8c61fd12 | 345 | // cleanup orphan tags |
f71e55ac JB |
346 | $em = $this->getDoctrine()->getManager(); |
347 | ||
348 | foreach ($tags as $tag) { | |
349 | if (count($tag->getEntries()) === 0) { | |
350 | $em->remove($tag); | |
351 | } | |
352 | } | |
353 | ||
354 | $em->flush(); | |
191564b7 JB |
355 | } |
356 | ||
e682a70f NL |
357 | /** |
358 | * Remove all tags for a given user and cleanup orphan tags. | |
359 | * | |
360 | * @param int $userId | |
361 | */ | |
362 | private function removeAllTagsByUserId($userId) | |
363 | { | |
25203e50 | 364 | $tags = $this->get('wallabag_core.tag_repository')->findAllTags($userId); |
e682a70f NL |
365 | $this->removeAllTagsByStatusAndUserId($tags, $userId); |
366 | } | |
367 | ||
6da1aebc TC |
368 | /** |
369 | * Remove all tags for a given user and cleanup orphan tags. | |
370 | * | |
371 | * @param int $userId | |
372 | */ | |
373 | private function removeTagsForArchivedByUserId($userId) | |
374 | { | |
25203e50 | 375 | $tags = $this->get('wallabag_core.tag_repository')->findForArchivedArticlesByUser($userId); |
e682a70f | 376 | $this->removeAllTagsByStatusAndUserId($tags, $userId); |
6da1aebc TC |
377 | } |
378 | ||
379 | private function removeAnnotationsForArchivedByUserId($userId) | |
380 | { | |
381 | $em = $this->getDoctrine()->getManager(); | |
382 | ||
383 | $archivedEntriesAnnotations = $this->getDoctrine() | |
384 | ->getRepository('WallabagAnnotationBundle:Annotation') | |
13a592a1 | 385 | ->findAllArchivedEntriesByUser($userId); |
6da1aebc TC |
386 | |
387 | foreach ($archivedEntriesAnnotations as $archivedEntriesAnnotation) { | |
388 | $em->remove($archivedEntriesAnnotation); | |
389 | } | |
390 | ||
391 | $em->flush(); | |
392 | } | |
393 | ||
8799bde0 | 394 | /** |
2455472e | 395 | * Validate that a rule can be edited/deleted by the current user. |
8799bde0 | 396 | * |
2455472e | 397 | * @param TaggingRule $rule |
8799bde0 JB |
398 | */ |
399 | private function validateRuleAction(TaggingRule $rule) | |
bf3dc999 JB |
400 | { |
401 | if ($this->getUser()->getId() != $rule->getConfig()->getUser()->getId()) { | |
402 | throw $this->createAccessDeniedException('You can not access this tagging rule.'); | |
403 | } | |
bf3dc999 JB |
404 | } |
405 | ||
d9085c63 J |
406 | /** |
407 | * Retrieve config for the current user. | |
408 | * If no config were found, create a new one. | |
409 | * | |
4094ea47 | 410 | * @return Config |
d9085c63 | 411 | */ |
4d85d7e9 J |
412 | private function getConfig() |
413 | { | |
414 | $config = $this->getDoctrine() | |
415 | ->getRepository('WallabagCoreBundle:Config') | |
416 | ->findOneByUser($this->getUser()); | |
417 | ||
ca17abce | 418 | // should NEVER HAPPEN ... |
4d85d7e9 J |
419 | if (!$config) { |
420 | $config = new Config($this->getUser()); | |
421 | } | |
422 | ||
423 | return $config; | |
424 | } | |
e4b46f77 | 425 | |
7ac3e575 JB |
426 | /** |
427 | * Delete account for current user. | |
428 | * | |
429 | * @Route("/account/delete", name="delete_account") | |
430 | * | |
431 | * @param Request $request | |
432 | * | |
433 | * @throws AccessDeniedHttpException | |
434 | * | |
435 | * @return \Symfony\Component\HttpFoundation\RedirectResponse | |
436 | */ | |
eed812af JB |
437 | public function deleteAccountAction(Request $request) |
438 | { | |
25203e50 | 439 | $enabledUsers = $this->get('wallabag_user.user_repository') |
eed812af JB |
440 | ->getSumEnabledUsers(); |
441 | ||
442 | if ($enabledUsers <= 1) { | |
443 | throw new AccessDeniedHttpException(); | |
444 | } | |
445 | ||
446 | $user = $this->getUser(); | |
447 | ||
448 | // logout current user | |
449 | $this->get('security.token_storage')->setToken(null); | |
450 | $request->getSession()->invalidate(); | |
451 | ||
bf6c0346 TC |
452 | $account = $user->getAccount(); |
453 | ||
eed812af JB |
454 | $em = $this->get('fos_user.user_manager'); |
455 | $em->deleteUser($user); | |
456 | ||
bf6c0346 TC |
457 | $this->get('event_dispatcher')->dispatch(UserDeletedEvent::NAME, new UserDeletedEvent($account)); |
458 | ||
eed812af JB |
459 | return $this->redirect($this->generateUrl('fos_user_security_login')); |
460 | } | |
9f01d0fd NL |
461 | |
462 | /** | |
463 | * Switch view mode for current user. | |
464 | * | |
465 | * @Route("/config/view-mode", name="switch_view_mode") | |
466 | * | |
467 | * @param Request $request | |
468 | * | |
469 | * @return \Symfony\Component\HttpFoundation\RedirectResponse | |
470 | */ | |
471 | public function changeViewModeAction(Request $request) | |
472 | { | |
473 | $user = $this->getUser(); | |
9aa99128 | 474 | $user->getConfig()->setListMode(!$user->getConfig()->getListMode()); |
9f01d0fd NL |
475 | |
476 | $em = $this->getDoctrine()->getManager(); | |
477 | $em->persist($user); | |
478 | $em->flush(); | |
479 | ||
480 | return $this->redirect($request->headers->get('referer')); | |
481 | } | |
4d85d7e9 | 482 | } |