]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
Allow to remove all archived entries
authorThomas Citharel <tcit@tcit.fr>
Thu, 30 Mar 2017 14:24:59 +0000 (16:24 +0200)
committerNicolas Lœuillet <nicolas@loeuillet.org>
Fri, 31 Mar 2017 08:46:05 +0000 (10:46 +0200)
Since we still support fucking SQLite, we need to retrieve all tags & annotations for archived entries before deleting them.

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
18 files changed:
src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php
src/Wallabag/CoreBundle/Controller/ConfigController.php
src/Wallabag/CoreBundle/Repository/EntryRepository.php
src/Wallabag/CoreBundle/Repository/TagRepository.php
src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php

index 8d3f07eef350f2eb8ebf12a05b80deb5f6d026fb..23f21c3e3630a0e9636348e1e8871af94e083dee 100644 (file)
@@ -122,4 +122,20 @@ class AnnotationRepository extends EntityRepository
             ->setParameter('userId', $userId)
             ->execute();
     }
+
+    /**
+     * Find all annotations related to archived entries
+     *
+     * @param $userId
+     * @return mixed
+     */
+    public function findAllByArchivedEntriesAndUserId($userId)
+    {
+        return $this->createQueryBuilder('a')
+            ->leftJoin('a.entry', 'e')
+            ->where('a.user = :userid')->setParameter(':userid', $userId)
+            ->andWhere('e.isArchived = true')
+            ->getQuery()
+            ->getResult();
+    }
 }
index 907bf78e148955cab069c730d8942de2731be664..7dbe3f1875902d88e3f65df80ccd14a8f5dd9a85 100644 (file)
@@ -248,7 +248,7 @@ class ConfigController extends Controller
                 break;
 
             case 'entries':
-                // SQLite doesn't care about cascading remove, so we need to manually remove associated stuf
+                // SQLite doesn't care about cascading remove, so we need to manually remove associated stuff
                 // otherwise they won't be removed ...
                 if ($this->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) {
                     $this->getDoctrine()->getRepository('WallabagAnnotationBundle:Annotation')->removeAllByUserId($this->getUser()->getId());
@@ -260,6 +260,19 @@ class ConfigController extends Controller
                 $this->getDoctrine()
                     ->getRepository('WallabagCoreBundle:Entry')
                     ->removeAllByUserId($this->getUser()->getId());
+                break;
+            case 'archived':
+                if ($this->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) {
+                    $this->removeAnnotationsForArchivedByUserId($this->getUser()->getId());
+                }
+
+                // manually remove tags to avoid orphan tag
+                $this->removeTagsForArchivedByUserId($this->getUser()->getId());
+
+                $this->getDoctrine()
+                    ->getRepository('WallabagCoreBundle:Entry')
+                    ->removeArchivedByUserId($this->getUser()->getId());
+                break;
         }
 
         $this->get('session')->getFlashBag()->add(
@@ -299,6 +312,50 @@ class ConfigController extends Controller
         $em->flush();
     }
 
+    /**
+     * Remove all tags for a given user and cleanup orphan tags.
+     *
+     * @param int $userId
+     */
+    private function removeTagsForArchivedByUserId($userId)
+    {
+        $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findTagsForArchivedArticles($userId);
+
+        if (empty($tags)) {
+            return;
+        }
+
+        $this->getDoctrine()
+            ->getRepository('WallabagCoreBundle:Entry')
+            ->removeTags($userId, $tags);
+
+        // cleanup orphan tags
+        $em = $this->getDoctrine()->getManager();
+
+        foreach ($tags as $tag) {
+            if (count($tag->getEntries()) === 0) {
+                $em->remove($tag);
+            }
+        }
+
+        $em->flush();
+    }
+
+    private function removeAnnotationsForArchivedByUserId($userId)
+    {
+        $em = $this->getDoctrine()->getManager();
+
+        $archivedEntriesAnnotations = $this->getDoctrine()
+            ->getRepository('WallabagAnnotationBundle:Annotation')
+            ->findAllByArchivedEntriesAndUserId($userId);
+
+        foreach ($archivedEntriesAnnotations as $archivedEntriesAnnotation) {
+            $em->remove($archivedEntriesAnnotation);
+        }
+
+        $em->flush();
+    }
+
     /**
      * Validate that a rule can be edited/deleted by the current user.
      *
index 9325d261f4e284ead6c1697079d0a6f69b62a841..1f22e901ba4d537a2e757f9901a03987bc0b5bcf 100644 (file)
@@ -371,4 +371,12 @@ class EntryRepository extends EntityRepository
             ->setParameter('userId', $userId)
             ->execute();
     }
+
+    public function removeArchivedByUserId($userId)
+    {
+        $this->getEntityManager()
+            ->createQuery('DELETE FROM Wallabag\CoreBundle\Entity\Entry e WHERE e.user = :userId AND e.isArchived = TRUE')
+            ->setParameter('userId', $userId)
+            ->execute();
+    }
 }
index 2182df254315b9341448f01ba7191bfc50eed7e1..b78e244ecda63d1ca8834768f1602cb82cbe3488 100644 (file)
@@ -76,4 +76,24 @@ class TagRepository extends EntityRepository
             ->getQuery()
             ->getSingleResult();
     }
+
+    public function findTagsForArchivedArticles($userId)
+    {
+        $ids = $this->createQueryBuilder('t')
+            ->select('t.id')
+            ->leftJoin('t.entries', 'e')
+            ->where('e.user = :userId')->setParameter('userId', $userId)
+            ->andWhere('e.isArchived = true')
+            ->groupBy('t.id')
+            ->orderBy('t.slug')
+            ->getQuery()
+            ->getArrayResult();
+
+        $tags = [];
+        foreach ($ids as $id) {
+            $tags[] = $this->find($id);
+        }
+
+        return $tags;
+    }
 }
index 5d9e85e40898ce1e885d5db328a9af8fc1c073f3..dfac7a65a5f28236ef4f5ab7378602d166a26725 100644 (file)
@@ -110,6 +110,7 @@ config:
         # annotations: Remove ALL annotations
         # tags: Remove ALL tags
         # entries: Remove ALL entries
+        # archived: Remove ALL archived entries
         # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
     form_password:
         # description: "You can change your password here. Your new password should by at least 8 characters long."
@@ -528,6 +529,7 @@ flashes:
             # annotations_reset: Annotations reset
             # tags_reset: Tags reset
             # entries_reset: Entries reset
+            # archived_reset: Archived entries deleted
     entry:
         notice:
             # entry_already_saved: 'Entry already saved on %date%'
index f1952a3e8b298d6ed95e0105d175e1c1c7033686..0b9df325b023064c8235b30edb56318da5e5edd9 100644 (file)
@@ -110,6 +110,7 @@ config:
         annotations: Entferne ALLE Annotationen
         tags: Entferne ALLE Tags
         entries: Entferne ALLE Einträge
+        # archived: Remove ALL archived entries
         confirm: Bist du wirklich sicher? (DIES KANN NICHT RÜCKGÄNGIG GEMACHT WERDEN)
     form_password:
         description: "Hier kannst du dein Kennwort ändern. Dieses sollte mindestens acht Zeichen enthalten."
@@ -528,6 +529,7 @@ flashes:
             annotations_reset: Anmerkungen zurücksetzen
             tags_reset: Tags zurücksetzen
             entries_reset: Einträge zurücksetzen
+            # archived_reset: Archived entries deleted
     entry:
         notice:
             entry_already_saved: 'Eintrag bereits am %date% gespeichert'
index 8e7e3c2ce7655932478f69ee1533bd055e29da38..2fa3192ed5c51a77018bd20699b44bc0b08d90d8 100644 (file)
@@ -110,6 +110,7 @@ config:
         annotations: Remove ALL annotations
         tags: Remove ALL tags
         entries: Remove ALL entries
+        archived: Remove ALL archived entries
         confirm: Are you really sure? (THIS CAN'T BE UNDONE)
     form_password:
         description: "You can change your password here. Your new password should by at least 8 characters long."
@@ -528,6 +529,7 @@ flashes:
             annotations_reset: Annotations reset
             tags_reset: Tags reset
             entries_reset: Entries reset
+            archived_reset: Archived entries deleted
     entry:
         notice:
             entry_already_saved: 'Entry already saved on %date%'
index 3d65c311b1460261efd8b09d4cd6e0c53c0b9b52..ce581d8998f4b182ee28591b0d4ba34beaaf7635 100644 (file)
@@ -110,6 +110,7 @@ config:
         annotations: Eliminar TODAS las anotaciones
         tags: Eliminar TODAS las etiquetas
         entries: Eliminar TODOS los artículos
+        # archived: Remove ALL archived entries
         confirm: ¿Estás completamente seguro? (NO SE PUEDE DESHACER)
     form_password:
         description: "Puedes cambiar la contraseña aquí. Tu nueva contraseña debe tener al menos 8 caracteres."
@@ -528,6 +529,7 @@ flashes:
             annotations_reset: Anotaciones reiniciadas
             tags_reset: Etiquetas reiniciadas
             entries_reset: Artículos reiniciados
+            # archived_reset: Archived entries deleted
     entry:
         notice:
             entry_already_saved: 'Artículo ya guardado el %fecha%'
index 80500d194acd724e2911c5ac87f1a7daca7a1c36..3e3ee12c307580563bc705bf83bec6cb684c60e3 100644 (file)
@@ -110,6 +110,7 @@ config:
         # annotations: Remove ALL annotations
         # tags: Remove ALL tags
         # entries: Remove ALL entries
+        # archived: Remove ALL archived entries
         # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
     form_password:
         # description: "You can change your password here. Your new password should by at least 8 characters long."
@@ -528,6 +529,7 @@ flashes:
             # annotations_reset: Annotations reset
             # tags_reset: Tags reset
             # entries_reset: Entries reset
+            # archived_reset: Archived entries deleted
     entry:
         notice:
             entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود'
index 4f49f777a69993141d58c6516db04567b4942997..074593a6f13d565d52ef40087c91b2bbdfc3653e 100644 (file)
@@ -110,6 +110,7 @@ config:
         annotations: Supprimer TOUTES les annotations
         tags: Supprimer TOUS les tags
         entries: Supprimer TOUS les articles
+        archived: Supprimer TOUS les articles archivés
         confirm: Êtes-vous vraiment vraiment sûr ? (C'EST IRRÉVERSIBLE)
     form_password:
         description: "Vous pouvez changer ici votre mot de passe. Le mot de passe doit contenir au moins 8 caractères."
@@ -528,6 +529,7 @@ flashes:
             annotations_reset: Annotations supprimées
             tags_reset: Tags supprimés
             entries_reset: Articles supprimés
+            archived_reset: Articles archivés supprimés
     entry:
         notice:
             entry_already_saved: "Article déjà sauvegardé le %date%"
index 992ff71cb4178deb3e7786638e8a25716a58f9a2..0d86756ab4c2234fd1f5a3010ebba4a0a293e3ad 100644 (file)
@@ -110,6 +110,7 @@ config:
         # annotations: Remove ALL annotations
         # tags: Remove ALL tags
         # entries: Remove ALL entries
+        # archived: Remove ALL archived entries
         # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
     form_password:
         # description: "You can change your password here. Your new password should by at least 8 characters long."
@@ -528,6 +529,7 @@ flashes:
             # annotations_reset: Annotations reset
             # tags_reset: Tags reset
             # entries_reset: Entries reset
+            # archived_reset: Archived entries deleted
     entry:
         notice:
             entry_already_saved: 'Contenuto già salvato in data %date%'
index f64885654124909fd21d14309320cc1b0e396561..d2949c503accb81d8afb4864d7058dffee0c1bc6 100644 (file)
@@ -110,6 +110,7 @@ config:
         annotations: Levar TOTAS las anotacions
         tags: Levar TOTAS las etiquetas
         entries: Levar TOTES los articles
+        # archived: Remove ALL archived entries
         confirm: Sètz vertadièrament segur ? (ES IRREVERSIBLE)
     form_password:
         description: "Podètz cambiar vòstre senhal aquí. Vòstre senhal deu èsser long d'almens 8 caractèrs."
@@ -528,6 +529,7 @@ flashes:
             annotations_reset: Anotacions levadas
             tags_reset: Etiquetas levadas
             entries_reset: Articles levats
+            # archived_reset: Archived entries deleted
     entry:
         notice:
             entry_already_saved: 'Article ja salvargardat lo %date%'
index eda9bbbf68fb7ad4246f4ad536b340970f2a8be9..1f512942b6709692d6f5673f2661386031843b92 100644 (file)
@@ -110,6 +110,7 @@ config:
         annotations: Usuń WSZYSTKIE adnotacje
         tags: Usuń WSZYSTKIE tagi
         entries: usuń WSZYTSTKIE wpisy
+        # archived: Remove ALL archived entries
         confirm: Jesteś pewien? (tej operacji NIE MOŻNA cofnąć)
     form_password:
         description: "Tutaj możesz zmienić swoje hasło. Twoje nowe hasło powinno mieć conajmniej 8 znaków."
@@ -528,6 +529,7 @@ flashes:
             annotations_reset: Zresetuj adnotacje
             tags_reset: Zresetuj tagi
             entries_reset: Zresetuj wpisy
+            # archived_reset: Archived entries deleted
     entry:
         notice:
             entry_already_saved: 'Wpis już został dodany %date%'
index 8a7cc6f8617a701c9ab23e2f0b056c5c770993f9..2e8152304f12597040ea668c00c9f9b8277838c6 100644 (file)
@@ -110,6 +110,7 @@ config:
         # annotations: Remove ALL annotations
         # tags: Remove ALL tags
         # entries: Remove ALL entries
+        # archived: Remove ALL archived entries
         # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
     form_password:
         # description: "You can change your password here. Your new password should by at least 8 characters long."
@@ -528,6 +529,7 @@ flashes:
             # annotations_reset: Annotations reset
             # tags_reset: Tags reset
             # entries_reset: Entries reset
+            # archived_reset: Archived entries deleted
     entry:
         notice:
             entry_already_saved: 'Entrada já foi salva em %date%'
index 52b6414f3f008c5f7357430cd29939e925d31463..16401efd12ab5c1f45f088c071b37945efaae5ea 100644 (file)
@@ -110,6 +110,7 @@ config:
         # annotations: Remove ALL annotations
         # tags: Remove ALL tags
         # entries: Remove ALL entries
+        # archived: Remove ALL archived entries
         # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
     form_password:
         # description: "You can change your password here. Your new password should by at least 8 characters long."
@@ -528,6 +529,7 @@ flashes:
             # annotations_reset: Annotations reset
             # tags_reset: Tags reset
             # entries_reset: Entries reset
+            # archived_reset: Archived entries deleted
     entry:
         notice:
             # entry_already_saved: 'Entry already saved on %date%'
index bfb7e206a5eb7c5d56afbec06b788156ad09dfac..a4bf7dfe2541569ea95ff63ea150cd8a196336d8 100644 (file)
@@ -110,6 +110,7 @@ config:
         # annotations: Remove ALL annotations
         # tags: Remove ALL tags
         # entries: Remove ALL entries
+        # archived: Remove ALL archived entries
         # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
     form_password:
         # description: "You can change your password here. Your new password should by at least 8 characters long."
@@ -528,6 +529,7 @@ flashes:
             # annotations_reset: Annotations reset
             # tags_reset: Tags reset
             # entries_reset: Entries reset
+            # archived_reset: Archived entries deleted
     entry:
         notice:
             entry_already_saved: 'Entry already saved on %date%'
index 5d411fdd1f0cc4496a8990a050b87dcab5873ef6..708ff951f609e3091207c527a5336e706d89309d 100644 (file)
                             <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
                                 {{ 'config.reset.tags'|trans }}
                             </a>
+                            <a href="{{ path('config_reset', { type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
+                                {{ 'config.reset.archived'|trans }}
+                            </a>
                             <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
                                 {{ 'config.reset.entries'|trans }}
                             </a>
index 8f2ca1cb3954c44f4c3610958028fbf996ac7d54..b434a4c4009645a65f7af59121df372a4a203c87 100644 (file)
@@ -803,6 +803,82 @@ class ConfigControllerTest extends WallabagCoreTestCase
         $this->assertEquals(0, $entryReset, 'Entries were reset');
     }
 
+    public function testResetArchivedEntries()
+    {
+        $this->logInAs('empty');
+        $client = $this->getClient();
+
+        $em = $client->getContainer()->get('doctrine.orm.entity_manager');
+
+        $user = static::$kernel->getContainer()->get('security.token_storage')->getToken()->getUser();
+
+        $tag = new Tag();
+        $tag->setLabel('super');
+        $em->persist($tag);
+
+        $entry = new Entry($user);
+        $entry->setUrl('http://www.lemonde.fr/europe/article/2016/10/01/pour-le-psoe-chaque-election-s-est-transformee-en-une-agonie_5006476_3214.html');
+        $entry->setContent('Youhou');
+        $entry->setTitle('Youhou');
+        $entry->addTag($tag);
+        $em->persist($entry);
+
+        $annotation = new Annotation($user);
+        $annotation->setText('annotated');
+        $annotation->setQuote('annotated');
+        $annotation->setRanges([]);
+        $annotation->setEntry($entry);
+        $em->persist($annotation);
+
+        $tagArchived = new Tag();
+        $tagArchived->setLabel('super');
+        $em->persist($tagArchived);
+
+        $entryArchived = new Entry($user);
+        $entryArchived->setUrl('http://www.lemonde.fr/europe/article/2016/10/01/pour-le-psoe-chaque-election-s-est-transformee-en-une-agonie_5006476_3214.html');
+        $entryArchived->setContent('Youhou');
+        $entryArchived->setTitle('Youhou');
+        $entryArchived->addTag($tagArchived);
+        $entryArchived->setArchived(true);
+        $em->persist($entryArchived);
+
+        $annotationArchived = new Annotation($user);
+        $annotationArchived->setText('annotated');
+        $annotationArchived->setQuote('annotated');
+        $annotationArchived->setRanges([]);
+        $annotationArchived->setEntry($entryArchived);
+        $em->persist($annotationArchived);
+
+        $em->flush();
+
+        $crawler = $client->request('GET', '/config#set3');
+
+        $this->assertEquals(200, $client->getResponse()->getStatusCode());
+
+        $crawler = $client->click($crawler->selectLink('config.reset.archived')->link());
+
+        $this->assertEquals(302, $client->getResponse()->getStatusCode());
+        $this->assertContains('flashes.config.notice.archived_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
+
+        $entryReset = $em
+            ->getRepository('WallabagCoreBundle:Entry')
+            ->countAllEntriesByUsername($user->getId());
+
+        $this->assertEquals(1, $entryReset, 'Entries were reset');
+
+        $tagReset = $em
+            ->getRepository('WallabagCoreBundle:Tag')
+            ->countAllTags($user->getId());
+
+        $this->assertEquals(1, $tagReset, 'Tags were reset');
+
+        $annotationsReset = $em
+            ->getRepository('WallabagAnnotationBundle:Annotation')
+            ->findAnnotationsByPageId($annotationArchived->getId(), $user->getId());
+
+        $this->assertEmpty($annotationsReset, 'Annotations were reset');
+    }
+
     public function testResetEntriesCascade()
     {
         $this->logInAs('empty');