Add a command to automatically tag all entries for a user

This commit is contained in:
Kévin Gomez 2015-10-24 15:11:06 +02:00
parent cad8cda7af
commit 625acf3352
9 changed files with 149 additions and 11 deletions

View file

@ -189,3 +189,7 @@ scheb_two_factor:
sender_email: %twofactor_sender% sender_email: %twofactor_sender%
digits: 6 digits: 6
template: WallabagUserBundle:Authentication:form.html.twig template: WallabagUserBundle:Authentication:form.html.twig
kphoen_rulerz:
executors:
doctrine: true

View file

@ -58,7 +58,7 @@
"scheb/two-factor-bundle": "~1.4", "scheb/two-factor-bundle": "~1.4",
"grandt/phpepub": "~4.0", "grandt/phpepub": "~4.0",
"wallabag/php-mobi": "~1.0.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": { "require-dev": {
"doctrine/doctrine-fixtures-bundle": "~2.2.0", "doctrine/doctrine-fixtures-bundle": "~2.2.0",

4
composer.lock generated
View file

@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "8719c5ec3c13338ff792ce5ed8d12926", "hash": "a1f0e0b886031d96a9756de581d7d557",
"content-hash": "3f28af906ef3d4eaac41583bfcc5bd85", "content-hash": "d0a24cdd93bd431af386715f24e3e389",
"packages": [ "packages": [
{ {
"name": "doctrine/annotations", "name": "doctrine/annotations",

View file

@ -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');
}
}

View file

@ -458,6 +458,10 @@ class Entry
*/ */
public function addTag(Tag $tag) public function addTag(Tag $tag)
{ {
if ($this->tags->contains($tag)) {
return;
}
$this->tags[] = $tag; $this->tags[] = $tag;
$tag->addEntry($this); $tag->addEntry($this);
} }

View file

@ -6,6 +6,7 @@ use RulerZ\RulerZ;
use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Entity\Tag; use Wallabag\CoreBundle\Entity\Tag;
use Wallabag\CoreBundle\Repository\EntryRepository;
use Wallabag\CoreBundle\Repository\TagRepository; use Wallabag\CoreBundle\Repository\TagRepository;
use Wallabag\UserBundle\Entity\User; use Wallabag\UserBundle\Entity\User;
@ -13,11 +14,13 @@ class RuleBasedTagger
{ {
private $rulerz; private $rulerz;
private $tagRepository; private $tagRepository;
private $entryRepository;
public function __construct(RulerZ $rulerz, TagRepository $tagRepository) public function __construct(RulerZ $rulerz, TagRepository $tagRepository, EntryRepository $entryRepository)
{ {
$this->rulerz = $rulerz; $this->rulerz = $rulerz;
$this->tagRepository = $tagRepository; $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. * Fetch a tag for a user.
* *

View file

@ -61,6 +61,14 @@ services:
arguments: arguments:
- @rulerz - @rulerz
- @wallabag_core.tag_repository - @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: wallabag_core.tag_repository:
class: Wallabag\CoreBundle\Repository\TagRepository class: Wallabag\CoreBundle\Repository\TagRepository

View file

@ -12,15 +12,17 @@ use Wallabag\CoreBundle\Helper\RuleBasedTagger;
class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
{ {
private $rulerz; private $rulerz;
private $repository; private $tagRepository;
private $entryRepository;
private $tagger; private $tagger;
public function setUp() public function setUp()
{ {
$this->rulerz = $this->getRulerZMock(); $this->rulerz = $this->getRulerZMock();
$this->repository = $this->getTagRepositoryMock(); $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() public function testTagWithNoRule()
@ -106,7 +108,7 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
->with($entry, 'rule as string') ->with($entry, 'rule as string')
->willReturn(true); ->willReturn(true);
$this->repository $this->tagRepository
->expects($this->once()) ->expects($this->once())
->method('findOneByLabelAndUserId') ->method('findOneByLabelAndUserId')
->willReturn($tag); ->willReturn($tag);
@ -155,4 +157,11 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
} }
private function getEntryRepositoryMock()
{
return $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
->disableOriginalConstructor()
->getMock();
}
} }

View file

@ -23,4 +23,19 @@ class UserRepository extends EntityRepository
->getQuery() ->getQuery()
->getOneOrNullResult(); ->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();
}
} }