diff options
Diffstat (limited to 'src')
60 files changed, 1355 insertions, 383 deletions
diff --git a/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php b/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php index 8d3f07ee..da361308 100644 --- a/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php +++ b/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php | |||
@@ -122,4 +122,21 @@ class AnnotationRepository extends EntityRepository | |||
122 | ->setParameter('userId', $userId) | 122 | ->setParameter('userId', $userId) |
123 | ->execute(); | 123 | ->execute(); |
124 | } | 124 | } |
125 | |||
126 | /** | ||
127 | * Find all annotations related to archived entries. | ||
128 | * | ||
129 | * @param $userId | ||
130 | * | ||
131 | * @return mixed | ||
132 | */ | ||
133 | public function findAllArchivedEntriesByUser($userId) | ||
134 | { | ||
135 | return $this->createQueryBuilder('a') | ||
136 | ->leftJoin('a.entry', 'e') | ||
137 | ->where('a.user = :userid')->setParameter(':userid', $userId) | ||
138 | ->andWhere('e.isArchived = true') | ||
139 | ->getQuery() | ||
140 | ->getResult(); | ||
141 | } | ||
125 | } | 142 | } |
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php index 54c1747c..31bb67fd 100644 --- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php +++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php | |||
@@ -5,6 +5,7 @@ namespace Wallabag\ApiBundle\Controller; | |||
5 | use Hateoas\Configuration\Route; | 5 | use Hateoas\Configuration\Route; |
6 | use Hateoas\Representation\Factory\PagerfantaFactory; | 6 | use Hateoas\Representation\Factory\PagerfantaFactory; |
7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | 7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; |
8 | use Symfony\Component\HttpKernel\Exception\HttpException; | ||
8 | use Symfony\Component\HttpFoundation\Request; | 9 | use Symfony\Component\HttpFoundation\Request; |
9 | use Symfony\Component\HttpFoundation\JsonResponse; | 10 | use Symfony\Component\HttpFoundation\JsonResponse; |
10 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | 11 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
@@ -41,12 +42,10 @@ class EntryRestController extends WallabagRestController | |||
41 | ->getRepository('WallabagCoreBundle:Entry') | 42 | ->getRepository('WallabagCoreBundle:Entry') |
42 | ->findByUrlAndUserId($url, $this->getUser()->getId()); | 43 | ->findByUrlAndUserId($url, $this->getUser()->getId()); |
43 | 44 | ||
44 | $results[$url] = false === $res ? false : true; | 45 | $results[$url] = $res instanceof Entry ? $res->getId() : false; |
45 | } | 46 | } |
46 | 47 | ||
47 | $json = $this->get('serializer')->serialize($results, 'json'); | 48 | return $this->sendResponse($results); |
48 | |||
49 | return (new JsonResponse())->setJson($json); | ||
50 | } | 49 | } |
51 | 50 | ||
52 | // let's see if it is a simple url? | 51 | // let's see if it is a simple url? |
@@ -60,11 +59,9 @@ class EntryRestController extends WallabagRestController | |||
60 | ->getRepository('WallabagCoreBundle:Entry') | 59 | ->getRepository('WallabagCoreBundle:Entry') |
61 | ->findByUrlAndUserId($url, $this->getUser()->getId()); | 60 | ->findByUrlAndUserId($url, $this->getUser()->getId()); |
62 | 61 | ||
63 | $exists = false === $res ? false : true; | 62 | $exists = $res instanceof Entry ? $res->getId() : false; |
64 | |||
65 | $json = $this->get('serializer')->serialize(['exists' => $exists], 'json'); | ||
66 | 63 | ||
67 | return (new JsonResponse())->setJson($json); | 64 | return $this->sendResponse(['exists' => $exists]); |
68 | } | 65 | } |
69 | 66 | ||
70 | /** | 67 | /** |
@@ -125,9 +122,7 @@ class EntryRestController extends WallabagRestController | |||
125 | ) | 122 | ) |
126 | ); | 123 | ); |
127 | 124 | ||
128 | $json = $this->get('serializer')->serialize($paginatedCollection, 'json'); | 125 | return $this->sendResponse($paginatedCollection); |
129 | |||
130 | return (new JsonResponse())->setJson($json); | ||
131 | } | 126 | } |
132 | 127 | ||
133 | /** | 128 | /** |
@@ -146,9 +141,7 @@ class EntryRestController extends WallabagRestController | |||
146 | $this->validateAuthentication(); | 141 | $this->validateAuthentication(); |
147 | $this->validateUserAccess($entry->getUser()->getId()); | 142 | $this->validateUserAccess($entry->getUser()->getId()); |
148 | 143 | ||
149 | $json = $this->get('serializer')->serialize($entry, 'json'); | 144 | return $this->sendResponse($entry); |
150 | |||
151 | return (new JsonResponse())->setJson($json); | ||
152 | } | 145 | } |
153 | 146 | ||
154 | /** | 147 | /** |
@@ -174,6 +167,110 @@ class EntryRestController extends WallabagRestController | |||
174 | } | 167 | } |
175 | 168 | ||
176 | /** | 169 | /** |
170 | * Handles an entries list and delete URL. | ||
171 | * | ||
172 | * @ApiDoc( | ||
173 | * parameters={ | ||
174 | * {"name"="urls", "dataType"="string", "required"=true, "format"="A JSON array of urls [{'url': 'http://...'}, {'url': 'http://...'}]", "description"="Urls (as an array) to delete."} | ||
175 | * } | ||
176 | * ) | ||
177 | * | ||
178 | * @return JsonResponse | ||
179 | */ | ||
180 | public function deleteEntriesListAction(Request $request) | ||
181 | { | ||
182 | $this->validateAuthentication(); | ||
183 | |||
184 | $urls = json_decode($request->query->get('urls', [])); | ||
185 | |||
186 | if (empty($urls)) { | ||
187 | return $this->sendResponse([]); | ||
188 | } | ||
189 | |||
190 | $results = []; | ||
191 | |||
192 | // handle multiple urls | ||
193 | foreach ($urls as $key => $url) { | ||
194 | $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId( | ||
195 | $url, | ||
196 | $this->getUser()->getId() | ||
197 | ); | ||
198 | |||
199 | $results[$key]['url'] = $url; | ||
200 | |||
201 | if (false !== $entry) { | ||
202 | $em = $this->getDoctrine()->getManager(); | ||
203 | $em->remove($entry); | ||
204 | $em->flush(); | ||
205 | |||
206 | // entry deleted, dispatch event about it! | ||
207 | $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry)); | ||
208 | } | ||
209 | |||
210 | $results[$key]['entry'] = $entry instanceof Entry ? true : false; | ||
211 | } | ||
212 | |||
213 | return $this->sendResponse($results); | ||
214 | } | ||
215 | |||
216 | /** | ||
217 | * Handles an entries list and create URL. | ||
218 | * | ||
219 | * @ApiDoc( | ||
220 | * parameters={ | ||
221 | * {"name"="urls", "dataType"="string", "required"=true, "format"="A JSON array of urls [{'url': 'http://...'}, {'url': 'http://...'}]", "description"="Urls (as an array) to create."} | ||
222 | * } | ||
223 | * ) | ||
224 | * | ||
225 | * @return JsonResponse | ||
226 | * | ||
227 | * @throws HttpException When limit is reached | ||
228 | */ | ||
229 | public function postEntriesListAction(Request $request) | ||
230 | { | ||
231 | $this->validateAuthentication(); | ||
232 | |||
233 | $urls = json_decode($request->query->get('urls', [])); | ||
234 | $results = []; | ||
235 | |||
236 | $limit = $this->container->getParameter('wallabag_core.api_limit_mass_actions'); | ||
237 | |||
238 | if (count($urls) > $limit) { | ||
239 | throw new HttpException(400, 'API limit reached'); | ||
240 | } | ||
241 | |||
242 | // handle multiple urls | ||
243 | if (!empty($urls)) { | ||
244 | foreach ($urls as $key => $url) { | ||
245 | $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId( | ||
246 | $url, | ||
247 | $this->getUser()->getId() | ||
248 | ); | ||
249 | |||
250 | $results[$key]['url'] = $url; | ||
251 | |||
252 | if (false === $entry) { | ||
253 | $entry = $this->get('wallabag_core.content_proxy')->updateEntry( | ||
254 | new Entry($this->getUser()), | ||
255 | $url | ||
256 | ); | ||
257 | } | ||
258 | |||
259 | $em = $this->getDoctrine()->getManager(); | ||
260 | $em->persist($entry); | ||
261 | $em->flush(); | ||
262 | |||
263 | $results[$key]['entry'] = $entry instanceof Entry ? $entry->getId() : false; | ||
264 | |||
265 | // entry saved, dispatch event about it! | ||
266 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | return $this->sendResponse($results); | ||
271 | } | ||
272 | |||
273 | /** | ||
177 | * Create an entry. | 274 | * Create an entry. |
178 | * | 275 | * |
179 | * @ApiDoc( | 276 | * @ApiDoc( |
@@ -221,7 +318,7 @@ class EntryRestController extends WallabagRestController | |||
221 | 318 | ||
222 | $tags = $request->request->get('tags', ''); | 319 | $tags = $request->request->get('tags', ''); |
223 | if (!empty($tags)) { | 320 | if (!empty($tags)) { |
224 | $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags); | 321 | $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags); |
225 | } | 322 | } |
226 | 323 | ||
227 | if (!is_null($isStarred)) { | 324 | if (!is_null($isStarred)) { |
@@ -239,9 +336,7 @@ class EntryRestController extends WallabagRestController | |||
239 | // entry saved, dispatch event about it! | 336 | // entry saved, dispatch event about it! |
240 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | 337 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); |
241 | 338 | ||
242 | $json = $this->get('serializer')->serialize($entry, 'json'); | 339 | return $this->sendResponse($entry); |
243 | |||
244 | return (new JsonResponse())->setJson($json); | ||
245 | } | 340 | } |
246 | 341 | ||
247 | /** | 342 | /** |
@@ -284,15 +379,13 @@ class EntryRestController extends WallabagRestController | |||
284 | 379 | ||
285 | $tags = $request->request->get('tags', ''); | 380 | $tags = $request->request->get('tags', ''); |
286 | if (!empty($tags)) { | 381 | if (!empty($tags)) { |
287 | $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags); | 382 | $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags); |
288 | } | 383 | } |
289 | 384 | ||
290 | $em = $this->getDoctrine()->getManager(); | 385 | $em = $this->getDoctrine()->getManager(); |
291 | $em->flush(); | 386 | $em->flush(); |
292 | 387 | ||
293 | $json = $this->get('serializer')->serialize($entry, 'json'); | 388 | return $this->sendResponse($entry); |
294 | |||
295 | return (new JsonResponse())->setJson($json); | ||
296 | } | 389 | } |
297 | 390 | ||
298 | /** | 391 | /** |
@@ -335,9 +428,7 @@ class EntryRestController extends WallabagRestController | |||
335 | // entry saved, dispatch event about it! | 428 | // entry saved, dispatch event about it! |
336 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | 429 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); |
337 | 430 | ||
338 | $json = $this->get('serializer')->serialize($entry, 'json'); | 431 | return $this->sendResponse($entry); |
339 | |||
340 | return (new JsonResponse())->setJson($json); | ||
341 | } | 432 | } |
342 | 433 | ||
343 | /** | 434 | /** |
@@ -363,9 +454,7 @@ class EntryRestController extends WallabagRestController | |||
363 | // entry deleted, dispatch event about it! | 454 | // entry deleted, dispatch event about it! |
364 | $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry)); | 455 | $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry)); |
365 | 456 | ||
366 | $json = $this->get('serializer')->serialize($entry, 'json'); | 457 | return $this->sendResponse($entry); |
367 | |||
368 | return (new JsonResponse())->setJson($json); | ||
369 | } | 458 | } |
370 | 459 | ||
371 | /** | 460 | /** |
@@ -384,9 +473,7 @@ class EntryRestController extends WallabagRestController | |||
384 | $this->validateAuthentication(); | 473 | $this->validateAuthentication(); |
385 | $this->validateUserAccess($entry->getUser()->getId()); | 474 | $this->validateUserAccess($entry->getUser()->getId()); |
386 | 475 | ||
387 | $json = $this->get('serializer')->serialize($entry->getTags(), 'json'); | 476 | return $this->sendResponse($entry->getTags()); |
388 | |||
389 | return (new JsonResponse())->setJson($json); | ||
390 | } | 477 | } |
391 | 478 | ||
392 | /** | 479 | /** |
@@ -410,16 +497,14 @@ class EntryRestController extends WallabagRestController | |||
410 | 497 | ||
411 | $tags = $request->request->get('tags', ''); | 498 | $tags = $request->request->get('tags', ''); |
412 | if (!empty($tags)) { | 499 | if (!empty($tags)) { |
413 | $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags); | 500 | $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags); |
414 | } | 501 | } |
415 | 502 | ||
416 | $em = $this->getDoctrine()->getManager(); | 503 | $em = $this->getDoctrine()->getManager(); |
417 | $em->persist($entry); | 504 | $em->persist($entry); |
418 | $em->flush(); | 505 | $em->flush(); |
419 | 506 | ||
420 | $json = $this->get('serializer')->serialize($entry, 'json'); | 507 | return $this->sendResponse($entry); |
421 | |||
422 | return (new JsonResponse())->setJson($json); | ||
423 | } | 508 | } |
424 | 509 | ||
425 | /** | 510 | /** |
@@ -444,7 +529,124 @@ class EntryRestController extends WallabagRestController | |||
444 | $em->persist($entry); | 529 | $em->persist($entry); |
445 | $em->flush(); | 530 | $em->flush(); |
446 | 531 | ||
447 | $json = $this->get('serializer')->serialize($entry, 'json'); | 532 | return $this->sendResponse($entry); |
533 | } | ||
534 | |||
535 | /** | ||
536 | * Handles an entries list delete tags from them. | ||
537 | * | ||
538 | * @ApiDoc( | ||
539 | * parameters={ | ||
540 | * {"name"="list", "dataType"="string", "required"=true, "format"="A JSON array of urls [{'url': 'http://...','tags': 'tag1, tag2'}, {'url': 'http://...','tags': 'tag1, tag2'}]", "description"="Urls (as an array) to handle."} | ||
541 | * } | ||
542 | * ) | ||
543 | * | ||
544 | * @return JsonResponse | ||
545 | */ | ||
546 | public function deleteEntriesTagsListAction(Request $request) | ||
547 | { | ||
548 | $this->validateAuthentication(); | ||
549 | |||
550 | $list = json_decode($request->query->get('list', [])); | ||
551 | |||
552 | if (empty($list)) { | ||
553 | return $this->sendResponse([]); | ||
554 | } | ||
555 | |||
556 | // handle multiple urls | ||
557 | $results = []; | ||
558 | |||
559 | foreach ($list as $key => $element) { | ||
560 | $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId( | ||
561 | $element->url, | ||
562 | $this->getUser()->getId() | ||
563 | ); | ||
564 | |||
565 | $results[$key]['url'] = $element->url; | ||
566 | $results[$key]['entry'] = $entry instanceof Entry ? $entry->getId() : false; | ||
567 | |||
568 | $tags = $element->tags; | ||
569 | |||
570 | if (false !== $entry && !(empty($tags))) { | ||
571 | $tags = explode(',', $tags); | ||
572 | foreach ($tags as $label) { | ||
573 | $label = trim($label); | ||
574 | |||
575 | $tag = $this->getDoctrine() | ||
576 | ->getRepository('WallabagCoreBundle:Tag') | ||
577 | ->findOneByLabel($label); | ||
578 | |||
579 | if (false !== $tag) { | ||
580 | $entry->removeTag($tag); | ||
581 | } | ||
582 | } | ||
583 | |||
584 | $em = $this->getDoctrine()->getManager(); | ||
585 | $em->persist($entry); | ||
586 | $em->flush(); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | return $this->sendResponse($results); | ||
591 | } | ||
592 | |||
593 | /** | ||
594 | * Handles an entries list and add tags to them. | ||
595 | * | ||
596 | * @ApiDoc( | ||
597 | * parameters={ | ||
598 | * {"name"="list", "dataType"="string", "required"=true, "format"="A JSON array of urls [{'url': 'http://...','tags': 'tag1, tag2'}, {'url': 'http://...','tags': 'tag1, tag2'}]", "description"="Urls (as an array) to handle."} | ||
599 | * } | ||
600 | * ) | ||
601 | * | ||
602 | * @return JsonResponse | ||
603 | */ | ||
604 | public function postEntriesTagsListAction(Request $request) | ||
605 | { | ||
606 | $this->validateAuthentication(); | ||
607 | |||
608 | $list = json_decode($request->query->get('list', [])); | ||
609 | |||
610 | if (empty($list)) { | ||
611 | return $this->sendResponse([]); | ||
612 | } | ||
613 | |||
614 | $results = []; | ||
615 | |||
616 | // handle multiple urls | ||
617 | foreach ($list as $key => $element) { | ||
618 | $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId( | ||
619 | $element->url, | ||
620 | $this->getUser()->getId() | ||
621 | ); | ||
622 | |||
623 | $results[$key]['url'] = $element->url; | ||
624 | $results[$key]['entry'] = $entry instanceof Entry ? $entry->getId() : false; | ||
625 | |||
626 | $tags = $element->tags; | ||
627 | |||
628 | if (false !== $entry && !(empty($tags))) { | ||
629 | $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags); | ||
630 | |||
631 | $em = $this->getDoctrine()->getManager(); | ||
632 | $em->persist($entry); | ||
633 | $em->flush(); | ||
634 | } | ||
635 | } | ||
636 | |||
637 | return $this->sendResponse($results); | ||
638 | } | ||
639 | |||
640 | /** | ||
641 | * Shortcut to send data serialized in json. | ||
642 | * | ||
643 | * @param mixed $data | ||
644 | * | ||
645 | * @return JsonResponse | ||
646 | */ | ||
647 | private function sendResponse($data) | ||
648 | { | ||
649 | $json = $this->get('serializer')->serialize($data, 'json'); | ||
448 | 650 | ||
449 | return (new JsonResponse())->setJson($json); | 651 | return (new JsonResponse())->setJson($json); |
450 | } | 652 | } |
diff --git a/src/Wallabag/ApiBundle/Controller/TagRestController.php b/src/Wallabag/ApiBundle/Controller/TagRestController.php index bc6d4e64..354187a0 100644 --- a/src/Wallabag/ApiBundle/Controller/TagRestController.php +++ b/src/Wallabag/ApiBundle/Controller/TagRestController.php | |||
@@ -31,7 +31,7 @@ class TagRestController extends WallabagRestController | |||
31 | } | 31 | } |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * Permanently remove one tag from **every** entry. | 34 | * Permanently remove one tag from **every** entry by passing the Tag label. |
35 | * | 35 | * |
36 | * @ApiDoc( | 36 | * @ApiDoc( |
37 | * requirements={ | 37 | * requirements={ |
@@ -44,7 +44,7 @@ class TagRestController extends WallabagRestController | |||
44 | public function deleteTagLabelAction(Request $request) | 44 | public function deleteTagLabelAction(Request $request) |
45 | { | 45 | { |
46 | $this->validateAuthentication(); | 46 | $this->validateAuthentication(); |
47 | $label = $request->request->get('tag', ''); | 47 | $label = $request->get('tag', ''); |
48 | 48 | ||
49 | $tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($label); | 49 | $tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($label); |
50 | 50 | ||
@@ -78,7 +78,7 @@ class TagRestController extends WallabagRestController | |||
78 | { | 78 | { |
79 | $this->validateAuthentication(); | 79 | $this->validateAuthentication(); |
80 | 80 | ||
81 | $tagsLabels = $request->request->get('tags', ''); | 81 | $tagsLabels = $request->get('tags', ''); |
82 | 82 | ||
83 | $tags = []; | 83 | $tags = []; |
84 | 84 | ||
@@ -106,7 +106,7 @@ class TagRestController extends WallabagRestController | |||
106 | } | 106 | } |
107 | 107 | ||
108 | /** | 108 | /** |
109 | * Permanently remove one tag from **every** entry. | 109 | * Permanently remove one tag from **every** entry by passing the Tag ID. |
110 | * | 110 | * |
111 | * @ApiDoc( | 111 | * @ApiDoc( |
112 | * requirements={ | 112 | * requirements={ |
diff --git a/src/Wallabag/CoreBundle/Command/CleanDuplicatesCommand.php b/src/Wallabag/CoreBundle/Command/CleanDuplicatesCommand.php new file mode 100644 index 00000000..65f35d8e --- /dev/null +++ b/src/Wallabag/CoreBundle/Command/CleanDuplicatesCommand.php | |||
@@ -0,0 +1,119 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Command; | ||
4 | |||
5 | use Doctrine\ORM\NoResultException; | ||
6 | use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; | ||
7 | use Symfony\Component\Console\Input\InputArgument; | ||
8 | use Symfony\Component\Console\Input\InputInterface; | ||
9 | use Symfony\Component\Console\Output\OutputInterface; | ||
10 | use Wallabag\CoreBundle\Entity\Entry; | ||
11 | use Wallabag\UserBundle\Entity\User; | ||
12 | |||
13 | class CleanDuplicatesCommand extends ContainerAwareCommand | ||
14 | { | ||
15 | /** @var OutputInterface */ | ||
16 | protected $output; | ||
17 | |||
18 | protected $duplicates = 0; | ||
19 | |||
20 | protected function configure() | ||
21 | { | ||
22 | $this | ||
23 | ->setName('wallabag:clean-duplicates') | ||
24 | ->setDescription('Cleans the database for duplicates') | ||
25 | ->setHelp('This command helps you to clean your articles list in case of duplicates') | ||
26 | ->addArgument( | ||
27 | 'username', | ||
28 | InputArgument::OPTIONAL, | ||
29 | 'User to clean' | ||
30 | ); | ||
31 | } | ||
32 | |||
33 | protected function execute(InputInterface $input, OutputInterface $output) | ||
34 | { | ||
35 | $this->output = $output; | ||
36 | |||
37 | $username = $input->getArgument('username'); | ||
38 | |||
39 | if ($username) { | ||
40 | try { | ||
41 | $user = $this->getUser($username); | ||
42 | $this->cleanDuplicates($user); | ||
43 | } catch (NoResultException $e) { | ||
44 | $output->writeln(sprintf('<error>User "%s" not found.</error>', $username)); | ||
45 | |||
46 | return 1; | ||
47 | } | ||
48 | } else { | ||
49 | $users = $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findAll(); | ||
50 | |||
51 | $output->writeln(sprintf('Cleaning through %d user accounts', count($users))); | ||
52 | |||
53 | foreach ($users as $user) { | ||
54 | $output->writeln(sprintf('Processing user %s', $user->getUsername())); | ||
55 | $this->cleanDuplicates($user); | ||
56 | } | ||
57 | $output->writeln(sprintf('Finished cleaning. %d duplicates found in total', $this->duplicates)); | ||
58 | } | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * @param User $user | ||
65 | */ | ||
66 | private function cleanDuplicates(User $user) | ||
67 | { | ||
68 | $em = $this->getContainer()->get('doctrine.orm.entity_manager'); | ||
69 | $repo = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry'); | ||
70 | |||
71 | $entries = $repo->getAllEntriesIdAndUrl($user->getId()); | ||
72 | |||
73 | $duplicatesCount = 0; | ||
74 | $urls = []; | ||
75 | foreach ($entries as $entry) { | ||
76 | $url = $this->similarUrl($entry['url']); | ||
77 | |||
78 | /* @var $entry Entry */ | ||
79 | if (in_array($url, $urls)) { | ||
80 | ++$duplicatesCount; | ||
81 | |||
82 | $em->remove($repo->find($entry['id'])); | ||
83 | $em->flush(); // Flushing at the end of the loop would require the instance not being online | ||
84 | } else { | ||
85 | $urls[] = $entry['url']; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | $this->duplicates += $duplicatesCount; | ||
90 | |||
91 | $this->output->writeln(sprintf('Cleaned %d duplicates for user %s', $duplicatesCount, $user->getUserName())); | ||
92 | } | ||
93 | |||
94 | private function similarUrl($url) | ||
95 | { | ||
96 | if (in_array(substr($url, -1), ['/', '#'])) { // get rid of "/" and "#" and the end of urls | ||
97 | return substr($url, 0, strlen($url)); | ||
98 | } | ||
99 | |||
100 | return $url; | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * Fetches a user from its username. | ||
105 | * | ||
106 | * @param string $username | ||
107 | * | ||
108 | * @return \Wallabag\UserBundle\Entity\User | ||
109 | */ | ||
110 | private function getUser($username) | ||
111 | { | ||
112 | return $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findOneByUserName($username); | ||
113 | } | ||
114 | |||
115 | private function getDoctrine() | ||
116 | { | ||
117 | return $this->getContainer()->get('doctrine'); | ||
118 | } | ||
119 | } | ||
diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php index f0738b91..0d9364f6 100644 --- a/src/Wallabag/CoreBundle/Command/InstallCommand.php +++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php | |||
@@ -63,6 +63,7 @@ class InstallCommand extends ContainerAwareCommand | |||
63 | ->setupDatabase() | 63 | ->setupDatabase() |
64 | ->setupAdmin() | 64 | ->setupAdmin() |
65 | ->setupConfig() | 65 | ->setupConfig() |
66 | ->runMigrations() | ||
66 | ; | 67 | ; |
67 | 68 | ||
68 | $output->writeln('<info>wallabag has been successfully installed.</info>'); | 69 | $output->writeln('<info>wallabag has been successfully installed.</info>'); |
@@ -71,7 +72,7 @@ class InstallCommand extends ContainerAwareCommand | |||
71 | 72 | ||
72 | protected function checkRequirements() | 73 | protected function checkRequirements() |
73 | { | 74 | { |
74 | $this->defaultOutput->writeln('<info><comment>Step 1 of 4.</comment> Checking system requirements.</info>'); | 75 | $this->defaultOutput->writeln('<info><comment>Step 1 of 5.</comment> Checking system requirements.</info>'); |
75 | $doctrineManager = $this->getContainer()->get('doctrine')->getManager(); | 76 | $doctrineManager = $this->getContainer()->get('doctrine')->getManager(); |
76 | 77 | ||
77 | $rows = []; | 78 | $rows = []; |
@@ -175,11 +176,11 @@ class InstallCommand extends ContainerAwareCommand | |||
175 | 176 | ||
176 | protected function setupDatabase() | 177 | protected function setupDatabase() |
177 | { | 178 | { |
178 | $this->defaultOutput->writeln('<info><comment>Step 2 of 4.</comment> Setting up database.</info>'); | 179 | $this->defaultOutput->writeln('<info><comment>Step 2 of 5.</comment> Setting up database.</info>'); |
179 | 180 | ||
180 | // user want to reset everything? Don't care about what is already here | 181 | // user want to reset everything? Don't care about what is already here |
181 | if (true === $this->defaultInput->getOption('reset')) { | 182 | if (true === $this->defaultInput->getOption('reset')) { |
182 | $this->defaultOutput->writeln('Droping database, creating database and schema, clearing the cache'); | 183 | $this->defaultOutput->writeln('Dropping database, creating database and schema, clearing the cache'); |
183 | 184 | ||
184 | $this | 185 | $this |
185 | ->runCommand('doctrine:database:drop', ['--force' => true]) | 186 | ->runCommand('doctrine:database:drop', ['--force' => true]) |
@@ -211,7 +212,7 @@ class InstallCommand extends ContainerAwareCommand | |||
211 | $question = new ConfirmationQuestion('It appears that your database already exists. Would you like to reset it? (y/N)', false); | 212 | $question = new ConfirmationQuestion('It appears that your database already exists. Would you like to reset it? (y/N)', false); |
212 | 213 | ||
213 | if ($questionHelper->ask($this->defaultInput, $this->defaultOutput, $question)) { | 214 | if ($questionHelper->ask($this->defaultInput, $this->defaultOutput, $question)) { |
214 | $this->defaultOutput->writeln('Droping database, creating database and schema'); | 215 | $this->defaultOutput->writeln('Dropping database, creating database and schema'); |
215 | 216 | ||
216 | $this | 217 | $this |
217 | ->runCommand('doctrine:database:drop', ['--force' => true]) | 218 | ->runCommand('doctrine:database:drop', ['--force' => true]) |
@@ -221,7 +222,7 @@ class InstallCommand extends ContainerAwareCommand | |||
221 | } elseif ($this->isSchemaPresent()) { | 222 | } elseif ($this->isSchemaPresent()) { |
222 | $question = new ConfirmationQuestion('Seems like your database contains schema. Do you want to reset it? (y/N)', false); | 223 | $question = new ConfirmationQuestion('Seems like your database contains schema. Do you want to reset it? (y/N)', false); |
223 | if ($questionHelper->ask($this->defaultInput, $this->defaultOutput, $question)) { | 224 | if ($questionHelper->ask($this->defaultInput, $this->defaultOutput, $question)) { |
224 | $this->defaultOutput->writeln('Droping schema and creating schema'); | 225 | $this->defaultOutput->writeln('Dropping schema and creating schema'); |
225 | 226 | ||
226 | $this | 227 | $this |
227 | ->runCommand('doctrine:schema:drop', ['--force' => true]) | 228 | ->runCommand('doctrine:schema:drop', ['--force' => true]) |
@@ -246,7 +247,7 @@ class InstallCommand extends ContainerAwareCommand | |||
246 | 247 | ||
247 | protected function setupAdmin() | 248 | protected function setupAdmin() |
248 | { | 249 | { |
249 | $this->defaultOutput->writeln('<info><comment>Step 3 of 4.</comment> Administration setup.</info>'); | 250 | $this->defaultOutput->writeln('<info><comment>Step 3 of 5.</comment> Administration setup.</info>'); |
250 | 251 | ||
251 | $questionHelper = $this->getHelperSet()->get('question'); | 252 | $questionHelper = $this->getHelperSet()->get('question'); |
252 | $question = new ConfirmationQuestion('Would you like to create a new admin user (recommended) ? (Y/n)', true); | 253 | $question = new ConfirmationQuestion('Would you like to create a new admin user (recommended) ? (Y/n)', true); |
@@ -285,7 +286,7 @@ class InstallCommand extends ContainerAwareCommand | |||
285 | 286 | ||
286 | protected function setupConfig() | 287 | protected function setupConfig() |
287 | { | 288 | { |
288 | $this->defaultOutput->writeln('<info><comment>Step 4 of 4.</comment> Config setup.</info>'); | 289 | $this->defaultOutput->writeln('<info><comment>Step 4 of 5.</comment> Config setup.</info>'); |
289 | $em = $this->getContainer()->get('doctrine.orm.entity_manager'); | 290 | $em = $this->getContainer()->get('doctrine.orm.entity_manager'); |
290 | 291 | ||
291 | // cleanup before insert new stuff | 292 | // cleanup before insert new stuff |
@@ -333,6 +334,16 @@ class InstallCommand extends ContainerAwareCommand | |||
333 | 'section' => 'entry', | 334 | 'section' => 'entry', |
334 | ], | 335 | ], |
335 | [ | 336 | [ |
337 | 'name' => 'share_scuttle', | ||
338 | 'value' => '1', | ||
339 | 'section' => 'entry', | ||
340 | ], | ||
341 | [ | ||
342 | 'name' => 'scuttle_url', | ||
343 | 'value' => 'http://scuttle.org', | ||
344 | 'section' => 'entry', | ||
345 | ], | ||
346 | [ | ||
336 | 'name' => 'share_mail', | 347 | 'name' => 'share_mail', |
337 | 'value' => '1', | 348 | 'value' => '1', |
338 | 'section' => 'entry', | 349 | 'section' => 'entry', |
@@ -454,6 +465,14 @@ class InstallCommand extends ContainerAwareCommand | |||
454 | return $this; | 465 | return $this; |
455 | } | 466 | } |
456 | 467 | ||
468 | protected function runMigrations() | ||
469 | { | ||
470 | $this->defaultOutput->writeln('<info><comment>Step 5 of 5.</comment> Run migrations.</info>'); | ||
471 | |||
472 | $this | ||
473 | ->runCommand('doctrine:migrations:migrate', ['--no-interaction' => true]); | ||
474 | } | ||
475 | |||
457 | /** | 476 | /** |
458 | * Run a command. | 477 | * Run a command. |
459 | * | 478 | * |
diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php index 907bf78e..1a80cc1a 100644 --- a/src/Wallabag/CoreBundle/Controller/ConfigController.php +++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php | |||
@@ -248,7 +248,7 @@ class ConfigController extends Controller | |||
248 | break; | 248 | break; |
249 | 249 | ||
250 | case 'entries': | 250 | case 'entries': |
251 | // SQLite doesn't care about cascading remove, so we need to manually remove associated stuf | 251 | // SQLite doesn't care about cascading remove, so we need to manually remove associated stuff |
252 | // otherwise they won't be removed ... | 252 | // otherwise they won't be removed ... |
253 | if ($this->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) { | 253 | if ($this->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) { |
254 | $this->getDoctrine()->getRepository('WallabagAnnotationBundle:Annotation')->removeAllByUserId($this->getUser()->getId()); | 254 | $this->getDoctrine()->getRepository('WallabagAnnotationBundle:Annotation')->removeAllByUserId($this->getUser()->getId()); |
@@ -260,6 +260,19 @@ class ConfigController extends Controller | |||
260 | $this->getDoctrine() | 260 | $this->getDoctrine() |
261 | ->getRepository('WallabagCoreBundle:Entry') | 261 | ->getRepository('WallabagCoreBundle:Entry') |
262 | ->removeAllByUserId($this->getUser()->getId()); | 262 | ->removeAllByUserId($this->getUser()->getId()); |
263 | break; | ||
264 | case 'archived': | ||
265 | if ($this->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) { | ||
266 | $this->removeAnnotationsForArchivedByUserId($this->getUser()->getId()); | ||
267 | } | ||
268 | |||
269 | // manually remove tags to avoid orphan tag | ||
270 | $this->removeTagsForArchivedByUserId($this->getUser()->getId()); | ||
271 | |||
272 | $this->getDoctrine() | ||
273 | ->getRepository('WallabagCoreBundle:Entry') | ||
274 | ->removeArchivedByUserId($this->getUser()->getId()); | ||
275 | break; | ||
263 | } | 276 | } |
264 | 277 | ||
265 | $this->get('session')->getFlashBag()->add( | 278 | $this->get('session')->getFlashBag()->add( |
@@ -271,14 +284,13 @@ class ConfigController extends Controller | |||
271 | } | 284 | } |
272 | 285 | ||
273 | /** | 286 | /** |
274 | * Remove all tags for a given user and cleanup orphan tags. | 287 | * Remove all tags for given tags and a given user and cleanup orphan tags. |
275 | * | 288 | * |
276 | * @param int $userId | 289 | * @param array $tags |
290 | * @param int $userId | ||
277 | */ | 291 | */ |
278 | private function removeAllTagsByUserId($userId) | 292 | private function removeAllTagsByStatusAndUserId($tags, $userId) |
279 | { | 293 | { |
280 | $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findAllTags($userId); | ||
281 | |||
282 | if (empty($tags)) { | 294 | if (empty($tags)) { |
283 | return; | 295 | return; |
284 | } | 296 | } |
@@ -300,6 +312,43 @@ class ConfigController extends Controller | |||
300 | } | 312 | } |
301 | 313 | ||
302 | /** | 314 | /** |
315 | * Remove all tags for a given user and cleanup orphan tags. | ||
316 | * | ||
317 | * @param int $userId | ||
318 | */ | ||
319 | private function removeAllTagsByUserId($userId) | ||
320 | { | ||
321 | $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findAllTags($userId); | ||
322 | $this->removeAllTagsByStatusAndUserId($tags, $userId); | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * Remove all tags for a given user and cleanup orphan tags. | ||
327 | * | ||
328 | * @param int $userId | ||
329 | */ | ||
330 | private function removeTagsForArchivedByUserId($userId) | ||
331 | { | ||
332 | $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findForArchivedArticlesByUser($userId); | ||
333 | $this->removeAllTagsByStatusAndUserId($tags, $userId); | ||
334 | } | ||
335 | |||
336 | private function removeAnnotationsForArchivedByUserId($userId) | ||
337 | { | ||
338 | $em = $this->getDoctrine()->getManager(); | ||
339 | |||
340 | $archivedEntriesAnnotations = $this->getDoctrine() | ||
341 | ->getRepository('WallabagAnnotationBundle:Annotation') | ||
342 | ->findAllArchivedEntriesByUser($userId); | ||
343 | |||
344 | foreach ($archivedEntriesAnnotations as $archivedEntriesAnnotation) { | ||
345 | $em->remove($archivedEntriesAnnotation); | ||
346 | } | ||
347 | |||
348 | $em->flush(); | ||
349 | } | ||
350 | |||
351 | /** | ||
303 | * Validate that a rule can be edited/deleted by the current user. | 352 | * Validate that a rule can be edited/deleted by the current user. |
304 | * | 353 | * |
305 | * @param TaggingRule $rule | 354 | * @param TaggingRule $rule |
diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php index f7398e69..8d2ac6d4 100644 --- a/src/Wallabag/CoreBundle/Controller/EntryController.php +++ b/src/Wallabag/CoreBundle/Controller/EntryController.php | |||
@@ -227,7 +227,7 @@ class EntryController extends Controller | |||
227 | public function showUnreadAction(Request $request, $page) | 227 | public function showUnreadAction(Request $request, $page) |
228 | { | 228 | { |
229 | // load the quickstart if no entry in database | 229 | // load the quickstart if no entry in database |
230 | if ($page == 1 && $this->get('wallabag_core.entry_repository')->countAllEntriesByUsername($this->getUser()->getId()) == 0) { | 230 | if ($page == 1 && $this->get('wallabag_core.entry_repository')->countAllEntriesByUser($this->getUser()->getId()) == 0) { |
231 | return $this->redirect($this->generateUrl('quickstart')); | 231 | return $this->redirect($this->generateUrl('quickstart')); |
232 | } | 232 | } |
233 | 233 | ||
diff --git a/src/Wallabag/CoreBundle/Controller/TagController.php b/src/Wallabag/CoreBundle/Controller/TagController.php index 8a093289..fb6a720b 100644 --- a/src/Wallabag/CoreBundle/Controller/TagController.php +++ b/src/Wallabag/CoreBundle/Controller/TagController.php | |||
@@ -28,7 +28,7 @@ class TagController extends Controller | |||
28 | $form->handleRequest($request); | 28 | $form->handleRequest($request); |
29 | 29 | ||
30 | if ($form->isSubmitted() && $form->isValid()) { | 30 | if ($form->isSubmitted() && $form->isValid()) { |
31 | $this->get('wallabag_core.content_proxy')->assignTagsToEntry( | 31 | $this->get('wallabag_core.tags_assigner')->assignTagsToEntry( |
32 | $entry, | 32 | $entry, |
33 | $form->get('label')->getData() | 33 | $form->get('label')->getData() |
34 | ); | 34 | ); |
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php index a723656e..aaeb9ee9 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php | |||
@@ -51,11 +51,21 @@ class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface | |||
51 | 'section' => 'entry', | 51 | 'section' => 'entry', |
52 | ], | 52 | ], |
53 | [ | 53 | [ |
54 | 'name' => 'share_scuttle', | ||
55 | 'value' => '1', | ||
56 | 'section' => 'entry', | ||
57 | ], | ||
58 | [ | ||
54 | 'name' => 'shaarli_url', | 59 | 'name' => 'shaarli_url', |
55 | 'value' => 'http://myshaarli.com', | 60 | 'value' => 'http://myshaarli.com', |
56 | 'section' => 'entry', | 61 | 'section' => 'entry', |
57 | ], | 62 | ], |
58 | [ | 63 | [ |
64 | 'name' => 'scuttle_url', | ||
65 | 'value' => 'http://scuttle.org', | ||
66 | 'section' => 'entry', | ||
67 | ], | ||
68 | [ | ||
59 | 'name' => 'share_mail', | 69 | 'name' => 'share_mail', |
60 | 'value' => '1', | 70 | 'value' => '1', |
61 | 'section' => 'entry', | 71 | 'section' => 'entry', |
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/DependencyInjection/Configuration.php b/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php index 006a18c3..75b37729 100644 --- a/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php +++ b/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php | |||
@@ -47,6 +47,9 @@ class Configuration implements ConfigurationInterface | |||
47 | ->scalarNode('list_mode') | 47 | ->scalarNode('list_mode') |
48 | ->defaultValue(1) | 48 | ->defaultValue(1) |
49 | ->end() | 49 | ->end() |
50 | ->scalarNode('api_limit_mass_actions') | ||
51 | ->defaultValue(10) | ||
52 | ->end() | ||
50 | ->end() | 53 | ->end() |
51 | ; | 54 | ; |
52 | 55 | ||
diff --git a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php index aa9ee339..c075c19f 100644 --- a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php +++ b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php | |||
@@ -26,6 +26,7 @@ class WallabagCoreExtension extends Extension | |||
26 | $container->setParameter('wallabag_core.action_mark_as_read', $config['action_mark_as_read']); | 26 | $container->setParameter('wallabag_core.action_mark_as_read', $config['action_mark_as_read']); |
27 | $container->setParameter('wallabag_core.list_mode', $config['list_mode']); | 27 | $container->setParameter('wallabag_core.list_mode', $config['list_mode']); |
28 | $container->setParameter('wallabag_core.fetching_error_message', $config['fetching_error_message']); | 28 | $container->setParameter('wallabag_core.fetching_error_message', $config['fetching_error_message']); |
29 | $container->setParameter('wallabag_core.api_limit_mass_actions', $config['api_limit_mass_actions']); | ||
29 | 30 | ||
30 | $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); | 31 | $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); |
31 | $loader->load('services.yml'); | 32 | $loader->load('services.yml'); |
diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index 7276b437..08a67c34 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php | |||
@@ -122,6 +122,24 @@ class Entry | |||
122 | private $updatedAt; | 122 | private $updatedAt; |
123 | 123 | ||
124 | /** | 124 | /** |
125 | * @var \DateTime | ||
126 | * | ||
127 | * @ORM\Column(name="published_at", type="datetime", nullable=true) | ||
128 | * | ||
129 | * @Groups({"entries_for_user", "export_all"}) | ||
130 | */ | ||
131 | private $publishedAt; | ||
132 | |||
133 | /** | ||
134 | * @var array | ||
135 | * | ||
136 | * @ORM\Column(name="published_by", type="array", nullable=true) | ||
137 | * | ||
138 | * @Groups({"entries_for_user", "export_all"}) | ||
139 | */ | ||
140 | private $publishedBy; | ||
141 | |||
142 | /** | ||
125 | * @ORM\OneToMany(targetEntity="Wallabag\AnnotationBundle\Entity\Annotation", mappedBy="entry", cascade={"persist", "remove"}) | 143 | * @ORM\OneToMany(targetEntity="Wallabag\AnnotationBundle\Entity\Annotation", mappedBy="entry", cascade={"persist", "remove"}) |
126 | * @ORM\JoinTable | 144 | * @ORM\JoinTable |
127 | * | 145 | * |
@@ -175,22 +193,22 @@ class Entry | |||
175 | private $previewPicture; | 193 | private $previewPicture; |
176 | 194 | ||
177 | /** | 195 | /** |
178 | * @var bool | 196 | * @var string |
179 | * | 197 | * |
180 | * @ORM\Column(name="is_public", type="boolean", nullable=true, options={"default" = false}) | 198 | * @ORM\Column(name="http_status", type="string", length=3, nullable=true) |
181 | * | 199 | * |
182 | * @Groups({"export_all"}) | 200 | * @Groups({"entries_for_user", "export_all"}) |
183 | */ | 201 | */ |
184 | private $isPublic; | 202 | private $httpStatus; |
185 | 203 | ||
186 | /** | 204 | /** |
187 | * @var string | 205 | * @var array |
188 | * | 206 | * |
189 | * @ORM\Column(name="http_status", type="string", length=3, nullable=true) | 207 | * @ORM\Column(name="headers", type="array", nullable=true) |
190 | * | 208 | * |
191 | * @Groups({"entries_for_user", "export_all"}) | 209 | * @Groups({"entries_for_user", "export_all"}) |
192 | */ | 210 | */ |
193 | private $httpStatus; | 211 | private $headers; |
194 | 212 | ||
195 | /** | 213 | /** |
196 | * @Exclude | 214 | * @Exclude |
@@ -532,22 +550,6 @@ class Entry | |||
532 | } | 550 | } |
533 | 551 | ||
534 | /** | 552 | /** |
535 | * @return bool | ||
536 | */ | ||
537 | public function isPublic() | ||
538 | { | ||
539 | return $this->isPublic; | ||
540 | } | ||
541 | |||
542 | /** | ||
543 | * @param bool $isPublic | ||
544 | */ | ||
545 | public function setIsPublic($isPublic) | ||
546 | { | ||
547 | $this->isPublic = $isPublic; | ||
548 | } | ||
549 | |||
550 | /** | ||
551 | * @return ArrayCollection<Tag> | 553 | * @return ArrayCollection<Tag> |
552 | */ | 554 | */ |
553 | public function getTags() | 555 | public function getTags() |
@@ -701,4 +703,64 @@ class Entry | |||
701 | 703 | ||
702 | return $this; | 704 | return $this; |
703 | } | 705 | } |
706 | |||
707 | /** | ||
708 | * @return \Datetime | ||
709 | */ | ||
710 | public function getPublishedAt() | ||
711 | { | ||
712 | return $this->publishedAt; | ||
713 | } | ||
714 | |||
715 | /** | ||
716 | * @param \Datetime $publishedAt | ||
717 | * | ||
718 | * @return Entry | ||
719 | */ | ||
720 | public function setPublishedAt(\Datetime $publishedAt) | ||
721 | { | ||
722 | $this->publishedAt = $publishedAt; | ||
723 | |||
724 | return $this; | ||
725 | } | ||
726 | |||
727 | /** | ||
728 | * @return array | ||
729 | */ | ||
730 | public function getPublishedBy() | ||
731 | { | ||
732 | return $this->publishedBy; | ||
733 | } | ||
734 | |||
735 | /** | ||
736 | * @param array $publishedBy | ||
737 | * | ||
738 | * @return Entry | ||
739 | */ | ||
740 | public function setPublishedBy($publishedBy) | ||
741 | { | ||
742 | $this->publishedBy = $publishedBy; | ||
743 | |||
744 | return $this; | ||
745 | } | ||
746 | |||
747 | /** | ||
748 | * @return array | ||
749 | */ | ||
750 | public function getHeaders() | ||
751 | { | ||
752 | return $this->headers; | ||
753 | } | ||
754 | |||
755 | /** | ||
756 | * @param array $headers | ||
757 | * | ||
758 | * @return Entry | ||
759 | */ | ||
760 | public function setHeaders($headers) | ||
761 | { | ||
762 | $this->headers = $headers; | ||
763 | |||
764 | return $this; | ||
765 | } | ||
704 | } | 766 | } |
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/Form/Type/EditEntryType.php b/src/Wallabag/CoreBundle/Form/Type/EditEntryType.php index c3715646..1627cc44 100644 --- a/src/Wallabag/CoreBundle/Form/Type/EditEntryType.php +++ b/src/Wallabag/CoreBundle/Form/Type/EditEntryType.php | |||
@@ -3,7 +3,6 @@ | |||
3 | namespace Wallabag\CoreBundle\Form\Type; | 3 | namespace Wallabag\CoreBundle\Form\Type; |
4 | 4 | ||
5 | use Symfony\Component\Form\AbstractType; | 5 | use Symfony\Component\Form\AbstractType; |
6 | use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | ||
7 | use Symfony\Component\Form\Extension\Core\Type\SubmitType; | 6 | use Symfony\Component\Form\Extension\Core\Type\SubmitType; |
8 | use Symfony\Component\Form\Extension\Core\Type\TextType; | 7 | use Symfony\Component\Form\Extension\Core\Type\TextType; |
9 | use Symfony\Component\Form\FormBuilderInterface; | 8 | use Symfony\Component\Form\FormBuilderInterface; |
@@ -18,11 +17,6 @@ class EditEntryType extends AbstractType | |||
18 | 'required' => true, | 17 | 'required' => true, |
19 | 'label' => 'entry.edit.title_label', | 18 | 'label' => 'entry.edit.title_label', |
20 | ]) | 19 | ]) |
21 | ->add('is_public', CheckboxType::class, [ | ||
22 | 'required' => false, | ||
23 | 'label' => 'entry.edit.is_public_label', | ||
24 | 'property_path' => 'isPublic', | ||
25 | ]) | ||
26 | ->add('url', TextType::class, [ | 20 | ->add('url', TextType::class, [ |
27 | 'disabled' => true, | 21 | 'disabled' => true, |
28 | 'required' => false, | 22 | 'required' => false, |
diff --git a/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php b/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php index 6d4129e8..c712bb26 100644 --- a/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php +++ b/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php | |||
@@ -6,28 +6,35 @@ use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfig; | |||
6 | use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfigBuilder; | 6 | use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfigBuilder; |
7 | use Graby\SiteConfig\ConfigBuilder; | 7 | use Graby\SiteConfig\ConfigBuilder; |
8 | use OutOfRangeException; | 8 | use OutOfRangeException; |
9 | use Psr\Log\LoggerInterface; | ||
9 | 10 | ||
10 | class GrabySiteConfigBuilder implements SiteConfigBuilder | 11 | class GrabySiteConfigBuilder implements SiteConfigBuilder |
11 | { | 12 | { |
12 | /** | 13 | /** |
13 | * @var \Graby\SiteConfig\ConfigBuilder | 14 | * @var ConfigBuilder |
14 | */ | 15 | */ |
15 | private $grabyConfigBuilder; | 16 | private $grabyConfigBuilder; |
16 | /** | 17 | /** |
17 | * @var array | 18 | * @var array |
18 | */ | 19 | */ |
19 | private $credentials; | 20 | private $credentials; |
21 | /** | ||
22 | * @var LoggerInterface | ||
23 | */ | ||
24 | private $logger; | ||
20 | 25 | ||
21 | /** | 26 | /** |
22 | * GrabySiteConfigBuilder constructor. | 27 | * GrabySiteConfigBuilder constructor. |
23 | * | 28 | * |
24 | * @param \Graby\SiteConfig\ConfigBuilder $grabyConfigBuilder | 29 | * @param ConfigBuilder $grabyConfigBuilder |
25 | * @param array $credentials | 30 | * @param array $credentials |
31 | * @param LoggerInterface $logger | ||
26 | */ | 32 | */ |
27 | public function __construct(ConfigBuilder $grabyConfigBuilder, array $credentials = []) | 33 | public function __construct(ConfigBuilder $grabyConfigBuilder, array $credentials, LoggerInterface $logger) |
28 | { | 34 | { |
29 | $this->grabyConfigBuilder = $grabyConfigBuilder; | 35 | $this->grabyConfigBuilder = $grabyConfigBuilder; |
30 | $this->credentials = $credentials; | 36 | $this->credentials = $credentials; |
37 | $this->logger = $logger; | ||
31 | } | 38 | } |
32 | 39 | ||
33 | /** | 40 | /** |
@@ -47,6 +54,12 @@ class GrabySiteConfigBuilder implements SiteConfigBuilder | |||
47 | $host = substr($host, 4); | 54 | $host = substr($host, 4); |
48 | } | 55 | } |
49 | 56 | ||
57 | if (empty($this->credentials[$host])) { | ||
58 | $this->logger->debug('Auth: no credentials available for host.', ['host' => $host]); | ||
59 | |||
60 | return false; | ||
61 | } | ||
62 | |||
50 | $config = $this->grabyConfigBuilder->buildForHost($host); | 63 | $config = $this->grabyConfigBuilder->buildForHost($host); |
51 | $parameters = [ | 64 | $parameters = [ |
52 | 'host' => $host, | 65 | 'host' => $host, |
@@ -54,15 +67,46 @@ class GrabySiteConfigBuilder implements SiteConfigBuilder | |||
54 | 'loginUri' => $config->login_uri ?: null, | 67 | 'loginUri' => $config->login_uri ?: null, |
55 | 'usernameField' => $config->login_username_field ?: null, | 68 | 'usernameField' => $config->login_username_field ?: null, |
56 | 'passwordField' => $config->login_password_field ?: null, | 69 | 'passwordField' => $config->login_password_field ?: null, |
57 | 'extraFields' => is_array($config->login_extra_fields) ? $config->login_extra_fields : [], | 70 | 'extraFields' => $this->processExtraFields($config->login_extra_fields), |
58 | 'notLoggedInXpath' => $config->not_logged_in_xpath ?: null, | 71 | 'notLoggedInXpath' => $config->not_logged_in_xpath ?: null, |
72 | 'username' => $this->credentials[$host]['username'], | ||
73 | 'password' => $this->credentials[$host]['password'], | ||
59 | ]; | 74 | ]; |
60 | 75 | ||
61 | if (isset($this->credentials[$host])) { | 76 | $config = new SiteConfig($parameters); |
62 | $parameters['username'] = $this->credentials[$host]['username']; | 77 | |
63 | $parameters['password'] = $this->credentials[$host]['password']; | 78 | // do not leak password in log |
79 | $parameters['password'] = '**masked**'; | ||
80 | |||
81 | $this->logger->debug('Auth: add parameters.', ['host' => $host, 'parameters' => $parameters]); | ||
82 | |||
83 | return $config; | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * Processes login_extra_fields config, transforming an '=' separated array of strings | ||
88 | * into a key/value array. | ||
89 | * | ||
90 | * @param array|mixed $extraFieldsStrings | ||
91 | * | ||
92 | * @return array | ||
93 | */ | ||
94 | protected function processExtraFields($extraFieldsStrings) | ||
95 | { | ||
96 | if (!is_array($extraFieldsStrings)) { | ||
97 | return []; | ||
98 | } | ||
99 | |||
100 | $extraFields = []; | ||
101 | foreach ($extraFieldsStrings as $extraField) { | ||
102 | if (strpos($extraField, '=') === false) { | ||
103 | continue; | ||
104 | } | ||
105 | |||
106 | list($fieldName, $fieldValue) = explode('=', $extraField, 2); | ||
107 | $extraFields[$fieldName] = $fieldValue; | ||
64 | } | 108 | } |
65 | 109 | ||
66 | return new SiteConfig($parameters); | 110 | return $extraFields; |
67 | } | 111 | } |
68 | } | 112 | } |
diff --git a/src/Wallabag/CoreBundle/Helper/ContentProxy.php b/src/Wallabag/CoreBundle/Helper/ContentProxy.php index f222dd88..4b3e6fbb 100644 --- a/src/Wallabag/CoreBundle/Helper/ContentProxy.php +++ b/src/Wallabag/CoreBundle/Helper/ContentProxy.php | |||
@@ -5,9 +5,7 @@ namespace Wallabag\CoreBundle\Helper; | |||
5 | use Graby\Graby; | 5 | use Graby\Graby; |
6 | use Psr\Log\LoggerInterface; | 6 | use Psr\Log\LoggerInterface; |
7 | use Wallabag\CoreBundle\Entity\Entry; | 7 | use Wallabag\CoreBundle\Entity\Entry; |
8 | use Wallabag\CoreBundle\Entity\Tag; | ||
9 | use Wallabag\CoreBundle\Tools\Utils; | 8 | use Wallabag\CoreBundle\Tools\Utils; |
10 | use Wallabag\CoreBundle\Repository\TagRepository; | ||
11 | use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser; | 9 | use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser; |
12 | 10 | ||
13 | /** | 11 | /** |
@@ -19,16 +17,15 @@ class ContentProxy | |||
19 | protected $graby; | 17 | protected $graby; |
20 | protected $tagger; | 18 | protected $tagger; |
21 | protected $logger; | 19 | protected $logger; |
22 | protected $tagRepository; | ||
23 | protected $mimeGuesser; | 20 | protected $mimeGuesser; |
24 | protected $fetchingErrorMessage; | 21 | protected $fetchingErrorMessage; |
22 | protected $eventDispatcher; | ||
25 | 23 | ||
26 | public function __construct(Graby $graby, RuleBasedTagger $tagger, TagRepository $tagRepository, LoggerInterface $logger, $fetchingErrorMessage) | 24 | public function __construct(Graby $graby, RuleBasedTagger $tagger, LoggerInterface $logger, $fetchingErrorMessage) |
27 | { | 25 | { |
28 | $this->graby = $graby; | 26 | $this->graby = $graby; |
29 | $this->tagger = $tagger; | 27 | $this->tagger = $tagger; |
30 | $this->logger = $logger; | 28 | $this->logger = $logger; |
31 | $this->tagRepository = $tagRepository; | ||
32 | $this->mimeGuesser = new MimeTypeExtensionGuesser(); | 29 | $this->mimeGuesser = new MimeTypeExtensionGuesser(); |
33 | $this->fetchingErrorMessage = $fetchingErrorMessage; | 30 | $this->fetchingErrorMessage = $fetchingErrorMessage; |
34 | } | 31 | } |
@@ -79,6 +76,18 @@ class ContentProxy | |||
79 | $entry->setContent($html); | 76 | $entry->setContent($html); |
80 | $entry->setHttpStatus(isset($content['status']) ? $content['status'] : ''); | 77 | $entry->setHttpStatus(isset($content['status']) ? $content['status'] : ''); |
81 | 78 | ||
79 | if (isset($content['date']) && null !== $content['date'] && '' !== $content['date']) { | ||
80 | $entry->setPublishedAt(new \DateTime($content['date'])); | ||
81 | } | ||
82 | |||
83 | if (!empty($content['authors'])) { | ||
84 | $entry->setPublishedBy($content['authors']); | ||
85 | } | ||
86 | |||
87 | if (!empty($content['all_headers'])) { | ||
88 | $entry->setHeaders($content['all_headers']); | ||
89 | } | ||
90 | |||
82 | $entry->setLanguage(isset($content['language']) ? $content['language'] : ''); | 91 | $entry->setLanguage(isset($content['language']) ? $content['language'] : ''); |
83 | $entry->setMimetype(isset($content['content_type']) ? $content['content_type'] : ''); | 92 | $entry->setMimetype(isset($content['content_type']) ? $content['content_type'] : ''); |
84 | $entry->setReadingTime(Utils::getReadingTime($html)); | 93 | $entry->setReadingTime(Utils::getReadingTime($html)); |
@@ -110,54 +119,6 @@ class ContentProxy | |||
110 | } | 119 | } |
111 | 120 | ||
112 | /** | 121 | /** |
113 | * Assign some tags to an entry. | ||
114 | * | ||
115 | * @param Entry $entry | ||
116 | * @param array|string $tags An array of tag or a string coma separated of tag | ||
117 | * @param array $entitiesReady Entities from the EntityManager which are persisted but not yet flushed | ||
118 | * It is mostly to fix duplicate tag on import @see http://stackoverflow.com/a/7879164/569101 | ||
119 | */ | ||
120 | public function assignTagsToEntry(Entry $entry, $tags, array $entitiesReady = []) | ||
121 | { | ||
122 | if (!is_array($tags)) { | ||
123 | $tags = explode(',', $tags); | ||
124 | } | ||
125 | |||
126 | // keeps only Tag entity from the "not yet flushed entities" | ||
127 | $tagsNotYetFlushed = []; | ||
128 | foreach ($entitiesReady as $entity) { | ||
129 | if ($entity instanceof Tag) { | ||
130 | $tagsNotYetFlushed[$entity->getLabel()] = $entity; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | foreach ($tags as $label) { | ||
135 | $label = trim($label); | ||
136 | |||
137 | // avoid empty tag | ||
138 | if (0 === strlen($label)) { | ||
139 | continue; | ||
140 | } | ||
141 | |||
142 | if (isset($tagsNotYetFlushed[$label])) { | ||
143 | $tagEntity = $tagsNotYetFlushed[$label]; | ||
144 | } else { | ||
145 | $tagEntity = $this->tagRepository->findOneByLabel($label); | ||
146 | |||
147 | if (is_null($tagEntity)) { | ||
148 | $tagEntity = new Tag(); | ||
149 | $tagEntity->setLabel($label); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | // only add the tag on the entry if the relation doesn't exist | ||
154 | if (false === $entry->getTags()->contains($tagEntity)) { | ||
155 | $entry->addTag($tagEntity); | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * Validate that the given content as enough value to be used | 122 | * Validate that the given content as enough value to be used |
162 | * instead of fetch the content from the url. | 123 | * instead of fetch the content from the url. |
163 | * | 124 | * |
diff --git a/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php b/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php index 1ac8feb1..43f5b119 100644 --- a/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php +++ b/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php | |||
@@ -13,8 +13,8 @@ use Psr\Log\LoggerInterface; | |||
13 | */ | 13 | */ |
14 | class HttpClientFactory | 14 | class HttpClientFactory |
15 | { | 15 | { |
16 | /** @var \GuzzleHttp\Event\SubscriberInterface */ | 16 | /** @var [\GuzzleHttp\Event\SubscriberInterface] */ |
17 | private $authenticatorSubscriber; | 17 | private $subscribers = []; |
18 | 18 | ||
19 | /** @var \GuzzleHttp\Cookie\CookieJar */ | 19 | /** @var \GuzzleHttp\Cookie\CookieJar */ |
20 | private $cookieJar; | 20 | private $cookieJar; |
@@ -25,14 +25,12 @@ class HttpClientFactory | |||
25 | /** | 25 | /** |
26 | * HttpClientFactory constructor. | 26 | * HttpClientFactory constructor. |
27 | * | 27 | * |
28 | * @param \GuzzleHttp\Event\SubscriberInterface $authenticatorSubscriber | 28 | * @param \GuzzleHttp\Cookie\CookieJar $cookieJar |
29 | * @param \GuzzleHttp\Cookie\CookieJar $cookieJar | 29 | * @param string $restrictedAccess This param is a kind of boolean. Values: 0 or 1 |
30 | * @param string $restrictedAccess this param is a kind of boolean. Values: 0 or 1 | 30 | * @param LoggerInterface $logger |
31 | * @param LoggerInterface $logger | ||
32 | */ | 31 | */ |
33 | public function __construct(SubscriberInterface $authenticatorSubscriber, CookieJar $cookieJar, $restrictedAccess, LoggerInterface $logger) | 32 | public function __construct(CookieJar $cookieJar, $restrictedAccess, LoggerInterface $logger) |
34 | { | 33 | { |
35 | $this->authenticatorSubscriber = $authenticatorSubscriber; | ||
36 | $this->cookieJar = $cookieJar; | 34 | $this->cookieJar = $cookieJar; |
37 | $this->restrictedAccess = $restrictedAccess; | 35 | $this->restrictedAccess = $restrictedAccess; |
38 | $this->logger = $logger; | 36 | $this->logger = $logger; |
@@ -53,8 +51,21 @@ class HttpClientFactory | |||
53 | $this->cookieJar->clear(); | 51 | $this->cookieJar->clear(); |
54 | // need to set the (shared) cookie jar | 52 | // need to set the (shared) cookie jar |
55 | $client = new Client(['handler' => new SafeCurlHandler(), 'defaults' => ['cookies' => $this->cookieJar]]); | 53 | $client = new Client(['handler' => new SafeCurlHandler(), 'defaults' => ['cookies' => $this->cookieJar]]); |
56 | $client->getEmitter()->attach($this->authenticatorSubscriber); | 54 | |
55 | foreach ($this->subscribers as $subscriber) { | ||
56 | $client->getEmitter()->attach($subscriber); | ||
57 | } | ||
57 | 58 | ||
58 | return $client; | 59 | return $client; |
59 | } | 60 | } |
61 | |||
62 | /** | ||
63 | * Adds a subscriber to the HTTP client. | ||
64 | * | ||
65 | * @param SubscriberInterface $subscriber | ||
66 | */ | ||
67 | public function addSubscriber(SubscriberInterface $subscriber) | ||
68 | { | ||
69 | $this->subscribers[] = $subscriber; | ||
70 | } | ||
60 | } | 71 | } |
diff --git a/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php b/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php index b490e209..add27db2 100644 --- a/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php +++ b/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php | |||
@@ -8,6 +8,7 @@ use Wallabag\CoreBundle\Entity\Tag; | |||
8 | use Wallabag\CoreBundle\Repository\EntryRepository; | 8 | use Wallabag\CoreBundle\Repository\EntryRepository; |
9 | use Wallabag\CoreBundle\Repository\TagRepository; | 9 | use Wallabag\CoreBundle\Repository\TagRepository; |
10 | use Wallabag\UserBundle\Entity\User; | 10 | use Wallabag\UserBundle\Entity\User; |
11 | use Psr\Log\LoggerInterface; | ||
11 | 12 | ||
12 | class RuleBasedTagger | 13 | class RuleBasedTagger |
13 | { | 14 | { |
@@ -15,11 +16,12 @@ class RuleBasedTagger | |||
15 | private $tagRepository; | 16 | private $tagRepository; |
16 | private $entryRepository; | 17 | private $entryRepository; |
17 | 18 | ||
18 | public function __construct(RulerZ $rulerz, TagRepository $tagRepository, EntryRepository $entryRepository) | 19 | public function __construct(RulerZ $rulerz, TagRepository $tagRepository, EntryRepository $entryRepository, LoggerInterface $logger) |
19 | { | 20 | { |
20 | $this->rulerz = $rulerz; | 21 | $this->rulerz = $rulerz; |
21 | $this->tagRepository = $tagRepository; | 22 | $this->tagRepository = $tagRepository; |
22 | $this->entryRepository = $entryRepository; | 23 | $this->entryRepository = $entryRepository; |
24 | $this->logger = $logger; | ||
23 | } | 25 | } |
24 | 26 | ||
25 | /** | 27 | /** |
@@ -36,6 +38,11 @@ class RuleBasedTagger | |||
36 | continue; | 38 | continue; |
37 | } | 39 | } |
38 | 40 | ||
41 | $this->logger->info('Matching rule.', [ | ||
42 | 'rule' => $rule->getRule(), | ||
43 | 'tags' => $rule->getTags(), | ||
44 | ]); | ||
45 | |||
39 | foreach ($rule->getTags() as $label) { | 46 | foreach ($rule->getTags() as $label) { |
40 | $tag = $this->getTag($label); | 47 | $tag = $this->getTag($label); |
41 | 48 | ||
diff --git a/src/Wallabag/CoreBundle/Helper/TagsAssigner.php b/src/Wallabag/CoreBundle/Helper/TagsAssigner.php new file mode 100644 index 00000000..a2fb0b9a --- /dev/null +++ b/src/Wallabag/CoreBundle/Helper/TagsAssigner.php | |||
@@ -0,0 +1,75 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Helper; | ||
4 | |||
5 | use Wallabag\CoreBundle\Entity\Entry; | ||
6 | use Wallabag\CoreBundle\Entity\Tag; | ||
7 | use Wallabag\CoreBundle\Repository\TagRepository; | ||
8 | |||
9 | class TagsAssigner | ||
10 | { | ||
11 | /** | ||
12 | * @var TagRepository | ||
13 | */ | ||
14 | protected $tagRepository; | ||
15 | |||
16 | public function __construct(TagRepository $tagRepository) | ||
17 | { | ||
18 | $this->tagRepository = $tagRepository; | ||
19 | } | ||
20 | |||
21 | /** | ||
22 | * Assign some tags to an entry. | ||
23 | * | ||
24 | * @param Entry $entry | ||
25 | * @param array|string $tags An array of tag or a string coma separated of tag | ||
26 | * @param array $entitiesReady Entities from the EntityManager which are persisted but not yet flushed | ||
27 | * It is mostly to fix duplicate tag on import @see http://stackoverflow.com/a/7879164/569101 | ||
28 | * | ||
29 | * @return Tag[] | ||
30 | */ | ||
31 | public function assignTagsToEntry(Entry $entry, $tags, array $entitiesReady = []) | ||
32 | { | ||
33 | $tagsEntities = []; | ||
34 | |||
35 | if (!is_array($tags)) { | ||
36 | $tags = explode(',', $tags); | ||
37 | } | ||
38 | |||
39 | // keeps only Tag entity from the "not yet flushed entities" | ||
40 | $tagsNotYetFlushed = []; | ||
41 | foreach ($entitiesReady as $entity) { | ||
42 | if ($entity instanceof Tag) { | ||
43 | $tagsNotYetFlushed[$entity->getLabel()] = $entity; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | foreach ($tags as $label) { | ||
48 | $label = trim($label); | ||
49 | |||
50 | // avoid empty tag | ||
51 | if (0 === strlen($label)) { | ||
52 | continue; | ||
53 | } | ||
54 | |||
55 | if (isset($tagsNotYetFlushed[$label])) { | ||
56 | $tagEntity = $tagsNotYetFlushed[$label]; | ||
57 | } else { | ||
58 | $tagEntity = $this->tagRepository->findOneByLabel($label); | ||
59 | |||
60 | if (null === $tagEntity) { | ||
61 | $tagEntity = new Tag(); | ||
62 | $tagEntity->setLabel($label); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | // only add the tag on the entry if the relation doesn't exist | ||
67 | if (false === $entry->getTags()->contains($tagEntity)) { | ||
68 | $entry->addTag($tagEntity); | ||
69 | $tagsEntities[] = $tagEntity; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | return $tagsEntities; | ||
74 | } | ||
75 | } | ||
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 | |||
3 | namespace 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 | */ | ||
15 | class 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 | |||
3 | namespace 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 | */ | ||
15 | class NotMatches | ||
16 | { | ||
17 | public function __invoke($subject, $pattern) | ||
18 | { | ||
19 | return stripos($subject, $pattern) === false; | ||
20 | } | ||
21 | } | ||
diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index 4071301d..6972e974 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php | |||
@@ -328,7 +328,7 @@ class EntryRepository extends EntityRepository | |||
328 | * | 328 | * |
329 | * @return int | 329 | * @return int |
330 | */ | 330 | */ |
331 | public function countAllEntriesByUsername($userId) | 331 | public function countAllEntriesByUser($userId) |
332 | { | 332 | { |
333 | $qb = $this->createQueryBuilder('e') | 333 | $qb = $this->createQueryBuilder('e') |
334 | ->select('count(e)') | 334 | ->select('count(e)') |
@@ -371,4 +371,42 @@ class EntryRepository extends EntityRepository | |||
371 | ->setParameter('userId', $userId) | 371 | ->setParameter('userId', $userId) |
372 | ->execute(); | 372 | ->execute(); |
373 | } | 373 | } |
374 | |||
375 | public function removeArchivedByUserId($userId) | ||
376 | { | ||
377 | $this->getEntityManager() | ||
378 | ->createQuery('DELETE FROM Wallabag\CoreBundle\Entity\Entry e WHERE e.user = :userId AND e.isArchived = TRUE') | ||
379 | ->setParameter('userId', $userId) | ||
380 | ->execute(); | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * Get id and url from all entries | ||
385 | * Used for the clean-duplicates command. | ||
386 | */ | ||
387 | public function getAllEntriesIdAndUrl($userId) | ||
388 | { | ||
389 | $qb = $this->createQueryBuilder('e') | ||
390 | ->select('e.id, e.url') | ||
391 | ->where('e.user = :userid')->setParameter(':userid', $userId); | ||
392 | |||
393 | return $qb->getQuery()->getArrayResult(); | ||
394 | } | ||
395 | |||
396 | /** | ||
397 | * Find all entries by url and owner. | ||
398 | * | ||
399 | * @param $url | ||
400 | * @param $userId | ||
401 | * | ||
402 | * @return array | ||
403 | */ | ||
404 | public function findAllByUrlAndUserId($url, $userId) | ||
405 | { | ||
406 | return $this->createQueryBuilder('e') | ||
407 | ->where('e.url = :url')->setParameter('url', urldecode($url)) | ||
408 | ->andWhere('e.user = :user_id')->setParameter('user_id', $userId) | ||
409 | ->getQuery() | ||
410 | ->getResult(); | ||
411 | } | ||
374 | } | 412 | } |
diff --git a/src/Wallabag/CoreBundle/Repository/TagRepository.php b/src/Wallabag/CoreBundle/Repository/TagRepository.php index 2182df25..6c63a6a2 100644 --- a/src/Wallabag/CoreBundle/Repository/TagRepository.php +++ b/src/Wallabag/CoreBundle/Repository/TagRepository.php | |||
@@ -76,4 +76,24 @@ class TagRepository extends EntityRepository | |||
76 | ->getQuery() | 76 | ->getQuery() |
77 | ->getSingleResult(); | 77 | ->getSingleResult(); |
78 | } | 78 | } |
79 | |||
80 | public function findForArchivedArticlesByUser($userId) | ||
81 | { | ||
82 | $ids = $this->createQueryBuilder('t') | ||
83 | ->select('t.id') | ||
84 | ->leftJoin('t.entries', 'e') | ||
85 | ->where('e.user = :userId')->setParameter('userId', $userId) | ||
86 | ->andWhere('e.isArchived = true') | ||
87 | ->groupBy('t.id') | ||
88 | ->orderBy('t.slug') | ||
89 | ->getQuery() | ||
90 | ->getArrayResult(); | ||
91 | |||
92 | $tags = []; | ||
93 | foreach ($ids as $id) { | ||
94 | $tags[] = $this->find($id); | ||
95 | } | ||
96 | |||
97 | return $tags; | ||
98 | } | ||
79 | } | 99 | } |
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index 51d6ab47..a68b2fdc 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml | |||
@@ -63,6 +63,9 @@ services: | |||
63 | arguments: | 63 | arguments: |
64 | - "@wallabag_core.graby.config_builder" | 64 | - "@wallabag_core.graby.config_builder" |
65 | - "%sites_credentials%" | 65 | - "%sites_credentials%" |
66 | - '@logger' | ||
67 | tags: | ||
68 | - { name: monolog.logger, channel: graby } | ||
66 | 69 | ||
67 | # service alias override | 70 | # service alias override |
68 | bd_guzzle_site_authenticator.site_config_builder: | 71 | bd_guzzle_site_authenticator.site_config_builder: |
@@ -71,10 +74,11 @@ services: | |||
71 | wallabag_core.guzzle.http_client_factory: | 74 | wallabag_core.guzzle.http_client_factory: |
72 | class: Wallabag\CoreBundle\Helper\HttpClientFactory | 75 | class: Wallabag\CoreBundle\Helper\HttpClientFactory |
73 | arguments: | 76 | arguments: |
74 | - "@bd_guzzle_site_authenticator.authenticator_subscriber" | ||
75 | - "@wallabag_core.guzzle.cookie_jar" | 77 | - "@wallabag_core.guzzle.cookie_jar" |
76 | - '@=service(''craue_config'').get(''restricted_access'')' | 78 | - '@=service(''craue_config'').get(''restricted_access'')' |
77 | - '@logger' | 79 | - '@logger' |
80 | calls: | ||
81 | - ["addSubscriber", ["@bd_guzzle_site_authenticator.authenticator_subscriber"]] | ||
78 | 82 | ||
79 | wallabag_core.guzzle.cookie_jar: | 83 | wallabag_core.guzzle.cookie_jar: |
80 | class: GuzzleHttp\Cookie\FileCookieJar | 84 | class: GuzzleHttp\Cookie\FileCookieJar |
@@ -85,16 +89,21 @@ services: | |||
85 | arguments: | 89 | arguments: |
86 | - "@wallabag_core.graby" | 90 | - "@wallabag_core.graby" |
87 | - "@wallabag_core.rule_based_tagger" | 91 | - "@wallabag_core.rule_based_tagger" |
88 | - "@wallabag_core.tag_repository" | ||
89 | - "@logger" | 92 | - "@logger" |
90 | - '%wallabag_core.fetching_error_message%' | 93 | - '%wallabag_core.fetching_error_message%' |
91 | 94 | ||
95 | wallabag_core.tags_assigner: | ||
96 | class: Wallabag\CoreBundle\Helper\TagsAssigner | ||
97 | arguments: | ||
98 | - "@wallabag_core.tag_repository" | ||
99 | |||
92 | wallabag_core.rule_based_tagger: | 100 | wallabag_core.rule_based_tagger: |
93 | class: Wallabag\CoreBundle\Helper\RuleBasedTagger | 101 | class: Wallabag\CoreBundle\Helper\RuleBasedTagger |
94 | arguments: | 102 | arguments: |
95 | - "@rulerz" | 103 | - "@rulerz" |
96 | - "@wallabag_core.tag_repository" | 104 | - "@wallabag_core.tag_repository" |
97 | - "@wallabag_core.entry_repository" | 105 | - "@wallabag_core.entry_repository" |
106 | - "@logger" | ||
98 | 107 | ||
99 | # repository as a service | 108 | # repository as a service |
100 | wallabag_core.entry_repository: | 109 | wallabag_core.entry_repository: |
@@ -125,6 +134,16 @@ services: | |||
125 | tags: | 134 | tags: |
126 | - { name: rulerz.operator, target: doctrine, operator: matches, inline: true } | 135 | - { name: rulerz.operator, target: doctrine, operator: matches, inline: true } |
127 | 136 | ||
137 | wallabag.operator.array.notmatches: | ||
138 | class: Wallabag\CoreBundle\Operator\PHP\NotMatches | ||
139 | tags: | ||
140 | - { name: rulerz.operator, target: native, operator: notmatches } | ||
141 | |||
142 | wallabag.operator.doctrine.notmatches: | ||
143 | class: Wallabag\CoreBundle\Operator\Doctrine\NotMatches | ||
144 | tags: | ||
145 | - { name: rulerz.operator, target: doctrine, operator: notmatches, inline: true } | ||
146 | |||
128 | wallabag_core.helper.redirect: | 147 | wallabag_core.helper.redirect: |
129 | class: Wallabag\CoreBundle\Helper\Redirect | 148 | class: Wallabag\CoreBundle\Helper\Redirect |
130 | arguments: | 149 | arguments: |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml index 67421942..3e64af8f 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml | |||
@@ -110,6 +110,7 @@ config: | |||
110 | # annotations: Remove ALL annotations | 110 | # annotations: Remove ALL annotations |
111 | # tags: Remove ALL tags | 111 | # tags: Remove ALL tags |
112 | # entries: Remove ALL entries | 112 | # entries: Remove ALL entries |
113 | # archived: Remove ALL archived entries | ||
113 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | 114 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) |
114 | form_password: | 115 | form_password: |
115 | # description: "You can change your password here. Your new password should by at least 8 characters long." | 116 | # description: "You can change your password here. Your new password should by at least 8 characters long." |
@@ -154,7 +155,7 @@ config: | |||
154 | # or: 'One rule OR another' | 155 | # or: 'One rule OR another' |
155 | # and: 'One rule AND another' | 156 | # and: 'One rule AND another' |
156 | # 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>' |
157 | 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 | entry: | 159 | entry: |
159 | page_titles: | 160 | page_titles: |
160 | # unread: 'Unread entries' | 161 | # unread: 'Unread entries' |
@@ -223,6 +224,8 @@ entry: | |||
223 | original_article: 'original' | 224 | original_article: 'original' |
224 | # annotations_on_the_entry: '{0} No annotations|{1} One annotation|]1,Inf[ %count% annotations' | 225 | # annotations_on_the_entry: '{0} No annotations|{1} One annotation|]1,Inf[ %count% annotations' |
225 | created_at: 'Oprettelsesdato' | 226 | created_at: 'Oprettelsesdato' |
227 | # published_at: 'Publication date' | ||
228 | # published_by: 'Published by' | ||
226 | new: | 229 | new: |
227 | page_title: 'Gem ny artikel' | 230 | page_title: 'Gem ny artikel' |
228 | placeholder: 'http://website.com' | 231 | placeholder: 'http://website.com' |
@@ -234,10 +237,12 @@ entry: | |||
234 | # page_title: 'Edit an entry' | 237 | # page_title: 'Edit an entry' |
235 | # title_label: 'Title' | 238 | # title_label: 'Title' |
236 | url_label: 'Url' | 239 | url_label: 'Url' |
237 | # is_public_label: 'Public' | ||
238 | save_label: 'Gem' | 240 | save_label: 'Gem' |
239 | public: | 241 | public: |
240 | # shared_by_wallabag: "This article has been shared by <a href=%wallabag_instance%'>wallabag</a>" | 242 | # shared_by_wallabag: "This article has been shared by <a href=%wallabag_instance%'>wallabag</a>" |
243 | confirm: | ||
244 | # delete: "Are you sure you want to remove that article?" | ||
245 | # delete_tag: "Are you sure you want to remove that tag from that article?" | ||
241 | 246 | ||
242 | about: | 247 | about: |
243 | page_title: 'Om' | 248 | page_title: 'Om' |
@@ -510,6 +515,8 @@ user: | |||
510 | # delete: Delete | 515 | # delete: Delete |
511 | # delete_confirm: Are you sure? | 516 | # delete_confirm: Are you sure? |
512 | # back_to_list: Back to list | 517 | # back_to_list: Back to list |
518 | search: | ||
519 | # placeholder: Filter by username or email | ||
513 | 520 | ||
514 | error: | 521 | error: |
515 | # page_title: An error occurred | 522 | # page_title: An error occurred |
@@ -528,6 +535,7 @@ flashes: | |||
528 | # annotations_reset: Annotations reset | 535 | # annotations_reset: Annotations reset |
529 | # tags_reset: Tags reset | 536 | # tags_reset: Tags reset |
530 | # entries_reset: Entries reset | 537 | # entries_reset: Entries reset |
538 | # archived_reset: Archived entries deleted | ||
531 | entry: | 539 | entry: |
532 | notice: | 540 | notice: |
533 | # entry_already_saved: 'Entry already saved on %date%' | 541 | # entry_already_saved: 'Entry already saved on %date%' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml index 35cb4b5b..00468575 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml | |||
@@ -110,6 +110,7 @@ config: | |||
110 | annotations: Entferne ALLE Annotationen | 110 | annotations: Entferne ALLE Annotationen |
111 | tags: Entferne ALLE Tags | 111 | tags: Entferne ALLE Tags |
112 | entries: Entferne ALLE Einträge | 112 | entries: Entferne ALLE Einträge |
113 | archived: Entferne ALLE archivierten Einträge | ||
113 | confirm: Bist du wirklich sicher? (DIES KANN NICHT RÜCKGÄNGIG GEMACHT WERDEN) | 114 | confirm: Bist du wirklich sicher? (DIES KANN NICHT RÜCKGÄNGIG GEMACHT WERDEN) |
114 | form_password: | 115 | form_password: |
115 | description: "Hier kannst du dein Kennwort ändern. Dieses sollte mindestens acht Zeichen enthalten." | 116 | description: "Hier kannst du dein Kennwort ändern. Dieses sollte mindestens acht Zeichen enthalten." |
@@ -154,6 +155,7 @@ config: | |||
154 | or: 'Eine Regel ODER die andere' | 155 | or: 'Eine Regel ODER die andere' |
155 | and: 'Eine Regel UND eine andere' | 156 | and: 'Eine Regel UND eine andere' |
156 | 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: 'Testet, ob ein <i>Titel</i> nicht auf eine <i>Suche</i> zutrifft (Groß- und Kleinschreibung wird nicht berücksichtigt).<br />Beispiel: <code>title notmatches "Fußball"</code>' | ||
157 | 159 | ||
158 | entry: | 160 | entry: |
159 | page_titles: | 161 | page_titles: |
@@ -223,6 +225,8 @@ entry: | |||
223 | original_article: 'original' | 225 | original_article: 'original' |
224 | annotations_on_the_entry: '{0} Keine Anmerkungen|{1} Eine Anmerkung|]1,Inf[ %count% Anmerkungen' | 226 | annotations_on_the_entry: '{0} Keine Anmerkungen|{1} Eine Anmerkung|]1,Inf[ %count% Anmerkungen' |
225 | created_at: 'Erstellungsdatum' | 227 | created_at: 'Erstellungsdatum' |
228 | published_at: 'Erscheinungsdatum' | ||
229 | published_by: 'Veröffentlicht von' | ||
226 | new: | 230 | new: |
227 | page_title: 'Neuen Artikel speichern' | 231 | page_title: 'Neuen Artikel speichern' |
228 | placeholder: 'https://website.de' | 232 | placeholder: 'https://website.de' |
@@ -234,10 +238,12 @@ entry: | |||
234 | page_title: 'Eintrag bearbeiten' | 238 | page_title: 'Eintrag bearbeiten' |
235 | title_label: 'Titel' | 239 | title_label: 'Titel' |
236 | url_label: 'URL' | 240 | url_label: 'URL' |
237 | is_public_label: 'Öffentlich' | ||
238 | save_label: 'Speichern' | 241 | save_label: 'Speichern' |
239 | public: | 242 | public: |
240 | shared_by_wallabag: "Dieser Artikel wurde mittels <a href='%wallabag_instance%'>wallabag</a> geteilt" | 243 | shared_by_wallabag: "Dieser Artikel wurde mittels <a href='%wallabag_instance%'>wallabag</a> geteilt" |
244 | confirm: | ||
245 | delete: "Bist du sicher, dass du diesen Artikel löschen möchtest?" | ||
246 | delete_tag: "Bist du sicher, dass du diesen Tag vom Artikel entfernen möchtest?" | ||
241 | 247 | ||
242 | about: | 248 | about: |
243 | page_title: 'Ãœber' | 249 | page_title: 'Ãœber' |
@@ -510,6 +516,8 @@ user: | |||
510 | delete: Löschen | 516 | delete: Löschen |
511 | delete_confirm: Bist du sicher? | 517 | delete_confirm: Bist du sicher? |
512 | back_to_list: Zurück zur Liste | 518 | back_to_list: Zurück zur Liste |
519 | search: | ||
520 | placeholder: Filtere nach Benutzer oder E-Mail-Adresse | ||
513 | 521 | ||
514 | error: | 522 | error: |
515 | page_title: Ein Fehler ist aufgetreten | 523 | page_title: Ein Fehler ist aufgetreten |
@@ -528,6 +536,7 @@ flashes: | |||
528 | annotations_reset: Anmerkungen zurücksetzen | 536 | annotations_reset: Anmerkungen zurücksetzen |
529 | tags_reset: Tags zurücksetzen | 537 | tags_reset: Tags zurücksetzen |
530 | entries_reset: Einträge zurücksetzen | 538 | entries_reset: Einträge zurücksetzen |
539 | archived_reset: Archiverte Einträge zurücksetzen | ||
531 | entry: | 540 | entry: |
532 | notice: | 541 | notice: |
533 | entry_already_saved: 'Eintrag bereits am %date% gespeichert' | 542 | entry_already_saved: 'Eintrag bereits am %date% gespeichert' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml index e0ef3212..8703a0e5 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml | |||
@@ -110,6 +110,7 @@ config: | |||
110 | annotations: Remove ALL annotations | 110 | annotations: Remove ALL annotations |
111 | tags: Remove ALL tags | 111 | tags: Remove ALL tags |
112 | entries: Remove ALL entries | 112 | entries: Remove ALL entries |
113 | archived: Remove ALL archived entries | ||
113 | confirm: Are you really sure? (THIS CAN'T BE UNDONE) | 114 | confirm: Are you really sure? (THIS CAN'T BE UNDONE) |
114 | form_password: | 115 | form_password: |
115 | description: "You can change your password here. Your new password should by at least 8 characters long." | 116 | description: "You can change your password here. Your new password should by at least 8 characters long." |
@@ -154,6 +155,7 @@ config: | |||
154 | or: 'One rule OR another' | 155 | or: 'One rule OR another' |
155 | and: 'One rule AND another' | 156 | and: 'One rule AND another' |
156 | 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>' | ||
157 | 159 | ||
158 | entry: | 160 | entry: |
159 | page_titles: | 161 | page_titles: |
@@ -223,6 +225,8 @@ entry: | |||
223 | original_article: 'original' | 225 | original_article: 'original' |
224 | annotations_on_the_entry: '{0} No annotations|{1} One annotation|]1,Inf[ %count% annotations' | 226 | annotations_on_the_entry: '{0} No annotations|{1} One annotation|]1,Inf[ %count% annotations' |
225 | created_at: 'Creation date' | 227 | created_at: 'Creation date' |
228 | published_at: 'Publication date' | ||
229 | published_by: 'Published by' | ||
226 | new: | 230 | new: |
227 | page_title: 'Save new entry' | 231 | page_title: 'Save new entry' |
228 | placeholder: 'http://website.com' | 232 | placeholder: 'http://website.com' |
@@ -234,10 +238,12 @@ entry: | |||
234 | page_title: 'Edit an entry' | 238 | page_title: 'Edit an entry' |
235 | title_label: 'Title' | 239 | title_label: 'Title' |
236 | url_label: 'Url' | 240 | url_label: 'Url' |
237 | is_public_label: 'Public' | ||
238 | save_label: 'Save' | 241 | save_label: 'Save' |
239 | public: | 242 | public: |
240 | shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" | 243 | shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" |
244 | confirm: | ||
245 | delete: "Are you sure you want to remove that article?" | ||
246 | delete_tag: "Are you sure you want to remove that tag from that article?" | ||
241 | 247 | ||
242 | about: | 248 | about: |
243 | page_title: 'About' | 249 | page_title: 'About' |
@@ -510,6 +516,8 @@ user: | |||
510 | delete: Delete | 516 | delete: Delete |
511 | delete_confirm: Are you sure? | 517 | delete_confirm: Are you sure? |
512 | back_to_list: Back to list | 518 | back_to_list: Back to list |
519 | search: | ||
520 | placeholder: Filter by username or email | ||
513 | 521 | ||
514 | error: | 522 | error: |
515 | page_title: An error occurred | 523 | page_title: An error occurred |
@@ -528,6 +536,7 @@ flashes: | |||
528 | annotations_reset: Annotations reset | 536 | annotations_reset: Annotations reset |
529 | tags_reset: Tags reset | 537 | tags_reset: Tags reset |
530 | entries_reset: Entries reset | 538 | entries_reset: Entries reset |
539 | archived_reset: Archived entries deleted | ||
531 | entry: | 540 | entry: |
532 | notice: | 541 | notice: |
533 | entry_already_saved: 'Entry already saved on %date%' | 542 | entry_already_saved: 'Entry already saved on %date%' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml index 2f769b7e..0f2a4a7b 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml | |||
@@ -110,6 +110,7 @@ config: | |||
110 | annotations: Eliminar TODAS las anotaciones | 110 | annotations: Eliminar TODAS las anotaciones |
111 | tags: Eliminar TODAS las etiquetas | 111 | tags: Eliminar TODAS las etiquetas |
112 | entries: Eliminar TODOS los artÃculos | 112 | entries: Eliminar TODOS los artÃculos |
113 | # archived: Remove ALL archived entries | ||
113 | confirm: ¿Estás completamente seguro? (NO SE PUEDE DESHACER) | 114 | confirm: ¿Estás completamente seguro? (NO SE PUEDE DESHACER) |
114 | form_password: | 115 | form_password: |
115 | description: "Puedes cambiar la contraseña aquÃ. Tu nueva contraseña debe tener al menos 8 caracteres." | 116 | description: "Puedes cambiar la contraseña aquÃ. Tu nueva contraseña debe tener al menos 8 caracteres." |
@@ -154,6 +155,7 @@ config: | |||
154 | or: 'Una regla U otra' | 155 | or: 'Una regla U otra' |
155 | and: 'Una regla Y la otra' | 156 | and: 'Una regla Y la otra' |
156 | 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>' | ||
157 | 159 | ||
158 | entry: | 160 | entry: |
159 | page_titles: | 161 | page_titles: |
@@ -223,6 +225,8 @@ entry: | |||
223 | original_article: 'original' | 225 | original_article: 'original' |
224 | annotations_on_the_entry: '{0} Sin anotaciones|{1} Una anotación|]1,Inf[ %count% anotaciones' | 226 | annotations_on_the_entry: '{0} Sin anotaciones|{1} Una anotación|]1,Inf[ %count% anotaciones' |
225 | created_at: 'Fecha de creación' | 227 | created_at: 'Fecha de creación' |
228 | # published_at: 'Publication date' | ||
229 | # published_by: 'Published by' | ||
226 | new: | 230 | new: |
227 | page_title: 'Guardar un nuevo artÃculo' | 231 | page_title: 'Guardar un nuevo artÃculo' |
228 | placeholder: 'http://sitioweb.com' | 232 | placeholder: 'http://sitioweb.com' |
@@ -234,10 +238,12 @@ entry: | |||
234 | page_title: 'Editar un artÃculo' | 238 | page_title: 'Editar un artÃculo' |
235 | title_label: 'TÃtulo' | 239 | title_label: 'TÃtulo' |
236 | url_label: 'URL' | 240 | url_label: 'URL' |
237 | is_public_label: 'Es público' | ||
238 | save_label: 'Guardar' | 241 | save_label: 'Guardar' |
239 | public: | 242 | public: |
240 | shared_by_wallabag: "Este artÃculo se ha compartido con <a href='%wallabag_instance%'>wallabag</a>" | 243 | shared_by_wallabag: "Este artÃculo se ha compartido con <a href='%wallabag_instance%'>wallabag</a>" |
244 | confirm: | ||
245 | # delete: "Are you sure you want to remove that article?" | ||
246 | # delete_tag: "Are you sure you want to remove that tag from that article?" | ||
241 | 247 | ||
242 | about: | 248 | about: |
243 | page_title: 'Acerca de' | 249 | page_title: 'Acerca de' |
@@ -510,6 +516,8 @@ user: | |||
510 | delete: Eliminar | 516 | delete: Eliminar |
511 | delete_confirm: ¿Estás seguro? | 517 | delete_confirm: ¿Estás seguro? |
512 | back_to_list: Volver a la lista | 518 | back_to_list: Volver a la lista |
519 | search: | ||
520 | # placeholder: Filter by username or email | ||
513 | 521 | ||
514 | error: | 522 | error: |
515 | page_title: Ha ocurrido un error | 523 | page_title: Ha ocurrido un error |
@@ -528,6 +536,7 @@ flashes: | |||
528 | annotations_reset: Anotaciones reiniciadas | 536 | annotations_reset: Anotaciones reiniciadas |
529 | tags_reset: Etiquetas reiniciadas | 537 | tags_reset: Etiquetas reiniciadas |
530 | entries_reset: ArtÃculos reiniciados | 538 | entries_reset: ArtÃculos reiniciados |
539 | # archived_reset: Archived entries deleted | ||
531 | entry: | 540 | entry: |
532 | notice: | 541 | notice: |
533 | entry_already_saved: 'ArtÃculo ya guardado el %fecha%' | 542 | entry_already_saved: 'ArtÃculo ya guardado el %fecha%' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml index d9d76b32..ec7a4362 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml | |||
@@ -110,6 +110,7 @@ config: | |||
110 | # annotations: Remove ALL annotations | 110 | # annotations: Remove ALL annotations |
111 | # tags: Remove ALL tags | 111 | # tags: Remove ALL tags |
112 | # entries: Remove ALL entries | 112 | # entries: Remove ALL entries |
113 | # archived: Remove ALL archived entries | ||
113 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | 114 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) |
114 | form_password: | 115 | form_password: |
115 | # description: "You can change your password here. Your new password should by at least 8 characters long." | 116 | # description: "You can change your password here. Your new password should by at least 8 characters long." |
@@ -154,6 +155,7 @@ config: | |||
154 | # or: 'One rule OR another' | 155 | # or: 'One rule OR another' |
155 | # and: 'One rule AND another' | 156 | # and: 'One rule AND another' |
156 | # 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>' | ||
157 | 159 | ||
158 | entry: | 160 | entry: |
159 | page_titles: | 161 | page_titles: |
@@ -223,6 +225,8 @@ entry: | |||
223 | original_article: 'اصلی' | 225 | original_article: 'اصلی' |
224 | annotations_on_the_entry: '{0} بدون Øاشیه|{1} یک Øاشیه|]1,Inf[ %nbØاشیه% annotations' | 226 | annotations_on_the_entry: '{0} بدون Øاشیه|{1} یک Øاشیه|]1,Inf[ %nbØاشیه% annotations' |
225 | created_at: 'زمان ساخت' | 227 | created_at: 'زمان ساخت' |
228 | # published_at: 'Publication date' | ||
229 | # published_by: 'Published by' | ||
226 | new: | 230 | new: |
227 | page_title: 'ذخیرهٔ مقالهٔ تازه' | 231 | page_title: 'ذخیرهٔ مقالهٔ تازه' |
228 | placeholder: 'http://website.com' | 232 | placeholder: 'http://website.com' |
@@ -234,10 +238,12 @@ entry: | |||
234 | page_title: 'ویرایش مقاله' | 238 | page_title: 'ویرایش مقاله' |
235 | title_label: 'عنوان' | 239 | title_label: 'عنوان' |
236 | url_label: 'نشانی' | 240 | url_label: 'نشانی' |
237 | is_public_label: 'عمومی' | ||
238 | save_label: 'ذخیره' | 241 | save_label: 'ذخیره' |
239 | public: | 242 | public: |
240 | # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" | 243 | # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" |
244 | confirm: | ||
245 | # delete: "Are you sure you want to remove that article?" | ||
246 | # delete_tag: "Are you sure you want to remove that tag from that article?" | ||
241 | 247 | ||
242 | about: | 248 | about: |
243 | page_title: 'درباره' | 249 | page_title: 'درباره' |
@@ -510,6 +516,8 @@ user: | |||
510 | # delete: Delete | 516 | # delete: Delete |
511 | # delete_confirm: Are you sure? | 517 | # delete_confirm: Are you sure? |
512 | # back_to_list: Back to list | 518 | # back_to_list: Back to list |
519 | search: | ||
520 | # placeholder: Filter by username or email | ||
513 | 521 | ||
514 | error: | 522 | error: |
515 | # page_title: An error occurred | 523 | # page_title: An error occurred |
@@ -528,6 +536,7 @@ flashes: | |||
528 | # annotations_reset: Annotations reset | 536 | # annotations_reset: Annotations reset |
529 | # tags_reset: Tags reset | 537 | # tags_reset: Tags reset |
530 | # entries_reset: Entries reset | 538 | # entries_reset: Entries reset |
539 | # archived_reset: Archived entries deleted | ||
531 | entry: | 540 | entry: |
532 | notice: | 541 | notice: |
533 | entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود' | 542 | entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml index efddc46a..6969b67b 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 | ||
51 | config: | 51 | config: |
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,17 +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 | confirm: Êtes-vous vraiment vraiment sûr ? (C'EST IRRÉVERSIBLE) | 113 | archived: "Supprimer TOUS les articles archivés" |
114 | confirm: "Êtes-vous vraiment vraiment sûr ? (C’EST IRRÉVERSIBLE)" | ||
114 | form_password: | 115 | form_password: |
115 | 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." |
116 | old_password_label: "Mot de passe actuel" | 117 | old_password_label: "Mot de passe actuel" |
@@ -154,6 +155,7 @@ config: | |||
154 | or: "Une règle OU l’autre" | 155 | or: "Une règle OU l’autre" |
155 | and: "Une règle ET l’autre" | 156 | and: "Une règle ET l’autre" |
156 | 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>" | ||
157 | 159 | ||
158 | entry: | 160 | entry: |
159 | page_titles: | 161 | page_titles: |
@@ -162,7 +164,7 @@ entry: | |||
162 | archived: "Articles lus" | 164 | archived: "Articles lus" |
163 | filtered: "Articles filtrés" | 165 | filtered: "Articles filtrés" |
164 | filtered_tags: "Articles filtrés par tags :" | 166 | filtered_tags: "Articles filtrés par tags :" |
165 | filtered_search: 'Articles filtrés par recherche :' | 167 | filtered_search: "Articles filtrés par recherche :" |
166 | untagged: "Article sans tag" | 168 | untagged: "Article sans tag" |
167 | list: | 169 | list: |
168 | 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." |
@@ -186,7 +188,7 @@ entry: | |||
186 | preview_picture_label: "A une photo" | 188 | preview_picture_label: "A une photo" |
187 | preview_picture_help: "Photo" | 189 | preview_picture_help: "Photo" |
188 | language_label: "Langue" | 190 | language_label: "Langue" |
189 | http_status_label: 'Statut HTTP' | 191 | http_status_label: "Statut HTTP" |
190 | reading_time: | 192 | reading_time: |
191 | label: "Durée de lecture en minutes" | 193 | label: "Durée de lecture en minutes" |
192 | from: "de" | 194 | from: "de" |
@@ -223,6 +225,8 @@ entry: | |||
223 | original_article: "original" | 225 | original_article: "original" |
224 | annotations_on_the_entry: "{0} Aucune annotation|{1} Une annotation|]1,Inf[ %count% annotations" | 226 | annotations_on_the_entry: "{0} Aucune annotation|{1} Une annotation|]1,Inf[ %count% annotations" |
225 | created_at: "Date de création" | 227 | created_at: "Date de création" |
228 | published_at: "Date de publication" | ||
229 | published_by: "Publié par" | ||
226 | new: | 230 | new: |
227 | page_title: "Sauvegarder un nouvel article" | 231 | page_title: "Sauvegarder un nouvel article" |
228 | placeholder: "http://website.com" | 232 | placeholder: "http://website.com" |
@@ -234,10 +238,12 @@ entry: | |||
234 | page_title: "Éditer un article" | 238 | page_title: "Éditer un article" |
235 | title_label: "Titre" | 239 | title_label: "Titre" |
236 | url_label: "Adresse" | 240 | url_label: "Adresse" |
237 | is_public_label: "Public" | ||
238 | save_label: "Enregistrer" | 241 | save_label: "Enregistrer" |
239 | public: | 242 | public: |
240 | shared_by_wallabag: "Cet article a été partagé par <a href=\"%wallabag_instance%\">wallabag</a>" | 243 | shared_by_wallabag: "Cet article a été partagé par <a href=\"%wallabag_instance%\">wallabag</a>" |
244 | confirm: | ||
245 | delete: "Voulez-vous vraiment supprimer cet article ?" | ||
246 | delete_tag: "Voulez-vous vraiment supprimer ce tag de cet article ?" | ||
241 | 247 | ||
242 | about: | 248 | about: |
243 | page_title: "À propos" | 249 | page_title: "À propos" |
@@ -295,32 +301,32 @@ howto: | |||
295 | bookmarklet: | 301 | bookmarklet: |
296 | description: "Glissez et déposez ce lien dans votre barre de favoris :" | 302 | description: "Glissez et déposez ce lien dans votre barre de favoris :" |
297 | shortcuts: | 303 | shortcuts: |
298 | page_description: Voici les raccourcis disponibles dans wallabag. | 304 | page_description: "Voici les raccourcis disponibles dans wallabag." |
299 | shortcut: Raccourci | 305 | shortcut: "Raccourci" |
300 | action: Action | 306 | action: "Action" |
301 | all_pages_title: Raccourcis disponibles dans toutes les pages | 307 | all_pages_title: "Raccourcis disponibles dans toutes les pages" |
302 | go_unread: Afficher les articles non lus | 308 | go_unread: "Afficher les articles non lus" |
303 | go_starred: Afficher les articles favoris | 309 | go_starred: "Afficher les articles favoris" |
304 | go_archive: Afficher les articles lus | 310 | go_archive: "Afficher les articles lus" |
305 | go_all: Afficher tous les articles | 311 | go_all: "Afficher tous les articles" |
306 | go_tags: Afficher les tags | 312 | go_tags: "Afficher les tags" |
307 | go_config: Aller à la configuration | 313 | go_config: "Aller à la configuration" |
308 | go_import: Aller aux imports | 314 | go_import: "Aller aux imports" |
309 | go_developers: Aller à la section Développeurs | 315 | go_developers: "Aller à la section Développeurs" |
310 | go_howto: Afficher l'aide (cette page !) | 316 | go_howto: "Afficher l’aide (cette page !)" |
311 | go_logout: Se déconnecter | 317 | go_logout: "Se déconnecter" |
312 | list_title: Raccourcis disponibles dans les pages de liste | 318 | list_title: "Raccourcis disponibles dans les pages de liste" |
313 | search: Afficher le formulaire de recherche | 319 | search: "Afficher le formulaire de recherche" |
314 | article_title: Raccourcis disponibles quand on affiche un article | 320 | article_title: "Raccourcis disponibles quand on affiche un article" |
315 | open_original: Ouvrir l'URL originale de l'article | 321 | open_original: "Ouvrir l’URL originale de l’article" |
316 | toggle_favorite: Changer le statut Favori de l'article | 322 | toggle_favorite: "Changer le statut Favori de l’article" |
317 | toggle_archive: Changer le status Lu de l'article | 323 | toggle_archive: "Changer le status Lu de l’article" |
318 | delete: Supprimer l'article | 324 | delete: "Supprimer l’article" |
319 | material_title: Raccourcis disponibles avec le thème Material uniquement | 325 | material_title: "Raccourcis disponibles avec le thème Material uniquement" |
320 | add_link: Ajouter un nouvel article | 326 | add_link: "Ajouter un nouvel article" |
321 | hide_form: Masquer le formulaire courant (recherche ou nouvel article) | 327 | hide_form: "Masquer le formulaire courant (recherche ou nouvel article)" |
322 | arrows_navigation: Naviguer à travers les articles | 328 | arrows_navigation: "Naviguer à travers les articles" |
323 | open_article: Afficher l'article sélectionné | 329 | open_article: "Afficher l’article sélectionné" |
324 | 330 | ||
325 | quickstart: | 331 | quickstart: |
326 | page_title: "Pour bien débuter" | 332 | page_title: "Pour bien débuter" |
@@ -382,8 +388,8 @@ tag: | |||
382 | 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." | 388 | 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." |
383 | see_untagged_entries: "Voir les articles sans tag" | 389 | see_untagged_entries: "Voir les articles sans tag" |
384 | new: | 390 | new: |
385 | add: 'Ajouter' | 391 | add: "Ajouter" |
386 | placeholder: 'Vous pouvez ajouter plusieurs tags, séparés par une virgule.' | 392 | placeholder: "Vous pouvez ajouter plusieurs tags, séparés par une virgule." |
387 | 393 | ||
388 | import: | 394 | import: |
389 | page_title: "Importer" | 395 | page_title: "Importer" |
@@ -417,7 +423,7 @@ import: | |||
417 | how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l’importer." | 423 | how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l’importer." |
418 | worker: | 424 | worker: |
419 | enabled: "Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :" | 425 | enabled: "Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :" |
420 | 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." | 426 | 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." |
421 | firefox: | 427 | firefox: |
422 | page_title: "Import > Firefox" | 428 | page_title: "Import > Firefox" |
423 | 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>" | 429 | 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>" |
@@ -486,16 +492,16 @@ developer: | |||
486 | back: "Retour" | 492 | back: "Retour" |
487 | 493 | ||
488 | user: | 494 | user: |
489 | page_title: Gestion des utilisateurs | 495 | page_title: "Gestion des utilisateurs" |
490 | new_user: Créer un nouvel utilisateur | 496 | new_user: "Créer un nouvel utilisateur" |
491 | edit_user: Éditer un utilisateur existant | 497 | edit_user: "Éditer un utilisateur existant" |
492 | description: Ici vous pouvez gérer vos utilisateurs (création, mise à jour et suppression) | 498 | description: "Ici vous pouvez gérer vos utilisateurs (création, mise à jour et suppression)" |
493 | list: | 499 | list: |
494 | actions: Actions | 500 | actions: "Actions" |
495 | edit_action: Éditer | 501 | edit_action: "Éditer" |
496 | yes: Oui | 502 | yes: "Oui" |
497 | no: Non | 503 | no: "Non" |
498 | create_new_one: Créer un nouvel utilisateur | 504 | create_new_one: "Créer un nouvel utilisateur" |
499 | form: | 505 | form: |
500 | username_label: "Nom d’utilisateur" | 506 | username_label: "Nom d’utilisateur" |
501 | name_label: "Nom" | 507 | name_label: "Nom" |
@@ -510,9 +516,11 @@ user: | |||
510 | delete: "Supprimer" | 516 | delete: "Supprimer" |
511 | delete_confirm: "Voulez-vous vraiment ?" | 517 | delete_confirm: "Voulez-vous vraiment ?" |
512 | back_to_list: "Revenir à la liste" | 518 | back_to_list: "Revenir à la liste" |
519 | search: | ||
520 | placeholder: "Filtrer par nom d’utilisateur ou email" | ||
513 | 521 | ||
514 | error: | 522 | error: |
515 | page_title: Une erreur est survenue | 523 | page_title: "Une erreur est survenue" |
516 | 524 | ||
517 | flashes: | 525 | flashes: |
518 | config: | 526 | config: |
@@ -525,9 +533,10 @@ flashes: | |||
525 | tagging_rules_updated: "Règles mises à jour" | 533 | tagging_rules_updated: "Règles mises à jour" |
526 | tagging_rules_deleted: "Règle supprimée" | 534 | tagging_rules_deleted: "Règle supprimée" |
527 | rss_token_updated: "Jeton RSS mis à jour" | 535 | rss_token_updated: "Jeton RSS mis à jour" |
528 | annotations_reset: Annotations supprimées | 536 | annotations_reset: "Annotations supprimées" |
529 | tags_reset: Tags supprimés | 537 | tags_reset: "Tags supprimés" |
530 | entries_reset: Articles supprimés | 538 | entries_reset: "Articles supprimés" |
539 | archived_reset: "Articles archivés supprimés" | ||
531 | entry: | 540 | entry: |
532 | notice: | 541 | notice: |
533 | entry_already_saved: "Article déjà sauvegardé le %date%" | 542 | entry_already_saved: "Article déjà sauvegardé le %date%" |
@@ -559,6 +568,6 @@ flashes: | |||
559 | client_deleted: "Client %name% supprimé" | 568 | client_deleted: "Client %name% supprimé" |
560 | user: | 569 | user: |
561 | notice: | 570 | notice: |
562 | added: 'Utilisateur "%username%" ajouté' | 571 | added: "Utilisateur \"%username%\" ajouté" |
563 | updated: 'Utilisateur "%username%" mis à jour' | 572 | updated: "Utilisateur \"%username%\" mis à jour" |
564 | deleted: 'Utilisateur "%username%" supprimé' | 573 | 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 3f7c7010..70e9575a 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml | |||
@@ -110,6 +110,7 @@ config: | |||
110 | # annotations: Remove ALL annotations | 110 | # annotations: Remove ALL annotations |
111 | # tags: Remove ALL tags | 111 | # tags: Remove ALL tags |
112 | # entries: Remove ALL entries | 112 | # entries: Remove ALL entries |
113 | # archived: Remove ALL archived entries | ||
113 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | 114 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) |
114 | form_password: | 115 | form_password: |
115 | # description: "You can change your password here. Your new password should by at least 8 characters long." | 116 | # description: "You can change your password here. Your new password should by at least 8 characters long." |
@@ -154,6 +155,7 @@ config: | |||
154 | or: "Una regola O un'altra" | 155 | or: "Una regola O un'altra" |
155 | and: "Una regola E un'altra" | 156 | and: "Una regola E un'altra" |
156 | 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>' | ||
157 | 159 | ||
158 | entry: | 160 | entry: |
159 | page_titles: | 161 | page_titles: |
@@ -223,6 +225,8 @@ entry: | |||
223 | original_article: 'originale' | 225 | original_article: 'originale' |
224 | annotations_on_the_entry: '{0} Nessuna annotazione|{1} Una annotazione|]1,Inf[ %count% annotazioni' | 226 | annotations_on_the_entry: '{0} Nessuna annotazione|{1} Una annotazione|]1,Inf[ %count% annotazioni' |
225 | created_at: 'Data di creazione' | 227 | created_at: 'Data di creazione' |
228 | # published_at: 'Publication date' | ||
229 | # published_by: 'Published by' | ||
226 | new: | 230 | new: |
227 | page_title: 'Salva un nuovo contenuto' | 231 | page_title: 'Salva un nuovo contenuto' |
228 | placeholder: 'http://website.com' | 232 | placeholder: 'http://website.com' |
@@ -234,10 +238,12 @@ entry: | |||
234 | page_title: 'Modifica voce' | 238 | page_title: 'Modifica voce' |
235 | title_label: 'Titolo' | 239 | title_label: 'Titolo' |
236 | url_label: 'Url' | 240 | url_label: 'Url' |
237 | is_public_label: 'Pubblico' | ||
238 | save_label: 'Salva' | 241 | save_label: 'Salva' |
239 | public: | 242 | public: |
240 | # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" | 243 | # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" |
244 | confirm: | ||
245 | # delete: "Are you sure you want to remove that article?" | ||
246 | # delete_tag: "Are you sure you want to remove that tag from that article?" | ||
241 | 247 | ||
242 | about: | 248 | about: |
243 | page_title: 'About' | 249 | page_title: 'About' |
@@ -510,6 +516,8 @@ user: | |||
510 | # delete: Delete | 516 | # delete: Delete |
511 | # delete_confirm: Are you sure? | 517 | # delete_confirm: Are you sure? |
512 | # back_to_list: Back to list | 518 | # back_to_list: Back to list |
519 | search: | ||
520 | # placeholder: Filter by username or email | ||
513 | 521 | ||
514 | error: | 522 | error: |
515 | # page_title: An error occurred | 523 | # page_title: An error occurred |
@@ -528,6 +536,7 @@ flashes: | |||
528 | # annotations_reset: Annotations reset | 536 | # annotations_reset: Annotations reset |
529 | # tags_reset: Tags reset | 537 | # tags_reset: Tags reset |
530 | # entries_reset: Entries reset | 538 | # entries_reset: Entries reset |
539 | # archived_reset: Archived entries deleted | ||
531 | entry: | 540 | entry: |
532 | notice: | 541 | notice: |
533 | entry_already_saved: 'Contenuto già salvato in data %date%' | 542 | entry_already_saved: 'Contenuto già salvato in data %date%' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml index 913e3bcb..3ac472d0 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml | |||
@@ -110,6 +110,7 @@ config: | |||
110 | annotations: Levar TOTAS las anotacions | 110 | annotations: Levar TOTAS las anotacions |
111 | tags: Levar TOTAS las etiquetas | 111 | tags: Levar TOTAS las etiquetas |
112 | entries: Levar TOTES los articles | 112 | entries: Levar TOTES los articles |
113 | archived: Levar TOTES los articles archivats | ||
113 | confirm: Sètz vertadièrament segur ? (ES IRREVERSIBLE) | 114 | confirm: Sètz vertadièrament segur ? (ES IRREVERSIBLE) |
114 | form_password: | 115 | form_password: |
115 | description: "Podètz cambiar vòstre senhal aquÃ. Vòstre senhal deu èsser long d'almens 8 caractèrs." | 116 | description: "Podètz cambiar vòstre senhal aquÃ. Vòstre senhal deu èsser long d'almens 8 caractèrs." |
@@ -153,7 +154,8 @@ config: | |||
153 | not_equal_to: 'Diferent de…' | 154 | not_equal_to: 'Diferent de…' |
154 | or: "Una règla O l'autra" | 155 | or: "Una règla O l'autra" |
155 | and: "Una règla E l'autra" | 156 | and: "Una règla E l'autra" |
156 | 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>recèrca</i> (non sensibla a la cassa).<br />Exemple : <code>title matches \"football\"</code>' |
158 | notmatches: 'Teste se <i>subjècte</i> correspond pas a una <i>recèrca</i> (sensibla a la cassa).<br />Example : <code>title notmatches "football"</code>' | ||
157 | 159 | ||
158 | entry: | 160 | entry: |
159 | page_titles: | 161 | page_titles: |
@@ -183,8 +185,8 @@ entry: | |||
183 | archived_label: 'Legits' | 185 | archived_label: 'Legits' |
184 | starred_label: 'Favorits' | 186 | starred_label: 'Favorits' |
185 | unread_label: 'Pas legits' | 187 | unread_label: 'Pas legits' |
186 | preview_picture_label: 'A una fotò' | 188 | preview_picture_label: 'A un imatge' |
187 | preview_picture_help: 'Fotò' | 189 | preview_picture_help: 'Imatge' |
188 | language_label: 'Lenga' | 190 | language_label: 'Lenga' |
189 | http_status_label: 'Estatut HTTP' | 191 | http_status_label: 'Estatut HTTP' |
190 | reading_time: | 192 | reading_time: |
@@ -223,6 +225,8 @@ entry: | |||
223 | original_article: 'original' | 225 | original_article: 'original' |
224 | annotations_on_the_entry: "{0} Pas cap d'anotacion|{1} Una anotacion|]1,Inf[ %count% anotacions" | 226 | annotations_on_the_entry: "{0} Pas cap d'anotacion|{1} Una anotacion|]1,Inf[ %count% anotacions" |
225 | created_at: 'Data de creacion' | 227 | created_at: 'Data de creacion' |
228 | published_at: 'Data de publicacion' | ||
229 | published_by: 'Publicat per' | ||
226 | new: | 230 | new: |
227 | page_title: 'Enregistrar un novèl article' | 231 | page_title: 'Enregistrar un novèl article' |
228 | placeholder: 'http://website.com' | 232 | placeholder: 'http://website.com' |
@@ -234,10 +238,12 @@ entry: | |||
234 | page_title: 'Modificar un article' | 238 | page_title: 'Modificar un article' |
235 | title_label: 'TÃtol' | 239 | title_label: 'TÃtol' |
236 | url_label: 'Url' | 240 | url_label: 'Url' |
237 | is_public_label: 'Public' | ||
238 | save_label: 'Enregistrar' | 241 | save_label: 'Enregistrar' |
239 | public: | 242 | public: |
240 | shared_by_wallabag: "Aqueste article es estat partejat per <a href='%wallabag_instance%'>wallabag</a>" | 243 | shared_by_wallabag: "Aqueste article es estat partejat per <a href='%wallabag_instance%'>wallabag</a>" |
244 | confirm: | ||
245 | # delete: "Are you sure you want to remove that article?" | ||
246 | # delete_tag: "Are you sure you want to remove that tag from that article?" | ||
241 | 247 | ||
242 | about: | 248 | about: |
243 | page_title: 'A prepaus' | 249 | page_title: 'A prepaus' |
@@ -341,8 +347,8 @@ quickstart: | |||
341 | new_user: 'Crear un novèl utilizaire' | 347 | new_user: 'Crear un novèl utilizaire' |
342 | analytics: 'Configurar las estadisticas' | 348 | analytics: 'Configurar las estadisticas' |
343 | sharing: 'Activar de paramètres de partatge' | 349 | sharing: 'Activar de paramètres de partatge' |
344 | export: 'Configurar los expòrt' | 350 | export: 'Configurar los expòrts' |
345 | import: 'Configurar los impòrt' | 351 | import: 'Configurar los impòrts' |
346 | first_steps: | 352 | first_steps: |
347 | title: 'Primièrs passes' | 353 | title: 'Primièrs passes' |
348 | description: "Ara wallabag es ben configurat, es lo moment d'archivar lo web. Podètz clicar sul signe + a man drecha amont per ajustar un ligam." | 354 | description: "Ara wallabag es ben configurat, es lo moment d'archivar lo web. Podètz clicar sul signe + a man drecha amont per ajustar un ligam." |
@@ -458,7 +464,7 @@ developer: | |||
458 | action: 'Suprimir aqueste client' | 464 | action: 'Suprimir aqueste client' |
459 | client: | 465 | client: |
460 | page_title: 'Gestion dels clients API > Novèl client' | 466 | page_title: 'Gestion dels clients API > Novèl client' |
461 | page_description: "Anatz crear un novèl client. Mercés de cumplir l'url de redireccion cap a vòstra aplicacion." | 467 | page_description: "Anatz crear un novèl client. Mercés de garnir l'url de redireccion cap a vòstra aplicacion." |
462 | form: | 468 | form: |
463 | name_label: "Nom del client" | 469 | name_label: "Nom del client" |
464 | redirect_uris_label: 'URLs de redireccion' | 470 | redirect_uris_label: 'URLs de redireccion' |
@@ -469,7 +475,7 @@ developer: | |||
469 | page_description: 'Vaquà los paramètres de vòstre client.' | 475 | page_description: 'Vaquà los paramètres de vòstre client.' |
470 | field_name: 'Nom del client' | 476 | field_name: 'Nom del client' |
471 | field_id: 'ID Client' | 477 | field_id: 'ID Client' |
472 | field_secret: 'Clau secreta' | 478 | field_secret: 'Clau secrèta' |
473 | back: 'Retour' | 479 | back: 'Retour' |
474 | read_howto: 'Legir "cossà crear ma primièra aplicacion"' | 480 | read_howto: 'Legir "cossà crear ma primièra aplicacion"' |
475 | howto: | 481 | howto: |
@@ -510,6 +516,8 @@ user: | |||
510 | delete: 'Suprimir' | 516 | delete: 'Suprimir' |
511 | delete_confirm: 'Sètz segur ?' | 517 | delete_confirm: 'Sètz segur ?' |
512 | back_to_list: 'Tornar a la lista' | 518 | back_to_list: 'Tornar a la lista' |
519 | search: | ||
520 | placeholder: "Filtrar per nom d'utilizaire o corrièl" | ||
513 | 521 | ||
514 | error: | 522 | error: |
515 | page_title: Una error s'es produsida | 523 | page_title: Una error s'es produsida |
@@ -528,6 +536,7 @@ flashes: | |||
528 | annotations_reset: Anotacions levadas | 536 | annotations_reset: Anotacions levadas |
529 | tags_reset: Etiquetas levadas | 537 | tags_reset: Etiquetas levadas |
530 | entries_reset: Articles levats | 538 | entries_reset: Articles levats |
539 | archived_reset: Articles archivat suprimits | ||
531 | entry: | 540 | entry: |
532 | notice: | 541 | notice: |
533 | entry_already_saved: 'Article ja salvargardat lo %date%' | 542 | entry_already_saved: 'Article ja salvargardat lo %date%' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml index b990a6b9..fa672387 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml | |||
@@ -110,6 +110,7 @@ config: | |||
110 | annotations: Usuń WSZYSTKIE adnotacje | 110 | annotations: Usuń WSZYSTKIE adnotacje |
111 | tags: Usuń WSZYSTKIE tagi | 111 | tags: Usuń WSZYSTKIE tagi |
112 | entries: usuń WSZYTSTKIE wpisy | 112 | entries: usuń WSZYTSTKIE wpisy |
113 | archived: usuń WSZYSTKIE zarchiwizowane wpisy | ||
113 | confirm: Jesteś pewien? (tej operacji NIE MOŻNA cofnąć) | 114 | confirm: Jesteś pewien? (tej operacji NIE MOŻNA cofnąć) |
114 | form_password: | 115 | form_password: |
115 | description: "Tutaj możesz zmienić swoje hasło. Twoje nowe hasło powinno mieć conajmniej 8 znaków." | 116 | description: "Tutaj możesz zmienić swoje hasło. Twoje nowe hasło powinno mieć conajmniej 8 znaków." |
@@ -154,6 +155,7 @@ config: | |||
154 | or: 'Jedna reguła LUB inna' | 155 | or: 'Jedna reguła LUB inna' |
155 | and: 'Jedna reguła I inna' | 156 | and: 'Jedna reguła I inna' |
156 | 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: 'Sprawdź czy <i>temat</i> nie zawiera <i>szukaj</i> (duże lub małe litery).<br />Przykład: <code>tytuł nie zawiera "piłka nożna"</code>' | ||
157 | 159 | ||
158 | entry: | 160 | entry: |
159 | page_titles: | 161 | page_titles: |
@@ -223,6 +225,8 @@ entry: | |||
223 | original_article: 'oryginalny' | 225 | original_article: 'oryginalny' |
224 | annotations_on_the_entry: '{0} Nie ma adnotacji |{1} Jedna adnotacja |]1,Inf[ %count% adnotacji' | 226 | annotations_on_the_entry: '{0} Nie ma adnotacji |{1} Jedna adnotacja |]1,Inf[ %count% adnotacji' |
225 | created_at: 'Czas stworzenia' | 227 | created_at: 'Czas stworzenia' |
228 | published_at: 'Data publikacji' | ||
229 | published_by: 'Opublikowane przez' | ||
226 | new: | 230 | new: |
227 | page_title: 'Zapisz nowy wpis' | 231 | page_title: 'Zapisz nowy wpis' |
228 | placeholder: 'http://website.com' | 232 | placeholder: 'http://website.com' |
@@ -234,10 +238,12 @@ entry: | |||
234 | page_title: 'Edytuj wpis' | 238 | page_title: 'Edytuj wpis' |
235 | title_label: 'Tytuł' | 239 | title_label: 'Tytuł' |
236 | url_label: 'Adres URL' | 240 | url_label: 'Adres URL' |
237 | is_public_label: 'Publiczny' | ||
238 | save_label: 'Zapisz' | 241 | save_label: 'Zapisz' |
239 | public: | 242 | public: |
240 | shared_by_wallabag: "Ten artykuł został udostępniony przez <a href='%wallabag_instance%'>wallabag</a>" | 243 | shared_by_wallabag: "Ten artykuł został udostępniony przez <a href='%wallabag_instance%'>wallabag</a>" |
244 | confirm: | ||
245 | delete: "Czy jesteś pewien, że chcesz usunąć ten artykuł?" | ||
246 | delete_tag: "Czy jesteś pewien, że chcesz usunąć ten tag, z tego artykułu?" | ||
241 | 247 | ||
242 | about: | 248 | about: |
243 | page_title: 'O nas' | 249 | page_title: 'O nas' |
@@ -510,6 +516,8 @@ user: | |||
510 | delete: Usuń | 516 | delete: Usuń |
511 | delete_confirm: JesteÅ› pewien? | 517 | delete_confirm: JesteÅ› pewien? |
512 | back_to_list: Powrót do listy | 518 | back_to_list: Powrót do listy |
519 | search: | ||
520 | placeholder: Filtruj po nazwie użytkownika lub adresie e-mail | ||
513 | 521 | ||
514 | error: | 522 | error: |
515 | page_title: Wystąpił błąd | 523 | page_title: Wystąpił błąd |
@@ -528,6 +536,7 @@ flashes: | |||
528 | annotations_reset: Zresetuj adnotacje | 536 | annotations_reset: Zresetuj adnotacje |
529 | tags_reset: Zresetuj tagi | 537 | tags_reset: Zresetuj tagi |
530 | entries_reset: Zresetuj wpisy | 538 | entries_reset: Zresetuj wpisy |
539 | archived_reset: Zarchiwizowane wpisy usunięte | ||
531 | entry: | 540 | entry: |
532 | notice: | 541 | notice: |
533 | entry_already_saved: 'Wpis już został dodany %date%' | 542 | entry_already_saved: 'Wpis już został dodany %date%' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml index fd87ca44..bf038ee8 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml | |||
@@ -110,6 +110,7 @@ config: | |||
110 | # annotations: Remove ALL annotations | 110 | # annotations: Remove ALL annotations |
111 | # tags: Remove ALL tags | 111 | # tags: Remove ALL tags |
112 | # entries: Remove ALL entries | 112 | # entries: Remove ALL entries |
113 | # archived: Remove ALL archived entries | ||
113 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | 114 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) |
114 | form_password: | 115 | form_password: |
115 | # description: "You can change your password here. Your new password should by at least 8 characters long." | 116 | # description: "You can change your password here. Your new password should by at least 8 characters long." |
@@ -154,6 +155,7 @@ config: | |||
154 | or: 'Uma regra OU outra' | 155 | or: 'Uma regra OU outra' |
155 | and: 'Uma regra E outra' | 156 | and: 'Uma regra E outra' |
156 | 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>' | ||
157 | 159 | ||
158 | entry: | 160 | entry: |
159 | page_titles: | 161 | page_titles: |
@@ -223,6 +225,8 @@ entry: | |||
223 | original_article: 'original' | 225 | original_article: 'original' |
224 | annotations_on_the_entry: '{0} Sem anotações|{1} Uma anotação|]1,Inf[ %nbAnnotations% anotações' | 226 | annotations_on_the_entry: '{0} Sem anotações|{1} Uma anotação|]1,Inf[ %nbAnnotations% anotações' |
225 | created_at: 'Data de criação' | 227 | created_at: 'Data de criação' |
228 | # published_at: 'Publication date' | ||
229 | # published_by: 'Published by' | ||
226 | new: | 230 | new: |
227 | page_title: 'Salvar nova entrada' | 231 | page_title: 'Salvar nova entrada' |
228 | placeholder: 'http://website.com' | 232 | placeholder: 'http://website.com' |
@@ -234,10 +238,12 @@ entry: | |||
234 | page_title: 'Editar uma entrada' | 238 | page_title: 'Editar uma entrada' |
235 | title_label: 'TÃtulo' | 239 | title_label: 'TÃtulo' |
236 | url_label: 'Url' | 240 | url_label: 'Url' |
237 | is_public_label: 'Público' | ||
238 | save_label: 'Salvar' | 241 | save_label: 'Salvar' |
239 | public: | 242 | public: |
240 | shared_by_wallabag: "Este artigo foi compartilhado pelo <a href='%wallabag_instance%'>wallabag</a>" | 243 | shared_by_wallabag: "Este artigo foi compartilhado pelo <a href='%wallabag_instance%'>wallabag</a>" |
244 | confirm: | ||
245 | # delete: "Are you sure you want to remove that article?" | ||
246 | # delete_tag: "Are you sure you want to remove that tag from that article?" | ||
241 | 247 | ||
242 | about: | 248 | about: |
243 | page_title: 'Sobre' | 249 | page_title: 'Sobre' |
@@ -510,6 +516,8 @@ user: | |||
510 | delete: 'Apagar' | 516 | delete: 'Apagar' |
511 | delete_confirm: 'Tem certeza?' | 517 | delete_confirm: 'Tem certeza?' |
512 | back_to_list: 'Voltar para a lista' | 518 | back_to_list: 'Voltar para a lista' |
519 | search: | ||
520 | # placeholder: Filter by username or email | ||
513 | 521 | ||
514 | error: | 522 | error: |
515 | # page_title: An error occurred | 523 | # page_title: An error occurred |
@@ -528,6 +536,7 @@ flashes: | |||
528 | # annotations_reset: Annotations reset | 536 | # annotations_reset: Annotations reset |
529 | # tags_reset: Tags reset | 537 | # tags_reset: Tags reset |
530 | # entries_reset: Entries reset | 538 | # entries_reset: Entries reset |
539 | # archived_reset: Archived entries deleted | ||
531 | entry: | 540 | entry: |
532 | notice: | 541 | notice: |
533 | entry_already_saved: 'Entrada já foi salva em %date%' | 542 | entry_already_saved: 'Entrada já foi salva em %date%' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml index 14954b53..bd66d83a 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml | |||
@@ -110,6 +110,7 @@ config: | |||
110 | # annotations: Remove ALL annotations | 110 | # annotations: Remove ALL annotations |
111 | # tags: Remove ALL tags | 111 | # tags: Remove ALL tags |
112 | # entries: Remove ALL entries | 112 | # entries: Remove ALL entries |
113 | # archived: Remove ALL archived entries | ||
113 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | 114 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) |
114 | form_password: | 115 | form_password: |
115 | # description: "You can change your password here. Your new password should by at least 8 characters long." | 116 | # description: "You can change your password here. Your new password should by at least 8 characters long." |
@@ -154,6 +155,7 @@ config: | |||
154 | # or: 'One rule OR another' | 155 | # or: 'One rule OR another' |
155 | # and: 'One rule AND another' | 156 | # and: 'One rule AND another' |
156 | # 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>' | ||
157 | 159 | ||
158 | entry: | 160 | entry: |
159 | page_titles: | 161 | page_titles: |
@@ -223,6 +225,8 @@ entry: | |||
223 | original_article: 'original' | 225 | original_article: 'original' |
224 | # annotations_on_the_entry: '{0} No annotations|{1} One annotation|]1,Inf[ %count% annotations' | 226 | # annotations_on_the_entry: '{0} No annotations|{1} One annotation|]1,Inf[ %count% annotations' |
225 | created_at: 'Data creării' | 227 | created_at: 'Data creării' |
228 | # published_at: 'Publication date' | ||
229 | # published_by: 'Published by' | ||
226 | new: | 230 | new: |
227 | page_title: 'Salvează un nou articol' | 231 | page_title: 'Salvează un nou articol' |
228 | placeholder: 'http://website.com' | 232 | placeholder: 'http://website.com' |
@@ -234,10 +238,12 @@ entry: | |||
234 | # page_title: 'Edit an entry' | 238 | # page_title: 'Edit an entry' |
235 | # title_label: 'Title' | 239 | # title_label: 'Title' |
236 | url_label: 'Url' | 240 | url_label: 'Url' |
237 | # is_public_label: 'Public' | ||
238 | save_label: 'Salvează' | 241 | save_label: 'Salvează' |
239 | public: | 242 | public: |
240 | # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" | 243 | # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" |
244 | confirm: | ||
245 | # delete: "Are you sure you want to remove that article?" | ||
246 | # delete_tag: "Are you sure you want to remove that tag from that article?" | ||
241 | 247 | ||
242 | about: | 248 | about: |
243 | page_title: 'Despre' | 249 | page_title: 'Despre' |
@@ -510,6 +516,8 @@ user: | |||
510 | # delete: Delete | 516 | # delete: Delete |
511 | # delete_confirm: Are you sure? | 517 | # delete_confirm: Are you sure? |
512 | # back_to_list: Back to list | 518 | # back_to_list: Back to list |
519 | search: | ||
520 | # placeholder: Filter by username or email | ||
513 | 521 | ||
514 | error: | 522 | error: |
515 | # page_title: An error occurred | 523 | # page_title: An error occurred |
@@ -528,6 +536,7 @@ flashes: | |||
528 | # annotations_reset: Annotations reset | 536 | # annotations_reset: Annotations reset |
529 | # tags_reset: Tags reset | 537 | # tags_reset: Tags reset |
530 | # entries_reset: Entries reset | 538 | # entries_reset: Entries reset |
539 | # archived_reset: Archived entries deleted | ||
531 | entry: | 540 | entry: |
532 | notice: | 541 | notice: |
533 | # entry_already_saved: 'Entry already saved on %date%' | 542 | # entry_already_saved: 'Entry already saved on %date%' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml index 778a5515..b86c4003 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml | |||
@@ -110,6 +110,7 @@ config: | |||
110 | # annotations: Remove ALL annotations | 110 | # annotations: Remove ALL annotations |
111 | # tags: Remove ALL tags | 111 | # tags: Remove ALL tags |
112 | # entries: Remove ALL entries | 112 | # entries: Remove ALL entries |
113 | # archived: Remove ALL archived entries | ||
113 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) | 114 | # confirm: Are you really really sure? (THIS CAN'T BE UNDONE) |
114 | form_password: | 115 | form_password: |
115 | # description: "You can change your password here. Your new password should by at least 8 characters long." | 116 | # description: "You can change your password here. Your new password should by at least 8 characters long." |
@@ -154,6 +155,7 @@ config: | |||
154 | or: 'Bir kural veya birbaşkası' | 155 | or: 'Bir kural veya birbaşkası' |
155 | and: 'Bir kural ve diÄŸeri' | 156 | and: 'Bir kural ve diÄŸeri' |
156 | # 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>' | ||
157 | 159 | ||
158 | entry: | 160 | entry: |
159 | page_titles: | 161 | page_titles: |
@@ -223,6 +225,8 @@ entry: | |||
223 | original_article: 'orijinal' | 225 | original_article: 'orijinal' |
224 | # annotations_on_the_entry: '{0} No annotations|{1} One annotation|]1,Inf[ %count% annotations' | 226 | # annotations_on_the_entry: '{0} No annotations|{1} One annotation|]1,Inf[ %count% annotations' |
225 | created_at: 'OluÅŸturulma tarihi' | 227 | created_at: 'OluÅŸturulma tarihi' |
228 | # published_at: 'Publication date' | ||
229 | # published_by: 'Published by' | ||
226 | new: | 230 | new: |
227 | page_title: 'Yeni makaleyi kaydet' | 231 | page_title: 'Yeni makaleyi kaydet' |
228 | placeholder: 'http://website.com' | 232 | placeholder: 'http://website.com' |
@@ -234,10 +238,12 @@ entry: | |||
234 | page_title: 'Makaleyi düzenle' | 238 | page_title: 'Makaleyi düzenle' |
235 | title_label: 'Başlık' | 239 | title_label: 'Başlık' |
236 | url_label: 'Url' | 240 | url_label: 'Url' |
237 | is_public_label: 'Herkes tarafından erişime açık olsun mu?' | ||
238 | save_label: 'Kaydet' | 241 | save_label: 'Kaydet' |
239 | public: | 242 | public: |
240 | # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" | 243 | # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" |
244 | confirm: | ||
245 | # delete: "Are you sure you want to remove that article?" | ||
246 | # delete_tag: "Are you sure you want to remove that tag from that article?" | ||
241 | 247 | ||
242 | about: | 248 | about: |
243 | page_title: 'Hakkımızda' | 249 | page_title: 'Hakkımızda' |
@@ -510,6 +516,8 @@ user: | |||
510 | # delete: Delete | 516 | # delete: Delete |
511 | # delete_confirm: Are you sure? | 517 | # delete_confirm: Are you sure? |
512 | # back_to_list: Back to list | 518 | # back_to_list: Back to list |
519 | search: | ||
520 | # placeholder: Filter by username or email | ||
513 | 521 | ||
514 | error: | 522 | error: |
515 | # page_title: An error occurred | 523 | # page_title: An error occurred |
@@ -528,6 +536,7 @@ flashes: | |||
528 | # annotations_reset: Annotations reset | 536 | # annotations_reset: Annotations reset |
529 | # tags_reset: Tags reset | 537 | # tags_reset: Tags reset |
530 | # entries_reset: Entries reset | 538 | # entries_reset: Entries reset |
539 | # archived_reset: Archived entries deleted | ||
531 | entry: | 540 | entry: |
532 | notice: | 541 | notice: |
533 | entry_already_saved: 'Entry already saved on %date%' | 542 | entry_already_saved: 'Entry already saved on %date%' |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig index 3548f590..01f63a7b 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig | |||
@@ -200,6 +200,11 @@ | |||
200 | </a> | 200 | </a> |
201 | </li> | 201 | </li> |
202 | <li> | 202 | <li> |
203 | <a href="{{ path('config_reset', { type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
204 | {{ 'config.reset.archived'|trans }} | ||
205 | </a> | ||
206 | </li> | ||
207 | <li> | ||
203 | <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | 208 | <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> |
204 | {{ 'config.reset.entries'|trans }} | 209 | {{ 'config.reset.entries'|trans }} |
205 | </a> | 210 | </a> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig index 859b166b..0ba6f4f4 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig | |||
@@ -17,9 +17,9 @@ | |||
17 | <div class="results"> | 17 | <div class="results"> |
18 | <div class="nb-results">{{ 'entry.list.number_on_the_page'|transchoice(entries.count) }}</div> | 18 | <div class="nb-results">{{ 'entry.list.number_on_the_page'|transchoice(entries.count) }}</div> |
19 | <div class="pagination"> | 19 | <div class="pagination"> |
20 | <a href="{{ path('switch_view_mode') }}"><i class="listMode-btn material-icons md-36">{% if listMode == 0 %}list{% else %}view_module{% endif %}</i></a> | 20 | <a href="{{ path('switch_view_mode') }}"><i class="listMode-btn material-icons md-24">{% if listMode == 0 %}list{% else %}view_module{% endif %}</i></a> |
21 | <i class="btn-clickable download-btn material-icons md-36 js-export-action">file_download</i> | 21 | <i class="btn-clickable download-btn material-icons md-24 js-export-action">file_download</i> |
22 | <i class="btn-clickable filter-btn material-icons md-36 js-filters-action">filter_list</i> | 22 | <i class="btn-clickable filter-btn material-icons md-24 js-filters-action">filter_list</i> |
23 | {% if entries.getNbPages > 1 %} | 23 | {% if entries.getNbPages > 1 %} |
24 | {{ pagerfanta(entries, 'twitter_bootstrap_translated', {'proximity': 1}) }} | 24 | {{ pagerfanta(entries, 'twitter_bootstrap_translated', {'proximity': 1}) }} |
25 | {% endif %} | 25 | {% endif %} |
@@ -47,10 +47,10 @@ | |||
47 | </div> | 47 | </div> |
48 | 48 | ||
49 | <ul class="tools links"> | 49 | <ul class="tools links"> |
50 | <li><a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool icon-check icon {% if entry.isArchived == 0 %}archive-off{% else %}archive{% endif %}" href="{{ path('archive_entry', { 'id': entry.id }) }}"><span>{{ 'entry.list.toogle_as_read'|trans }}</span></a></li> | 50 | <li><a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.list.original_article'|trans }} : {{ entry.title|e }}"><span>{{ entry.domainName|removeWww }}</span></a></li> |
51 | <li><a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool icon-star icon {% if entry.isStarred == 0 %}fav-off{% else %}fav{% endif %}" href="{{ path('star_entry', { 'id': entry.id }) }}"><span>{{ 'entry.list.toogle_as_star'|trans }}</span></a></li> | 51 | <li><a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool icon {% if entry.isArchived == 0 %}archive-off{% else %}archive{% endif %}" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">check</i><span>{{ 'entry.list.toogle_as_read'|trans }}</span></a></li> |
52 | <li><a title="{{ 'entry.list.delete'|trans }}" class="tool delete icon-trash icon" href="{{ path('delete_entry', { 'id': entry.id }) }}"><span>{{ 'entry.list.delete'|trans }}</span></a></li> | 52 | <li><a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool icon {% if entry.isStarred == 0 %}fav-off{% else %}fav{% endif %}" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">star_rate</i><span>{{ 'entry.list.toogle_as_star'|trans }}</span></a></li> |
53 | <li><a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.list.original_article'|trans }} : {{ entry.title|e }}" class="tool link icon-link icon"><span>{{ entry.domainName|removeWww }}</span></a></li> | 53 | <li><a title="{{ 'entry.list.delete'|trans }}" class="tool icon" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">delete</i><span>{{ 'entry.list.delete'|trans }}</span></a></li> |
54 | </ul> | 54 | </ul> |
55 | {% if (entry.previewPicture is null or listMode == 1) %} | 55 | {% if (entry.previewPicture is null or listMode == 1) %} |
56 | <ul class="card-entry-tags"> | 56 | <ul class="card-entry-tags"> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entry.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entry.html.twig index a555691d..3d20a6bc 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entry.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entry.html.twig | |||
@@ -22,7 +22,7 @@ | |||
22 | <li><a title="{{ markAsReadLabel|trans }}" class="tool icon icon-check {% if entry.isArchived == 0 %}archive-off{% else %}archive{% endif %} markasread" href="{{ path('archive_entry', { 'id': entry.id }) }}"><span>{{ markAsReadLabel|trans }}</span></a></li> | 22 | <li><a title="{{ markAsReadLabel|trans }}" class="tool icon icon-check {% if entry.isArchived == 0 %}archive-off{% else %}archive{% endif %} markasread" href="{{ path('archive_entry', { 'id': entry.id }) }}"><span>{{ markAsReadLabel|trans }}</span></a></li> |
23 | <li><a title="{{ 'entry.view.left_menu.set_as_starred'|trans }}" class="tool icon icon-star {% if entry.isStarred == 0 %}fav-off{% else %}fav{% endif %} favorite" href="{{ path('star_entry', { 'id': entry.id }) }}"><span>{{ 'entry.view.left_menu.set_as_starred'|trans }}</span></a></li> | 23 | <li><a title="{{ 'entry.view.left_menu.set_as_starred'|trans }}" class="tool icon icon-star {% if entry.isStarred == 0 %}fav-off{% else %}fav{% endif %} favorite" href="{{ path('star_entry', { 'id': entry.id }) }}"><span>{{ 'entry.view.left_menu.set_as_starred'|trans }}</span></a></li> |
24 | <li><a id="nav-btn-add-tag" class="tool icon icon-price-tags" title="{{ 'entry.view.left_menu.add_a_tag'|trans }}"><span>{{ 'entry.view.left_menu.add_a_tag'|trans }}</span></a></li> | 24 | <li><a id="nav-btn-add-tag" class="tool icon icon-price-tags" title="{{ 'entry.view.left_menu.add_a_tag'|trans }}"><span>{{ 'entry.view.left_menu.add_a_tag'|trans }}</span></a></li> |
25 | <li><a title="{{ 'entry.view.left_menu.delete'|trans }}" class="tool delete icon icon-trash" href="{{ path('delete_entry', { 'id': entry.id }) }}"><span>{{ 'entry.view.left_menu.delete'|trans }}</span></a></li> | 25 | <li><a title="{{ 'entry.view.left_menu.delete'|trans }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" class="tool delete icon icon-trash" href="{{ path('delete_entry', { 'id': entry.id }) }}"><span>{{ 'entry.view.left_menu.delete'|trans }}</span></a></li> |
26 | {% if craue_setting('share_public') %} | 26 | {% if craue_setting('share_public') %} |
27 | <li><a href="{{ path('share', {'id': entry.id }) }}" target="_blank" class="tool icon icon-eye" title="{{ 'entry.view.left_menu.public_link'|trans }}"><span>{{ 'entry.view.left_menu.public_link'|trans }}</span></a></li> | 27 | <li><a href="{{ path('share', {'id': entry.id }) }}" target="_blank" class="tool icon icon-eye" title="{{ 'entry.view.left_menu.public_link'|trans }}"><span>{{ 'entry.view.left_menu.public_link'|trans }}</span></a></li> |
28 | <li><a href="{{ path('delete_share', {'id': entry.id }) }}" class="tool icon icon-no-eye" title="{{ 'entry.view.left_menu.delete_public_link'|trans }}"><span>{{ 'entry.view.left_menu.delete_public_link'|trans }}</span></a></li> | 28 | <li><a href="{{ path('delete_share', {'id': entry.id }) }}" class="tool icon icon-no-eye" title="{{ 'entry.view.left_menu.delete_public_link'|trans }}"><span>{{ 'entry.view.left_menu.delete_public_link'|trans }}</span></a></li> |
@@ -30,6 +30,7 @@ | |||
30 | {% if craue_setting('share_twitter') %}<li><a href="https://twitter.com/home?status={{entry.title|url_encode}}%20{{ entry.url|url_encode }}%20via%20@wallabagapp" target="_blank" class="tool twitter icon icon-twitter" title="Tweet"><span>Tweet</span></a></li>{% endif %} | 30 | {% if craue_setting('share_twitter') %}<li><a href="https://twitter.com/home?status={{entry.title|url_encode}}%20{{ entry.url|url_encode }}%20via%20@wallabagapp" target="_blank" class="tool twitter icon icon-twitter" title="Tweet"><span>Tweet</span></a></li>{% endif %} |
31 | {% if craue_setting('share_mail') %}<li><a href="mailto:?subject={{ entry.title|url_encode }}&body={{ entry.url|url_encode }}%20via%20@wallabagapp" class="tool email icon icon-mail" title="Email"><span>Email</span></a></li>{% endif %} | 31 | {% if craue_setting('share_mail') %}<li><a href="mailto:?subject={{ entry.title|url_encode }}&body={{ entry.url|url_encode }}%20via%20@wallabagapp" class="tool email icon icon-mail" title="Email"><span>Email</span></a></li>{% endif %} |
32 | {% if craue_setting('share_shaarli') %}<li><a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}&tags={{ entry.tags|join(',')|url_encode }}" target="_blank" class="tool icon-image icon-image--shaarli" title="shaarli"><span>shaarli</span></a></li>{% endif %} | 32 | {% if craue_setting('share_shaarli') %}<li><a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}&tags={{ entry.tags|join(',')|url_encode }}" target="_blank" class="tool icon-image icon-image--shaarli" title="shaarli"><span>shaarli</span></a></li>{% endif %} |
33 | {% if craue_setting('share_scuttle') %}<li><a href="{{ craue_setting('scuttle_url') }}/bookmarks.php?action=add&address={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}&tags={{ entry.tags|join(',')|url_encode }}" target="_blank" class="tool icon-image icon-image--scuttle" title="scuttle"><span>scuttle</span></a></li>{% endif %} | ||
33 | {% if craue_setting('share_diaspora') %}<li><a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}¬es=&v=1&noui=1&jump=doclose" target="_blank" class="tool diaspora icon-image icon-image--diaspora" title="diaspora"><span>diaspora</span></a></li>{% endif %} | 34 | {% if craue_setting('share_diaspora') %}<li><a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}¬es=&v=1&noui=1&jump=doclose" target="_blank" class="tool diaspora icon-image icon-image--diaspora" title="diaspora"><span>diaspora</span></a></li>{% endif %} |
34 | {% if craue_setting('share_unmark') %}<li><a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&title={{entry.title|url_encode}}&v=6" target="_blank" class="tool unmark icon-image icon-image--unmark" title="unmark"><span>unmark.it</span></a></li>{% endif %} | 35 | {% if craue_setting('share_unmark') %}<li><a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&title={{entry.title|url_encode}}&v=6" target="_blank" class="tool unmark icon-image icon-image--unmark" title="unmark"><span>unmark.it</span></a></li>{% endif %} |
35 | {% if craue_setting('carrot') %}<li><a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}" class="tool carrot icon-image icon-image--carrot" target="_blank" title="carrot"><span>Carrot</span></a></li>{% endif %} | 36 | {% if craue_setting('carrot') %}<li><a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}" class="tool carrot icon-image icon-image--carrot" target="_blank" title="carrot"><span>Carrot</span></a></li>{% endif %} |
@@ -43,9 +44,23 @@ | |||
43 | 44 | ||
44 | <div id="article-informations"> | 45 | <div id="article-informations"> |
45 | <i class="tool icon icon-calendar" title="{{ 'entry.view.created_at'|trans }}"> | 46 | <i class="tool icon icon-calendar" title="{{ 'entry.view.created_at'|trans }}"> |
46 | {{ entry.createdAt|date('Y-m-d') }} | 47 | {{ entry.createdAt|date('Y-m-d H:i') }} |
47 | </i> | 48 | </i> |
48 | 49 | ||
50 | {% if entry.publishedAt is not null %} | ||
51 | <i class="tool icon icon-pencil2" title="{{ 'entry.view.published_at'|trans }}"> | ||
52 | {{ entry.publishedAt|date('Y-m-d H:i') }} | ||
53 | </i> | ||
54 | {% endif %} | ||
55 | |||
56 | {% if entry.publishedBy is not empty %} | ||
57 | <i class="tool icon icon-users" title="{{ 'entry.view.published_by'|trans }}"> | ||
58 | {% for author in entry.publishedBy %} | ||
59 | {{ author }}{% if not loop.last %}, {% endif %} | ||
60 | {% endfor %} | ||
61 | </i> | ||
62 | {% endif %} | ||
63 | |||
49 | <i class="tool icon icon-time"> | 64 | <i class="tool icon icon-time"> |
50 | {% set readingTime = entry.readingTime / app.user.config.readingSpeed %} | 65 | {% set readingTime = entry.readingTime / app.user.config.readingSpeed %} |
51 | {% if readingTime > 0 %} | 66 | {% if readingTime > 0 %} |
@@ -59,10 +74,16 @@ | |||
59 | <aside class="tags"> | 74 | <aside class="tags"> |
60 | <div class="card-entry-tags"> | 75 | <div class="card-entry-tags"> |
61 | {% for tag in entry.tags %} | 76 | {% for tag in entry.tags %} |
62 | <span class="label-outline"><i class="material-icons">label_outline</i> <a href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{ tag.label }}</a> <a href="{{ path('remove_tag', { 'entry': entry.id, 'tag': tag.id }) }}" class="nostyle"><i>✘</i></a></span> | 77 | <span class="label-outline"> |
78 | <i class="material-icons">label_outline</i> | ||
79 | <a href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{ tag.label }}</a> | ||
80 | <a href="{{ path('remove_tag', { 'entry': entry.id, 'tag': tag.id }) }}" onclick="return confirm('{{ 'entry.confirm.delete_tag'|trans|escape('js') }}')" class="nostyle"> | ||
81 | <i>✘</i> | ||
82 | </a> | ||
83 | </span> | ||
63 | {% endfor %} | 84 | {% endfor %} |
64 | </div> | 85 | </div> |
65 | <div class="input-field nav-panel-add-tag" style="display: none"> | 86 | <div class="input-field baggy-add-tag" style="display: none"> |
66 | {{ render(controller( "WallabagCoreBundle:Tag:addTagForm", { 'id': entry.id } )) }} | 87 | {{ render(controller( "WallabagCoreBundle:Tag:addTagForm", { 'id': entry.id } )) }} |
67 | </div> | 88 | </div> |
68 | </aside> | 89 | </aside> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig index 07ff8e14..42aeace9 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig | |||
@@ -2,12 +2,14 @@ | |||
2 | 2 | ||
3 | {% block css %} | 3 | {% block css %} |
4 | {{ parent() }} | 4 | {{ parent() }} |
5 | <link rel="stylesheet" href="{{ asset('bundles/wallabagcore/themes/baggy/css/style.min.css') }}" media="screen,projection,print"/> | 5 | {% if not app.debug %} |
6 | <link rel="stylesheet" href="{{ asset('bundles/wallabagcore/baggy.css') }}"> | ||
7 | {% endif %} | ||
6 | {% endblock %} | 8 | {% endblock %} |
7 | 9 | ||
8 | {% block scripts %} | 10 | {% block scripts %} |
9 | {{ parent() }} | 11 | {{ parent() }} |
10 | <script src="{{ asset('bundles/wallabagcore/themes/baggy/js/baggy.min.js') }}"></script> | 12 | <script src="{{ asset('bundles/wallabagcore/baggy' ~ (app.debug ? '.dev' : '') ~ '.js') }}"></script> |
11 | {% endblock %} | 13 | {% endblock %} |
12 | 14 | ||
13 | {% block header %} | 15 | {% block header %} |
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 5d411fdd..9b0816eb 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 | |||
@@ -25,9 +25,9 @@ | |||
25 | 25 | ||
26 | <div class="row"> | 26 | <div class="row"> |
27 | <div class="input-field col s11"> | 27 | <div class="input-field col s11"> |
28 | {{ form_label(form.config.theme) }} | ||
29 | {{ form_errors(form.config.theme) }} | 28 | {{ form_errors(form.config.theme) }} |
30 | {{ form_widget(form.config.theme) }} | 29 | {{ form_widget(form.config.theme) }} |
30 | {{ form_label(form.config.theme) }} | ||
31 | </div> | 31 | </div> |
32 | <div class="input-field col s1"> | 32 | <div class="input-field col s1"> |
33 | <a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_theme'|trans }}"> | 33 | <a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_theme'|trans }}"> |
@@ -38,9 +38,9 @@ | |||
38 | 38 | ||
39 | <div class="row"> | 39 | <div class="row"> |
40 | <div class="input-field col s11"> | 40 | <div class="input-field col s11"> |
41 | {{ form_label(form.config.items_per_page) }} | ||
42 | {{ form_errors(form.config.items_per_page) }} | 41 | {{ form_errors(form.config.items_per_page) }} |
43 | {{ form_widget(form.config.items_per_page) }} | 42 | {{ form_widget(form.config.items_per_page) }} |
43 | {{ form_label(form.config.items_per_page) }} | ||
44 | </div> | 44 | </div> |
45 | <div class="input-field col s1"> | 45 | <div class="input-field col s1"> |
46 | <a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_items_per_page'|trans }}"> | 46 | <a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_items_per_page'|trans }}"> |
@@ -51,9 +51,9 @@ | |||
51 | 51 | ||
52 | <div class="row"> | 52 | <div class="row"> |
53 | <div class="input-field col s11"> | 53 | <div class="input-field col s11"> |
54 | {{ form_label(form.config.reading_speed) }} | ||
55 | {{ form_errors(form.config.reading_speed) }} | 54 | {{ form_errors(form.config.reading_speed) }} |
56 | {{ form_widget(form.config.reading_speed) }} | 55 | {{ form_widget(form.config.reading_speed) }} |
56 | {{ form_label(form.config.reading_speed) }} | ||
57 | <p> | 57 | <p> |
58 | {{ 'config.form_settings.reading_speed.help_message'|trans }} | 58 | {{ 'config.form_settings.reading_speed.help_message'|trans }} |
59 | <a href="http://www.myreadspeed.com/calculate/">myreadspeed</a> | 59 | <a href="http://www.myreadspeed.com/calculate/">myreadspeed</a> |
@@ -68,17 +68,17 @@ | |||
68 | 68 | ||
69 | <div class="row"> | 69 | <div class="row"> |
70 | <div class="input-field col s12"> | 70 | <div class="input-field col s12"> |
71 | {{ form_label(form.config.action_mark_as_read) }} | ||
72 | {{ form_errors(form.config.action_mark_as_read) }} | 71 | {{ form_errors(form.config.action_mark_as_read) }} |
73 | {{ form_widget(form.config.action_mark_as_read) }} | 72 | {{ form_widget(form.config.action_mark_as_read) }} |
73 | {{ form_label(form.config.action_mark_as_read) }} | ||
74 | </div> | 74 | </div> |
75 | </div> | 75 | </div> |
76 | 76 | ||
77 | <div class="row"> | 77 | <div class="row"> |
78 | <div class="input-field col s11"> | 78 | <div class="input-field col s11"> |
79 | {{ form_label(form.config.language) }} | ||
80 | {{ form_errors(form.config.language) }} | 79 | {{ form_errors(form.config.language) }} |
81 | {{ form_widget(form.config.language) }} | 80 | {{ form_widget(form.config.language) }} |
81 | {{ form_label(form.config.language) }} | ||
82 | </div> | 82 | </div> |
83 | <div class="input-field col s1"> | 83 | <div class="input-field col s1"> |
84 | <a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_language'|trans }}"> | 84 | <a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_language'|trans }}"> |
@@ -89,9 +89,9 @@ | |||
89 | 89 | ||
90 | <div class="row"> | 90 | <div class="row"> |
91 | <div class="input-field col s11"> | 91 | <div class="input-field col s11"> |
92 | {{ form_label(form.config.pocket_consumer_key) }} | ||
93 | {{ form_errors(form.config.pocket_consumer_key) }} | 92 | {{ form_errors(form.config.pocket_consumer_key) }} |
94 | {{ form_widget(form.config.pocket_consumer_key) }} | 93 | {{ form_widget(form.config.pocket_consumer_key) }} |
94 | {{ form_label(form.config.pocket_consumer_key) }} | ||
95 | <p> | 95 | <p> |
96 | » | 96 | » |
97 | <a href="https://getpocket.com/developer/docs/authentication">https://getpocket.com/developer/docs/authentication</a> | 97 | <a href="https://getpocket.com/developer/docs/authentication">https://getpocket.com/developer/docs/authentication</a> |
@@ -132,8 +132,8 @@ | |||
132 | </div> | 132 | </div> |
133 | 133 | ||
134 | <div class="row"> | 134 | <div class="row"> |
135 | <div class="input-field col s12"> | 135 | <div class="col s12"> |
136 | <label>{{ 'config.form_rss.token_label'|trans }}</label> | 136 | <h6 class="grey-text">{{ 'config.form_rss.token_label'|trans }}</h6> |
137 | <div> | 137 | <div> |
138 | {% if rss.token %} | 138 | {% if rss.token %} |
139 | {{ rss.token }} | 139 | {{ rss.token }} |
@@ -151,8 +151,8 @@ | |||
151 | </div> | 151 | </div> |
152 | {% if rss.token %} | 152 | {% if rss.token %} |
153 | <div class="row"> | 153 | <div class="row"> |
154 | <div class="input-field col s12"> | 154 | <div class="col s12"> |
155 | <label>{{ 'config.form_rss.rss_links'|trans }}</label> | 155 | <h6 class="grey-text">{{ 'config.form_rss.rss_links'|trans }}</h6> |
156 | <ul> | 156 | <ul> |
157 | <li><a href="{{ path('unread_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.unread'|trans }}</a></li> | 157 | <li><a href="{{ path('unread_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.unread'|trans }}</a></li> |
158 | <li><a href="{{ path('starred_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.starred'|trans }}</a></li> | 158 | <li><a href="{{ path('starred_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.starred'|trans }}</a></li> |
@@ -229,6 +229,9 @@ | |||
229 | <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | 229 | <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> |
230 | {{ 'config.reset.tags'|trans }} | 230 | {{ 'config.reset.tags'|trans }} |
231 | </a> | 231 | </a> |
232 | <a href="{{ path('config_reset', { type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
233 | {{ 'config.reset.archived'|trans }} | ||
234 | </a> | ||
232 | <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | 235 | <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> |
233 | {{ 'config.reset.entries'|trans }} | 236 | {{ 'config.reset.entries'|trans }} |
234 | </a> | 237 | </a> |
@@ -410,8 +413,8 @@ | |||
410 | <tr> | 413 | <tr> |
411 | <td>domainName</td> | 414 | <td>domainName</td> |
412 | <td>{{ 'config.form_rules.faq.variable_description.domainName'|trans }}</td> | 415 | <td>{{ 'config.form_rules.faq.variable_description.domainName'|trans }}</td> |
413 | <td>matches</td> | 416 | <td>matches<br />notmaches</td> |
414 | <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> |
415 | </tr> | 418 | </tr> |
416 | </tbody> | 419 | </tbody> |
417 | </table> | 420 | </table> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_actions.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_actions.html.twig index d278da1b..468338ac 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_actions.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_actions.html.twig | |||
@@ -9,7 +9,7 @@ | |||
9 | <li> | 9 | <li> |
10 | <a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}redo{% endif %}</i></a> | 10 | <a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}redo{% endif %}</i></a> |
11 | <a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a> | 11 | <a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a> |
12 | <a title="{{ 'entry.list.delete'|trans }}" class="tool grey-text delete" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons">delete</i></a> | 12 | <a title="{{ 'entry.list.delete'|trans }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" class="tool grey-text delete" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons">delete</i></a> |
13 | </li> | 13 | </li> |
14 | </ul> | 14 | </ul> |
15 | </div> | 15 | </div> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_list.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_list.html.twig index 3ba6253a..174b7b54 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_list.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_list.html.twig | |||
@@ -10,7 +10,7 @@ | |||
10 | <li> | 10 | <li> |
11 | <a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}redo{% endif %}</i></a> | 11 | <a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}redo{% endif %}</i></a> |
12 | <a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a> | 12 | <a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a> |
13 | <a title="{{ 'entry.list.delete'|trans }}" class="tool grey-text delete" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons">delete</i></a> | 13 | <a title="{{ 'entry.list.delete'|trans }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" class="tool grey-text delete" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons">delete</i></a> |
14 | </li> | 14 | </li> |
15 | </ul> | 15 | </ul> |
16 | </div> | 16 | </div> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_reading_time.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_reading_time.html.twig index 1a932a9f..6ba18768 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_reading_time.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_reading_time.html.twig | |||
@@ -1,7 +1,7 @@ | |||
1 | {% set readingTime = entry.readingTime / app.user.config.readingSpeed %} | 1 | {% set readingTime = entry.readingTime / app.user.config.readingSpeed %} |
2 | <i class="material-icons">timer</i> | 2 | <i class="material-icons">timer</i> |
3 | {% if readingTime > 0 %} | 3 | {% if readingTime > 0 %} |
4 | {{ 'entry.list.reading_time_minutes_short'|trans({'%readingTime%': readingTime|round}) }} | 4 | <span>{{ 'entry.list.reading_time_minutes_short'|trans({'%readingTime%': readingTime|round}) }}</span> |
5 | {% else %} | 5 | {% else %} |
6 | {{ 'entry.list.reading_time_less_one_minute_short'|trans|raw }} | 6 | <span>{{ 'entry.list.reading_time_less_one_minute_short'|trans|raw }}</span> |
7 | {% endif %} | 7 | {% endif %} |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/edit.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/edit.html.twig index 1c5e2aab..b9537975 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/edit.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/edit.html.twig | |||
@@ -27,11 +27,6 @@ | |||
27 | {{ form_label(form.url) }} | 27 | {{ form_label(form.url) }} |
28 | {{ form_widget(form.url) }} | 28 | {{ form_widget(form.url) }} |
29 | </div> | 29 | </div> |
30 | |||
31 | <div class="input-field s12"> | ||
32 | {{ form_widget(form.is_public) }} | ||
33 | {{ form_label(form.is_public) }} | ||
34 | </div> | ||
35 | <br> | 30 | <br> |
36 | 31 | ||
37 | {{ form_widget(form.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} | 32 | {{ form_widget(form.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig index 5fca53ae..b2d91c9c 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig | |||
@@ -45,7 +45,7 @@ | |||
45 | {% endif %} | 45 | {% endif %} |
46 | 46 | ||
47 | <!-- Export --> | 47 | <!-- Export --> |
48 | <div id="export" class="side-nav fixed right-aligned"> | 48 | <div id="export" class="side-nav right-aligned"> |
49 | {% set currentRoute = app.request.attributes.get('_route') %} | 49 | {% set currentRoute = app.request.attributes.get('_route') %} |
50 | {% set currentTag = '' %} | 50 | {% set currentTag = '' %} |
51 | {% if tag is defined %} | 51 | {% if tag is defined %} |
@@ -68,7 +68,7 @@ | |||
68 | 68 | ||
69 | <!-- Filters --> | 69 | <!-- Filters --> |
70 | {% if form is not null %} | 70 | {% if form is not null %} |
71 | <div id="filters" class="side-nav fixed right-aligned"> | 71 | <div id="filters" class="side-nav right-aligned"> |
72 | <form action="{{ path('all') }}"> | 72 | <form action="{{ path('all') }}"> |
73 | 73 | ||
74 | <h4 class="center">{{ 'entry.filters.title'|trans }}</h4> | 74 | <h4 class="center">{{ 'entry.filters.title'|trans }}</h4> |
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 af53084f..4cff7bf2 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> |
@@ -82,7 +82,7 @@ | |||
82 | <div class="collapsible-body"></div> | 82 | <div class="collapsible-body"></div> |
83 | </li> | 83 | </li> |
84 | <li class="bold border-bottom"> | 84 | <li class="bold border-bottom"> |
85 | <a class="waves-effect collapsible-header delete" title="{{ 'entry.view.left_menu.delete'|trans }}" href="{{ path('delete_entry', { 'id': entry.id }) }}"> | 85 | <a class="waves-effect collapsible-header delete" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" title="{{ 'entry.view.left_menu.delete'|trans }}" href="{{ path('delete_entry', { 'id': entry.id }) }}"> |
86 | <i class="material-icons small">delete</i> | 86 | <i class="material-icons small">delete</i> |
87 | <span>{{ 'entry.view.left_menu.delete'|trans }}</span> | 87 | <span>{{ 'entry.view.left_menu.delete'|trans }}</span> |
88 | </a> | 88 | </a> |
@@ -125,39 +125,43 @@ | |||
125 | {% endif %} | 125 | {% endif %} |
126 | {% if craue_setting('share_shaarli') %} | 126 | {% if craue_setting('share_shaarli') %} |
127 | <li> | 127 | <li> |
128 | <a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&title={{ entry.title|striptags|url_encode }}&tags={{ entry.tags|join(',')|striptags|url_encode }}" target="_blank"> | 128 | <a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&title={{ entry.title|striptags|url_encode }}&tags={{ entry.tags|join(',')|striptags|url_encode }}" target="_blank" title="shaarli" class="tool icon-image shaarli"> |
129 | <i class="tool icon-image icon-image--shaarli" title="shaarli"></i> | ||
130 | <span>shaarli</span> | 129 | <span>shaarli</span> |
131 | </a> | 130 | </a> |
132 | </li> | 131 | </li> |
133 | {% endif %} | 132 | {% endif %} |
133 | {% if craue_setting('share_scuttle') %} | ||
134 | <li> | ||
135 | <a href="{{ craue_setting('scuttle_url') }}/bookmarks.php?action=add&address={{ entry.url|url_encode }}&title={{ entry.title|striptags|url_encode }}&tags={{ entry.tags|join(',')|striptags|url_encode }}" target="_blank" title="scuttle" class="tool icon-image scuttle"> | ||
136 | <span>scuttle</span> | ||
137 | </a> | ||
138 | </li> | ||
139 | {% endif %} | ||
134 | {% if craue_setting('share_diaspora') %} | 140 | {% if craue_setting('share_diaspora') %} |
135 | <li> | 141 | <li> |
136 | <a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&title={{ entry.title|striptags|url_encode }}&notes=&v=1&noui=1&jump=doclose" target="_blank"> | 142 | <a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&title={{ entry.title|striptags|url_encode }}&notes=&v=1&noui=1&jump=doclose" target="_blank" class="tool icon-image diaspora" title="diaspora"> |
137 | <i class="tool icon-image icon-image--diaspora" title="diaspora"></i> | ||
138 | <span>diaspora*</span> | 143 | <span>diaspora*</span> |
139 | </a> | 144 | </a> |
140 | </li> | 145 | </li> |
141 | {% endif %} | 146 | {% endif %} |
142 | {% if craue_setting('share_unmark') %} | 147 | {% if craue_setting('share_unmark') %} |
143 | <li> | 148 | <li> |
144 | <a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&title={{entry.title|striptags|url_encode}}&v=6" target="_blank"> | 149 | <a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&title={{entry.title|striptags|url_encode}}&v=6" target="_blank" class="tool icon-image unmark" title="unmark"> |
145 | <i class="tool icon-image icon-image--unmark" title="unmark"></i> | ||
146 | <span>unmark.it</span> | 150 | <span>unmark.it</span> |
147 | </a> | 151 | </a> |
148 | </li> | 152 | </li> |
149 | {% endif %} | 153 | {% endif %} |
150 | {% if craue_setting('carrot') %} | 154 | {% if craue_setting('carrot') %} |
151 | <li> | 155 | <li> |
152 | <a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&title={{ entry.title|striptags|url_encode }}" target="_blank" title="carrot"> | 156 | <a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&title={{ entry.title|striptags|url_encode }}" target="_blank" title="carrot" class="tool icon-image carrot"> |
153 | <i class="tool icon-image icon-image--carrot"></i> | ||
154 | <span>Carrot</span> | 157 | <span>Carrot</span> |
155 | </a> | 158 | </a> |
156 | </li> | 159 | </li> |
157 | {% endif %} | 160 | {% endif %} |
158 | {% if craue_setting('share_mail') %} | 161 | {% if craue_setting('share_mail') %} |
159 | <li> | 162 | <li> |
160 | <a href="mailto:?subject={{ entry.title|striptags|url_encode }}&body={{ entry.url|url_encode }}%20via%20@wallabagapp" title="{{ 'entry.view.left_menu.share_email_label'|trans }}" class="tool email icon icon-mail"> | 163 | <a href="mailto:?subject={{ entry.title|striptags|url_encode }}&body={{ entry.url|url_encode }}%20via%20@wallabagapp" title="{{ 'entry.view.left_menu.share_email_label'|trans }}" class="tool icon"> |
164 | <i class="material-icons vertical-align-middle">mail</i> | ||
161 | <span>{{ 'entry.view.left_menu.share_email_label'|trans }}</span> | 165 | <span>{{ 'entry.view.left_menu.share_email_label'|trans }}</span> |
162 | </a> | 166 | </a> |
163 | </li> | 167 | </li> |
@@ -212,32 +216,51 @@ | |||
212 | <h1>{{ entry.title|striptags|raw }} <a href="{{ path('edit', { 'id': entry.id }) }}" title="{{ 'entry.view.edit_title'|trans }}">✎</a></h1> | 216 | <h1>{{ entry.title|striptags|raw }} <a href="{{ path('edit', { 'id': entry.id }) }}" title="{{ 'entry.view.edit_title'|trans }}">✎</a></h1> |
213 | </header> | 217 | </header> |
214 | <aside> | 218 | <aside> |
215 | <ul class="tools"> | 219 | <div class="tools"> |
216 | <li> | 220 | <ul class="stats"> |
217 | {% include "@WallabagCore/themes/material/Entry/_reading_time.html.twig" with {'entry': entry} only %} | 221 | <li> |
218 | </li> | 222 | {% include "@WallabagCore/themes/material/Entry/_reading_time.html.twig" with {'entry': entry} only %} |
219 | <li> | 223 | </li> |
220 | <i class="material-icons" title="{{ 'entry.view.created_at'|trans }}">today</i> | 224 | <li> |
221 | {{ entry.createdAt|date('Y-m-d') }} | 225 | <i class="material-icons" title="{{ 'entry.view.created_at'|trans }}">today</i> |
222 | </li> | 226 | {{ entry.createdAt|date('Y-m-d H:i') }} |
223 | <li> | 227 | </li> |
224 | <i class="material-icons link">link</i> | 228 | {% if entry.publishedAt is not null %} |
225 | <a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|striptags }}" class="tool"> | 229 | <li> |
226 | {{ entry.domainName|removeWww }} | 230 | <i class="material-icons" title="{{ 'entry.view.published_at'|trans }}">create</i> |
227 | </a> | 231 | {{ entry.publishedAt|date('Y-m-d H:i') }} |
228 | </li> | 232 | </li> |
229 | <li> | 233 | {% endif %} |
230 | <i class="material-icons link">comment</i> | 234 | {% if entry.publishedBy is not empty %} |
231 | {{ 'entry.view.annotations_on_the_entry'|transchoice(entry.annotations | length) }} | 235 | <li> |
232 | </li> | 236 | <i class="material-icons" title="{{ 'entry.view.published_by'|trans }}">person</i> |
233 | <li id="list"> | 237 | {% for author in entry.publishedBy %} |
238 | {{ author }}{% if not loop.last %}, {% endif %} | ||
239 | {% endfor %} | ||
240 | </li> | ||
241 | {% endif %} | ||
242 | <li> | ||
243 | <i class="material-icons link">link</i> | ||
244 | <a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|striptags }}" class="tool"> | ||
245 | {{ entry.domainName|removeWww }} | ||
246 | </a> | ||
247 | </li> | ||
248 | <li> | ||
249 | <i class="material-icons link">comment</i> | ||
250 | {{ 'entry.view.annotations_on_the_entry'|transchoice(entry.annotations | length) }} | ||
251 | </li> | ||
252 | </ul> | ||
253 | <ul class="tags"> | ||
234 | {% for tag in entry.tags %} | 254 | {% for tag in entry.tags %} |
235 | <div class="chip"> | 255 | <li class="chip"> |
236 | <a href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{ tag.label }}</a> <a href="{{ path('remove_tag', { 'entry': entry.id, 'tag': tag.id }) }}"><i class="material-icons">delete</i></a> | 256 | <a href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{ tag.label }}</a> |
237 | </div> | 257 | <a href="{{ path('remove_tag', { 'entry': entry.id, 'tag': tag.id }) }}" onclick="return confirm('{{ 'entry.confirm.delete_tag'|trans|escape('js') }}')"> |
258 | <i class="material-icons vertical-align-middle">delete</i> | ||
259 | </a> | ||
260 | </li> | ||
238 | {% endfor %} | 261 | {% endfor %} |
239 | </li> | 262 | </ul> |
240 | </ul> | 263 | </div> |
241 | 264 | ||
242 | <div class="input-field nav-panel-add-tag" style="display: none"> | 265 | <div class="input-field nav-panel-add-tag" style="display: none"> |
243 | {{ render(controller( "WallabagCoreBundle:Tag:addTagForm", { 'id': entry.id } )) }} | 266 | {{ render(controller( "WallabagCoreBundle:Tag:addTagForm", { 'id': entry.id } )) }} |
@@ -259,7 +282,7 @@ | |||
259 | <ul> | 282 | <ul> |
260 | <li><a class="btn-floating" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">done</i></a></li> | 283 | <li><a class="btn-floating" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">done</i></a></li> |
261 | <li><a class="btn-floating" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons">star_outline</i></a></li> | 284 | <li><a class="btn-floating" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons">star_outline</i></a></li> |
262 | <li><a class="btn-floating" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons">delete</i></a></li> | 285 | <li><a class="btn-floating" href="{{ path('delete_entry', { 'id': entry.id }) }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')"><i class="material-icons">delete</i></a></li> |
263 | </ul> | 286 | </ul> |
264 | </div> | 287 | </div> |
265 | </div> | 288 | </div> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig index 3c169c04..2dab1c18 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig | |||
@@ -2,12 +2,14 @@ | |||
2 | 2 | ||
3 | {% block css %} | 3 | {% block css %} |
4 | {{ parent() }} | 4 | {{ parent() }} |
5 | <link rel="stylesheet" href="{{ asset('bundles/wallabagcore/themes/material/css/style.min.css') }}" media="screen,projection,print"/> | 5 | {% if not app.debug %} |
6 | <link rel="stylesheet" href="{{ asset('bundles/wallabagcore/material.css') }}"> | ||
7 | {% endif %} | ||
6 | {% endblock %} | 8 | {% endblock %} |
7 | 9 | ||
8 | {% block scripts %} | 10 | {% block scripts %} |
9 | {{ parent() }} | 11 | {{ parent() }} |
10 | <script src="{{ asset('bundles/wallabagcore/themes/material/js/material.min.js') }}"></script> | 12 | <script src="{{ asset('bundles/wallabagcore/material' ~ (app.debug ? '.dev' : '') ~ '.js') }}"></script> |
11 | {% endblock %} | 13 | {% endblock %} |
12 | 14 | ||
13 | {% block header %} | 15 | {% block header %} |
@@ -116,12 +118,12 @@ | |||
116 | </ul> | 118 | </ul> |
117 | <div class="input-field nav-panel-search" style="display: none"> | 119 | <div class="input-field nav-panel-search" style="display: none"> |
118 | {{ render(controller("WallabagCoreBundle:Entry:searchForm", {'currentRoute': app.request.attributes.get('_route')})) }} | 120 | {{ render(controller("WallabagCoreBundle:Entry:searchForm", {'currentRoute': app.request.attributes.get('_route')})) }} |
119 | <label for="search" class="active"><i class="material-icons search">search</i></label> | 121 | <label for="search"><i class="material-icons search">search</i></label> |
120 | <i class="material-icons close">clear</i> | 122 | <i class="material-icons close">clear</i> |
121 | </div> | 123 | </div> |
122 | <div class="input-field nav-panel-add" style="display: none"> | 124 | <div class="input-field nav-panel-add" style="display: none"> |
123 | {{ render(controller("WallabagCoreBundle:Entry:addEntryForm")) }} | 125 | {{ render(controller("WallabagCoreBundle:Entry:addEntryForm")) }} |
124 | <label for="add" class="active"><i class="material-icons add">add</i></label> | 126 | <label for="add"><i class="material-icons add">add</i></label> |
125 | <i class="material-icons close">clear</i> | 127 | <i class="material-icons close">clear</i> |
126 | </div> | 128 | </div> |
127 | </div> | 129 | </div> |
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/ImportBundle/Import/AbstractImport.php b/src/Wallabag/ImportBundle/Import/AbstractImport.php index 1d4a6e27..a61388c0 100644 --- a/src/Wallabag/ImportBundle/Import/AbstractImport.php +++ b/src/Wallabag/ImportBundle/Import/AbstractImport.php | |||
@@ -8,6 +8,7 @@ use Doctrine\ORM\EntityManager; | |||
8 | use Wallabag\CoreBundle\Helper\ContentProxy; | 8 | use Wallabag\CoreBundle\Helper\ContentProxy; |
9 | use Wallabag\CoreBundle\Entity\Entry; | 9 | use Wallabag\CoreBundle\Entity\Entry; |
10 | use Wallabag\CoreBundle\Entity\Tag; | 10 | use Wallabag\CoreBundle\Entity\Tag; |
11 | use Wallabag\CoreBundle\Helper\TagsAssigner; | ||
11 | use Wallabag\UserBundle\Entity\User; | 12 | use Wallabag\UserBundle\Entity\User; |
12 | use OldSound\RabbitMqBundle\RabbitMq\ProducerInterface; | 13 | use OldSound\RabbitMqBundle\RabbitMq\ProducerInterface; |
13 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; | 14 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
@@ -18,6 +19,7 @@ abstract class AbstractImport implements ImportInterface | |||
18 | protected $em; | 19 | protected $em; |
19 | protected $logger; | 20 | protected $logger; |
20 | protected $contentProxy; | 21 | protected $contentProxy; |
22 | protected $tagsAssigner; | ||
21 | protected $eventDispatcher; | 23 | protected $eventDispatcher; |
22 | protected $producer; | 24 | protected $producer; |
23 | protected $user; | 25 | protected $user; |
@@ -26,11 +28,12 @@ abstract class AbstractImport implements ImportInterface | |||
26 | protected $importedEntries = 0; | 28 | protected $importedEntries = 0; |
27 | protected $queuedEntries = 0; | 29 | protected $queuedEntries = 0; |
28 | 30 | ||
29 | public function __construct(EntityManager $em, ContentProxy $contentProxy, EventDispatcherInterface $eventDispatcher) | 31 | public function __construct(EntityManager $em, ContentProxy $contentProxy, TagsAssigner $tagsAssigner, EventDispatcherInterface $eventDispatcher) |
30 | { | 32 | { |
31 | $this->em = $em; | 33 | $this->em = $em; |
32 | $this->logger = new NullLogger(); | 34 | $this->logger = new NullLogger(); |
33 | $this->contentProxy = $contentProxy; | 35 | $this->contentProxy = $contentProxy; |
36 | $this->tagsAssigner = $tagsAssigner; | ||
34 | $this->eventDispatcher = $eventDispatcher; | 37 | $this->eventDispatcher = $eventDispatcher; |
35 | } | 38 | } |
36 | 39 | ||
diff --git a/src/Wallabag/ImportBundle/Import/BrowserImport.php b/src/Wallabag/ImportBundle/Import/BrowserImport.php index 8bf7d92e..ef0eeb7e 100644 --- a/src/Wallabag/ImportBundle/Import/BrowserImport.php +++ b/src/Wallabag/ImportBundle/Import/BrowserImport.php | |||
@@ -4,7 +4,6 @@ namespace Wallabag\ImportBundle\Import; | |||
4 | 4 | ||
5 | use Wallabag\CoreBundle\Entity\Entry; | 5 | use Wallabag\CoreBundle\Entity\Entry; |
6 | use Wallabag\UserBundle\Entity\User; | 6 | use Wallabag\UserBundle\Entity\User; |
7 | use Wallabag\CoreBundle\Helper\ContentProxy; | ||
8 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | 7 | use Wallabag\CoreBundle\Event\EntrySavedEvent; |
9 | 8 | ||
10 | abstract class BrowserImport extends AbstractImport | 9 | abstract class BrowserImport extends AbstractImport |
@@ -205,7 +204,7 @@ abstract class BrowserImport extends AbstractImport | |||
205 | $entry = $this->fetchContent($entry, $data['url'], $data); | 204 | $entry = $this->fetchContent($entry, $data['url'], $data); |
206 | 205 | ||
207 | if (array_key_exists('tags', $data)) { | 206 | if (array_key_exists('tags', $data)) { |
208 | $this->contentProxy->assignTagsToEntry( | 207 | $this->tagsAssigner->assignTagsToEntry( |
209 | $entry, | 208 | $entry, |
210 | $data['tags'] | 209 | $data['tags'] |
211 | ); | 210 | ); |
diff --git a/src/Wallabag/ImportBundle/Import/PinboardImport.php b/src/Wallabag/ImportBundle/Import/PinboardImport.php index d9865534..489b9257 100644 --- a/src/Wallabag/ImportBundle/Import/PinboardImport.php +++ b/src/Wallabag/ImportBundle/Import/PinboardImport.php | |||
@@ -112,7 +112,7 @@ class PinboardImport extends AbstractImport | |||
112 | $entry = $this->fetchContent($entry, $data['url'], $data); | 112 | $entry = $this->fetchContent($entry, $data['url'], $data); |
113 | 113 | ||
114 | if (!empty($data['tags'])) { | 114 | if (!empty($data['tags'])) { |
115 | $this->contentProxy->assignTagsToEntry( | 115 | $this->tagsAssigner->assignTagsToEntry( |
116 | $entry, | 116 | $entry, |
117 | $data['tags'], | 117 | $data['tags'], |
118 | $this->em->getUnitOfWork()->getScheduledEntityInsertions() | 118 | $this->em->getUnitOfWork()->getScheduledEntityInsertions() |
diff --git a/src/Wallabag/ImportBundle/Import/PocketImport.php b/src/Wallabag/ImportBundle/Import/PocketImport.php index 33093480..8835161b 100644 --- a/src/Wallabag/ImportBundle/Import/PocketImport.php +++ b/src/Wallabag/ImportBundle/Import/PocketImport.php | |||
@@ -5,7 +5,6 @@ namespace Wallabag\ImportBundle\Import; | |||
5 | use GuzzleHttp\Client; | 5 | use GuzzleHttp\Client; |
6 | use GuzzleHttp\Exception\RequestException; | 6 | use GuzzleHttp\Exception\RequestException; |
7 | use Wallabag\CoreBundle\Entity\Entry; | 7 | use Wallabag\CoreBundle\Entity\Entry; |
8 | use Wallabag\CoreBundle\Helper\ContentProxy; | ||
9 | 8 | ||
10 | class PocketImport extends AbstractImport | 9 | class PocketImport extends AbstractImport |
11 | { | 10 | { |
@@ -216,7 +215,7 @@ class PocketImport extends AbstractImport | |||
216 | } | 215 | } |
217 | 216 | ||
218 | if (isset($importedEntry['tags']) && !empty($importedEntry['tags'])) { | 217 | if (isset($importedEntry['tags']) && !empty($importedEntry['tags'])) { |
219 | $this->contentProxy->assignTagsToEntry( | 218 | $this->tagsAssigner->assignTagsToEntry( |
220 | $entry, | 219 | $entry, |
221 | array_keys($importedEntry['tags']), | 220 | array_keys($importedEntry['tags']), |
222 | $this->em->getUnitOfWork()->getScheduledEntityInsertions() | 221 | $this->em->getUnitOfWork()->getScheduledEntityInsertions() |
diff --git a/src/Wallabag/ImportBundle/Import/WallabagImport.php b/src/Wallabag/ImportBundle/Import/WallabagImport.php index 702da057..0e5382cf 100644 --- a/src/Wallabag/ImportBundle/Import/WallabagImport.php +++ b/src/Wallabag/ImportBundle/Import/WallabagImport.php | |||
@@ -111,7 +111,7 @@ abstract class WallabagImport extends AbstractImport | |||
111 | $entry = $this->fetchContent($entry, $data['url'], $data); | 111 | $entry = $this->fetchContent($entry, $data['url'], $data); |
112 | 112 | ||
113 | if (array_key_exists('tags', $data)) { | 113 | if (array_key_exists('tags', $data)) { |
114 | $this->contentProxy->assignTagsToEntry( | 114 | $this->tagsAssigner->assignTagsToEntry( |
115 | $entry, | 115 | $entry, |
116 | $data['tags'], | 116 | $data['tags'], |
117 | $this->em->getUnitOfWork()->getScheduledEntityInsertions() | 117 | $this->em->getUnitOfWork()->getScheduledEntityInsertions() |
diff --git a/src/Wallabag/ImportBundle/Resources/config/services.yml b/src/Wallabag/ImportBundle/Resources/config/services.yml index c4fe3f92..661dc7e1 100644 --- a/src/Wallabag/ImportBundle/Resources/config/services.yml +++ b/src/Wallabag/ImportBundle/Resources/config/services.yml | |||
@@ -20,6 +20,7 @@ services: | |||
20 | arguments: | 20 | arguments: |
21 | - "@doctrine.orm.entity_manager" | 21 | - "@doctrine.orm.entity_manager" |
22 | - "@wallabag_core.content_proxy" | 22 | - "@wallabag_core.content_proxy" |
23 | - "@wallabag_core.tags_assigner" | ||
23 | - "@event_dispatcher" | 24 | - "@event_dispatcher" |
24 | calls: | 25 | calls: |
25 | - [ setClient, [ "@wallabag_import.pocket.client" ] ] | 26 | - [ setClient, [ "@wallabag_import.pocket.client" ] ] |
@@ -32,6 +33,7 @@ services: | |||
32 | arguments: | 33 | arguments: |
33 | - "@doctrine.orm.entity_manager" | 34 | - "@doctrine.orm.entity_manager" |
34 | - "@wallabag_core.content_proxy" | 35 | - "@wallabag_core.content_proxy" |
36 | - "@wallabag_core.tags_assigner" | ||
35 | - "@event_dispatcher" | 37 | - "@event_dispatcher" |
36 | calls: | 38 | calls: |
37 | - [ setLogger, [ "@logger" ]] | 39 | - [ setLogger, [ "@logger" ]] |
@@ -43,6 +45,7 @@ services: | |||
43 | arguments: | 45 | arguments: |
44 | - "@doctrine.orm.entity_manager" | 46 | - "@doctrine.orm.entity_manager" |
45 | - "@wallabag_core.content_proxy" | 47 | - "@wallabag_core.content_proxy" |
48 | - "@wallabag_core.tags_assigner" | ||
46 | - "@event_dispatcher" | 49 | - "@event_dispatcher" |
47 | calls: | 50 | calls: |
48 | - [ setLogger, [ "@logger" ]] | 51 | - [ setLogger, [ "@logger" ]] |
@@ -54,6 +57,7 @@ services: | |||
54 | arguments: | 57 | arguments: |
55 | - "@doctrine.orm.entity_manager" | 58 | - "@doctrine.orm.entity_manager" |
56 | - "@wallabag_core.content_proxy" | 59 | - "@wallabag_core.content_proxy" |
60 | - "@wallabag_core.tags_assigner" | ||
57 | - "@event_dispatcher" | 61 | - "@event_dispatcher" |
58 | calls: | 62 | calls: |
59 | - [ setLogger, [ "@logger" ]] | 63 | - [ setLogger, [ "@logger" ]] |
@@ -65,6 +69,7 @@ services: | |||
65 | arguments: | 69 | arguments: |
66 | - "@doctrine.orm.entity_manager" | 70 | - "@doctrine.orm.entity_manager" |
67 | - "@wallabag_core.content_proxy" | 71 | - "@wallabag_core.content_proxy" |
72 | - "@wallabag_core.tags_assigner" | ||
68 | - "@event_dispatcher" | 73 | - "@event_dispatcher" |
69 | calls: | 74 | calls: |
70 | - [ setLogger, [ "@logger" ]] | 75 | - [ setLogger, [ "@logger" ]] |
@@ -76,6 +81,7 @@ services: | |||
76 | arguments: | 81 | arguments: |
77 | - "@doctrine.orm.entity_manager" | 82 | - "@doctrine.orm.entity_manager" |
78 | - "@wallabag_core.content_proxy" | 83 | - "@wallabag_core.content_proxy" |
84 | - "@wallabag_core.tags_assigner" | ||
79 | - "@event_dispatcher" | 85 | - "@event_dispatcher" |
80 | calls: | 86 | calls: |
81 | - [ setLogger, [ "@logger" ]] | 87 | - [ setLogger, [ "@logger" ]] |
@@ -87,6 +93,7 @@ services: | |||
87 | arguments: | 93 | arguments: |
88 | - "@doctrine.orm.entity_manager" | 94 | - "@doctrine.orm.entity_manager" |
89 | - "@wallabag_core.content_proxy" | 95 | - "@wallabag_core.content_proxy" |
96 | - "@wallabag_core.tags_assigner" | ||
90 | - "@event_dispatcher" | 97 | - "@event_dispatcher" |
91 | calls: | 98 | calls: |
92 | - [ setLogger, [ "@logger" ]] | 99 | - [ setLogger, [ "@logger" ]] |
@@ -97,6 +104,7 @@ services: | |||
97 | arguments: | 104 | arguments: |
98 | - "@doctrine.orm.entity_manager" | 105 | - "@doctrine.orm.entity_manager" |
99 | - "@wallabag_core.content_proxy" | 106 | - "@wallabag_core.content_proxy" |
107 | - "@wallabag_core.tags_assigner" | ||
100 | - "@event_dispatcher" | 108 | - "@event_dispatcher" |
101 | calls: | 109 | calls: |
102 | - [ setLogger, [ "@logger" ]] | 110 | - [ setLogger, [ "@logger" ]] |
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 | ||
5 | use FOS\UserBundle\Event\UserEvent; | 5 | use FOS\UserBundle\Event\UserEvent; |
6 | use FOS\UserBundle\FOSUserEvents; | 6 | use FOS\UserBundle\FOSUserEvents; |
7 | use Pagerfanta\Adapter\DoctrineORMAdapter; | ||
8 | use Pagerfanta\Exception\OutOfRangeCurrentPageException; | ||
9 | use Pagerfanta\Pagerfanta; | ||
7 | use Symfony\Component\HttpFoundation\Request; | 10 | use Symfony\Component\HttpFoundation\Request; |
8 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 11 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
9 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; | 12 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; |
10 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | 13 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; |
11 | use Wallabag\UserBundle\Entity\User; | 14 | use Wallabag\UserBundle\Entity\User; |
12 | use Wallabag\CoreBundle\Entity\Config; | 15 | use Wallabag\UserBundle\Form\SearchUserType; |
13 | 16 | ||
14 | /** | 17 | /** |
15 | * User controller. | 18 | * User controller. |
@@ -17,23 +20,6 @@ use Wallabag\CoreBundle\Entity\Config; | |||
17 | class ManageController extends Controller | 20 | class 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 | |||
3 | namespace Wallabag\UserBundle\Form; | ||
4 | |||
5 | use Symfony\Component\Form\AbstractType; | ||
6 | use Symfony\Component\Form\Extension\Core\Type\TextType; | ||
7 | use Symfony\Component\Form\FormBuilderInterface; | ||
8 | use Symfony\Component\OptionsResolver\OptionsResolver; | ||
9 | |||
10 | class 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> |