diff options
Diffstat (limited to 'src')
59 files changed, 1305 insertions, 164 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 @@ | |||
3 | namespace Wallabag\AnnotationBundle\Controller; | 3 | namespace Wallabag\AnnotationBundle\Controller; |
4 | 4 | ||
5 | use FOS\RestBundle\Controller\FOSRestController; | 5 | use FOS\RestBundle\Controller\FOSRestController; |
6 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | 6 | use Symfony\Component\HttpFoundation\JsonResponse; |
7 | use Symfony\Component\HttpFoundation\Request; | 7 | use Symfony\Component\HttpFoundation\Request; |
8 | use Symfony\Component\HttpFoundation\Response; | ||
9 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | 8 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; |
10 | use Wallabag\AnnotationBundle\Entity\Annotation; | 9 | use Wallabag\AnnotationBundle\Entity\Annotation; |
11 | use Wallabag\CoreBundle\Entity\Entry; | 10 | use 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/DeveloperController.php b/src/Wallabag/ApiBundle/Controller/DeveloperController.php index 5a36a260..550c0608 100644 --- a/src/Wallabag/ApiBundle/Controller/DeveloperController.php +++ b/src/Wallabag/ApiBundle/Controller/DeveloperController.php | |||
@@ -19,7 +19,7 @@ class DeveloperController extends Controller | |||
19 | */ | 19 | */ |
20 | public function indexAction() | 20 | public function indexAction() |
21 | { | 21 | { |
22 | $clients = $this->getDoctrine()->getRepository('WallabagApiBundle:Client')->findAll(); | 22 | $clients = $this->getDoctrine()->getRepository('WallabagApiBundle:Client')->findByUser($this->getUser()->getId()); |
23 | 23 | ||
24 | return $this->render('@WallabagCore/themes/common/Developer/index.html.twig', [ | 24 | return $this->render('@WallabagCore/themes/common/Developer/index.html.twig', [ |
25 | 'clients' => $clients, | 25 | 'clients' => $clients, |
@@ -38,7 +38,7 @@ class DeveloperController extends Controller | |||
38 | public function createClientAction(Request $request) | 38 | public function createClientAction(Request $request) |
39 | { | 39 | { |
40 | $em = $this->getDoctrine()->getManager(); | 40 | $em = $this->getDoctrine()->getManager(); |
41 | $client = new Client(); | 41 | $client = new Client($this->getUser()); |
42 | $clientForm = $this->createForm(ClientType::class, $client); | 42 | $clientForm = $this->createForm(ClientType::class, $client); |
43 | $clientForm->handleRequest($request); | 43 | $clientForm->handleRequest($request); |
44 | 44 | ||
@@ -75,6 +75,10 @@ class DeveloperController extends Controller | |||
75 | */ | 75 | */ |
76 | public function deleteClientAction(Client $client) | 76 | public function deleteClientAction(Client $client) |
77 | { | 77 | { |
78 | if (null === $this->getUser() || $client->getUser()->getId() != $this->getUser()->getId()) { | ||
79 | throw $this->createAccessDeniedException('You can not access this client.'); | ||
80 | } | ||
81 | |||
78 | $em = $this->getDoctrine()->getManager(); | 82 | $em = $this->getDoctrine()->getManager(); |
79 | $em->remove($client); | 83 | $em->remove($client); |
80 | $em->flush(); | 84 | $em->flush(); |
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php index 24fa7b3b..b3622c62 100644 --- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php +++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php | |||
@@ -10,6 +10,8 @@ use Symfony\Component\HttpFoundation\JsonResponse; | |||
10 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | 10 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
11 | use Wallabag\CoreBundle\Entity\Entry; | 11 | use Wallabag\CoreBundle\Entity\Entry; |
12 | use Wallabag\CoreBundle\Entity\Tag; | 12 | use Wallabag\CoreBundle\Entity\Tag; |
13 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | ||
14 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; | ||
13 | 15 | ||
14 | class EntryRestController extends WallabagRestController | 16 | class EntryRestController extends WallabagRestController |
15 | { | 17 | { |
@@ -200,9 +202,11 @@ class EntryRestController extends WallabagRestController | |||
200 | 202 | ||
201 | $em = $this->getDoctrine()->getManager(); | 203 | $em = $this->getDoctrine()->getManager(); |
202 | $em->persist($entry); | 204 | $em->persist($entry); |
203 | |||
204 | $em->flush(); | 205 | $em->flush(); |
205 | 206 | ||
207 | // entry saved, dispatch event about it! | ||
208 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
209 | |||
206 | $json = $this->get('serializer')->serialize($entry, 'json'); | 210 | $json = $this->get('serializer')->serialize($entry, 'json'); |
207 | 211 | ||
208 | return (new JsonResponse())->setJson($json); | 212 | return (new JsonResponse())->setJson($json); |
@@ -279,6 +283,9 @@ class EntryRestController extends WallabagRestController | |||
279 | $em->remove($entry); | 283 | $em->remove($entry); |
280 | $em->flush(); | 284 | $em->flush(); |
281 | 285 | ||
286 | // entry deleted, dispatch event about it! | ||
287 | $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry)); | ||
288 | |||
282 | $json = $this->get('serializer')->serialize($entry, 'json'); | 289 | $json = $this->get('serializer')->serialize($entry, 'json'); |
283 | 290 | ||
284 | return (new JsonResponse())->setJson($json); | 291 | return (new JsonResponse())->setJson($json); |
diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php index e927a890..544c1ea9 100644 --- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php | |||
@@ -8,6 +8,20 @@ use Wallabag\CoreBundle\Entity\Entry; | |||
8 | 8 | ||
9 | class WallabagRestController extends FOSRestController | 9 | class WallabagRestController extends FOSRestController |
10 | { | 10 | { |
11 | /** | ||
12 | * Retrieve version number. | ||
13 | * | ||
14 | * @ApiDoc() | ||
15 | * | ||
16 | * @return JsonResponse | ||
17 | */ | ||
18 | public function getVersionAction() | ||
19 | { | ||
20 | $version = $this->container->getParameter('wallabag_core.version'); | ||
21 | $json = $this->get('serializer')->serialize($version, 'json'); | ||
22 | return (new JsonResponse())->setJson($json); | ||
23 | } | ||
24 | |||
11 | protected function validateAuthentication() | 25 | protected function validateAuthentication() |
12 | { | 26 | { |
13 | if (false === $this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { | 27 | if (false === $this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { |
diff --git a/src/Wallabag/ApiBundle/Entity/Client.php b/src/Wallabag/ApiBundle/Entity/Client.php index f7898ac8..427a4c7f 100644 --- a/src/Wallabag/ApiBundle/Entity/Client.php +++ b/src/Wallabag/ApiBundle/Entity/Client.php | |||
@@ -4,6 +4,7 @@ namespace Wallabag\ApiBundle\Entity; | |||
4 | 4 | ||
5 | use Doctrine\ORM\Mapping as ORM; | 5 | use Doctrine\ORM\Mapping as ORM; |
6 | use FOS\OAuthServerBundle\Entity\Client as BaseClient; | 6 | use FOS\OAuthServerBundle\Entity\Client as BaseClient; |
7 | use Wallabag\UserBundle\Entity\User; | ||
7 | 8 | ||
8 | /** | 9 | /** |
9 | * @ORM\Table("oauth2_clients") | 10 | * @ORM\Table("oauth2_clients") |
@@ -35,9 +36,15 @@ class Client extends BaseClient | |||
35 | */ | 36 | */ |
36 | protected $accessTokens; | 37 | protected $accessTokens; |
37 | 38 | ||
38 | public function __construct() | 39 | /** |
40 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="clients") | ||
41 | */ | ||
42 | private $user; | ||
43 | |||
44 | public function __construct(User $user) | ||
39 | { | 45 | { |
40 | parent::__construct(); | 46 | parent::__construct(); |
47 | $this->user = $user; | ||
41 | } | 48 | } |
42 | 49 | ||
43 | /** | 50 | /** |
@@ -63,4 +70,12 @@ class Client extends BaseClient | |||
63 | 70 | ||
64 | return $this; | 71 | return $this; |
65 | } | 72 | } |
73 | |||
74 | /** | ||
75 | * @return User | ||
76 | */ | ||
77 | public function getUser() | ||
78 | { | ||
79 | return $this->user; | ||
80 | } | ||
66 | } | 81 | } |
diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml index c1af9e02..8e1886ac 100644 --- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml +++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml | |||
@@ -1,9 +1,14 @@ | |||
1 | entries: | 1 | entry: |
2 | type: rest | 2 | type: rest |
3 | resource: "WallabagApiBundle:EntryRest" | 3 | resource: "WallabagApiBundle:EntryRest" |
4 | name_prefix: api_ | 4 | name_prefix: api_ |
5 | 5 | ||
6 | tags: | 6 | tag: |
7 | type: rest | 7 | type: rest |
8 | resource: "WallabagApiBundle:TagRest" | 8 | resource: "WallabagApiBundle:TagRest" |
9 | name_prefix: api_ | ||
10 | |||
11 | misc: | ||
12 | type: rest | ||
13 | resource: "WallabagApiBundle:WallabagRest" | ||
9 | name_prefix: api_ | 14 | name_prefix: api_ |
diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php index 857a8b4c..9fe90357 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 | ||
@@ -354,7 +370,7 @@ class InstallCommand extends ContainerAwareCommand | |||
354 | ], | 370 | ], |
355 | [ | 371 | [ |
356 | 'name' => 'wallabag_url', | 372 | 'name' => 'wallabag_url', |
357 | 'value' => 'http://v2.wallabag.org', | 373 | 'value' => '', |
358 | 'section' => 'misc', | 374 | 'section' => 'misc', |
359 | ], | 375 | ], |
360 | [ | 376 | [ |
@@ -382,6 +398,11 @@ class InstallCommand extends ContainerAwareCommand | |||
382 | 'value' => 'wallabag', | 398 | 'value' => 'wallabag', |
383 | 'section' => 'misc', | 399 | 'section' => 'misc', |
384 | ], | 400 | ], |
401 | [ | ||
402 | 'name' => 'download_images_enabled', | ||
403 | 'value' => '0', | ||
404 | 'section' => 'misc', | ||
405 | ], | ||
385 | ]; | 406 | ]; |
386 | 407 | ||
387 | foreach ($settings as $setting) { | 408 | foreach ($settings as $setting) { |
diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php index 91cdcae5..d40efcd7 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; | |||
7 | use Symfony\Component\HttpFoundation\JsonResponse; | 7 | use Symfony\Component\HttpFoundation\JsonResponse; |
8 | use Symfony\Component\HttpFoundation\RedirectResponse; | 8 | use Symfony\Component\HttpFoundation\RedirectResponse; |
9 | use Symfony\Component\HttpFoundation\Request; | 9 | use Symfony\Component\HttpFoundation\Request; |
10 | use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; | ||
10 | use Wallabag\CoreBundle\Entity\Config; | 11 | use Wallabag\CoreBundle\Entity\Config; |
11 | use Wallabag\CoreBundle\Entity\TaggingRule; | 12 | use Wallabag\CoreBundle\Entity\TaggingRule; |
12 | use Wallabag\CoreBundle\Form\Type\ConfigType; | 13 | use Wallabag\CoreBundle\Form\Type\ConfigType; |
@@ -148,6 +149,10 @@ 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 | 'wallabag_url' => $this->get('craue_config')->get('wallabag_url'), | ||
153 | 'enabled_users' => $this->getDoctrine() | ||
154 | ->getRepository('WallabagUserBundle:User') | ||
155 | ->getSumEnabledUsers(), | ||
151 | ]); | 156 | ]); |
152 | } | 157 | } |
153 | 158 | ||
@@ -221,6 +226,80 @@ class ConfigController extends Controller | |||
221 | } | 226 | } |
222 | 227 | ||
223 | /** | 228 | /** |
229 | * Remove all annotations OR tags OR entries for the current user. | ||
230 | * | ||
231 | * @Route("/reset/{type}", requirements={"id" = "annotations|tags|entries"}, name="config_reset") | ||
232 | * | ||
233 | * @return RedirectResponse | ||
234 | */ | ||
235 | public function resetAction($type) | ||
236 | { | ||
237 | $em = $this->getDoctrine()->getManager(); | ||
238 | |||
239 | switch ($type) { | ||
240 | case 'annotations': | ||
241 | $this->getDoctrine() | ||
242 | ->getRepository('WallabagAnnotationBundle:Annotation') | ||
243 | ->removeAllByUserId($this->getUser()->getId()); | ||
244 | break; | ||
245 | |||
246 | case 'tags': | ||
247 | $this->removeAllTagsByUserId($this->getUser()->getId()); | ||
248 | break; | ||
249 | |||
250 | case 'entries': | ||
251 | // SQLite doesn't care about cascading remove, so we need to manually remove associated stuf | ||
252 | // otherwise they won't be removed ... | ||
253 | if ($this->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) { | ||
254 | $this->getDoctrine()->getRepository('WallabagAnnotationBundle:Annotation')->removeAllByUserId($this->getUser()->getId()); | ||
255 | } | ||
256 | |||
257 | // manually remove tags to avoid orphan tag | ||
258 | $this->removeAllTagsByUserId($this->getUser()->getId()); | ||
259 | |||
260 | $this->getDoctrine() | ||
261 | ->getRepository('WallabagCoreBundle:Entry') | ||
262 | ->removeAllByUserId($this->getUser()->getId()); | ||
263 | } | ||
264 | |||
265 | $this->get('session')->getFlashBag()->add( | ||
266 | 'notice', | ||
267 | 'flashes.config.notice.'.$type.'_reset' | ||
268 | ); | ||
269 | |||
270 | return $this->redirect($this->generateUrl('config').'#set3'); | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * Remove all tags for a given user and cleanup orphan tags. | ||
275 | * | ||
276 | * @param int $userId | ||
277 | */ | ||
278 | private function removeAllTagsByUserId($userId) | ||
279 | { | ||
280 | $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findAllTags($userId); | ||
281 | |||
282 | if (empty($tags)) { | ||
283 | return; | ||
284 | } | ||
285 | |||
286 | $this->getDoctrine() | ||
287 | ->getRepository('WallabagCoreBundle:Entry') | ||
288 | ->removeTags($userId, $tags); | ||
289 | |||
290 | // cleanup orphan tags | ||
291 | $em = $this->getDoctrine()->getManager(); | ||
292 | |||
293 | foreach ($tags as $tag) { | ||
294 | if (count($tag->getEntries()) === 0) { | ||
295 | $em->remove($tag); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | $em->flush(); | ||
300 | } | ||
301 | |||
302 | /** | ||
224 | * Validate that a rule can be edited/deleted by the current user. | 303 | * Validate that a rule can be edited/deleted by the current user. |
225 | * | 304 | * |
226 | * @param TaggingRule $rule | 305 | * @param TaggingRule $rule |
@@ -251,4 +330,37 @@ class ConfigController extends Controller | |||
251 | 330 | ||
252 | return $config; | 331 | return $config; |
253 | } | 332 | } |
333 | |||
334 | /** | ||
335 | * Delete account for current user. | ||
336 | * | ||
337 | * @Route("/account/delete", name="delete_account") | ||
338 | * | ||
339 | * @param Request $request | ||
340 | * | ||
341 | * @throws AccessDeniedHttpException | ||
342 | * | ||
343 | * @return \Symfony\Component\HttpFoundation\RedirectResponse | ||
344 | */ | ||
345 | public function deleteAccountAction(Request $request) | ||
346 | { | ||
347 | $enabledUsers = $this->getDoctrine() | ||
348 | ->getRepository('WallabagUserBundle:User') | ||
349 | ->getSumEnabledUsers(); | ||
350 | |||
351 | if ($enabledUsers <= 1) { | ||
352 | throw new AccessDeniedHttpException(); | ||
353 | } | ||
354 | |||
355 | $user = $this->getUser(); | ||
356 | |||
357 | // logout current user | ||
358 | $this->get('security.token_storage')->setToken(null); | ||
359 | $request->getSession()->invalidate(); | ||
360 | |||
361 | $em = $this->get('fos_user.user_manager'); | ||
362 | $em->deleteUser($user); | ||
363 | |||
364 | return $this->redirect($this->generateUrl('fos_user_security_login')); | ||
365 | } | ||
254 | } | 366 | } |
diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php index 97bb3d12..3f4eb17d 100644 --- a/src/Wallabag/CoreBundle/Controller/EntryController.php +++ b/src/Wallabag/CoreBundle/Controller/EntryController.php | |||
@@ -13,6 +13,8 @@ use Wallabag\CoreBundle\Form\Type\EntryFilterType; | |||
13 | use Wallabag\CoreBundle\Form\Type\EditEntryType; | 13 | use Wallabag\CoreBundle\Form\Type\EditEntryType; |
14 | use Wallabag\CoreBundle\Form\Type\NewEntryType; | 14 | use Wallabag\CoreBundle\Form\Type\NewEntryType; |
15 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; | 15 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; |
16 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | ||
17 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; | ||
16 | 18 | ||
17 | class EntryController extends Controller | 19 | class EntryController extends Controller |
18 | { | 20 | { |
@@ -81,6 +83,9 @@ class EntryController extends Controller | |||
81 | $em->persist($entry); | 83 | $em->persist($entry); |
82 | $em->flush(); | 84 | $em->flush(); |
83 | 85 | ||
86 | // entry saved, dispatch event about it! | ||
87 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
88 | |||
84 | return $this->redirect($this->generateUrl('homepage')); | 89 | return $this->redirect($this->generateUrl('homepage')); |
85 | } | 90 | } |
86 | 91 | ||
@@ -107,6 +112,9 @@ class EntryController extends Controller | |||
107 | $em = $this->getDoctrine()->getManager(); | 112 | $em = $this->getDoctrine()->getManager(); |
108 | $em->persist($entry); | 113 | $em->persist($entry); |
109 | $em->flush(); | 114 | $em->flush(); |
115 | |||
116 | // entry saved, dispatch event about it! | ||
117 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
110 | } | 118 | } |
111 | 119 | ||
112 | return $this->redirect($this->generateUrl('homepage')); | 120 | return $this->redirect($this->generateUrl('homepage')); |
@@ -343,6 +351,9 @@ class EntryController extends Controller | |||
343 | $em->persist($entry); | 351 | $em->persist($entry); |
344 | $em->flush(); | 352 | $em->flush(); |
345 | 353 | ||
354 | // entry saved, dispatch event about it! | ||
355 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
356 | |||
346 | return $this->redirect($this->generateUrl('view', ['id' => $entry->getId()])); | 357 | return $this->redirect($this->generateUrl('view', ['id' => $entry->getId()])); |
347 | } | 358 | } |
348 | 359 | ||
@@ -431,6 +442,9 @@ class EntryController extends Controller | |||
431 | UrlGeneratorInterface::ABSOLUTE_PATH | 442 | UrlGeneratorInterface::ABSOLUTE_PATH |
432 | ); | 443 | ); |
433 | 444 | ||
445 | // entry deleted, dispatch event about it! | ||
446 | $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry)); | ||
447 | |||
434 | $em = $this->getDoctrine()->getManager(); | 448 | $em = $this->getDoctrine()->getManager(); |
435 | $em->remove($entry); | 449 | $em->remove($entry); |
436 | $em->flush(); | 450 | $em->flush(); |
diff --git a/src/Wallabag/CoreBundle/Controller/TagController.php b/src/Wallabag/CoreBundle/Controller/TagController.php index 707f3bbe..a3e70fd0 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/DataFixtures/ORM/LoadSettingData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php index a5e1be65..d0085660 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php | |||
@@ -140,6 +140,11 @@ class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface | |||
140 | 'value' => 'wallabag', | 140 | 'value' => 'wallabag', |
141 | 'section' => 'misc', | 141 | 'section' => 'misc', |
142 | ], | 142 | ], |
143 | [ | ||
144 | 'name' => 'download_images_enabled', | ||
145 | 'value' => '0', | ||
146 | 'section' => 'misc', | ||
147 | ], | ||
143 | ]; | 148 | ]; |
144 | 149 | ||
145 | foreach ($settings as $setting) { | 150 | foreach ($settings as $setting) { |
@@ -158,6 +163,6 @@ class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface | |||
158 | */ | 163 | */ |
159 | public function getOrder() | 164 | public function getOrder() |
160 | { | 165 | { |
161 | return 50; | 166 | return 29; |
162 | } | 167 | } |
163 | } | 168 | } |
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/Event/EntryDeletedEvent.php b/src/Wallabag/CoreBundle/Event/EntryDeletedEvent.php new file mode 100644 index 00000000..e9061d04 --- /dev/null +++ b/src/Wallabag/CoreBundle/Event/EntryDeletedEvent.php | |||
@@ -0,0 +1,26 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Event; | ||
4 | |||
5 | use Symfony\Component\EventDispatcher\Event; | ||
6 | use Wallabag\CoreBundle\Entity\Entry; | ||
7 | |||
8 | /** | ||
9 | * This event is fired as soon as an entry is deleted. | ||
10 | */ | ||
11 | class EntryDeletedEvent extends Event | ||
12 | { | ||
13 | const NAME = 'entry.deleted'; | ||
14 | |||
15 | protected $entry; | ||
16 | |||
17 | public function __construct(Entry $entry) | ||
18 | { | ||
19 | $this->entry = $entry; | ||
20 | } | ||
21 | |||
22 | public function getEntry() | ||
23 | { | ||
24 | return $this->entry; | ||
25 | } | ||
26 | } | ||
diff --git a/src/Wallabag/CoreBundle/Event/EntrySavedEvent.php b/src/Wallabag/CoreBundle/Event/EntrySavedEvent.php new file mode 100644 index 00000000..5fdb5221 --- /dev/null +++ b/src/Wallabag/CoreBundle/Event/EntrySavedEvent.php | |||
@@ -0,0 +1,26 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Event; | ||
4 | |||
5 | use Symfony\Component\EventDispatcher\Event; | ||
6 | use Wallabag\CoreBundle\Entity\Entry; | ||
7 | |||
8 | /** | ||
9 | * This event is fired as soon as an entry was saved. | ||
10 | */ | ||
11 | class EntrySavedEvent extends Event | ||
12 | { | ||
13 | const NAME = 'entry.saved'; | ||
14 | |||
15 | protected $entry; | ||
16 | |||
17 | public function __construct(Entry $entry) | ||
18 | { | ||
19 | $this->entry = $entry; | ||
20 | } | ||
21 | |||
22 | public function getEntry() | ||
23 | { | ||
24 | return $this->entry; | ||
25 | } | ||
26 | } | ||
diff --git a/src/Wallabag/CoreBundle/EventListener/LocaleListener.php b/src/Wallabag/CoreBundle/Event/Listener/LocaleListener.php index a1c7e5ab..b435d99e 100644 --- a/src/Wallabag/CoreBundle/EventListener/LocaleListener.php +++ b/src/Wallabag/CoreBundle/Event/Listener/LocaleListener.php | |||
@@ -1,6 +1,6 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\EventListener; | 3 | namespace Wallabag\CoreBundle\Event\Listener; |
4 | 4 | ||
5 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; | 5 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
6 | use Symfony\Component\HttpKernel\Event\GetResponseEvent; | 6 | use Symfony\Component\HttpKernel\Event\GetResponseEvent; |
diff --git a/src/Wallabag/CoreBundle/EventListener/UserLocaleListener.php b/src/Wallabag/CoreBundle/Event/Listener/UserLocaleListener.php index 82d1a63a..367cdfb0 100644 --- a/src/Wallabag/CoreBundle/EventListener/UserLocaleListener.php +++ b/src/Wallabag/CoreBundle/Event/Listener/UserLocaleListener.php | |||
@@ -1,6 +1,6 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\EventListener; | 3 | namespace Wallabag\CoreBundle\Event\Listener; |
4 | 4 | ||
5 | use Symfony\Component\HttpFoundation\Session\Session; | 5 | use Symfony\Component\HttpFoundation\Session\Session; |
6 | use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; | 6 | use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; |
diff --git a/src/Wallabag/CoreBundle/Event/Subscriber/DownloadImagesSubscriber.php b/src/Wallabag/CoreBundle/Event/Subscriber/DownloadImagesSubscriber.php new file mode 100644 index 00000000..4ebe837b --- /dev/null +++ b/src/Wallabag/CoreBundle/Event/Subscriber/DownloadImagesSubscriber.php | |||
@@ -0,0 +1,121 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Event\Subscriber; | ||
4 | |||
5 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; | ||
6 | use Psr\Log\LoggerInterface; | ||
7 | use Wallabag\CoreBundle\Helper\DownloadImages; | ||
8 | use Wallabag\CoreBundle\Entity\Entry; | ||
9 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | ||
10 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; | ||
11 | use Doctrine\ORM\EntityManager; | ||
12 | |||
13 | class DownloadImagesSubscriber implements EventSubscriberInterface | ||
14 | { | ||
15 | private $em; | ||
16 | private $downloadImages; | ||
17 | private $enabled; | ||
18 | private $logger; | ||
19 | |||
20 | public function __construct(EntityManager $em, DownloadImages $downloadImages, $enabled, LoggerInterface $logger) | ||
21 | { | ||
22 | $this->em = $em; | ||
23 | $this->downloadImages = $downloadImages; | ||
24 | $this->enabled = $enabled; | ||
25 | $this->logger = $logger; | ||
26 | } | ||
27 | |||
28 | public static function getSubscribedEvents() | ||
29 | { | ||
30 | return [ | ||
31 | EntrySavedEvent::NAME => 'onEntrySaved', | ||
32 | EntryDeletedEvent::NAME => 'onEntryDeleted', | ||
33 | ]; | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * Download images and updated the data into the entry. | ||
38 | * | ||
39 | * @param EntrySavedEvent $event | ||
40 | */ | ||
41 | public function onEntrySaved(EntrySavedEvent $event) | ||
42 | { | ||
43 | if (!$this->enabled) { | ||
44 | $this->logger->debug('DownloadImagesSubscriber: disabled.'); | ||
45 | |||
46 | return; | ||
47 | } | ||
48 | |||
49 | $entry = $event->getEntry(); | ||
50 | |||
51 | $html = $this->downloadImages($entry); | ||
52 | if (false !== $html) { | ||
53 | $this->logger->debug('DownloadImagesSubscriber: updated html.'); | ||
54 | |||
55 | $entry->setContent($html); | ||
56 | } | ||
57 | |||
58 | // update preview picture | ||
59 | $previewPicture = $this->downloadPreviewImage($entry); | ||
60 | if (false !== $previewPicture) { | ||
61 | $this->logger->debug('DownloadImagesSubscriber: update preview picture.'); | ||
62 | |||
63 | $entry->setPreviewPicture($previewPicture); | ||
64 | } | ||
65 | |||
66 | $this->em->persist($entry); | ||
67 | $this->em->flush(); | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * Remove images related to the entry. | ||
72 | * | ||
73 | * @param EntryDeletedEvent $event | ||
74 | */ | ||
75 | public function onEntryDeleted(EntryDeletedEvent $event) | ||
76 | { | ||
77 | if (!$this->enabled) { | ||
78 | $this->logger->debug('DownloadImagesSubscriber: disabled.'); | ||
79 | |||
80 | return; | ||
81 | } | ||
82 | |||
83 | $this->downloadImages->removeImages($event->getEntry()->getId()); | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * Download all images from the html. | ||
88 | * | ||
89 | * @todo If we want to add async download, it should be done in that method | ||
90 | * | ||
91 | * @param Entry $entry | ||
92 | * | ||
93 | * @return string|false False in case of async | ||
94 | */ | ||
95 | private function downloadImages(Entry $entry) | ||
96 | { | ||
97 | return $this->downloadImages->processHtml( | ||
98 | $entry->getId(), | ||
99 | $entry->getContent(), | ||
100 | $entry->getUrl() | ||
101 | ); | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * Download the preview picture. | ||
106 | * | ||
107 | * @todo If we want to add async download, it should be done in that method | ||
108 | * | ||
109 | * @param Entry $entry | ||
110 | * | ||
111 | * @return string|false False in case of async | ||
112 | */ | ||
113 | private function downloadPreviewImage(Entry $entry) | ||
114 | { | ||
115 | return $this->downloadImages->processSingleImage( | ||
116 | $entry->getId(), | ||
117 | $entry->getPreviewPicture(), | ||
118 | $entry->getUrl() | ||
119 | ); | ||
120 | } | ||
121 | } | ||
diff --git a/src/Wallabag/CoreBundle/Event/Subscriber/SQLiteCascadeDeleteSubscriber.php b/src/Wallabag/CoreBundle/Event/Subscriber/SQLiteCascadeDeleteSubscriber.php new file mode 100644 index 00000000..3b4c4cf9 --- /dev/null +++ b/src/Wallabag/CoreBundle/Event/Subscriber/SQLiteCascadeDeleteSubscriber.php | |||
@@ -0,0 +1,70 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Event\Subscriber; | ||
4 | |||
5 | use Doctrine\Common\EventSubscriber; | ||
6 | use Doctrine\ORM\Event\LifecycleEventArgs; | ||
7 | use Wallabag\CoreBundle\Entity\Entry; | ||
8 | use 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 | */ | ||
17 | class 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/CoreBundle/Subscriber/TablePrefixSubscriber.php b/src/Wallabag/CoreBundle/Event/Subscriber/TablePrefixSubscriber.php index 0379ad6a..9013328f 100644 --- a/src/Wallabag/CoreBundle/Subscriber/TablePrefixSubscriber.php +++ b/src/Wallabag/CoreBundle/Event/Subscriber/TablePrefixSubscriber.php | |||
@@ -1,6 +1,6 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\Subscriber; | 3 | namespace Wallabag\CoreBundle\Event\Subscriber; |
4 | 4 | ||
5 | use Doctrine\Common\EventSubscriber; | 5 | use Doctrine\Common\EventSubscriber; |
6 | use Doctrine\ORM\Event\LoadClassMetadataEventArgs; | 6 | use Doctrine\ORM\Event\LoadClassMetadataEventArgs; |
diff --git a/src/Wallabag/CoreBundle/Helper/ContentProxy.php b/src/Wallabag/CoreBundle/Helper/ContentProxy.php index 8019df42..1986ab33 100644 --- a/src/Wallabag/CoreBundle/Helper/ContentProxy.php +++ b/src/Wallabag/CoreBundle/Helper/ContentProxy.php | |||
@@ -3,7 +3,7 @@ | |||
3 | namespace Wallabag\CoreBundle\Helper; | 3 | namespace Wallabag\CoreBundle\Helper; |
4 | 4 | ||
5 | use Graby\Graby; | 5 | use Graby\Graby; |
6 | use Psr\Log\LoggerInterface as Logger; | 6 | use Psr\Log\LoggerInterface; |
7 | use Wallabag\CoreBundle\Entity\Entry; | 7 | use Wallabag\CoreBundle\Entity\Entry; |
8 | use Wallabag\CoreBundle\Entity\Tag; | 8 | use Wallabag\CoreBundle\Entity\Tag; |
9 | use Wallabag\CoreBundle\Tools\Utils; | 9 | use Wallabag\CoreBundle\Tools\Utils; |
@@ -20,7 +20,7 @@ class ContentProxy | |||
20 | protected $logger; | 20 | protected $logger; |
21 | protected $tagRepository; | 21 | protected $tagRepository; |
22 | 22 | ||
23 | public function __construct(Graby $graby, RuleBasedTagger $tagger, TagRepository $tagRepository, Logger $logger) | 23 | public function __construct(Graby $graby, RuleBasedTagger $tagger, TagRepository $tagRepository, LoggerInterface $logger) |
24 | { | 24 | { |
25 | $this->graby = $graby; | 25 | $this->graby = $graby; |
26 | $this->tagger = $tagger; | 26 | $this->tagger = $tagger; |
@@ -66,6 +66,7 @@ class ContentProxy | |||
66 | $entry->setUrl($content['url'] ?: $url); | 66 | $entry->setUrl($content['url'] ?: $url); |
67 | $entry->setTitle($title); | 67 | $entry->setTitle($title); |
68 | $entry->setContent($html); | 68 | $entry->setContent($html); |
69 | |||
69 | $entry->setLanguage($content['language']); | 70 | $entry->setLanguage($content['language']); |
70 | $entry->setMimetype($content['content_type']); | 71 | $entry->setMimetype($content['content_type']); |
71 | $entry->setReadingTime(Utils::getReadingTime($html)); | 72 | $entry->setReadingTime(Utils::getReadingTime($html)); |
diff --git a/src/Wallabag/CoreBundle/Helper/DownloadImages.php b/src/Wallabag/CoreBundle/Helper/DownloadImages.php new file mode 100644 index 00000000..c5298236 --- /dev/null +++ b/src/Wallabag/CoreBundle/Helper/DownloadImages.php | |||
@@ -0,0 +1,233 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Helper; | ||
4 | |||
5 | use Psr\Log\LoggerInterface; | ||
6 | use Symfony\Component\DomCrawler\Crawler; | ||
7 | use GuzzleHttp\Client; | ||
8 | use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser; | ||
9 | use Symfony\Component\Finder\Finder; | ||
10 | |||
11 | class DownloadImages | ||
12 | { | ||
13 | const REGENERATE_PICTURES_QUALITY = 80; | ||
14 | |||
15 | private $client; | ||
16 | private $baseFolder; | ||
17 | private $logger; | ||
18 | private $mimeGuesser; | ||
19 | private $wallabagUrl; | ||
20 | |||
21 | public function __construct(Client $client, $baseFolder, $wallabagUrl, LoggerInterface $logger) | ||
22 | { | ||
23 | $this->client = $client; | ||
24 | $this->baseFolder = $baseFolder; | ||
25 | $this->wallabagUrl = rtrim($wallabagUrl, '/'); | ||
26 | $this->logger = $logger; | ||
27 | $this->mimeGuesser = new MimeTypeExtensionGuesser(); | ||
28 | |||
29 | $this->setFolder(); | ||
30 | } | ||
31 | |||
32 | /** | ||
33 | * Setup base folder where all images are going to be saved. | ||
34 | */ | ||
35 | private function setFolder() | ||
36 | { | ||
37 | // if folder doesn't exist, attempt to create one and store the folder name in property $folder | ||
38 | if (!file_exists($this->baseFolder)) { | ||
39 | mkdir($this->baseFolder, 0777, true); | ||
40 | } | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * Process the html and extract image from it, save them to local and return the updated html. | ||
45 | * | ||
46 | * @param int $entryId ID of the entry | ||
47 | * @param string $html | ||
48 | * @param string $url Used as a base path for relative image and folder | ||
49 | * | ||
50 | * @return string | ||
51 | */ | ||
52 | public function processHtml($entryId, $html, $url) | ||
53 | { | ||
54 | $crawler = new Crawler($html); | ||
55 | $result = $crawler | ||
56 | ->filterXpath('//img') | ||
57 | ->extract(array('src')); | ||
58 | |||
59 | $relativePath = $this->getRelativePath($entryId); | ||
60 | |||
61 | // download and save the image to the folder | ||
62 | foreach ($result as $image) { | ||
63 | $imagePath = $this->processSingleImage($entryId, $image, $url, $relativePath); | ||
64 | |||
65 | if (false === $imagePath) { | ||
66 | continue; | ||
67 | } | ||
68 | |||
69 | $html = str_replace($image, $imagePath, $html); | ||
70 | } | ||
71 | |||
72 | return $html; | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * Process a single image: | ||
77 | * - retrieve it | ||
78 | * - re-saved it (for security reason) | ||
79 | * - return the new local path. | ||
80 | * | ||
81 | * @param int $entryId ID of the entry | ||
82 | * @param string $imagePath Path to the image to retrieve | ||
83 | * @param string $url Url from where the image were found | ||
84 | * @param string $relativePath Relative local path to saved the image | ||
85 | * | ||
86 | * @return string Relative url to access the image from the web | ||
87 | */ | ||
88 | public function processSingleImage($entryId, $imagePath, $url, $relativePath = null) | ||
89 | { | ||
90 | if (null === $relativePath) { | ||
91 | $relativePath = $this->getRelativePath($entryId); | ||
92 | } | ||
93 | |||
94 | $this->logger->debug('DownloadImages: working on image: '.$imagePath); | ||
95 | |||
96 | $folderPath = $this->baseFolder.'/'.$relativePath; | ||
97 | |||
98 | // build image path | ||
99 | $absolutePath = $this->getAbsoluteLink($url, $imagePath); | ||
100 | if (false === $absolutePath) { | ||
101 | $this->logger->error('DownloadImages: Can not determine the absolute path for that image, skipping.'); | ||
102 | |||
103 | return false; | ||
104 | } | ||
105 | |||
106 | try { | ||
107 | $res = $this->client->get($absolutePath); | ||
108 | } catch (\Exception $e) { | ||
109 | $this->logger->error('DownloadImages: Can not retrieve image, skipping.', ['exception' => $e]); | ||
110 | |||
111 | return false; | ||
112 | } | ||
113 | |||
114 | $ext = $this->mimeGuesser->guess($res->getHeader('content-type')); | ||
115 | $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]); | ||
116 | if (!in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) { | ||
117 | $this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping '.$imagePath); | ||
118 | |||
119 | return false; | ||
120 | } | ||
121 | $hashImage = hash('crc32', $absolutePath); | ||
122 | $localPath = $folderPath.'/'.$hashImage.'.'.$ext; | ||
123 | |||
124 | try { | ||
125 | $im = imagecreatefromstring($res->getBody()); | ||
126 | } catch (\Exception $e) { | ||
127 | $im = false; | ||
128 | } | ||
129 | |||
130 | if (false === $im) { | ||
131 | $this->logger->error('DownloadImages: Error while regenerating image', ['path' => $localPath]); | ||
132 | |||
133 | return false; | ||
134 | } | ||
135 | |||
136 | switch ($ext) { | ||
137 | case 'gif': | ||
138 | $result = imagegif($im, $localPath); | ||
139 | $this->logger->debug('DownloadImages: Re-creating gif'); | ||
140 | break; | ||
141 | case 'jpeg': | ||
142 | case 'jpg': | ||
143 | $result = imagejpeg($im, $localPath, self::REGENERATE_PICTURES_QUALITY); | ||
144 | $this->logger->debug('DownloadImages: Re-creating jpg'); | ||
145 | break; | ||
146 | case 'png': | ||
147 | $result = imagepng($im, $localPath, ceil(self::REGENERATE_PICTURES_QUALITY / 100 * 9)); | ||
148 | $this->logger->debug('DownloadImages: Re-creating png'); | ||
149 | } | ||
150 | |||
151 | imagedestroy($im); | ||
152 | |||
153 | return $this->wallabagUrl.'/assets/images/'.$relativePath.'/'.$hashImage.'.'.$ext; | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * Remove all images for the given entry id. | ||
158 | * | ||
159 | * @param int $entryId ID of the entry | ||
160 | */ | ||
161 | public function removeImages($entryId) | ||
162 | { | ||
163 | $relativePath = $this->getRelativePath($entryId); | ||
164 | $folderPath = $this->baseFolder.'/'.$relativePath; | ||
165 | |||
166 | $finder = new Finder(); | ||
167 | $finder | ||
168 | ->files() | ||
169 | ->ignoreDotFiles(true) | ||
170 | ->in($folderPath); | ||
171 | |||
172 | foreach ($finder as $file) { | ||
173 | @unlink($file->getRealPath()); | ||
174 | } | ||
175 | |||
176 | @rmdir($folderPath); | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * Generate the folder where we are going to save images based on the entry url. | ||
181 | * | ||
182 | * @param int $entryId ID of the entry | ||
183 | * | ||
184 | * @return string | ||
185 | */ | ||
186 | private function getRelativePath($entryId) | ||
187 | { | ||
188 | $hashId = hash('crc32', $entryId); | ||
189 | $relativePath = $hashId[0].'/'.$hashId[1].'/'.$hashId; | ||
190 | $folderPath = $this->baseFolder.'/'.$relativePath; | ||
191 | |||
192 | if (!file_exists($folderPath)) { | ||
193 | mkdir($folderPath, 0777, true); | ||
194 | } | ||
195 | |||
196 | $this->logger->debug('DownloadImages: Folder used for that Entry id', ['folder' => $folderPath, 'entryId' => $entryId]); | ||
197 | |||
198 | return $relativePath; | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * Make an $url absolute based on the $base. | ||
203 | * | ||
204 | * @see Graby->makeAbsoluteStr | ||
205 | * | ||
206 | * @param string $base Base url | ||
207 | * @param string $url Url to make it absolute | ||
208 | * | ||
209 | * @return false|string | ||
210 | */ | ||
211 | private function getAbsoluteLink($base, $url) | ||
212 | { | ||
213 | if (preg_match('!^https?://!i', $url)) { | ||
214 | // already absolute | ||
215 | return $url; | ||
216 | } | ||
217 | |||
218 | $base = new \SimplePie_IRI($base); | ||
219 | |||
220 | // remove '//' in URL path (causes URLs not to resolve properly) | ||
221 | if (isset($base->ipath)) { | ||
222 | $base->ipath = preg_replace('!//+!', '/', $base->ipath); | ||
223 | } | ||
224 | |||
225 | if ($absolute = \SimplePie_IRI::absolutize($base, $url)) { | ||
226 | return $absolute->get_uri(); | ||
227 | } | ||
228 | |||
229 | $this->logger->error('DownloadImages: Can not make an absolute link', ['base' => $base, 'url' => $url]); | ||
230 | |||
231 | return false; | ||
232 | } | ||
233 | } | ||
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 90a2419e..9786ac27 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml | |||
@@ -30,7 +30,7 @@ services: | |||
30 | - "@doctrine" | 30 | - "@doctrine" |
31 | 31 | ||
32 | wallabag_core.subscriber.table_prefix: | 32 | wallabag_core.subscriber.table_prefix: |
33 | class: Wallabag\CoreBundle\Subscriber\TablePrefixSubscriber | 33 | class: Wallabag\CoreBundle\Event\Subscriber\TablePrefixSubscriber |
34 | arguments: | 34 | arguments: |
35 | - "%database_table_prefix%" | 35 | - "%database_table_prefix%" |
36 | tags: | 36 | tags: |
@@ -130,3 +130,31 @@ services: | |||
130 | arguments: | 130 | arguments: |
131 | - '@twig' | 131 | - '@twig' |
132 | - '%kernel.debug%' | 132 | - '%kernel.debug%' |
133 | |||
134 | wallabag_core.subscriber.sqlite_cascade_delete: | ||
135 | class: Wallabag\CoreBundle\Event\Subscriber\SQLiteCascadeDeleteSubscriber | ||
136 | arguments: | ||
137 | - "@doctrine" | ||
138 | tags: | ||
139 | - { name: doctrine.event_subscriber } | ||
140 | |||
141 | wallabag_core.subscriber.download_images: | ||
142 | class: Wallabag\CoreBundle\Event\Subscriber\DownloadImagesSubscriber | ||
143 | arguments: | ||
144 | - "@doctrine.orm.default_entity_manager" | ||
145 | - "@wallabag_core.entry.download_images" | ||
146 | - '@=service(''craue_config'').get(''download_images_enabled'')' | ||
147 | - "@logger" | ||
148 | tags: | ||
149 | - { name: kernel.event_subscriber } | ||
150 | |||
151 | wallabag_core.entry.download_images: | ||
152 | class: Wallabag\CoreBundle\Helper\DownloadImages | ||
153 | arguments: | ||
154 | - "@wallabag_core.entry.download_images.client" | ||
155 | - "%kernel.root_dir%/../web/assets/images" | ||
156 | - '@=service(''craue_config'').get(''wallabag_url'')' | ||
157 | - "@logger" | ||
158 | |||
159 | wallabag_core.entry.download_images.client: | ||
160 | class: GuzzleHttp\Client | ||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml index 6ca7e459..aeae6bcf 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml | |||
@@ -71,6 +71,7 @@ config: | |||
71 | # 300_word: 'I read ~300 words per minute' | 71 | # 300_word: 'I read ~300 words per minute' |
72 | # 400_word: 'I read ~400 words per minute' | 72 | # 400_word: 'I read ~400 words per minute' |
73 | pocket_consumer_key_label: Brugers nøgle til Pocket for at importere materialer | 73 | pocket_consumer_key_label: Brugers nøgle til Pocket for at importere materialer |
74 | # android_configuration: Configure your Android application | ||
74 | form_rss: | 75 | form_rss: |
75 | description: 'RSS-feeds fra wallabag gør det muligt at læse de artikler, der gemmes i wallabag, med din RSS-læser. Det kræver, at du genererer et token først.' | 76 | description: 'RSS-feeds fra wallabag gør det muligt at læse de artikler, der gemmes i wallabag, med din RSS-læser. Det kræver, at du genererer et token først.' |
76 | token_label: 'RSS-Token' | 77 | token_label: 'RSS-Token' |
@@ -88,6 +89,18 @@ config: | |||
88 | name_label: 'Navn' | 89 | name_label: 'Navn' |
89 | email_label: 'Emailadresse' | 90 | email_label: 'Emailadresse' |
90 | # twoFactorAuthentication_label: 'Two factor authentication' | 91 | # twoFactorAuthentication_label: 'Two factor authentication' |
92 | delete: | ||
93 | # title: Delete my account (a.k.a danger zone) | ||
94 | # 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. | ||
95 | # confirm: Are you really sure? (THIS CAN'T BE UNDONE) | ||
96 | # button: Delete my account | ||
97 | reset: | ||
98 | # title: Reset area (a.k.a danger zone) | ||
99 | # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE. | ||
100 | # annotations: Remove ALL annotations | ||
101 | # tags: Remove ALL tags | ||
102 | # entries: Remove ALL entries | ||
103 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | ||
91 | form_password: | 104 | form_password: |
92 | old_password_label: 'Gammel adgangskode' | 105 | old_password_label: 'Gammel adgangskode' |
93 | new_password_label: 'Ny adgangskode' | 106 | new_password_label: 'Ny adgangskode' |
@@ -355,6 +368,7 @@ import: | |||
355 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' | 368 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' |
356 | worker: | 369 | worker: |
357 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" | 370 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" |
371 | # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors." | ||
358 | # firefox: | 372 | # firefox: |
359 | # page_title: 'Import > Firefox' | 373 | # page_title: 'Import > Firefox' |
360 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." | 374 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." |
@@ -458,8 +472,10 @@ flashes: | |||
458 | rss_updated: 'RSS-oplysninger opdateret' | 472 | rss_updated: 'RSS-oplysninger opdateret' |
459 | # tagging_rules_updated: 'Tagging rules updated' | 473 | # tagging_rules_updated: 'Tagging rules updated' |
460 | # tagging_rules_deleted: 'Tagging rule deleted' | 474 | # tagging_rules_deleted: 'Tagging rule deleted' |
461 | # user_added: 'User "%username%" added' | ||
462 | # rss_token_updated: 'RSS token updated' | 475 | # rss_token_updated: 'RSS token updated' |
476 | # annotations_reset: Annotations reset | ||
477 | # tags_reset: Tags reset | ||
478 | # entries_reset: Entries reset | ||
463 | entry: | 479 | entry: |
464 | notice: | 480 | notice: |
465 | # entry_already_saved: 'Entry already saved on %date%' | 481 | # entry_already_saved: 'Entry already saved on %date%' |
@@ -489,3 +505,8 @@ flashes: | |||
489 | notice: | 505 | notice: |
490 | # client_created: 'New client created.' | 506 | # client_created: 'New client created.' |
491 | # client_deleted: 'Client deleted' | 507 | # client_deleted: 'Client deleted' |
508 | user: | ||
509 | notice: | ||
510 | # added: 'User "%username%" added' | ||
511 | # updated: 'User "%username%" updated' | ||
512 | # deleted: 'User "%username%" deleted' | ||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml index 8fd1d82a..2105d02d 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml | |||
@@ -71,6 +71,7 @@ config: | |||
71 | 300_word: 'Ich lese ~300 Wörter pro Minute' | 71 | 300_word: 'Ich lese ~300 Wörter pro Minute' |
72 | 400_word: 'Ich lese ~400 Wörter pro Minute' | 72 | 400_word: 'Ich lese ~400 Wörter pro Minute' |
73 | pocket_consumer_key_label: Consumer-Key für Pocket, um Inhalte zu importieren | 73 | pocket_consumer_key_label: Consumer-Key für Pocket, um Inhalte zu importieren |
74 | # android_configuration: Configure your Android application | ||
74 | form_rss: | 75 | form_rss: |
75 | description: 'Die RSS-Feeds von wallabag erlauben es dir, deine gespeicherten Artikel mit deinem bevorzugten RSS-Reader zu lesen. Vorher musst du jedoch einen Token erstellen.' | 76 | description: 'Die RSS-Feeds von wallabag erlauben es dir, deine gespeicherten Artikel mit deinem bevorzugten RSS-Reader zu lesen. Vorher musst du jedoch einen Token erstellen.' |
76 | token_label: 'RSS-Token' | 77 | token_label: 'RSS-Token' |
@@ -88,6 +89,18 @@ config: | |||
88 | name_label: 'Name' | 89 | name_label: 'Name' |
89 | email_label: 'E-Mail-Adresse' | 90 | email_label: 'E-Mail-Adresse' |
90 | twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung' | 91 | twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung' |
92 | delete: | ||
93 | # title: Delete my account (a.k.a danger zone) | ||
94 | # 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. | ||
95 | # confirm: Are you really sure? (THIS CAN'T BE UNDONE) | ||
96 | # button: Delete my account | ||
97 | reset: | ||
98 | # title: Reset area (a.k.a danger zone) | ||
99 | # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE. | ||
100 | # annotations: Remove ALL annotations | ||
101 | # tags: Remove ALL tags | ||
102 | # entries: Remove ALL entries | ||
103 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | ||
91 | form_password: | 104 | form_password: |
92 | old_password_label: 'Altes Kennwort' | 105 | old_password_label: 'Altes Kennwort' |
93 | new_password_label: 'Neues Kennwort' | 106 | new_password_label: 'Neues Kennwort' |
@@ -355,6 +368,7 @@ import: | |||
355 | how_to: 'Bitte wähle deinen Readability Export aus und klicke den unteren Button für das Hochladen und Importieren dessen.' | 368 | how_to: 'Bitte wähle deinen Readability Export aus und klicke den unteren Button für das Hochladen und Importieren dessen.' |
356 | worker: | 369 | worker: |
357 | enabled: "Der Import erfolgt asynchron. Sobald der Import gestartet ist, wird diese Aufgabe extern abgearbeitet. Der aktuelle Service dafür ist:" | 370 | enabled: "Der Import erfolgt asynchron. Sobald der Import gestartet ist, wird diese Aufgabe extern abgearbeitet. Der aktuelle Service dafür ist:" |
371 | # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors." | ||
358 | firefox: | 372 | firefox: |
359 | page_title: 'Aus Firefox importieren' | 373 | page_title: 'Aus Firefox importieren' |
360 | description: "Dieser Import wird all deine Lesezeichen aus Firefox importieren. Gehe zu deinen Lesezeichen (Strg+Shift+O), dann auf \"Importen und Sichern\", wähle \"Sichern…\". Du erhälst eine .json Datei." | 374 | description: "Dieser Import wird all deine Lesezeichen aus Firefox importieren. Gehe zu deinen Lesezeichen (Strg+Shift+O), dann auf \"Importen und Sichern\", wähle \"Sichern…\". Du erhälst eine .json Datei." |
@@ -458,8 +472,10 @@ flashes: | |||
458 | rss_updated: 'RSS-Informationen aktualisiert' | 472 | rss_updated: 'RSS-Informationen aktualisiert' |
459 | tagging_rules_updated: 'Tagging-Regeln aktualisiert' | 473 | tagging_rules_updated: 'Tagging-Regeln aktualisiert' |
460 | tagging_rules_deleted: 'Tagging-Regel gelöscht' | 474 | tagging_rules_deleted: 'Tagging-Regel gelöscht' |
461 | user_added: 'Benutzer "%username%" erstellt' | ||
462 | rss_token_updated: 'RSS-Token aktualisiert' | 475 | rss_token_updated: 'RSS-Token aktualisiert' |
476 | # annotations_reset: Annotations reset | ||
477 | # tags_reset: Tags reset | ||
478 | # entries_reset: Entries reset | ||
463 | entry: | 479 | entry: |
464 | notice: | 480 | notice: |
465 | entry_already_saved: 'Eintrag bereits am %date% gespeichert' | 481 | entry_already_saved: 'Eintrag bereits am %date% gespeichert' |
@@ -489,3 +505,8 @@ flashes: | |||
489 | notice: | 505 | notice: |
490 | client_created: 'Neuer Client erstellt.' | 506 | client_created: 'Neuer Client erstellt.' |
491 | client_deleted: 'Client gelöscht' | 507 | client_deleted: 'Client gelöscht' |
508 | user: | ||
509 | notice: | ||
510 | # added: 'User "%username%" added' | ||
511 | # updated: 'User "%username%" updated' | ||
512 | # deleted: 'User "%username%" deleted' | ||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml index 02f56535..2bb95728 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml | |||
@@ -71,6 +71,7 @@ config: | |||
71 | 300_word: 'I read ~300 words per minute' | 71 | 300_word: 'I read ~300 words per minute' |
72 | 400_word: 'I read ~400 words per minute' | 72 | 400_word: 'I read ~400 words per minute' |
73 | pocket_consumer_key_label: Consumer key for Pocket to import contents | 73 | pocket_consumer_key_label: Consumer key for Pocket to import contents |
74 | android_configuration: Configure your Android application | ||
74 | form_rss: | 75 | form_rss: |
75 | description: 'RSS feeds provided by wallabag allow you to read your saved articles with your favourite RSS reader. You need to generate a token first.' | 76 | description: 'RSS feeds provided by wallabag allow you to read your saved articles with your favourite RSS reader. You need to generate a token first.' |
76 | token_label: 'RSS token' | 77 | token_label: 'RSS token' |
@@ -88,6 +89,18 @@ config: | |||
88 | name_label: 'Name' | 89 | name_label: 'Name' |
89 | email_label: 'Email' | 90 | email_label: 'Email' |
90 | twoFactorAuthentication_label: 'Two factor authentication' | 91 | twoFactorAuthentication_label: 'Two factor authentication' |
92 | delete: | ||
93 | title: Delete my account (a.k.a danger zone) | ||
94 | 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. | ||
95 | confirm: Are you really sure? (THIS CAN'T BE UNDONE) | ||
96 | button: Delete my account | ||
97 | reset: | ||
98 | title: Reset area (a.k.a danger zone) | ||
99 | description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE. | ||
100 | annotations: Remove ALL annotations | ||
101 | tags: Remove ALL tags | ||
102 | entries: Remove ALL entries | ||
103 | confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | ||
91 | form_password: | 104 | form_password: |
92 | old_password_label: 'Current password' | 105 | old_password_label: 'Current password' |
93 | new_password_label: 'New password' | 106 | new_password_label: 'New password' |
@@ -355,6 +368,7 @@ import: | |||
355 | how_to: 'Please select your Readability export and click on the below button to upload and import it.' | 368 | how_to: 'Please select your Readability export and click on the below button to upload and import it.' |
356 | worker: | 369 | worker: |
357 | enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" | 370 | enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" |
371 | download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors." | ||
358 | firefox: | 372 | firefox: |
359 | page_title: 'Import > Firefox' | 373 | page_title: 'Import > Firefox' |
360 | description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." | 374 | description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." |
@@ -459,6 +473,9 @@ flashes: | |||
459 | tagging_rules_updated: 'Tagging rules updated' | 473 | tagging_rules_updated: 'Tagging rules updated' |
460 | tagging_rules_deleted: 'Tagging rule deleted' | 474 | tagging_rules_deleted: 'Tagging rule deleted' |
461 | rss_token_updated: 'RSS token updated' | 475 | rss_token_updated: 'RSS token updated' |
476 | annotations_reset: Annotations reset | ||
477 | tags_reset: Tags reset | ||
478 | entries_reset: Entries reset | ||
462 | entry: | 479 | entry: |
463 | notice: | 480 | notice: |
464 | entry_already_saved: 'Entry already saved on %date%' | 481 | 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 42ec8183..ca3db487 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml | |||
@@ -71,6 +71,7 @@ config: | |||
71 | 300_word: 'Leo ~300 palabras por minuto' | 71 | 300_word: 'Leo ~300 palabras por minuto' |
72 | 400_word: 'Leo ~400 palabras por minuto' | 72 | 400_word: 'Leo ~400 palabras por minuto' |
73 | # pocket_consumer_key_label: Consumer key for Pocket to import contents | 73 | # pocket_consumer_key_label: Consumer key for Pocket to import contents |
74 | # android_configuration: Configure your Android application | ||
74 | form_rss: | 75 | form_rss: |
75 | description: 'Los feeds RSS de wallabag permiten leer los artículos guardados con su lector RSS favorito. Necesita generar un token primero' | 76 | description: 'Los feeds RSS de wallabag permiten leer los artículos guardados con su lector RSS favorito. Necesita generar un token primero' |
76 | token_label: 'RSS token' | 77 | token_label: 'RSS token' |
@@ -88,6 +89,18 @@ config: | |||
88 | name_label: 'Nombre' | 89 | name_label: 'Nombre' |
89 | email_label: 'Direccion e-mail' | 90 | email_label: 'Direccion e-mail' |
90 | twoFactorAuthentication_label: 'Autentificación de dos factores' | 91 | twoFactorAuthentication_label: 'Autentificación de dos factores' |
92 | delete: | ||
93 | # title: Delete my account (a.k.a danger zone) | ||
94 | # 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. | ||
95 | # confirm: Are you really sure? (THIS CAN'T BE UNDONE) | ||
96 | # button: Delete my account | ||
97 | reset: | ||
98 | # title: Reset area (a.k.a danger zone) | ||
99 | # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE. | ||
100 | # annotations: Remove ALL annotations | ||
101 | # tags: Remove ALL tags | ||
102 | # entries: Remove ALL entries | ||
103 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | ||
91 | form_password: | 104 | form_password: |
92 | old_password_label: 'Contraseña actual' | 105 | old_password_label: 'Contraseña actual' |
93 | new_password_label: 'Nueva contraseña' | 106 | new_password_label: 'Nueva contraseña' |
@@ -355,6 +368,7 @@ import: | |||
355 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' | 368 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' |
356 | worker: | 369 | worker: |
357 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" | 370 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" |
371 | # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors." | ||
358 | firefox: | 372 | firefox: |
359 | page_title: 'Importar > Firefox' | 373 | page_title: 'Importar > Firefox' |
360 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." | 374 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." |
@@ -458,8 +472,10 @@ flashes: | |||
458 | rss_updated: 'La configuración de los feeds RSS ha sido actualizada' | 472 | rss_updated: 'La configuración de los feeds RSS ha sido actualizada' |
459 | tagging_rules_updated: 'Regla de etiquetado borrada' | 473 | tagging_rules_updated: 'Regla de etiquetado borrada' |
460 | tagging_rules_deleted: 'Regla de etiquetado actualizada' | 474 | tagging_rules_deleted: 'Regla de etiquetado actualizada' |
461 | user_added: 'Usuario "%username%" añadido' | ||
462 | rss_token_updated: 'RSS token actualizado' | 475 | rss_token_updated: 'RSS token actualizado' |
476 | # annotations_reset: Annotations reset | ||
477 | # tags_reset: Tags reset | ||
478 | # entries_reset: Entries reset | ||
463 | entry: | 479 | entry: |
464 | notice: | 480 | notice: |
465 | entry_already_saved: 'Entrada ya guardada por %fecha%' | 481 | entry_already_saved: 'Entrada ya guardada por %fecha%' |
@@ -489,3 +505,8 @@ flashes: | |||
489 | notice: | 505 | notice: |
490 | client_created: 'Nuevo cliente creado.' | 506 | client_created: 'Nuevo cliente creado.' |
491 | client_deleted: 'Cliente suprimido' | 507 | client_deleted: 'Cliente suprimido' |
508 | user: | ||
509 | notice: | ||
510 | # added: 'User "%username%" added' | ||
511 | # updated: 'User "%username%" updated' | ||
512 | # deleted: 'User "%username%" deleted' | ||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml index f82167df..1914215a 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml | |||
@@ -71,6 +71,7 @@ config: | |||
71 | 300_word: 'من تقریباً ۳۰۰ واژه را در دقیقه میخوانم' | 71 | 300_word: 'من تقریباً ۳۰۰ واژه را در دقیقه میخوانم' |
72 | 400_word: 'من تقریباً ۴۰۰ واژه را در دقیقه میخوانم' | 72 | 400_word: 'من تقریباً ۴۰۰ واژه را در دقیقه میخوانم' |
73 | pocket_consumer_key_label: کلید کاربری Pocket برای درونریزی مطالب | 73 | pocket_consumer_key_label: کلید کاربری Pocket برای درونریزی مطالب |
74 | # android_configuration: Configure your Android application | ||
74 | form_rss: | 75 | form_rss: |
75 | description: 'با خوراک آر-اس-اس که wallabag در اختیارتان میگذارد، میتوانید مقالههای ذخیرهشده را در نرمافزار آر-اس-اس دلخواه خود بخوانید. برای این کار نخست باید یک کد بسازید.' | 76 | description: 'با خوراک آر-اس-اس که wallabag در اختیارتان میگذارد، میتوانید مقالههای ذخیرهشده را در نرمافزار آر-اس-اس دلخواه خود بخوانید. برای این کار نخست باید یک کد بسازید.' |
76 | token_label: 'کد آر-اس-اس' | 77 | token_label: 'کد آر-اس-اس' |
@@ -88,6 +89,18 @@ config: | |||
88 | name_label: 'نام' | 89 | name_label: 'نام' |
89 | email_label: 'نشانی ایمیل' | 90 | email_label: 'نشانی ایمیل' |
90 | twoFactorAuthentication_label: 'تأیید ۲مرحلهای' | 91 | twoFactorAuthentication_label: 'تأیید ۲مرحلهای' |
92 | delete: | ||
93 | # title: Delete my account (a.k.a danger zone) | ||
94 | # 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. | ||
95 | # confirm: Are you really sure? (THIS CAN'T BE UNDONE) | ||
96 | # button: Delete my account | ||
97 | reset: | ||
98 | # title: Reset area (a.k.a danger zone) | ||
99 | # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE. | ||
100 | # annotations: Remove ALL annotations | ||
101 | # tags: Remove ALL tags | ||
102 | # entries: Remove ALL entries | ||
103 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | ||
91 | form_password: | 104 | form_password: |
92 | old_password_label: 'رمز قدیمی' | 105 | old_password_label: 'رمز قدیمی' |
93 | new_password_label: 'رمز تازه' | 106 | new_password_label: 'رمز تازه' |
@@ -272,6 +285,7 @@ quickstart: | |||
272 | paragraph_2: 'ادامه دهید!' | 285 | paragraph_2: 'ادامه دهید!' |
273 | configure: | 286 | configure: |
274 | title: 'برنامه را تنظیم کنید' | 287 | title: 'برنامه را تنظیم کنید' |
288 | # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' | ||
275 | language: 'زبان و نمای برنامه را تغییر دهید' | 289 | language: 'زبان و نمای برنامه را تغییر دهید' |
276 | rss: 'خوراک آر-اس-اس را فعال کنید' | 290 | rss: 'خوراک آر-اس-اس را فعال کنید' |
277 | tagging_rules: 'قانونهای برچسبگذاری خودکار مقالههایتان را تعریف کنید' | 291 | tagging_rules: 'قانونهای برچسبگذاری خودکار مقالههایتان را تعریف کنید' |
@@ -354,6 +368,7 @@ import: | |||
354 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' | 368 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' |
355 | worker: | 369 | worker: |
356 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" | 370 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" |
371 | # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors." | ||
357 | firefox: | 372 | firefox: |
358 | page_title: 'درونریزی > Firefox' | 373 | page_title: 'درونریزی > Firefox' |
359 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." | 374 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." |
@@ -457,8 +472,10 @@ flashes: | |||
457 | rss_updated: 'اطلاعات آر-اس-اس بهروز شد' | 472 | rss_updated: 'اطلاعات آر-اس-اس بهروز شد' |
458 | tagging_rules_updated: 'برچسبگذاری خودکار بهروز شد' | 473 | tagging_rules_updated: 'برچسبگذاری خودکار بهروز شد' |
459 | tagging_rules_deleted: 'قانون برچسبگذاری پاک شد' | 474 | tagging_rules_deleted: 'قانون برچسبگذاری پاک شد' |
460 | user_added: 'کابر "%username%" افزوده شد' | ||
461 | rss_token_updated: 'کد آر-اس-اس بهروز شد' | 475 | rss_token_updated: 'کد آر-اس-اس بهروز شد' |
476 | # annotations_reset: Annotations reset | ||
477 | # tags_reset: Tags reset | ||
478 | # entries_reset: Entries reset | ||
462 | entry: | 479 | entry: |
463 | notice: | 480 | notice: |
464 | entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود' | 481 | entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود' |
@@ -488,3 +505,8 @@ flashes: | |||
488 | notice: | 505 | notice: |
489 | # client_created: 'New client created.' | 506 | # client_created: 'New client created.' |
490 | # client_deleted: 'Client deleted' | 507 | # client_deleted: 'Client deleted' |
508 | user: | ||
509 | notice: | ||
510 | # added: 'User "%username%" added' | ||
511 | # updated: 'User "%username%" updated' | ||
512 | # deleted: 'User "%username%" deleted' | ||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml index 421cb8b5..60fa9a39 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml | |||
@@ -71,6 +71,7 @@ config: | |||
71 | 300_word: "Je lis environ 300 mots par minute" | 71 | 300_word: "Je lis environ 300 mots par minute" |
72 | 400_word: "Je lis environ 400 mots par minute" | 72 | 400_word: "Je lis environ 400 mots par minute" |
73 | pocket_consumer_key_label: Clé d’authentification Pocket pour importer les données | 73 | pocket_consumer_key_label: Clé d’authentification Pocket pour importer les données |
74 | android_configuration: Configurez votre application Android | ||
74 | form_rss: | 75 | form_rss: |
75 | description: "Les flux RSS fournis par wallabag vous permettent de lire vos articles sauvegardés dans votre lecteur de flux préféré. Pour pouvoir les utiliser, vous devez d’abord créer un jeton." | 76 | description: "Les flux RSS fournis par wallabag vous permettent de lire vos articles sauvegardés dans votre lecteur de flux préféré. Pour pouvoir les utiliser, vous devez d’abord créer un jeton." |
76 | token_label: "Jeton RSS" | 77 | token_label: "Jeton RSS" |
@@ -88,6 +89,18 @@ config: | |||
88 | name_label: "Nom" | 89 | name_label: "Nom" |
89 | email_label: "Adresse courriel" | 90 | email_label: "Adresse courriel" |
90 | twoFactorAuthentication_label: "Double authentification" | 91 | twoFactorAuthentication_label: "Double authentification" |
92 | delete: | ||
93 | title: Supprimer mon compte (attention danger !) | ||
94 | 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é. | ||
95 | confirm: Vous êtes vraiment sûr ? (C'EST IRRÉVERSIBLE) | ||
96 | button: 'Supprimer mon compte' | ||
97 | reset: | ||
98 | title: Réinitialisation (attention danger !) | ||
99 | 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 ! | ||
100 | annotations: Supprimer TOUTES les annotations | ||
101 | tags: Supprimer TOUS les tags | ||
102 | entries: Supprimer TOUS les articles | ||
103 | confirm: Êtes-vous vraiment vraiment sûr ? (C'EST IRRÉVERSIBLE) | ||
91 | form_password: | 104 | form_password: |
92 | old_password_label: "Mot de passe actuel" | 105 | old_password_label: "Mot de passe actuel" |
93 | new_password_label: "Nouveau mot de passe" | 106 | new_password_label: "Nouveau mot de passe" |
@@ -355,6 +368,7 @@ import: | |||
355 | how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l’importer." | 368 | how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l’importer." |
356 | worker: | 369 | worker: |
357 | enabled: "Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :" | 370 | enabled: "Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :" |
371 | download_images_warning: "Vous avez configuré le téléchagement des images pour vos articles. Combiné à l'import classique, cette opération peut être très très longue (voire échouer). Nous vous conseillons <strong>vivement</strong> d'activer les imports asynchrones." | ||
358 | firefox: | 372 | firefox: |
359 | page_title: "Import > Firefox" | 373 | page_title: "Import > Firefox" |
360 | description: "Cet outil va vous permettre d’importer tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde... ». Vous allez récupérer un fichier .json. </p>" | 374 | description: "Cet outil va vous permettre d’importer tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde... ». Vous allez récupérer un fichier .json. </p>" |
@@ -458,8 +472,10 @@ flashes: | |||
458 | rss_updated: "La configuration des flux RSS a bien été mise à jour" | 472 | rss_updated: "La configuration des flux RSS a bien été mise à jour" |
459 | tagging_rules_updated: "Règles mises à jour" | 473 | tagging_rules_updated: "Règles mises à jour" |
460 | tagging_rules_deleted: "Règle supprimée" | 474 | tagging_rules_deleted: "Règle supprimée" |
461 | user_added: "Utilisateur \"%username%\" ajouté" | ||
462 | rss_token_updated: "Jeton RSS mis à jour" | 475 | rss_token_updated: "Jeton RSS mis à jour" |
476 | annotations_reset: Annotations supprimées | ||
477 | tags_reset: Tags supprimés | ||
478 | entries_reset: Articles supprimés | ||
463 | entry: | 479 | entry: |
464 | notice: | 480 | notice: |
465 | entry_already_saved: "Article déjà sauvergardé le %date%" | 481 | entry_already_saved: "Article déjà sauvergardé le %date%" |
@@ -489,3 +505,8 @@ flashes: | |||
489 | notice: | 505 | notice: |
490 | client_created: "Nouveau client %name% créé" | 506 | client_created: "Nouveau client %name% créé" |
491 | client_deleted: "Client %name% supprimé" | 507 | client_deleted: "Client %name% supprimé" |
508 | user: | ||
509 | notice: | ||
510 | added: 'Utilisateur "%username%" ajouté' | ||
511 | updated: 'Utilisateur "%username%" mis à jour' | ||
512 | deleted: 'Utilisateur "%username%" supprimé' | ||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml index d679ef00..7f401684 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml | |||
@@ -71,6 +71,7 @@ config: | |||
71 | 300_word: 'Leggo ~300 parole al minuto' | 71 | 300_word: 'Leggo ~300 parole al minuto' |
72 | 400_word: 'Leggo ~400 parole al minuto' | 72 | 400_word: 'Leggo ~400 parole al minuto' |
73 | pocket_consumer_key_label: Consumer key per Pocket per importare i contenuti | 73 | pocket_consumer_key_label: Consumer key per Pocket per importare i contenuti |
74 | # android_configuration: Configure your Android application | ||
74 | form_rss: | 75 | form_rss: |
75 | description: 'I feed RSS generati da wallabag ti permettono di leggere i tuoi contenuti salvati con il tuo lettore di RSS preferito. Prima, devi generare un token.' | 76 | description: 'I feed RSS generati da wallabag ti permettono di leggere i tuoi contenuti salvati con il tuo lettore di RSS preferito. Prima, devi generare un token.' |
76 | token_label: 'RSS token' | 77 | token_label: 'RSS token' |
@@ -88,6 +89,18 @@ config: | |||
88 | name_label: 'Nome' | 89 | name_label: 'Nome' |
89 | email_label: 'E-mail' | 90 | email_label: 'E-mail' |
90 | twoFactorAuthentication_label: 'Two factor authentication' | 91 | twoFactorAuthentication_label: 'Two factor authentication' |
92 | delete: | ||
93 | # title: Delete my account (a.k.a danger zone) | ||
94 | # 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. | ||
95 | # confirm: Are you really sure? (THIS CAN'T BE UNDONE) | ||
96 | # button: Delete my account | ||
97 | reset: | ||
98 | # title: Reset area (a.k.a danger zone) | ||
99 | # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE. | ||
100 | # annotations: Remove ALL annotations | ||
101 | # tags: Remove ALL tags | ||
102 | # entries: Remove ALL entries | ||
103 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | ||
91 | form_password: | 104 | form_password: |
92 | old_password_label: 'Password corrente' | 105 | old_password_label: 'Password corrente' |
93 | new_password_label: 'Nuova password' | 106 | new_password_label: 'Nuova password' |
@@ -355,6 +368,7 @@ import: | |||
355 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' | 368 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' |
356 | worker: | 369 | worker: |
357 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" | 370 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" |
371 | # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors." | ||
358 | firefox: | 372 | firefox: |
359 | page_title: 'Importa da > Firefox' | 373 | page_title: 'Importa da > Firefox' |
360 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." | 374 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." |
@@ -458,8 +472,10 @@ flashes: | |||
458 | rss_updated: 'Informazioni RSS aggiornate' | 472 | rss_updated: 'Informazioni RSS aggiornate' |
459 | tagging_rules_updated: 'Regole di tagging aggiornate' | 473 | tagging_rules_updated: 'Regole di tagging aggiornate' |
460 | tagging_rules_deleted: 'Regola di tagging aggiornate' | 474 | tagging_rules_deleted: 'Regola di tagging aggiornate' |
461 | user_added: 'Utente "%username%" aggiunto' | ||
462 | rss_token_updated: 'RSS token aggiornato' | 475 | rss_token_updated: 'RSS token aggiornato' |
476 | # annotations_reset: Annotations reset | ||
477 | # tags_reset: Tags reset | ||
478 | # entries_reset: Entries reset | ||
463 | entry: | 479 | entry: |
464 | notice: | 480 | notice: |
465 | entry_already_saved: 'Contenuto già salvato in data %date%' | 481 | entry_already_saved: 'Contenuto già salvato in data %date%' |
@@ -489,3 +505,8 @@ flashes: | |||
489 | notice: | 505 | notice: |
490 | client_created: 'Nuovo client creato.' | 506 | client_created: 'Nuovo client creato.' |
491 | client_deleted: 'Client eliminato' | 507 | client_deleted: 'Client eliminato' |
508 | user: | ||
509 | notice: | ||
510 | # added: 'User "%username%" added' | ||
511 | # updated: 'User "%username%" updated' | ||
512 | # deleted: 'User "%username%" deleted' | ||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml index af0fba0d..c3282b0e 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 | ||
51 | config: | 51 | config: |
52 | page_title: 'Configuracion' | 52 | page_title: 'Configuracion' |
@@ -71,6 +71,7 @@ config: | |||
71 | 300_word: "Legissi a l'entorn de 300 mots per minuta" | 71 | 300_word: "Legissi a l'entorn de 300 mots per minuta" |
72 | 400_word: "Legissi a l'entorn de 400 mots per minuta" | 72 | 400_word: "Legissi a l'entorn de 400 mots per minuta" |
73 | pocket_consumer_key_label: Clau d'autentificacion Pocket per importar las donadas | 73 | pocket_consumer_key_label: Clau d'autentificacion Pocket per importar las donadas |
74 | # android_configuration: Configure your Android application | ||
74 | form_rss: | 75 | form_rss: |
75 | description: "Los fluxes RSS fornits per wallabag vos permeton de legir vòstres articles salvagardats dins vòstre lector de fluxes preferit. Per los poder emplegar, vos cal, d'en primièr crear un geton." | 76 | description: "Los fluxes RSS fornits per wallabag vos permeton de legir vòstres articles salvagardats dins vòstre lector de fluxes preferit. Per los poder emplegar, vos cal, d'en primièr crear un geton." |
76 | token_label: 'Geton RSS' | 77 | token_label: 'Geton RSS' |
@@ -88,6 +89,18 @@ config: | |||
88 | name_label: 'Nom' | 89 | name_label: 'Nom' |
89 | email_label: 'Adreça de corrièl' | 90 | email_label: 'Adreça de corrièl' |
90 | twoFactorAuthentication_label: 'Dobla autentificacion' | 91 | twoFactorAuthentication_label: 'Dobla autentificacion' |
92 | delete: | ||
93 | # title: Delete my account (a.k.a danger zone) | ||
94 | # 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. | ||
95 | # confirm: Are you really sure? (THIS CAN'T BE UNDONE) | ||
96 | # button: Delete my account | ||
97 | reset: | ||
98 | # title: Reset area (a.k.a danger zone) | ||
99 | # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE. | ||
100 | # annotations: Remove ALL annotations | ||
101 | # tags: Remove ALL tags | ||
102 | # entries: Remove ALL entries | ||
103 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | ||
91 | form_password: | 104 | form_password: |
92 | old_password_label: 'Senhal actual' | 105 | old_password_label: 'Senhal actual' |
93 | new_password_label: 'Senhal novèl' | 106 | new_password_label: 'Senhal novèl' |
@@ -96,7 +109,7 @@ config: | |||
96 | if_label: 'se' | 109 | if_label: 'se' |
97 | then_tag_as_label: 'alara atribuir las etiquetas' | 110 | then_tag_as_label: 'alara atribuir las etiquetas' |
98 | delete_rule_label: 'suprimir' | 111 | delete_rule_label: 'suprimir' |
99 | # edit_rule_label: 'edit' | 112 | edit_rule_label: 'modificar' |
100 | rule_label: 'Règla' | 113 | rule_label: 'Règla' |
101 | tags_label: 'Etiquetas' | 114 | tags_label: 'Etiquetas' |
102 | faq: | 115 | faq: |
@@ -209,7 +222,7 @@ entry: | |||
209 | is_public_label: 'Public' | 222 | is_public_label: 'Public' |
210 | save_label: 'Enregistrar' | 223 | save_label: 'Enregistrar' |
211 | public: | 224 | public: |
212 | # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" | 225 | shared_by_wallabag: "Aqueste article es estat partejat per <a href='%wallabag_instance%'>wallabag</a>" |
213 | 226 | ||
214 | about: | 227 | about: |
215 | page_title: 'A prepaus' | 228 | page_title: 'A prepaus' |
@@ -265,14 +278,14 @@ howto: | |||
265 | 278 | ||
266 | quickstart: | 279 | quickstart: |
267 | page_title: 'Per ben començar' | 280 | page_title: 'Per ben començar' |
268 | # more: 'More…' | 281 | more: 'Mai…' |
269 | intro: | 282 | intro: |
270 | title: 'Benvenguda sus wallabag !' | 283 | 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." | 284 | 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 ' | 285 | paragraph_2: 'Seguètz-nos ' |
273 | configure: | 286 | configure: |
274 | title: "Configuratz l'aplicacio" | 287 | title: "Configuratz l'aplicacion" |
275 | # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' | 288 | 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" | 289 | language: "Cambiatz la lenga e l'estil de l'aplicacion" |
277 | rss: 'Activatz los fluxes RSS' | 290 | rss: 'Activatz los fluxes RSS' |
278 | tagging_rules: 'Escrivètz de règlas per classar automaticament vòstres articles' | 291 | tagging_rules: 'Escrivètz de règlas per classar automaticament vòstres articles' |
@@ -286,7 +299,7 @@ quickstart: | |||
286 | import: 'Configurar los impòrt' | 299 | import: 'Configurar los impòrt' |
287 | first_steps: | 300 | first_steps: |
288 | title: 'Primièrs passes' | 301 | 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." | 302 | 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' | 303 | new_article: 'Ajustatz vòstre primièr article' |
291 | unread_articles: 'E racaptatz-lo !' | 304 | unread_articles: 'E racaptatz-lo !' |
292 | migrate: | 305 | migrate: |
@@ -298,14 +311,14 @@ quickstart: | |||
298 | readability: 'Migrar dempuèi Readability' | 311 | readability: 'Migrar dempuèi Readability' |
299 | instapaper: 'Migrar dempuèi Instapaper' | 312 | instapaper: 'Migrar dempuèi Instapaper' |
300 | developer: | 313 | developer: |
301 | title: 'Pels desvolopadors' | 314 | title: 'Pels desvolopaires' |
302 | # description: 'We also thought to the developers: Docker, API, translations, etc.' | 315 | description: 'Avèm tanben pensat als desvolopaires : Docker, API, traduccions, etc.' |
303 | create_application: 'Crear vòstra aplicacion tèrça' | 316 | create_application: 'Crear vòstra aplicacion tèrça' |
304 | # use_docker: 'Use Docker to install wallabag' | 317 | use_docker: 'Utilizar Docker per installar wallabag' |
305 | docs: | 318 | docs: |
306 | title: 'Documentacion complèta' | 319 | 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." | 320 | 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' | 321 | annotate: 'Anotar vòstre article' |
309 | export: 'Convertissètz vòstres articles en ePub o en PDF' | 322 | 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" | 323 | 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 ?" | 324 | fetching_errors: "Qué far se mon article es pas recuperat coma cal ?" |
@@ -355,6 +368,7 @@ import: | |||
355 | how_to: "Mercés de seleccionar vòstre Readability fichièr e de clicar sul boton dejós per lo telecargar e l'importar." | 368 | how_to: "Mercés de seleccionar vòstre Readability fichièr e de clicar sul boton dejós per lo telecargar e l'importar." |
356 | worker: | 369 | worker: |
357 | enabled: "L'importacion se fa de manièra asincròna. Un còp l'importacion lançada, una aisina externa s'ocuparà dels messatges un per un. Lo servici actual es : " | 370 | enabled: "L'importacion se fa de manièra asincròna. Un còp l'importacion lançada, una aisina externa s'ocuparà dels messatges un per un. Lo servici actual es : " |
371 | # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors." | ||
358 | firefox: | 372 | firefox: |
359 | page_title: 'Importar > Firefox' | 373 | page_title: 'Importar > Firefox' |
360 | description: "Aquesta aisina importarà totas vòstres favorits de Firefox. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." | 374 | description: "Aquesta aisina importarà totas vòstres favorits de Firefox. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." |
@@ -390,7 +404,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." | 404 | 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' | 405 | action: 'Suprimir aqueste client' |
392 | client: | 406 | client: |
393 | page_title: 'Desvlopador > Novèl client' | 407 | 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." | 408 | page_description: "Anatz crear un novèl client. Mercés de cumplir l'url de redireccion cap a vòstra aplicacion." |
395 | form: | 409 | form: |
396 | name_label: "Nom del client" | 410 | name_label: "Nom del client" |
@@ -398,7 +412,7 @@ developer: | |||
398 | save_label: 'Crear un novèl client' | 412 | save_label: 'Crear un novèl client' |
399 | action_back: 'Retorn' | 413 | action_back: 'Retorn' |
400 | client_parameter: | 414 | client_parameter: |
401 | page_title: 'Desvolopador > Los paramètres de vòstre client' | 415 | page_title: 'Desvolopaire > Los paramètres de vòstre client' |
402 | page_description: 'Vaquí los paramètres de vòstre client' | 416 | page_description: 'Vaquí los paramètres de vòstre client' |
403 | field_name: 'Nom del client' | 417 | field_name: 'Nom del client' |
404 | field_id: 'ID Client' | 418 | field_id: 'ID Client' |
@@ -406,7 +420,7 @@ developer: | |||
406 | back: 'Retour' | 420 | back: 'Retour' |
407 | read_howto: 'Legir "cossí crear ma primièra aplicacion"' | 421 | read_howto: 'Legir "cossí crear ma primièra aplicacion"' |
408 | howto: | 422 | howto: |
409 | page_title: 'Desvolopador > Cossí crear ma primièra aplicacion' | 423 | page_title: 'Desvolopaire > Cossí crear ma primièra aplicacion' |
410 | description: | 424 | 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." | 425 | 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." | 426 | paragraph_2: "Vos cal un geton per escambiar entre vòstra aplicacion e l'API de wallabar." |
@@ -419,31 +433,31 @@ developer: | |||
419 | back: 'Retorn' | 433 | back: 'Retorn' |
420 | 434 | ||
421 | user: | 435 | user: |
422 | # page_title: Users management | 436 | page_title: 'Gestion dels utilizaires' |
423 | # new_user: Create a new user | 437 | new_user: 'Crear un novèl utilizaire' |
424 | # edit_user: Edit an existing user | 438 | edit_user: 'Modificar un utilizaire existent' |
425 | # description: "Here you can manage all users (create, edit and delete)" | 439 | description: "Aquí podètz gerir totes los utilizaires (crear, modificar e suprimir)" |
426 | # list: | 440 | list: |
427 | # actions: Actions | 441 | actions: 'Accions' |
428 | # edit_action: Edit | 442 | edit_action: 'Modificar' |
429 | # yes: Yes | 443 | yes: 'Òc' |
430 | # no: No | 444 | no: 'Non' |
431 | # create_new_one: Create a new user | 445 | create_new_one: 'Crear un novèl utilizaire' |
432 | form: | 446 | form: |
433 | username_label: "Nom d'utilizaire" | 447 | username_label: "Nom d'utilizaire" |
434 | # name_label: 'Name' | 448 | name_label: 'Nom' |
435 | password_label: 'Senhal' | 449 | password_label: 'Senhal' |
436 | repeat_new_password_label: 'Confirmatz vòstre novèl senhal' | 450 | repeat_new_password_label: 'Confirmatz vòstre novèl senhal' |
437 | plain_password_label: 'Senhal en clar' | 451 | plain_password_label: 'Senhal en clar' |
438 | email_label: 'Adreça de corrièl' | 452 | email_label: 'Adreça de corrièl' |
439 | # enabled_label: 'Enabled' | 453 | enabled_label: 'Actiu' |
440 | # locked_label: 'Locked' | 454 | locked_label: 'Varrolhat' |
441 | # last_login_label: 'Last login' | 455 | last_login_label: 'Darrièra connexion' |
442 | # twofactor_label: Two factor authentication | 456 | twofactor_label: 'Autentificacion doble-factor' |
443 | # save: Save | 457 | save: 'Enregistrar' |
444 | # delete: Delete | 458 | delete: 'Suprimir' |
445 | # delete_confirm: Are you sure? | 459 | delete_confirm: 'Sètz segur ?' |
446 | # back_to_list: Back to list | 460 | back_to_list: 'Tornar a la lista' |
447 | 461 | ||
448 | error: | 462 | error: |
449 | # page_title: An error occurred | 463 | # page_title: An error occurred |
@@ -458,8 +472,10 @@ flashes: | |||
458 | rss_updated: 'La configuracion dels fluxes RSS es ben estada mesa a jorn' | 472 | rss_updated: 'La configuracion dels fluxes RSS es ben estada mesa a jorn' |
459 | tagging_rules_updated: 'Règlas misa a jorn' | 473 | tagging_rules_updated: 'Règlas misa a jorn' |
460 | tagging_rules_deleted: 'Règla suprimida' | 474 | tagging_rules_deleted: 'Règla suprimida' |
461 | user_added: 'Utilizaire "%username%" apondut' | ||
462 | rss_token_updated: 'Geton RSS mes a jorn' | 475 | rss_token_updated: 'Geton RSS mes a jorn' |
476 | # annotations_reset: Annotations reset | ||
477 | # tags_reset: Tags reset | ||
478 | # entries_reset: Entries reset | ||
463 | entry: | 479 | entry: |
464 | notice: | 480 | notice: |
465 | entry_already_saved: 'Article ja salvargardat lo %date%' | 481 | entry_already_saved: 'Article ja salvargardat lo %date%' |
@@ -470,12 +486,12 @@ flashes: | |||
470 | entry_reloaded_failed: "L'article es estat cargat de nòu mai la recuperacion del contengut a fracassat" | 486 | 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' | 487 | entry_archived: 'Article marcat coma legit' |
472 | entry_unarchived: 'Article marcat coma pas legit' | 488 | entry_unarchived: 'Article marcat coma pas legit' |
473 | entry_starred: 'Article apondut dins los favorits' | 489 | entry_starred: 'Article ajustat dins los favorits' |
474 | entry_unstarred: 'Article quitat dels favorits' | 490 | entry_unstarred: 'Article quitat dels favorits' |
475 | entry_deleted: 'Article suprimit' | 491 | entry_deleted: 'Article suprimit' |
476 | tag: | 492 | tag: |
477 | notice: | 493 | notice: |
478 | tag_added: 'Etiqueta aponduda' | 494 | tag_added: 'Etiqueta ajustada' |
479 | import: | 495 | import: |
480 | notice: | 496 | notice: |
481 | failed: "L'importacion a fracassat, mercés de tornar ensajar" | 497 | failed: "L'importacion a fracassat, mercés de tornar ensajar" |
@@ -489,3 +505,8 @@ flashes: | |||
489 | notice: | 505 | notice: |
490 | client_created: 'Novèl client creat' | 506 | client_created: 'Novèl client creat' |
491 | client_deleted: 'Client suprimit' | 507 | client_deleted: 'Client suprimit' |
508 | user: | ||
509 | notice: | ||
510 | # added: 'User "%username%" added' | ||
511 | # updated: 'User "%username%" updated' | ||
512 | # deleted: 'User "%username%" deleted' | ||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml index bf47b58a..87731faf 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml | |||
@@ -71,6 +71,7 @@ config: | |||
71 | 300_word: 'Czytam ~300 słów na minutę' | 71 | 300_word: 'Czytam ~300 słów na minutę' |
72 | 400_word: 'Czytam ~400 słów na minutę' | 72 | 400_word: 'Czytam ~400 słów na minutę' |
73 | pocket_consumer_key_label: 'Klucz klienta Pocket do importu zawartości' | 73 | pocket_consumer_key_label: 'Klucz klienta Pocket do importu zawartości' |
74 | # android_configuration: Configure your Android application | ||
74 | form_rss: | 75 | form_rss: |
75 | description: 'Kanały RSS prowadzone przez wallabag pozwalają Ci na czytanie twoich zapisanych artykułów w twoium ulubionym czytniku RSS. Musisz najpierw wynegenerować tokena.' | 76 | description: 'Kanały RSS prowadzone przez wallabag pozwalają Ci na czytanie twoich zapisanych artykułów w twoium ulubionym czytniku RSS. Musisz najpierw wynegenerować tokena.' |
76 | token_label: 'Token RSS' | 77 | token_label: 'Token RSS' |
@@ -88,6 +89,18 @@ config: | |||
88 | name_label: 'Nazwa' | 89 | name_label: 'Nazwa' |
89 | email_label: 'Adres email' | 90 | email_label: 'Adres email' |
90 | twoFactorAuthentication_label: 'Autoryzacja dwuetapowa' | 91 | twoFactorAuthentication_label: 'Autoryzacja dwuetapowa' |
92 | delete: | ||
93 | title: Usuń moje konto (niebezpieczna strefa !) | ||
94 | 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. | ||
95 | confirm: Jesteś pewien? (tej operacji NIE MOŻNA cofnąć) | ||
96 | button: Usuń moje konto | ||
97 | reset: | ||
98 | title: Reset (niebezpieczna strefa) | ||
99 | description: Poniższe przyciski pozwalają usunąć pewne informacje z twojego konta. Uważaj te operacje są NIEODWRACALNE. | ||
100 | annotations: Usuń WSZYSTKIE adnotacje | ||
101 | tags: Usuń WSZYSTKIE tagi | ||
102 | entries: usuń WSZYTSTKIE wpisy | ||
103 | confirm: Jesteś pewien? (tej operacji NIE MOŻNA cofnąć) | ||
91 | form_password: | 104 | form_password: |
92 | old_password_label: 'Stare hasło' | 105 | old_password_label: 'Stare hasło' |
93 | new_password_label: 'Nowe hasło' | 106 | new_password_label: 'Nowe hasło' |
@@ -355,6 +368,7 @@ import: | |||
355 | how_to: 'Wybierz swój plik eksportu z Readability i kliknij poniższy przycisk, aby go załadować.' | 368 | how_to: 'Wybierz swój plik eksportu z Readability i kliknij poniższy przycisk, aby go załadować.' |
356 | worker: | 369 | worker: |
357 | enabled: "Import jest wykonywany asynchronicznie. Od momentu rozpoczęcia importu, zewnętrzna usługa może zajmować się na raz tylko jednym zadaniem. Bieżącą usługą jest:" | 370 | enabled: "Import jest wykonywany asynchronicznie. Od momentu rozpoczęcia importu, zewnętrzna usługa może zajmować się na raz tylko jednym zadaniem. Bieżącą usługą jest:" |
371 | # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors." | ||
358 | firefox: | 372 | firefox: |
359 | page_title: 'Import > Firefox' | 373 | page_title: 'Import > Firefox' |
360 | description: "Ten importer zaimportuje wszystkie twoje zakładki z Firefoksa. Idź do twoich zakładek (Ctrl+Shift+O), następnie w \"Import i kopie zapasowe\", wybierz \"Utwórz kopię zapasową...\". Uzyskasz plik .json." | 374 | description: "Ten importer zaimportuje wszystkie twoje zakładki z Firefoksa. Idź do twoich zakładek (Ctrl+Shift+O), następnie w \"Import i kopie zapasowe\", wybierz \"Utwórz kopię zapasową...\". Uzyskasz plik .json." |
@@ -446,7 +460,7 @@ user: | |||
446 | back_to_list: Powrót do listy | 460 | back_to_list: Powrót do listy |
447 | 461 | ||
448 | error: | 462 | error: |
449 | # page_title: An error occurred | 463 | page_title: Wystąpił błąd |
450 | 464 | ||
451 | flashes: | 465 | flashes: |
452 | config: | 466 | config: |
@@ -458,8 +472,10 @@ flashes: | |||
458 | rss_updated: 'Informacje RSS zaktualizowane' | 472 | rss_updated: 'Informacje RSS zaktualizowane' |
459 | tagging_rules_updated: 'Reguły tagowania zaktualizowane' | 473 | tagging_rules_updated: 'Reguły tagowania zaktualizowane' |
460 | tagging_rules_deleted: 'Reguła tagowania usunięta' | 474 | tagging_rules_deleted: 'Reguła tagowania usunięta' |
461 | user_added: 'Użytkownik "%username%" dodany' | ||
462 | rss_token_updated: 'Token kanału RSS zaktualizowany' | 475 | rss_token_updated: 'Token kanału RSS zaktualizowany' |
476 | annotations_reset: Zresetuj adnotacje | ||
477 | tags_reset: Zresetuj tagi | ||
478 | entries_reset: Zresetuj wpisy | ||
463 | entry: | 479 | entry: |
464 | notice: | 480 | notice: |
465 | entry_already_saved: 'Wpis już został dodany %date%' | 481 | entry_already_saved: 'Wpis już został dodany %date%' |
@@ -489,3 +505,8 @@ flashes: | |||
489 | notice: | 505 | notice: |
490 | client_created: 'Nowy klient utworzony.' | 506 | client_created: 'Nowy klient utworzony.' |
491 | client_deleted: 'Klient usunięty' | 507 | client_deleted: 'Klient usunięty' |
508 | user: | ||
509 | notice: | ||
510 | # added: 'User "%username%" added' | ||
511 | # updated: 'User "%username%" updated' | ||
512 | # deleted: 'User "%username%" deleted' | ||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml index f10dc9aa..c1c60430 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml | |||
@@ -451,7 +451,6 @@ flashes: | |||
451 | config_saved: 'Configiração salva. Alguns parâmetros podem ser considerados depois da desconexão.' | 451 | config_saved: 'Configiração salva. Alguns parâmetros podem ser considerados depois da desconexão.' |
452 | password_updated: 'Senha atualizada' | 452 | password_updated: 'Senha atualizada' |
453 | password_not_updated_demo: 'Em modo de demonstração, você não pode alterar a senha deste usuário.' | 453 | password_not_updated_demo: 'Em modo de demonstração, você não pode alterar a senha deste usuário.' |
454 | user_updated: 'Informação atualizada' | ||
455 | rss_updated: 'Informação de RSS atualizada' | 454 | rss_updated: 'Informação de RSS atualizada' |
456 | tagging_rules_updated: 'Regras de tags atualizadas' | 455 | tagging_rules_updated: 'Regras de tags atualizadas' |
457 | tagging_rules_deleted: 'Regra de tag apagada' | 456 | tagging_rules_deleted: 'Regra de tag apagada' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml index 875c82e8..50f1b6a2 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml | |||
@@ -71,6 +71,7 @@ config: | |||
71 | # 300_word: 'I read ~300 words per minute' | 71 | # 300_word: 'I read ~300 words per minute' |
72 | # 400_word: 'I read ~400 words per minute' | 72 | # 400_word: 'I read ~400 words per minute' |
73 | pocket_consumer_key_label: Cheie consumator pentru importarea contentului din Pocket | 73 | pocket_consumer_key_label: Cheie consumator pentru importarea contentului din Pocket |
74 | # android_configuration: Configure your Android application | ||
74 | form_rss: | 75 | form_rss: |
75 | description: 'Feed-urile RSS oferite de wallabag îți permit să-ți citești articolele salvate în reader-ul tău preferat RSS.' | 76 | description: 'Feed-urile RSS oferite de wallabag îți permit să-ți citești articolele salvate în reader-ul tău preferat RSS.' |
76 | token_label: 'RSS-Token' | 77 | token_label: 'RSS-Token' |
@@ -88,6 +89,18 @@ config: | |||
88 | name_label: 'Nume' | 89 | name_label: 'Nume' |
89 | email_label: 'E-mail' | 90 | email_label: 'E-mail' |
90 | # twoFactorAuthentication_label: 'Two factor authentication' | 91 | # twoFactorAuthentication_label: 'Two factor authentication' |
92 | delete: | ||
93 | # title: Delete my account (a.k.a danger zone) | ||
94 | # 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. | ||
95 | # confirm: Are you really sure? (THIS CAN'T BE UNDONE) | ||
96 | # button: Delete my account | ||
97 | reset: | ||
98 | # title: Reset area (a.k.a danger zone) | ||
99 | # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE. | ||
100 | # annotations: Remove ALL annotations | ||
101 | # tags: Remove ALL tags | ||
102 | # entries: Remove ALL entries | ||
103 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | ||
91 | form_password: | 104 | form_password: |
92 | old_password_label: 'Parola veche' | 105 | old_password_label: 'Parola veche' |
93 | new_password_label: 'Parola nouă' | 106 | new_password_label: 'Parola nouă' |
@@ -355,6 +368,7 @@ import: | |||
355 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' | 368 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' |
356 | worker: | 369 | worker: |
357 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" | 370 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" |
371 | # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors." | ||
358 | # firefox: | 372 | # firefox: |
359 | # page_title: 'Import > Firefox' | 373 | # page_title: 'Import > Firefox' |
360 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." | 374 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." |
@@ -458,8 +472,10 @@ flashes: | |||
458 | rss_updated: 'Informație RSS actualizată' | 472 | rss_updated: 'Informație RSS actualizată' |
459 | # tagging_rules_updated: 'Tagging rules updated' | 473 | # tagging_rules_updated: 'Tagging rules updated' |
460 | # tagging_rules_deleted: 'Tagging rule deleted' | 474 | # tagging_rules_deleted: 'Tagging rule deleted' |
461 | # user_added: 'User "%username%" added' | ||
462 | # rss_token_updated: 'RSS token updated' | 475 | # rss_token_updated: 'RSS token updated' |
476 | # annotations_reset: Annotations reset | ||
477 | # tags_reset: Tags reset | ||
478 | # entries_reset: Entries reset | ||
463 | entry: | 479 | entry: |
464 | notice: | 480 | notice: |
465 | # entry_already_saved: 'Entry already saved on %date%' | 481 | # entry_already_saved: 'Entry already saved on %date%' |
@@ -489,3 +505,8 @@ flashes: | |||
489 | notice: | 505 | notice: |
490 | # client_created: 'New client created.' | 506 | # client_created: 'New client created.' |
491 | # client_deleted: 'Client deleted' | 507 | # client_deleted: 'Client deleted' |
508 | user: | ||
509 | notice: | ||
510 | # added: 'User "%username%" added' | ||
511 | # updated: 'User "%username%" updated' | ||
512 | # deleted: 'User "%username%" deleted' | ||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml index f50f629a..07939ebc 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml | |||
@@ -71,6 +71,7 @@ config: | |||
71 | # 300_word: 'I read ~300 words per minute' | 71 | # 300_word: 'I read ~300 words per minute' |
72 | # 400_word: 'I read ~400 words per minute' | 72 | # 400_word: 'I read ~400 words per minute' |
73 | # pocket_consumer_key_label: Consumer key for Pocket to import contents | 73 | # pocket_consumer_key_label: Consumer key for Pocket to import contents |
74 | # android_configuration: Configure your Android application | ||
74 | form_rss: | 75 | form_rss: |
75 | description: 'wallabag RSS akışı kaydetmiş olduğunuz makalelerini favori RSS okuyucunuzda görüntülemenizi sağlar. Bunu yapabilmek için öncelikle belirteç (token) oluşturmalısınız.' | 76 | description: 'wallabag RSS akışı kaydetmiş olduğunuz makalelerini favori RSS okuyucunuzda görüntülemenizi sağlar. Bunu yapabilmek için öncelikle belirteç (token) oluşturmalısınız.' |
76 | token_label: 'RSS belirteci (token)' | 77 | token_label: 'RSS belirteci (token)' |
@@ -88,6 +89,18 @@ config: | |||
88 | name_label: 'İsim' | 89 | name_label: 'İsim' |
89 | email_label: 'E-posta' | 90 | email_label: 'E-posta' |
90 | twoFactorAuthentication_label: 'İki adımlı doğrulama' | 91 | twoFactorAuthentication_label: 'İki adımlı doğrulama' |
92 | delete: | ||
93 | # title: Delete my account (a.k.a danger zone) | ||
94 | # 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. | ||
95 | # confirm: Are you really sure? (THIS CAN'T BE UNDONE) | ||
96 | # button: Delete my account | ||
97 | reset: | ||
98 | # title: Reset area (a.k.a danger zone) | ||
99 | # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE. | ||
100 | # annotations: Remove ALL annotations | ||
101 | # tags: Remove ALL tags | ||
102 | # entries: Remove ALL entries | ||
103 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | ||
91 | form_password: | 104 | form_password: |
92 | old_password_label: 'Eski şifre' | 105 | old_password_label: 'Eski şifre' |
93 | new_password_label: 'Yeni şifre' | 106 | new_password_label: 'Yeni şifre' |
@@ -96,6 +109,7 @@ config: | |||
96 | # if_label: 'if' | 109 | # if_label: 'if' |
97 | # then_tag_as_label: 'then tag as' | 110 | # then_tag_as_label: 'then tag as' |
98 | # delete_rule_label: 'delete' | 111 | # delete_rule_label: 'delete' |
112 | # edit_rule_label: 'edit' | ||
99 | rule_label: 'Kural' | 113 | rule_label: 'Kural' |
100 | tags_label: 'Etiketler' | 114 | tags_label: 'Etiketler' |
101 | faq: | 115 | faq: |
@@ -354,6 +368,7 @@ import: | |||
354 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' | 368 | # how_to: 'Please select your Readability export and click on the below button to upload and import it.' |
355 | worker: | 369 | worker: |
356 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" | 370 | # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:" |
371 | # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors." | ||
357 | firefox: | 372 | firefox: |
358 | page_title: 'İçe Aktar > Firefox' | 373 | page_title: 'İçe Aktar > Firefox' |
359 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." | 374 | # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file." |
@@ -457,8 +472,10 @@ flashes: | |||
457 | rss_updated: 'RSS bilgiler güncellendi' | 472 | rss_updated: 'RSS bilgiler güncellendi' |
458 | tagging_rules_updated: 'Tagging rules updated' | 473 | tagging_rules_updated: 'Tagging rules updated' |
459 | tagging_rules_deleted: 'Tagging rule deleted' | 474 | tagging_rules_deleted: 'Tagging rule deleted' |
460 | user_added: 'User "%username%" added' | ||
461 | rss_token_updated: 'RSS token updated' | 475 | rss_token_updated: 'RSS token updated' |
476 | # annotations_reset: Annotations reset | ||
477 | # tags_reset: Tags reset | ||
478 | # entries_reset: Entries reset | ||
462 | entry: | 479 | entry: |
463 | notice: | 480 | notice: |
464 | entry_already_saved: 'Entry already saved on %date%' | 481 | entry_already_saved: 'Entry already saved on %date%' |
@@ -488,3 +505,8 @@ flashes: | |||
488 | notice: | 505 | notice: |
489 | # client_created: 'New client created.' | 506 | # client_created: 'New client created.' |
490 | # client_deleted: 'Client deleted' | 507 | # client_deleted: 'Client deleted' |
508 | user: | ||
509 | notice: | ||
510 | # added: 'User "%username%" added' | ||
511 | # updated: 'User "%username%" updated' | ||
512 | # deleted: 'User "%username%" deleted' | ||
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..ec3b23c8 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 | |||
@@ -54,6 +54,16 @@ | |||
54 | <a href="https://getpocket.com/developer/docs/authentication">https://getpocket.com/developer/docs/authentication</a> | 54 | <a href="https://getpocket.com/developer/docs/authentication">https://getpocket.com/developer/docs/authentication</a> |
55 | </p> | 55 | </p> |
56 | </div> | 56 | </div> |
57 | |||
58 | <div class="row"> | ||
59 | <h3>{{ 'config.form_settings.android_configuration'|trans }}</h3> | ||
60 | <a href="wallabag://{{ app.user.username }}@{{ wallabag_url }}" >Touch here to prefill your Android application</a> | ||
61 | <img id="androidQrcode" /> | ||
62 | <script> | ||
63 | const imgBase64 = jrQrcode.getQrBase64('wallabag://{{ app.user.username }}@{{ wallabag_url }}'); | ||
64 | document.getElementById('androidQrcode').src = imgBase64; | ||
65 | </script> | ||
66 | </div> | ||
57 | </fieldset> | 67 | </fieldset> |
58 | 68 | ||
59 | {{ form_rest(form.config) }} | 69 | {{ form_rest(form.config) }} |
@@ -146,10 +156,41 @@ | |||
146 | </fieldset> | 156 | </fieldset> |
147 | {% endif %} | 157 | {% endif %} |
148 | 158 | ||
159 | <h2>{{ 'config.reset.title'|trans }}</h2> | ||
160 | <fieldset class="w500p inline"> | ||
161 | <p>{{ 'config.reset.description'|trans }}</p> | ||
162 | <ul> | ||
163 | <li> | ||
164 | <a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
165 | {{ 'config.reset.annotations'|trans }} | ||
166 | </a> | ||
167 | </li> | ||
168 | <li> | ||
169 | <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
170 | {{ 'config.reset.tags'|trans }} | ||
171 | </a> | ||
172 | </li> | ||
173 | <li> | ||
174 | <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
175 | {{ 'config.reset.entries'|trans }} | ||
176 | </a> | ||
177 | </li> | ||
178 | </ul> | ||
179 | </fieldset> | ||
180 | |||
149 | {{ form_widget(form.user._token) }} | 181 | {{ form_widget(form.user._token) }} |
150 | {{ form_widget(form.user.save) }} | 182 | {{ form_widget(form.user.save) }} |
151 | </form> | 183 | </form> |
152 | 184 | ||
185 | {% if enabled_users > 1 %} | ||
186 | <h2>{{ 'config.form_user.delete.title'|trans }}</h2> | ||
187 | |||
188 | <p>{{ 'config.form_user.delete.description'|trans }}</p> | ||
189 | <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"> | ||
190 | {{ 'config.form_user.delete.button'|trans }} | ||
191 | </a> | ||
192 | {% endif %} | ||
193 | |||
153 | <h2>{{ 'config.tab_menu.password'|trans }}</h2> | 194 | <h2>{{ 'config.tab_menu.password'|trans }}</h2> |
154 | 195 | ||
155 | {{ form_start(form.pwd) }} | 196 | {{ 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..f69d158f 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 | |||
@@ -71,6 +71,18 @@ | |||
71 | </div> | 71 | </div> |
72 | </div> | 72 | </div> |
73 | 73 | ||
74 | <div class="row"> | ||
75 | <div class="input-field col s12"> | ||
76 | <h5>{{ 'config.form_settings.android_configuration'|trans }}</h5> | ||
77 | <a href="wallabag://{{ app.user.username }}@{{ wallabag_url }}" class="waves-effect waves-light btn hide-on-large-only">Touch here to prefill your Android application</a> | ||
78 | <img id="androidQrcode" class="hide-on-med-and-down" /> | ||
79 | </div> | ||
80 | <script> | ||
81 | const imgBase64 = jrQrcode.getQrBase64('wallabag://{{ app.user.username }}@{{ wallabag_url }}'); | ||
82 | document.getElementById('androidQrcode').src = imgBase64; | ||
83 | </script> | ||
84 | </div> | ||
85 | |||
74 | {{ form_widget(form.config.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} | 86 | {{ form_widget(form.config.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} |
75 | {{ form_rest(form.config) }} | 87 | {{ form_rest(form.config) }} |
76 | </form> | 88 | </form> |
@@ -167,6 +179,34 @@ | |||
167 | {{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} | 179 | {{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} |
168 | {{ form_widget(form.user._token) }} | 180 | {{ form_widget(form.user._token) }} |
169 | </form> | 181 | </form> |
182 | |||
183 | <br /><hr /><br /> | ||
184 | |||
185 | <div class="row"> | ||
186 | <h5>{{ 'config.reset.title'|trans }}</h5> | ||
187 | <p>{{ 'config.reset.description'|trans }}</p> | ||
188 | <a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
189 | {{ 'config.reset.annotations'|trans }} | ||
190 | </a> | ||
191 | <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
192 | {{ 'config.reset.tags'|trans }} | ||
193 | </a> | ||
194 | <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
195 | {{ 'config.reset.entries'|trans }} | ||
196 | </a> | ||
197 | </div> | ||
198 | |||
199 | {% if enabled_users > 1 %} | ||
200 | <br /><hr /><br /> | ||
201 | |||
202 | <div class="row"> | ||
203 | <h5>{{ 'config.form_user.delete.title'|trans }}</h5> | ||
204 | <p>{{ 'config.form_user.delete.description'|trans }}</p> | ||
205 | <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"> | ||
206 | {{ 'config.form_user.delete.button'|trans }} | ||
207 | </a> | ||
208 | </div> | ||
209 | {% endif %} | ||
170 | </div> | 210 | </div> |
171 | 211 | ||
172 | <div id="set4" class="col s12"> | 212 | <div id="set4" class="col s12"> |
diff --git a/src/Wallabag/ImportBundle/Command/ImportCommand.php b/src/Wallabag/ImportBundle/Command/ImportCommand.php index d1325338..13f3dcb9 100644 --- a/src/Wallabag/ImportBundle/Command/ImportCommand.php +++ b/src/Wallabag/ImportBundle/Command/ImportCommand.php | |||
@@ -14,10 +14,10 @@ class ImportCommand extends ContainerAwareCommand | |||
14 | { | 14 | { |
15 | $this | 15 | $this |
16 | ->setName('wallabag:import') | 16 | ->setName('wallabag:import') |
17 | ->setDescription('Import entries from a JSON export from a wallabag v1 instance') | 17 | ->setDescription('Import entries from a JSON export') |
18 | ->addArgument('userId', InputArgument::REQUIRED, 'User ID to populate') | 18 | ->addArgument('userId', InputArgument::REQUIRED, 'User ID to populate') |
19 | ->addArgument('filepath', InputArgument::REQUIRED, 'Path to the JSON file') | 19 | ->addArgument('filepath', InputArgument::REQUIRED, 'Path to the JSON file') |
20 | ->addOption('importer', null, InputArgument::OPTIONAL, 'The importer to use: wallabag v1, v2, firefox or chrome', 'v1') | 20 | ->addOption('importer', null, InputArgument::OPTIONAL, 'The importer to use: v1, v2, instapaper, readability, firefox or chrome', 'v1') |
21 | ->addOption('markAsRead', null, InputArgument::OPTIONAL, 'Mark all entries as read', false) | 21 | ->addOption('markAsRead', null, InputArgument::OPTIONAL, 'Mark all entries as read', false) |
22 | ; | 22 | ; |
23 | } | 23 | } |
@@ -42,32 +42,38 @@ class ImportCommand extends ContainerAwareCommand | |||
42 | 42 | ||
43 | switch ($input->getOption('importer')) { | 43 | switch ($input->getOption('importer')) { |
44 | case 'v2': | 44 | case 'v2': |
45 | $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v2.import'); | 45 | $import = $this->getContainer()->get('wallabag_import.wallabag_v2.import'); |
46 | break; | 46 | break; |
47 | case 'firefox': | 47 | case 'firefox': |
48 | $wallabag = $this->getContainer()->get('wallabag_import.firefox.import'); | 48 | $import = $this->getContainer()->get('wallabag_import.firefox.import'); |
49 | break; | 49 | break; |
50 | case 'chrome': | 50 | case 'chrome': |
51 | $wallabag = $this->getContainer()->get('wallabag_import.chrome.import'); | 51 | $import = $this->getContainer()->get('wallabag_import.chrome.import'); |
52 | break; | ||
53 | case 'readability': | ||
54 | $import = $this->getContainer()->get('wallabag_import.readability.import'); | ||
55 | break; | ||
56 | case 'instapaper': | ||
57 | $import = $this->getContainer()->get('wallabag_import.instapaper.import'); | ||
52 | break; | 58 | break; |
53 | case 'instapaper': | 59 | case 'instapaper': |
54 | $wallabag = $this->getContainer()->get('wallabag_import.instapaper.import'); | 60 | $wallabag = $this->getContainer()->get('wallabag_import.instapaper.import'); |
55 | break; | 61 | break; |
56 | case 'v1': | 62 | case 'v1': |
57 | default: | 63 | default: |
58 | $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v1.import'); | 64 | $import = $this->getContainer()->get('wallabag_import.wallabag_v1.import'); |
59 | break; | 65 | break; |
60 | } | 66 | } |
61 | 67 | ||
62 | $wallabag->setMarkAsRead($input->getOption('markAsRead')); | 68 | $import->setMarkAsRead($input->getOption('markAsRead')); |
63 | $wallabag->setUser($user); | 69 | $import->setUser($user); |
64 | 70 | ||
65 | $res = $wallabag | 71 | $res = $import |
66 | ->setFilepath($input->getArgument('filepath')) | 72 | ->setFilepath($input->getArgument('filepath')) |
67 | ->import(); | 73 | ->import(); |
68 | 74 | ||
69 | if (true === $res) { | 75 | if (true === $res) { |
70 | $summary = $wallabag->getSummary(); | 76 | $summary = $import->getSummary(); |
71 | $output->writeln('<info>'.$summary['imported'].' imported</info>'); | 77 | $output->writeln('<info>'.$summary['imported'].' imported</info>'); |
72 | $output->writeln('<comment>'.$summary['skipped'].' already saved</comment>'); | 78 | $output->writeln('<comment>'.$summary['skipped'].' already saved</comment>'); |
73 | } | 79 | } |
diff --git a/src/Wallabag/ImportBundle/Consumer/AbstractConsumer.php b/src/Wallabag/ImportBundle/Consumer/AbstractConsumer.php index b893ea29..aa7ff914 100644 --- a/src/Wallabag/ImportBundle/Consumer/AbstractConsumer.php +++ b/src/Wallabag/ImportBundle/Consumer/AbstractConsumer.php | |||
@@ -9,6 +9,8 @@ use Wallabag\CoreBundle\Entity\Entry; | |||
9 | use Wallabag\CoreBundle\Entity\Tag; | 9 | use Wallabag\CoreBundle\Entity\Tag; |
10 | use Psr\Log\LoggerInterface; | 10 | use Psr\Log\LoggerInterface; |
11 | use Psr\Log\NullLogger; | 11 | use Psr\Log\NullLogger; |
12 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; | ||
13 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | ||
12 | 14 | ||
13 | abstract class AbstractConsumer | 15 | abstract class AbstractConsumer |
14 | { | 16 | { |
@@ -17,11 +19,12 @@ abstract class AbstractConsumer | |||
17 | protected $import; | 19 | protected $import; |
18 | protected $logger; | 20 | protected $logger; |
19 | 21 | ||
20 | public function __construct(EntityManager $em, UserRepository $userRepository, AbstractImport $import, LoggerInterface $logger = null) | 22 | public function __construct(EntityManager $em, UserRepository $userRepository, AbstractImport $import, EventDispatcherInterface $eventDispatcher, LoggerInterface $logger = null) |
21 | { | 23 | { |
22 | $this->em = $em; | 24 | $this->em = $em; |
23 | $this->userRepository = $userRepository; | 25 | $this->userRepository = $userRepository; |
24 | $this->import = $import; | 26 | $this->import = $import; |
27 | $this->eventDispatcher = $eventDispatcher; | ||
25 | $this->logger = $logger ?: new NullLogger(); | 28 | $this->logger = $logger ?: new NullLogger(); |
26 | } | 29 | } |
27 | 30 | ||
@@ -59,6 +62,9 @@ abstract class AbstractConsumer | |||
59 | try { | 62 | try { |
60 | $this->em->flush(); | 63 | $this->em->flush(); |
61 | 64 | ||
65 | // entry saved, dispatch event about it! | ||
66 | $this->eventDispatcher->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
67 | |||
62 | // clear only affected entities | 68 | // clear only affected entities |
63 | $this->em->clear(Entry::class); | 69 | $this->em->clear(Entry::class); |
64 | $this->em->clear(Tag::class); | 70 | $this->em->clear(Tag::class); |
diff --git a/src/Wallabag/ImportBundle/Import/AbstractImport.php b/src/Wallabag/ImportBundle/Import/AbstractImport.php index 764b390a..1d4a6e27 100644 --- a/src/Wallabag/ImportBundle/Import/AbstractImport.php +++ b/src/Wallabag/ImportBundle/Import/AbstractImport.php | |||
@@ -10,12 +10,15 @@ use Wallabag\CoreBundle\Entity\Entry; | |||
10 | use Wallabag\CoreBundle\Entity\Tag; | 10 | use Wallabag\CoreBundle\Entity\Tag; |
11 | use Wallabag\UserBundle\Entity\User; | 11 | use Wallabag\UserBundle\Entity\User; |
12 | use OldSound\RabbitMqBundle\RabbitMq\ProducerInterface; | 12 | use OldSound\RabbitMqBundle\RabbitMq\ProducerInterface; |
13 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; | ||
14 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | ||
13 | 15 | ||
14 | abstract class AbstractImport implements ImportInterface | 16 | abstract class AbstractImport implements ImportInterface |
15 | { | 17 | { |
16 | protected $em; | 18 | protected $em; |
17 | protected $logger; | 19 | protected $logger; |
18 | protected $contentProxy; | 20 | protected $contentProxy; |
21 | protected $eventDispatcher; | ||
19 | protected $producer; | 22 | protected $producer; |
20 | protected $user; | 23 | protected $user; |
21 | protected $markAsRead; | 24 | protected $markAsRead; |
@@ -23,11 +26,12 @@ abstract class AbstractImport implements ImportInterface | |||
23 | protected $importedEntries = 0; | 26 | protected $importedEntries = 0; |
24 | protected $queuedEntries = 0; | 27 | protected $queuedEntries = 0; |
25 | 28 | ||
26 | public function __construct(EntityManager $em, ContentProxy $contentProxy) | 29 | public function __construct(EntityManager $em, ContentProxy $contentProxy, EventDispatcherInterface $eventDispatcher) |
27 | { | 30 | { |
28 | $this->em = $em; | 31 | $this->em = $em; |
29 | $this->logger = new NullLogger(); | 32 | $this->logger = new NullLogger(); |
30 | $this->contentProxy = $contentProxy; | 33 | $this->contentProxy = $contentProxy; |
34 | $this->eventDispatcher = $eventDispatcher; | ||
31 | } | 35 | } |
32 | 36 | ||
33 | public function setLogger(LoggerInterface $logger) | 37 | public function setLogger(LoggerInterface $logger) |
@@ -104,6 +108,7 @@ abstract class AbstractImport implements ImportInterface | |||
104 | protected function parseEntries($entries) | 108 | protected function parseEntries($entries) |
105 | { | 109 | { |
106 | $i = 1; | 110 | $i = 1; |
111 | $entryToBeFlushed = []; | ||
107 | 112 | ||
108 | foreach ($entries as $importedEntry) { | 113 | foreach ($entries as $importedEntry) { |
109 | if ($this->markAsRead) { | 114 | if ($this->markAsRead) { |
@@ -116,10 +121,21 @@ abstract class AbstractImport implements ImportInterface | |||
116 | continue; | 121 | continue; |
117 | } | 122 | } |
118 | 123 | ||
124 | // store each entry to be flushed so we can trigger the entry.saved event for each of them | ||
125 | // entry.saved needs the entry to be persisted in db because it needs it id to generate | ||
126 | // images (at least) | ||
127 | $entryToBeFlushed[] = $entry; | ||
128 | |||
119 | // flush every 20 entries | 129 | // flush every 20 entries |
120 | if (($i % 20) === 0) { | 130 | if (($i % 20) === 0) { |
121 | $this->em->flush(); | 131 | $this->em->flush(); |
122 | 132 | ||
133 | foreach ($entryToBeFlushed as $entry) { | ||
134 | $this->eventDispatcher->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
135 | } | ||
136 | |||
137 | $entryToBeFlushed = []; | ||
138 | |||
123 | // clear only affected entities | 139 | // clear only affected entities |
124 | $this->em->clear(Entry::class); | 140 | $this->em->clear(Entry::class); |
125 | $this->em->clear(Tag::class); | 141 | $this->em->clear(Tag::class); |
@@ -128,6 +144,12 @@ abstract class AbstractImport implements ImportInterface | |||
128 | } | 144 | } |
129 | 145 | ||
130 | $this->em->flush(); | 146 | $this->em->flush(); |
147 | |||
148 | if (!empty($entryToBeFlushed)) { | ||
149 | foreach ($entryToBeFlushed as $entry) { | ||
150 | $this->eventDispatcher->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
151 | } | ||
152 | } | ||
131 | } | 153 | } |
132 | 154 | ||
133 | /** | 155 | /** |
diff --git a/src/Wallabag/ImportBundle/Import/BrowserImport.php b/src/Wallabag/ImportBundle/Import/BrowserImport.php index 2ca1683b..8bf7d92e 100644 --- a/src/Wallabag/ImportBundle/Import/BrowserImport.php +++ b/src/Wallabag/ImportBundle/Import/BrowserImport.php | |||
@@ -5,6 +5,7 @@ namespace Wallabag\ImportBundle\Import; | |||
5 | use Wallabag\CoreBundle\Entity\Entry; | 5 | use Wallabag\CoreBundle\Entity\Entry; |
6 | use Wallabag\UserBundle\Entity\User; | 6 | use Wallabag\UserBundle\Entity\User; |
7 | use Wallabag\CoreBundle\Helper\ContentProxy; | 7 | use Wallabag\CoreBundle\Helper\ContentProxy; |
8 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | ||
8 | 9 | ||
9 | abstract class BrowserImport extends AbstractImport | 10 | abstract class BrowserImport extends AbstractImport |
10 | { | 11 | { |
@@ -81,6 +82,7 @@ abstract class BrowserImport extends AbstractImport | |||
81 | protected function parseEntries($entries) | 82 | protected function parseEntries($entries) |
82 | { | 83 | { |
83 | $i = 1; | 84 | $i = 1; |
85 | $entryToBeFlushed = []; | ||
84 | 86 | ||
85 | foreach ($entries as $importedEntry) { | 87 | foreach ($entries as $importedEntry) { |
86 | if ((array) $importedEntry !== $importedEntry) { | 88 | if ((array) $importedEntry !== $importedEntry) { |
@@ -93,14 +95,29 @@ abstract class BrowserImport extends AbstractImport | |||
93 | continue; | 95 | continue; |
94 | } | 96 | } |
95 | 97 | ||
98 | // @see AbstractImport | ||
99 | $entryToBeFlushed[] = $entry; | ||
100 | |||
96 | // flush every 20 entries | 101 | // flush every 20 entries |
97 | if (($i % 20) === 0) { | 102 | if (($i % 20) === 0) { |
98 | $this->em->flush(); | 103 | $this->em->flush(); |
104 | |||
105 | foreach ($entryToBeFlushed as $entry) { | ||
106 | $this->eventDispatcher->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
107 | } | ||
108 | |||
109 | $entryToBeFlushed = []; | ||
99 | } | 110 | } |
100 | ++$i; | 111 | ++$i; |
101 | } | 112 | } |
102 | 113 | ||
103 | $this->em->flush(); | 114 | $this->em->flush(); |
115 | |||
116 | if (!empty($entryToBeFlushed)) { | ||
117 | foreach ($entryToBeFlushed as $entry) { | ||
118 | $this->eventDispatcher->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
119 | } | ||
120 | } | ||
104 | } | 121 | } |
105 | 122 | ||
106 | /** | 123 | /** |
diff --git a/src/Wallabag/ImportBundle/Import/PocketImport.php b/src/Wallabag/ImportBundle/Import/PocketImport.php index 327e2500..33093480 100644 --- a/src/Wallabag/ImportBundle/Import/PocketImport.php +++ b/src/Wallabag/ImportBundle/Import/PocketImport.php | |||
@@ -2,8 +2,6 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Import; | 3 | namespace Wallabag\ImportBundle\Import; |
4 | 4 | ||
5 | use Psr\Log\NullLogger; | ||
6 | use Doctrine\ORM\EntityManager; | ||
7 | use GuzzleHttp\Client; | 5 | use GuzzleHttp\Client; |
8 | use GuzzleHttp\Exception\RequestException; | 6 | use GuzzleHttp\Exception\RequestException; |
9 | use Wallabag\CoreBundle\Entity\Entry; | 7 | use Wallabag\CoreBundle\Entity\Entry; |
@@ -16,13 +14,6 @@ class PocketImport extends AbstractImport | |||
16 | 14 | ||
17 | const NB_ELEMENTS = 5000; | 15 | const NB_ELEMENTS = 5000; |
18 | 16 | ||
19 | public function __construct(EntityManager $em, ContentProxy $contentProxy) | ||
20 | { | ||
21 | $this->em = $em; | ||
22 | $this->contentProxy = $contentProxy; | ||
23 | $this->logger = new NullLogger(); | ||
24 | } | ||
25 | |||
26 | /** | 17 | /** |
27 | * Only used for test purpose. | 18 | * Only used for test purpose. |
28 | * | 19 | * |
diff --git a/src/Wallabag/ImportBundle/Resources/config/rabbit.yml b/src/Wallabag/ImportBundle/Resources/config/rabbit.yml index 70b8a0d4..a5af5282 100644 --- a/src/Wallabag/ImportBundle/Resources/config/rabbit.yml +++ b/src/Wallabag/ImportBundle/Resources/config/rabbit.yml | |||
@@ -6,6 +6,7 @@ services: | |||
6 | - "@doctrine.orm.entity_manager" | 6 | - "@doctrine.orm.entity_manager" |
7 | - "@wallabag_user.user_repository" | 7 | - "@wallabag_user.user_repository" |
8 | - "@wallabag_import.pocket.import" | 8 | - "@wallabag_import.pocket.import" |
9 | - "@event_dispatcher" | ||
9 | - "@logger" | 10 | - "@logger" |
10 | wallabag_import.consumer.amqp.readability: | 11 | wallabag_import.consumer.amqp.readability: |
11 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer | 12 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer |
@@ -13,6 +14,7 @@ services: | |||
13 | - "@doctrine.orm.entity_manager" | 14 | - "@doctrine.orm.entity_manager" |
14 | - "@wallabag_user.user_repository" | 15 | - "@wallabag_user.user_repository" |
15 | - "@wallabag_import.readability.import" | 16 | - "@wallabag_import.readability.import" |
17 | - "@event_dispatcher" | ||
16 | - "@logger" | 18 | - "@logger" |
17 | wallabag_import.consumer.amqp.instapaper: | 19 | wallabag_import.consumer.amqp.instapaper: |
18 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer | 20 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer |
@@ -20,6 +22,7 @@ services: | |||
20 | - "@doctrine.orm.entity_manager" | 22 | - "@doctrine.orm.entity_manager" |
21 | - "@wallabag_user.user_repository" | 23 | - "@wallabag_user.user_repository" |
22 | - "@wallabag_import.instapaper.import" | 24 | - "@wallabag_import.instapaper.import" |
25 | - "@event_dispatcher" | ||
23 | - "@logger" | 26 | - "@logger" |
24 | wallabag_import.consumer.amqp.wallabag_v1: | 27 | wallabag_import.consumer.amqp.wallabag_v1: |
25 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer | 28 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer |
@@ -27,6 +30,7 @@ services: | |||
27 | - "@doctrine.orm.entity_manager" | 30 | - "@doctrine.orm.entity_manager" |
28 | - "@wallabag_user.user_repository" | 31 | - "@wallabag_user.user_repository" |
29 | - "@wallabag_import.wallabag_v1.import" | 32 | - "@wallabag_import.wallabag_v1.import" |
33 | - "@event_dispatcher" | ||
30 | - "@logger" | 34 | - "@logger" |
31 | wallabag_import.consumer.amqp.wallabag_v2: | 35 | wallabag_import.consumer.amqp.wallabag_v2: |
32 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer | 36 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer |
@@ -34,6 +38,7 @@ services: | |||
34 | - "@doctrine.orm.entity_manager" | 38 | - "@doctrine.orm.entity_manager" |
35 | - "@wallabag_user.user_repository" | 39 | - "@wallabag_user.user_repository" |
36 | - "@wallabag_import.wallabag_v2.import" | 40 | - "@wallabag_import.wallabag_v2.import" |
41 | - "@event_dispatcher" | ||
37 | - "@logger" | 42 | - "@logger" |
38 | wallabag_import.consumer.amqp.firefox: | 43 | wallabag_import.consumer.amqp.firefox: |
39 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer | 44 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer |
@@ -41,6 +46,7 @@ services: | |||
41 | - "@doctrine.orm.entity_manager" | 46 | - "@doctrine.orm.entity_manager" |
42 | - "@wallabag_user.user_repository" | 47 | - "@wallabag_user.user_repository" |
43 | - "@wallabag_import.firefox.import" | 48 | - "@wallabag_import.firefox.import" |
49 | - "@event_dispatcher" | ||
44 | - "@logger" | 50 | - "@logger" |
45 | wallabag_import.consumer.amqp.chrome: | 51 | wallabag_import.consumer.amqp.chrome: |
46 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer | 52 | class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer |
@@ -48,4 +54,5 @@ services: | |||
48 | - "@doctrine.orm.entity_manager" | 54 | - "@doctrine.orm.entity_manager" |
49 | - "@wallabag_user.user_repository" | 55 | - "@wallabag_user.user_repository" |
50 | - "@wallabag_import.chrome.import" | 56 | - "@wallabag_import.chrome.import" |
57 | - "@event_dispatcher" | ||
51 | - "@logger" | 58 | - "@logger" |
diff --git a/src/Wallabag/ImportBundle/Resources/config/redis.yml b/src/Wallabag/ImportBundle/Resources/config/redis.yml index 0a81e1b5..5ced4c83 100644 --- a/src/Wallabag/ImportBundle/Resources/config/redis.yml +++ b/src/Wallabag/ImportBundle/Resources/config/redis.yml | |||
@@ -18,6 +18,7 @@ services: | |||
18 | - "@doctrine.orm.entity_manager" | 18 | - "@doctrine.orm.entity_manager" |
19 | - "@wallabag_user.user_repository" | 19 | - "@wallabag_user.user_repository" |
20 | - "@wallabag_import.readability.import" | 20 | - "@wallabag_import.readability.import" |
21 | - "@event_dispatcher" | ||
21 | - "@logger" | 22 | - "@logger" |
22 | 23 | ||
23 | # instapaper | 24 | # instapaper |
@@ -38,6 +39,7 @@ services: | |||
38 | - "@doctrine.orm.entity_manager" | 39 | - "@doctrine.orm.entity_manager" |
39 | - "@wallabag_user.user_repository" | 40 | - "@wallabag_user.user_repository" |
40 | - "@wallabag_import.instapaper.import" | 41 | - "@wallabag_import.instapaper.import" |
42 | - "@event_dispatcher" | ||
41 | - "@logger" | 43 | - "@logger" |
42 | 44 | ||
43 | 45 | ||
@@ -58,6 +60,7 @@ services: | |||
58 | - "@doctrine.orm.entity_manager" | 60 | - "@doctrine.orm.entity_manager" |
59 | - "@wallabag_user.user_repository" | 61 | - "@wallabag_user.user_repository" |
60 | - "@wallabag_import.pocket.import" | 62 | - "@wallabag_import.pocket.import" |
63 | - "@event_dispatcher" | ||
61 | - "@logger" | 64 | - "@logger" |
62 | 65 | ||
63 | # wallabag v1 | 66 | # wallabag v1 |
@@ -78,6 +81,7 @@ services: | |||
78 | - "@doctrine.orm.entity_manager" | 81 | - "@doctrine.orm.entity_manager" |
79 | - "@wallabag_user.user_repository" | 82 | - "@wallabag_user.user_repository" |
80 | - "@wallabag_import.wallabag_v1.import" | 83 | - "@wallabag_import.wallabag_v1.import" |
84 | - "@event_dispatcher" | ||
81 | - "@logger" | 85 | - "@logger" |
82 | 86 | ||
83 | # wallabag v2 | 87 | # wallabag v2 |
@@ -98,6 +102,7 @@ services: | |||
98 | - "@doctrine.orm.entity_manager" | 102 | - "@doctrine.orm.entity_manager" |
99 | - "@wallabag_user.user_repository" | 103 | - "@wallabag_user.user_repository" |
100 | - "@wallabag_import.wallabag_v2.import" | 104 | - "@wallabag_import.wallabag_v2.import" |
105 | - "@event_dispatcher" | ||
101 | - "@logger" | 106 | - "@logger" |
102 | 107 | ||
103 | # firefox | 108 | # firefox |
@@ -118,6 +123,7 @@ services: | |||
118 | - "@doctrine.orm.entity_manager" | 123 | - "@doctrine.orm.entity_manager" |
119 | - "@wallabag_user.user_repository" | 124 | - "@wallabag_user.user_repository" |
120 | - "@wallabag_import.firefox.import" | 125 | - "@wallabag_import.firefox.import" |
126 | - "@event_dispatcher" | ||
121 | - "@logger" | 127 | - "@logger" |
122 | 128 | ||
123 | # chrome | 129 | # chrome |
@@ -138,4 +144,5 @@ services: | |||
138 | - "@doctrine.orm.entity_manager" | 144 | - "@doctrine.orm.entity_manager" |
139 | - "@wallabag_user.user_repository" | 145 | - "@wallabag_user.user_repository" |
140 | - "@wallabag_import.chrome.import" | 146 | - "@wallabag_import.chrome.import" |
147 | - "@event_dispatcher" | ||
141 | - "@logger" | 148 | - "@logger" |
diff --git a/src/Wallabag/ImportBundle/Resources/config/services.yml b/src/Wallabag/ImportBundle/Resources/config/services.yml index d600be0f..64822963 100644 --- a/src/Wallabag/ImportBundle/Resources/config/services.yml +++ b/src/Wallabag/ImportBundle/Resources/config/services.yml | |||
@@ -20,6 +20,7 @@ services: | |||
20 | arguments: | 20 | arguments: |
21 | - "@doctrine.orm.entity_manager" | 21 | - "@doctrine.orm.entity_manager" |
22 | - "@wallabag_core.content_proxy" | 22 | - "@wallabag_core.content_proxy" |
23 | - "@event_dispatcher" | ||
23 | calls: | 24 | calls: |
24 | - [ setClient, [ "@wallabag_import.pocket.client" ] ] | 25 | - [ setClient, [ "@wallabag_import.pocket.client" ] ] |
25 | - [ setLogger, [ "@logger" ]] | 26 | - [ setLogger, [ "@logger" ]] |
@@ -31,6 +32,7 @@ services: | |||
31 | arguments: | 32 | arguments: |
32 | - "@doctrine.orm.entity_manager" | 33 | - "@doctrine.orm.entity_manager" |
33 | - "@wallabag_core.content_proxy" | 34 | - "@wallabag_core.content_proxy" |
35 | - "@event_dispatcher" | ||
34 | calls: | 36 | calls: |
35 | - [ setLogger, [ "@logger" ]] | 37 | - [ setLogger, [ "@logger" ]] |
36 | tags: | 38 | tags: |
@@ -41,6 +43,7 @@ services: | |||
41 | arguments: | 43 | arguments: |
42 | - "@doctrine.orm.entity_manager" | 44 | - "@doctrine.orm.entity_manager" |
43 | - "@wallabag_core.content_proxy" | 45 | - "@wallabag_core.content_proxy" |
46 | - "@event_dispatcher" | ||
44 | calls: | 47 | calls: |
45 | - [ setLogger, [ "@logger" ]] | 48 | - [ setLogger, [ "@logger" ]] |
46 | tags: | 49 | tags: |
@@ -51,6 +54,7 @@ services: | |||
51 | arguments: | 54 | arguments: |
52 | - "@doctrine.orm.entity_manager" | 55 | - "@doctrine.orm.entity_manager" |
53 | - "@wallabag_core.content_proxy" | 56 | - "@wallabag_core.content_proxy" |
57 | - "@event_dispatcher" | ||
54 | calls: | 58 | calls: |
55 | - [ setLogger, [ "@logger" ]] | 59 | - [ setLogger, [ "@logger" ]] |
56 | tags: | 60 | tags: |
@@ -61,6 +65,7 @@ services: | |||
61 | arguments: | 65 | arguments: |
62 | - "@doctrine.orm.entity_manager" | 66 | - "@doctrine.orm.entity_manager" |
63 | - "@wallabag_core.content_proxy" | 67 | - "@wallabag_core.content_proxy" |
68 | - "@event_dispatcher" | ||
64 | calls: | 69 | calls: |
65 | - [ setLogger, [ "@logger" ]] | 70 | - [ setLogger, [ "@logger" ]] |
66 | tags: | 71 | tags: |
@@ -71,6 +76,7 @@ services: | |||
71 | arguments: | 76 | arguments: |
72 | - "@doctrine.orm.entity_manager" | 77 | - "@doctrine.orm.entity_manager" |
73 | - "@wallabag_core.content_proxy" | 78 | - "@wallabag_core.content_proxy" |
79 | - "@event_dispatcher" | ||
74 | calls: | 80 | calls: |
75 | - [ setLogger, [ "@logger" ]] | 81 | - [ setLogger, [ "@logger" ]] |
76 | tags: | 82 | tags: |
@@ -80,6 +86,7 @@ services: | |||
80 | arguments: | 86 | arguments: |
81 | - "@doctrine.orm.entity_manager" | 87 | - "@doctrine.orm.entity_manager" |
82 | - "@wallabag_core.content_proxy" | 88 | - "@wallabag_core.content_proxy" |
89 | - "@event_dispatcher" | ||
83 | calls: | 90 | calls: |
84 | - [ setLogger, [ "@logger" ]] | 91 | - [ setLogger, [ "@logger" ]] |
85 | tags: | 92 | tags: |
diff --git a/src/Wallabag/ImportBundle/Resources/views/Chrome/index.html.twig b/src/Wallabag/ImportBundle/Resources/views/Chrome/index.html.twig index ead828c6..93b08540 100644 --- a/src/Wallabag/ImportBundle/Resources/views/Chrome/index.html.twig +++ b/src/Wallabag/ImportBundle/Resources/views/Chrome/index.html.twig | |||
@@ -6,6 +6,8 @@ | |||
6 | <div class="row"> | 6 | <div class="row"> |
7 | <div class="col s12"> | 7 | <div class="col s12"> |
8 | <div class="card-panel settings"> | 8 | <div class="card-panel settings"> |
9 | {% include 'WallabagImportBundle:Import:_information.html.twig' %} | ||
10 | |||
9 | <div class="row"> | 11 | <div class="row"> |
10 | <blockquote>{{ import.description|trans|raw }}</blockquote> | 12 | <blockquote>{{ import.description|trans|raw }}</blockquote> |
11 | <p>{{ 'import.chrome.how_to'|trans }}</p> | 13 | <p>{{ 'import.chrome.how_to'|trans }}</p> |
diff --git a/src/Wallabag/ImportBundle/Resources/views/Firefox/index.html.twig b/src/Wallabag/ImportBundle/Resources/views/Firefox/index.html.twig index f975da3f..ced3f008 100644 --- a/src/Wallabag/ImportBundle/Resources/views/Firefox/index.html.twig +++ b/src/Wallabag/ImportBundle/Resources/views/Firefox/index.html.twig | |||
@@ -6,6 +6,8 @@ | |||
6 | <div class="row"> | 6 | <div class="row"> |
7 | <div class="col s12"> | 7 | <div class="col s12"> |
8 | <div class="card-panel settings"> | 8 | <div class="card-panel settings"> |
9 | {% include 'WallabagImportBundle:Import:_information.html.twig' %} | ||
10 | |||
9 | <div class="row"> | 11 | <div class="row"> |
10 | <blockquote>{{ import.description|trans|raw }}</blockquote> | 12 | <blockquote>{{ import.description|trans|raw }}</blockquote> |
11 | <p>{{ 'import.firefox.how_to'|trans }}</p> | 13 | <p>{{ 'import.firefox.how_to'|trans }}</p> |
diff --git a/src/Wallabag/ImportBundle/Resources/views/Import/_workerEnabled.html.twig b/src/Wallabag/ImportBundle/Resources/views/Import/_information.html.twig index 2390a41f..48bbcfe7 100644 --- a/src/Wallabag/ImportBundle/Resources/views/Import/_workerEnabled.html.twig +++ b/src/Wallabag/ImportBundle/Resources/views/Import/_information.html.twig | |||
@@ -1,8 +1,15 @@ | |||
1 | {% set redis = craue_setting('import_with_redis') %} | 1 | {% set redis = craue_setting('import_with_redis') %} |
2 | {% set rabbit = craue_setting('import_with_rabbitmq') %} | 2 | {% set rabbit = craue_setting('import_with_rabbitmq') %} |
3 | {% set downloadImages = craue_setting('download_images_enabled') %} | ||
3 | 4 | ||
4 | {% if redis or rabbit %} | 5 | {% if redis or rabbit %} |
5 | <div class="card-panel yellow darken-1 black-text"> | 6 | <div class="card-panel yellow darken-1 black-text"> |
6 | {{ 'import.worker.enabled'|trans }} <strong>{% if rabbit %}RabbitMQ{% elseif redis %}Redis{% endif %}</strong> | 7 | {{ 'import.worker.enabled'|trans }} <strong>{% if rabbit %}RabbitMQ{% elseif redis %}Redis{% endif %}</strong> |
7 | </div> | 8 | </div> |
8 | {% endif %} | 9 | {% endif %} |
10 | |||
11 | {% if not redis and not rabbit and downloadImages %} | ||
12 | <div class="card-panel orange darken-1 black-text"> | ||
13 | {{ 'import.worker.download_images_warning'|trans|raw }} | ||
14 | </div> | ||
15 | {% endif %} | ||
diff --git a/src/Wallabag/ImportBundle/Resources/views/Import/index.html.twig b/src/Wallabag/ImportBundle/Resources/views/Import/index.html.twig index 6ea5e0f4..b1ec40a6 100644 --- a/src/Wallabag/ImportBundle/Resources/views/Import/index.html.twig +++ b/src/Wallabag/ImportBundle/Resources/views/Import/index.html.twig | |||
@@ -6,6 +6,8 @@ | |||
6 | <div class="row"> | 6 | <div class="row"> |
7 | <div class="col s12"> | 7 | <div class="col s12"> |
8 | <div class="card-panel settings"> | 8 | <div class="card-panel settings"> |
9 | {% include 'WallabagImportBundle:Import:_information.html.twig' %} | ||
10 | |||
9 | {{ 'import.page_description'|trans }} | 11 | {{ 'import.page_description'|trans }} |
10 | <ul> | 12 | <ul> |
11 | {% for import in imports %} | 13 | {% for import in imports %} |
diff --git a/src/Wallabag/ImportBundle/Resources/views/Instapaper/index.html.twig b/src/Wallabag/ImportBundle/Resources/views/Instapaper/index.html.twig index 5789361f..28165d19 100644 --- a/src/Wallabag/ImportBundle/Resources/views/Instapaper/index.html.twig +++ b/src/Wallabag/ImportBundle/Resources/views/Instapaper/index.html.twig | |||
@@ -6,7 +6,7 @@ | |||
6 | <div class="row"> | 6 | <div class="row"> |
7 | <div class="col s12"> | 7 | <div class="col s12"> |
8 | <div class="card-panel settings"> | 8 | <div class="card-panel settings"> |
9 | {% include 'WallabagImportBundle:Import:_workerEnabled.html.twig' %} | 9 | {% include 'WallabagImportBundle:Import:_information.html.twig' %} |
10 | 10 | ||
11 | <div class="row"> | 11 | <div class="row"> |
12 | <blockquote>{{ import.description|trans }}</blockquote> | 12 | <blockquote>{{ import.description|trans }}</blockquote> |
diff --git a/src/Wallabag/ImportBundle/Resources/views/Pocket/index.html.twig b/src/Wallabag/ImportBundle/Resources/views/Pocket/index.html.twig index 6195fa07..536e3d1a 100644 --- a/src/Wallabag/ImportBundle/Resources/views/Pocket/index.html.twig +++ b/src/Wallabag/ImportBundle/Resources/views/Pocket/index.html.twig | |||
@@ -6,7 +6,7 @@ | |||
6 | <div class="row"> | 6 | <div class="row"> |
7 | <div class="col s12"> | 7 | <div class="col s12"> |
8 | <div class="card-panel settings"> | 8 | <div class="card-panel settings"> |
9 | {% include 'WallabagImportBundle:Import:_workerEnabled.html.twig' %} | 9 | {% include 'WallabagImportBundle:Import:_information.html.twig' %} |
10 | 10 | ||
11 | {% if not has_consumer_key %} | 11 | {% if not has_consumer_key %} |
12 | <div class="card-panel red white-text"> | 12 | <div class="card-panel red white-text"> |
diff --git a/src/Wallabag/ImportBundle/Resources/views/Readability/index.html.twig b/src/Wallabag/ImportBundle/Resources/views/Readability/index.html.twig index 74653b0f..737b0adf 100644 --- a/src/Wallabag/ImportBundle/Resources/views/Readability/index.html.twig +++ b/src/Wallabag/ImportBundle/Resources/views/Readability/index.html.twig | |||
@@ -6,7 +6,7 @@ | |||
6 | <div class="row"> | 6 | <div class="row"> |
7 | <div class="col s12"> | 7 | <div class="col s12"> |
8 | <div class="card-panel settings"> | 8 | <div class="card-panel settings"> |
9 | {% include 'WallabagImportBundle:Import:_workerEnabled.html.twig' %} | 9 | {% include 'WallabagImportBundle:Import:_information.html.twig' %} |
10 | 10 | ||
11 | <div class="row"> | 11 | <div class="row"> |
12 | <blockquote>{{ import.description|trans }}</blockquote> | 12 | <blockquote>{{ import.description|trans }}</blockquote> |
diff --git a/src/Wallabag/ImportBundle/Resources/views/WallabagV1/index.html.twig b/src/Wallabag/ImportBundle/Resources/views/WallabagV1/index.html.twig index 0b19bc34..974b2c73 100644 --- a/src/Wallabag/ImportBundle/Resources/views/WallabagV1/index.html.twig +++ b/src/Wallabag/ImportBundle/Resources/views/WallabagV1/index.html.twig | |||
@@ -6,7 +6,7 @@ | |||
6 | <div class="row"> | 6 | <div class="row"> |
7 | <div class="col s12"> | 7 | <div class="col s12"> |
8 | <div class="card-panel settings"> | 8 | <div class="card-panel settings"> |
9 | {% include 'WallabagImportBundle:Import:_workerEnabled.html.twig' %} | 9 | {% include 'WallabagImportBundle:Import:_information.html.twig' %} |
10 | 10 | ||
11 | <div class="row"> | 11 | <div class="row"> |
12 | <blockquote>{{ import.description|trans }}</blockquote> | 12 | <blockquote>{{ import.description|trans }}</blockquote> |
diff --git a/src/Wallabag/UserBundle/Entity/User.php b/src/Wallabag/UserBundle/Entity/User.php index d98ae76a..3a167de7 100644 --- a/src/Wallabag/UserBundle/Entity/User.php +++ b/src/Wallabag/UserBundle/Entity/User.php | |||
@@ -11,6 +11,7 @@ use JMS\Serializer\Annotation\ExclusionPolicy; | |||
11 | use JMS\Serializer\Annotation\Expose; | 11 | use JMS\Serializer\Annotation\Expose; |
12 | use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; | 12 | use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; |
13 | use Symfony\Component\Security\Core\User\UserInterface; | 13 | use Symfony\Component\Security\Core\User\UserInterface; |
14 | use Wallabag\ApiBundle\Entity\Client; | ||
14 | use Wallabag\CoreBundle\Entity\Config; | 15 | use Wallabag\CoreBundle\Entity\Config; |
15 | use Wallabag\CoreBundle\Entity\Entry; | 16 | use Wallabag\CoreBundle\Entity\Entry; |
16 | 17 | ||
@@ -84,6 +85,11 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
84 | */ | 85 | */ |
85 | private $trusted; | 86 | private $trusted; |
86 | 87 | ||
88 | /** | ||
89 | * @ORM\OneToMany(targetEntity="Wallabag\ApiBundle\Entity\Client", mappedBy="user", cascade={"remove"}) | ||
90 | */ | ||
91 | protected $clients; | ||
92 | |||
87 | public function __construct() | 93 | public function __construct() |
88 | { | 94 | { |
89 | parent::__construct(); | 95 | parent::__construct(); |
@@ -240,4 +246,24 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
240 | 246 | ||
241 | return false; | 247 | return false; |
242 | } | 248 | } |
249 | |||
250 | /** | ||
251 | * @param Client $client | ||
252 | * | ||
253 | * @return User | ||
254 | */ | ||
255 | public function addClient(Client $client) | ||
256 | { | ||
257 | $this->clients[] = $client; | ||
258 | |||
259 | return $this; | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * @return ArrayCollection<Entry> | ||
264 | */ | ||
265 | public function getClients() | ||
266 | { | ||
267 | return $this->clients; | ||
268 | } | ||
243 | } | 269 | } |
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 a8ee721b..164a25ec 100644 --- a/src/Wallabag/UserBundle/Resources/config/services.yml +++ b/src/Wallabag/UserBundle/Resources/config/services.yml | |||
@@ -22,7 +22,7 @@ services: | |||
22 | arguments: | 22 | arguments: |
23 | - WallabagUserBundle:User | 23 | - WallabagUserBundle:User |
24 | 24 | ||
25 | wallabag_user.create_config: | 25 | wallabag_user.listener.create_config: |
26 | class: Wallabag\UserBundle\EventListener\CreateConfigListener | 26 | class: Wallabag\UserBundle\EventListener\CreateConfigListener |
27 | arguments: | 27 | arguments: |
28 | - "@doctrine.orm.entity_manager" | 28 | - "@doctrine.orm.entity_manager" |