From 625acf335298186b4ff983f9321900d1238e854b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Gomez?= Date: Sat, 24 Oct 2015 15:11:06 +0200 Subject: [PATCH] Add a command to automatically tag all entries for a user --- app/config/config.yml | 4 ++ composer.json | 2 +- composer.lock | 4 +- .../CoreBundle/Command/TagAllCommand.php | 66 +++++++++++++++++++ src/Wallabag/CoreBundle/Entity/Entry.php | 4 ++ .../CoreBundle/Helper/RuleBasedTagger.php | 38 ++++++++++- .../CoreBundle/Resources/config/services.yml | 8 +++ .../Tests/Helper/RuleBasedTaggerTest.php | 19 ++++-- .../UserBundle/Repository/UserRepository.php | 15 +++++ 9 files changed, 149 insertions(+), 11 deletions(-) create mode 100644 src/Wallabag/CoreBundle/Command/TagAllCommand.php diff --git a/app/config/config.yml b/app/config/config.yml index 285fbd7cf..82c5e7c99 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -189,3 +189,7 @@ scheb_two_factor: sender_email: %twofactor_sender% digits: 6 template: WallabagUserBundle:Authentication:form.html.twig + +kphoen_rulerz: + executors: + doctrine: true diff --git a/composer.json b/composer.json index a9c734ab5..bf40e471d 100644 --- a/composer.json +++ b/composer.json @@ -58,7 +58,7 @@ "scheb/two-factor-bundle": "~1.4", "grandt/phpepub": "~4.0", "wallabag/php-mobi": "~1.0.0", - "kphoen/rulerz-bundle": "~0.7,>=0.7.2" + "kphoen/rulerz-bundle": "~0.7,>=0.7.3" }, "require-dev": { "doctrine/doctrine-fixtures-bundle": "~2.2.0", diff --git a/composer.lock b/composer.lock index b88c56e86..c470656ad 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "8719c5ec3c13338ff792ce5ed8d12926", - "content-hash": "3f28af906ef3d4eaac41583bfcc5bd85", + "hash": "a1f0e0b886031d96a9756de581d7d557", + "content-hash": "d0a24cdd93bd431af386715f24e3e389", "packages": [ { "name": "doctrine/annotations", diff --git a/src/Wallabag/CoreBundle/Command/TagAllCommand.php b/src/Wallabag/CoreBundle/Command/TagAllCommand.php new file mode 100644 index 000000000..2cf3f8084 --- /dev/null +++ b/src/Wallabag/CoreBundle/Command/TagAllCommand.php @@ -0,0 +1,66 @@ +setName('wallabag:tag:all') + ->setDescription('Tag all entries using the tagging rules.') + ->addArgument( + 'username', + InputArgument::REQUIRED, + 'User to tag entries for.' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + try { + $user = $this->getUser($input->getArgument('username')); + } catch (NoResultException $e) { + $output->writeln(sprintf('User %s not found.', $input->getArgument('username'))); + + return 1; + } + $tagger = $this->getContainer()->get('wallabag_core.rule_based_tagger'); + + $output->write(sprintf('Tagging entries for user « %s »... ', $user->getUserName())); + + $entries = $tagger->tagAllForUser($user); + + $em = $this->getDoctrine()->getManager(); + foreach ($entries as $entry) { + $em->persist($entry); + } + $em->flush(); + + $output->writeln('Done.'); + } + + /** + * Fetches a user from its username. + * + * @param string $username + * + * @return \Wallabag\UserBundle\Entity\User + */ + private function getUser($username) + { + return $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findOneByUserName($username); + } + + private function getDoctrine() + { + return $this->getContainer()->get('doctrine'); + } +} diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index 5aa582f8d..608ed2f0d 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php @@ -458,6 +458,10 @@ class Entry */ public function addTag(Tag $tag) { + if ($this->tags->contains($tag)) { + return; + } + $this->tags[] = $tag; $tag->addEntry($this); } diff --git a/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php b/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php index bb9337797..3f9953c09 100644 --- a/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php +++ b/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php @@ -6,6 +6,7 @@ use RulerZ\RulerZ; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; +use Wallabag\CoreBundle\Repository\EntryRepository; use Wallabag\CoreBundle\Repository\TagRepository; use Wallabag\UserBundle\Entity\User; @@ -13,11 +14,13 @@ class RuleBasedTagger { private $rulerz; private $tagRepository; + private $entryRepository; - public function __construct(RulerZ $rulerz, TagRepository $tagRepository) + public function __construct(RulerZ $rulerz, TagRepository $tagRepository, EntryRepository $entryRepository) { - $this->rulerz = $rulerz; - $this->tagRepository = $tagRepository; + $this->rulerz = $rulerz; + $this->tagRepository = $tagRepository; + $this->entryRepository = $entryRepository; } /** @@ -42,6 +45,35 @@ class RuleBasedTagger } } + /** + * Apply all the tagging rules defined by a user on its entries. + * + * @param User $user + * + * @return array A list of modified entries. + */ + public function tagAllForUser(User $user) + { + $rules = $this->getRulesForUser($user); + $entries = array(); + + foreach ($rules as $rule) { + $qb = $this->entryRepository->getBuilderForAllByUser($user->getId()); + $entries = $this->rulerz->filter($qb, $rule->getRule()); + + foreach ($entries as $entry) { + foreach ($rule->getTags() as $label) { + $tag = $this->getTag($user, $label); + + $entry->addTag($tag); + $entries[] = $entry; + } + } + } + + return $entries; + } + /** * Fetch a tag for a user. * diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index 0100a62d9..cef4450d1 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml @@ -61,6 +61,14 @@ services: arguments: - @rulerz - @wallabag_core.tag_repository + - @wallabag_core.entry_repository + + wallabag_core.entry_repository: + class: Wallabag\CoreBundle\Repository\EntryRepository + factory_service: doctrine.orm.default_entity_manager + factory_method: getRepository + arguments: + - WallabagCoreBundle:Entry wallabag_core.tag_repository: class: Wallabag\CoreBundle\Repository\TagRepository diff --git a/src/Wallabag/CoreBundle/Tests/Helper/RuleBasedTaggerTest.php b/src/Wallabag/CoreBundle/Tests/Helper/RuleBasedTaggerTest.php index 56a1ed61e..5180f7ddb 100644 --- a/src/Wallabag/CoreBundle/Tests/Helper/RuleBasedTaggerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Helper/RuleBasedTaggerTest.php @@ -12,15 +12,17 @@ use Wallabag\CoreBundle\Helper\RuleBasedTagger; class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase { private $rulerz; - private $repository; + private $tagRepository; + private $entryRepository; private $tagger; public function setUp() { - $this->rulerz = $this->getRulerZMock(); - $this->repository = $this->getTagRepositoryMock(); + $this->rulerz = $this->getRulerZMock(); + $this->tagRepository = $this->getTagRepositoryMock(); + $this->entryRepository = $this->getEntryRepositoryMock(); - $this->tagger = new RuleBasedTagger($this->rulerz, $this->repository); + $this->tagger = new RuleBasedTagger($this->rulerz, $this->tagRepository, $this->entryRepository); } public function testTagWithNoRule() @@ -106,7 +108,7 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase ->with($entry, 'rule as string') ->willReturn(true); - $this->repository + $this->tagRepository ->expects($this->once()) ->method('findOneByLabelAndUserId') ->willReturn($tag); @@ -155,4 +157,11 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); } + + private function getEntryRepositoryMock() + { + return $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') + ->disableOriginalConstructor() + ->getMock(); + } } diff --git a/src/Wallabag/UserBundle/Repository/UserRepository.php b/src/Wallabag/UserBundle/Repository/UserRepository.php index c020f3ca9..009c4881d 100644 --- a/src/Wallabag/UserBundle/Repository/UserRepository.php +++ b/src/Wallabag/UserBundle/Repository/UserRepository.php @@ -23,4 +23,19 @@ class UserRepository extends EntityRepository ->getQuery() ->getOneOrNullResult(); } + + /** + * Find a user by its username. + * + * @param string $username + * + * @return User + */ + public function findOneByUserName($username) + { + return $this->createQueryBuilder('u') + ->andWhere('u.username = :username')->setParameter('username', $username) + ->getQuery() + ->getSingleResult(); + } }