aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKevin Decherf <kevin@kdecherf.com>2019-08-11 23:51:55 +0200
committerKevin Decherf <kevin@kdecherf.com>2020-04-25 15:59:23 +0200
commitf39c5a2a702036750b4d7c32d02e7f92955a4eed (patch)
tree267e1488312d8c336ef937bbe6baeddc9441f694
parent24230a5130005e274e1d8d3fe8eaca13cb978b9c (diff)
downloadwallabag-f39c5a2a702036750b4d7c32d02e7f92955a4eed.tar.gz
wallabag-f39c5a2a702036750b4d7c32d02e7f92955a4eed.tar.zst
wallabag-f39c5a2a702036750b4d7c32d02e7f92955a4eed.zip
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>
-rw-r--r--src/Wallabag/CoreBundle/Entity/IgnoreOriginInstanceRule.php3
-rw-r--r--src/Wallabag/CoreBundle/Entity/IgnoreOriginUserRule.php3
-rw-r--r--src/Wallabag/CoreBundle/Helper/RuleBasedIgnoreOriginProcessor.php50
-rw-r--r--src/Wallabag/CoreBundle/Operator/PHP/PatternMatches.php23
-rw-r--r--src/Wallabag/CoreBundle/Resources/config/services.yml13
-rw-r--r--tests/Wallabag/CoreBundle/Helper/RuleBasedIgnoreOriginProcessorTest.php212
6 files changed, 300 insertions, 4 deletions
diff --git a/src/Wallabag/CoreBundle/Entity/IgnoreOriginInstanceRule.php b/src/Wallabag/CoreBundle/Entity/IgnoreOriginInstanceRule.php
index 34aed50c..ce3b6e7d 100644
--- a/src/Wallabag/CoreBundle/Entity/IgnoreOriginInstanceRule.php
+++ b/src/Wallabag/CoreBundle/Entity/IgnoreOriginInstanceRule.php
@@ -11,7 +11,6 @@ use Symfony\Component\Validator\Constraints as Assert;
11 * 11 *
12 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\IgnoreOriginInstanceRuleRepository") 12 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\IgnoreOriginInstanceRuleRepository")
13 * @ORM\Table(name="`ignore_origin_instance_rule`") 13 * @ORM\Table(name="`ignore_origin_instance_rule`")
14 * @ORM\Entity
15 */ 14 */
16class IgnoreOriginInstanceRule implements IgnoreOriginRuleInterface, RuleInterface 15class IgnoreOriginInstanceRule implements IgnoreOriginRuleInterface, RuleInterface
17{ 16{
@@ -30,7 +29,7 @@ class IgnoreOriginInstanceRule implements IgnoreOriginRuleInterface, RuleInterfa
30 * @Assert\NotBlank() 29 * @Assert\NotBlank()
31 * @Assert\Length(max=255) 30 * @Assert\Length(max=255)
32 * @RulerZAssert\ValidRule( 31 * @RulerZAssert\ValidRule(
33 * allowed_variables={"host","pattern"}, 32 * allowed_variables={"host","_all"},
34 * allowed_operators={"=","~"} 33 * allowed_operators={"=","~"}
35 * ) 34 * )
36 * @ORM\Column(name="rule", type="string", nullable=false) 35 * @ORM\Column(name="rule", type="string", nullable=false)
diff --git a/src/Wallabag/CoreBundle/Entity/IgnoreOriginUserRule.php b/src/Wallabag/CoreBundle/Entity/IgnoreOriginUserRule.php
index befd6090..0b6f318d 100644
--- a/src/Wallabag/CoreBundle/Entity/IgnoreOriginUserRule.php
+++ b/src/Wallabag/CoreBundle/Entity/IgnoreOriginUserRule.php
@@ -11,7 +11,6 @@ use Symfony\Component\Validator\Constraints as Assert;
11 * 11 *
12 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\IgnoreOriginUserRuleRepository") 12 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\IgnoreOriginUserRuleRepository")
13 * @ORM\Table(name="`ignore_origin_user_rule`") 13 * @ORM\Table(name="`ignore_origin_user_rule`")
14 * @ORM\Entity
15 */ 14 */
16class IgnoreOriginUserRule implements IgnoreOriginRuleInterface, RuleInterface 15class IgnoreOriginUserRule implements IgnoreOriginRuleInterface, RuleInterface
17{ 16{
@@ -30,7 +29,7 @@ class IgnoreOriginUserRule implements IgnoreOriginRuleInterface, RuleInterface
30 * @Assert\NotBlank() 29 * @Assert\NotBlank()
31 * @Assert\Length(max=255) 30 * @Assert\Length(max=255)
32 * @RulerZAssert\ValidRule( 31 * @RulerZAssert\ValidRule(
33 * allowed_variables={"host","pattern"}, 32 * allowed_variables={"host","_all"},
34 * allowed_operators={"=","~"} 33 * allowed_operators={"=","~"}
35 * ) 34 * )
36 * @ORM\Column(name="rule", type="string", nullable=false) 35 * @ORM\Column(name="rule", type="string", nullable=false)
diff --git a/src/Wallabag/CoreBundle/Helper/RuleBasedIgnoreOriginProcessor.php b/src/Wallabag/CoreBundle/Helper/RuleBasedIgnoreOriginProcessor.php
new file mode 100644
index 00000000..333e5b0a
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Helper/RuleBasedIgnoreOriginProcessor.php
@@ -0,0 +1,50 @@
1<?php
2
3namespace Wallabag\CoreBundle\Helper;
4
5use Psr\Log\LoggerInterface;
6use RulerZ\RulerZ;
7use Wallabag\CoreBundle\Entity\Entry;
8use Wallabag\CoreBundle\Repository\IgnoreOriginInstanceRuleRepository;
9
10class RuleBasedIgnoreOriginProcessor
11{
12 protected $rulerz;
13 protected $logger;
14 protected $ignoreOriginInstanceRuleRepository;
15
16 public function __construct(RulerZ $rulerz, LoggerInterface $logger, IgnoreOriginInstanceRuleRepository $ignoreOriginInstanceRuleRepository)
17 {
18 $this->rulerz = $rulerz;
19 $this->logger = $logger;
20 $this->ignoreOriginInstanceRuleRepository = $ignoreOriginInstanceRuleRepository;
21 }
22
23 /**
24 * @param Entry $entry Entry to process
25 *
26 * @return bool
27 */
28 public function process(Entry $entry)
29 {
30 $url = $entry->getUrl();
31 $userRules = $entry->getUser()->getConfig()->getIgnoreOriginRules()->toArray();
32 $rules = array_merge($this->ignoreOriginInstanceRuleRepository->findAll(), $userRules);
33
34 $parsed_url = parse_url($url);
35 // We add the former url as a new key _all for pattern matching
36 $parsed_url['_all'] = $url;
37
38 foreach ($rules as $rule) {
39 if ($this->rulerz->satisfies($parsed_url, $rule->getRule())) {
40 $this->logger->info('Origin url matching ignore rule.', [
41 'rule' => $rule->getRule(),
42 ]);
43
44 return true;
45 }
46 }
47
48 return false;
49 }
50}
diff --git a/src/Wallabag/CoreBundle/Operator/PHP/PatternMatches.php b/src/Wallabag/CoreBundle/Operator/PHP/PatternMatches.php
new file mode 100644
index 00000000..532e2bb3
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Operator/PHP/PatternMatches.php
@@ -0,0 +1,23 @@
1<?php
2
3namespace Wallabag\CoreBundle\Operator\PHP;
4
5/**
6 * Provides a "~" operator used for ignore origin rules.
7 *
8 * It asserts that a subject matches a given regexp pattern, in a
9 * case-insensitive way.
10 *
11 * This operator will be used to compile ignore origin rules in PHP, usable
12 * directly on Entry objects for instance.
13 * It's registered in RulerZ using a service (wallabag.operator.array.pattern_matches);
14 */
15class PatternMatches
16{
17 public function __invoke($subject, $pattern)
18 {
19 $count = preg_match("`$pattern`i", $subject);
20
21 return \is_int($count) && $count > 0;
22 }
23}
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml
index 4ece046a..8417ac35 100644
--- a/src/Wallabag/CoreBundle/Resources/config/services.yml
+++ b/src/Wallabag/CoreBundle/Resources/config/services.yml
@@ -92,6 +92,7 @@ services:
92 arguments: 92 arguments:
93 - "@wallabag_core.graby" 93 - "@wallabag_core.graby"
94 - "@wallabag_core.rule_based_tagger" 94 - "@wallabag_core.rule_based_tagger"
95 - "@wallabag_core.rule_based_ignore_origin_processor"
95 - "@validator" 96 - "@validator"
96 - "@logger" 97 - "@logger"
97 - '%wallabag_core.fetching_error_message%' 98 - '%wallabag_core.fetching_error_message%'
@@ -110,6 +111,13 @@ services:
110 - "@wallabag_core.entry_repository" 111 - "@wallabag_core.entry_repository"
111 - "@logger" 112 - "@logger"
112 113
114 wallabag_core.rule_based_ignore_origin_processor:
115 class: Wallabag\CoreBundle\Helper\RuleBasedIgnoreOriginProcessor
116 arguments:
117 - "@rulerz"
118 - "@logger"
119 - "@wallabag_core.ignore_origin_instance_rule_repository"
120
113 # repository as a service 121 # repository as a service
114 wallabag_core.entry_repository: 122 wallabag_core.entry_repository:
115 class: Wallabag\CoreBundle\Repository\EntryRepository 123 class: Wallabag\CoreBundle\Repository\EntryRepository
@@ -164,6 +172,11 @@ services:
164 tags: 172 tags:
165 - { name: rulerz.operator, target: doctrine, operator: notmatches, inline: true } 173 - { name: rulerz.operator, target: doctrine, operator: notmatches, inline: true }
166 174
175 wallabag.operator.array.pattern_matches:
176 class: Wallabag\CoreBundle\Operator\PHP\PatternMatches
177 tags:
178 - { name: rulerz.operator, target: native, operator: "~" }
179
167 wallabag_core.helper.redirect: 180 wallabag_core.helper.redirect:
168 class: Wallabag\CoreBundle\Helper\Redirect 181 class: Wallabag\CoreBundle\Helper\Redirect
169 arguments: 182 arguments:
diff --git a/tests/Wallabag/CoreBundle/Helper/RuleBasedIgnoreOriginProcessorTest.php b/tests/Wallabag/CoreBundle/Helper/RuleBasedIgnoreOriginProcessorTest.php
new file mode 100644
index 00000000..9e39bc81
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/Helper/RuleBasedIgnoreOriginProcessorTest.php
@@ -0,0 +1,212 @@
1<?php
2
3namespace Tests\Wallabag\CoreBundle\Helper;
4
5use Monolog\Handler\TestHandler;
6use Monolog\Logger;
7use PHPUnit\Framework\TestCase;
8use Wallabag\CoreBundle\Entity\Config;
9use Wallabag\CoreBundle\Entity\Entry;
10use Wallabag\CoreBundle\Entity\IgnoreOriginInstanceRule;
11use Wallabag\CoreBundle\Entity\IgnoreOriginUserRule;
12use Wallabag\CoreBundle\Helper\RuleBasedIgnoreOriginProcessor;
13use Wallabag\UserBundle\Entity\User;
14
15class RuleBasedIgnoreOriginProcessorTest extends TestCase
16{
17 private $rulerz;
18 private $processor;
19 private $ignoreOriginInstanceRuleRepository;
20 private $logger;
21 private $handler;
22
23 public function setUp()
24 {
25 $this->rulerz = $this->getRulerZMock();
26 $this->logger = $this->getLogger();
27 $this->ignoreOriginInstanceRuleRepository = $this->getIgnoreOriginInstanceRuleRepositoryMock();
28 $this->handler = new TestHandler();
29 $this->logger->pushHandler($this->handler);
30
31 $this->processor = new RuleBasedIgnoreOriginProcessor($this->rulerz, $this->logger, $this->ignoreOriginInstanceRuleRepository);
32 }
33
34 public function testProcessWithNoRule()
35 {
36 $user = $this->getUser();
37 $entry = new Entry($user);
38 $entry->setUrl('http://example.com/hello-world');
39
40 $this->ignoreOriginInstanceRuleRepository
41 ->expects($this->once())
42 ->method('findAll')
43 ->willReturn([]);
44
45 $this->rulerz
46 ->expects($this->never())
47 ->method('satisfies');
48
49 $result = $this->processor->process($entry);
50
51 $this->assertFalse($result);
52 }
53
54 public function testProcessWithNoMatchingRule()
55 {
56 $userRule = $this->getIgnoreOriginUserRule('rule as string');
57 $user = $this->getUser([$userRule]);
58 $entry = new Entry($user);
59 $entry->setUrl('http://example.com/hello-world');
60
61 $this->ignoreOriginInstanceRuleRepository
62 ->expects($this->once())
63 ->method('findAll')
64 ->willReturn([]);
65
66 $this->rulerz
67 ->expects($this->once())
68 ->method('satisfies')
69 ->willReturn(false);
70
71 $result = $this->processor->process($entry);
72
73 $this->assertFalse($result);
74 }
75
76 public function testProcessWithAMatchingRule()
77 {
78 $userRule = $this->getIgnoreOriginUserRule('rule as string');
79 $user = $this->getUser([$userRule]);
80 $entry = new Entry($user);
81 $entry->setUrl('http://example.com/hello-world');
82
83 $this->ignoreOriginInstanceRuleRepository
84 ->expects($this->once())
85 ->method('findAll')
86 ->willReturn([]);
87
88 $this->rulerz
89 ->expects($this->once())
90 ->method('satisfies')
91 ->willReturn(true);
92
93 $result = $this->processor->process($entry);
94
95 $this->assertTrue($result);
96 }
97
98 public function testProcessWithAMixOfMatchingRules()
99 {
100 $userRule = $this->getIgnoreOriginUserRule('rule as string');
101 $anotherUserRule = $this->getIgnoreOriginUserRule('another rule as string');
102 $user = $this->getUser([$userRule, $anotherUserRule]);
103 $entry = new Entry($user);
104 $entry->setUrl('http://example.com/hello-world');
105
106 $this->ignoreOriginInstanceRuleRepository
107 ->expects($this->once())
108 ->method('findAll')
109 ->willReturn([]);
110
111 $this->rulerz
112 ->method('satisfies')
113 ->will($this->onConsecutiveCalls(false, true));
114
115 $result = $this->processor->process($entry);
116
117 $this->assertTrue($result);
118 }
119
120 public function testProcessWithInstanceRules()
121 {
122 $user = $this->getUser();
123 $entry = new Entry($user);
124 $entry->setUrl('http://example.com/hello-world');
125
126 $instanceRule = $this->getIgnoreOriginInstanceRule('rule as string');
127 $this->ignoreOriginInstanceRuleRepository
128 ->expects($this->once())
129 ->method('findAll')
130 ->willReturn([$instanceRule]);
131
132 $this->rulerz
133 ->expects($this->once())
134 ->method('satisfies')
135 ->willReturn(true);
136
137 $result = $this->processor->process($entry);
138
139 $this->assertTrue($result);
140 }
141
142 public function testProcessWithMixedRules()
143 {
144 $userRule = $this->getIgnoreOriginUserRule('rule as string');
145 $user = $this->getUser([$userRule]);
146 $entry = new Entry($user);
147 $entry->setUrl('http://example.com/hello-world');
148
149 $instanceRule = $this->getIgnoreOriginInstanceRule('rule as string');
150 $this->ignoreOriginInstanceRuleRepository
151 ->expects($this->once())
152 ->method('findAll')
153 ->willReturn([$instanceRule]);
154
155 $this->rulerz
156 ->method('satisfies')
157 ->will($this->onConsecutiveCalls(false, true));
158
159 $result = $this->processor->process($entry);
160
161 $this->assertTrue($result);
162 }
163
164 private function getUser(array $ignoreOriginRules = [])
165 {
166 $user = new User();
167 $config = new Config($user);
168
169 $user->setConfig($config);
170
171 foreach ($ignoreOriginRules as $rule) {
172 $config->addIgnoreOriginRule($rule);
173 }
174
175 return $user;
176 }
177
178 private function getIgnoreOriginUserRule($rule)
179 {
180 $ignoreOriginUserRule = new IgnoreOriginUserRule();
181 $ignoreOriginUserRule->setRule($rule);
182
183 return $ignoreOriginUserRule;
184 }
185
186 private function getIgnoreOriginInstanceRule($rule)
187 {
188 $ignoreOriginInstanceRule = new IgnoreOriginInstanceRule();
189 $ignoreOriginInstanceRule->setRule($rule);
190
191 return $ignoreOriginInstanceRule;
192 }
193
194 private function getRulerZMock()
195 {
196 return $this->getMockBuilder('RulerZ\RulerZ')
197 ->disableOriginalConstructor()
198 ->getMock();
199 }
200
201 private function getIgnoreOriginInstanceRuleRepositoryMock()
202 {
203 return $this->getMockBuilder('Wallabag\CoreBundle\Repository\IgnoreOriginInstanceRuleRepository')
204 ->disableOriginalConstructor()
205 ->getMock();
206 }
207
208 private function getLogger()
209 {
210 return new Logger('foo');
211 }
212}