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>
->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();
+ }
}
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());
$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(
$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.
*
->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();
+ }
}
->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;
+ }
}
# 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."
# 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%'
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."
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'
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."
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%'
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."
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%'
# 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."
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
+ # archived_reset: Archived entries deleted
entry:
notice:
entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود'
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."
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%"
# 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."
# 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%'
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."
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%'
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."
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%'
# 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."
# 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%'
# 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."
# 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%'
# 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."
# 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%'
<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>
$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');