diff options
author | Jeremy Benoist <jeremy.benoist@gmail.com> | 2016-10-01 14:01:13 +0200 |
---|---|---|
committer | Jeremy Benoist <jeremy.benoist@gmail.com> | 2016-10-22 13:13:07 +0200 |
commit | 191564b7f71d01fb4c597c9b9641e23db564278d (patch) | |
tree | 1cf81a2474d064f11663c70bd77121fc3c4c69a1 /src | |
parent | 98efffc2a62820bad347a0f93840c48fa57f8cc3 (diff) | |
download | wallabag-191564b7f71d01fb4c597c9b9641e23db564278d.tar.gz wallabag-191564b7f71d01fb4c597c9b9641e23db564278d.tar.zst wallabag-191564b7f71d01fb4c597c9b9641e23db564278d.zip |
Add custom doctrine subscriber for SQLite
Since SQLite doesn’t handle cascade remove by default, we need to handle it manually.
Also some refacto
Diffstat (limited to 'src')
5 files changed, 144 insertions, 11 deletions
diff --git a/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php b/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php index 5f7da70e..d999dc0f 100644 --- a/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php +++ b/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php | |||
@@ -106,4 +106,17 @@ class AnnotationRepository extends EntityRepository | |||
106 | ->getQuery() | 106 | ->getQuery() |
107 | ->getSingleResult(); | 107 | ->getSingleResult(); |
108 | } | 108 | } |
109 | |||
110 | /** | ||
111 | * Remove all annotations for a user id. | ||
112 | * Used when a user want to reset all informations | ||
113 | * | ||
114 | * @param int $userId | ||
115 | */ | ||
116 | public function removeAllByUserId($userId) | ||
117 | { | ||
118 | $this->getEntityManager() | ||
119 | ->createQuery('DELETE FROM Wallabag\AnnotationBundle\Entity\Annotation a WHERE a.user = '.$userId) | ||
120 | ->execute(); | ||
121 | } | ||
109 | } | 122 | } |
diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php index ccbf550a..faa85d16 100644 --- a/src/Wallabag/CoreBundle/Controller/ConfigController.php +++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php | |||
@@ -237,25 +237,26 @@ class ConfigController extends Controller | |||
237 | 237 | ||
238 | switch ($type) { | 238 | switch ($type) { |
239 | case 'annotations': | 239 | case 'annotations': |
240 | $em->createQuery('DELETE FROM Wallabag\AnnotationBundle\Entity\Annotation a WHERE a.user = '.$this->getUser()->getId()) | 240 | $this->getDoctrine() |
241 | ->execute(); | 241 | ->getRepository('WallabagAnnotationBundle:Annotation') |
242 | ->removeAllByUserId($this->getUser()->getId()); | ||
242 | break; | 243 | break; |
243 | 244 | ||
244 | case 'tags': | 245 | case 'tags': |
245 | $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findAllTags($this->getUser()->getId()); | 246 | $this->removeAllTagsByUserId($this->getUser()->getId()); |
247 | break; | ||
246 | 248 | ||
247 | if (empty($tags)) { | 249 | case 'entries': |
248 | break; | 250 | // SQLite doesn't care about cascading remove, so we need to manually remove associated stuf |
251 | // otherwise they won't be removed ... | ||
252 | if ($this->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) { | ||
253 | $this->getDoctrine()->getRepository('WallabagAnnotationBundle:Annotation')->removeAllByUserId($this->getUser()->getId()); | ||
254 | $this->removeAllTagsByUserId($this->getUser()->getId()); | ||
249 | } | 255 | } |
250 | 256 | ||
251 | $this->getDoctrine() | 257 | $this->getDoctrine() |
252 | ->getRepository('WallabagCoreBundle:Entry') | 258 | ->getRepository('WallabagCoreBundle:Entry') |
253 | ->removeTags($this->getUser()->getId(), $tags); | 259 | ->removeAllByUserId($this->getUser()->getId()); |
254 | break; | ||
255 | |||
256 | case 'entries': | ||
257 | $em->createQuery('DELETE FROM Wallabag\CoreBundle\Entity\Entry e WHERE e.user = '.$this->getUser()->getId()) | ||
258 | ->execute(); | ||
259 | } | 260 | } |
260 | 261 | ||
261 | $this->get('session')->getFlashBag()->add( | 262 | $this->get('session')->getFlashBag()->add( |
@@ -267,6 +268,24 @@ class ConfigController extends Controller | |||
267 | } | 268 | } |
268 | 269 | ||
269 | /** | 270 | /** |
271 | * Remove all tags for a given user. | ||
272 | * | ||
273 | * @param int $userId | ||
274 | */ | ||
275 | private function removeAllTagsByUserId($userId) | ||
276 | { | ||
277 | $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findAllTags($userId); | ||
278 | |||
279 | if (empty($tags)) { | ||
280 | return; | ||
281 | } | ||
282 | |||
283 | $this->getDoctrine() | ||
284 | ->getRepository('WallabagCoreBundle:Entry') | ||
285 | ->removeTags($userId, $tags); | ||
286 | } | ||
287 | |||
288 | /** | ||
270 | * Validate that a rule can be edited/deleted by the current user. | 289 | * Validate that a rule can be edited/deleted by the current user. |
271 | * | 290 | * |
272 | * @param TaggingRule $rule | 291 | * @param TaggingRule $rule |
diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index cd2b47b9..8704a2a6 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php | |||
@@ -329,4 +329,17 @@ 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 | ->execute(); | ||
344 | } | ||
332 | } | 345 | } |
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index a4b727f4..540d21f1 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml | |||
@@ -88,6 +88,17 @@ services: | |||
88 | arguments: | 88 | arguments: |
89 | - WallabagCoreBundle:Tag | 89 | - WallabagCoreBundle:Tag |
90 | 90 | ||
91 | wallabag_core.listener.registration_confirmed: | ||
92 | class: Wallabag\CoreBundle\EventListener\RegistrationConfirmedListener | ||
93 | arguments: | ||
94 | - "@doctrine.orm.entity_manager" | ||
95 | - "%wallabag_core.theme%" | ||
96 | - "%wallabag_core.items_on_page%" | ||
97 | - "%wallabag_core.rss_limit%" | ||
98 | - "%wallabag_core.language%" | ||
99 | tags: | ||
100 | - { name: kernel.event_subscriber } | ||
101 | |||
91 | wallabag_core.helper.entries_export: | 102 | wallabag_core.helper.entries_export: |
92 | class: Wallabag\CoreBundle\Helper\EntriesExport | 103 | class: Wallabag\CoreBundle\Helper\EntriesExport |
93 | arguments: | 104 | arguments: |
@@ -129,3 +140,10 @@ services: | |||
129 | arguments: | 140 | arguments: |
130 | - '@twig' | 141 | - '@twig' |
131 | - '%kernel.debug%' | 142 | - '%kernel.debug%' |
143 | |||
144 | wallabag_core.subscriber.sqlite_cascade_delete: | ||
145 | class: Wallabag\CoreBundle\Subscriber\SQLiteCascadeDeleteSubscriber | ||
146 | arguments: | ||
147 | - "@doctrine" | ||
148 | tags: | ||
149 | - { name: doctrine.event_subscriber } | ||
diff --git a/src/Wallabag/CoreBundle/Subscriber/SQLiteCascadeDeleteSubscriber.php b/src/Wallabag/CoreBundle/Subscriber/SQLiteCascadeDeleteSubscriber.php new file mode 100644 index 00000000..d5180577 --- /dev/null +++ b/src/Wallabag/CoreBundle/Subscriber/SQLiteCascadeDeleteSubscriber.php | |||
@@ -0,0 +1,70 @@ | |||
1 | <?php | ||
2 | namespace Wallabag\CoreBundle\Subscriber; | ||
3 | |||
4 | use Doctrine\Common\EventSubscriber; | ||
5 | use Doctrine\ORM\EntityManager; | ||
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 | } | ||