]> git.immae.eu Git - github/wallabag/wallabag.git/blame - src/Wallabag/CoreBundle/Controller/ConfigController.php
WIP
[github/wallabag/wallabag.git] / src / Wallabag / CoreBundle / Controller / ConfigController.php
CommitLineData
4d85d7e9
J
1<?php
2
3namespace Wallabag\CoreBundle\Controller;
4
5use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
6use Symfony\Bundle\FrameworkBundle\Controller\Controller;
0c83fd59 7use Symfony\Component\HttpFoundation\JsonResponse;
98568055 8use Symfony\Component\HttpFoundation\RedirectResponse;
619cc453 9use Symfony\Component\HttpFoundation\Request;
bb0c78f4 10use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
4d85d7e9 11use Wallabag\CoreBundle\Entity\Config;
f19f9f62 12use Wallabag\CoreBundle\Entity\TaggingRule;
bf6c0346
TC
13use Wallabag\CoreBundle\Event\Activity\Actions\User\UserDeletedEvent;
14use Wallabag\CoreBundle\Event\Activity\Actions\User\UserEditedEvent;
5c895a7f 15use Wallabag\CoreBundle\Form\Type\ConfigType;
d9085c63 16use Wallabag\CoreBundle\Form\Type\ChangePasswordType;
0c83fd59 17use Wallabag\CoreBundle\Form\Type\RssType;
619cc453
JB
18use Wallabag\CoreBundle\Form\Type\TaggingRuleType;
19use Wallabag\CoreBundle\Form\Type\UserInformationType;
0c83fd59 20use Wallabag\CoreBundle\Tools\Utils;
bf6c0346
TC
21use Wallabag\FederationBundle\Form\Type\AccountType;
22use Wallabag\UserBundle\Entity\User;
4d85d7e9
J
23
24class 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}