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();
+ }
}