aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNicolas Lœuillet <nicolas@loeuillet.org>2017-04-20 14:58:20 +0200
committerNicolas Lœuillet <nicolas@loeuillet.org>2017-04-20 15:17:02 +0200
commitfdd725f58cfe96d9bb9454d0347f6ff847fce69d (patch)
tree7f70e8d3b766d8a8ffc7cd807ca7a2a16d5f2bda
parent64f1d8f77a75332b731124c5ebab4bed7a512081 (diff)
downloadwallabag-fdd725f58cfe96d9bb9454d0347f6ff847fce69d.tar.gz
wallabag-fdd725f58cfe96d9bb9454d0347f6ff847fce69d.tar.zst
wallabag-fdd725f58cfe96d9bb9454d0347f6ff847fce69d.zip
Added notmatches operator for tagging rule
-rw-r--r--docs/de/user/configuration.rst27
-rw-r--r--docs/en/user/configuration.rst27
-rw-r--r--docs/fr/user/configuration.rst1
-rw-r--r--src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTaggingRuleData.php7
-rw-r--r--src/Wallabag/CoreBundle/Entity/TaggingRule.php4
-rw-r--r--src/Wallabag/CoreBundle/Operator/Doctrine/NotMatches.php25
-rw-r--r--src/Wallabag/CoreBundle/Operator/PHP/NotMatches.php21
-rw-r--r--src/Wallabag/CoreBundle/Resources/config/services.yml10
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.da.yml2
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.de.yml1
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.en.yml1
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.es.yml1
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml1
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml1
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.it.yml1
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml1
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml1
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml1
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml1
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml1
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig4
-rw-r--r--tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php4
-rw-r--r--tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php6
-rw-r--r--tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php2
-rw-r--r--tests/Wallabag/CoreBundle/Controller/TagControllerTest.php6
-rw-r--r--tests/Wallabag/ImportBundle/Controller/ChromeControllerTest.php2
-rw-r--r--tests/Wallabag/ImportBundle/Controller/FirefoxControllerTest.php2
-rw-r--r--tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php2
-rw-r--r--tests/Wallabag/ImportBundle/Controller/PinboardControllerTest.php2
-rw-r--r--tests/Wallabag/ImportBundle/Controller/ReadabilityControllerTest.php2
-rw-r--r--tests/Wallabag/ImportBundle/Controller/WallabagV1ControllerTest.php2
-rw-r--r--tests/Wallabag/ImportBundle/Controller/WallabagV2ControllerTest.php4
32 files changed, 125 insertions, 48 deletions
diff --git a/docs/de/user/configuration.rst b/docs/de/user/configuration.rst
index c0c04bde..06cae7cb 100644
--- a/docs/de/user/configuration.rst
+++ b/docs/de/user/configuration.rst
@@ -115,16 +115,17 @@ Welche Variablen und Operatoren kann ich zum Regeln schreiben nutzen?
115 115
116Die folgenden Variablen und Operatoren können genutzt werden, um Tagging-Regeln zu erstellen (sei vorsichtig, denn bei einigen Werten musst du Anführungszeichen hinzufügen, z.B. ``language = "de"``): 116Die folgenden Variablen und Operatoren können genutzt werden, um Tagging-Regeln zu erstellen (sei vorsichtig, denn bei einigen Werten musst du Anführungszeichen hinzufügen, z.B. ``language = "de"``):
117 117
118=========== ============================================== ======== ========== 118=========== ============================================== ========== ==========
119Variable Bedeutung Operator Bedeutung 119Variable Bedeutung Operator Bedeutung
120----------- ---------------------------------------------- -------- ---------- 120----------- ---------------------------------------------- ---------- ----------
121title Titel des Artikels <= Kleiner gleich als… 121title Titel des Artikels <= Kleiner gleich als…
122url URL des Artikels < Kleiner als… 122url URL des Artikels < Kleiner als…
123isArchived Ob der Artikel archiviert ist oder nicht => Größer gleich als… 123isArchived Ob der Artikel archiviert ist oder nicht => Größer gleich als…
124isStarred Ob der Artikel favorisiert ist oder nicht > Größer als… 124isStarred Ob der Artikel favorisiert ist oder nicht > Größer als…
125content Inhalt des Eintrags = Gleich zu… 125content Inhalt des Eintrags = Gleich zu…
126language Sprache des Eintrags != Nicht gleich zu… 126language Sprache des Eintrags != Nicht gleich zu…
127mimetype MIME-Typ des Eintrags OR Eine Regel oder die andere 127mimetype MIME-Typ des Eintrags OR Eine Regel oder die andere
128readingTime Die geschätzte Lesezeit in Minuten AND Eine Regel und die andere 128readingTime Die geschätzte Lesezeit in Minuten AND Eine Regel und die andere
129domainName Der Domain-Name des Eintrags matches Testet, dass ein Feld einer Suche (unabhängig von Groß- und Kleinschreibung) übereinstimmt. Z.B.: title matches "Fußball" 129domainName Der Domain-Name des Eintrags matches Testet, dass ein Feld einer Suche (unabhängig von Groß- und Kleinschreibung) übereinstimmt. Z.B.: title matches "Fußball"
130=========== ============================================== ======== ========== 130 notmatches
131=========== ============================================== ========== ==========
diff --git a/docs/en/user/configuration.rst b/docs/en/user/configuration.rst
index bba12cb9..0f3ac38f 100644
--- a/docs/en/user/configuration.rst
+++ b/docs/en/user/configuration.rst
@@ -116,16 +116,17 @@ Which variables and operators can I use to write rules?
116 116
117The following variables and operators can be used to create tagging rules (be careful, for some values, you need to add quotes, for example ``language = "en"``): 117The following variables and operators can be used to create tagging rules (be careful, for some values, you need to add quotes, for example ``language = "en"``):
118 118
119=========== ============================================== ======== ========== 119=========== ============================================== ========== ==========
120Variable Meaning Operator Meaning 120Variable Meaning Operator Meaning
121----------- ---------------------------------------------- -------- ---------- 121----------- ---------------------------------------------- ---------- ----------
122title Title of the entry <= Less than… 122title Title of the entry <= Less than…
123url URL of the entry < Strictly less than… 123url URL of the entry < Strictly less than…
124isArchived Whether the entry is archived or not => Greater than… 124isArchived Whether the entry is archived or not => Greater than…
125isStarred Whether the entry is starred or not > Strictly greater than… 125isStarred Whether the entry is starred or not > Strictly greater than…
126content The entry's content = Equal to… 126content The entry's content = Equal to…
127language The entry's language != Not equal to… 127language The entry's language != Not equal to…
128mimetype The entry's mime-type OR One rule or another 128mimetype The entry's mime-type OR One rule or another
129readingTime The estimated entry's reading time, in minutes AND One rule and another 129readingTime The estimated entry's reading time, in minutes AND One rule and another
130domainName The domain name of the entry matches Tests that a subject is matches a search (case-insensitive). Example: title matches "football" 130domainName The domain name of the entry matches Tests that a subject is matches a search (case-insensitive). Example: title matches "football"
131=========== ============================================== ======== ========== 131 notmatches Tests that a subject is not matches a search (case-insensitive). Example: title notmatches "football"
132=========== ============================================== ========== ==========
diff --git a/docs/fr/user/configuration.rst b/docs/fr/user/configuration.rst
index 772000c3..0f5d4375 100644
--- a/docs/fr/user/configuration.rst
+++ b/docs/fr/user/configuration.rst
@@ -130,4 +130,5 @@ language La langue de l'article != Différ
130mimetype The type MIME de l'article OR Telle règle ou telle autre règle 130mimetype The type MIME de l'article OR Telle règle ou telle autre règle
131readingTime Le temps de lecture de l'article, en minutes AND Telle règle et telle règle 131readingTime Le temps de lecture de l'article, en minutes AND Telle règle et telle règle
132domainName Le nom de domaine de l'article matches Contient telle chaîne de caractère (insensible à la casse). Exemple : title matches "football" 132domainName Le nom de domaine de l'article matches Contient telle chaîne de caractère (insensible à la casse). Exemple : title matches "football"
133 notmaches Ne contient pas telle chaîne de caractère (insensible à la casse). Exemple : title notmatches "football"
133=========== ============================================== ========== ========== 134=========== ============================================== ========== ==========
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTaggingRuleData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTaggingRuleData.php
index 7efe6356..55abd63c 100644
--- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTaggingRuleData.php
+++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTaggingRuleData.php
@@ -36,6 +36,13 @@ class LoadTaggingRuleData extends AbstractFixture implements OrderedFixtureInter
36 36
37 $manager->persist($tr3); 37 $manager->persist($tr3);
38 38
39 $tr4 = new TaggingRule();
40 $tr4->setRule('content notmatches "basket"');
41 $tr4->setTags(['foot']);
42 $tr4->setConfig($this->getReference('admin-config'));
43
44 $manager->persist($tr4);
45
39 $manager->flush(); 46 $manager->flush();
40 } 47 }
41 48
diff --git a/src/Wallabag/CoreBundle/Entity/TaggingRule.php b/src/Wallabag/CoreBundle/Entity/TaggingRule.php
index 72651b19..84e11e26 100644
--- a/src/Wallabag/CoreBundle/Entity/TaggingRule.php
+++ b/src/Wallabag/CoreBundle/Entity/TaggingRule.php
@@ -31,7 +31,7 @@ class TaggingRule
31 * @Assert\Length(max=255) 31 * @Assert\Length(max=255)
32 * @RulerZAssert\ValidRule( 32 * @RulerZAssert\ValidRule(
33 * allowed_variables={"title", "url", "isArchived", "isStared", "content", "language", "mimetype", "readingTime", "domainName"}, 33 * allowed_variables={"title", "url", "isArchived", "isStared", "content", "language", "mimetype", "readingTime", "domainName"},
34 * allowed_operators={">", "<", ">=", "<=", "=", "is", "!=", "and", "not", "or", "matches"} 34 * allowed_operators={">", "<", ">=", "<=", "=", "is", "!=", "and", "not", "or", "matches", "notmatches"}
35 * ) 35 * )
36 * @ORM\Column(name="rule", type="string", nullable=false) 36 * @ORM\Column(name="rule", type="string", nullable=false)
37 */ 37 */
@@ -87,7 +87,7 @@ class TaggingRule
87 /** 87 /**
88 * Set tags. 88 * Set tags.
89 * 89 *
90 * @param array<string> $tags 90 * @param array <string> $tags
91 * 91 *
92 * @return TaggingRule 92 * @return TaggingRule
93 */ 93 */
diff --git a/src/Wallabag/CoreBundle/Operator/Doctrine/NotMatches.php b/src/Wallabag/CoreBundle/Operator/Doctrine/NotMatches.php
new file mode 100644
index 00000000..090da77c
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Operator/Doctrine/NotMatches.php
@@ -0,0 +1,25 @@
1<?php
2
3namespace Wallabag\CoreBundle\Operator\Doctrine;
4
5/**
6 * Provides a "notmatches" operator used for tagging rules.
7 *
8 * It asserts that a given pattern is not contained in a subject, in a
9 * case-insensitive way.
10 *
11 * This operator will be used to compile tagging rules in DQL, usable
12 * by Doctrine ORM.
13 * It's registered in RulerZ using a service (wallabag.operator.doctrine.matches);
14 */
15class NotMatches
16{
17 public function __invoke($subject, $pattern)
18 {
19 if ($pattern[0] === "'") {
20 $pattern = sprintf("'%%%s%%'", substr($pattern, 1, -1));
21 }
22
23 return sprintf('UPPER(%s) NOT LIKE UPPER(%s)', $subject, $pattern);
24 }
25}
diff --git a/src/Wallabag/CoreBundle/Operator/PHP/NotMatches.php b/src/Wallabag/CoreBundle/Operator/PHP/NotMatches.php
new file mode 100644
index 00000000..eecb43cc
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Operator/PHP/NotMatches.php
@@ -0,0 +1,21 @@
1<?php
2
3namespace Wallabag\CoreBundle\Operator\PHP;
4
5/**
6 * Provides a "notmatches" operator used for tagging rules.
7 *
8 * It asserts that a given pattern is not contained in a subject, in a
9 * case-insensitive way.
10 *
11 * This operator will be used to compile tagging rules in PHP, usable
12 * directly on Entry objects for instance.
13 * It's registered in RulerZ using a service (wallabag.operator.array.matches);
14 */
15class NotMatches
16{
17 public function __invoke($subject, $pattern)
18 {
19 return stripos($subject, $pattern) === false;
20 }
21}
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml
index 51d6ab47..bccb2e19 100644
--- a/src/Wallabag/CoreBundle/Resources/config/services.yml
+++ b/src/Wallabag/CoreBundle/Resources/config/services.yml
@@ -125,6 +125,16 @@ services:
125 tags: 125 tags:
126 - { name: rulerz.operator, target: doctrine, operator: matches, inline: true } 126 - { name: rulerz.operator, target: doctrine, operator: matches, inline: true }
127 127
128 wallabag.operator.array.notmatches:
129 class: Wallabag\CoreBundle\Operator\PHP\NotMatches
130 tags:
131 - { name: rulerz.operator, target: native, operator: notmatches }
132
133 wallabag.operator.doctrine.notmatches:
134 class: Wallabag\CoreBundle\Operator\Doctrine\NotMatches
135 tags:
136 - { name: rulerz.operator, target: doctrine, operator: notmatches, inline: true }
137
128 wallabag_core.helper.redirect: 138 wallabag_core.helper.redirect:
129 class: Wallabag\CoreBundle\Helper\Redirect 139 class: Wallabag\CoreBundle\Helper\Redirect
130 arguments: 140 arguments:
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
index 72493fe3..e5211b57 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
@@ -155,7 +155,7 @@ config:
155 # or: 'One rule OR another' 155 # or: 'One rule OR another'
156 # and: 'One rule AND another' 156 # and: 'One rule AND another'
157 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' 157 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
158 158 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
159entry: 159entry:
160 page_titles: 160 page_titles:
161 # unread: 'Unread entries' 161 # unread: 'Unread entries'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
index dbad8b16..893a4564 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
@@ -155,6 +155,7 @@ config:
155 or: 'Eine Regel ODER die andere' 155 or: 'Eine Regel ODER die andere'
156 and: 'Eine Regel UND eine andere' 156 and: 'Eine Regel UND eine andere'
157 matches: 'Testet, ob eine <i>Variable</i> auf eine <i>Suche</i> zutrifft (Groß- und Kleinschreibung wird nicht berücksichtigt).<br />Beispiel: <code>title matches "Fußball"</code>' 157 matches: 'Testet, ob eine <i>Variable</i> auf eine <i>Suche</i> zutrifft (Groß- und Kleinschreibung wird nicht berücksichtigt).<br />Beispiel: <code>title matches "Fußball"</code>'
158 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
158 159
159entry: 160entry:
160 page_titles: 161 page_titles:
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
index 7da9fe6b..29f9938c 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
@@ -155,6 +155,7 @@ config:
155 or: 'One rule OR another' 155 or: 'One rule OR another'
156 and: 'One rule AND another' 156 and: 'One rule AND another'
157 matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' 157 matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
158 notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
158 159
159entry: 160entry:
160 page_titles: 161 page_titles:
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
index 6e21614e..99d25859 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
@@ -155,6 +155,7 @@ config:
155 or: 'Una regla U otra' 155 or: 'Una regla U otra'
156 and: 'Una regla Y la otra' 156 and: 'Una regla Y la otra'
157 matches: 'Prueba si un <i>sujeto</i> corresponde a una <i>búsqueda</i> (insensible a mayusculas).<br />Ejemplo : <code>title matches "fútbol"</code>' 157 matches: 'Prueba si un <i>sujeto</i> corresponde a una <i>búsqueda</i> (insensible a mayusculas).<br />Ejemplo : <code>title matches "fútbol"</code>'
158 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
158 159
159entry: 160entry:
160 page_titles: 161 page_titles:
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
index b938c80a..ccd9d555 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
@@ -155,6 +155,7 @@ config:
155 # or: 'One rule OR another' 155 # or: 'One rule OR another'
156 # and: 'One rule AND another' 156 # and: 'One rule AND another'
157 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' 157 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
158 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
158 159
159entry: 160entry:
160 page_titles: 161 page_titles:
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index 9abcda45..a0f100f7 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -155,6 +155,7 @@ config:
155 or: "Une règle OU l’autre" 155 or: "Une règle OU l’autre"
156 and: "Une règle ET l’autre" 156 and: "Une règle ET l’autre"
157 matches: "Teste si un <i>sujet</i> correspond à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title matches \"football\"</code>" 157 matches: "Teste si un <i>sujet</i> correspond à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title matches \"football\"</code>"
158 notmatches: "Teste si un <i>sujet</i> ne correspond pas à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title notmatches \"football\"</code>"
158 159
159entry: 160entry:
160 page_titles: 161 page_titles:
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
index 58d0962a..374071ce 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
@@ -155,6 +155,7 @@ config:
155 or: "Una regola O un'altra" 155 or: "Una regola O un'altra"
156 and: "Una regola E un'altra" 156 and: "Una regola E un'altra"
157 matches: 'Verifica che un <i>oggetto</i> risulti in una <i>ricerca</i> (case-insensitive).<br />Esempio: <code>titolo contiene "football"</code>' 157 matches: 'Verifica che un <i>oggetto</i> risulti in una <i>ricerca</i> (case-insensitive).<br />Esempio: <code>titolo contiene "football"</code>'
158 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
158 159
159entry: 160entry:
160 page_titles: 161 page_titles:
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
index 825a0efd..b01c611b 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
@@ -155,6 +155,7 @@ config:
155 or: "Una règla O l'autra" 155 or: "Una règla O l'autra"
156 and: "Una règla E l'autra" 156 and: "Una règla E l'autra"
157 matches: 'Teste se un <i>subjècte</i> correspond a una <i>recerca</i> (non sensibla a la cassa).<br />Exemple : <code>title matches \"football\"</code>' 157 matches: 'Teste se un <i>subjècte</i> correspond a una <i>recerca</i> (non sensibla a la cassa).<br />Exemple : <code>title matches \"football\"</code>'
158 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
158 159
159entry: 160entry:
160 page_titles: 161 page_titles:
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
index b02aa4ec..d76ac328 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
@@ -155,6 +155,7 @@ config:
155 or: 'Jedna reguła LUB inna' 155 or: 'Jedna reguła LUB inna'
156 and: 'Jedna reguła I inna' 156 and: 'Jedna reguła I inna'
157 matches: 'Sprawdź czy <i>temat</i> pasuje <i>szukaj</i> (duże lub małe litery).<br />Przykład: <code>tytuł zawiera "piłka nożna"</code>' 157 matches: 'Sprawdź czy <i>temat</i> pasuje <i>szukaj</i> (duże lub małe litery).<br />Przykład: <code>tytuł zawiera "piłka nożna"</code>'
158 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
158 159
159entry: 160entry:
160 page_titles: 161 page_titles:
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
index 8aa7e5af..98dfcd25 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
@@ -155,6 +155,7 @@ config:
155 or: 'Uma regra OU outra' 155 or: 'Uma regra OU outra'
156 and: 'Uma regra E outra' 156 and: 'Uma regra E outra'
157 matches: 'Testa que um <i>assunto</i> corresponde a uma <i>pesquisa</i> (maiúscula ou minúscula).<br />Exemplo: <code>título corresponde a "futebol"</code>' 157 matches: 'Testa que um <i>assunto</i> corresponde a uma <i>pesquisa</i> (maiúscula ou minúscula).<br />Exemplo: <code>título corresponde a "futebol"</code>'
158 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
158 159
159entry: 160entry:
160 page_titles: 161 page_titles:
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
index ce8d8d52..8c07c13f 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
@@ -155,6 +155,7 @@ config:
155 # or: 'One rule OR another' 155 # or: 'One rule OR another'
156 # and: 'One rule AND another' 156 # and: 'One rule AND another'
157 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' 157 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
158 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
158 159
159entry: 160entry:
160 page_titles: 161 page_titles:
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
index d8903608..bd21cb67 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
@@ -155,6 +155,7 @@ config:
155 or: 'Bir kural veya birbaşkası' 155 or: 'Bir kural veya birbaşkası'
156 and: 'Bir kural ve diğeri' 156 and: 'Bir kural ve diğeri'
157 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' 157 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
158 # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
158 159
159entry: 160entry:
160 page_titles: 161 page_titles:
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
index 708ff951..d6e414e9 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
@@ -413,8 +413,8 @@
413 <tr> 413 <tr>
414 <td>domainName</td> 414 <td>domainName</td>
415 <td>{{ 'config.form_rules.faq.variable_description.domainName'|trans }}</td> 415 <td>{{ 'config.form_rules.faq.variable_description.domainName'|trans }}</td>
416 <td>matches</td> 416 <td>matches<br />notmaches</td>
417 <td>{{ 'config.form_rules.faq.operator_description.matches'|trans|raw }}</td> 417 <td>{{ 'config.form_rules.faq.operator_description.matches'|trans|raw }}<br />{{ 'config.form_rules.faq.operator_description.notmatches'|trans|raw }}</td>
418 </tr> 418 </tr>
419 </tbody> 419 </tbody>
420 </table> 420 </table>
diff --git a/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
index dc5160c7..d9acacfc 100644
--- a/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
+++ b/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
@@ -337,7 +337,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
337 $this->assertEquals(false, $content['is_starred']); 337 $this->assertEquals(false, $content['is_starred']);
338 $this->assertEquals('New title for my article', $content['title']); 338 $this->assertEquals('New title for my article', $content['title']);
339 $this->assertEquals(1, $content['user_id']); 339 $this->assertEquals(1, $content['user_id']);
340 $this->assertCount(1, $content['tags']); 340 $this->assertCount(2, $content['tags']);
341 } 341 }
342 342
343 public function testPostSameEntry() 343 public function testPostSameEntry()
@@ -356,7 +356,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
356 $this->assertEquals('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']); 356 $this->assertEquals('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']);
357 $this->assertEquals(true, $content['is_archived']); 357 $this->assertEquals(true, $content['is_archived']);
358 $this->assertEquals(false, $content['is_starred']); 358 $this->assertEquals(false, $content['is_starred']);
359 $this->assertCount(2, $content['tags']); 359 $this->assertCount(3, $content['tags']);
360 } 360 }
361 361
362 public function testPostArchivedAndStarredEntry() 362 public function testPostArchivedAndStarredEntry()
diff --git a/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php b/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php
index d26a56f8..35438c83 100644
--- a/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php
@@ -270,7 +270,7 @@ class EntryControllerTest extends WallabagCoreTestCase
270 ->findOneByUrl($url); 270 ->findOneByUrl($url);
271 $tags = $entry->getTags(); 271 $tags = $entry->getTags();
272 272
273 $this->assertCount(1, $tags); 273 $this->assertCount(2, $tags);
274 $this->assertEquals('wallabag', $tags[0]->getLabel()); 274 $this->assertEquals('wallabag', $tags[0]->getLabel());
275 275
276 $em->remove($entry); 276 $em->remove($entry);
@@ -299,8 +299,8 @@ class EntryControllerTest extends WallabagCoreTestCase
299 299
300 $tags = $entry->getTags(); 300 $tags = $entry->getTags();
301 301
302 $this->assertCount(1, $tags); 302 $this->assertCount(2, $tags);
303 $this->assertEquals('wallabag', $tags[0]->getLabel()); 303 $this->assertEquals('wallabag', $tags[1]->getLabel());
304 304
305 $em->remove($entry); 305 $em->remove($entry);
306 $em->flush(); 306 $em->flush();
diff --git a/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php b/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php
index 32a18e26..1b8ecc49 100644
--- a/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php
@@ -241,7 +241,7 @@ class ExportControllerTest extends WallabagCoreTestCase
241 $this->assertEquals($contentInDB->getLanguage(), $content[0]['language']); 241 $this->assertEquals($contentInDB->getLanguage(), $content[0]['language']);
242 $this->assertEquals($contentInDB->getReadingtime(), $content[0]['reading_time']); 242 $this->assertEquals($contentInDB->getReadingtime(), $content[0]['reading_time']);
243 $this->assertEquals($contentInDB->getDomainname(), $content[0]['domain_name']); 243 $this->assertEquals($contentInDB->getDomainname(), $content[0]['domain_name']);
244 $this->assertEquals(['foo bar', 'baz'], $content[0]['tags']); 244 $this->assertEquals(['foo bar', 'baz', 'foot'], $content[0]['tags']);
245 } 245 }
246 246
247 public function testXmlExport() 247 public function testXmlExport()
diff --git a/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php b/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php
index fa1a3539..c3b22dcd 100644
--- a/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php
@@ -46,7 +46,7 @@ class TagControllerTest extends WallabagCoreTestCase
46 ->getRepository('WallabagCoreBundle:Entry') 46 ->getRepository('WallabagCoreBundle:Entry')
47 ->findByUrlAndUserId('http://0.0.0.0/entry1', $this->getLoggedInUserId()); 47 ->findByUrlAndUserId('http://0.0.0.0/entry1', $this->getLoggedInUserId());
48 48
49 $this->assertEquals(3, count($entry->getTags())); 49 $this->assertEquals(4, count($entry->getTags()));
50 50
51 // tag already exists and already assigned 51 // tag already exists and already assigned
52 $client->submit($form, $data); 52 $client->submit($form, $data);
@@ -57,7 +57,7 @@ class TagControllerTest extends WallabagCoreTestCase
57 ->getRepository('WallabagCoreBundle:Entry') 57 ->getRepository('WallabagCoreBundle:Entry')
58 ->find($entry->getId()); 58 ->find($entry->getId());
59 59
60 $this->assertEquals(3, count($newEntry->getTags())); 60 $this->assertEquals(4, count($newEntry->getTags()));
61 61
62 // tag already exists but still not assigned to this entry 62 // tag already exists but still not assigned to this entry
63 $data = [ 63 $data = [
@@ -72,7 +72,7 @@ class TagControllerTest extends WallabagCoreTestCase
72 ->getRepository('WallabagCoreBundle:Entry') 72 ->getRepository('WallabagCoreBundle:Entry')
73 ->find($entry->getId()); 73 ->find($entry->getId());
74 74
75 $this->assertEquals(3, count($newEntry->getTags())); 75 $this->assertEquals(4, count($newEntry->getTags()));
76 } 76 }
77 77
78 public function testAddMultipleTagToEntry() 78 public function testAddMultipleTagToEntry()
diff --git a/tests/Wallabag/ImportBundle/Controller/ChromeControllerTest.php b/tests/Wallabag/ImportBundle/Controller/ChromeControllerTest.php
index c1f82ea9..8e9f65e3 100644
--- a/tests/Wallabag/ImportBundle/Controller/ChromeControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/ChromeControllerTest.php
@@ -120,7 +120,7 @@ class ChromeControllerTest extends WallabagCoreTestCase
120 120
121 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.usinenouvelle.com is ok'); 121 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.usinenouvelle.com is ok');
122 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.usinenouvelle.com is ok'); 122 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.usinenouvelle.com is ok');
123 $this->assertEquals(0, count($content->getTags())); 123 $this->assertEquals(1, count($content->getTags()));
124 124
125 $createdAt = $content->getCreatedAt(); 125 $createdAt = $content->getCreatedAt();
126 $this->assertEquals('2011', $createdAt->format('Y')); 126 $this->assertEquals('2011', $createdAt->format('Y'));
diff --git a/tests/Wallabag/ImportBundle/Controller/FirefoxControllerTest.php b/tests/Wallabag/ImportBundle/Controller/FirefoxControllerTest.php
index 7557ea32..68453027 100644
--- a/tests/Wallabag/ImportBundle/Controller/FirefoxControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/FirefoxControllerTest.php
@@ -121,7 +121,7 @@ class FirefoxControllerTest extends WallabagCoreTestCase
121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://lexpansion.lexpress.fr is ok'); 121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://lexpansion.lexpress.fr is ok');
122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://lexpansion.lexpress.fr is ok'); 122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://lexpansion.lexpress.fr is ok');
123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://lexpansion.lexpress.fr is ok'); 123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://lexpansion.lexpress.fr is ok');
124 $this->assertEquals(2, count($content->getTags())); 124 $this->assertEquals(3, count($content->getTags()));
125 125
126 $content = $client->getContainer() 126 $content = $client->getContainer()
127 ->get('doctrine.orm.entity_manager') 127 ->get('doctrine.orm.entity_manager')
diff --git a/tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php b/tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php
index 3f6f2b9f..c2e5fdb7 100644
--- a/tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php
@@ -121,7 +121,7 @@ class InstapaperControllerTest extends WallabagCoreTestCase
121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.liberation.fr is ok'); 121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.liberation.fr is ok');
122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.liberation.fr is ok'); 122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.liberation.fr is ok');
123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.liberation.fr is ok'); 123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.liberation.fr is ok');
124 $this->assertEquals(0, count($content->getTags())); 124 $this->assertEquals(1, count($content->getTags()));
125 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); 125 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
126 } 126 }
127 127
diff --git a/tests/Wallabag/ImportBundle/Controller/PinboardControllerTest.php b/tests/Wallabag/ImportBundle/Controller/PinboardControllerTest.php
index 75a7e332..96b32484 100644
--- a/tests/Wallabag/ImportBundle/Controller/PinboardControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/PinboardControllerTest.php
@@ -121,7 +121,7 @@ class PinboardControllerTest extends WallabagCoreTestCase
121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://ma.ttias.be is ok'); 121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://ma.ttias.be is ok');
122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://ma.ttias.be is ok'); 122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://ma.ttias.be is ok');
123 $this->assertNotEmpty($content->getLanguage(), 'Language for https://ma.ttias.be is ok'); 123 $this->assertNotEmpty($content->getLanguage(), 'Language for https://ma.ttias.be is ok');
124 $this->assertEquals(2, count($content->getTags())); 124 $this->assertEquals(3, count($content->getTags()));
125 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); 125 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
126 $this->assertEquals('2016-10-26', $content->getCreatedAt()->format('Y-m-d')); 126 $this->assertEquals('2016-10-26', $content->getCreatedAt()->format('Y-m-d'));
127 } 127 }
diff --git a/tests/Wallabag/ImportBundle/Controller/ReadabilityControllerTest.php b/tests/Wallabag/ImportBundle/Controller/ReadabilityControllerTest.php
index acb61ca1..e6d33fe9 100644
--- a/tests/Wallabag/ImportBundle/Controller/ReadabilityControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/ReadabilityControllerTest.php
@@ -121,7 +121,7 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.zataz.com is ok'); 121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.zataz.com is ok');
122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.zataz.com is ok'); 122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.zataz.com is ok');
123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.zataz.com is ok'); 123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.zataz.com is ok');
124 $this->assertEquals(0, count($content->getTags())); 124 $this->assertEquals(1, count($content->getTags()));
125 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); 125 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
126 $this->assertEquals('2016-09-08', $content->getCreatedAt()->format('Y-m-d')); 126 $this->assertEquals('2016-09-08', $content->getCreatedAt()->format('Y-m-d'));
127 } 127 }
diff --git a/tests/Wallabag/ImportBundle/Controller/WallabagV1ControllerTest.php b/tests/Wallabag/ImportBundle/Controller/WallabagV1ControllerTest.php
index acc39997..0c7f97ed 100644
--- a/tests/Wallabag/ImportBundle/Controller/WallabagV1ControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/WallabagV1ControllerTest.php
@@ -129,7 +129,7 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
129 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.framablog.org is ok'); 129 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.framablog.org is ok');
130 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.framablog.org is ok'); 130 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.framablog.org is ok');
131 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.framablog.org is ok'); 131 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.framablog.org is ok');
132 $this->assertEquals(1, count($content->getTags())); 132 $this->assertEquals(2, count($content->getTags()));
133 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); 133 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
134 } 134 }
135 135
diff --git a/tests/Wallabag/ImportBundle/Controller/WallabagV2ControllerTest.php b/tests/Wallabag/ImportBundle/Controller/WallabagV2ControllerTest.php
index 26e2f40b..556ab1bd 100644
--- a/tests/Wallabag/ImportBundle/Controller/WallabagV2ControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/WallabagV2ControllerTest.php
@@ -122,7 +122,7 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
122 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.liberation.fr is ok'); 122 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.liberation.fr is ok');
123 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.liberation.fr is ok'); 123 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.liberation.fr is ok');
124 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.liberation.fr is ok'); 124 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.liberation.fr is ok');
125 $this->assertEquals(0, count($content->getTags())); 125 $this->assertEquals(1, count($content->getTags()));
126 126
127 $content = $client->getContainer() 127 $content = $client->getContainer()
128 ->get('doctrine.orm.entity_manager') 128 ->get('doctrine.orm.entity_manager')
@@ -135,7 +135,7 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
135 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://www.mediapart.fr is ok'); 135 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://www.mediapart.fr is ok');
136 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://www.mediapart.fr is ok'); 136 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://www.mediapart.fr is ok');
137 $this->assertNotEmpty($content->getLanguage(), 'Language for https://www.mediapart.fr is ok'); 137 $this->assertNotEmpty($content->getLanguage(), 'Language for https://www.mediapart.fr is ok');
138 $this->assertEquals(2, count($content->getTags())); 138 $this->assertEquals(3, count($content->getTags()));
139 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); 139 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
140 $this->assertEquals('2016-09-08', $content->getCreatedAt()->format('Y-m-d')); 140 $this->assertEquals('2016-09-08', $content->getCreatedAt()->format('Y-m-d'));
141 } 141 }