mirror of
https://github.com/wallabag/wallabag.git
synced 2025-09-15 18:57:05 +00:00
Add new Helper to process Ignore Origin rules and RulerZ operator
This commits adds a new helper like RuleBasedTagger for processing ignore origin rules. It also adds a new custom RulerZ operator for the '~' pattern matching rule. Renames 'pattern' with '_all' in IgnoreOriginRule entity. Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
This commit is contained in:
parent
24230a5130
commit
f39c5a2a70
6 changed files with 300 additions and 4 deletions
|
@ -11,7 +11,6 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||||
*
|
*
|
||||||
* @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\IgnoreOriginInstanceRuleRepository")
|
* @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\IgnoreOriginInstanceRuleRepository")
|
||||||
* @ORM\Table(name="`ignore_origin_instance_rule`")
|
* @ORM\Table(name="`ignore_origin_instance_rule`")
|
||||||
* @ORM\Entity
|
|
||||||
*/
|
*/
|
||||||
class IgnoreOriginInstanceRule implements IgnoreOriginRuleInterface, RuleInterface
|
class IgnoreOriginInstanceRule implements IgnoreOriginRuleInterface, RuleInterface
|
||||||
{
|
{
|
||||||
|
@ -30,7 +29,7 @@ class IgnoreOriginInstanceRule implements IgnoreOriginRuleInterface, RuleInterfa
|
||||||
* @Assert\NotBlank()
|
* @Assert\NotBlank()
|
||||||
* @Assert\Length(max=255)
|
* @Assert\Length(max=255)
|
||||||
* @RulerZAssert\ValidRule(
|
* @RulerZAssert\ValidRule(
|
||||||
* allowed_variables={"host","pattern"},
|
* allowed_variables={"host","_all"},
|
||||||
* allowed_operators={"=","~"}
|
* allowed_operators={"=","~"}
|
||||||
* )
|
* )
|
||||||
* @ORM\Column(name="rule", type="string", nullable=false)
|
* @ORM\Column(name="rule", type="string", nullable=false)
|
||||||
|
|
|
@ -11,7 +11,6 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||||
*
|
*
|
||||||
* @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\IgnoreOriginUserRuleRepository")
|
* @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\IgnoreOriginUserRuleRepository")
|
||||||
* @ORM\Table(name="`ignore_origin_user_rule`")
|
* @ORM\Table(name="`ignore_origin_user_rule`")
|
||||||
* @ORM\Entity
|
|
||||||
*/
|
*/
|
||||||
class IgnoreOriginUserRule implements IgnoreOriginRuleInterface, RuleInterface
|
class IgnoreOriginUserRule implements IgnoreOriginRuleInterface, RuleInterface
|
||||||
{
|
{
|
||||||
|
@ -30,7 +29,7 @@ class IgnoreOriginUserRule implements IgnoreOriginRuleInterface, RuleInterface
|
||||||
* @Assert\NotBlank()
|
* @Assert\NotBlank()
|
||||||
* @Assert\Length(max=255)
|
* @Assert\Length(max=255)
|
||||||
* @RulerZAssert\ValidRule(
|
* @RulerZAssert\ValidRule(
|
||||||
* allowed_variables={"host","pattern"},
|
* allowed_variables={"host","_all"},
|
||||||
* allowed_operators={"=","~"}
|
* allowed_operators={"=","~"}
|
||||||
* )
|
* )
|
||||||
* @ORM\Column(name="rule", type="string", nullable=false)
|
* @ORM\Column(name="rule", type="string", nullable=false)
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CoreBundle\Helper;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use RulerZ\RulerZ;
|
||||||
|
use Wallabag\CoreBundle\Entity\Entry;
|
||||||
|
use Wallabag\CoreBundle\Repository\IgnoreOriginInstanceRuleRepository;
|
||||||
|
|
||||||
|
class RuleBasedIgnoreOriginProcessor
|
||||||
|
{
|
||||||
|
protected $rulerz;
|
||||||
|
protected $logger;
|
||||||
|
protected $ignoreOriginInstanceRuleRepository;
|
||||||
|
|
||||||
|
public function __construct(RulerZ $rulerz, LoggerInterface $logger, IgnoreOriginInstanceRuleRepository $ignoreOriginInstanceRuleRepository)
|
||||||
|
{
|
||||||
|
$this->rulerz = $rulerz;
|
||||||
|
$this->logger = $logger;
|
||||||
|
$this->ignoreOriginInstanceRuleRepository = $ignoreOriginInstanceRuleRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Entry $entry Entry to process
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function process(Entry $entry)
|
||||||
|
{
|
||||||
|
$url = $entry->getUrl();
|
||||||
|
$userRules = $entry->getUser()->getConfig()->getIgnoreOriginRules()->toArray();
|
||||||
|
$rules = array_merge($this->ignoreOriginInstanceRuleRepository->findAll(), $userRules);
|
||||||
|
|
||||||
|
$parsed_url = parse_url($url);
|
||||||
|
// We add the former url as a new key _all for pattern matching
|
||||||
|
$parsed_url['_all'] = $url;
|
||||||
|
|
||||||
|
foreach ($rules as $rule) {
|
||||||
|
if ($this->rulerz->satisfies($parsed_url, $rule->getRule())) {
|
||||||
|
$this->logger->info('Origin url matching ignore rule.', [
|
||||||
|
'rule' => $rule->getRule(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
23
src/Wallabag/CoreBundle/Operator/PHP/PatternMatches.php
Normal file
23
src/Wallabag/CoreBundle/Operator/PHP/PatternMatches.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CoreBundle\Operator\PHP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a "~" operator used for ignore origin rules.
|
||||||
|
*
|
||||||
|
* It asserts that a subject matches a given regexp pattern, in a
|
||||||
|
* case-insensitive way.
|
||||||
|
*
|
||||||
|
* This operator will be used to compile ignore origin rules in PHP, usable
|
||||||
|
* directly on Entry objects for instance.
|
||||||
|
* It's registered in RulerZ using a service (wallabag.operator.array.pattern_matches);
|
||||||
|
*/
|
||||||
|
class PatternMatches
|
||||||
|
{
|
||||||
|
public function __invoke($subject, $pattern)
|
||||||
|
{
|
||||||
|
$count = preg_match("`$pattern`i", $subject);
|
||||||
|
|
||||||
|
return \is_int($count) && $count > 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -92,6 +92,7 @@ services:
|
||||||
arguments:
|
arguments:
|
||||||
- "@wallabag_core.graby"
|
- "@wallabag_core.graby"
|
||||||
- "@wallabag_core.rule_based_tagger"
|
- "@wallabag_core.rule_based_tagger"
|
||||||
|
- "@wallabag_core.rule_based_ignore_origin_processor"
|
||||||
- "@validator"
|
- "@validator"
|
||||||
- "@logger"
|
- "@logger"
|
||||||
- '%wallabag_core.fetching_error_message%'
|
- '%wallabag_core.fetching_error_message%'
|
||||||
|
@ -110,6 +111,13 @@ services:
|
||||||
- "@wallabag_core.entry_repository"
|
- "@wallabag_core.entry_repository"
|
||||||
- "@logger"
|
- "@logger"
|
||||||
|
|
||||||
|
wallabag_core.rule_based_ignore_origin_processor:
|
||||||
|
class: Wallabag\CoreBundle\Helper\RuleBasedIgnoreOriginProcessor
|
||||||
|
arguments:
|
||||||
|
- "@rulerz"
|
||||||
|
- "@logger"
|
||||||
|
- "@wallabag_core.ignore_origin_instance_rule_repository"
|
||||||
|
|
||||||
# repository as a service
|
# repository as a service
|
||||||
wallabag_core.entry_repository:
|
wallabag_core.entry_repository:
|
||||||
class: Wallabag\CoreBundle\Repository\EntryRepository
|
class: Wallabag\CoreBundle\Repository\EntryRepository
|
||||||
|
@ -164,6 +172,11 @@ services:
|
||||||
tags:
|
tags:
|
||||||
- { name: rulerz.operator, target: doctrine, operator: notmatches, inline: true }
|
- { name: rulerz.operator, target: doctrine, operator: notmatches, inline: true }
|
||||||
|
|
||||||
|
wallabag.operator.array.pattern_matches:
|
||||||
|
class: Wallabag\CoreBundle\Operator\PHP\PatternMatches
|
||||||
|
tags:
|
||||||
|
- { name: rulerz.operator, target: native, operator: "~" }
|
||||||
|
|
||||||
wallabag_core.helper.redirect:
|
wallabag_core.helper.redirect:
|
||||||
class: Wallabag\CoreBundle\Helper\Redirect
|
class: Wallabag\CoreBundle\Helper\Redirect
|
||||||
arguments:
|
arguments:
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Wallabag\CoreBundle\Helper;
|
||||||
|
|
||||||
|
use Monolog\Handler\TestHandler;
|
||||||
|
use Monolog\Logger;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Wallabag\CoreBundle\Entity\Config;
|
||||||
|
use Wallabag\CoreBundle\Entity\Entry;
|
||||||
|
use Wallabag\CoreBundle\Entity\IgnoreOriginInstanceRule;
|
||||||
|
use Wallabag\CoreBundle\Entity\IgnoreOriginUserRule;
|
||||||
|
use Wallabag\CoreBundle\Helper\RuleBasedIgnoreOriginProcessor;
|
||||||
|
use Wallabag\UserBundle\Entity\User;
|
||||||
|
|
||||||
|
class RuleBasedIgnoreOriginProcessorTest extends TestCase
|
||||||
|
{
|
||||||
|
private $rulerz;
|
||||||
|
private $processor;
|
||||||
|
private $ignoreOriginInstanceRuleRepository;
|
||||||
|
private $logger;
|
||||||
|
private $handler;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->rulerz = $this->getRulerZMock();
|
||||||
|
$this->logger = $this->getLogger();
|
||||||
|
$this->ignoreOriginInstanceRuleRepository = $this->getIgnoreOriginInstanceRuleRepositoryMock();
|
||||||
|
$this->handler = new TestHandler();
|
||||||
|
$this->logger->pushHandler($this->handler);
|
||||||
|
|
||||||
|
$this->processor = new RuleBasedIgnoreOriginProcessor($this->rulerz, $this->logger, $this->ignoreOriginInstanceRuleRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessWithNoRule()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
$entry = new Entry($user);
|
||||||
|
$entry->setUrl('http://example.com/hello-world');
|
||||||
|
|
||||||
|
$this->ignoreOriginInstanceRuleRepository
|
||||||
|
->expects($this->once())
|
||||||
|
->method('findAll')
|
||||||
|
->willReturn([]);
|
||||||
|
|
||||||
|
$this->rulerz
|
||||||
|
->expects($this->never())
|
||||||
|
->method('satisfies');
|
||||||
|
|
||||||
|
$result = $this->processor->process($entry);
|
||||||
|
|
||||||
|
$this->assertFalse($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessWithNoMatchingRule()
|
||||||
|
{
|
||||||
|
$userRule = $this->getIgnoreOriginUserRule('rule as string');
|
||||||
|
$user = $this->getUser([$userRule]);
|
||||||
|
$entry = new Entry($user);
|
||||||
|
$entry->setUrl('http://example.com/hello-world');
|
||||||
|
|
||||||
|
$this->ignoreOriginInstanceRuleRepository
|
||||||
|
->expects($this->once())
|
||||||
|
->method('findAll')
|
||||||
|
->willReturn([]);
|
||||||
|
|
||||||
|
$this->rulerz
|
||||||
|
->expects($this->once())
|
||||||
|
->method('satisfies')
|
||||||
|
->willReturn(false);
|
||||||
|
|
||||||
|
$result = $this->processor->process($entry);
|
||||||
|
|
||||||
|
$this->assertFalse($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessWithAMatchingRule()
|
||||||
|
{
|
||||||
|
$userRule = $this->getIgnoreOriginUserRule('rule as string');
|
||||||
|
$user = $this->getUser([$userRule]);
|
||||||
|
$entry = new Entry($user);
|
||||||
|
$entry->setUrl('http://example.com/hello-world');
|
||||||
|
|
||||||
|
$this->ignoreOriginInstanceRuleRepository
|
||||||
|
->expects($this->once())
|
||||||
|
->method('findAll')
|
||||||
|
->willReturn([]);
|
||||||
|
|
||||||
|
$this->rulerz
|
||||||
|
->expects($this->once())
|
||||||
|
->method('satisfies')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
|
$result = $this->processor->process($entry);
|
||||||
|
|
||||||
|
$this->assertTrue($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessWithAMixOfMatchingRules()
|
||||||
|
{
|
||||||
|
$userRule = $this->getIgnoreOriginUserRule('rule as string');
|
||||||
|
$anotherUserRule = $this->getIgnoreOriginUserRule('another rule as string');
|
||||||
|
$user = $this->getUser([$userRule, $anotherUserRule]);
|
||||||
|
$entry = new Entry($user);
|
||||||
|
$entry->setUrl('http://example.com/hello-world');
|
||||||
|
|
||||||
|
$this->ignoreOriginInstanceRuleRepository
|
||||||
|
->expects($this->once())
|
||||||
|
->method('findAll')
|
||||||
|
->willReturn([]);
|
||||||
|
|
||||||
|
$this->rulerz
|
||||||
|
->method('satisfies')
|
||||||
|
->will($this->onConsecutiveCalls(false, true));
|
||||||
|
|
||||||
|
$result = $this->processor->process($entry);
|
||||||
|
|
||||||
|
$this->assertTrue($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessWithInstanceRules()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
$entry = new Entry($user);
|
||||||
|
$entry->setUrl('http://example.com/hello-world');
|
||||||
|
|
||||||
|
$instanceRule = $this->getIgnoreOriginInstanceRule('rule as string');
|
||||||
|
$this->ignoreOriginInstanceRuleRepository
|
||||||
|
->expects($this->once())
|
||||||
|
->method('findAll')
|
||||||
|
->willReturn([$instanceRule]);
|
||||||
|
|
||||||
|
$this->rulerz
|
||||||
|
->expects($this->once())
|
||||||
|
->method('satisfies')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
|
$result = $this->processor->process($entry);
|
||||||
|
|
||||||
|
$this->assertTrue($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessWithMixedRules()
|
||||||
|
{
|
||||||
|
$userRule = $this->getIgnoreOriginUserRule('rule as string');
|
||||||
|
$user = $this->getUser([$userRule]);
|
||||||
|
$entry = new Entry($user);
|
||||||
|
$entry->setUrl('http://example.com/hello-world');
|
||||||
|
|
||||||
|
$instanceRule = $this->getIgnoreOriginInstanceRule('rule as string');
|
||||||
|
$this->ignoreOriginInstanceRuleRepository
|
||||||
|
->expects($this->once())
|
||||||
|
->method('findAll')
|
||||||
|
->willReturn([$instanceRule]);
|
||||||
|
|
||||||
|
$this->rulerz
|
||||||
|
->method('satisfies')
|
||||||
|
->will($this->onConsecutiveCalls(false, true));
|
||||||
|
|
||||||
|
$result = $this->processor->process($entry);
|
||||||
|
|
||||||
|
$this->assertTrue($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUser(array $ignoreOriginRules = [])
|
||||||
|
{
|
||||||
|
$user = new User();
|
||||||
|
$config = new Config($user);
|
||||||
|
|
||||||
|
$user->setConfig($config);
|
||||||
|
|
||||||
|
foreach ($ignoreOriginRules as $rule) {
|
||||||
|
$config->addIgnoreOriginRule($rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getIgnoreOriginUserRule($rule)
|
||||||
|
{
|
||||||
|
$ignoreOriginUserRule = new IgnoreOriginUserRule();
|
||||||
|
$ignoreOriginUserRule->setRule($rule);
|
||||||
|
|
||||||
|
return $ignoreOriginUserRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getIgnoreOriginInstanceRule($rule)
|
||||||
|
{
|
||||||
|
$ignoreOriginInstanceRule = new IgnoreOriginInstanceRule();
|
||||||
|
$ignoreOriginInstanceRule->setRule($rule);
|
||||||
|
|
||||||
|
return $ignoreOriginInstanceRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getRulerZMock()
|
||||||
|
{
|
||||||
|
return $this->getMockBuilder('RulerZ\RulerZ')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getIgnoreOriginInstanceRuleRepositoryMock()
|
||||||
|
{
|
||||||
|
return $this->getMockBuilder('Wallabag\CoreBundle\Repository\IgnoreOriginInstanceRuleRepository')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getLogger()
|
||||||
|
{
|
||||||
|
return new Logger('foo');
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue