aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.de.yml3
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.en.yml5
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.es.yml3
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml3
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml141
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.it.yml3
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml3
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml3
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml3
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml3
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml3
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig4
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig10
-rw-r--r--src/Wallabag/ImportBundle/Command/ImportCommand.php11
-rw-r--r--src/Wallabag/UserBundle/Controller/ManageController.php67
-rw-r--r--src/Wallabag/UserBundle/Form/SearchUserType.php29
-rw-r--r--src/Wallabag/UserBundle/Repository/UserRepository.php13
-rw-r--r--src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig77
24 files changed, 327 insertions, 128 deletions
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..b7f9da57
--- /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.notmatches);
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..68b2676f
--- /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.notmatches);
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..57319af7 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'
@@ -512,6 +512,8 @@ user:
512 # delete: Delete 512 # delete: Delete
513 # delete_confirm: Are you sure? 513 # delete_confirm: Are you sure?
514 # back_to_list: Back to list 514 # back_to_list: Back to list
515 search:
516 # placeholder: Filter by username or email
515 517
516error: 518error:
517 # page_title: An error occurred 519 # page_title: An error occurred
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
index dbad8b16..a7bcecc6 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:
@@ -512,6 +513,8 @@ user:
512 delete: Löschen 513 delete: Löschen
513 delete_confirm: Bist du sicher? 514 delete_confirm: Bist du sicher?
514 back_to_list: Zurück zur Liste 515 back_to_list: Zurück zur Liste
516 search:
517 # placeholder: Filter by username or email
515 518
516error: 519error:
517 page_title: Ein Fehler ist aufgetreten 520 page_title: Ein Fehler ist aufgetreten
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
index 7da9fe6b..1ef2874d 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:
@@ -361,7 +362,7 @@ quickstart:
361 developer: 362 developer:
362 title: 'Developers' 363 title: 'Developers'
363 description: 'We also thought to the developers: Docker, API, translations, etc.' 364 description: 'We also thought to the developers: Docker, API, translations, etc.'
364 create_application: 'Create your third application' 365 create_application: 'Create your third-party application'
365 use_docker: 'Use Docker to install wallabag' 366 use_docker: 'Use Docker to install wallabag'
366 docs: 367 docs:
367 title: 'Full documentation' 368 title: 'Full documentation'
@@ -512,6 +513,8 @@ user:
512 delete: Delete 513 delete: Delete
513 delete_confirm: Are you sure? 514 delete_confirm: Are you sure?
514 back_to_list: Back to list 515 back_to_list: Back to list
516 search:
517 placeholder: Filter by username or email
515 518
516error: 519error:
517 page_title: An error occurred 520 page_title: An error occurred
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
index 6e21614e..6cd079b0 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:
@@ -512,6 +513,8 @@ user:
512 delete: Eliminar 513 delete: Eliminar
513 delete_confirm: ¿Estás seguro? 514 delete_confirm: ¿Estás seguro?
514 back_to_list: Volver a la lista 515 back_to_list: Volver a la lista
516 search:
517 # placeholder: Filter by username or email
515 518
516error: 519error:
517 page_title: Ha ocurrido un error 520 page_title: Ha ocurrido un error
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
index b938c80a..fb6e315e 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:
@@ -512,6 +513,8 @@ user:
512 # delete: Delete 513 # delete: Delete
513 # delete_confirm: Are you sure? 514 # delete_confirm: Are you sure?
514 # back_to_list: Back to list 515 # back_to_list: Back to list
516 search:
517 # placeholder: Filter by username or email
515 518
516error: 519error:
517 # page_title: An error occurred 520 # page_title: An error occurred
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index 9abcda45..ad886363 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -46,7 +46,7 @@ footer:
46 social: "Social" 46 social: "Social"
47 powered_by: "propulsé par" 47 powered_by: "propulsé par"
48 about: "À propos" 48 about: "À propos"
49 stats: Depuis le %user_creation%, vous avez lu %nb_archives% articles. Ce qui fait %per_day% par jour ! 49 stats: "Depuis le %user_creation%, vous avez lu %nb_archives% articles. Ce qui fait %per_day% par jour !"
50 50
51config: 51config:
52 page_title: "Configuration" 52 page_title: "Configuration"
@@ -71,16 +71,16 @@ config:
71 300_word: "Je lis environ 300 mots par minute" 71 300_word: "Je lis environ 300 mots par minute"
72 400_word: "Je lis environ 400 mots par minute" 72 400_word: "Je lis environ 400 mots par minute"
73 action_mark_as_read: 73 action_mark_as_read:
74 label: 'Où souhaitez-vous être redirigé après avoir marqué un article comme lu ?' 74 label: "Où souhaitez-vous être redirigé après avoir marqué un article comme lu ?"
75 redirect_homepage: "À la page d'accueil" 75 redirect_homepage: "À la page d’accueil"
76 redirect_current_page: 'À la page courante' 76 redirect_current_page: "À la page courante"
77 pocket_consumer_key_label: Clé d’authentification Pocket pour importer les données 77 pocket_consumer_key_label: "Clé d’authentification Pocket pour importer les données"
78 android_configuration: Configurez votre application Android 78 android_configuration: "Configurez votre application Android"
79 help_theme: "L'affichage de wallabag est personnalisable. C'est ici que vous choisissez le thème que vous préférez." 79 help_theme: "L’affichage de wallabag est personnalisable. C’est ici que vous choisissez le thème que vous préférez."
80 help_items_per_page: "Vous pouvez définir le nombre d'articles affichés sur chaque page." 80 help_items_per_page: "Vous pouvez définir le nombre d’articles affichés sur chaque page."
81 help_reading_speed: "wallabag calcule une durée de lecture pour chaque article. Vous pouvez définir ici, grâce à cette liste déroulante, si vous lisez plus ou moins vite. wallabag recalculera la durée de lecture de chaque article." 81 help_reading_speed: "wallabag calcule une durée de lecture pour chaque article. Vous pouvez définir ici, grâce à cette liste déroulante, si vous lisez plus ou moins vite. wallabag recalculera la durée de lecture de chaque article."
82 help_language: "Vous pouvez définir la langue de l'interface de wallabag." 82 help_language: "Vous pouvez définir la langue de l’interface de wallabag."
83 help_pocket_consumer_key: "Nécessaire pour l'import depuis Pocket. Vous pouvez le créer depuis votre compte Pocket." 83 help_pocket_consumer_key: "Nécessaire pour l’import depuis Pocket. Vous pouvez le créer depuis votre compte Pocket."
84 form_rss: 84 form_rss:
85 description: "Les flux RSS fournis par wallabag vous permettent de lire vos articles sauvegardés dans votre lecteur de flux préféré. Pour pouvoir les utiliser, vous devez d’abord créer un jeton." 85 description: "Les flux RSS fournis par wallabag vous permettent de lire vos articles sauvegardés dans votre lecteur de flux préféré. Pour pouvoir les utiliser, vous devez d’abord créer un jeton."
86 token_label: "Jeton RSS" 86 token_label: "Jeton RSS"
@@ -100,18 +100,18 @@ config:
100 twoFactorAuthentication_label: "Double authentification" 100 twoFactorAuthentication_label: "Double authentification"
101 help_twoFactorAuthentication: "Si vous activez 2FA, à chaque tentative de connexion à wallabag, vous recevrez un code par email." 101 help_twoFactorAuthentication: "Si vous activez 2FA, à chaque tentative de connexion à wallabag, vous recevrez un code par email."
102 delete: 102 delete:
103 title: Supprimer mon compte (attention danger !) 103 title: "Supprimer mon compte (attention danger !)"
104 description: Si vous confirmez la suppression de votre compte, TOUS les articles, TOUS les tags, TOUTES les annotations et votre compte seront DÉFINITIVEMENT supprimé (c'est IRRÉVERSIBLE). Vous serez ensuite déconnecté. 104 description: "Si vous confirmez la suppression de votre compte, TOUS les articles, TOUS les tags, TOUTES les annotations et votre compte seront DÉFINITIVEMENT supprimé (c’est IRRÉVERSIBLE). Vous serez ensuite déconnecté."
105 confirm: Vous êtes vraiment sûr ? (C'EST IRRÉVERSIBLE) 105 confirm: "Vous êtes vraiment sûr ? (C’EST IRRÉVERSIBLE)"
106 button: 'Supprimer mon compte' 106 button: "Supprimer mon compte"
107 reset: 107 reset:
108 title: Réinitialisation (attention danger !) 108 title: "Réinitialisation (attention danger !)"
109 description: En cliquant sur les boutons ci-dessous vous avez la possibilité de supprimer certaines informations de votre compte. Attention, ces actions sont IRRÉVERSIBLES ! 109 description: "En cliquant sur les boutons ci-dessous vous avez la possibilité de supprimer certaines informations de votre compte. Attention, ces actions sont IRRÉVERSIBLES !"
110 annotations: Supprimer TOUTES les annotations 110 annotations: "Supprimer TOUTES les annotations"
111 tags: Supprimer TOUS les tags 111 tags: "Supprimer TOUS les tags"
112 entries: Supprimer TOUS les articles 112 entries: "Supprimer TOUS les articles"
113 archived: Supprimer TOUS les articles archivés 113 archived: "Supprimer TOUS les articles archivés"
114 confirm: Êtes-vous vraiment vraiment sûr ? (C'EST IRRÉVERSIBLE) 114 confirm: "Êtes-vous vraiment vraiment sûr ? (C’EST IRRÉVERSIBLE)"
115 form_password: 115 form_password:
116 description: "Vous pouvez changer ici votre mot de passe. Le mot de passe doit contenir au moins 8 caractères." 116 description: "Vous pouvez changer ici votre mot de passe. Le mot de passe doit contenir au moins 8 caractères."
117 old_password_label: "Mot de passe actuel" 117 old_password_label: "Mot de passe actuel"
@@ -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:
@@ -163,7 +164,7 @@ entry:
163 archived: "Articles lus" 164 archived: "Articles lus"
164 filtered: "Articles filtrés" 165 filtered: "Articles filtrés"
165 filtered_tags: "Articles filtrés par tags :" 166 filtered_tags: "Articles filtrés par tags :"
166 filtered_search: 'Articles filtrés par recherche :' 167 filtered_search: "Articles filtrés par recherche :"
167 untagged: "Article sans tag" 168 untagged: "Article sans tag"
168 list: 169 list:
169 number_on_the_page: "{0} Il n’y a pas d’article.|{1} Il y a un article.|]1,Inf[ Il y a %count% articles." 170 number_on_the_page: "{0} Il n’y a pas d’article.|{1} Il y a un article.|]1,Inf[ Il y a %count% articles."
@@ -187,7 +188,7 @@ entry:
187 preview_picture_label: "A une photo" 188 preview_picture_label: "A une photo"
188 preview_picture_help: "Photo" 189 preview_picture_help: "Photo"
189 language_label: "Langue" 190 language_label: "Langue"
190 http_status_label: 'Statut HTTP' 191 http_status_label: "Statut HTTP"
191 reading_time: 192 reading_time:
192 label: "Durée de lecture en minutes" 193 label: "Durée de lecture en minutes"
193 from: "de" 194 from: "de"
@@ -297,32 +298,32 @@ howto:
297 bookmarklet: 298 bookmarklet:
298 description: "Glissez et déposez ce lien dans votre barre de favoris :" 299 description: "Glissez et déposez ce lien dans votre barre de favoris :"
299 shortcuts: 300 shortcuts:
300 page_description: Voici les raccourcis disponibles dans wallabag. 301 page_description: "Voici les raccourcis disponibles dans wallabag."
301 shortcut: Raccourci 302 shortcut: "Raccourci"
302 action: Action 303 action: "Action"
303 all_pages_title: Raccourcis disponibles dans toutes les pages 304 all_pages_title: "Raccourcis disponibles dans toutes les pages"
304 go_unread: Afficher les articles non lus 305 go_unread: "Afficher les articles non lus"
305 go_starred: Afficher les articles favoris 306 go_starred: "Afficher les articles favoris"
306 go_archive: Afficher les articles lus 307 go_archive: "Afficher les articles lus"
307 go_all: Afficher tous les articles 308 go_all: "Afficher tous les articles"
308 go_tags: Afficher les tags 309 go_tags: "Afficher les tags"
309 go_config: Aller à la configuration 310 go_config: "Aller à la configuration"
310 go_import: Aller aux imports 311 go_import: "Aller aux imports"
311 go_developers: Aller à la section Développeurs 312 go_developers: "Aller à la section Développeurs"
312 go_howto: Afficher l'aide (cette page !) 313 go_howto: "Afficher l’aide (cette page !)"
313 go_logout: Se déconnecter 314 go_logout: "Se déconnecter"
314 list_title: Raccourcis disponibles dans les pages de liste 315 list_title: "Raccourcis disponibles dans les pages de liste"
315 search: Afficher le formulaire de recherche 316 search: "Afficher le formulaire de recherche"
316 article_title: Raccourcis disponibles quand on affiche un article 317 article_title: "Raccourcis disponibles quand on affiche un article"
317 open_original: Ouvrir l'URL originale de l'article 318 open_original: "Ouvrir l’URL originale de l’article"
318 toggle_favorite: Changer le statut Favori de l'article 319 toggle_favorite: "Changer le statut Favori de l’article"
319 toggle_archive: Changer le status Lu de l'article 320 toggle_archive: "Changer le status Lu de l’article"
320 delete: Supprimer l'article 321 delete: "Supprimer l’article"
321 material_title: Raccourcis disponibles avec le thème Material uniquement 322 material_title: "Raccourcis disponibles avec le thème Material uniquement"
322 add_link: Ajouter un nouvel article 323 add_link: "Ajouter un nouvel article"
323 hide_form: Masquer le formulaire courant (recherche ou nouvel article) 324 hide_form: "Masquer le formulaire courant (recherche ou nouvel article)"
324 arrows_navigation: Naviguer à travers les articles 325 arrows_navigation: "Naviguer à travers les articles"
325 open_article: Afficher l'article sélectionné 326 open_article: "Afficher l’article sélectionné"
326 327
327quickstart: 328quickstart:
328 page_title: "Pour bien débuter" 329 page_title: "Pour bien débuter"
@@ -384,8 +385,8 @@ tag:
384 number_on_the_page: "{0} Il n’y a pas de tag.|{1} Il y a un tag.|]1,Inf[ Il y a %count% tags." 385 number_on_the_page: "{0} Il n’y a pas de tag.|{1} Il y a un tag.|]1,Inf[ Il y a %count% tags."
385 see_untagged_entries: "Voir les articles sans tag" 386 see_untagged_entries: "Voir les articles sans tag"
386 new: 387 new:
387 add: 'Ajouter' 388 add: "Ajouter"
388 placeholder: 'Vous pouvez ajouter plusieurs tags, séparés par une virgule.' 389 placeholder: "Vous pouvez ajouter plusieurs tags, séparés par une virgule."
389 390
390import: 391import:
391 page_title: "Importer" 392 page_title: "Importer"
@@ -419,7 +420,7 @@ import:
419 how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l’importer." 420 how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l’importer."
420 worker: 421 worker:
421 enabled: "Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :" 422 enabled: "Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :"
422 download_images_warning: "Vous avez configuré le téléchagement des images pour vos articles. Combiné à l'import classique, cette opération peut être très très longue (voire échouer). Nous vous conseillons <strong>vivement</strong> d'activer les imports asynchrones." 423 download_images_warning: "Vous avez configuré le téléchagement des images pour vos articles. Combiné à l’import classique, cette opération peut être très très longue (voire échouer). Nous vous conseillons <strong>vivement</strong> d’activer les imports asynchrones."
423 firefox: 424 firefox:
424 page_title: "Import > Firefox" 425 page_title: "Import > Firefox"
425 description: "Cet outil va vous permettre d’importer tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde… ». Vous allez récupérer un fichier .json. </p>" 426 description: "Cet outil va vous permettre d’importer tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde… ». Vous allez récupérer un fichier .json. </p>"
@@ -488,16 +489,16 @@ developer:
488 back: "Retour" 489 back: "Retour"
489 490
490user: 491user:
491 page_title: Gestion des utilisateurs 492 page_title: "Gestion des utilisateurs"
492 new_user: Créer un nouvel utilisateur 493 new_user: "Créer un nouvel utilisateur"
493 edit_user: Éditer un utilisateur existant 494 edit_user: "Éditer un utilisateur existant"
494 description: Ici vous pouvez gérer vos utilisateurs (création, mise à jour et suppression) 495 description: "Ici vous pouvez gérer vos utilisateurs (création, mise à jour et suppression)"
495 list: 496 list:
496 actions: Actions 497 actions: "Actions"
497 edit_action: Éditer 498 edit_action: "Éditer"
498 yes: Oui 499 yes: "Oui"
499 no: Non 500 no: "Non"
500 create_new_one: Créer un nouvel utilisateur 501 create_new_one: "Créer un nouvel utilisateur"
501 form: 502 form:
502 username_label: "Nom d’utilisateur" 503 username_label: "Nom d’utilisateur"
503 name_label: "Nom" 504 name_label: "Nom"
@@ -512,9 +513,11 @@ user:
512 delete: "Supprimer" 513 delete: "Supprimer"
513 delete_confirm: "Voulez-vous vraiment ?" 514 delete_confirm: "Voulez-vous vraiment ?"
514 back_to_list: "Revenir à la liste" 515 back_to_list: "Revenir à la liste"
516 search:
517 placeholder: "Filtrer par nom d’utilisateur ou email"
515 518
516error: 519error:
517 page_title: Une erreur est survenue 520 page_title: "Une erreur est survenue"
518 521
519flashes: 522flashes:
520 config: 523 config:
@@ -527,10 +530,10 @@ flashes:
527 tagging_rules_updated: "Règles mises à jour" 530 tagging_rules_updated: "Règles mises à jour"
528 tagging_rules_deleted: "Règle supprimée" 531 tagging_rules_deleted: "Règle supprimée"
529 rss_token_updated: "Jeton RSS mis à jour" 532 rss_token_updated: "Jeton RSS mis à jour"
530 annotations_reset: Annotations supprimées 533 annotations_reset: "Annotations supprimées"
531 tags_reset: Tags supprimés 534 tags_reset: "Tags supprimés"
532 entries_reset: Articles supprimés 535 entries_reset: "Articles supprimés"
533 archived_reset: Articles archivés supprimés 536 archived_reset: "Articles archivés supprimés"
534 entry: 537 entry:
535 notice: 538 notice:
536 entry_already_saved: "Article déjà sauvegardé le %date%" 539 entry_already_saved: "Article déjà sauvegardé le %date%"
@@ -562,6 +565,6 @@ flashes:
562 client_deleted: "Client %name% supprimé" 565 client_deleted: "Client %name% supprimé"
563 user: 566 user:
564 notice: 567 notice:
565 added: 'Utilisateur "%username%" ajouté' 568 added: "Utilisateur \"%username%\" ajouté"
566 updated: 'Utilisateur "%username%" mis à jour' 569 updated: "Utilisateur \"%username%\" mis à jour"
567 deleted: 'Utilisateur "%username%" supprimé' 570 deleted: "Utilisateur \"%username%\" supprimé"
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
index 58d0962a..5a9605ff 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:
@@ -512,6 +513,8 @@ user:
512 # delete: Delete 513 # delete: Delete
513 # delete_confirm: Are you sure? 514 # delete_confirm: Are you sure?
514 # back_to_list: Back to list 515 # back_to_list: Back to list
516 search:
517 # placeholder: Filter by username or email
515 518
516error: 519error:
517 # page_title: An error occurred 520 # page_title: An error occurred
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
index 825a0efd..942bc257 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:
@@ -512,6 +513,8 @@ user:
512 delete: 'Suprimir' 513 delete: 'Suprimir'
513 delete_confirm: 'Sètz segur ?' 514 delete_confirm: 'Sètz segur ?'
514 back_to_list: 'Tornar a la lista' 515 back_to_list: 'Tornar a la lista'
516 search:
517 # placeholder: Filter by username or email
515 518
516error: 519error:
517 page_title: Una error s'es produsida 520 page_title: Una error s'es produsida
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
index b02aa4ec..fea90440 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:
@@ -512,6 +513,8 @@ user:
512 delete: Usuń 513 delete: Usuń
513 delete_confirm: JesteÅ› pewien? 514 delete_confirm: JesteÅ› pewien?
514 back_to_list: Powrót do listy 515 back_to_list: Powrót do listy
516 search:
517 # placeholder: Filter by username or email
515 518
516error: 519error:
517 page_title: Wystąpił błąd 520 page_title: Wystąpił błąd
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
index 8aa7e5af..c59991f8 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:
@@ -512,6 +513,8 @@ user:
512 delete: 'Apagar' 513 delete: 'Apagar'
513 delete_confirm: 'Tem certeza?' 514 delete_confirm: 'Tem certeza?'
514 back_to_list: 'Voltar para a lista' 515 back_to_list: 'Voltar para a lista'
516 search:
517 # placeholder: Filter by username or email
515 518
516error: 519error:
517 # page_title: An error occurred 520 # page_title: An error occurred
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
index ce8d8d52..5846b7cc 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:
@@ -512,6 +513,8 @@ user:
512 # delete: Delete 513 # delete: Delete
513 # delete_confirm: Are you sure? 514 # delete_confirm: Are you sure?
514 # back_to_list: Back to list 515 # back_to_list: Back to list
516 search:
517 # placeholder: Filter by username or email
515 518
516error: 519error:
517 # page_title: An error occurred 520 # page_title: An error occurred
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
index d8903608..430fb96b 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:
@@ -512,6 +513,8 @@ user:
512 # delete: Delete 513 # delete: Delete
513 # delete_confirm: Are you sure? 514 # delete_confirm: Are you sure?
514 # back_to_list: Back to list 515 # back_to_list: Back to list
516 search:
517 # placeholder: Filter by username or email
515 518
516error: 519error:
517 # page_title: An error occurred 520 # page_title: An error occurred
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/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig
index 8be5fd0d..3c4ad024 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig
@@ -12,6 +12,11 @@
12 <div class="nav-wrapper cyan darken-1"> 12 <div class="nav-wrapper cyan darken-1">
13 <ul> 13 <ul>
14 <li> 14 <li>
15 <a href="#" data-activates="slide-out" class="button-collapse">
16 <i class="material-icons">menu</i>
17 </a>
18 </li>
19 <li>
15 <a class="waves-effect" href="{{ path('homepage') }}"> 20 <a class="waves-effect" href="{{ path('homepage') }}">
16 <i class="material-icons">exit_to_app</i> 21 <i class="material-icons">exit_to_app</i>
17 </a> 22 </a>
@@ -28,11 +33,6 @@
28 <i class="material-icons small">{% if entry.isStarred == 0 %}star_outline{% else %}star{% endif %}</i> 33 <i class="material-icons small">{% if entry.isStarred == 0 %}star_outline{% else %}star{% endif %}</i>
29 </a> 34 </a>
30 </li> 35 </li>
31 <li>
32 <a href="#" data-activates="slide-out" class="button-collapse right">
33 <i class="material-icons">menu</i>
34 </a>
35 </li>
36 </ul> 36 </ul>
37 </div> 37 </div>
38 </nav> 38 </nav>
diff --git a/src/Wallabag/ImportBundle/Command/ImportCommand.php b/src/Wallabag/ImportBundle/Command/ImportCommand.php
index 28d01715..ce72837a 100644
--- a/src/Wallabag/ImportBundle/Command/ImportCommand.php
+++ b/src/Wallabag/ImportBundle/Command/ImportCommand.php
@@ -15,10 +15,11 @@ class ImportCommand extends ContainerAwareCommand
15 $this 15 $this
16 ->setName('wallabag:import') 16 ->setName('wallabag:import')
17 ->setDescription('Import entries from a JSON export') 17 ->setDescription('Import entries from a JSON export')
18 ->addArgument('userId', InputArgument::REQUIRED, 'User ID to populate') 18 ->addArgument('username', InputArgument::REQUIRED, 'User to populate')
19 ->addArgument('filepath', InputArgument::REQUIRED, 'Path to the JSON file') 19 ->addArgument('filepath', InputArgument::REQUIRED, 'Path to the JSON file')
20 ->addOption('importer', null, InputArgument::OPTIONAL, 'The importer to use: v1, v2, instapaper, pinboard, readability, firefox or chrome', 'v1') 20 ->addOption('importer', null, InputArgument::OPTIONAL, 'The importer to use: v1, v2, instapaper, pinboard, readability, firefox or chrome', 'v1')
21 ->addOption('markAsRead', null, InputArgument::OPTIONAL, 'Mark all entries as read', false) 21 ->addOption('markAsRead', null, InputArgument::OPTIONAL, 'Mark all entries as read', false)
22 ->addOption('useUserId', null, InputArgument::OPTIONAL, 'Use user id instead of username to find account', false)
22 ; 23 ;
23 } 24 }
24 25
@@ -34,10 +35,14 @@ class ImportCommand extends ContainerAwareCommand
34 // Turning off doctrine default logs queries for saving memory 35 // Turning off doctrine default logs queries for saving memory
35 $em->getConnection()->getConfiguration()->setSQLLogger(null); 36 $em->getConnection()->getConfiguration()->setSQLLogger(null);
36 37
37 $user = $em->getRepository('WallabagUserBundle:User')->findOneById($input->getArgument('userId')); 38 if ($input->getOption('useUserId')) {
39 $user = $em->getRepository('WallabagUserBundle:User')->findOneById($input->getArgument('username'));
40 } else {
41 $user = $em->getRepository('WallabagUserBundle:User')->findOneByUsername($input->getArgument('username'));
42 }
38 43
39 if (!is_object($user)) { 44 if (!is_object($user)) {
40 throw new Exception(sprintf('User with id "%s" not found', $input->getArgument('userId'))); 45 throw new Exception(sprintf('User "%s" not found', $input->getArgument('username')));
41 } 46 }
42 47
43 switch ($input->getOption('importer')) { 48 switch ($input->getOption('importer')) {
diff --git a/src/Wallabag/UserBundle/Controller/ManageController.php b/src/Wallabag/UserBundle/Controller/ManageController.php
index 92ee2b41..1c5c86d4 100644
--- a/src/Wallabag/UserBundle/Controller/ManageController.php
+++ b/src/Wallabag/UserBundle/Controller/ManageController.php
@@ -4,12 +4,15 @@ namespace Wallabag\UserBundle\Controller;
4 4
5use FOS\UserBundle\Event\UserEvent; 5use FOS\UserBundle\Event\UserEvent;
6use FOS\UserBundle\FOSUserEvents; 6use FOS\UserBundle\FOSUserEvents;
7use Pagerfanta\Adapter\DoctrineORMAdapter;
8use Pagerfanta\Exception\OutOfRangeCurrentPageException;
9use Pagerfanta\Pagerfanta;
7use Symfony\Component\HttpFoundation\Request; 10use Symfony\Component\HttpFoundation\Request;
8use Symfony\Bundle\FrameworkBundle\Controller\Controller; 11use Symfony\Bundle\FrameworkBundle\Controller\Controller;
9use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; 12use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
10use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 13use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
11use Wallabag\UserBundle\Entity\User; 14use Wallabag\UserBundle\Entity\User;
12use Wallabag\CoreBundle\Entity\Config; 15use Wallabag\UserBundle\Form\SearchUserType;
13 16
14/** 17/**
15 * User controller. 18 * User controller.
@@ -17,23 +20,6 @@ use Wallabag\CoreBundle\Entity\Config;
17class ManageController extends Controller 20class ManageController extends Controller
18{ 21{
19 /** 22 /**
20 * Lists all User entities.
21 *
22 * @Route("/", name="user_index")
23 * @Method("GET")
24 */
25 public function indexAction()
26 {
27 $em = $this->getDoctrine()->getManager();
28
29 $users = $em->getRepository('WallabagUserBundle:User')->findAll();
30
31 return $this->render('WallabagUserBundle:Manage:index.html.twig', array(
32 'users' => $users,
33 ));
34 }
35
36 /**
37 * Creates a new User entity. 23 * Creates a new User entity.
38 * 24 *
39 * @Route("/new", name="user_new") 25 * @Route("/new", name="user_new")
@@ -146,4 +132,49 @@ class ManageController extends Controller
146 ->getForm() 132 ->getForm()
147 ; 133 ;
148 } 134 }
135
136 /**
137 * @param Request $request
138 * @param int $page
139 *
140 * @Route("/list/{page}", name="user_index", defaults={"page" = 1})
141 *
142 * Default parameter for page is hardcoded (in duplication of the defaults from the Route)
143 * because this controller is also called inside the layout template without any page as argument
144 *
145 * @return \Symfony\Component\HttpFoundation\Response
146 */
147 public function searchFormAction(Request $request, $page = 1)
148 {
149 $em = $this->getDoctrine()->getManager();
150 $qb = $em->getRepository('WallabagUserBundle:User')->createQueryBuilder('u');
151
152 $form = $this->createForm(SearchUserType::class);
153 $form->handleRequest($request);
154
155 if ($form->isSubmitted() && $form->isValid()) {
156 $this->get('logger')->info('searching users');
157
158 $searchTerm = (isset($request->get('search_user')['term']) ? $request->get('search_user')['term'] : '');
159
160 $qb = $em->getRepository('WallabagUserBundle:User')->getQueryBuilderForSearch($searchTerm);
161 }
162
163 $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false);
164 $pagerFanta = new Pagerfanta($pagerAdapter);
165 $pagerFanta->setMaxPerPage(50);
166
167 try {
168 $pagerFanta->setCurrentPage($page);
169 } catch (OutOfRangeCurrentPageException $e) {
170 if ($page > 1) {
171 return $this->redirect($this->generateUrl('user_index', ['page' => $pagerFanta->getNbPages()]), 302);
172 }
173 }
174
175 return $this->render('WallabagUserBundle:Manage:index.html.twig', [
176 'searchForm' => $form->createView(),
177 'users' => $pagerFanta,
178 ]);
179 }
149} 180}
diff --git a/src/Wallabag/UserBundle/Form/SearchUserType.php b/src/Wallabag/UserBundle/Form/SearchUserType.php
new file mode 100644
index 00000000..9ce46ee1
--- /dev/null
+++ b/src/Wallabag/UserBundle/Form/SearchUserType.php
@@ -0,0 +1,29 @@
1<?php
2
3namespace Wallabag\UserBundle\Form;
4
5use Symfony\Component\Form\AbstractType;
6use Symfony\Component\Form\Extension\Core\Type\TextType;
7use Symfony\Component\Form\FormBuilderInterface;
8use Symfony\Component\OptionsResolver\OptionsResolver;
9
10class SearchUserType extends AbstractType
11{
12 public function buildForm(FormBuilderInterface $builder, array $options)
13 {
14 $builder
15 ->setMethod('GET')
16 ->add('term', TextType::class, [
17 'required' => true,
18 'label' => 'user.new.form_search.term_label',
19 ])
20 ;
21 }
22
23 public function configureOptions(OptionsResolver $resolver)
24 {
25 $resolver->setDefaults([
26 'csrf_protection' => false,
27 ]);
28 }
29}
diff --git a/src/Wallabag/UserBundle/Repository/UserRepository.php b/src/Wallabag/UserBundle/Repository/UserRepository.php
index f913f52d..6adbe329 100644
--- a/src/Wallabag/UserBundle/Repository/UserRepository.php
+++ b/src/Wallabag/UserBundle/Repository/UserRepository.php
@@ -52,4 +52,17 @@ class UserRepository extends EntityRepository
52 ->getQuery() 52 ->getQuery()
53 ->getSingleScalarResult(); 53 ->getSingleScalarResult();
54 } 54 }
55
56 /**
57 * Retrieves users filtered with a search term.
58 *
59 * @param string $term
60 *
61 * @return QueryBuilder
62 */
63 public function getQueryBuilderForSearch($term)
64 {
65 return $this->createQueryBuilder('u')
66 ->andWhere('lower(u.username) LIKE lower(:term) OR lower(u.email) LIKE lower(:term) OR lower(u.name) LIKE lower(:term)')->setParameter('term', '%'.$term.'%');
67 }
55} 68}
diff --git a/src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig b/src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig
index daba29e4..15002632 100644
--- a/src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig
+++ b/src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig
@@ -7,37 +7,60 @@
7 <div class="row"> 7 <div class="row">
8 <div class="col s12"> 8 <div class="col s12">
9 <div class="card-panel"> 9 <div class="card-panel">
10 {% if users.getNbPages > 1 %}
11 {{ pagerfanta(users, 'twitter_bootstrap_translated', {'proximity': 1}) }}
12 {% endif %}
10 <div class="row"> 13 <div class="row">
11 <div class="input-field col s12"> 14 <div class="col s6">
12 <p class="help">{{ 'user.description'|trans|raw }}</p> 15 <p class="help">{{ 'user.description'|trans|raw }}</p>
16 </div>
17 <div class="col s6">
18 <div class="input-field">
19 <form name="search_users" method="GET" action="{{ path('user_index')}}">
20 {% if form_errors(searchForm) %}
21 <span class="black-text">{{ form_errors(searchForm) }}</span>
22 {% endif %}
23
24 {% if form_errors(searchForm.term) %}
25 <span class="black-text">{{ form_errors(searchForm.term) }}</span>
26 {% endif %}
13 27
14 <table class="bordered"> 28 {{ form_widget(searchForm.term, { 'attr': {'autocomplete': 'off', 'placeholder': 'user.search.placeholder'} }) }}
15 <thead> 29
16 <tr> 30 {{ form_rest(searchForm) }}
17 <th>{{ 'user.form.username_label'|trans }}</th> 31 </form>
18 <th>{{ 'user.form.email_label'|trans }}</th> 32 </div>
19 <th>{{ 'user.form.last_login_label'|trans }}</th>
20 <th>{{ 'user.list.actions'|trans }}</th>
21 </tr>
22 </thead>
23 <tbody>
24 {% for user in users %}
25 <tr>
26 <td>{{ user.username }}</td>
27 <td>{{ user.email }}</td>
28 <td>{% if user.lastLogin %}{{ user.lastLogin|date('Y-m-d H:i:s') }}{% endif %}</td>
29 <td>
30 <a href="{{ path('user_edit', { 'id': user.id }) }}">{{ 'user.list.edit_action'|trans }}</a>
31 </td>
32 </tr>
33 {% endfor %}
34 </tbody>
35 </table>
36 <br />
37 <p>
38 <a href="{{ path('user_new') }}" class="waves-effect waves-light btn">{{ 'user.list.create_new_one'|trans }}</a>
39 </p>
40 </div> 33 </div>
34
35 <table class="bordered">
36 <thead>
37 <tr>
38 <th>{{ 'user.form.username_label'|trans }}</th>
39 <th>{{ 'user.form.email_label'|trans }}</th>
40 <th>{{ 'user.form.last_login_label'|trans }}</th>
41 <th>{{ 'user.list.actions'|trans }}</th>
42 </tr>
43 </thead>
44 <tbody>
45 {% for user in users %}
46 <tr>
47 <td>{{ user.username }}</td>
48 <td>{{ user.email }}</td>
49 <td>{% if user.lastLogin %}{{ user.lastLogin|date('Y-m-d H:i:s') }}{% endif %}</td>
50 <td>
51 <a href="{{ path('user_edit', { 'id': user.id }) }}">{{ 'user.list.edit_action'|trans }}</a>
52 </td>
53 </tr>
54 {% endfor %}
55 </tbody>
56 </table>
57 <br />
58 <p>
59 <a href="{{ path('user_new') }}" class="waves-effect waves-light btn">{{ 'user.list.create_new_one'|trans }}</a>
60 </p>
61 {% if users.getNbPages > 1 %}
62 {{ pagerfanta(users, 'twitter_bootstrap_translated', {'proximity': 1}) }}
63 {% endif %}
41 </div> 64 </div>
42 </div> 65 </div>
43 </div> 66 </div>