From 4059a061c0c8cc787f71e96aef2ab01599d3241d Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Tue, 29 Dec 2015 15:08:33 +0100 Subject: [PATCH] Fix the way to remove a tag from all user entries --- .../Controller/WallabagRestControllerTest.php | 7 +++ .../ApiBundle/Tests/WallabagApiTestCase.php | 9 +++- .../CoreBundle/Repository/EntryRepository.php | 47 +++++++++++++++---- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/Wallabag/ApiBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/ApiBundle/Tests/Controller/WallabagRestControllerTest.php index a7120e83..22894a77 100644 --- a/src/Wallabag/ApiBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/ApiBundle/Tests/Controller/WallabagRestControllerTest.php @@ -310,5 +310,12 @@ class WallabagRestControllerTest extends WallabagApiTestCase $this->assertArrayHasKey('label', $content); $this->assertEquals($tag['label'], $content['label']); $this->assertEquals($tag['slug'], $content['slug']); + + $entries = $entry = $this->client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCoreBundle:Entry') + ->findAllByTagId($this->user->getId(), $tag['id']); + + $this->assertCount(0, $entries); } } diff --git a/src/Wallabag/ApiBundle/Tests/WallabagApiTestCase.php b/src/Wallabag/ApiBundle/Tests/WallabagApiTestCase.php index 8a57fea2..a415c749 100644 --- a/src/Wallabag/ApiBundle/Tests/WallabagApiTestCase.php +++ b/src/Wallabag/ApiBundle/Tests/WallabagApiTestCase.php @@ -12,6 +12,11 @@ abstract class WallabagApiTestCase extends WebTestCase */ protected $client = null; + /** + * @var \FOS\UserBundle\Model\UserInterface + */ + protected $user; + public function setUp() { $this->client = $this->createAuthorizedClient(); @@ -31,8 +36,8 @@ abstract class WallabagApiTestCase extends WebTestCase $loginManager = $container->get('fos_user.security.login_manager'); $firewallName = $container->getParameter('fos_user.firewall_name'); - $user = $userManager->findUserBy(array('username' => 'admin')); - $loginManager->loginUser($firewallName, $user); + $this->user = $userManager->findUserBy(array('username' => 'admin')); + $loginManager->loginUser($firewallName, $this->user); // save the login token into the session and put it in a cookie $container->get('session')->set('_security_'.$firewallName, serialize($container->get('security.token_storage')->getToken())); diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index 9ff80d6e..e658a359 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php @@ -183,19 +183,50 @@ class EntryRepository extends EntityRepository /** * Remove a tag from all user entries. - * We are using a native SQL query because Doctrine doesn't know EntryTag entity because it's a ManyToMany relation. - * Instead of that SQL query we should loop on every entry and remove the tag, could be really long ... + * + * We need to loop on each entry attached to the given tag to remove it, since Doctrine doesn't know EntryTag entity because it's a ManyToMany relation. + * It could be faster with one query but I don't know how to retrieve the table name `entry_tag` which can have a prefix. * * @param int $userId * @param Tag $tag */ public function removeTag($userId, Tag $tag) { - $sql = 'DELETE et FROM entry_tag et WHERE et.entry_id IN ( SELECT e.id FROM entry e WHERE e.user_id = :userId ) AND et.tag_id = :tagId'; - $stmt = $this->getEntityManager()->getConnection()->prepare($sql); - $stmt->execute([ - 'userId' => $userId, - 'tagId' => $tag->getId(), - ]); + $entries = $this->getBuilderByUser($userId) + ->innerJoin('e.tags', 't') + ->andWhere('t.id = :tagId')->setParameter('tagId', $tag->getId()) + ->getQuery() + ->getResult(); + + foreach ($entries as $entry) { + $entry->removeTag($tag); + } + + $this->getEntityManager()->flush(); + + // An other solution can be to use raw query but I can't find a way to retrieve the `entry_tag` table name since it can be prefixed.... + // $sql = 'DELETE et FROM entry_tag et WHERE et.entry_id IN ( SELECT e.id FROM entry e WHERE e.user_id = :userId ) AND et.tag_id = :tagId'; + // $stmt = $this->getEntityManager()->getConnection()->prepare($sql); + // $stmt->execute([ + // 'userId' => $userId, + // 'tagId' => $tag->getId(), + // ]); + } + + /** + * Find all entries that are attached to a give tag id. + * + * @param int $userId + * @param int $tagId + * + * @return array + */ + public function findAllByTagId($userId, $tagId) + { + return $this->getBuilderByUser($userId) + ->innerJoin('e.tags', 't') + ->andWhere('t.id = :tagId')->setParameter('tagId', $tagId) + ->getQuery() + ->getResult(); } } -- 2.41.0