aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag
diff options
context:
space:
mode:
Diffstat (limited to 'src/Wallabag')
-rw-r--r--src/Wallabag/AnnotationBundle/Controller/WallabagAnnotationController.php74
-rw-r--r--src/Wallabag/AnnotationBundle/Entity/Annotation.php2
-rw-r--r--src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php20
-rw-r--r--src/Wallabag/ApiBundle/Controller/WallabagRestController.php126
-rw-r--r--src/Wallabag/ApiBundle/Resources/config/routing_rest.yml8
-rw-r--r--src/Wallabag/CoreBundle/Command/InstallCommand.php30
-rw-r--r--src/Wallabag/CoreBundle/Controller/ConfigController.php111
-rw-r--r--src/Wallabag/CoreBundle/Controller/TagController.php10
-rw-r--r--src/Wallabag/CoreBundle/Entity/Entry.php6
-rw-r--r--src/Wallabag/CoreBundle/Repository/EntryRepository.php14
-rw-r--r--src/Wallabag/CoreBundle/Repository/TagRepository.php18
-rw-r--r--src/Wallabag/CoreBundle/Resources/config/services.yml7
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.da.yml15
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.de.yml15
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.en.yml15
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.es.yml15
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml15
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml19
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.it.yml15
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml93
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml15
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml15
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml15
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig31
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig28
-rw-r--r--src/Wallabag/CoreBundle/Subscriber/SQLiteCascadeDeleteSubscriber.php70
-rw-r--r--src/Wallabag/UserBundle/Repository/UserRepository.php14
-rw-r--r--src/Wallabag/UserBundle/Resources/config/services.yml2
28 files changed, 698 insertions, 120 deletions
diff --git a/src/Wallabag/AnnotationBundle/Controller/WallabagAnnotationController.php b/src/Wallabag/AnnotationBundle/Controller/WallabagAnnotationController.php
index ad083e31..c13a034f 100644
--- a/src/Wallabag/AnnotationBundle/Controller/WallabagAnnotationController.php
+++ b/src/Wallabag/AnnotationBundle/Controller/WallabagAnnotationController.php
@@ -3,9 +3,8 @@
3namespace Wallabag\AnnotationBundle\Controller; 3namespace Wallabag\AnnotationBundle\Controller;
4 4
5use FOS\RestBundle\Controller\FOSRestController; 5use FOS\RestBundle\Controller\FOSRestController;
6use Nelmio\ApiDocBundle\Annotation\ApiDoc; 6use Symfony\Component\HttpFoundation\JsonResponse;
7use Symfony\Component\HttpFoundation\Request; 7use Symfony\Component\HttpFoundation\Request;
8use Symfony\Component\HttpFoundation\Response;
9use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; 8use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
10use Wallabag\AnnotationBundle\Entity\Annotation; 9use Wallabag\AnnotationBundle\Entity\Annotation;
11use Wallabag\CoreBundle\Entity\Entry; 10use Wallabag\CoreBundle\Entity\Entry;
@@ -15,42 +14,35 @@ class WallabagAnnotationController extends FOSRestController
15 /** 14 /**
16 * Retrieve annotations for an entry. 15 * Retrieve annotations for an entry.
17 * 16 *
18 * @ApiDoc( 17 * @param Entry $entry
19 * requirements={ 18 *
20 * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} 19 * @see Wallabag\ApiBundle\Controller\WallabagRestController
21 * }
22 * )
23 * 20 *
24 * @return Response 21 * @return JsonResponse
25 */ 22 */
26 public function getAnnotationsAction(Entry $entry) 23 public function getAnnotationsAction(Entry $entry)
27 { 24 {
28 $annotationRows = $this 25 $annotationRows = $this
29 ->getDoctrine() 26 ->getDoctrine()
30 ->getRepository('WallabagAnnotationBundle:Annotation') 27 ->getRepository('WallabagAnnotationBundle:Annotation')
31 ->findAnnotationsByPageId($entry->getId(), $this->getUser()->getId()); 28 ->findAnnotationsByPageId($entry->getId(), $this->getUser()->getId());
32 $total = count($annotationRows); 29 $total = count($annotationRows);
33 $annotations = ['total' => $total, 'rows' => $annotationRows]; 30 $annotations = ['total' => $total, 'rows' => $annotationRows];
34 31
35 $json = $this->get('serializer')->serialize($annotations, 'json'); 32 $json = $this->get('serializer')->serialize($annotations, 'json');
36 33
37 return $this->renderJsonResponse($json); 34 return (new JsonResponse())->setJson($json);
38 } 35 }
39 36
40 /** 37 /**
41 * Creates a new annotation. 38 * Creates a new annotation.
42 * 39 *
43 * @param Entry $entry 40 * @param Request $request
41 * @param Entry $entry
44 * 42 *
45 * @ApiDoc( 43 * @return JsonResponse
46 * requirements={
47 * {"name"="ranges", "dataType"="array", "requirement"="\w+", "description"="The range array for the annotation"},
48 * {"name"="quote", "dataType"="string", "required"=false, "description"="Optional, quote for the annotation"},
49 * {"name"="text", "dataType"="string", "required"=true, "description"=""},
50 * }
51 * )
52 * 44 *
53 * @return Response 45 * @see Wallabag\ApiBundle\Controller\WallabagRestController
54 */ 46 */
55 public function postAnnotationAction(Request $request, Entry $entry) 47 public function postAnnotationAction(Request $request, Entry $entry)
56 { 48 {
@@ -75,21 +67,20 @@ class WallabagAnnotationController extends FOSRestController
75 67
76 $json = $this->get('serializer')->serialize($annotation, 'json'); 68 $json = $this->get('serializer')->serialize($annotation, 'json');
77 69
78 return $this->renderJsonResponse($json); 70 return (new JsonResponse())->setJson($json);
79 } 71 }
80 72
81 /** 73 /**
82 * Updates an annotation. 74 * Updates an annotation.
83 * 75 *
84 * @ApiDoc( 76 * @see Wallabag\ApiBundle\Controller\WallabagRestController
85 * requirements={
86 * {"name"="annotation", "dataType"="string", "requirement"="\w+", "description"="The annotation ID"}
87 * }
88 * )
89 * 77 *
90 * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation") 78 * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation")
91 * 79 *
92 * @return Response 80 * @param Annotation $annotation
81 * @param Request $request
82 *
83 * @return JsonResponse
93 */ 84 */
94 public function putAnnotationAction(Annotation $annotation, Request $request) 85 public function putAnnotationAction(Annotation $annotation, Request $request)
95 { 86 {
@@ -104,21 +95,19 @@ class WallabagAnnotationController extends FOSRestController
104 95
105 $json = $this->get('serializer')->serialize($annotation, 'json'); 96 $json = $this->get('serializer')->serialize($annotation, 'json');
106 97
107 return $this->renderJsonResponse($json); 98 return (new JsonResponse())->setJson($json);
108 } 99 }
109 100
110 /** 101 /**
111 * Removes an annotation. 102 * Removes an annotation.
112 * 103 *
113 * @ApiDoc( 104 * @see Wallabag\ApiBundle\Controller\WallabagRestController
114 * requirements={
115 * {"name"="annotation", "dataType"="string", "requirement"="\w+", "description"="The annotation ID"}
116 * }
117 * )
118 * 105 *
119 * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation") 106 * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation")
120 * 107 *
121 * @return Response 108 * @param Annotation $annotation
109 *
110 * @return JsonResponse
122 */ 111 */
123 public function deleteAnnotationAction(Annotation $annotation) 112 public function deleteAnnotationAction(Annotation $annotation)
124 { 113 {
@@ -128,19 +117,6 @@ class WallabagAnnotationController extends FOSRestController
128 117
129 $json = $this->get('serializer')->serialize($annotation, 'json'); 118 $json = $this->get('serializer')->serialize($annotation, 'json');
130 119
131 return $this->renderJsonResponse($json); 120 return (new JsonResponse())->setJson($json);
132 }
133
134 /**
135 * Send a JSON Response.
136 * We don't use the Symfony JsonRespone, because it takes an array as parameter instead of a JSON string.
137 *
138 * @param string $json
139 *
140 * @return Response
141 */
142 private function renderJsonResponse($json, $code = 200)
143 {
144 return new Response($json, $code, ['application/json']);
145 } 121 }
146} 122}
diff --git a/src/Wallabag/AnnotationBundle/Entity/Annotation.php b/src/Wallabag/AnnotationBundle/Entity/Annotation.php
index c48d8731..0838f5aa 100644
--- a/src/Wallabag/AnnotationBundle/Entity/Annotation.php
+++ b/src/Wallabag/AnnotationBundle/Entity/Annotation.php
@@ -82,7 +82,7 @@ class Annotation
82 * @Exclude 82 * @Exclude
83 * 83 *
84 * @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\Entry", inversedBy="annotations") 84 * @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\Entry", inversedBy="annotations")
85 * @ORM\JoinColumn(name="entry_id", referencedColumnName="id") 85 * @ORM\JoinColumn(name="entry_id", referencedColumnName="id", onDelete="cascade")
86 */ 86 */
87 private $entry; 87 private $entry;
88 88
diff --git a/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php b/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php
index 5f7da70e..8d3f07ee 100644
--- a/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php
+++ b/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php
@@ -50,7 +50,8 @@ class AnnotationRepository extends EntityRepository
50 { 50 {
51 return $this->createQueryBuilder('a') 51 return $this->createQueryBuilder('a')
52 ->andWhere('a.id = :annotationId')->setParameter('annotationId', $annotationId) 52 ->andWhere('a.id = :annotationId')->setParameter('annotationId', $annotationId)
53 ->getQuery()->getSingleResult() 53 ->getQuery()
54 ->getSingleResult()
54 ; 55 ;
55 } 56 }
56 57
@@ -67,7 +68,8 @@ class AnnotationRepository extends EntityRepository
67 return $this->createQueryBuilder('a') 68 return $this->createQueryBuilder('a')
68 ->where('a.entry = :entryId')->setParameter('entryId', $entryId) 69 ->where('a.entry = :entryId')->setParameter('entryId', $entryId)
69 ->andwhere('a.user = :userId')->setParameter('userId', $userId) 70 ->andwhere('a.user = :userId')->setParameter('userId', $userId)
70 ->getQuery()->getResult() 71 ->getQuery()
72 ->getResult()
71 ; 73 ;
72 } 74 }
73 75
@@ -106,4 +108,18 @@ class AnnotationRepository extends EntityRepository
106 ->getQuery() 108 ->getQuery()
107 ->getSingleResult(); 109 ->getSingleResult();
108 } 110 }
111
112 /**
113 * Remove all annotations for a user id.
114 * Used when a user want to reset all informations.
115 *
116 * @param int $userId
117 */
118 public function removeAllByUserId($userId)
119 {
120 $this->getEntityManager()
121 ->createQuery('DELETE FROM Wallabag\AnnotationBundle\Entity\Annotation a WHERE a.user = :userId')
122 ->setParameter('userId', $userId)
123 ->execute();
124 }
109} 125}
diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
index 9997913d..a73d44ca 100644
--- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
@@ -3,15 +3,17 @@
3namespace Wallabag\ApiBundle\Controller; 3namespace Wallabag\ApiBundle\Controller;
4 4
5use FOS\RestBundle\Controller\FOSRestController; 5use FOS\RestBundle\Controller\FOSRestController;
6use Hateoas\Configuration\Route; 6use Hateoas\Configuration\Route as HateoasRoute;
7use Hateoas\Representation\Factory\PagerfantaFactory; 7use Hateoas\Representation\Factory\PagerfantaFactory;
8use Nelmio\ApiDocBundle\Annotation\ApiDoc; 8use Nelmio\ApiDocBundle\Annotation\ApiDoc;
9use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
9use Symfony\Component\HttpFoundation\Request; 10use Symfony\Component\HttpFoundation\Request;
10use Symfony\Component\HttpFoundation\JsonResponse; 11use Symfony\Component\HttpFoundation\JsonResponse;
11use Symfony\Component\Routing\Generator\UrlGeneratorInterface; 12use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
12use Symfony\Component\Security\Core\Exception\AccessDeniedException; 13use Symfony\Component\Security\Core\Exception\AccessDeniedException;
13use Wallabag\CoreBundle\Entity\Entry; 14use Wallabag\CoreBundle\Entity\Entry;
14use Wallabag\CoreBundle\Entity\Tag; 15use Wallabag\CoreBundle\Entity\Tag;
16use Wallabag\AnnotationBundle\Entity\Annotation;
15 17
16class WallabagRestController extends FOSRestController 18class WallabagRestController extends FOSRestController
17{ 19{
@@ -115,7 +117,7 @@ class WallabagRestController extends FOSRestController
115 $pagerfantaFactory = new PagerfantaFactory('page', 'perPage'); 117 $pagerfantaFactory = new PagerfantaFactory('page', 'perPage');
116 $paginatedCollection = $pagerfantaFactory->createRepresentation( 118 $paginatedCollection = $pagerfantaFactory->createRepresentation(
117 $pager, 119 $pager,
118 new Route( 120 new HateoasRoute(
119 'api_get_entries', 121 'api_get_entries',
120 [ 122 [
121 'archive' => $isArchived, 123 'archive' => $isArchived,
@@ -158,6 +160,28 @@ class WallabagRestController extends FOSRestController
158 } 160 }
159 161
160 /** 162 /**
163 * Retrieve a single entry as a predefined format.
164 *
165 * @ApiDoc(
166 * requirements={
167 * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
168 * }
169 * )
170 *
171 * @return Response
172 */
173 public function getEntryExportAction(Entry $entry, Request $request)
174 {
175 $this->validateAuthentication();
176 $this->validateUserAccess($entry->getUser()->getId());
177
178 return $this->get('wallabag_core.helper.entries_export')
179 ->setEntries($entry)
180 ->updateTitle('entry')
181 ->exportAs($request->attributes->get('_format'));
182 }
183
184 /**
161 * Create an entry. 185 * Create an entry.
162 * 186 *
163 * @ApiDoc( 187 * @ApiDoc(
@@ -496,6 +520,104 @@ class WallabagRestController extends FOSRestController
496 } 520 }
497 521
498 /** 522 /**
523 * Retrieve annotations for an entry.
524 *
525 * @ApiDoc(
526 * requirements={
527 * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
528 * }
529 * )
530 *
531 * @param Entry $entry
532 *
533 * @return JsonResponse
534 */
535 public function getAnnotationsAction(Entry $entry)
536 {
537 $this->validateAuthentication();
538
539 return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:getAnnotations', [
540 'entry' => $entry,
541 ]);
542 }
543
544 /**
545 * Creates a new annotation.
546 *
547 * @ApiDoc(
548 * requirements={
549 * {"name"="ranges", "dataType"="array", "requirement"="\w+", "description"="The range array for the annotation"},
550 * {"name"="quote", "dataType"="string", "required"=false, "description"="Optional, quote for the annotation"},
551 * {"name"="text", "dataType"="string", "required"=true, "description"=""},
552 * }
553 * )
554 *
555 * @param Request $request
556 * @param Entry $entry
557 *
558 * @return JsonResponse
559 */
560 public function postAnnotationAction(Request $request, Entry $entry)
561 {
562 $this->validateAuthentication();
563
564 return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:postAnnotation', [
565 'request' => $request,
566 'entry' => $entry,
567 ]);
568 }
569
570 /**
571 * Updates an annotation.
572 *
573 * @ApiDoc(
574 * requirements={
575 * {"name"="annotation", "dataType"="string", "requirement"="\w+", "description"="The annotation ID"}
576 * }
577 * )
578 *
579 * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation")
580 *
581 * @param Annotation $annotation
582 * @param Request $request
583 *
584 * @return JsonResponse
585 */
586 public function putAnnotationAction(Annotation $annotation, Request $request)
587 {
588 $this->validateAuthentication();
589
590 return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:putAnnotation', [
591 'annotation' => $annotation,
592 'request' => $request,
593 ]);
594 }
595
596 /**
597 * Removes an annotation.
598 *
599 * @ApiDoc(
600 * requirements={
601 * {"name"="annotation", "dataType"="string", "requirement"="\w+", "description"="The annotation ID"}
602 * }
603 * )
604 *
605 * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation")
606 *
607 * @param Annotation $annotation
608 *
609 * @return JsonResponse
610 */
611 public function deleteAnnotationAction(Annotation $annotation)
612 {
613 $this->validateAuthentication();
614
615 return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:deleteAnnotation', [
616 'annotation' => $annotation,
617 ]);
618 }
619
620 /**
499 * Retrieve version number. 621 * Retrieve version number.
500 * 622 *
501 * @ApiDoc() 623 * @ApiDoc()
diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
index 5f43f971..35f8b2c1 100644
--- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
+++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
@@ -1,4 +1,4 @@
1entries: 1api:
2 type: rest 2 type: rest
3 resource: "WallabagApiBundle:WallabagRest" 3 resource: "WallabagApiBundle:WallabagRest"
4 name_prefix: api_ 4 name_prefix: api_
diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php
index 857a8b4c..277f8524 100644
--- a/src/Wallabag/CoreBundle/Command/InstallCommand.php
+++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php
@@ -40,7 +40,7 @@ class InstallCommand extends ContainerAwareCommand
40 { 40 {
41 $this 41 $this
42 ->setName('wallabag:install') 42 ->setName('wallabag:install')
43 ->setDescription('Wallabag installer.') 43 ->setDescription('wallabag installer.')
44 ->addOption( 44 ->addOption(
45 'reset', 45 'reset',
46 null, 46 null,
@@ -55,7 +55,7 @@ class InstallCommand extends ContainerAwareCommand
55 $this->defaultInput = $input; 55 $this->defaultInput = $input;
56 $this->defaultOutput = $output; 56 $this->defaultOutput = $output;
57 57
58 $output->writeln('<info>Installing Wallabag...</info>'); 58 $output->writeln('<info>Installing wallabag...</info>');
59 $output->writeln(''); 59 $output->writeln('');
60 60
61 $this 61 $this
@@ -65,7 +65,7 @@ class InstallCommand extends ContainerAwareCommand
65 ->setupConfig() 65 ->setupConfig()
66 ; 66 ;
67 67
68 $output->writeln('<info>Wallabag has been successfully installed.</info>'); 68 $output->writeln('<info>wallabag has been successfully installed.</info>');
69 $output->writeln('<comment>Just execute `php bin/console server:run --env=prod` for using wallabag: http://localhost:8000</comment>'); 69 $output->writeln('<comment>Just execute `php bin/console server:run --env=prod` for using wallabag: http://localhost:8000</comment>');
70 } 70 }
71 71
@@ -77,7 +77,7 @@ class InstallCommand extends ContainerAwareCommand
77 77
78 // testing if database driver exists 78 // testing if database driver exists
79 $fulfilled = true; 79 $fulfilled = true;
80 $label = '<comment>PDO Driver</comment>'; 80 $label = '<comment>PDO Driver (%s)</comment>';
81 $status = '<info>OK!</info>'; 81 $status = '<info>OK!</info>';
82 $help = ''; 82 $help = '';
83 83
@@ -87,7 +87,7 @@ class InstallCommand extends ContainerAwareCommand
87 $help = 'Database driver "'.$this->getContainer()->getParameter('database_driver').'" is not installed.'; 87 $help = 'Database driver "'.$this->getContainer()->getParameter('database_driver').'" is not installed.';
88 } 88 }
89 89
90 $rows[] = [$label, $status, $help]; 90 $rows[] = [sprintf($label, $this->getContainer()->getParameter('database_driver')), $status, $help];
91 91
92 // testing if connection to the database can be etablished 92 // testing if connection to the database can be etablished
93 $label = '<comment>Database connection</comment>'; 93 $label = '<comment>Database connection</comment>';
@@ -95,7 +95,8 @@ class InstallCommand extends ContainerAwareCommand
95 $help = ''; 95 $help = '';
96 96
97 try { 97 try {
98 $this->getContainer()->get('doctrine')->getManager()->getConnection()->connect(); 98 $conn = $this->getContainer()->get('doctrine')->getManager()->getConnection();
99 $conn->connect();
99 } catch (\Exception $e) { 100 } catch (\Exception $e) {
100 if (false === strpos($e->getMessage(), 'Unknown database') 101 if (false === strpos($e->getMessage(), 'Unknown database')
101 && false === strpos($e->getMessage(), 'database "'.$this->getContainer()->getParameter('database_name').'" does not exist')) { 102 && false === strpos($e->getMessage(), 'database "'.$this->getContainer()->getParameter('database_name').'" does not exist')) {
@@ -107,6 +108,21 @@ class InstallCommand extends ContainerAwareCommand
107 108
108 $rows[] = [$label, $status, $help]; 109 $rows[] = [$label, $status, $help];
109 110
111 // now check if MySQL isn't too old to handle utf8mb4
112 if ($conn->isConnected() && $conn->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\MySqlPlatform) {
113 $version = $conn->query('select version()')->fetchColumn();
114 $minimalVersion = '5.5.4';
115
116 if (false === version_compare($version, $minimalVersion, '>')) {
117 $fulfilled = false;
118 $rows[] = [
119 '<comment>Database version</comment>',
120 '<error>ERROR!</error>',
121 'Your MySQL version ('.$version.') is too old, consider upgrading ('.$minimalVersion.'+).',
122 ];
123 }
124 }
125
110 foreach ($this->functionExists as $functionRequired) { 126 foreach ($this->functionExists as $functionRequired) {
111 $label = '<comment>'.$functionRequired.'</comment>'; 127 $label = '<comment>'.$functionRequired.'</comment>';
112 $status = '<info>OK!</info>'; 128 $status = '<info>OK!</info>';
@@ -131,7 +147,7 @@ class InstallCommand extends ContainerAwareCommand
131 throw new \RuntimeException('Some system requirements are not fulfilled. Please check output messages and fix them.'); 147 throw new \RuntimeException('Some system requirements are not fulfilled. Please check output messages and fix them.');
132 } 148 }
133 149
134 $this->defaultOutput->writeln('<info>Success! Your system can run Wallabag properly.</info>'); 150 $this->defaultOutput->writeln('<info>Success! Your system can run wallabag properly.</info>');
135 151
136 $this->defaultOutput->writeln(''); 152 $this->defaultOutput->writeln('');
137 153
diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php
index 91cdcae5..8d391917 100644
--- a/src/Wallabag/CoreBundle/Controller/ConfigController.php
+++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php
@@ -7,6 +7,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
7use Symfony\Component\HttpFoundation\JsonResponse; 7use Symfony\Component\HttpFoundation\JsonResponse;
8use Symfony\Component\HttpFoundation\RedirectResponse; 8use Symfony\Component\HttpFoundation\RedirectResponse;
9use Symfony\Component\HttpFoundation\Request; 9use Symfony\Component\HttpFoundation\Request;
10use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
10use Wallabag\CoreBundle\Entity\Config; 11use Wallabag\CoreBundle\Entity\Config;
11use Wallabag\CoreBundle\Entity\TaggingRule; 12use Wallabag\CoreBundle\Entity\TaggingRule;
12use Wallabag\CoreBundle\Form\Type\ConfigType; 13use Wallabag\CoreBundle\Form\Type\ConfigType;
@@ -148,6 +149,9 @@ class ConfigController extends Controller
148 'token' => $config->getRssToken(), 149 'token' => $config->getRssToken(),
149 ], 150 ],
150 'twofactor_auth' => $this->getParameter('twofactor_auth'), 151 'twofactor_auth' => $this->getParameter('twofactor_auth'),
152 'enabled_users' => $this->getDoctrine()
153 ->getRepository('WallabagUserBundle:User')
154 ->getSumEnabledUsers(),
151 ]); 155 ]);
152 } 156 }
153 157
@@ -221,6 +225,80 @@ class ConfigController extends Controller
221 } 225 }
222 226
223 /** 227 /**
228 * Remove all annotations OR tags OR entries for the current user.
229 *
230 * @Route("/reset/{type}", requirements={"id" = "annotations|tags|entries"}, name="config_reset")
231 *
232 * @return RedirectResponse
233 */
234 public function resetAction($type)
235 {
236 $em = $this->getDoctrine()->getManager();
237
238 switch ($type) {
239 case 'annotations':
240 $this->getDoctrine()
241 ->getRepository('WallabagAnnotationBundle:Annotation')
242 ->removeAllByUserId($this->getUser()->getId());
243 break;
244
245 case 'tags':
246 $this->removeAllTagsByUserId($this->getUser()->getId());
247 break;
248
249 case 'entries':
250 // SQLite doesn't care about cascading remove, so we need to manually remove associated stuf
251 // otherwise they won't be removed ...
252 if ($this->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) {
253 $this->getDoctrine()->getRepository('WallabagAnnotationBundle:Annotation')->removeAllByUserId($this->getUser()->getId());
254 }
255
256 // manually remove tags to avoid orphan tag
257 $this->removeAllTagsByUserId($this->getUser()->getId());
258
259 $this->getDoctrine()
260 ->getRepository('WallabagCoreBundle:Entry')
261 ->removeAllByUserId($this->getUser()->getId());
262 }
263
264 $this->get('session')->getFlashBag()->add(
265 'notice',
266 'flashes.config.notice.'.$type.'_reset'
267 );
268
269 return $this->redirect($this->generateUrl('config').'#set3');
270 }
271
272 /**
273 * Remove all tags for a given user and cleanup orphan tags.
274 *
275 * @param int $userId
276 */
277 private function removeAllTagsByUserId($userId)
278 {
279 $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findAllTags($userId);
280
281 if (empty($tags)) {
282 return;
283 }
284
285 $this->getDoctrine()
286 ->getRepository('WallabagCoreBundle:Entry')
287 ->removeTags($userId, $tags);
288
289 // cleanup orphan tags
290 $em = $this->getDoctrine()->getManager();
291
292 foreach ($tags as $tag) {
293 if (count($tag->getEntries()) === 0) {
294 $em->remove($tag);
295 }
296 }
297
298 $em->flush();
299 }
300
301 /**
224 * Validate that a rule can be edited/deleted by the current user. 302 * Validate that a rule can be edited/deleted by the current user.
225 * 303 *
226 * @param TaggingRule $rule 304 * @param TaggingRule $rule
@@ -251,4 +329,37 @@ class ConfigController extends Controller
251 329
252 return $config; 330 return $config;
253 } 331 }
332
333 /**
334 * Delete account for current user.
335 *
336 * @Route("/account/delete", name="delete_account")
337 *
338 * @param Request $request
339 *
340 * @throws AccessDeniedHttpException
341 *
342 * @return \Symfony\Component\HttpFoundation\RedirectResponse
343 */
344 public function deleteAccountAction(Request $request)
345 {
346 $enabledUsers = $this->getDoctrine()
347 ->getRepository('WallabagUserBundle:User')
348 ->getSumEnabledUsers();
349
350 if ($enabledUsers <= 1) {
351 throw new AccessDeniedHttpException();
352 }
353
354 $user = $this->getUser();
355
356 // logout current user
357 $this->get('security.token_storage')->setToken(null);
358 $request->getSession()->invalidate();
359
360 $em = $this->get('fos_user.user_manager');
361 $em->deleteUser($user);
362
363 return $this->redirect($this->generateUrl('fos_user_security_login'));
364 }
254} 365}
diff --git a/src/Wallabag/CoreBundle/Controller/TagController.php b/src/Wallabag/CoreBundle/Controller/TagController.php
index 5acc6852..4542d484 100644
--- a/src/Wallabag/CoreBundle/Controller/TagController.php
+++ b/src/Wallabag/CoreBundle/Controller/TagController.php
@@ -90,15 +90,15 @@ class TagController extends Controller
90 90
91 $flatTags = []; 91 $flatTags = [];
92 92
93 foreach ($tags as $key => $tag) { 93 foreach ($tags as $tag) {
94 $nbEntries = $this->getDoctrine() 94 $nbEntries = $this->getDoctrine()
95 ->getRepository('WallabagCoreBundle:Entry') 95 ->getRepository('WallabagCoreBundle:Entry')
96 ->countAllEntriesByUserIdAndTagId($this->getUser()->getId(), $tag['id']); 96 ->countAllEntriesByUserIdAndTagId($this->getUser()->getId(), $tag->getId());
97 97
98 $flatTags[] = [ 98 $flatTags[] = [
99 'id' => $tag['id'], 99 'id' => $tag->getId(),
100 'label' => $tag['label'], 100 'label' => $tag->getLabel(),
101 'slug' => $tag['slug'], 101 'slug' => $tag->getSlug(),
102 'nbEntries' => $nbEntries, 102 'nbEntries' => $nbEntries,
103 ]; 103 ];
104 } 104 }
diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php
index f2da3f4d..dd0f7e67 100644
--- a/src/Wallabag/CoreBundle/Entity/Entry.php
+++ b/src/Wallabag/CoreBundle/Entity/Entry.php
@@ -19,7 +19,7 @@ use Wallabag\AnnotationBundle\Entity\Annotation;
19 * 19 *
20 * @XmlRoot("entry") 20 * @XmlRoot("entry")
21 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\EntryRepository") 21 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\EntryRepository")
22 * @ORM\Table(name="`entry`") 22 * @ORM\Table(name="`entry`", options={"collate"="utf8mb4_unicode_ci", "charset"="utf8mb4"})
23 * @ORM\HasLifecycleCallbacks() 23 * @ORM\HasLifecycleCallbacks()
24 * @Hateoas\Relation("self", href = "expr('/api/entries/' ~ object.getId())") 24 * @Hateoas\Relation("self", href = "expr('/api/entries/' ~ object.getId())")
25 */ 25 */
@@ -190,10 +190,10 @@ class Entry
190 * @ORM\JoinTable( 190 * @ORM\JoinTable(
191 * name="entry_tag", 191 * name="entry_tag",
192 * joinColumns={ 192 * joinColumns={
193 * @ORM\JoinColumn(name="entry_id", referencedColumnName="id") 193 * @ORM\JoinColumn(name="entry_id", referencedColumnName="id", onDelete="cascade")
194 * }, 194 * },
195 * inverseJoinColumns={ 195 * inverseJoinColumns={
196 * @ORM\JoinColumn(name="tag_id", referencedColumnName="id") 196 * @ORM\JoinColumn(name="tag_id", referencedColumnName="id", onDelete="cascade")
197 * } 197 * }
198 * ) 198 * )
199 */ 199 */
diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php
index cd2b47b9..14616d88 100644
--- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php
+++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php
@@ -329,4 +329,18 @@ class EntryRepository extends EntityRepository
329 329
330 return $qb->getQuery()->getSingleScalarResult(); 330 return $qb->getQuery()->getSingleScalarResult();
331 } 331 }
332
333 /**
334 * Remove all entries for a user id.
335 * Used when a user want to reset all informations.
336 *
337 * @param int $userId
338 */
339 public function removeAllByUserId($userId)
340 {
341 $this->getEntityManager()
342 ->createQuery('DELETE FROM Wallabag\CoreBundle\Entity\Entry e WHERE e.user = :userId')
343 ->setParameter('userId', $userId)
344 ->execute();
345 }
332} 346}
diff --git a/src/Wallabag/CoreBundle/Repository/TagRepository.php b/src/Wallabag/CoreBundle/Repository/TagRepository.php
index e76878d4..81445989 100644
--- a/src/Wallabag/CoreBundle/Repository/TagRepository.php
+++ b/src/Wallabag/CoreBundle/Repository/TagRepository.php
@@ -34,6 +34,9 @@ class TagRepository extends EntityRepository
34 34
35 /** 35 /**
36 * Find all tags per user. 36 * Find all tags per user.
37 * Instead of just left joined on the Entry table, we select only id and group by id to avoid tag multiplication in results.
38 * Once we have all tags id, we can safely request them one by one.
39 * This'll still be fastest than the previous query.
37 * 40 *
38 * @param int $userId 41 * @param int $userId
39 * 42 *
@@ -41,15 +44,20 @@ class TagRepository extends EntityRepository
41 */ 44 */
42 public function findAllTags($userId) 45 public function findAllTags($userId)
43 { 46 {
44 return $this->createQueryBuilder('t') 47 $ids = $this->createQueryBuilder('t')
45 ->select('t.slug', 't.label', 't.id') 48 ->select('t.id')
46 ->leftJoin('t.entries', 'e') 49 ->leftJoin('t.entries', 'e')
47 ->where('e.user = :userId')->setParameter('userId', $userId) 50 ->where('e.user = :userId')->setParameter('userId', $userId)
48 ->groupBy('t.slug') 51 ->groupBy('t.id')
49 ->addGroupBy('t.label')
50 ->addGroupBy('t.id')
51 ->getQuery() 52 ->getQuery()
52 ->getArrayResult(); 53 ->getArrayResult();
54
55 $tags = [];
56 foreach ($ids as $id) {
57 $tags[] = $this->find($id);
58 }
59
60 return $tags;
53 } 61 }
54 62
55 /** 63 /**
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml
index 614488a6..cc5f9e9a 100644
--- a/src/Wallabag/CoreBundle/Resources/config/services.yml
+++ b/src/Wallabag/CoreBundle/Resources/config/services.yml
@@ -129,3 +129,10 @@ services:
129 arguments: 129 arguments:
130 - '@twig' 130 - '@twig'
131 - '%kernel.debug%' 131 - '%kernel.debug%'
132
133 wallabag_core.subscriber.sqlite_cascade_delete:
134 class: Wallabag\CoreBundle\Subscriber\SQLiteCascadeDeleteSubscriber
135 arguments:
136 - "@doctrine"
137 tags:
138 - { name: doctrine.event_subscriber }
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
index 714ced14..c0595583 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
@@ -88,6 +88,18 @@ config:
88 name_label: 'Navn' 88 name_label: 'Navn'
89 email_label: 'Emailadresse' 89 email_label: 'Emailadresse'
90 # twoFactorAuthentication_label: 'Two factor authentication' 90 # twoFactorAuthentication_label: 'Two factor authentication'
91 delete:
92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
91 form_password: 103 form_password:
92 old_password_label: 'Gammel adgangskode' 104 old_password_label: 'Gammel adgangskode'
93 new_password_label: 'Ny adgangskode' 105 new_password_label: 'Ny adgangskode'
@@ -460,6 +472,9 @@ flashes:
460 # tagging_rules_deleted: 'Tagging rule deleted' 472 # tagging_rules_deleted: 'Tagging rule deleted'
461 # user_added: 'User "%username%" added' 473 # user_added: 'User "%username%" added'
462 # rss_token_updated: 'RSS token updated' 474 # rss_token_updated: 'RSS token updated'
475 # annotations_reset: Annotations reset
476 # tags_reset: Tags reset
477 # entries_reset: Entries reset
463 entry: 478 entry:
464 notice: 479 notice:
465 # entry_already_saved: 'Entry already saved on %date%' 480 # entry_already_saved: 'Entry already saved on %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
index 57e49f84..0051da2f 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
@@ -88,6 +88,18 @@ config:
88 name_label: 'Name' 88 name_label: 'Name'
89 email_label: 'E-Mail-Adresse' 89 email_label: 'E-Mail-Adresse'
90 twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung' 90 twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung'
91 delete:
92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
91 form_password: 103 form_password:
92 old_password_label: 'Altes Kennwort' 104 old_password_label: 'Altes Kennwort'
93 new_password_label: 'Neues Kennwort' 105 new_password_label: 'Neues Kennwort'
@@ -460,6 +472,9 @@ flashes:
460 tagging_rules_deleted: 'Tagging-Regel gelöscht' 472 tagging_rules_deleted: 'Tagging-Regel gelöscht'
461 user_added: 'Benutzer "%username%" erstellt' 473 user_added: 'Benutzer "%username%" erstellt'
462 rss_token_updated: 'RSS-Token aktualisiert' 474 rss_token_updated: 'RSS-Token aktualisiert'
475 # annotations_reset: Annotations reset
476 # tags_reset: Tags reset
477 # entries_reset: Entries reset
463 entry: 478 entry:
464 notice: 479 notice:
465 entry_already_saved: 'Eintrag bereits am %date% gespeichert' 480 entry_already_saved: 'Eintrag bereits am %date% gespeichert'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
index 4a59c75e..462be556 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
@@ -88,6 +88,18 @@ config:
88 name_label: 'Name' 88 name_label: 'Name'
89 email_label: 'Email' 89 email_label: 'Email'
90 twoFactorAuthentication_label: 'Two factor authentication' 90 twoFactorAuthentication_label: 'Two factor authentication'
91 delete:
92 title: Delete my account (a.k.a danger zone)
93 description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 button: Delete my account
96 reset:
97 title: Reset area (a.k.a danger zone)
98 description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 annotations: Remove ALL annotations
100 tags: Remove ALL tags
101 entries: Remove ALL entries
102 confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
91 form_password: 103 form_password:
92 old_password_label: 'Current password' 104 old_password_label: 'Current password'
93 new_password_label: 'New password' 105 new_password_label: 'New password'
@@ -459,6 +471,9 @@ flashes:
459 tagging_rules_updated: 'Tagging rules updated' 471 tagging_rules_updated: 'Tagging rules updated'
460 tagging_rules_deleted: 'Tagging rule deleted' 472 tagging_rules_deleted: 'Tagging rule deleted'
461 rss_token_updated: 'RSS token updated' 473 rss_token_updated: 'RSS token updated'
474 annotations_reset: Annotations reset
475 tags_reset: Tags reset
476 entries_reset: Entries reset
462 entry: 477 entry:
463 notice: 478 notice:
464 entry_already_saved: 'Entry already saved on %date%' 479 entry_already_saved: 'Entry already saved on %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
index 1b1e0cb1..cfabe09f 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
@@ -88,6 +88,18 @@ config:
88 name_label: 'Nombre' 88 name_label: 'Nombre'
89 email_label: 'Direccion e-mail' 89 email_label: 'Direccion e-mail'
90 twoFactorAuthentication_label: 'Autentificación de dos factores' 90 twoFactorAuthentication_label: 'Autentificación de dos factores'
91 delete:
92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
91 form_password: 103 form_password:
92 old_password_label: 'Contraseña actual' 104 old_password_label: 'Contraseña actual'
93 new_password_label: 'Nueva contraseña' 105 new_password_label: 'Nueva contraseña'
@@ -460,6 +472,9 @@ flashes:
460 tagging_rules_deleted: 'Regla de etiquetado actualizada' 472 tagging_rules_deleted: 'Regla de etiquetado actualizada'
461 user_added: 'Usuario "%username%" añadido' 473 user_added: 'Usuario "%username%" añadido'
462 rss_token_updated: 'RSS token actualizado' 474 rss_token_updated: 'RSS token actualizado'
475 # annotations_reset: Annotations reset
476 # tags_reset: Tags reset
477 # entries_reset: Entries reset
463 entry: 478 entry:
464 notice: 479 notice:
465 entry_already_saved: 'Entrada ya guardada por %fecha%' 480 entry_already_saved: 'Entrada ya guardada por %fecha%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
index 41dc8acf..07b5bee7 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
@@ -88,6 +88,18 @@ config:
88 name_label: 'نام' 88 name_label: 'نام'
89 email_label: 'نشانی ایمیل' 89 email_label: 'نشانی ایمیل'
90 twoFactorAuthentication_label: 'تأیید ۲مرحله‌ای' 90 twoFactorAuthentication_label: 'تأیید ۲مرحله‌ای'
91 delete:
92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
91 form_password: 103 form_password:
92 old_password_label: 'رمز قدیمی' 104 old_password_label: 'رمز قدیمی'
93 new_password_label: 'رمز تازه' 105 new_password_label: 'رمز تازه'
@@ -459,6 +471,9 @@ flashes:
459 tagging_rules_deleted: 'قانون برچسب‌گذاری پاک شد' 471 tagging_rules_deleted: 'قانون برچسب‌گذاری پاک شد'
460 user_added: 'کابر "%username%" افزوده شد' 472 user_added: 'کابر "%username%" افزوده شد'
461 rss_token_updated: 'کد آر-اس-اس به‌روز شد' 473 rss_token_updated: 'کد آر-اس-اس به‌روز شد'
474 # annotations_reset: Annotations reset
475 # tags_reset: Tags reset
476 # entries_reset: Entries reset
462 entry: 477 entry:
463 notice: 478 notice:
464 entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود' 479 entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index 7fb9681d..db6f9f7e 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -88,6 +88,18 @@ config:
88 name_label: 'Nom' 88 name_label: 'Nom'
89 email_label: 'Adresse e-mail' 89 email_label: 'Adresse e-mail'
90 twoFactorAuthentication_label: 'Double authentification' 90 twoFactorAuthentication_label: 'Double authentification'
91 delete:
92 title: Supprimer mon compte (attention danger !)
93 description: Si vous confirmez la suppression de votre compte, TOUS les articles, TOUS les tags, TOUTES les annotations et votre compte seront DÉFINITIVEMENT supprimé (c'est IRRÉVERSIBLE). Vous serez ensuite déconnecté.
94 confirm: Vous êtes vraiment sûr ? (C'EST IRRÉVERSIBLE)
95 button: 'Supprimer mon compte'
96 reset:
97 title: Réinitialisation (attention danger !)
98 description: En cliquant sur les boutons ci-dessous vous avez la possibilité de supprimer certaines informations de votre compte. Attention, ces actions sont IRRÉVERSIBLES !
99 annotations: Supprimer TOUTES les annotations
100 tags: Supprimer TOUS les tags
101 entries: Supprimer TOUS les articles
102 confirm: Êtes-vous vraiment vraiment sûr ? (C'EST IRRÉVERSIBLE)
91 form_password: 103 form_password:
92 old_password_label: 'Mot de passe actuel' 104 old_password_label: 'Mot de passe actuel'
93 new_password_label: 'Nouveau mot de passe' 105 new_password_label: 'Nouveau mot de passe'
@@ -386,7 +398,7 @@ developer:
386 field_grant_types: 'Type de privilège accordé' 398 field_grant_types: 'Type de privilège accordé'
387 no_client: 'Aucun client pour le moment' 399 no_client: 'Aucun client pour le moment'
388 remove: 400 remove:
389 warn_message_1: 'Vous avez la possibilité de supprimer le client %name%. Cette action est IRREVERSIBLE !' 401 warn_message_1: 'Vous avez la possibilité de supprimer le client %name%. Cette action est IRRÉVERSIBLE !'
390 warn_message_2: "Si vous supprimez le client %name%, toutes les applications qui l'utilisaient ne fonctionneront plus avec votre compte wallabag." 402 warn_message_2: "Si vous supprimez le client %name%, toutes les applications qui l'utilisaient ne fonctionneront plus avec votre compte wallabag."
391 action: 'Supprimer le client %name%' 403 action: 'Supprimer le client %name%'
392 client: 404 client:
@@ -460,9 +472,12 @@ flashes:
460 tagging_rules_deleted: 'Règle supprimée' 472 tagging_rules_deleted: 'Règle supprimée'
461 user_added: 'Utilisateur "%username%" ajouté' 473 user_added: 'Utilisateur "%username%" ajouté'
462 rss_token_updated: 'Jeton RSS mis à jour' 474 rss_token_updated: 'Jeton RSS mis à jour'
475 annotations_reset: Annotations supprimées
476 tags_reset: Tags supprimés
477 entries_reset: Articles supprimés
463 entry: 478 entry:
464 notice: 479 notice:
465 entry_already_saved: 'Article déjà sauvergardé le %date%' 480 entry_already_saved: 'Article déjà sauvegardé le %date%'
466 entry_saved: 'Article enregistré' 481 entry_saved: 'Article enregistré'
467 entry_saved_failed: 'Article enregistré mais impossible de récupérer le contenu' 482 entry_saved_failed: 'Article enregistré mais impossible de récupérer le contenu'
468 entry_updated: 'Article mis à jour' 483 entry_updated: 'Article mis à jour'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
index b279ae40..f1aff51a 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
@@ -88,6 +88,18 @@ config:
88 name_label: 'Nome' 88 name_label: 'Nome'
89 email_label: 'E-mail' 89 email_label: 'E-mail'
90 twoFactorAuthentication_label: 'Two factor authentication' 90 twoFactorAuthentication_label: 'Two factor authentication'
91 delete:
92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
91 form_password: 103 form_password:
92 old_password_label: 'Password corrente' 104 old_password_label: 'Password corrente'
93 new_password_label: 'Nuova password' 105 new_password_label: 'Nuova password'
@@ -460,6 +472,9 @@ flashes:
460 tagging_rules_deleted: 'Regola di tagging aggiornate' 472 tagging_rules_deleted: 'Regola di tagging aggiornate'
461 user_added: 'Utente "%username%" aggiunto' 473 user_added: 'Utente "%username%" aggiunto'
462 rss_token_updated: 'RSS token aggiornato' 474 rss_token_updated: 'RSS token aggiornato'
475 # annotations_reset: Annotations reset
476 # tags_reset: Tags reset
477 # entries_reset: Entries reset
463 entry: 478 entry:
464 notice: 479 notice:
465 entry_already_saved: 'Contenuto già salvato in data %date%' 480 entry_already_saved: 'Contenuto già salvato in data %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
index a4659620..e0567d7e 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
@@ -25,13 +25,13 @@ menu:
25 internal_settings: 'Configuracion interna' 25 internal_settings: 'Configuracion interna'
26 import: 'Importar' 26 import: 'Importar'
27 howto: 'Ajuda' 27 howto: 'Ajuda'
28 developer: 'Desvolopador' 28 developer: 'Desvolopaire'
29 logout: 'Desconnexion' 29 logout: 'Desconnexion'
30 about: 'A prepaus' 30 about: 'A prepaus'
31 search: 'Cercar' 31 search: 'Cercar'
32 save_link: 'Enregistrar un novèl article' 32 save_link: 'Enregistrar un novèl article'
33 back_to_unread: 'Tornar als articles pas legits' 33 back_to_unread: 'Tornar als articles pas legits'
34 # users_management: 'Users management' 34 users_management: 'Gestion dels utilizaires'
35 top: 35 top:
36 add_new_entry: 'Enregistrar un novèl article' 36 add_new_entry: 'Enregistrar un novèl article'
37 search: 'Cercar' 37 search: 'Cercar'
@@ -46,7 +46,7 @@ footer:
46 social: 'Social' 46 social: 'Social'
47 powered_by: 'propulsat per' 47 powered_by: 'propulsat per'
48 about: 'A prepaus' 48 about: 'A prepaus'
49 # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day! 49 stats: "Dempuèi %user_creation% avètz legit %nb_archives% articles. Es a l'entorn de %per_day% per jorn !"
50 50
51config: 51config:
52 page_title: 'Configuracion' 52 page_title: 'Configuracion'
@@ -88,6 +88,18 @@ config:
88 name_label: 'Nom' 88 name_label: 'Nom'
89 email_label: 'Adreça de corrièl' 89 email_label: 'Adreça de corrièl'
90 twoFactorAuthentication_label: 'Dobla autentificacion' 90 twoFactorAuthentication_label: 'Dobla autentificacion'
91 delete:
92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
91 form_password: 103 form_password:
92 old_password_label: 'Senhal actual' 104 old_password_label: 'Senhal actual'
93 new_password_label: 'Senhal novèl' 105 new_password_label: 'Senhal novèl'
@@ -96,7 +108,7 @@ config:
96 if_label: 'se' 108 if_label: 'se'
97 then_tag_as_label: 'alara atribuir las etiquetas' 109 then_tag_as_label: 'alara atribuir las etiquetas'
98 delete_rule_label: 'suprimir' 110 delete_rule_label: 'suprimir'
99 # edit_rule_label: 'edit' 111 edit_rule_label: 'modificar'
100 rule_label: 'Règla' 112 rule_label: 'Règla'
101 tags_label: 'Etiquetas' 113 tags_label: 'Etiquetas'
102 faq: 114 faq:
@@ -209,7 +221,7 @@ entry:
209 is_public_label: 'Public' 221 is_public_label: 'Public'
210 save_label: 'Enregistrar' 222 save_label: 'Enregistrar'
211 public: 223 public:
212 # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" 224 shared_by_wallabag: "Aqueste article es estat partejat per <a href='%wallabag_instance%'>wallabag</a>"
213 225
214about: 226about:
215 page_title: 'A prepaus' 227 page_title: 'A prepaus'
@@ -265,14 +277,14 @@ howto:
265 277
266quickstart: 278quickstart:
267 page_title: 'Per ben començar' 279 page_title: 'Per ben començar'
268 # more: 'More…' 280 more: 'Mai…'
269 intro: 281 intro:
270 title: 'Benvenguda sus wallabag !' 282 title: 'Benvenguda sus wallabag !'
271 paragraph_1: "Anem vos guidar per far lo torn de la proprietat e vos presentar unas fonccionalitats que vos poirián interessar per vos apropriar aquesta aisina." 283 paragraph_1: "Anem vos guidar per far lo torn de la proprietat e vos presentar unas fonccionalitats que vos poirián interessar per vos apropriar aquesta aisina."
272 paragraph_2: 'Seguètz-nos ' 284 paragraph_2: 'Seguètz-nos '
273 configure: 285 configure:
274 title: "Configuratz l'aplicacio" 286 title: "Configuratz l'aplicacion"
275 # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' 287 description: "Per fin d'aver una aplicacion que vos va ben, anatz veire la configuracion de wallabag."
276 language: "Cambiatz la lenga e l'estil de l'aplicacion" 288 language: "Cambiatz la lenga e l'estil de l'aplicacion"
277 rss: 'Activatz los fluxes RSS' 289 rss: 'Activatz los fluxes RSS'
278 tagging_rules: 'Escrivètz de règlas per classar automaticament vòstres articles' 290 tagging_rules: 'Escrivètz de règlas per classar automaticament vòstres articles'
@@ -286,7 +298,7 @@ quickstart:
286 import: 'Configurar los impòrt' 298 import: 'Configurar los impòrt'
287 first_steps: 299 first_steps:
288 title: 'Primièrs passes' 300 title: 'Primièrs passes'
289 # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link." 301 description: "Ara wallabag es ben configurat, es lo moment d'archivar lo web. Podètz clicar sul signe + a man drecha amont per ajustar un ligam."
290 new_article: 'Ajustatz vòstre primièr article' 302 new_article: 'Ajustatz vòstre primièr article'
291 unread_articles: 'E racaptatz-lo !' 303 unread_articles: 'E racaptatz-lo !'
292 migrate: 304 migrate:
@@ -298,14 +310,14 @@ quickstart:
298 readability: 'Migrar dempuèi Readability' 310 readability: 'Migrar dempuèi Readability'
299 instapaper: 'Migrar dempuèi Instapaper' 311 instapaper: 'Migrar dempuèi Instapaper'
300 developer: 312 developer:
301 title: 'Pels desvolopadors' 313 title: 'Pels desvolopaires'
302 # description: 'We also thought to the developers: Docker, API, translations, etc.' 314 description: 'Avèm tanben pensat als desvolopaires : Docker, API, traduccions, etc.'
303 create_application: 'Crear vòstra aplicacion tèrça' 315 create_application: 'Crear vòstra aplicacion tèrça'
304 # use_docker: 'Use Docker to install wallabag' 316 use_docker: 'Utilizar Docker per installar wallabag'
305 docs: 317 docs:
306 title: 'Documentacion complèta' 318 title: 'Documentacion complèta'
307 # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them." 319 description: "I a un fum de fonccionalitats dins wallabag. Esitetz pas a legir lo manual per las conéisser e aprendre a las utilizar."
308 annotate: 'Anotatar vòstre article' 320 annotate: 'Anotar vòstre article'
309 export: 'Convertissètz vòstres articles en ePub o en PDF' 321 export: 'Convertissètz vòstres articles en ePub o en PDF'
310 search_filters: "Aprenètz a utilizar lo motor de recèrca e los filtres per retrobar l'article que vos interèssa" 322 search_filters: "Aprenètz a utilizar lo motor de recèrca e los filtres per retrobar l'article que vos interèssa"
311 fetching_errors: "Qué far se mon article es pas recuperat coma cal ?" 323 fetching_errors: "Qué far se mon article es pas recuperat coma cal ?"
@@ -390,7 +402,7 @@ developer:
390 warn_message_2: "Se suprimissètz un client, totas las aplicacions que l'emplegan foncionaràn pas mai amb vòstre compte wallabag." 402 warn_message_2: "Se suprimissètz un client, totas las aplicacions que l'emplegan foncionaràn pas mai amb vòstre compte wallabag."
391 action: 'Suprimir aqueste client' 403 action: 'Suprimir aqueste client'
392 client: 404 client:
393 page_title: 'Desvlopador > Novèl client' 405 page_title: 'Desvolopaire > Novèl client'
394 page_description: "Anatz crear un novèl client. Mercés de cumplir l'url de redireccion cap a vòstra aplicacion." 406 page_description: "Anatz crear un novèl client. Mercés de cumplir l'url de redireccion cap a vòstra aplicacion."
395 form: 407 form:
396 name_label: "Nom del client" 408 name_label: "Nom del client"
@@ -398,7 +410,7 @@ developer:
398 save_label: 'Crear un novèl client' 410 save_label: 'Crear un novèl client'
399 action_back: 'Retorn' 411 action_back: 'Retorn'
400 client_parameter: 412 client_parameter:
401 page_title: 'Desvolopador > Los paramètres de vòstre client' 413 page_title: 'Desvolopaire > Los paramètres de vòstre client'
402 page_description: 'Vaquí los paramètres de vòstre client' 414 page_description: 'Vaquí los paramètres de vòstre client'
403 field_name: 'Nom del client' 415 field_name: 'Nom del client'
404 field_id: 'ID Client' 416 field_id: 'ID Client'
@@ -406,7 +418,7 @@ developer:
406 back: 'Retour' 418 back: 'Retour'
407 read_howto: 'Legir "cossí crear ma primièra aplicacion"' 419 read_howto: 'Legir "cossí crear ma primièra aplicacion"'
408 howto: 420 howto:
409 page_title: 'Desvolopador > Cossí crear ma primièra aplicacion' 421 page_title: 'Desvolopaire > Cossí crear ma primièra aplicacion'
410 description: 422 description:
411 paragraph_1: "Las comandas seguentas utilizan la <a href=\"https://github.com/jkbrzt/httpie\">bibliotèca HTTPie</a>. Asseguratz-vos que siasqueòu installadas abans de l'utilizar." 423 paragraph_1: "Las comandas seguentas utilizan la <a href=\"https://github.com/jkbrzt/httpie\">bibliotèca HTTPie</a>. Asseguratz-vos que siasqueòu installadas abans de l'utilizar."
412 paragraph_2: "Vos cal un geton per escambiar entre vòstra aplicacion e l'API de wallabar." 424 paragraph_2: "Vos cal un geton per escambiar entre vòstra aplicacion e l'API de wallabar."
@@ -419,31 +431,31 @@ developer:
419 back: 'Retorn' 431 back: 'Retorn'
420 432
421user: 433user:
422 # page_title: Users management 434 page_title: 'Gestion dels utilizaires'
423 # new_user: Create a new user 435 new_user: 'Crear un novèl utilizaire'
424 # edit_user: Edit an existing user 436 edit_user: 'Modificar un utilizaire existent'
425 # description: "Here you can manage all users (create, edit and delete)" 437 description: "Aquí podètz gerir totes los utilizaires (crear, modificar e suprimir)"
426 # list: 438 list:
427 # actions: Actions 439 actions: 'Accions'
428 # edit_action: Edit 440 edit_action: 'Modificar'
429 # yes: Yes 441 yes: 'Òc'
430 # no: No 442 no: 'Non'
431 # create_new_one: Create a new user 443 create_new_one: 'Crear un novèl utilizaire'
432 form: 444 form:
433 username_label: "Nom d'utilizaire" 445 username_label: "Nom d'utilizaire"
434 # name_label: 'Name' 446 name_label: 'Nom'
435 password_label: 'Senhal' 447 password_label: 'Senhal'
436 repeat_new_password_label: 'Confirmatz vòstre novèl senhal' 448 repeat_new_password_label: 'Confirmatz vòstre novèl senhal'
437 plain_password_label: 'Senhal en clar' 449 plain_password_label: 'Senhal en clar'
438 email_label: 'Adreça de corrièl' 450 email_label: 'Adreça de corrièl'
439 # enabled_label: 'Enabled' 451 enabled_label: 'Actiu'
440 # locked_label: 'Locked' 452 locked_label: 'Varrolhat'
441 # last_login_label: 'Last login' 453 last_login_label: 'Darrièra connexion'
442 # twofactor_label: Two factor authentication 454 twofactor_label: 'Autentificacion doble-factor'
443 # save: Save 455 save: 'Enregistrar'
444 # delete: Delete 456 delete: 'Suprimir'
445 # delete_confirm: Are you sure? 457 delete_confirm: 'Sètz segur ?'
446 # back_to_list: Back to list 458 back_to_list: 'Tornar a la lista'
447 459
448error: 460error:
449 # page_title: An error occurred 461 # page_title: An error occurred
@@ -458,8 +470,11 @@ flashes:
458 rss_updated: 'La configuracion dels fluxes RSS es ben estada mesa a jorn' 470 rss_updated: 'La configuracion dels fluxes RSS es ben estada mesa a jorn'
459 tagging_rules_updated: 'Règlas misa a jorn' 471 tagging_rules_updated: 'Règlas misa a jorn'
460 tagging_rules_deleted: 'Règla suprimida' 472 tagging_rules_deleted: 'Règla suprimida'
461 user_added: 'Utilizaire "%username%" apondut' 473 user_added: 'Utilizaire "%username%" ajustat'
462 rss_token_updated: 'Geton RSS mes a jorn' 474 rss_token_updated: 'Geton RSS mes a jorn'
475 # annotations_reset: Annotations reset
476 # tags_reset: Tags reset
477 # entries_reset: Entries reset
463 entry: 478 entry:
464 notice: 479 notice:
465 entry_already_saved: 'Article ja salvargardat lo %date%' 480 entry_already_saved: 'Article ja salvargardat lo %date%'
@@ -470,12 +485,12 @@ flashes:
470 entry_reloaded_failed: "L'article es estat cargat de nòu mai la recuperacion del contengut a fracassat" 485 entry_reloaded_failed: "L'article es estat cargat de nòu mai la recuperacion del contengut a fracassat"
471 entry_archived: 'Article marcat coma legit' 486 entry_archived: 'Article marcat coma legit'
472 entry_unarchived: 'Article marcat coma pas legit' 487 entry_unarchived: 'Article marcat coma pas legit'
473 entry_starred: 'Article apondut dins los favorits' 488 entry_starred: 'Article ajustat dins los favorits'
474 entry_unstarred: 'Article quitat dels favorits' 489 entry_unstarred: 'Article quitat dels favorits'
475 entry_deleted: 'Article suprimit' 490 entry_deleted: 'Article suprimit'
476 tag: 491 tag:
477 notice: 492 notice:
478 tag_added: 'Etiqueta aponduda' 493 tag_added: 'Etiqueta ajustada'
479 import: 494 import:
480 notice: 495 notice:
481 failed: "L'importacion a fracassat, mercés de tornar ensajar" 496 failed: "L'importacion a fracassat, mercés de tornar ensajar"
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
index 798b39c2..8eef998b 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
@@ -88,6 +88,18 @@ config:
88 name_label: 'Nazwa' 88 name_label: 'Nazwa'
89 email_label: 'Adres email' 89 email_label: 'Adres email'
90 twoFactorAuthentication_label: 'Autoryzacja dwuetapowa' 90 twoFactorAuthentication_label: 'Autoryzacja dwuetapowa'
91 delete:
92 title: Usuń moje konto (niebezpieczna strefa !)
93 description: Jeżeli usuniesz swoje konto, wszystkie twoje artykuły, tagi, adnotacje, oraz konto zostaną trwale usunięte (operacja jest NIEODWRACALNA). Następnie zostaniesz wylogowany.
94 confirm: Jesteś pewien? (tej operacji NIE MOŻNA cofnąć)
95 button: Usuń moje konto
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
91 form_password: 103 form_password:
92 old_password_label: 'Stare hasło' 104 old_password_label: 'Stare hasło'
93 new_password_label: 'Nowe hasło' 105 new_password_label: 'Nowe hasło'
@@ -460,6 +472,9 @@ flashes:
460 tagging_rules_deleted: 'Reguła tagowania usunięta' 472 tagging_rules_deleted: 'Reguła tagowania usunięta'
461 user_added: 'Użytkownik "%username%" dodany' 473 user_added: 'Użytkownik "%username%" dodany'
462 rss_token_updated: 'Token kanału RSS zaktualizowany' 474 rss_token_updated: 'Token kanału RSS zaktualizowany'
475 # annotations_reset: Annotations reset
476 # tags_reset: Tags reset
477 # entries_reset: Entries reset
463 entry: 478 entry:
464 notice: 479 notice:
465 entry_already_saved: 'Wpis już został dodany %date%' 480 entry_already_saved: 'Wpis już został dodany %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
index 21f27e08..6e4813e5 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
@@ -88,6 +88,18 @@ config:
88 name_label: 'Nume' 88 name_label: 'Nume'
89 email_label: 'E-mail' 89 email_label: 'E-mail'
90 # twoFactorAuthentication_label: 'Two factor authentication' 90 # twoFactorAuthentication_label: 'Two factor authentication'
91 delete:
92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
91 form_password: 103 form_password:
92 old_password_label: 'Parola veche' 104 old_password_label: 'Parola veche'
93 new_password_label: 'Parola nouă' 105 new_password_label: 'Parola nouă'
@@ -460,6 +472,9 @@ flashes:
460 # tagging_rules_deleted: 'Tagging rule deleted' 472 # tagging_rules_deleted: 'Tagging rule deleted'
461 # user_added: 'User "%username%" added' 473 # user_added: 'User "%username%" added'
462 # rss_token_updated: 'RSS token updated' 474 # rss_token_updated: 'RSS token updated'
475 # annotations_reset: Annotations reset
476 # tags_reset: Tags reset
477 # entries_reset: Entries reset
463 entry: 478 entry:
464 notice: 479 notice:
465 # entry_already_saved: 'Entry already saved on %date%' 480 # entry_already_saved: 'Entry already saved on %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
index f137ec99..76903102 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
@@ -88,6 +88,18 @@ config:
88 name_label: 'İsim' 88 name_label: 'İsim'
89 email_label: 'E-posta' 89 email_label: 'E-posta'
90 twoFactorAuthentication_label: 'İki adımlı doğrulama' 90 twoFactorAuthentication_label: 'İki adımlı doğrulama'
91 delete:
92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
91 form_password: 103 form_password:
92 old_password_label: 'Eski şifre' 104 old_password_label: 'Eski şifre'
93 new_password_label: 'Yeni şifre' 105 new_password_label: 'Yeni şifre'
@@ -459,6 +471,9 @@ flashes:
459 tagging_rules_deleted: 'Tagging rule deleted' 471 tagging_rules_deleted: 'Tagging rule deleted'
460 user_added: 'User "%username%" added' 472 user_added: 'User "%username%" added'
461 rss_token_updated: 'RSS token updated' 473 rss_token_updated: 'RSS token updated'
474 # annotations_reset: Annotations reset
475 # tags_reset: Tags reset
476 # entries_reset: Entries reset
462 entry: 477 entry:
463 notice: 478 notice:
464 entry_already_saved: 'Entry already saved on %date%' 479 entry_already_saved: 'Entry already saved on %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig
index ff7ef73a..455d0295 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig
@@ -146,10 +146,41 @@
146 </fieldset> 146 </fieldset>
147 {% endif %} 147 {% endif %}
148 148
149 <h2>{{ 'config.reset.title'|trans }}</h2>
150 <fieldset class="w500p inline">
151 <p>{{ 'config.reset.description'|trans }}</p>
152 <ul>
153 <li>
154 <a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
155 {{ 'config.reset.annotations'|trans }}
156 </a>
157 </li>
158 <li>
159 <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
160 {{ 'config.reset.tags'|trans }}
161 </a>
162 </li>
163 <li>
164 <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
165 {{ 'config.reset.entries'|trans }}
166 </a>
167 </li>
168 </ul>
169 </fieldset>
170
149 {{ form_widget(form.user._token) }} 171 {{ form_widget(form.user._token) }}
150 {{ form_widget(form.user.save) }} 172 {{ form_widget(form.user.save) }}
151 </form> 173 </form>
152 174
175 {% if enabled_users > 1 %}
176 <h2>{{ 'config.form_user.delete.title'|trans }}</h2>
177
178 <p>{{ 'config.form_user.delete.description'|trans }}</p>
179 <a href="{{ path('delete_account') }}" onclick="return confirm('{{ 'config.form_user.delete.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red delete-account">
180 {{ 'config.form_user.delete.button'|trans }}
181 </a>
182 {% endif %}
183
153 <h2>{{ 'config.tab_menu.password'|trans }}</h2> 184 <h2>{{ 'config.tab_menu.password'|trans }}</h2>
154 185
155 {{ form_start(form.pwd) }} 186 {{ form_start(form.pwd) }}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
index 19faddc0..b53ae2fe 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
@@ -167,6 +167,34 @@
167 {{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} 167 {{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
168 {{ form_widget(form.user._token) }} 168 {{ form_widget(form.user._token) }}
169 </form> 169 </form>
170
171 <br /><hr /><br />
172
173 <div class="row">
174 <h5>{{ 'config.reset.title'|trans }}</h5>
175 <p>{{ 'config.reset.description'|trans }}</p>
176 <a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
177 {{ 'config.reset.annotations'|trans }}
178 </a>
179 <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
180 {{ 'config.reset.tags'|trans }}
181 </a>
182 <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
183 {{ 'config.reset.entries'|trans }}
184 </a>
185 </div>
186
187 {% if enabled_users > 1 %}
188 <br /><hr /><br />
189
190 <div class="row">
191 <h5>{{ 'config.form_user.delete.title'|trans }}</h5>
192 <p>{{ 'config.form_user.delete.description'|trans }}</p>
193 <a href="{{ path('delete_account') }}" onclick="return confirm('{{ 'config.form_user.delete.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red delete-account">
194 {{ 'config.form_user.delete.button'|trans }}
195 </a>
196 </div>
197 {% endif %}
170 </div> 198 </div>
171 199
172 <div id="set4" class="col s12"> 200 <div id="set4" class="col s12">
diff --git a/src/Wallabag/CoreBundle/Subscriber/SQLiteCascadeDeleteSubscriber.php b/src/Wallabag/CoreBundle/Subscriber/SQLiteCascadeDeleteSubscriber.php
new file mode 100644
index 00000000..f7210bd3
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Subscriber/SQLiteCascadeDeleteSubscriber.php
@@ -0,0 +1,70 @@
1<?php
2
3namespace Wallabag\CoreBundle\Subscriber;
4
5use Doctrine\Common\EventSubscriber;
6use Doctrine\ORM\Event\LifecycleEventArgs;
7use Wallabag\CoreBundle\Entity\Entry;
8use Doctrine\Bundle\DoctrineBundle\Registry;
9
10/**
11 * SQLite doesn't care about cascading remove, so we need to manually remove associated stuf for an Entry.
12 * Foreign Key Support can be enabled by running `PRAGMA foreign_keys = ON;` at runtime (AT RUNTIME !).
13 * But it needs a compilation flag that not all SQLite instance has ...
14 *
15 * @see https://www.sqlite.org/foreignkeys.html#fk_enable
16 */
17class SQLiteCascadeDeleteSubscriber implements EventSubscriber
18{
19 private $doctrine;
20
21 /**
22 * @param \Doctrine\Bundle\DoctrineBundle\Registry $doctrine
23 */
24 public function __construct(Registry $doctrine)
25 {
26 $this->doctrine = $doctrine;
27 }
28
29 /**
30 * @return array
31 */
32 public function getSubscribedEvents()
33 {
34 return [
35 'preRemove',
36 ];
37 }
38
39 /**
40 * We removed everything related to the upcoming removed entry because SQLite can't handle it on it own.
41 * We do it in the preRemove, because we can't retrieve tags in the postRemove (because the entry id is gone).
42 *
43 * @param LifecycleEventArgs $args
44 */
45 public function preRemove(LifecycleEventArgs $args)
46 {
47 $entity = $args->getEntity();
48
49 if (!$this->doctrine->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver ||
50 !$entity instanceof Entry) {
51 return;
52 }
53
54 $em = $this->doctrine->getManager();
55
56 if (null !== $entity->getTags()) {
57 foreach ($entity->getTags() as $tag) {
58 $entity->removeTag($tag);
59 }
60 }
61
62 if (null !== $entity->getAnnotations()) {
63 foreach ($entity->getAnnotations() as $annotation) {
64 $em->remove($annotation);
65 }
66 }
67
68 $em->flush();
69 }
70}
diff --git a/src/Wallabag/UserBundle/Repository/UserRepository.php b/src/Wallabag/UserBundle/Repository/UserRepository.php
index 009c4881..445edb3c 100644
--- a/src/Wallabag/UserBundle/Repository/UserRepository.php
+++ b/src/Wallabag/UserBundle/Repository/UserRepository.php
@@ -38,4 +38,18 @@ class UserRepository extends EntityRepository
38 ->getQuery() 38 ->getQuery()
39 ->getSingleResult(); 39 ->getSingleResult();
40 } 40 }
41
42 /**
43 * Count how many users are enabled.
44 *
45 * @return int
46 */
47 public function getSumEnabledUsers()
48 {
49 return $this->createQueryBuilder('u')
50 ->select('count(u)')
51 ->andWhere('u.expired = false')
52 ->getQuery()
53 ->getSingleScalarResult();
54 }
41} 55}
diff --git a/src/Wallabag/UserBundle/Resources/config/services.yml b/src/Wallabag/UserBundle/Resources/config/services.yml
index eb9c8e67..8062e53f 100644
--- a/src/Wallabag/UserBundle/Resources/config/services.yml
+++ b/src/Wallabag/UserBundle/Resources/config/services.yml
@@ -21,7 +21,7 @@ services:
21 arguments: 21 arguments:
22 - WallabagUserBundle:User 22 - WallabagUserBundle:User
23 23
24 wallabag_user.create_config: 24 wallabag_user.listener.create_config:
25 class: Wallabag\UserBundle\EventListener\CreateConfigListener 25 class: Wallabag\UserBundle\EventListener\CreateConfigListener
26 arguments: 26 arguments:
27 - "@doctrine.orm.entity_manager" 27 - "@doctrine.orm.entity_manager"