]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
Add a command to automatically tag all entries for a user
authorKévin Gomez <contact@kevingomez.fr>
Sat, 24 Oct 2015 13:11:06 +0000 (15:11 +0200)
committerKévin Gomez <contact@kevingomez.fr>
Wed, 11 Nov 2015 15:27:19 +0000 (16:27 +0100)
app/config/config.yml
composer.json
composer.lock
src/Wallabag/CoreBundle/Command/TagAllCommand.php [new file with mode: 0644]
src/Wallabag/CoreBundle/Entity/Entry.php
src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php
src/Wallabag/CoreBundle/Resources/config/services.yml
src/Wallabag/CoreBundle/Tests/Helper/RuleBasedTaggerTest.php
src/Wallabag/UserBundle/Repository/UserRepository.php

index 285fbd7cf10f96a06d5b622923ebfe6b4c7bd499..82c5e7c997c1a2225139c917ca21b254e03fc189 100644 (file)
@@ -189,3 +189,7 @@ scheb_two_factor:
         sender_email: %twofactor_sender%
         digits: 6
         template: WallabagUserBundle:Authentication:form.html.twig
+
+kphoen_rulerz:
+    executors:
+        doctrine: true
index a9c734ab590a5b3dea4f0ccf2b63cbe747f6b1b0..bf40e471d591e093671ec65be6a930281a2f9f0e 100644 (file)
@@ -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",
index b88c56e86a1961beada033ac716191554919c1cb..c470656ad5fb45ed28776cedfee338ba7c03a26c 100644 (file)
@@ -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 (file)
index 0000000..2cf3f80
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+
+namespace Wallabag\CoreBundle\Command;
+
+use Doctrine\ORM\NoResultException;
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class TagAllCommand extends ContainerAwareCommand
+{
+    protected function configure()
+    {
+        $this
+            ->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('<error>User %s not found.</error>', $input->getArgument('username')));
+
+            return 1;
+        }
+        $tagger = $this->getContainer()->get('wallabag_core.rule_based_tagger');
+
+        $output->write(sprintf('Tagging entries for user « <info>%s</info> »... ', $user->getUserName()));
+
+        $entries = $tagger->tagAllForUser($user);
+
+        $em = $this->getDoctrine()->getManager();
+        foreach ($entries as $entry) {
+            $em->persist($entry);
+        }
+        $em->flush();
+
+        $output->writeln('<info>Done.</info>');
+    }
+
+    /**
+     * 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');
+    }
+}
index 5aa582f8d434a1c4638ca3127a41d9efe5501cfb..608ed2f0d4ababf41230640cfb45804b137cf687 100644 (file)
@@ -458,6 +458,10 @@ class Entry
      */
     public function addTag(Tag $tag)
     {
+        if ($this->tags->contains($tag)) {
+            return;
+        }
+
         $this->tags[] = $tag;
         $tag->addEntry($this);
     }
index bb93377970b7ca6187ad4d9326b0f715a09562f6..3f9953c0995b8422de0cd78b0e5b39f82a28af8e 100644 (file)
@@ -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<Entry> 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.
      *
index 0100a62d967486955769f0d2f9a05236e7321cb8..cef4450d1370157e37a7862d28705cfc6e7cb385 100644 (file)
@@ -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
index 56a1ed61e50762743e9146562f10acffc1794d8b..5180f7ddb387b680279bf5267aa43a95bbf3718a 100644 (file)
@@ -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();
+    }
 }
index c020f3ca9478a6418ec1e4bc6732610a5999fe7b..009c4881d0ea8945379e159894f00b4ca51a1f2d 100644 (file)
@@ -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();
+    }
 }