diff options
author | Jérémy Benoist <j0k3r@users.noreply.github.com> | 2019-05-29 11:14:00 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-29 11:14:00 +0200 |
commit | 73ec68b1ffafb792265a3805833e5cd84c966aed (patch) | |
tree | 33c6040c050f85c537f8dbf5e91d8c281db092cd /src/Wallabag | |
parent | 2ba365c7c49556cd23b444dc3bb8d4a8cf08809d (diff) | |
parent | 2cbee36a0184786644470a84fdd8c720cfcac58e (diff) | |
download | wallabag-73ec68b1ffafb792265a3805833e5cd84c966aed.tar.gz wallabag-73ec68b1ffafb792265a3805833e5cd84c966aed.tar.zst wallabag-73ec68b1ffafb792265a3805833e5cd84c966aed.zip |
Merge pull request #3984 from wallabag/2.4
Merge 2.4 into master
Diffstat (limited to 'src/Wallabag')
120 files changed, 2363 insertions, 952 deletions
diff --git a/src/Wallabag/AnnotationBundle/DataFixtures/ORM/LoadAnnotationData.php b/src/Wallabag/AnnotationBundle/DataFixtures/AnnotationFixtures.php index 20e07fa3..ed46cea9 100644 --- a/src/Wallabag/AnnotationBundle/DataFixtures/ORM/LoadAnnotationData.php +++ b/src/Wallabag/AnnotationBundle/DataFixtures/AnnotationFixtures.php | |||
@@ -1,13 +1,15 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Wallabag\AnnotationBundle\DataFixtures\ORM; | 3 | namespace Wallabag\AnnotationBundle\DataFixtures; |
4 | 4 | ||
5 | use Doctrine\Common\DataFixtures\AbstractFixture; | 5 | use Doctrine\Bundle\FixturesBundle\Fixture; |
6 | use Doctrine\Common\DataFixtures\OrderedFixtureInterface; | 6 | use Doctrine\Common\DataFixtures\DependentFixtureInterface; |
7 | use Doctrine\Common\Persistence\ObjectManager; | 7 | use Doctrine\Common\Persistence\ObjectManager; |
8 | use Wallabag\AnnotationBundle\Entity\Annotation; | 8 | use Wallabag\AnnotationBundle\Entity\Annotation; |
9 | use Wallabag\CoreBundle\DataFixtures\EntryFixtures; | ||
10 | use Wallabag\UserBundle\DataFixtures\UserFixtures; | ||
9 | 11 | ||
10 | class LoadAnnotationData extends AbstractFixture implements OrderedFixtureInterface | 12 | class AnnotationFixtures extends Fixture implements DependentFixtureInterface |
11 | { | 13 | { |
12 | /** | 14 | /** |
13 | * {@inheritdoc} | 15 | * {@inheritdoc} |
@@ -38,8 +40,11 @@ class LoadAnnotationData extends AbstractFixture implements OrderedFixtureInterf | |||
38 | /** | 40 | /** |
39 | * {@inheritdoc} | 41 | * {@inheritdoc} |
40 | */ | 42 | */ |
41 | public function getOrder() | 43 | public function getDependencies() |
42 | { | 44 | { |
43 | return 35; | 45 | return [ |
46 | EntryFixtures::class, | ||
47 | UserFixtures::class, | ||
48 | ]; | ||
44 | } | 49 | } |
45 | } | 50 | } |
diff --git a/src/Wallabag/ApiBundle/Controller/DeveloperController.php b/src/Wallabag/ApiBundle/Controller/DeveloperController.php index c7178017..ae7e83da 100644 --- a/src/Wallabag/ApiBundle/Controller/DeveloperController.php +++ b/src/Wallabag/ApiBundle/Controller/DeveloperController.php | |||
@@ -2,9 +2,9 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ApiBundle\Controller; | 3 | namespace Wallabag\ApiBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 5 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
7 | use Symfony\Component\HttpFoundation\Request; | 6 | use Symfony\Component\HttpFoundation\Request; |
7 | use Symfony\Component\Routing\Annotation\Route; | ||
8 | use Wallabag\ApiBundle\Entity\Client; | 8 | use Wallabag\ApiBundle\Entity\Client; |
9 | use Wallabag\ApiBundle\Form\Type\ClientType; | 9 | use Wallabag\ApiBundle\Form\Type\ClientType; |
10 | 10 | ||
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php index 33b75665..aaacdcdc 100644 --- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php +++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php | |||
@@ -4,18 +4,17 @@ namespace Wallabag\ApiBundle\Controller; | |||
4 | 4 | ||
5 | use Hateoas\Configuration\Route; | 5 | use Hateoas\Configuration\Route; |
6 | use Hateoas\Representation\Factory\PagerfantaFactory; | 6 | use Hateoas\Representation\Factory\PagerfantaFactory; |
7 | use JMS\Serializer\SerializationContext; | ||
8 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | 7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; |
9 | use Symfony\Component\HttpFoundation\JsonResponse; | 8 | use Symfony\Component\HttpFoundation\JsonResponse; |
10 | use Symfony\Component\HttpFoundation\Request; | 9 | use Symfony\Component\HttpFoundation\Request; |
11 | use Symfony\Component\HttpFoundation\Response; | 10 | use Symfony\Component\HttpFoundation\Response; |
12 | use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; | 11 | use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; |
13 | use Symfony\Component\HttpKernel\Exception\HttpException; | 12 | use Symfony\Component\HttpKernel\Exception\HttpException; |
14 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | ||
15 | use Wallabag\CoreBundle\Entity\Entry; | 13 | use Wallabag\CoreBundle\Entity\Entry; |
16 | use Wallabag\CoreBundle\Entity\Tag; | 14 | use Wallabag\CoreBundle\Entity\Tag; |
17 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; | 15 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; |
18 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | 16 | use Wallabag\CoreBundle\Event\EntrySavedEvent; |
17 | use Wallabag\CoreBundle\Helper\UrlHasher; | ||
19 | 18 | ||
20 | class EntryRestController extends WallabagRestController | 19 | class EntryRestController extends WallabagRestController |
21 | { | 20 | { |
@@ -29,8 +28,10 @@ class EntryRestController extends WallabagRestController | |||
29 | * @ApiDoc( | 28 | * @ApiDoc( |
30 | * parameters={ | 29 | * parameters={ |
31 | * {"name"="return_id", "dataType"="string", "required"=false, "format"="1 or 0", "description"="Set 1 if you want to retrieve ID in case entry(ies) exists, 0 by default"}, | 30 | * {"name"="return_id", "dataType"="string", "required"=false, "format"="1 or 0", "description"="Set 1 if you want to retrieve ID in case entry(ies) exists, 0 by default"}, |
32 | * {"name"="url", "dataType"="string", "required"=true, "format"="An url", "description"="Url to check if it exists"}, | 31 | * {"name"="url", "dataType"="string", "required"=true, "format"="An url", "description"="DEPRECATED, use hashed_url instead"}, |
33 | * {"name"="urls", "dataType"="string", "required"=false, "format"="An array of urls (?urls[]=http...&urls[]=http...)", "description"="Urls (as an array) to check if it exists"} | 32 | * {"name"="urls", "dataType"="string", "required"=false, "format"="An array of urls (?urls[]=http...&urls[]=http...)", "description"="DEPRECATED, use hashed_urls instead"}, |
33 | * {"name"="hashed_url", "dataType"="string", "required"=false, "format"="A hashed url", "description"="Hashed url using SHA1 to check if it exists"}, | ||
34 | * {"name"="hashed_urls", "dataType"="string", "required"=false, "format"="An array of hashed urls (?hashed_urls[]=xxx...&hashed_urls[]=xxx...)", "description"="An array of hashed urls using SHA1 to check if they exist"} | ||
34 | * } | 35 | * } |
35 | * ) | 36 | * ) |
36 | * | 37 | * |
@@ -39,38 +40,49 @@ class EntryRestController extends WallabagRestController | |||
39 | public function getEntriesExistsAction(Request $request) | 40 | public function getEntriesExistsAction(Request $request) |
40 | { | 41 | { |
41 | $this->validateAuthentication(); | 42 | $this->validateAuthentication(); |
43 | $repo = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry'); | ||
42 | 44 | ||
43 | $returnId = (null === $request->query->get('return_id')) ? false : (bool) $request->query->get('return_id'); | 45 | $returnId = (null === $request->query->get('return_id')) ? false : (bool) $request->query->get('return_id'); |
44 | $urls = $request->query->get('urls', []); | ||
45 | |||
46 | // handle multiple urls first | ||
47 | if (!empty($urls)) { | ||
48 | $results = []; | ||
49 | foreach ($urls as $url) { | ||
50 | $res = $this->getDoctrine() | ||
51 | ->getRepository('WallabagCoreBundle:Entry') | ||
52 | ->findByUrlAndUserId($url, $this->getUser()->getId()); | ||
53 | |||
54 | $results[$url] = $this->returnExistInformation($res, $returnId); | ||
55 | } | ||
56 | 46 | ||
57 | return $this->sendResponse($results); | 47 | $hashedUrls = $request->query->get('hashed_urls', []); |
48 | $hashedUrl = $request->query->get('hashed_url', ''); | ||
49 | if (!empty($hashedUrl)) { | ||
50 | $hashedUrls[] = $hashedUrl; | ||
58 | } | 51 | } |
59 | 52 | ||
60 | // let's see if it is a simple url? | 53 | $urls = $request->query->get('urls', []); |
61 | $url = $request->query->get('url', ''); | 54 | $url = $request->query->get('url', ''); |
55 | if (!empty($url)) { | ||
56 | $urls[] = $url; | ||
57 | } | ||
58 | |||
59 | $urlHashMap = []; | ||
60 | foreach ($urls as $urlToHash) { | ||
61 | $urlHash = UrlHasher::hashUrl($urlToHash); | ||
62 | $hashedUrls[] = $urlHash; | ||
63 | $urlHashMap[$urlHash] = $urlToHash; | ||
64 | } | ||
62 | 65 | ||
63 | if (empty($url)) { | 66 | if (empty($hashedUrls)) { |
64 | throw $this->createAccessDeniedException('URL is empty?, logged user id: ' . $this->getUser()->getId()); | 67 | throw $this->createAccessDeniedException('URL is empty?, logged user id: ' . $this->getUser()->getId()); |
65 | } | 68 | } |
66 | 69 | ||
67 | $res = $this->getDoctrine() | 70 | $results = []; |
68 | ->getRepository('WallabagCoreBundle:Entry') | 71 | foreach ($hashedUrls as $hashedUrlToSearch) { |
69 | ->findByUrlAndUserId($url, $this->getUser()->getId()); | 72 | $res = $repo->findByHashedUrlAndUserId($hashedUrlToSearch, $this->getUser()->getId()); |
73 | |||
74 | $results[$hashedUrlToSearch] = $this->returnExistInformation($res, $returnId); | ||
75 | } | ||
70 | 76 | ||
71 | $exists = $this->returnExistInformation($res, $returnId); | 77 | $results = $this->replaceUrlHashes($results, $urlHashMap); |
72 | 78 | ||
73 | return $this->sendResponse(['exists' => $exists]); | 79 | if (!empty($url) || !empty($hashedUrl)) { |
80 | $hu = array_keys($results)[0]; | ||
81 | |||
82 | return $this->sendResponse(['exists' => $results[$hu]]); | ||
83 | } | ||
84 | |||
85 | return $this->sendResponse($results); | ||
74 | } | 86 | } |
75 | 87 | ||
76 | /** | 88 | /** |
@@ -80,13 +92,14 @@ class EntryRestController extends WallabagRestController | |||
80 | * parameters={ | 92 | * parameters={ |
81 | * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by archived status."}, | 93 | * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by archived status."}, |
82 | * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by starred status."}, | 94 | * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by starred status."}, |
83 | * {"name"="sort", "dataType"="string", "required"=false, "format"="'created' or 'updated', default 'created'", "description"="sort entries by date."}, | 95 | * {"name"="sort", "dataType"="string", "required"=false, "format"="'created' or 'updated' or 'archived', default 'created'", "description"="sort entries by date."}, |
84 | * {"name"="order", "dataType"="string", "required"=false, "format"="'asc' or 'desc', default 'desc'", "description"="order of sort."}, | 96 | * {"name"="order", "dataType"="string", "required"=false, "format"="'asc' or 'desc', default 'desc'", "description"="order of sort."}, |
85 | * {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."}, | 97 | * {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."}, |
86 | * {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."}, | 98 | * {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."}, |
87 | * {"name"="tags", "dataType"="string", "required"=false, "format"="api,rest", "description"="a list of tags url encoded. Will returns entries that matches ALL tags."}, | 99 | * {"name"="tags", "dataType"="string", "required"=false, "format"="api,rest", "description"="a list of tags url encoded. Will returns entries that matches ALL tags."}, |
88 | * {"name"="since", "dataType"="integer", "required"=false, "format"="default '0'", "description"="The timestamp since when you want entries updated."}, | 100 | * {"name"="since", "dataType"="integer", "required"=false, "format"="default '0'", "description"="The timestamp since when you want entries updated."}, |
89 | * {"name"="public", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by entries with a public link"}, | 101 | * {"name"="public", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by entries with a public link"}, |
102 | * {"name"="detail", "dataType"="string", "required"=false, "format"="metadata or full, metadata by default", "description"="include content field if 'full'. 'full' by default for backward compatibility."}, | ||
90 | * } | 103 | * } |
91 | * ) | 104 | * ) |
92 | * | 105 | * |
@@ -105,6 +118,7 @@ class EntryRestController extends WallabagRestController | |||
105 | $perPage = (int) $request->query->get('perPage', 30); | 118 | $perPage = (int) $request->query->get('perPage', 30); |
106 | $tags = \is_array($request->query->get('tags')) ? '' : (string) $request->query->get('tags', ''); | 119 | $tags = \is_array($request->query->get('tags')) ? '' : (string) $request->query->get('tags', ''); |
107 | $since = $request->query->get('since', 0); | 120 | $since = $request->query->get('since', 0); |
121 | $detail = strtolower($request->query->get('detail', 'full')); | ||
108 | 122 | ||
109 | try { | 123 | try { |
110 | /** @var \Pagerfanta\Pagerfanta $pager */ | 124 | /** @var \Pagerfanta\Pagerfanta $pager */ |
@@ -116,7 +130,8 @@ class EntryRestController extends WallabagRestController | |||
116 | $sort, | 130 | $sort, |
117 | $order, | 131 | $order, |
118 | $since, | 132 | $since, |
119 | $tags | 133 | $tags, |
134 | $detail | ||
120 | ); | 135 | ); |
121 | } catch (\Exception $e) { | 136 | } catch (\Exception $e) { |
122 | throw new BadRequestHttpException($e->getMessage()); | 137 | throw new BadRequestHttpException($e->getMessage()); |
@@ -140,8 +155,9 @@ class EntryRestController extends WallabagRestController | |||
140 | 'perPage' => $perPage, | 155 | 'perPage' => $perPage, |
141 | 'tags' => $tags, | 156 | 'tags' => $tags, |
142 | 'since' => $since, | 157 | 'since' => $since, |
158 | 'detail' => $detail, | ||
143 | ], | 159 | ], |
144 | UrlGeneratorInterface::ABSOLUTE_URL | 160 | true |
145 | ) | 161 | ) |
146 | ); | 162 | ); |
147 | 163 | ||
@@ -349,9 +365,7 @@ class EntryRestController extends WallabagRestController | |||
349 | 'language' => !empty($data['language']) ? $data['language'] : $entry->getLanguage(), | 365 | 'language' => !empty($data['language']) ? $data['language'] : $entry->getLanguage(), |
350 | 'date' => !empty($data['publishedAt']) ? $data['publishedAt'] : $entry->getPublishedAt(), | 366 | 'date' => !empty($data['publishedAt']) ? $data['publishedAt'] : $entry->getPublishedAt(), |
351 | // faking the open graph preview picture | 367 | // faking the open graph preview picture |
352 | 'open_graph' => [ | 368 | 'image' => !empty($data['picture']) ? $data['picture'] : $entry->getPreviewPicture(), |
353 | 'og_image' => !empty($data['picture']) ? $data['picture'] : $entry->getPreviewPicture(), | ||
354 | ], | ||
355 | 'authors' => \is_string($data['authors']) ? explode(',', $data['authors']) : $entry->getPublishedBy(), | 369 | 'authors' => \is_string($data['authors']) ? explode(',', $data['authors']) : $entry->getPublishedBy(), |
356 | ] | 370 | ] |
357 | ); | 371 | ); |
@@ -363,7 +377,7 @@ class EntryRestController extends WallabagRestController | |||
363 | } | 377 | } |
364 | 378 | ||
365 | if (null !== $data['isArchived']) { | 379 | if (null !== $data['isArchived']) { |
366 | $entry->setArchived((bool) $data['isArchived']); | 380 | $entry->updateArchived((bool) $data['isArchived']); |
367 | } | 381 | } |
368 | 382 | ||
369 | if (null !== $data['isStarred']) { | 383 | if (null !== $data['isStarred']) { |
@@ -479,7 +493,7 @@ class EntryRestController extends WallabagRestController | |||
479 | } | 493 | } |
480 | 494 | ||
481 | if (null !== $data['isArchived']) { | 495 | if (null !== $data['isArchived']) { |
482 | $entry->setArchived((bool) $data['isArchived']); | 496 | $entry->updateArchived((bool) $data['isArchived']); |
483 | } | 497 | } |
484 | 498 | ||
485 | if (null !== $data['isStarred']) { | 499 | if (null !== $data['isStarred']) { |
@@ -787,21 +801,21 @@ class EntryRestController extends WallabagRestController | |||
787 | } | 801 | } |
788 | 802 | ||
789 | /** | 803 | /** |
790 | * Shortcut to send data serialized in json. | 804 | * Replace the hashedUrl keys in $results with the unhashed URL from the |
791 | * | 805 | * request, as recorded in $urlHashMap. |
792 | * @param mixed $data | ||
793 | * | ||
794 | * @return JsonResponse | ||
795 | */ | 806 | */ |
796 | private function sendResponse($data) | 807 | private function replaceUrlHashes(array $results, array $urlHashMap) |
797 | { | 808 | { |
798 | // https://github.com/schmittjoh/JMSSerializerBundle/issues/293 | 809 | $newResults = []; |
799 | $context = new SerializationContext(); | 810 | foreach ($results as $hash => $res) { |
800 | $context->setSerializeNull(true); | 811 | if (isset($urlHashMap[$hash])) { |
801 | 812 | $newResults[$urlHashMap[$hash]] = $res; | |
802 | $json = $this->get('jms_serializer')->serialize($data, 'json', $context); | 813 | } else { |
814 | $newResults[$hash] = $res; | ||
815 | } | ||
816 | } | ||
803 | 817 | ||
804 | return (new JsonResponse())->setJson($json); | 818 | return $newResults; |
805 | } | 819 | } |
806 | 820 | ||
807 | /** | 821 | /** |
@@ -832,8 +846,8 @@ class EntryRestController extends WallabagRestController | |||
832 | /** | 846 | /** |
833 | * Return information about the entry if it exist and depending on the id or not. | 847 | * Return information about the entry if it exist and depending on the id or not. |
834 | * | 848 | * |
835 | * @param Entry|null $entry | 849 | * @param Entry|bool|null $entry |
836 | * @param bool $returnId | 850 | * @param bool $returnId |
837 | * | 851 | * |
838 | * @return bool|int | 852 | * @return bool|int |
839 | */ | 853 | */ |
diff --git a/src/Wallabag/ApiBundle/Controller/SearchRestController.php b/src/Wallabag/ApiBundle/Controller/SearchRestController.php new file mode 100644 index 00000000..d9f99844 --- /dev/null +++ b/src/Wallabag/ApiBundle/Controller/SearchRestController.php | |||
@@ -0,0 +1,65 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\ApiBundle\Controller; | ||
4 | |||
5 | use Hateoas\Configuration\Route; | ||
6 | use Hateoas\Representation\Factory\PagerfantaFactory; | ||
7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | ||
8 | use Pagerfanta\Adapter\DoctrineORMAdapter; | ||
9 | use Pagerfanta\Pagerfanta; | ||
10 | use Symfony\Component\HttpFoundation\JsonResponse; | ||
11 | use Symfony\Component\HttpFoundation\Request; | ||
12 | |||
13 | class SearchRestController extends WallabagRestController | ||
14 | { | ||
15 | /** | ||
16 | * Search all entries by term. | ||
17 | * | ||
18 | * @ApiDoc( | ||
19 | * parameters={ | ||
20 | * {"name"="term", "dataType"="string", "required"=false, "format"="any", "description"="Any query term"}, | ||
21 | * {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."}, | ||
22 | * {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."} | ||
23 | * } | ||
24 | * ) | ||
25 | * | ||
26 | * @return JsonResponse | ||
27 | */ | ||
28 | public function getSearchAction(Request $request) | ||
29 | { | ||
30 | $this->validateAuthentication(); | ||
31 | |||
32 | $term = $request->query->get('term'); | ||
33 | $page = (int) $request->query->get('page', 1); | ||
34 | $perPage = (int) $request->query->get('perPage', 30); | ||
35 | |||
36 | $qb = $this->get('wallabag_core.entry_repository') | ||
37 | ->getBuilderForSearchByUser( | ||
38 | $this->getUser()->getId(), | ||
39 | $term, | ||
40 | null | ||
41 | ); | ||
42 | |||
43 | $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false); | ||
44 | $pager = new Pagerfanta($pagerAdapter); | ||
45 | |||
46 | $pager->setMaxPerPage($perPage); | ||
47 | $pager->setCurrentPage($page); | ||
48 | |||
49 | $pagerfantaFactory = new PagerfantaFactory('page', 'perPage'); | ||
50 | $paginatedCollection = $pagerfantaFactory->createRepresentation( | ||
51 | $pager, | ||
52 | new Route( | ||
53 | 'api_get_search', | ||
54 | [ | ||
55 | 'term' => $term, | ||
56 | 'page' => $page, | ||
57 | 'perPage' => $perPage, | ||
58 | ], | ||
59 | true | ||
60 | ) | ||
61 | ); | ||
62 | |||
63 | return $this->sendResponse($paginatedCollection); | ||
64 | } | ||
65 | } | ||
diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php index 7d8cfbba..f18b0910 100644 --- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php | |||
@@ -3,6 +3,7 @@ | |||
3 | namespace Wallabag\ApiBundle\Controller; | 3 | namespace Wallabag\ApiBundle\Controller; |
4 | 4 | ||
5 | use FOS\RestBundle\Controller\FOSRestController; | 5 | use FOS\RestBundle\Controller\FOSRestController; |
6 | use JMS\Serializer\SerializationContext; | ||
6 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | 7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; |
7 | use Symfony\Component\HttpFoundation\JsonResponse; | 8 | use Symfony\Component\HttpFoundation\JsonResponse; |
8 | use Symfony\Component\Security\Core\Exception\AccessDeniedException; | 9 | use Symfony\Component\Security\Core\Exception\AccessDeniedException; |
@@ -14,6 +15,8 @@ class WallabagRestController extends FOSRestController | |||
14 | * | 15 | * |
15 | * @ApiDoc() | 16 | * @ApiDoc() |
16 | * | 17 | * |
18 | * @deprecated Should use info endpoint instead | ||
19 | * | ||
17 | * @return JsonResponse | 20 | * @return JsonResponse |
18 | */ | 21 | */ |
19 | public function getVersionAction() | 22 | public function getVersionAction() |
@@ -24,6 +27,24 @@ class WallabagRestController extends FOSRestController | |||
24 | return (new JsonResponse())->setJson($json); | 27 | return (new JsonResponse())->setJson($json); |
25 | } | 28 | } |
26 | 29 | ||
30 | /** | ||
31 | * Retrieve information about the wallabag instance. | ||
32 | * | ||
33 | * @ApiDoc() | ||
34 | * | ||
35 | * @return JsonResponse | ||
36 | */ | ||
37 | public function getInfoAction() | ||
38 | { | ||
39 | $info = [ | ||
40 | 'appname' => 'wallabag', | ||
41 | 'version' => $this->container->getParameter('wallabag_core.version'), | ||
42 | 'allowed_registration' => $this->container->getParameter('wallabag_user.registration_enabled'), | ||
43 | ]; | ||
44 | |||
45 | return (new JsonResponse())->setJson($this->get('jms_serializer')->serialize($info, 'json')); | ||
46 | } | ||
47 | |||
27 | protected function validateAuthentication() | 48 | protected function validateAuthentication() |
28 | { | 49 | { |
29 | if (false === $this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { | 50 | if (false === $this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { |
@@ -44,4 +65,22 @@ class WallabagRestController extends FOSRestController | |||
44 | throw $this->createAccessDeniedException('Access forbidden. Entry user id: ' . $requestUserId . ', logged user id: ' . $user->getId()); | 65 | throw $this->createAccessDeniedException('Access forbidden. Entry user id: ' . $requestUserId . ', logged user id: ' . $user->getId()); |
45 | } | 66 | } |
46 | } | 67 | } |
68 | |||
69 | /** | ||
70 | * Shortcut to send data serialized in json. | ||
71 | * | ||
72 | * @param mixed $data | ||
73 | * | ||
74 | * @return JsonResponse | ||
75 | */ | ||
76 | protected function sendResponse($data) | ||
77 | { | ||
78 | // https://github.com/schmittjoh/JMSSerializerBundle/issues/293 | ||
79 | $context = new SerializationContext(); | ||
80 | $context->setSerializeNull(true); | ||
81 | |||
82 | $json = $this->get('jms_serializer')->serialize($data, 'json', $context); | ||
83 | |||
84 | return (new JsonResponse())->setJson($json); | ||
85 | } | ||
47 | } | 86 | } |
diff --git a/src/Wallabag/ApiBundle/Entity/AccessToken.php b/src/Wallabag/ApiBundle/Entity/AccessToken.php index c09a0c80..98e0af3e 100644 --- a/src/Wallabag/ApiBundle/Entity/AccessToken.php +++ b/src/Wallabag/ApiBundle/Entity/AccessToken.php | |||
@@ -8,6 +8,22 @@ use FOS\OAuthServerBundle\Entity\AccessToken as BaseAccessToken; | |||
8 | /** | 8 | /** |
9 | * @ORM\Table("oauth2_access_tokens") | 9 | * @ORM\Table("oauth2_access_tokens") |
10 | * @ORM\Entity | 10 | * @ORM\Entity |
11 | * @ORM\AttributeOverrides({ | ||
12 | * @ORM\AttributeOverride(name="token", | ||
13 | * column=@ORM\Column( | ||
14 | * name = "token", | ||
15 | * type = "string", | ||
16 | * length = 191 | ||
17 | * ) | ||
18 | * ), | ||
19 | * @ORM\AttributeOverride(name="scope", | ||
20 | * column=@ORM\Column( | ||
21 | * name = "scope", | ||
22 | * type = "string", | ||
23 | * length = 191 | ||
24 | * ) | ||
25 | * ) | ||
26 | * }) | ||
11 | */ | 27 | */ |
12 | class AccessToken extends BaseAccessToken | 28 | class AccessToken extends BaseAccessToken |
13 | { | 29 | { |
@@ -26,6 +42,7 @@ class AccessToken extends BaseAccessToken | |||
26 | 42 | ||
27 | /** | 43 | /** |
28 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User") | 44 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User") |
45 | * @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE") | ||
29 | */ | 46 | */ |
30 | protected $user; | 47 | protected $user; |
31 | } | 48 | } |
diff --git a/src/Wallabag/ApiBundle/Entity/AuthCode.php b/src/Wallabag/ApiBundle/Entity/AuthCode.php index 4d4b09fe..7c9c8539 100644 --- a/src/Wallabag/ApiBundle/Entity/AuthCode.php +++ b/src/Wallabag/ApiBundle/Entity/AuthCode.php | |||
@@ -8,6 +8,22 @@ use FOS\OAuthServerBundle\Entity\AuthCode as BaseAuthCode; | |||
8 | /** | 8 | /** |
9 | * @ORM\Table("oauth2_auth_codes") | 9 | * @ORM\Table("oauth2_auth_codes") |
10 | * @ORM\Entity | 10 | * @ORM\Entity |
11 | * @ORM\AttributeOverrides({ | ||
12 | * @ORM\AttributeOverride(name="token", | ||
13 | * column=@ORM\Column( | ||
14 | * name = "token", | ||
15 | * type = "string", | ||
16 | * length = 191 | ||
17 | * ) | ||
18 | * ), | ||
19 | * @ORM\AttributeOverride(name="scope", | ||
20 | * column=@ORM\Column( | ||
21 | * name = "scope", | ||
22 | * type = "string", | ||
23 | * length = 191 | ||
24 | * ) | ||
25 | * ) | ||
26 | * }) | ||
11 | */ | 27 | */ |
12 | class AuthCode extends BaseAuthCode | 28 | class AuthCode extends BaseAuthCode |
13 | { | 29 | { |
@@ -26,6 +42,7 @@ class AuthCode extends BaseAuthCode | |||
26 | 42 | ||
27 | /** | 43 | /** |
28 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User") | 44 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User") |
45 | * @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE") | ||
29 | */ | 46 | */ |
30 | protected $user; | 47 | protected $user; |
31 | } | 48 | } |
diff --git a/src/Wallabag/ApiBundle/Entity/RefreshToken.php b/src/Wallabag/ApiBundle/Entity/RefreshToken.php index 822a02d8..55a507e1 100644 --- a/src/Wallabag/ApiBundle/Entity/RefreshToken.php +++ b/src/Wallabag/ApiBundle/Entity/RefreshToken.php | |||
@@ -8,6 +8,22 @@ use FOS\OAuthServerBundle\Entity\RefreshToken as BaseRefreshToken; | |||
8 | /** | 8 | /** |
9 | * @ORM\Table("oauth2_refresh_tokens") | 9 | * @ORM\Table("oauth2_refresh_tokens") |
10 | * @ORM\Entity | 10 | * @ORM\Entity |
11 | * @ORM\AttributeOverrides({ | ||
12 | * @ORM\AttributeOverride(name="token", | ||
13 | * column=@ORM\Column( | ||
14 | * name = "token", | ||
15 | * type = "string", | ||
16 | * length = 191 | ||
17 | * ) | ||
18 | * ), | ||
19 | * @ORM\AttributeOverride(name="scope", | ||
20 | * column=@ORM\Column( | ||
21 | * name = "scope", | ||
22 | * type = "string", | ||
23 | * length = 191 | ||
24 | * ) | ||
25 | * ) | ||
26 | * }) | ||
11 | */ | 27 | */ |
12 | class RefreshToken extends BaseRefreshToken | 28 | class RefreshToken extends BaseRefreshToken |
13 | { | 29 | { |
@@ -26,6 +42,7 @@ class RefreshToken extends BaseRefreshToken | |||
26 | 42 | ||
27 | /** | 43 | /** |
28 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User") | 44 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User") |
45 | * @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE") | ||
29 | */ | 46 | */ |
30 | protected $user; | 47 | protected $user; |
31 | } | 48 | } |
diff --git a/src/Wallabag/ApiBundle/Form/Type/ClientType.php b/src/Wallabag/ApiBundle/Form/Type/ClientType.php index fc22538f..14dc5c44 100644 --- a/src/Wallabag/ApiBundle/Form/Type/ClientType.php +++ b/src/Wallabag/ApiBundle/Form/Type/ClientType.php | |||
@@ -20,6 +20,7 @@ class ClientType extends AbstractType | |||
20 | 'required' => false, | 20 | 'required' => false, |
21 | 'label' => 'developer.client.form.redirect_uris_label', | 21 | 'label' => 'developer.client.form.redirect_uris_label', |
22 | 'property_path' => 'redirectUris', | 22 | 'property_path' => 'redirectUris', |
23 | 'default_protocol' => null, | ||
23 | ]) | 24 | ]) |
24 | ->add('save', SubmitType::class, ['label' => 'developer.client.form.save_label']) | 25 | ->add('save', SubmitType::class, ['label' => 'developer.client.form.save_label']) |
25 | ; | 26 | ; |
diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml index c0283e71..06e62c37 100644 --- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml +++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml | |||
@@ -3,6 +3,11 @@ entry: | |||
3 | resource: "WallabagApiBundle:EntryRest" | 3 | resource: "WallabagApiBundle:EntryRest" |
4 | name_prefix: api_ | 4 | name_prefix: api_ |
5 | 5 | ||
6 | search: | ||
7 | type: rest | ||
8 | resource: "WallabagApiBundle:SearchRest" | ||
9 | name_prefix: api_ | ||
10 | |||
6 | tag: | 11 | tag: |
7 | type: rest | 12 | type: rest |
8 | resource: "WallabagApiBundle:TagRest" | 13 | resource: "WallabagApiBundle:TagRest" |
diff --git a/src/Wallabag/CoreBundle/Command/GenerateUrlHashesCommand.php b/src/Wallabag/CoreBundle/Command/GenerateUrlHashesCommand.php new file mode 100644 index 00000000..8f2bff11 --- /dev/null +++ b/src/Wallabag/CoreBundle/Command/GenerateUrlHashesCommand.php | |||
@@ -0,0 +1,99 @@ | |||
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\Helper\UrlHasher; | ||
11 | use Wallabag\UserBundle\Entity\User; | ||
12 | |||
13 | class GenerateUrlHashesCommand extends ContainerAwareCommand | ||
14 | { | ||
15 | /** @var OutputInterface */ | ||
16 | protected $output; | ||
17 | |||
18 | protected function configure() | ||
19 | { | ||
20 | $this | ||
21 | ->setName('wallabag:generate-hashed-urls') | ||
22 | ->setDescription('Generates hashed urls for each entry') | ||
23 | ->setHelp('This command helps you to generates hashes of the url of each entry, to check through API if an URL is already saved') | ||
24 | ->addArgument('username', InputArgument::OPTIONAL, 'User to process entries'); | ||
25 | } | ||
26 | |||
27 | protected function execute(InputInterface $input, OutputInterface $output) | ||
28 | { | ||
29 | $this->output = $output; | ||
30 | |||
31 | $username = (string) $input->getArgument('username'); | ||
32 | |||
33 | if ($username) { | ||
34 | try { | ||
35 | $user = $this->getUser($username); | ||
36 | $this->generateHashedUrls($user); | ||
37 | } catch (NoResultException $e) { | ||
38 | $output->writeln(sprintf('<error>User "%s" not found.</error>', $username)); | ||
39 | |||
40 | return 1; | ||
41 | } | ||
42 | } else { | ||
43 | $users = $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findAll(); | ||
44 | |||
45 | $output->writeln(sprintf('Generating hashed urls for "%d" users', \count($users))); | ||
46 | |||
47 | foreach ($users as $user) { | ||
48 | $output->writeln(sprintf('Processing user: %s', $user->getUsername())); | ||
49 | $this->generateHashedUrls($user); | ||
50 | } | ||
51 | $output->writeln('Finished generated hashed urls'); | ||
52 | } | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | /** | ||
58 | * @param User $user | ||
59 | */ | ||
60 | private function generateHashedUrls(User $user) | ||
61 | { | ||
62 | $em = $this->getContainer()->get('doctrine.orm.entity_manager'); | ||
63 | $repo = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry'); | ||
64 | |||
65 | $entries = $repo->findByUser($user->getId()); | ||
66 | |||
67 | $i = 1; | ||
68 | foreach ($entries as $entry) { | ||
69 | $entry->setHashedUrl(UrlHasher::hashUrl($entry->getUrl())); | ||
70 | $em->persist($entry); | ||
71 | |||
72 | if (0 === ($i % 20)) { | ||
73 | $em->flush(); | ||
74 | } | ||
75 | ++$i; | ||
76 | } | ||
77 | |||
78 | $em->flush(); | ||
79 | |||
80 | $this->output->writeln(sprintf('Generated hashed urls for user: %s', $user->getUserName())); | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * Fetches a user from its username. | ||
85 | * | ||
86 | * @param string $username | ||
87 | * | ||
88 | * @return User | ||
89 | */ | ||
90 | private function getUser($username) | ||
91 | { | ||
92 | return $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findOneByUserName($username); | ||
93 | } | ||
94 | |||
95 | private function getDoctrine() | ||
96 | { | ||
97 | return $this->getContainer()->get('doctrine'); | ||
98 | } | ||
99 | } | ||
diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php index 3c76545c..c58ae2b5 100644 --- a/src/Wallabag/CoreBundle/Command/InstallCommand.php +++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php | |||
@@ -94,8 +94,9 @@ class InstallCommand extends ContainerAwareCommand | |||
94 | $status = '<info>OK!</info>'; | 94 | $status = '<info>OK!</info>'; |
95 | $help = ''; | 95 | $help = ''; |
96 | 96 | ||
97 | $conn = $this->getContainer()->get('doctrine')->getManager()->getConnection(); | ||
98 | |||
97 | try { | 99 | try { |
98 | $conn = $this->getContainer()->get('doctrine')->getManager()->getConnection(); | ||
99 | $conn->connect(); | 100 | $conn->connect(); |
100 | } catch (\Exception $e) { | 101 | } catch (\Exception $e) { |
101 | if (false === strpos($e->getMessage(), 'Unknown database') | 102 | if (false === strpos($e->getMessage(), 'Unknown database') |
@@ -253,7 +254,7 @@ class InstallCommand extends ContainerAwareCommand | |||
253 | $question->setHidden(true); | 254 | $question->setHidden(true); |
254 | $user->setPlainPassword($this->io->askQuestion($question)); | 255 | $user->setPlainPassword($this->io->askQuestion($question)); |
255 | 256 | ||
256 | $user->setEmail($this->io->ask('Email', '')); | 257 | $user->setEmail($this->io->ask('Email', 'wallabag@wallabag.io')); |
257 | 258 | ||
258 | $user->setEnabled(true); | 259 | $user->setEnabled(true); |
259 | $user->addRole('ROLE_SUPER_ADMIN'); | 260 | $user->addRole('ROLE_SUPER_ADMIN'); |
diff --git a/src/Wallabag/CoreBundle/Command/ShowUserCommand.php b/src/Wallabag/CoreBundle/Command/ShowUserCommand.php index a0184267..c95efbf3 100644 --- a/src/Wallabag/CoreBundle/Command/ShowUserCommand.php +++ b/src/Wallabag/CoreBundle/Command/ShowUserCommand.php | |||
@@ -57,7 +57,8 @@ class ShowUserCommand extends ContainerAwareCommand | |||
57 | sprintf('Display name: %s', $user->getName()), | 57 | sprintf('Display name: %s', $user->getName()), |
58 | sprintf('Creation date: %s', $user->getCreatedAt()->format('Y-m-d H:i:s')), | 58 | sprintf('Creation date: %s', $user->getCreatedAt()->format('Y-m-d H:i:s')), |
59 | sprintf('Last login: %s', null !== $user->getLastLogin() ? $user->getLastLogin()->format('Y-m-d H:i:s') : 'never'), | 59 | sprintf('Last login: %s', null !== $user->getLastLogin() ? $user->getLastLogin()->format('Y-m-d H:i:s') : 'never'), |
60 | sprintf('2FA activated: %s', $user->isTwoFactorAuthentication() ? 'yes' : 'no'), | 60 | sprintf('2FA (email) activated: %s', $user->isEmailTwoFactor() ? 'yes' : 'no'), |
61 | sprintf('2FA (OTP) activated: %s', $user->isGoogleAuthenticatorEnabled() ? 'yes' : 'no'), | ||
61 | ]); | 62 | ]); |
62 | } | 63 | } |
63 | 64 | ||
diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php index b999c539..3b281d48 100644 --- a/src/Wallabag/CoreBundle/Controller/ConfigController.php +++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php | |||
@@ -2,17 +2,19 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\Controller; | 3 | namespace Wallabag\CoreBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | 5 | use PragmaRX\Recovery\Recovery as BackupCodes; |
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
7 | use Symfony\Component\HttpFoundation\JsonResponse; | 7 | use Symfony\Component\HttpFoundation\JsonResponse; |
8 | use Symfony\Component\HttpFoundation\RedirectResponse; | 8 | use Symfony\Component\HttpFoundation\RedirectResponse; |
9 | use Symfony\Component\HttpFoundation\Request; | 9 | use Symfony\Component\HttpFoundation\Request; |
10 | use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; | 10 | use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; |
11 | use Symfony\Component\Routing\Annotation\Route; | ||
12 | use Symfony\Component\Validator\Constraints\Locale as LocaleConstraint; | ||
11 | use Wallabag\CoreBundle\Entity\Config; | 13 | use Wallabag\CoreBundle\Entity\Config; |
12 | use Wallabag\CoreBundle\Entity\TaggingRule; | 14 | use Wallabag\CoreBundle\Entity\TaggingRule; |
13 | use Wallabag\CoreBundle\Form\Type\ChangePasswordType; | 15 | use Wallabag\CoreBundle\Form\Type\ChangePasswordType; |
14 | use Wallabag\CoreBundle\Form\Type\ConfigType; | 16 | use Wallabag\CoreBundle\Form\Type\ConfigType; |
15 | use Wallabag\CoreBundle\Form\Type\RssType; | 17 | use Wallabag\CoreBundle\Form\Type\FeedType; |
16 | use Wallabag\CoreBundle\Form\Type\TaggingRuleType; | 18 | use Wallabag\CoreBundle\Form\Type\TaggingRuleType; |
17 | use Wallabag\CoreBundle\Form\Type\UserInformationType; | 19 | use Wallabag\CoreBundle\Form\Type\UserInformationType; |
18 | use Wallabag\CoreBundle\Tools\Utils; | 20 | use Wallabag\CoreBundle\Tools\Utils; |
@@ -45,7 +47,7 @@ class ConfigController extends Controller | |||
45 | $activeTheme = $this->get('liip_theme.active_theme'); | 47 | $activeTheme = $this->get('liip_theme.active_theme'); |
46 | $activeTheme->setName($config->getTheme()); | 48 | $activeTheme->setName($config->getTheme()); |
47 | 49 | ||
48 | $this->get('session')->getFlashBag()->add( | 50 | $this->addFlash( |
49 | 'notice', | 51 | 'notice', |
50 | 'flashes.config.notice.config_saved' | 52 | 'flashes.config.notice.config_saved' |
51 | ); | 53 | ); |
@@ -67,7 +69,7 @@ class ConfigController extends Controller | |||
67 | $userManager->updateUser($user, true); | 69 | $userManager->updateUser($user, true); |
68 | } | 70 | } |
69 | 71 | ||
70 | $this->get('session')->getFlashBag()->add('notice', $message); | 72 | $this->addFlash('notice', $message); |
71 | 73 | ||
72 | return $this->redirect($this->generateUrl('config') . '#set4'); | 74 | return $this->redirect($this->generateUrl('config') . '#set4'); |
73 | } | 75 | } |
@@ -82,7 +84,7 @@ class ConfigController extends Controller | |||
82 | if ($userForm->isSubmitted() && $userForm->isValid()) { | 84 | if ($userForm->isSubmitted() && $userForm->isValid()) { |
83 | $userManager->updateUser($user, true); | 85 | $userManager->updateUser($user, true); |
84 | 86 | ||
85 | $this->get('session')->getFlashBag()->add( | 87 | $this->addFlash( |
86 | 'notice', | 88 | 'notice', |
87 | 'flashes.config.notice.user_updated' | 89 | 'flashes.config.notice.user_updated' |
88 | ); | 90 | ); |
@@ -90,17 +92,17 @@ class ConfigController extends Controller | |||
90 | return $this->redirect($this->generateUrl('config') . '#set3'); | 92 | return $this->redirect($this->generateUrl('config') . '#set3'); |
91 | } | 93 | } |
92 | 94 | ||
93 | // handle rss information | 95 | // handle feed information |
94 | $rssForm = $this->createForm(RssType::class, $config, ['action' => $this->generateUrl('config') . '#set2']); | 96 | $feedForm = $this->createForm(FeedType::class, $config, ['action' => $this->generateUrl('config') . '#set2']); |
95 | $rssForm->handleRequest($request); | 97 | $feedForm->handleRequest($request); |
96 | 98 | ||
97 | if ($rssForm->isSubmitted() && $rssForm->isValid()) { | 99 | if ($feedForm->isSubmitted() && $feedForm->isValid()) { |
98 | $em->persist($config); | 100 | $em->persist($config); |
99 | $em->flush(); | 101 | $em->flush(); |
100 | 102 | ||
101 | $this->get('session')->getFlashBag()->add( | 103 | $this->addFlash( |
102 | 'notice', | 104 | 'notice', |
103 | 'flashes.config.notice.rss_updated' | 105 | 'flashes.config.notice.feed_updated' |
104 | ); | 106 | ); |
105 | 107 | ||
106 | return $this->redirect($this->generateUrl('config') . '#set2'); | 108 | return $this->redirect($this->generateUrl('config') . '#set2'); |
@@ -130,7 +132,7 @@ class ConfigController extends Controller | |||
130 | $em->persist($taggingRule); | 132 | $em->persist($taggingRule); |
131 | $em->flush(); | 133 | $em->flush(); |
132 | 134 | ||
133 | $this->get('session')->getFlashBag()->add( | 135 | $this->addFlash( |
134 | 'notice', | 136 | 'notice', |
135 | 'flashes.config.notice.tagging_rules_updated' | 137 | 'flashes.config.notice.tagging_rules_updated' |
136 | ); | 138 | ); |
@@ -141,23 +143,135 @@ class ConfigController extends Controller | |||
141 | return $this->render('WallabagCoreBundle:Config:index.html.twig', [ | 143 | return $this->render('WallabagCoreBundle:Config:index.html.twig', [ |
142 | 'form' => [ | 144 | 'form' => [ |
143 | 'config' => $configForm->createView(), | 145 | 'config' => $configForm->createView(), |
144 | 'rss' => $rssForm->createView(), | 146 | 'feed' => $feedForm->createView(), |
145 | 'pwd' => $pwdForm->createView(), | 147 | 'pwd' => $pwdForm->createView(), |
146 | 'user' => $userForm->createView(), | 148 | 'user' => $userForm->createView(), |
147 | 'new_tagging_rule' => $newTaggingRule->createView(), | 149 | 'new_tagging_rule' => $newTaggingRule->createView(), |
148 | ], | 150 | ], |
149 | 'rss' => [ | 151 | 'feed' => [ |
150 | 'username' => $user->getUsername(), | 152 | 'username' => $user->getUsername(), |
151 | 'token' => $config->getRssToken(), | 153 | 'token' => $config->getFeedToken(), |
152 | ], | 154 | ], |
153 | 'twofactor_auth' => $this->getParameter('twofactor_auth'), | 155 | 'twofactor_auth' => $this->getParameter('twofactor_auth'), |
154 | 'wallabag_url' => $this->getParameter('domain_name'), | 156 | 'wallabag_url' => $this->getParameter('domain_name'), |
155 | 'enabled_users' => $this->get('wallabag_user.user_repository') | 157 | 'enabled_users' => $this->get('wallabag_user.user_repository')->getSumEnabledUsers(), |
156 | ->getSumEnabledUsers(), | ||
157 | ]); | 158 | ]); |
158 | } | 159 | } |
159 | 160 | ||
160 | /** | 161 | /** |
162 | * Enable 2FA using email. | ||
163 | * | ||
164 | * @Route("/config/otp/email", name="config_otp_email") | ||
165 | */ | ||
166 | public function otpEmailAction() | ||
167 | { | ||
168 | if (!$this->getParameter('twofactor_auth')) { | ||
169 | return $this->createNotFoundException('two_factor not enabled'); | ||
170 | } | ||
171 | |||
172 | $user = $this->getUser(); | ||
173 | |||
174 | $user->setGoogleAuthenticatorSecret(null); | ||
175 | $user->setBackupCodes(null); | ||
176 | $user->setEmailTwoFactor(true); | ||
177 | |||
178 | $this->container->get('fos_user.user_manager')->updateUser($user, true); | ||
179 | |||
180 | $this->addFlash( | ||
181 | 'notice', | ||
182 | 'flashes.config.notice.otp_enabled' | ||
183 | ); | ||
184 | |||
185 | return $this->redirect($this->generateUrl('config') . '#set3'); | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * Enable 2FA using OTP app, user will need to confirm the generated code from the app. | ||
190 | * | ||
191 | * @Route("/config/otp/app", name="config_otp_app") | ||
192 | */ | ||
193 | public function otpAppAction() | ||
194 | { | ||
195 | if (!$this->getParameter('twofactor_auth')) { | ||
196 | return $this->createNotFoundException('two_factor not enabled'); | ||
197 | } | ||
198 | |||
199 | $user = $this->getUser(); | ||
200 | $secret = $this->get('scheb_two_factor.security.google_authenticator')->generateSecret(); | ||
201 | |||
202 | $user->setGoogleAuthenticatorSecret($secret); | ||
203 | $user->setEmailTwoFactor(false); | ||
204 | |||
205 | $backupCodes = (new BackupCodes())->toArray(); | ||
206 | $backupCodesHashed = array_map( | ||
207 | function ($backupCode) { | ||
208 | return password_hash($backupCode, PASSWORD_DEFAULT); | ||
209 | }, | ||
210 | $backupCodes | ||
211 | ); | ||
212 | |||
213 | $user->setBackupCodes($backupCodesHashed); | ||
214 | |||
215 | $this->container->get('fos_user.user_manager')->updateUser($user, true); | ||
216 | |||
217 | return $this->render('WallabagCoreBundle:Config:otp_app.html.twig', [ | ||
218 | 'backupCodes' => $backupCodes, | ||
219 | 'qr_code' => $this->get('scheb_two_factor.security.google_authenticator')->getQRContent($user), | ||
220 | ]); | ||
221 | } | ||
222 | |||
223 | /** | ||
224 | * Cancelling 2FA using OTP app. | ||
225 | * | ||
226 | * @Route("/config/otp/app/cancel", name="config_otp_app_cancel") | ||
227 | */ | ||
228 | public function otpAppCancelAction() | ||
229 | { | ||
230 | if (!$this->getParameter('twofactor_auth')) { | ||
231 | return $this->createNotFoundException('two_factor not enabled'); | ||
232 | } | ||
233 | |||
234 | $user = $this->getUser(); | ||
235 | $user->setGoogleAuthenticatorSecret(null); | ||
236 | $user->setBackupCodes(null); | ||
237 | |||
238 | $this->container->get('fos_user.user_manager')->updateUser($user, true); | ||
239 | |||
240 | return $this->redirect($this->generateUrl('config') . '#set3'); | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | * Validate OTP code. | ||
245 | * | ||
246 | * @param Request $request | ||
247 | * | ||
248 | * @Route("/config/otp/app/check", name="config_otp_app_check") | ||
249 | */ | ||
250 | public function otpAppCheckAction(Request $request) | ||
251 | { | ||
252 | $isValid = $this->get('scheb_two_factor.security.google_authenticator')->checkCode( | ||
253 | $this->getUser(), | ||
254 | $request->get('_auth_code') | ||
255 | ); | ||
256 | |||
257 | if (true === $isValid) { | ||
258 | $this->addFlash( | ||
259 | 'notice', | ||
260 | 'flashes.config.notice.otp_enabled' | ||
261 | ); | ||
262 | |||
263 | return $this->redirect($this->generateUrl('config') . '#set3'); | ||
264 | } | ||
265 | |||
266 | $this->addFlash( | ||
267 | 'two_factor', | ||
268 | 'scheb_two_factor.code_invalid' | ||
269 | ); | ||
270 | |||
271 | return $this->redirect($this->generateUrl('config_otp_app')); | ||
272 | } | ||
273 | |||
274 | /** | ||
161 | * @param Request $request | 275 | * @param Request $request |
162 | * | 276 | * |
163 | * @Route("/generate-token", name="generate_token") | 277 | * @Route("/generate-token", name="generate_token") |
@@ -167,19 +281,19 @@ class ConfigController extends Controller | |||
167 | public function generateTokenAction(Request $request) | 281 | public function generateTokenAction(Request $request) |
168 | { | 282 | { |
169 | $config = $this->getConfig(); | 283 | $config = $this->getConfig(); |
170 | $config->setRssToken(Utils::generateToken()); | 284 | $config->setFeedToken(Utils::generateToken()); |
171 | 285 | ||
172 | $em = $this->getDoctrine()->getManager(); | 286 | $em = $this->getDoctrine()->getManager(); |
173 | $em->persist($config); | 287 | $em->persist($config); |
174 | $em->flush(); | 288 | $em->flush(); |
175 | 289 | ||
176 | if ($request->isXmlHttpRequest()) { | 290 | if ($request->isXmlHttpRequest()) { |
177 | return new JsonResponse(['token' => $config->getRssToken()]); | 291 | return new JsonResponse(['token' => $config->getFeedToken()]); |
178 | } | 292 | } |
179 | 293 | ||
180 | $this->get('session')->getFlashBag()->add( | 294 | $this->addFlash( |
181 | 'notice', | 295 | 'notice', |
182 | 'flashes.config.notice.rss_token_updated' | 296 | 'flashes.config.notice.feed_token_updated' |
183 | ); | 297 | ); |
184 | 298 | ||
185 | return $this->redirect($this->generateUrl('config') . '#set2'); | 299 | return $this->redirect($this->generateUrl('config') . '#set2'); |
@@ -202,7 +316,7 @@ class ConfigController extends Controller | |||
202 | $em->remove($rule); | 316 | $em->remove($rule); |
203 | $em->flush(); | 317 | $em->flush(); |
204 | 318 | ||
205 | $this->get('session')->getFlashBag()->add( | 319 | $this->addFlash( |
206 | 'notice', | 320 | 'notice', |
207 | 'flashes.config.notice.tagging_rules_deleted' | 321 | 'flashes.config.notice.tagging_rules_deleted' |
208 | ); | 322 | ); |
@@ -268,7 +382,7 @@ class ConfigController extends Controller | |||
268 | break; | 382 | break; |
269 | } | 383 | } |
270 | 384 | ||
271 | $this->get('session')->getFlashBag()->add( | 385 | $this->addFlash( |
272 | 'notice', | 386 | 'notice', |
273 | 'flashes.config.notice.' . $type . '_reset' | 387 | 'flashes.config.notice.' . $type . '_reset' |
274 | ); | 388 | ); |
@@ -330,6 +444,27 @@ class ConfigController extends Controller | |||
330 | } | 444 | } |
331 | 445 | ||
332 | /** | 446 | /** |
447 | * Change the locale for the current user. | ||
448 | * | ||
449 | * @param Request $request | ||
450 | * @param string $language | ||
451 | * | ||
452 | * @Route("/locale/{language}", name="changeLocale") | ||
453 | * | ||
454 | * @return \Symfony\Component\HttpFoundation\RedirectResponse | ||
455 | */ | ||
456 | public function setLocaleAction(Request $request, $language = null) | ||
457 | { | ||
458 | $errors = $this->get('validator')->validate($language, (new LocaleConstraint())); | ||
459 | |||
460 | if (0 === \count($errors)) { | ||
461 | $request->getSession()->set('_locale', $language); | ||
462 | } | ||
463 | |||
464 | return $this->redirect($request->headers->get('referer', $this->generateUrl('homepage'))); | ||
465 | } | ||
466 | |||
467 | /** | ||
333 | * Remove all tags for given tags and a given user and cleanup orphan tags. | 468 | * Remove all tags for given tags and a given user and cleanup orphan tags. |
334 | * | 469 | * |
335 | * @param array $tags | 470 | * @param array $tags |
diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php index b7fdea27..5c8ecb40 100644 --- a/src/Wallabag/CoreBundle/Controller/EntryController.php +++ b/src/Wallabag/CoreBundle/Controller/EntryController.php | |||
@@ -2,12 +2,13 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\Controller; | 3 | namespace Wallabag\CoreBundle\Controller; |
4 | 4 | ||
5 | use Doctrine\ORM\NoResultException; | ||
5 | use Pagerfanta\Adapter\DoctrineORMAdapter; | 6 | use Pagerfanta\Adapter\DoctrineORMAdapter; |
6 | use Pagerfanta\Exception\OutOfRangeCurrentPageException; | 7 | use Pagerfanta\Exception\OutOfRangeCurrentPageException; |
7 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; | 8 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; |
8 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
9 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 9 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
10 | use Symfony\Component\HttpFoundation\Request; | 10 | use Symfony\Component\HttpFoundation\Request; |
11 | use Symfony\Component\Routing\Annotation\Route; | ||
11 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | 12 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
12 | use Wallabag\CoreBundle\Entity\Entry; | 13 | use Wallabag\CoreBundle\Entity\Entry; |
13 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; | 14 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; |
@@ -233,6 +234,46 @@ class EntryController extends Controller | |||
233 | } | 234 | } |
234 | 235 | ||
235 | /** | 236 | /** |
237 | * Shows untagged articles for current user. | ||
238 | * | ||
239 | * @param Request $request | ||
240 | * @param int $page | ||
241 | * | ||
242 | * @Route("/untagged/list/{page}", name="untagged", defaults={"page" = "1"}) | ||
243 | * | ||
244 | * @return \Symfony\Component\HttpFoundation\Response | ||
245 | */ | ||
246 | public function showUntaggedEntriesAction(Request $request, $page) | ||
247 | { | ||
248 | return $this->showEntries('untagged', $request, $page); | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * Shows random entry depending on the given type. | ||
253 | * | ||
254 | * @param string $type | ||
255 | * | ||
256 | * @Route("/{type}/random", name="random_entry", requirements={"type": "unread|starred|archive|untagged|all"}) | ||
257 | * | ||
258 | * @return \Symfony\Component\HttpFoundation\RedirectResponse | ||
259 | */ | ||
260 | public function redirectRandomEntryAction($type = 'all') | ||
261 | { | ||
262 | try { | ||
263 | $entry = $this->get('wallabag_core.entry_repository') | ||
264 | ->getRandomEntry($this->getUser()->getId(), $type); | ||
265 | } catch (NoResultException $e) { | ||
266 | $bag = $this->get('session')->getFlashBag(); | ||
267 | $bag->clear(); | ||
268 | $bag->add('notice', 'flashes.entry.notice.no_random_entry'); | ||
269 | |||
270 | return $this->redirect($this->generateUrl($type)); | ||
271 | } | ||
272 | |||
273 | return $this->redirect($this->generateUrl('view', ['id' => $entry->getId()])); | ||
274 | } | ||
275 | |||
276 | /** | ||
236 | * Shows entry content. | 277 | * Shows entry content. |
237 | * | 278 | * |
238 | * @param Entry $entry | 279 | * @param Entry $entry |
@@ -466,54 +507,6 @@ class EntryController extends Controller | |||
466 | } | 507 | } |
467 | 508 | ||
468 | /** | 509 | /** |
469 | * Shows untagged articles for current user. | ||
470 | * | ||
471 | * @param Request $request | ||
472 | * @param int $page | ||
473 | * | ||
474 | * @Route("/untagged/list/{page}", name="untagged", defaults={"page" = "1"}) | ||
475 | * | ||
476 | * @return \Symfony\Component\HttpFoundation\Response | ||
477 | */ | ||
478 | public function showUntaggedEntriesAction(Request $request, $page) | ||
479 | { | ||
480 | return $this->showEntries('untagged', $request, $page); | ||
481 | } | ||
482 | |||
483 | /** | ||
484 | * Fetch content and update entry. | ||
485 | * In case it fails, $entry->getContent will return an error message. | ||
486 | * | ||
487 | * @param Entry $entry | ||
488 | * @param string $prefixMessage Should be the translation key: entry_saved or entry_reloaded | ||
489 | */ | ||
490 | private function updateEntry(Entry $entry, $prefixMessage = 'entry_saved') | ||
491 | { | ||
492 | $message = 'flashes.entry.notice.' . $prefixMessage; | ||
493 | |||
494 | try { | ||
495 | $this->get('wallabag_core.content_proxy')->updateEntry($entry, $entry->getUrl()); | ||
496 | } catch (\Exception $e) { | ||
497 | $this->get('logger')->error('Error while saving an entry', [ | ||
498 | 'exception' => $e, | ||
499 | 'entry' => $entry, | ||
500 | ]); | ||
501 | |||
502 | $message = 'flashes.entry.notice.' . $prefixMessage . '_failed'; | ||
503 | } | ||
504 | |||
505 | if (empty($entry->getDomainName())) { | ||
506 | $this->get('wallabag_core.content_proxy')->setEntryDomainName($entry); | ||
507 | } | ||
508 | |||
509 | if (empty($entry->getTitle())) { | ||
510 | $this->get('wallabag_core.content_proxy')->setDefaultEntryTitle($entry); | ||
511 | } | ||
512 | |||
513 | $this->get('session')->getFlashBag()->add('notice', $message); | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * Global method to retrieve entries depending on the given type | 510 | * Global method to retrieve entries depending on the given type |
518 | * It returns the response to be send. | 511 | * It returns the response to be send. |
519 | * | 512 | * |
@@ -532,11 +525,9 @@ class EntryController extends Controller | |||
532 | switch ($type) { | 525 | switch ($type) { |
533 | case 'search': | 526 | case 'search': |
534 | $qb = $repository->getBuilderForSearchByUser($this->getUser()->getId(), $searchTerm, $currentRoute); | 527 | $qb = $repository->getBuilderForSearchByUser($this->getUser()->getId(), $searchTerm, $currentRoute); |
535 | |||
536 | break; | 528 | break; |
537 | case 'untagged': | 529 | case 'untagged': |
538 | $qb = $repository->getBuilderForUntaggedByUser($this->getUser()->getId()); | 530 | $qb = $repository->getBuilderForUntaggedByUser($this->getUser()->getId()); |
539 | |||
540 | break; | 531 | break; |
541 | case 'starred': | 532 | case 'starred': |
542 | $qb = $repository->getBuilderForStarredByUser($this->getUser()->getId()); | 533 | $qb = $repository->getBuilderForStarredByUser($this->getUser()->getId()); |
@@ -588,6 +579,39 @@ class EntryController extends Controller | |||
588 | } | 579 | } |
589 | 580 | ||
590 | /** | 581 | /** |
582 | * Fetch content and update entry. | ||
583 | * In case it fails, $entry->getContent will return an error message. | ||
584 | * | ||
585 | * @param Entry $entry | ||
586 | * @param string $prefixMessage Should be the translation key: entry_saved or entry_reloaded | ||
587 | */ | ||
588 | private function updateEntry(Entry $entry, $prefixMessage = 'entry_saved') | ||
589 | { | ||
590 | $message = 'flashes.entry.notice.' . $prefixMessage; | ||
591 | |||
592 | try { | ||
593 | $this->get('wallabag_core.content_proxy')->updateEntry($entry, $entry->getUrl()); | ||
594 | } catch (\Exception $e) { | ||
595 | $this->get('logger')->error('Error while saving an entry', [ | ||
596 | 'exception' => $e, | ||
597 | 'entry' => $entry, | ||
598 | ]); | ||
599 | |||
600 | $message = 'flashes.entry.notice.' . $prefixMessage . '_failed'; | ||
601 | } | ||
602 | |||
603 | if (empty($entry->getDomainName())) { | ||
604 | $this->get('wallabag_core.content_proxy')->setEntryDomainName($entry); | ||
605 | } | ||
606 | |||
607 | if (empty($entry->getTitle())) { | ||
608 | $this->get('wallabag_core.content_proxy')->setDefaultEntryTitle($entry); | ||
609 | } | ||
610 | |||
611 | $this->get('session')->getFlashBag()->add('notice', $message); | ||
612 | } | ||
613 | |||
614 | /** | ||
591 | * Check if the logged user can manage the given entry. | 615 | * Check if the logged user can manage the given entry. |
592 | * | 616 | * |
593 | * @param Entry $entry | 617 | * @param Entry $entry |
diff --git a/src/Wallabag/CoreBundle/Controller/ExportController.php b/src/Wallabag/CoreBundle/Controller/ExportController.php index 9e9dbe49..9ff35ff5 100644 --- a/src/Wallabag/CoreBundle/Controller/ExportController.php +++ b/src/Wallabag/CoreBundle/Controller/ExportController.php | |||
@@ -2,10 +2,10 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\Controller; | 3 | namespace Wallabag\CoreBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 5 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
7 | use Symfony\Component\HttpFoundation\Request; | 6 | use Symfony\Component\HttpFoundation\Request; |
8 | use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | 7 | use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
8 | use Symfony\Component\Routing\Annotation\Route; | ||
9 | use Wallabag\CoreBundle\Entity\Entry; | 9 | use Wallabag\CoreBundle\Entity\Entry; |
10 | 10 | ||
11 | /** | 11 | /** |
diff --git a/src/Wallabag/CoreBundle/Controller/RssController.php b/src/Wallabag/CoreBundle/Controller/FeedController.php index 848bb814..8d422a90 100644 --- a/src/Wallabag/CoreBundle/Controller/RssController.php +++ b/src/Wallabag/CoreBundle/Controller/FeedController.php | |||
@@ -7,86 +7,97 @@ use Pagerfanta\Adapter\DoctrineORMAdapter; | |||
7 | use Pagerfanta\Exception\OutOfRangeCurrentPageException; | 7 | use Pagerfanta\Exception\OutOfRangeCurrentPageException; |
8 | use Pagerfanta\Pagerfanta; | 8 | use Pagerfanta\Pagerfanta; |
9 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | 9 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; |
10 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
11 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 10 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
12 | use Symfony\Component\HttpFoundation\Request; | ||
13 | use Symfony\Component\HttpFoundation\Response; | 11 | use Symfony\Component\HttpFoundation\Response; |
12 | use Symfony\Component\Routing\Annotation\Route; | ||
14 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | 13 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
15 | use Wallabag\CoreBundle\Entity\Tag; | 14 | use Wallabag\CoreBundle\Entity\Tag; |
16 | use Wallabag\UserBundle\Entity\User; | 15 | use Wallabag\UserBundle\Entity\User; |
17 | 16 | ||
18 | class RssController extends Controller | 17 | class FeedController extends Controller |
19 | { | 18 | { |
20 | /** | 19 | /** |
21 | * Shows unread entries for current user. | 20 | * Shows unread entries for current user. |
22 | * | 21 | * |
23 | * @Route("/{username}/{token}/unread.xml", name="unread_rss", defaults={"_format"="xml"}) | 22 | * @Route("/feed/{username}/{token}/unread/{page}", name="unread_feed", defaults={"page"=1, "_format"="xml"}) |
24 | * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter") | 23 | * |
24 | * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_feed_token_converter") | ||
25 | * | ||
26 | * @param User $user | ||
27 | * @param $page | ||
25 | * | 28 | * |
26 | * @return \Symfony\Component\HttpFoundation\Response | 29 | * @return \Symfony\Component\HttpFoundation\Response |
27 | */ | 30 | */ |
28 | public function showUnreadRSSAction(Request $request, User $user) | 31 | public function showUnreadFeedAction(User $user, $page) |
29 | { | 32 | { |
30 | return $this->showEntries('unread', $user, $request->query->get('page', 1)); | 33 | return $this->showEntries('unread', $user, $page); |
31 | } | 34 | } |
32 | 35 | ||
33 | /** | 36 | /** |
34 | * Shows read entries for current user. | 37 | * Shows read entries for current user. |
35 | * | 38 | * |
36 | * @Route("/{username}/{token}/archive.xml", name="archive_rss", defaults={"_format"="xml"}) | 39 | * @Route("/feed/{username}/{token}/archive/{page}", name="archive_feed", defaults={"page"=1, "_format"="xml"}) |
37 | * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter") | 40 | * |
41 | * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_feed_token_converter") | ||
42 | * | ||
43 | * @param User $user | ||
44 | * @param $page | ||
38 | * | 45 | * |
39 | * @return \Symfony\Component\HttpFoundation\Response | 46 | * @return \Symfony\Component\HttpFoundation\Response |
40 | */ | 47 | */ |
41 | public function showArchiveRSSAction(Request $request, User $user) | 48 | public function showArchiveFeedAction(User $user, $page) |
42 | { | 49 | { |
43 | return $this->showEntries('archive', $user, $request->query->get('page', 1)); | 50 | return $this->showEntries('archive', $user, $page); |
44 | } | 51 | } |
45 | 52 | ||
46 | /** | 53 | /** |
47 | * Shows starred entries for current user. | 54 | * Shows starred entries for current user. |
48 | * | 55 | * |
49 | * @Route("/{username}/{token}/starred.xml", name="starred_rss", defaults={"_format"="xml"}) | 56 | * @Route("/feed/{username}/{token}/starred/{page}", name="starred_feed", defaults={"page"=1, "_format"="xml"}) |
50 | * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter") | 57 | * |
58 | * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_feed_token_converter") | ||
59 | * | ||
60 | * @param User $user | ||
61 | * @param $page | ||
51 | * | 62 | * |
52 | * @return \Symfony\Component\HttpFoundation\Response | 63 | * @return \Symfony\Component\HttpFoundation\Response |
53 | */ | 64 | */ |
54 | public function showStarredRSSAction(Request $request, User $user) | 65 | public function showStarredFeedAction(User $user, $page) |
55 | { | 66 | { |
56 | return $this->showEntries('starred', $user, $request->query->get('page', 1)); | 67 | return $this->showEntries('starred', $user, $page); |
57 | } | 68 | } |
58 | 69 | ||
59 | /** | 70 | /** |
60 | * Shows all entries for current user. | 71 | * Shows all entries for current user. |
61 | * | 72 | * |
62 | * @Route("/{username}/{token}/all.xml", name="all_rss", defaults={"_format"="xml"}) | 73 | * @Route("/feed/{username}/{token}/all/{page}", name="all_feed", defaults={"page"=1, "_format"="xml"}) |
63 | * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter") | 74 | * |
75 | * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_feed_token_converter") | ||
64 | * | 76 | * |
65 | * @return \Symfony\Component\HttpFoundation\Response | 77 | * @return \Symfony\Component\HttpFoundation\Response |
66 | */ | 78 | */ |
67 | public function showAllRSSAction(Request $request, User $user) | 79 | public function showAllFeedAction(User $user, $page) |
68 | { | 80 | { |
69 | return $this->showEntries('all', $user, $request->query->get('page', 1)); | 81 | return $this->showEntries('all', $user, $page); |
70 | } | 82 | } |
71 | 83 | ||
72 | /** | 84 | /** |
73 | * Shows entries associated to a tag for current user. | 85 | * Shows entries associated to a tag for current user. |
74 | * | 86 | * |
75 | * @Route("/{username}/{token}/tags/{slug}.xml", name="tag_rss", defaults={"_format"="xml"}) | 87 | * @Route("/feed/{username}/{token}/tags/{slug}/{page}", name="tag_feed", defaults={"page"=1, "_format"="xml"}) |
76 | * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter") | 88 | * |
89 | * @ParamConverter("user", class="WallabagUserBundle:User", converter="username_feed_token_converter") | ||
77 | * @ParamConverter("tag", options={"mapping": {"slug": "slug"}}) | 90 | * @ParamConverter("tag", options={"mapping": {"slug": "slug"}}) |
78 | * | 91 | * |
79 | * @return \Symfony\Component\HttpFoundation\Response | 92 | * @return \Symfony\Component\HttpFoundation\Response |
80 | */ | 93 | */ |
81 | public function showTagsAction(Request $request, User $user, Tag $tag) | 94 | public function showTagsFeedAction(User $user, Tag $tag, $page) |
82 | { | 95 | { |
83 | $page = $request->query->get('page', 1); | ||
84 | |||
85 | $url = $this->generateUrl( | 96 | $url = $this->generateUrl( |
86 | 'tag_rss', | 97 | 'tag_feed', |
87 | [ | 98 | [ |
88 | 'username' => $user->getUsername(), | 99 | 'username' => $user->getUsername(), |
89 | 'token' => $user->getConfig()->getRssToken(), | 100 | 'token' => $user->getConfig()->getFeedToken(), |
90 | 'slug' => $tag->getSlug(), | 101 | 'slug' => $tag->getSlug(), |
91 | ], | 102 | ], |
92 | UrlGeneratorInterface::ABSOLUTE_URL | 103 | UrlGeneratorInterface::ABSOLUTE_URL |
@@ -119,12 +130,15 @@ class RssController extends Controller | |||
119 | return $this->render( | 130 | return $this->render( |
120 | '@WallabagCore/themes/common/Entry/entries.xml.twig', | 131 | '@WallabagCore/themes/common/Entry/entries.xml.twig', |
121 | [ | 132 | [ |
122 | 'url_html' => $this->generateUrl('tag_entries', ['slug' => $tag->getSlug()], UrlGeneratorInterface::ABSOLUTE_URL), | 133 | 'type' => 'tag', |
123 | 'type' => 'tag (' . $tag->getLabel() . ')', | ||
124 | 'url' => $url, | 134 | 'url' => $url, |
125 | 'entries' => $entries, | 135 | 'entries' => $entries, |
136 | 'user' => $user->getUsername(), | ||
137 | 'domainName' => $this->getParameter('domain_name'), | ||
138 | 'version' => $this->getParameter('wallabag_core.version'), | ||
139 | 'tag' => $tag->getSlug(), | ||
126 | ], | 140 | ], |
127 | new Response('', 200, ['Content-Type' => 'application/rss+xml']) | 141 | new Response('', 200, ['Content-Type' => 'application/atom+xml']) |
128 | ); | 142 | ); |
129 | } | 143 | } |
130 | 144 | ||
@@ -162,14 +176,14 @@ class RssController extends Controller | |||
162 | $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false); | 176 | $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false); |
163 | $entries = new Pagerfanta($pagerAdapter); | 177 | $entries = new Pagerfanta($pagerAdapter); |
164 | 178 | ||
165 | $perPage = $user->getConfig()->getRssLimit() ?: $this->getParameter('wallabag_core.rss_limit'); | 179 | $perPage = $user->getConfig()->getFeedLimit() ?: $this->getParameter('wallabag_core.Feed_limit'); |
166 | $entries->setMaxPerPage($perPage); | 180 | $entries->setMaxPerPage($perPage); |
167 | 181 | ||
168 | $url = $this->generateUrl( | 182 | $url = $this->generateUrl( |
169 | $type . '_rss', | 183 | $type . '_feed', |
170 | [ | 184 | [ |
171 | 'username' => $user->getUsername(), | 185 | 'username' => $user->getUsername(), |
172 | 'token' => $user->getConfig()->getRssToken(), | 186 | 'token' => $user->getConfig()->getFeedToken(), |
173 | ], | 187 | ], |
174 | UrlGeneratorInterface::ABSOLUTE_URL | 188 | UrlGeneratorInterface::ABSOLUTE_URL |
175 | ); | 189 | ); |
@@ -178,19 +192,19 @@ class RssController extends Controller | |||
178 | $entries->setCurrentPage((int) $page); | 192 | $entries->setCurrentPage((int) $page); |
179 | } catch (OutOfRangeCurrentPageException $e) { | 193 | } catch (OutOfRangeCurrentPageException $e) { |
180 | if ($page > 1) { | 194 | if ($page > 1) { |
181 | return $this->redirect($url . '?page=' . $entries->getNbPages(), 302); | 195 | return $this->redirect($url . '/' . $entries->getNbPages()); |
182 | } | 196 | } |
183 | } | 197 | } |
184 | 198 | ||
185 | return $this->render( | 199 | return $this->render('@WallabagCore/themes/common/Entry/entries.xml.twig', [ |
186 | '@WallabagCore/themes/common/Entry/entries.xml.twig', | 200 | 'type' => $type, |
187 | [ | 201 | 'url' => $url, |
188 | 'url_html' => $this->generateUrl($type, [], UrlGeneratorInterface::ABSOLUTE_URL), | 202 | 'entries' => $entries, |
189 | 'type' => $type, | 203 | 'user' => $user->getUsername(), |
190 | 'url' => $url, | 204 | 'domainName' => $this->getParameter('domain_name'), |
191 | 'entries' => $entries, | 205 | 'version' => $this->getParameter('wallabag_core.version'), |
192 | ], | 206 | ], |
193 | new Response('', 200, ['Content-Type' => 'application/rss+xml']) | 207 | new Response('', 200, ['Content-Type' => 'application/atom+xml']) |
194 | ); | 208 | ); |
195 | } | 209 | } |
196 | } | 210 | } |
diff --git a/src/Wallabag/CoreBundle/Controller/SiteCredentialController.php b/src/Wallabag/CoreBundle/Controller/SiteCredentialController.php index 548de744..51bc1d94 100644 --- a/src/Wallabag/CoreBundle/Controller/SiteCredentialController.php +++ b/src/Wallabag/CoreBundle/Controller/SiteCredentialController.php | |||
@@ -2,10 +2,9 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\Controller; | 3 | namespace Wallabag\CoreBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; | ||
6 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
7 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 5 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
8 | use Symfony\Component\HttpFoundation\Request; | 6 | use Symfony\Component\HttpFoundation\Request; |
7 | use Symfony\Component\Routing\Annotation\Route; | ||
9 | use Wallabag\CoreBundle\Entity\SiteCredential; | 8 | use Wallabag\CoreBundle\Entity\SiteCredential; |
10 | use Wallabag\UserBundle\Entity\User; | 9 | use Wallabag\UserBundle\Entity\User; |
11 | 10 | ||
@@ -19,8 +18,7 @@ class SiteCredentialController extends Controller | |||
19 | /** | 18 | /** |
20 | * Lists all User entities. | 19 | * Lists all User entities. |
21 | * | 20 | * |
22 | * @Route("/", name="site_credentials_index") | 21 | * @Route("/", name="site_credentials_index", methods={"GET"}) |
23 | * @Method("GET") | ||
24 | */ | 22 | */ |
25 | public function indexAction() | 23 | public function indexAction() |
26 | { | 24 | { |
@@ -36,8 +34,7 @@ class SiteCredentialController extends Controller | |||
36 | /** | 34 | /** |
37 | * Creates a new site credential entity. | 35 | * Creates a new site credential entity. |
38 | * | 36 | * |
39 | * @Route("/new", name="site_credentials_new") | 37 | * @Route("/new", name="site_credentials_new", methods={"GET", "POST"}) |
40 | * @Method({"GET", "POST"}) | ||
41 | * | 38 | * |
42 | * @param Request $request | 39 | * @param Request $request |
43 | * | 40 | * |
@@ -77,8 +74,7 @@ class SiteCredentialController extends Controller | |||
77 | /** | 74 | /** |
78 | * Displays a form to edit an existing site credential entity. | 75 | * Displays a form to edit an existing site credential entity. |
79 | * | 76 | * |
80 | * @Route("/{id}/edit", name="site_credentials_edit") | 77 | * @Route("/{id}/edit", name="site_credentials_edit", methods={"GET", "POST"}) |
81 | * @Method({"GET", "POST"}) | ||
82 | * | 78 | * |
83 | * @param Request $request | 79 | * @param Request $request |
84 | * @param SiteCredential $siteCredential | 80 | * @param SiteCredential $siteCredential |
@@ -121,8 +117,7 @@ class SiteCredentialController extends Controller | |||
121 | /** | 117 | /** |
122 | * Deletes a site credential entity. | 118 | * Deletes a site credential entity. |
123 | * | 119 | * |
124 | * @Route("/{id}", name="site_credentials_delete") | 120 | * @Route("/{id}", name="site_credentials_delete", methods={"DELETE"}) |
125 | * @Method("DELETE") | ||
126 | * | 121 | * |
127 | * @param Request $request | 122 | * @param Request $request |
128 | * @param SiteCredential $siteCredential | 123 | * @param SiteCredential $siteCredential |
diff --git a/src/Wallabag/CoreBundle/Controller/StaticController.php b/src/Wallabag/CoreBundle/Controller/StaticController.php index 318af303..fa760c14 100644 --- a/src/Wallabag/CoreBundle/Controller/StaticController.php +++ b/src/Wallabag/CoreBundle/Controller/StaticController.php | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\Controller; | 3 | namespace Wallabag\CoreBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 5 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
6 | use Symfony\Component\Routing\Annotation\Route; | ||
7 | 7 | ||
8 | class StaticController extends Controller | 8 | class StaticController extends Controller |
9 | { | 9 | { |
diff --git a/src/Wallabag/CoreBundle/Controller/TagController.php b/src/Wallabag/CoreBundle/Controller/TagController.php index b6d28e59..d0155c60 100644 --- a/src/Wallabag/CoreBundle/Controller/TagController.php +++ b/src/Wallabag/CoreBundle/Controller/TagController.php | |||
@@ -5,12 +5,13 @@ namespace Wallabag\CoreBundle\Controller; | |||
5 | use Pagerfanta\Adapter\ArrayAdapter; | 5 | use Pagerfanta\Adapter\ArrayAdapter; |
6 | use Pagerfanta\Exception\OutOfRangeCurrentPageException; | 6 | use Pagerfanta\Exception\OutOfRangeCurrentPageException; |
7 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | 7 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; |
8 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
9 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 8 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
10 | use Symfony\Component\HttpFoundation\Request; | 9 | use Symfony\Component\HttpFoundation\Request; |
10 | use Symfony\Component\Routing\Annotation\Route; | ||
11 | use Wallabag\CoreBundle\Entity\Entry; | 11 | use Wallabag\CoreBundle\Entity\Entry; |
12 | use Wallabag\CoreBundle\Entity\Tag; | 12 | use Wallabag\CoreBundle\Entity\Tag; |
13 | use Wallabag\CoreBundle\Form\Type\NewTagType; | 13 | use Wallabag\CoreBundle\Form\Type\NewTagType; |
14 | use Wallabag\CoreBundle\Form\Type\RenameTagType; | ||
14 | 15 | ||
15 | class TagController extends Controller | 16 | class TagController extends Controller |
16 | { | 17 | { |
@@ -87,8 +88,14 @@ class TagController extends Controller | |||
87 | $tags = $this->get('wallabag_core.tag_repository') | 88 | $tags = $this->get('wallabag_core.tag_repository') |
88 | ->findAllFlatTagsWithNbEntries($this->getUser()->getId()); | 89 | ->findAllFlatTagsWithNbEntries($this->getUser()->getId()); |
89 | 90 | ||
91 | $renameForms = []; | ||
92 | foreach ($tags as $tag) { | ||
93 | $renameForms[$tag['id']] = $this->createForm(RenameTagType::class, new Tag())->createView(); | ||
94 | } | ||
95 | |||
90 | return $this->render('WallabagCoreBundle:Tag:tags.html.twig', [ | 96 | return $this->render('WallabagCoreBundle:Tag:tags.html.twig', [ |
91 | 'tags' => $tags, | 97 | 'tags' => $tags, |
98 | 'renameForms' => $renameForms, | ||
92 | ]); | 99 | ]); |
93 | } | 100 | } |
94 | 101 | ||
@@ -130,4 +137,48 @@ class TagController extends Controller | |||
130 | 'tag' => $tag, | 137 | 'tag' => $tag, |
131 | ]); | 138 | ]); |
132 | } | 139 | } |
140 | |||
141 | /** | ||
142 | * Rename a given tag with a new label | ||
143 | * Create a new tag with the new name and drop the old one. | ||
144 | * | ||
145 | * @param Tag $tag | ||
146 | * @param Request $request | ||
147 | * | ||
148 | * @Route("/tag/rename/{slug}", name="tag_rename") | ||
149 | * @ParamConverter("tag", options={"mapping": {"slug": "slug"}}) | ||
150 | * | ||
151 | * @return \Symfony\Component\HttpFoundation\Response | ||
152 | */ | ||
153 | public function renameTagAction(Tag $tag, Request $request) | ||
154 | { | ||
155 | $form = $this->createForm(RenameTagType::class, new Tag()); | ||
156 | $form->handleRequest($request); | ||
157 | |||
158 | if ($form->isSubmitted() && $form->isValid()) { | ||
159 | $entries = $this->get('wallabag_core.entry_repository')->findAllByTagId( | ||
160 | $this->getUser()->getId(), | ||
161 | $tag->getId() | ||
162 | ); | ||
163 | foreach ($entries as $entry) { | ||
164 | $this->get('wallabag_core.tags_assigner')->assignTagsToEntry( | ||
165 | $entry, | ||
166 | $form->get('label')->getData() | ||
167 | ); | ||
168 | $entry->removeTag($tag); | ||
169 | } | ||
170 | |||
171 | $em = $this->getDoctrine()->getManager(); | ||
172 | $em->flush(); | ||
173 | } | ||
174 | |||
175 | $this->get('session')->getFlashBag()->add( | ||
176 | 'notice', | ||
177 | 'flashes.tag.notice.tag_renamed' | ||
178 | ); | ||
179 | |||
180 | $redirectUrl = $this->get('wallabag_core.helper.redirect')->to($request->headers->get('referer'), '', true); | ||
181 | |||
182 | return $this->redirect($redirectUrl); | ||
183 | } | ||
133 | } | 184 | } |
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php b/src/Wallabag/CoreBundle/DataFixtures/ConfigFixtures.php index 3d4d5def..c54e9f2c 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ConfigFixtures.php | |||
@@ -1,13 +1,14 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\DataFixtures\ORM; | 3 | namespace Wallabag\CoreBundle\DataFixtures; |
4 | 4 | ||
5 | use Doctrine\Common\DataFixtures\AbstractFixture; | 5 | use Doctrine\Bundle\FixturesBundle\Fixture; |
6 | use Doctrine\Common\DataFixtures\OrderedFixtureInterface; | 6 | use Doctrine\Common\DataFixtures\DependentFixtureInterface; |
7 | use Doctrine\Common\Persistence\ObjectManager; | 7 | use Doctrine\Common\Persistence\ObjectManager; |
8 | use Wallabag\CoreBundle\Entity\Config; | 8 | use Wallabag\CoreBundle\Entity\Config; |
9 | use Wallabag\UserBundle\DataFixtures\UserFixtures; | ||
9 | 10 | ||
10 | class LoadConfigData extends AbstractFixture implements OrderedFixtureInterface | 11 | class ConfigFixtures extends Fixture implements DependentFixtureInterface |
11 | { | 12 | { |
12 | /** | 13 | /** |
13 | * {@inheritdoc} | 14 | * {@inheritdoc} |
@@ -60,8 +61,10 @@ class LoadConfigData extends AbstractFixture implements OrderedFixtureInterface | |||
60 | /** | 61 | /** |
61 | * {@inheritdoc} | 62 | * {@inheritdoc} |
62 | */ | 63 | */ |
63 | public function getOrder() | 64 | public function getDependencies() |
64 | { | 65 | { |
65 | return 20; | 66 | return [ |
67 | UserFixtures::class, | ||
68 | ]; | ||
66 | } | 69 | } |
67 | } | 70 | } |
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php b/src/Wallabag/CoreBundle/DataFixtures/EntryFixtures.php index 8e7a1d2a..024fcfdc 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/EntryFixtures.php | |||
@@ -1,13 +1,14 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\DataFixtures\ORM; | 3 | namespace Wallabag\CoreBundle\DataFixtures; |
4 | 4 | ||
5 | use Doctrine\Common\DataFixtures\AbstractFixture; | 5 | use Doctrine\Bundle\FixturesBundle\Fixture; |
6 | use Doctrine\Common\DataFixtures\OrderedFixtureInterface; | 6 | use Doctrine\Common\DataFixtures\DependentFixtureInterface; |
7 | use Doctrine\Common\Persistence\ObjectManager; | 7 | use Doctrine\Common\Persistence\ObjectManager; |
8 | use Wallabag\CoreBundle\Entity\Entry; | 8 | use Wallabag\CoreBundle\Entity\Entry; |
9 | use Wallabag\UserBundle\DataFixtures\UserFixtures; | ||
9 | 10 | ||
10 | class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface | 11 | class EntryFixtures extends Fixture implements DependentFixtureInterface |
11 | { | 12 | { |
12 | /** | 13 | /** |
13 | * {@inheritdoc} | 14 | * {@inheritdoc} |
@@ -127,8 +128,11 @@ class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface | |||
127 | /** | 128 | /** |
128 | * {@inheritdoc} | 129 | * {@inheritdoc} |
129 | */ | 130 | */ |
130 | public function getOrder() | 131 | public function getDependencies() |
131 | { | 132 | { |
132 | return 30; | 133 | return [ |
134 | UserFixtures::class, | ||
135 | TagFixtures::class, | ||
136 | ]; | ||
133 | } | 137 | } |
134 | } | 138 | } |
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php b/src/Wallabag/CoreBundle/DataFixtures/SettingFixtures.php index 3fe88e7f..cc7d1f59 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/SettingFixtures.php | |||
@@ -1,15 +1,14 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\DataFixtures\ORM; | 3 | namespace Wallabag\CoreBundle\DataFixtures; |
4 | 4 | ||
5 | use Craue\ConfigBundle\Entity\Setting; | 5 | use Craue\ConfigBundle\Entity\Setting; |
6 | use Doctrine\Common\DataFixtures\AbstractFixture; | 6 | use Doctrine\Bundle\FixturesBundle\Fixture; |
7 | use Doctrine\Common\DataFixtures\OrderedFixtureInterface; | ||
8 | use Doctrine\Common\Persistence\ObjectManager; | 7 | use Doctrine\Common\Persistence\ObjectManager; |
9 | use Symfony\Component\DependencyInjection\ContainerAwareInterface; | 8 | use Symfony\Component\DependencyInjection\ContainerAwareInterface; |
10 | use Symfony\Component\DependencyInjection\ContainerInterface; | 9 | use Symfony\Component\DependencyInjection\ContainerInterface; |
11 | 10 | ||
12 | class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface | 11 | class SettingFixtures extends Fixture implements ContainerAwareInterface |
13 | { | 12 | { |
14 | /** | 13 | /** |
15 | * @var ContainerInterface | 14 | * @var ContainerInterface |
@@ -36,12 +35,4 @@ class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface | |||
36 | 35 | ||
37 | $manager->flush(); | 36 | $manager->flush(); |
38 | } | 37 | } |
39 | |||
40 | /** | ||
41 | * {@inheritdoc} | ||
42 | */ | ||
43 | public function getOrder() | ||
44 | { | ||
45 | return 29; | ||
46 | } | ||
47 | } | 38 | } |
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSiteCredentialData.php b/src/Wallabag/CoreBundle/DataFixtures/SiteCredentialFixtures.php index faf29da6..9a7d116f 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSiteCredentialData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/SiteCredentialFixtures.php | |||
@@ -1,15 +1,16 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\DataFixtures\ORM; | 3 | namespace Wallabag\CoreBundle\DataFixtures; |
4 | 4 | ||
5 | use Doctrine\Common\DataFixtures\AbstractFixture; | 5 | use Doctrine\Bundle\FixturesBundle\Fixture; |
6 | use Doctrine\Common\DataFixtures\OrderedFixtureInterface; | 6 | use Doctrine\Common\DataFixtures\DependentFixtureInterface; |
7 | use Doctrine\Common\Persistence\ObjectManager; | 7 | use Doctrine\Common\Persistence\ObjectManager; |
8 | use Symfony\Component\DependencyInjection\ContainerAwareInterface; | 8 | use Symfony\Component\DependencyInjection\ContainerAwareInterface; |
9 | use Symfony\Component\DependencyInjection\ContainerInterface; | 9 | use Symfony\Component\DependencyInjection\ContainerInterface; |
10 | use Wallabag\CoreBundle\Entity\SiteCredential; | 10 | use Wallabag\CoreBundle\Entity\SiteCredential; |
11 | use Wallabag\UserBundle\DataFixtures\UserFixtures; | ||
11 | 12 | ||
12 | class LoadSiteCredentialData extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface | 13 | class SiteCredentialFixtures extends Fixture implements DependentFixtureInterface, ContainerAwareInterface |
13 | { | 14 | { |
14 | /** | 15 | /** |
15 | * @var ContainerInterface | 16 | * @var ContainerInterface |
@@ -46,8 +47,10 @@ class LoadSiteCredentialData extends AbstractFixture implements OrderedFixtureIn | |||
46 | /** | 47 | /** |
47 | * {@inheritdoc} | 48 | * {@inheritdoc} |
48 | */ | 49 | */ |
49 | public function getOrder() | 50 | public function getDependencies() |
50 | { | 51 | { |
51 | return 50; | 52 | return [ |
53 | UserFixtures::class, | ||
54 | ]; | ||
52 | } | 55 | } |
53 | } | 56 | } |
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php b/src/Wallabag/CoreBundle/DataFixtures/TagFixtures.php index 485445c1..58a0d799 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/TagFixtures.php | |||
@@ -1,13 +1,12 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\DataFixtures\ORM; | 3 | namespace Wallabag\CoreBundle\DataFixtures; |
4 | 4 | ||
5 | use Doctrine\Common\DataFixtures\AbstractFixture; | 5 | use Doctrine\Bundle\FixturesBundle\Fixture; |
6 | use Doctrine\Common\DataFixtures\OrderedFixtureInterface; | ||
7 | use Doctrine\Common\Persistence\ObjectManager; | 6 | use Doctrine\Common\Persistence\ObjectManager; |
8 | use Wallabag\CoreBundle\Entity\Tag; | 7 | use Wallabag\CoreBundle\Entity\Tag; |
9 | 8 | ||
10 | class LoadTagData extends AbstractFixture implements OrderedFixtureInterface | 9 | class TagFixtures extends Fixture |
11 | { | 10 | { |
12 | /** | 11 | /** |
13 | * {@inheritdoc} | 12 | * {@inheritdoc} |
@@ -33,12 +32,4 @@ class LoadTagData extends AbstractFixture implements OrderedFixtureInterface | |||
33 | 32 | ||
34 | $manager->flush(); | 33 | $manager->flush(); |
35 | } | 34 | } |
36 | |||
37 | /** | ||
38 | * {@inheritdoc} | ||
39 | */ | ||
40 | public function getOrder() | ||
41 | { | ||
42 | return 25; | ||
43 | } | ||
44 | } | 35 | } |
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTaggingRuleData.php b/src/Wallabag/CoreBundle/DataFixtures/TaggingRuleFixtures.php index 55abd63c..78ff314a 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTaggingRuleData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/TaggingRuleFixtures.php | |||
@@ -1,13 +1,13 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\DataFixtures\ORM; | 3 | namespace Wallabag\CoreBundle\DataFixtures; |
4 | 4 | ||
5 | use Doctrine\Common\DataFixtures\AbstractFixture; | 5 | use Doctrine\Bundle\FixturesBundle\Fixture; |
6 | use Doctrine\Common\DataFixtures\OrderedFixtureInterface; | 6 | use Doctrine\Common\DataFixtures\DependentFixtureInterface; |
7 | use Doctrine\Common\Persistence\ObjectManager; | 7 | use Doctrine\Common\Persistence\ObjectManager; |
8 | use Wallabag\CoreBundle\Entity\TaggingRule; | 8 | use Wallabag\CoreBundle\Entity\TaggingRule; |
9 | 9 | ||
10 | class LoadTaggingRuleData extends AbstractFixture implements OrderedFixtureInterface | 10 | class TaggingRuleFixtures extends Fixture implements DependentFixtureInterface |
11 | { | 11 | { |
12 | /** | 12 | /** |
13 | * {@inheritdoc} | 13 | * {@inheritdoc} |
@@ -49,8 +49,10 @@ class LoadTaggingRuleData extends AbstractFixture implements OrderedFixtureInter | |||
49 | /** | 49 | /** |
50 | * {@inheritdoc} | 50 | * {@inheritdoc} |
51 | */ | 51 | */ |
52 | public function getOrder() | 52 | public function getDependencies() |
53 | { | 53 | { |
54 | return 40; | 54 | return [ |
55 | ConfigFixtures::class, | ||
56 | ]; | ||
55 | } | 57 | } |
56 | } | 58 | } |
diff --git a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php index a3ef2b53..e9a1e9e0 100644 --- a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php +++ b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php | |||
@@ -18,7 +18,7 @@ class WallabagCoreExtension extends Extension | |||
18 | $container->setParameter('wallabag_core.items_on_page', $config['items_on_page']); | 18 | $container->setParameter('wallabag_core.items_on_page', $config['items_on_page']); |
19 | $container->setParameter('wallabag_core.theme', $config['theme']); | 19 | $container->setParameter('wallabag_core.theme', $config['theme']); |
20 | $container->setParameter('wallabag_core.language', $config['language']); | 20 | $container->setParameter('wallabag_core.language', $config['language']); |
21 | $container->setParameter('wallabag_core.rss_limit', $config['rss_limit']); | 21 | $container->setParameter('wallabag_core.feed_limit', $config['rss_limit']); |
22 | $container->setParameter('wallabag_core.reading_speed', $config['reading_speed']); | 22 | $container->setParameter('wallabag_core.reading_speed', $config['reading_speed']); |
23 | $container->setParameter('wallabag_core.version', $config['version']); | 23 | $container->setParameter('wallabag_core.version', $config['version']); |
24 | $container->setParameter('wallabag_core.paypal_url', $config['paypal_url']); | 24 | $container->setParameter('wallabag_core.paypal_url', $config['paypal_url']); |
diff --git a/src/Wallabag/CoreBundle/Doctrine/DBAL/Driver/CustomPostgreSQLDriver.php b/src/Wallabag/CoreBundle/Doctrine/DBAL/Driver/CustomPostgreSQLDriver.php deleted file mode 100644 index eb5b203f..00000000 --- a/src/Wallabag/CoreBundle/Doctrine/DBAL/Driver/CustomPostgreSQLDriver.php +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Doctrine\DBAL\Driver; | ||
4 | |||
5 | use Doctrine\DBAL\Connection; | ||
6 | use Doctrine\DBAL\Driver\PDOPgSql\Driver; | ||
7 | use Wallabag\CoreBundle\Doctrine\DBAL\Schema\CustomPostgreSqlSchemaManager; | ||
8 | |||
9 | /** | ||
10 | * This custom driver allow to use a different schema manager | ||
11 | * So we can fix the PostgreSQL 10 problem. | ||
12 | * | ||
13 | * @see https://github.com/wallabag/wallabag/issues/3479 | ||
14 | * @see https://github.com/doctrine/dbal/issues/2868 | ||
15 | */ | ||
16 | class CustomPostgreSQLDriver extends Driver | ||
17 | { | ||
18 | /** | ||
19 | * {@inheritdoc} | ||
20 | */ | ||
21 | public function getSchemaManager(Connection $conn) | ||
22 | { | ||
23 | return new CustomPostgreSqlSchemaManager($conn); | ||
24 | } | ||
25 | } | ||
diff --git a/src/Wallabag/CoreBundle/Doctrine/DBAL/Schema/CustomPostgreSqlSchemaManager.php b/src/Wallabag/CoreBundle/Doctrine/DBAL/Schema/CustomPostgreSqlSchemaManager.php deleted file mode 100644 index 439ae17d..00000000 --- a/src/Wallabag/CoreBundle/Doctrine/DBAL/Schema/CustomPostgreSqlSchemaManager.php +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Doctrine\DBAL\Schema; | ||
4 | |||
5 | use Doctrine\DBAL\Schema\PostgreSqlSchemaManager; | ||
6 | use Doctrine\DBAL\Schema\Sequence; | ||
7 | |||
8 | /** | ||
9 | * This custom schema manager fix the PostgreSQL 10 problem. | ||
10 | * | ||
11 | * @see https://github.com/wallabag/wallabag/issues/3479 | ||
12 | * @see https://github.com/doctrine/dbal/issues/2868 | ||
13 | */ | ||
14 | class CustomPostgreSqlSchemaManager extends PostgreSqlSchemaManager | ||
15 | { | ||
16 | /** | ||
17 | * {@inheritdoc} | ||
18 | */ | ||
19 | protected function _getPortableSequenceDefinition($sequence) | ||
20 | { | ||
21 | $sequenceName = $sequence['relname']; | ||
22 | if ('public' !== $sequence['schemaname']) { | ||
23 | $sequenceName = $sequence['schemaname'] . '.' . $sequence['relname']; | ||
24 | } | ||
25 | |||
26 | $query = 'SELECT min_value, increment_by FROM ' . $this->_platform->quoteIdentifier($sequenceName); | ||
27 | |||
28 | // the `method_exists` is only to avoid test to fail: | ||
29 | // DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticConnection doesn't support the `getServerVersion` | ||
30 | if (method_exists($this->_conn->getWrappedConnection(), 'getServerVersion') && (float) ($this->_conn->getWrappedConnection()->getServerVersion()) >= 10) { | ||
31 | $query = "SELECT min_value, increment_by FROM pg_sequences WHERE schemaname = 'public' AND sequencename = " . $this->_conn->quote($sequenceName); | ||
32 | } | ||
33 | |||
34 | $data = $this->_conn->fetchAll($query); | ||
35 | |||
36 | return new Sequence($sequenceName, $data[0]['increment_by'], $data[0]['min_value']); | ||
37 | } | ||
38 | } | ||
diff --git a/src/Wallabag/CoreBundle/Doctrine/WallabagMigration.php b/src/Wallabag/CoreBundle/Doctrine/WallabagMigration.php index 7aa2409a..4a3fef3b 100644 --- a/src/Wallabag/CoreBundle/Doctrine/WallabagMigration.php +++ b/src/Wallabag/CoreBundle/Doctrine/WallabagMigration.php | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\Doctrine; | 3 | namespace Wallabag\CoreBundle\Doctrine; |
4 | 4 | ||
5 | use Doctrine\DBAL\Migrations\AbstractMigration; | ||
6 | use Doctrine\DBAL\Schema\Schema; | 5 | use Doctrine\DBAL\Schema\Schema; |
6 | use Doctrine\Migrations\AbstractMigration; | ||
7 | use Symfony\Component\DependencyInjection\ContainerAwareInterface; | 7 | use Symfony\Component\DependencyInjection\ContainerAwareInterface; |
8 | use Symfony\Component\DependencyInjection\ContainerInterface; | 8 | use Symfony\Component\DependencyInjection\ContainerInterface; |
9 | 9 | ||
diff --git a/src/Wallabag/CoreBundle/Entity/Config.php b/src/Wallabag/CoreBundle/Entity/Config.php index b902ae2c..c6e65d66 100644 --- a/src/Wallabag/CoreBundle/Entity/Config.php +++ b/src/Wallabag/CoreBundle/Entity/Config.php | |||
@@ -60,21 +60,21 @@ class Config | |||
60 | /** | 60 | /** |
61 | * @var string | 61 | * @var string |
62 | * | 62 | * |
63 | * @ORM\Column(name="rss_token", type="string", nullable=true) | 63 | * @ORM\Column(name="feed_token", type="string", nullable=true) |
64 | */ | 64 | */ |
65 | private $rssToken; | 65 | private $feedToken; |
66 | 66 | ||
67 | /** | 67 | /** |
68 | * @var int | 68 | * @var int |
69 | * | 69 | * |
70 | * @ORM\Column(name="rss_limit", type="integer", nullable=true) | 70 | * @ORM\Column(name="feed_limit", type="integer", nullable=true) |
71 | * @Assert\Range( | 71 | * @Assert\Range( |
72 | * min = 1, | 72 | * min = 1, |
73 | * max = 100000, | 73 | * max = 100000, |
74 | * maxMessage = "validator.rss_limit_too_high" | 74 | * maxMessage = "validator.feed_limit_too_high" |
75 | * ) | 75 | * ) |
76 | */ | 76 | */ |
77 | private $rssLimit; | 77 | private $feedLimit; |
78 | 78 | ||
79 | /** | 79 | /** |
80 | * @var float | 80 | * @var float |
@@ -231,51 +231,51 @@ class Config | |||
231 | } | 231 | } |
232 | 232 | ||
233 | /** | 233 | /** |
234 | * Set rssToken. | 234 | * Set feed Token. |
235 | * | 235 | * |
236 | * @param string $rssToken | 236 | * @param string $feedToken |
237 | * | 237 | * |
238 | * @return Config | 238 | * @return Config |
239 | */ | 239 | */ |
240 | public function setRssToken($rssToken) | 240 | public function setFeedToken($feedToken) |
241 | { | 241 | { |
242 | $this->rssToken = $rssToken; | 242 | $this->feedToken = $feedToken; |
243 | 243 | ||
244 | return $this; | 244 | return $this; |
245 | } | 245 | } |
246 | 246 | ||
247 | /** | 247 | /** |
248 | * Get rssToken. | 248 | * Get feedToken. |
249 | * | 249 | * |
250 | * @return string | 250 | * @return string |
251 | */ | 251 | */ |
252 | public function getRssToken() | 252 | public function getFeedToken() |
253 | { | 253 | { |
254 | return $this->rssToken; | 254 | return $this->feedToken; |
255 | } | 255 | } |
256 | 256 | ||
257 | /** | 257 | /** |
258 | * Set rssLimit. | 258 | * Set Feed Limit. |
259 | * | 259 | * |
260 | * @param int $rssLimit | 260 | * @param int $feedLimit |
261 | * | 261 | * |
262 | * @return Config | 262 | * @return Config |
263 | */ | 263 | */ |
264 | public function setRssLimit($rssLimit) | 264 | public function setFeedLimit($feedLimit) |
265 | { | 265 | { |
266 | $this->rssLimit = $rssLimit; | 266 | $this->feedLimit = $feedLimit; |
267 | 267 | ||
268 | return $this; | 268 | return $this; |
269 | } | 269 | } |
270 | 270 | ||
271 | /** | 271 | /** |
272 | * Get rssLimit. | 272 | * Get Feed Limit. |
273 | * | 273 | * |
274 | * @return int | 274 | * @return int |
275 | */ | 275 | */ |
276 | public function getRssLimit() | 276 | public function getFeedLimit() |
277 | { | 277 | { |
278 | return $this->rssLimit; | 278 | return $this->feedLimit; |
279 | } | 279 | } |
280 | 280 | ||
281 | /** | 281 | /** |
diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index 2b1f2e05..1b4367fd 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php | |||
@@ -13,6 +13,7 @@ use JMS\Serializer\Annotation\XmlRoot; | |||
13 | use Symfony\Component\Validator\Constraints as Assert; | 13 | use Symfony\Component\Validator\Constraints as Assert; |
14 | use Wallabag\AnnotationBundle\Entity\Annotation; | 14 | use Wallabag\AnnotationBundle\Entity\Annotation; |
15 | use Wallabag\CoreBundle\Helper\EntityTimestampsTrait; | 15 | use Wallabag\CoreBundle\Helper\EntityTimestampsTrait; |
16 | use Wallabag\CoreBundle\Helper\UrlHasher; | ||
16 | use Wallabag\UserBundle\Entity\User; | 17 | use Wallabag\UserBundle\Entity\User; |
17 | 18 | ||
18 | /** | 19 | /** |
@@ -25,7 +26,8 @@ use Wallabag\UserBundle\Entity\User; | |||
25 | * options={"collate"="utf8mb4_unicode_ci", "charset"="utf8mb4"}, | 26 | * options={"collate"="utf8mb4_unicode_ci", "charset"="utf8mb4"}, |
26 | * indexes={ | 27 | * indexes={ |
27 | * @ORM\Index(name="created_at", columns={"created_at"}), | 28 | * @ORM\Index(name="created_at", columns={"created_at"}), |
28 | * @ORM\Index(name="uid", columns={"uid"}) | 29 | * @ORM\Index(name="uid", columns={"uid"}), |
30 | * @ORM\Index(name="hashed_url_user_id", columns={"user_id", "hashed_url"}, options={"lengths"={null, 40}}) | ||
29 | * } | 31 | * } |
30 | * ) | 32 | * ) |
31 | * @ORM\HasLifecycleCallbacks() | 33 | * @ORM\HasLifecycleCallbacks() |
@@ -76,6 +78,13 @@ class Entry | |||
76 | private $url; | 78 | private $url; |
77 | 79 | ||
78 | /** | 80 | /** |
81 | * @var string | ||
82 | * | ||
83 | * @ORM\Column(name="hashed_url", type="string", length=40, nullable=true) | ||
84 | */ | ||
85 | private $hashedUrl; | ||
86 | |||
87 | /** | ||
79 | * @var bool | 88 | * @var bool |
80 | * | 89 | * |
81 | * @Exclude | 90 | * @Exclude |
@@ -87,6 +96,15 @@ class Entry | |||
87 | private $isArchived = false; | 96 | private $isArchived = false; |
88 | 97 | ||
89 | /** | 98 | /** |
99 | * @var \DateTime | ||
100 | * | ||
101 | * @ORM\Column(name="archived_at", type="datetime", nullable=true) | ||
102 | * | ||
103 | * @Groups({"entries_for_user", "export_all"}) | ||
104 | */ | ||
105 | private $archivedAt = null; | ||
106 | |||
107 | /** | ||
90 | * @var bool | 108 | * @var bool |
91 | * | 109 | * |
92 | * @Exclude | 110 | * @Exclude |
@@ -307,6 +325,7 @@ class Entry | |||
307 | public function setUrl($url) | 325 | public function setUrl($url) |
308 | { | 326 | { |
309 | $this->url = $url; | 327 | $this->url = $url; |
328 | $this->hashedUrl = UrlHasher::hashUrl($url); | ||
310 | 329 | ||
311 | return $this; | 330 | return $this; |
312 | } | 331 | } |
@@ -336,6 +355,44 @@ class Entry | |||
336 | } | 355 | } |
337 | 356 | ||
338 | /** | 357 | /** |
358 | * update isArchived and archive_at fields. | ||
359 | * | ||
360 | * @param bool $isArchived | ||
361 | * | ||
362 | * @return Entry | ||
363 | */ | ||
364 | public function updateArchived($isArchived = false) | ||
365 | { | ||
366 | $this->setArchived($isArchived); | ||
367 | $this->setArchivedAt(null); | ||
368 | if ($this->isArchived()) { | ||
369 | $this->setArchivedAt(new \DateTime()); | ||
370 | } | ||
371 | |||
372 | return $this; | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * @return \DateTime|null | ||
377 | */ | ||
378 | public function getArchivedAt() | ||
379 | { | ||
380 | return $this->archivedAt; | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * @param \DateTime|null $archivedAt | ||
385 | * | ||
386 | * @return Entry | ||
387 | */ | ||
388 | public function setArchivedAt($archivedAt = null) | ||
389 | { | ||
390 | $this->archivedAt = $archivedAt; | ||
391 | |||
392 | return $this; | ||
393 | } | ||
394 | |||
395 | /** | ||
339 | * Get isArchived. | 396 | * Get isArchived. |
340 | * | 397 | * |
341 | * @return bool | 398 | * @return bool |
@@ -357,7 +414,7 @@ class Entry | |||
357 | 414 | ||
358 | public function toggleArchive() | 415 | public function toggleArchive() |
359 | { | 416 | { |
360 | $this->isArchived = $this->isArchived() ^ 1; | 417 | $this->updateArchived($this->isArchived() ^ 1); |
361 | 418 | ||
362 | return $this; | 419 | return $this; |
363 | } | 420 | } |
@@ -864,4 +921,24 @@ class Entry | |||
864 | { | 921 | { |
865 | return $this->originUrl; | 922 | return $this->originUrl; |
866 | } | 923 | } |
924 | |||
925 | /** | ||
926 | * @return string | ||
927 | */ | ||
928 | public function getHashedUrl() | ||
929 | { | ||
930 | return $this->hashedUrl; | ||
931 | } | ||
932 | |||
933 | /** | ||
934 | * @param mixed $hashedUrl | ||
935 | * | ||
936 | * @return Entry | ||
937 | */ | ||
938 | public function setHashedUrl($hashedUrl) | ||
939 | { | ||
940 | $this->hashedUrl = $hashedUrl; | ||
941 | |||
942 | return $this; | ||
943 | } | ||
867 | } | 944 | } |
diff --git a/src/Wallabag/CoreBundle/Entity/SiteCredential.php b/src/Wallabag/CoreBundle/Entity/SiteCredential.php index ac714359..dee48fd5 100644 --- a/src/Wallabag/CoreBundle/Entity/SiteCredential.php +++ b/src/Wallabag/CoreBundle/Entity/SiteCredential.php | |||
@@ -60,6 +60,13 @@ class SiteCredential | |||
60 | private $createdAt; | 60 | private $createdAt; |
61 | 61 | ||
62 | /** | 62 | /** |
63 | * @var \DateTime | ||
64 | * | ||
65 | * @ORM\Column(name="updated_at", type="datetime") | ||
66 | */ | ||
67 | private $updatedAt; | ||
68 | |||
69 | /** | ||
63 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="siteCredentials") | 70 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="siteCredentials") |
64 | */ | 71 | */ |
65 | private $user; | 72 | private $user; |
@@ -179,6 +186,16 @@ class SiteCredential | |||
179 | } | 186 | } |
180 | 187 | ||
181 | /** | 188 | /** |
189 | * Get updatedAt. | ||
190 | * | ||
191 | * @return \DateTime | ||
192 | */ | ||
193 | public function getUpdatedAt() | ||
194 | { | ||
195 | return $this->updatedAt; | ||
196 | } | ||
197 | |||
198 | /** | ||
182 | * @return User | 199 | * @return User |
183 | */ | 200 | */ |
184 | public function getUser() | 201 | public function getUser() |
diff --git a/src/Wallabag/CoreBundle/Entity/TaggingRule.php b/src/Wallabag/CoreBundle/Entity/TaggingRule.php index 84e11e26..c1be3165 100644 --- a/src/Wallabag/CoreBundle/Entity/TaggingRule.php +++ b/src/Wallabag/CoreBundle/Entity/TaggingRule.php | |||
@@ -3,7 +3,7 @@ | |||
3 | namespace Wallabag\CoreBundle\Entity; | 3 | namespace Wallabag\CoreBundle\Entity; |
4 | 4 | ||
5 | use Doctrine\ORM\Mapping as ORM; | 5 | use Doctrine\ORM\Mapping as ORM; |
6 | use KPhoen\RulerZBundle\Validator\Constraints as RulerZAssert; | 6 | use Symfony\Bridge\RulerZ\Validator\Constraints as RulerZAssert; |
7 | use Symfony\Component\Validator\Constraints as Assert; | 7 | use Symfony\Component\Validator\Constraints as Assert; |
8 | 8 | ||
9 | /** | 9 | /** |
diff --git a/src/Wallabag/CoreBundle/Event/Listener/UserLocaleListener.php b/src/Wallabag/CoreBundle/Event/Listener/UserLocaleListener.php index 367cdfb0..dc1db5c7 100644 --- a/src/Wallabag/CoreBundle/Event/Listener/UserLocaleListener.php +++ b/src/Wallabag/CoreBundle/Event/Listener/UserLocaleListener.php | |||
@@ -6,8 +6,10 @@ use Symfony\Component\HttpFoundation\Session\Session; | |||
6 | use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; | 6 | use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; |
7 | 7 | ||
8 | /** | 8 | /** |
9 | * Stores the locale of the user in the session after the | 9 | * Stores the locale of the user in the session after the login. |
10 | * login. This can be used by the LocaleListener afterwards. | 10 | * If no locale are defined (if user doesn't change it from the login screen), override it with the user's config one. |
11 | * | ||
12 | * This can be used by the LocaleListener afterwards. | ||
11 | * | 13 | * |
12 | * @see http://symfony.com/doc/master/cookbook/session/locale_sticky_session.html | 14 | * @see http://symfony.com/doc/master/cookbook/session/locale_sticky_session.html |
13 | */ | 15 | */ |
@@ -30,7 +32,7 @@ class UserLocaleListener | |||
30 | { | 32 | { |
31 | $user = $event->getAuthenticationToken()->getUser(); | 33 | $user = $event->getAuthenticationToken()->getUser(); |
32 | 34 | ||
33 | if (null !== $user->getConfig()->getLanguage()) { | 35 | if (null !== $user->getConfig()->getLanguage() && null === $this->session->get('_locale')) { |
34 | $this->session->set('_locale', $user->getConfig()->getLanguage()); | 36 | $this->session->set('_locale', $user->getConfig()->getLanguage()); |
35 | } | 37 | } |
36 | } | 38 | } |
diff --git a/src/Wallabag/CoreBundle/Form/Type/EditEntryType.php b/src/Wallabag/CoreBundle/Form/Type/EditEntryType.php index 08355928..2fc4c204 100644 --- a/src/Wallabag/CoreBundle/Form/Type/EditEntryType.php +++ b/src/Wallabag/CoreBundle/Form/Type/EditEntryType.php | |||
@@ -22,11 +22,13 @@ class EditEntryType extends AbstractType | |||
22 | 'disabled' => true, | 22 | 'disabled' => true, |
23 | 'required' => false, | 23 | 'required' => false, |
24 | 'label' => 'entry.edit.url_label', | 24 | 'label' => 'entry.edit.url_label', |
25 | 'default_protocol' => null, | ||
25 | ]) | 26 | ]) |
26 | ->add('origin_url', UrlType::class, [ | 27 | ->add('origin_url', UrlType::class, [ |
27 | 'required' => false, | 28 | 'required' => false, |
28 | 'property_path' => 'originUrl', | 29 | 'property_path' => 'originUrl', |
29 | 'label' => 'entry.edit.origin_url_label', | 30 | 'label' => 'entry.edit.origin_url_label', |
31 | 'default_protocol' => null, | ||
30 | ]) | 32 | ]) |
31 | ->add('save', SubmitType::class, [ | 33 | ->add('save', SubmitType::class, [ |
32 | 'label' => 'entry.edit.save_label', | 34 | 'label' => 'entry.edit.save_label', |
diff --git a/src/Wallabag/CoreBundle/Form/Type/RssType.php b/src/Wallabag/CoreBundle/Form/Type/FeedType.php index 49b31c1e..9b34daf4 100644 --- a/src/Wallabag/CoreBundle/Form/Type/RssType.php +++ b/src/Wallabag/CoreBundle/Form/Type/FeedType.php | |||
@@ -7,14 +7,14 @@ use Symfony\Component\Form\Extension\Core\Type\SubmitType; | |||
7 | use Symfony\Component\Form\FormBuilderInterface; | 7 | use Symfony\Component\Form\FormBuilderInterface; |
8 | use Symfony\Component\OptionsResolver\OptionsResolver; | 8 | use Symfony\Component\OptionsResolver\OptionsResolver; |
9 | 9 | ||
10 | class RssType extends AbstractType | 10 | class FeedType extends AbstractType |
11 | { | 11 | { |
12 | public function buildForm(FormBuilderInterface $builder, array $options) | 12 | public function buildForm(FormBuilderInterface $builder, array $options) |
13 | { | 13 | { |
14 | $builder | 14 | $builder |
15 | ->add('rss_limit', null, [ | 15 | ->add('feed_limit', null, [ |
16 | 'label' => 'config.form_rss.rss_limit', | 16 | 'label' => 'config.form_feed.feed_limit', |
17 | 'property_path' => 'rssLimit', | 17 | 'property_path' => 'feedLimit', |
18 | ]) | 18 | ]) |
19 | ->add('save', SubmitType::class, [ | 19 | ->add('save', SubmitType::class, [ |
20 | 'label' => 'config.form.save', | 20 | 'label' => 'config.form.save', |
@@ -31,6 +31,6 @@ class RssType extends AbstractType | |||
31 | 31 | ||
32 | public function getBlockPrefix() | 32 | public function getBlockPrefix() |
33 | { | 33 | { |
34 | return 'rss_config'; | 34 | return 'feed_config'; |
35 | } | 35 | } |
36 | } | 36 | } |
diff --git a/src/Wallabag/CoreBundle/Form/Type/NewEntryType.php b/src/Wallabag/CoreBundle/Form/Type/NewEntryType.php index 7d74fee3..7af1e589 100644 --- a/src/Wallabag/CoreBundle/Form/Type/NewEntryType.php +++ b/src/Wallabag/CoreBundle/Form/Type/NewEntryType.php | |||
@@ -15,6 +15,7 @@ class NewEntryType extends AbstractType | |||
15 | ->add('url', UrlType::class, [ | 15 | ->add('url', UrlType::class, [ |
16 | 'required' => true, | 16 | 'required' => true, |
17 | 'label' => 'entry.new.form_new.url_label', | 17 | 'label' => 'entry.new.form_new.url_label', |
18 | 'default_protocol' => null, | ||
18 | ]) | 19 | ]) |
19 | ; | 20 | ; |
20 | } | 21 | } |
diff --git a/src/Wallabag/CoreBundle/Form/Type/RenameTagType.php b/src/Wallabag/CoreBundle/Form/Type/RenameTagType.php new file mode 100644 index 00000000..e6270048 --- /dev/null +++ b/src/Wallabag/CoreBundle/Form/Type/RenameTagType.php | |||
@@ -0,0 +1,35 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Form\Type; | ||
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 RenameTagType extends AbstractType | ||
11 | { | ||
12 | public function buildForm(FormBuilderInterface $builder, array $options) | ||
13 | { | ||
14 | $builder | ||
15 | ->add('label', TextType::class, [ | ||
16 | 'required' => true, | ||
17 | 'attr' => [ | ||
18 | 'placeholder' => 'tag.rename.placeholder', | ||
19 | ], | ||
20 | ]) | ||
21 | ; | ||
22 | } | ||
23 | |||
24 | public function configureOptions(OptionsResolver $resolver) | ||
25 | { | ||
26 | $resolver->setDefaults([ | ||
27 | 'data_class' => 'Wallabag\CoreBundle\Entity\Tag', | ||
28 | ]); | ||
29 | } | ||
30 | |||
31 | public function getBlockPrefix() | ||
32 | { | ||
33 | return 'tag'; | ||
34 | } | ||
35 | } | ||
diff --git a/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php b/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php index 07c99949..6e4c9154 100644 --- a/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php +++ b/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php | |||
@@ -21,9 +21,14 @@ class UserInformationType extends AbstractType | |||
21 | ->add('email', EmailType::class, [ | 21 | ->add('email', EmailType::class, [ |
22 | 'label' => 'config.form_user.email_label', | 22 | 'label' => 'config.form_user.email_label', |
23 | ]) | 23 | ]) |
24 | ->add('twoFactorAuthentication', CheckboxType::class, [ | 24 | ->add('emailTwoFactor', CheckboxType::class, [ |
25 | 'required' => false, | 25 | 'required' => false, |
26 | 'label' => 'config.form_user.twoFactorAuthentication_label', | 26 | 'label' => 'config.form_user.emailTwoFactor_label', |
27 | ]) | ||
28 | ->add('googleTwoFactor', CheckboxType::class, [ | ||
29 | 'required' => false, | ||
30 | 'label' => 'config.form_user.googleTwoFactor_label', | ||
31 | 'mapped' => false, | ||
27 | ]) | 32 | ]) |
28 | ->add('save', SubmitType::class, [ | 33 | ->add('save', SubmitType::class, [ |
29 | 'label' => 'config.form.save', | 34 | 'label' => 'config.form.save', |
diff --git a/src/Wallabag/CoreBundle/Helper/ContentProxy.php b/src/Wallabag/CoreBundle/Helper/ContentProxy.php index bc257ffb..c6fa0d98 100644 --- a/src/Wallabag/CoreBundle/Helper/ContentProxy.php +++ b/src/Wallabag/CoreBundle/Helper/ContentProxy.php | |||
@@ -12,8 +12,8 @@ use Wallabag\CoreBundle\Entity\Entry; | |||
12 | use Wallabag\CoreBundle\Tools\Utils; | 12 | use Wallabag\CoreBundle\Tools\Utils; |
13 | 13 | ||
14 | /** | 14 | /** |
15 | * This kind of proxy class take care of getting the content from an url | 15 | * This kind of proxy class takes care of getting the content from an url |
16 | * and update the entry with what it found. | 16 | * and updates the entry with what it found. |
17 | */ | 17 | */ |
18 | class ContentProxy | 18 | class ContentProxy |
19 | { | 19 | { |
@@ -54,7 +54,11 @@ class ContentProxy | |||
54 | 54 | ||
55 | if ((empty($content) || false === $this->validateContent($content)) && false === $disableContentUpdate) { | 55 | if ((empty($content) || false === $this->validateContent($content)) && false === $disableContentUpdate) { |
56 | $fetchedContent = $this->graby->fetchContent($url); | 56 | $fetchedContent = $this->graby->fetchContent($url); |
57 | $fetchedContent['title'] = $this->sanitizeContentTitle($fetchedContent['title'], $fetchedContent['content_type']); | 57 | |
58 | $fetchedContent['title'] = $this->sanitizeContentTitle( | ||
59 | $fetchedContent['title'], | ||
60 | isset($fetchedContent['headers']['content-type']) ? $fetchedContent['headers']['content-type'] : '' | ||
61 | ); | ||
58 | 62 | ||
59 | // when content is imported, we have information in $content | 63 | // when content is imported, we have information in $content |
60 | // in case fetching content goes bad, we'll keep the imported information instead of overriding them | 64 | // in case fetching content goes bad, we'll keep the imported information instead of overriding them |
@@ -188,8 +192,8 @@ class ContentProxy | |||
188 | /** | 192 | /** |
189 | * Try to sanitize the title of the fetched content from wrong character encodings and invalid UTF-8 character. | 193 | * Try to sanitize the title of the fetched content from wrong character encodings and invalid UTF-8 character. |
190 | * | 194 | * |
191 | * @param $title | 195 | * @param string $title |
192 | * @param $contentType | 196 | * @param string $contentType |
193 | * | 197 | * |
194 | * @return string | 198 | * @return string |
195 | */ | 199 | */ |
@@ -253,16 +257,14 @@ class ContentProxy | |||
253 | 257 | ||
254 | if (!empty($content['title'])) { | 258 | if (!empty($content['title'])) { |
255 | $entry->setTitle($content['title']); | 259 | $entry->setTitle($content['title']); |
256 | } elseif (!empty($content['open_graph']['og_title'])) { | ||
257 | $entry->setTitle($content['open_graph']['og_title']); | ||
258 | } | 260 | } |
259 | 261 | ||
260 | if (empty($content['html'])) { | 262 | if (empty($content['html'])) { |
261 | $content['html'] = $this->fetchingErrorMessage; | 263 | $content['html'] = $this->fetchingErrorMessage; |
262 | 264 | ||
263 | if (!empty($content['open_graph']['og_description'])) { | 265 | if (!empty($content['description'])) { |
264 | $content['html'] .= '<p><i>But we found a short description: </i></p>'; | 266 | $content['html'] .= '<p><i>But we found a short description: </i></p>'; |
265 | $content['html'] .= $content['open_graph']['og_description']; | 267 | $content['html'] .= $content['description']; |
266 | } | 268 | } |
267 | } | 269 | } |
268 | 270 | ||
@@ -277,8 +279,8 @@ class ContentProxy | |||
277 | $entry->setPublishedBy($content['authors']); | 279 | $entry->setPublishedBy($content['authors']); |
278 | } | 280 | } |
279 | 281 | ||
280 | if (!empty($content['all_headers']) && $this->storeArticleHeaders) { | 282 | if (!empty($content['headers'])) { |
281 | $entry->setHeaders($content['all_headers']); | 283 | $entry->setHeaders($content['headers']); |
282 | } | 284 | } |
283 | 285 | ||
284 | if (!empty($content['date'])) { | 286 | if (!empty($content['date'])) { |
@@ -289,17 +291,30 @@ class ContentProxy | |||
289 | $this->updateLanguage($entry, $content['language']); | 291 | $this->updateLanguage($entry, $content['language']); |
290 | } | 292 | } |
291 | 293 | ||
292 | if (!empty($content['open_graph']['og_image'])) { | 294 | $previewPictureUrl = ''; |
293 | $this->updatePreviewPicture($entry, $content['open_graph']['og_image']); | 295 | if (!empty($content['image'])) { |
296 | $previewPictureUrl = $content['image']; | ||
294 | } | 297 | } |
295 | 298 | ||
296 | // if content is an image, define it as a preview too | 299 | // if content is an image, define it as a preview too |
297 | if (!empty($content['content_type']) && \in_array($this->mimeGuesser->guess($content['content_type']), ['jpeg', 'jpg', 'gif', 'png'], true)) { | 300 | if (!empty($content['headers']['content-type']) && \in_array($this->mimeGuesser->guess($content['headers']['content-type']), ['jpeg', 'jpg', 'gif', 'png'], true)) { |
298 | $this->updatePreviewPicture($entry, $content['url']); | 301 | $previewPictureUrl = $content['url']; |
302 | } elseif (empty($previewPictureUrl)) { | ||
303 | $this->logger->debug('Extracting images from content to provide a default preview picture'); | ||
304 | $imagesUrls = DownloadImages::extractImagesUrlsFromHtml($content['html']); | ||
305 | $this->logger->debug(\count($imagesUrls) . ' pictures found'); | ||
306 | |||
307 | if (!empty($imagesUrls)) { | ||
308 | $previewPictureUrl = $imagesUrls[0]; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | if (!empty($content['headers']['content-type'])) { | ||
313 | $entry->setMimetype($content['headers']['content-type']); | ||
299 | } | 314 | } |
300 | 315 | ||
301 | if (!empty($content['content_type'])) { | 316 | if (!empty($previewPictureUrl)) { |
302 | $entry->setMimetype($content['content_type']); | 317 | $this->updatePreviewPicture($entry, $previewPictureUrl); |
303 | } | 318 | } |
304 | 319 | ||
305 | try { | 320 | try { |
diff --git a/src/Wallabag/CoreBundle/Helper/DownloadImages.php b/src/Wallabag/CoreBundle/Helper/DownloadImages.php index cc3dcfce..7a39a2e4 100644 --- a/src/Wallabag/CoreBundle/Helper/DownloadImages.php +++ b/src/Wallabag/CoreBundle/Helper/DownloadImages.php | |||
@@ -2,8 +2,13 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\Helper; | 3 | namespace Wallabag\CoreBundle\Helper; |
4 | 4 | ||
5 | use GuzzleHttp\Client; | 5 | use Http\Client\Common\HttpMethodsClient; |
6 | use GuzzleHttp\Message\Response; | 6 | use Http\Client\Common\Plugin\ErrorPlugin; |
7 | use Http\Client\Common\PluginClient; | ||
8 | use Http\Client\HttpClient; | ||
9 | use Http\Discovery\MessageFactoryDiscovery; | ||
10 | use Http\Message\MessageFactory; | ||
11 | use Psr\Http\Message\ResponseInterface; | ||
7 | use Psr\Log\LoggerInterface; | 12 | use Psr\Log\LoggerInterface; |
8 | use Symfony\Component\DomCrawler\Crawler; | 13 | use Symfony\Component\DomCrawler\Crawler; |
9 | use Symfony\Component\Finder\Finder; | 14 | use Symfony\Component\Finder\Finder; |
@@ -19,9 +24,9 @@ class DownloadImages | |||
19 | private $mimeGuesser; | 24 | private $mimeGuesser; |
20 | private $wallabagUrl; | 25 | private $wallabagUrl; |
21 | 26 | ||
22 | public function __construct(Client $client, $baseFolder, $wallabagUrl, LoggerInterface $logger) | 27 | public function __construct(HttpClient $client, $baseFolder, $wallabagUrl, LoggerInterface $logger, MessageFactory $messageFactory = null) |
23 | { | 28 | { |
24 | $this->client = $client; | 29 | $this->client = new HttpMethodsClient(new PluginClient($client, [new ErrorPlugin()]), $messageFactory ?: MessageFactoryDiscovery::find()); |
25 | $this->baseFolder = $baseFolder; | 30 | $this->baseFolder = $baseFolder; |
26 | $this->wallabagUrl = rtrim($wallabagUrl, '/'); | 31 | $this->wallabagUrl = rtrim($wallabagUrl, '/'); |
27 | $this->logger = $logger; | 32 | $this->logger = $logger; |
@@ -31,23 +36,36 @@ class DownloadImages | |||
31 | } | 36 | } |
32 | 37 | ||
33 | /** | 38 | /** |
34 | * Process the html and extract image from it, save them to local and return the updated html. | 39 | * Process the html and extract images URLs from it. |
35 | * | 40 | * |
36 | * @param int $entryId ID of the entry | ||
37 | * @param string $html | 41 | * @param string $html |
38 | * @param string $url Used as a base path for relative image and folder | ||
39 | * | 42 | * |
40 | * @return string | 43 | * @return string[] |
41 | */ | 44 | */ |
42 | public function processHtml($entryId, $html, $url) | 45 | public static function extractImagesUrlsFromHtml($html) |
43 | { | 46 | { |
44 | $crawler = new Crawler($html); | 47 | $crawler = new Crawler($html); |
45 | $imagesCrawler = $crawler | 48 | $imagesCrawler = $crawler |
46 | ->filterXpath('//img'); | 49 | ->filterXpath('//img'); |
47 | $imagesUrls = $imagesCrawler | 50 | $imagesUrls = $imagesCrawler |
48 | ->extract(['src']); | 51 | ->extract(['src']); |
49 | $imagesSrcsetUrls = $this->getSrcsetUrls($imagesCrawler); | 52 | $imagesSrcsetUrls = self::getSrcsetUrls($imagesCrawler); |
50 | $imagesUrls = array_unique(array_merge($imagesUrls, $imagesSrcsetUrls)); | 53 | |
54 | return array_unique(array_merge($imagesUrls, $imagesSrcsetUrls)); | ||
55 | } | ||
56 | |||
57 | /** | ||
58 | * Process the html and extract image from it, save them to local and return the updated html. | ||
59 | * | ||
60 | * @param int $entryId ID of the entry | ||
61 | * @param string $html | ||
62 | * @param string $url Used as a base path for relative image and folder | ||
63 | * | ||
64 | * @return string | ||
65 | */ | ||
66 | public function processHtml($entryId, $html, $url) | ||
67 | { | ||
68 | $imagesUrls = self::extractImagesUrlsFromHtml($html); | ||
51 | 69 | ||
52 | $relativePath = $this->getRelativePath($entryId); | 70 | $relativePath = $this->getRelativePath($entryId); |
53 | 71 | ||
@@ -122,7 +140,7 @@ class DownloadImages | |||
122 | $localPath = $folderPath . '/' . $hashImage . '.' . $ext; | 140 | $localPath = $folderPath . '/' . $hashImage . '.' . $ext; |
123 | 141 | ||
124 | try { | 142 | try { |
125 | $im = imagecreatefromstring($res->getBody()); | 143 | $im = imagecreatefromstring((string) $res->getBody()); |
126 | } catch (\Exception $e) { | 144 | } catch (\Exception $e) { |
127 | $im = false; | 145 | $im = false; |
128 | } | 146 | } |
@@ -135,7 +153,21 @@ class DownloadImages | |||
135 | 153 | ||
136 | switch ($ext) { | 154 | switch ($ext) { |
137 | case 'gif': | 155 | case 'gif': |
138 | imagegif($im, $localPath); | 156 | // use Imagick if available to keep GIF animation |
157 | if (class_exists('\\Imagick')) { | ||
158 | try { | ||
159 | $imagick = new \Imagick(); | ||
160 | $imagick->readImageBlob($res->getBody()); | ||
161 | $imagick->setImageFormat('gif'); | ||
162 | $imagick->writeImages($localPath, true); | ||
163 | } catch (\Exception $e) { | ||
164 | // if Imagick fail, fallback to the default solution | ||
165 | imagegif($im, $localPath); | ||
166 | } | ||
167 | } else { | ||
168 | imagegif($im, $localPath); | ||
169 | } | ||
170 | |||
139 | $this->logger->debug('DownloadImages: Re-creating gif'); | 171 | $this->logger->debug('DownloadImages: Re-creating gif'); |
140 | break; | 172 | break; |
141 | case 'jpeg': | 173 | case 'jpeg': |
@@ -185,7 +217,7 @@ class DownloadImages | |||
185 | * | 217 | * |
186 | * @return array An array of urls | 218 | * @return array An array of urls |
187 | */ | 219 | */ |
188 | private function getSrcsetUrls(Crawler $imagesCrawler) | 220 | private static function getSrcsetUrls(Crawler $imagesCrawler) |
189 | { | 221 | { |
190 | $urls = []; | 222 | $urls = []; |
191 | $iterator = $imagesCrawler | 223 | $iterator = $imagesCrawler |
@@ -279,14 +311,14 @@ class DownloadImages | |||
279 | /** | 311 | /** |
280 | * Retrieve and validate the extension from the response of the url of the image. | 312 | * Retrieve and validate the extension from the response of the url of the image. |
281 | * | 313 | * |
282 | * @param Response $res Guzzle Response | 314 | * @param ResponseInterface $res Http Response |
283 | * @param string $imagePath Path from the src image from the content (used for log only) | 315 | * @param string $imagePath Path from the src image from the content (used for log only) |
284 | * | 316 | * |
285 | * @return string|false Extension name or false if validation failed | 317 | * @return string|false Extension name or false if validation failed |
286 | */ | 318 | */ |
287 | private function getExtensionFromResponse(Response $res, $imagePath) | 319 | private function getExtensionFromResponse(ResponseInterface $res, $imagePath) |
288 | { | 320 | { |
289 | $ext = $this->mimeGuesser->guess($res->getHeader('content-type')); | 321 | $ext = $this->mimeGuesser->guess(current($res->getHeader('content-type'))); |
290 | $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]); | 322 | $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]); |
291 | 323 | ||
292 | // ok header doesn't have the extension, try a different way | 324 | // ok header doesn't have the extension, try a different way |
diff --git a/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php b/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php index 4602a684..b8e95381 100644 --- a/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php +++ b/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php | |||
@@ -2,16 +2,18 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\Helper; | 3 | namespace Wallabag\CoreBundle\Helper; |
4 | 4 | ||
5 | use Graby\Ring\Client\SafeCurlHandler; | 5 | use GuzzleHttp\Client as GuzzleClient; |
6 | use GuzzleHttp\Client; | ||
7 | use GuzzleHttp\Cookie\CookieJar; | 6 | use GuzzleHttp\Cookie\CookieJar; |
8 | use GuzzleHttp\Event\SubscriberInterface; | 7 | use GuzzleHttp\Event\SubscriberInterface; |
8 | use Http\Adapter\Guzzle5\Client as GuzzleAdapter; | ||
9 | use Http\Client\HttpClient; | ||
10 | use Http\HttplugBundle\ClientFactory\ClientFactory; | ||
9 | use Psr\Log\LoggerInterface; | 11 | use Psr\Log\LoggerInterface; |
10 | 12 | ||
11 | /** | 13 | /** |
12 | * Builds and configures the Guzzle HTTP client. | 14 | * Builds and configures the HTTP client. |
13 | */ | 15 | */ |
14 | class HttpClientFactory | 16 | class HttpClientFactory implements ClientFactory |
15 | { | 17 | { |
16 | /** @var [\GuzzleHttp\Event\SubscriberInterface] */ | 18 | /** @var [\GuzzleHttp\Event\SubscriberInterface] */ |
17 | private $subscribers = []; | 19 | private $subscribers = []; |
@@ -37,35 +39,42 @@ class HttpClientFactory | |||
37 | } | 39 | } |
38 | 40 | ||
39 | /** | 41 | /** |
40 | * @return \GuzzleHttp\Client|null | 42 | * Adds a subscriber to the HTTP client. |
43 | * | ||
44 | * @param SubscriberInterface $subscriber | ||
45 | */ | ||
46 | public function addSubscriber(SubscriberInterface $subscriber) | ||
47 | { | ||
48 | $this->subscribers[] = $subscriber; | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * Input an array of configuration to be able to create a HttpClient. | ||
53 | * | ||
54 | * @param array $config | ||
55 | * | ||
56 | * @return HttpClient | ||
41 | */ | 57 | */ |
42 | public function buildHttpClient() | 58 | public function createClient(array $config = []) |
43 | { | 59 | { |
44 | $this->logger->log('debug', 'Restricted access config enabled?', ['enabled' => (int) $this->restrictedAccess]); | 60 | $this->logger->log('debug', 'Restricted access config enabled?', ['enabled' => (int) $this->restrictedAccess]); |
45 | 61 | ||
46 | if (0 === (int) $this->restrictedAccess) { | 62 | if (0 === (int) $this->restrictedAccess) { |
47 | return; | 63 | return new GuzzleAdapter(new GuzzleClient($config)); |
48 | } | 64 | } |
49 | 65 | ||
50 | // we clear the cookie to avoid websites who use cookies for analytics | 66 | // we clear the cookie to avoid websites who use cookies for analytics |
51 | $this->cookieJar->clear(); | 67 | $this->cookieJar->clear(); |
52 | // need to set the (shared) cookie jar | 68 | if (!isset($config['defaults']['cookies'])) { |
53 | $client = new Client(['handler' => new SafeCurlHandler(), 'defaults' => ['cookies' => $this->cookieJar]]); | 69 | // need to set the (shared) cookie jar |
70 | $config['defaults']['cookies'] = $this->cookieJar; | ||
71 | } | ||
54 | 72 | ||
73 | $guzzle = new GuzzleClient($config); | ||
55 | foreach ($this->subscribers as $subscriber) { | 74 | foreach ($this->subscribers as $subscriber) { |
56 | $client->getEmitter()->attach($subscriber); | 75 | $guzzle->getEmitter()->attach($subscriber); |
57 | } | 76 | } |
58 | 77 | ||
59 | return $client; | 78 | return new GuzzleAdapter($guzzle); |
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 | } | 79 | } |
71 | } | 80 | } |
diff --git a/src/Wallabag/CoreBundle/Helper/PreparePagerForEntries.php b/src/Wallabag/CoreBundle/Helper/PreparePagerForEntries.php index 183d394a..04abc6d0 100644 --- a/src/Wallabag/CoreBundle/Helper/PreparePagerForEntries.php +++ b/src/Wallabag/CoreBundle/Helper/PreparePagerForEntries.php | |||
@@ -21,7 +21,7 @@ class PreparePagerForEntries | |||
21 | 21 | ||
22 | /** | 22 | /** |
23 | * @param AdapterInterface $adapter | 23 | * @param AdapterInterface $adapter |
24 | * @param User $user If user isn't logged in, we can force it (like for rss) | 24 | * @param User $user If user isn't logged in, we can force it (like for feed) |
25 | * | 25 | * |
26 | * @return Pagerfanta|null | 26 | * @return Pagerfanta|null |
27 | */ | 27 | */ |
diff --git a/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php b/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php index 63f65067..fbdf2ac7 100644 --- a/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php +++ b/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php | |||
@@ -6,6 +6,7 @@ use Psr\Log\LoggerInterface; | |||
6 | use RulerZ\RulerZ; | 6 | use RulerZ\RulerZ; |
7 | use Wallabag\CoreBundle\Entity\Entry; | 7 | use Wallabag\CoreBundle\Entity\Entry; |
8 | use Wallabag\CoreBundle\Entity\Tag; | 8 | use Wallabag\CoreBundle\Entity\Tag; |
9 | use Wallabag\CoreBundle\Entity\TaggingRule; | ||
9 | use Wallabag\CoreBundle\Repository\EntryRepository; | 10 | use Wallabag\CoreBundle\Repository\EntryRepository; |
10 | use Wallabag\CoreBundle\Repository\TagRepository; | 11 | use Wallabag\CoreBundle\Repository\TagRepository; |
11 | use Wallabag\UserBundle\Entity\User; | 12 | use Wallabag\UserBundle\Entity\User; |
diff --git a/src/Wallabag/CoreBundle/Helper/UrlHasher.php b/src/Wallabag/CoreBundle/Helper/UrlHasher.php new file mode 100644 index 00000000..d123eaba --- /dev/null +++ b/src/Wallabag/CoreBundle/Helper/UrlHasher.php | |||
@@ -0,0 +1,23 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Helper; | ||
4 | |||
5 | /** | ||
6 | * Hash URLs for privacy and performance. | ||
7 | */ | ||
8 | class UrlHasher | ||
9 | { | ||
10 | /** | ||
11 | * Hash the given url using the given algorithm. | ||
12 | * Hashed url are faster to be retrieved in the database than the real url. | ||
13 | * | ||
14 | * @param string $url | ||
15 | * @param string $algorithm | ||
16 | * | ||
17 | * @return string | ||
18 | */ | ||
19 | public static function hashUrl(string $url, $algorithm = 'sha1') | ||
20 | { | ||
21 | return hash($algorithm, urldecode($url)); | ||
22 | } | ||
23 | } | ||
diff --git a/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php b/src/Wallabag/CoreBundle/ParamConverter/UsernameFeedTokenConverter.php index 4a2fcab5..e220abfc 100644 --- a/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php +++ b/src/Wallabag/CoreBundle/ParamConverter/UsernameFeedTokenConverter.php | |||
@@ -10,12 +10,12 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | |||
10 | use Wallabag\UserBundle\Entity\User; | 10 | use Wallabag\UserBundle\Entity\User; |
11 | 11 | ||
12 | /** | 12 | /** |
13 | * ParamConverter used in the RSS controller to retrieve the right user according to | 13 | * ParamConverter used in the Feed controller to retrieve the right user according to |
14 | * username & token given in the url. | 14 | * username & token given in the url. |
15 | * | 15 | * |
16 | * @see http://stfalcon.com/en/blog/post/symfony2-custom-paramconverter | 16 | * @see http://stfalcon.com/en/blog/post/symfony2-custom-paramconverter |
17 | */ | 17 | */ |
18 | class UsernameRssTokenConverter implements ParamConverterInterface | 18 | class UsernameFeedTokenConverter implements ParamConverterInterface |
19 | { | 19 | { |
20 | private $registry; | 20 | private $registry; |
21 | 21 | ||
@@ -67,7 +67,7 @@ class UsernameRssTokenConverter implements ParamConverterInterface | |||
67 | public function apply(Request $request, ParamConverter $configuration) | 67 | public function apply(Request $request, ParamConverter $configuration) |
68 | { | 68 | { |
69 | $username = $request->attributes->get('username'); | 69 | $username = $request->attributes->get('username'); |
70 | $rssToken = $request->attributes->get('token'); | 70 | $feedToken = $request->attributes->get('token'); |
71 | 71 | ||
72 | if (!$request->attributes->has('username') || !$request->attributes->has('token')) { | 72 | if (!$request->attributes->has('username') || !$request->attributes->has('token')) { |
73 | return false; | 73 | return false; |
@@ -78,8 +78,8 @@ class UsernameRssTokenConverter implements ParamConverterInterface | |||
78 | 78 | ||
79 | $userRepository = $em->getRepository($configuration->getClass()); | 79 | $userRepository = $em->getRepository($configuration->getClass()); |
80 | 80 | ||
81 | // Try to find user by its username and config rss_token | 81 | // Try to find user by its username and config feed_token |
82 | $user = $userRepository->findOneByUsernameAndRsstoken($username, $rssToken); | 82 | $user = $userRepository->findOneByUsernameAndFeedtoken($username, $feedToken); |
83 | 83 | ||
84 | if (null === $user || !($user instanceof User)) { | 84 | if (null === $user || !($user instanceof User)) { |
85 | throw new NotFoundHttpException(sprintf('%s not found.', $configuration->getClass())); | 85 | throw new NotFoundHttpException(sprintf('%s not found.', $configuration->getClass())); |
diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index cebce714..880e7c65 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php | |||
@@ -3,11 +3,13 @@ | |||
3 | namespace Wallabag\CoreBundle\Repository; | 3 | namespace Wallabag\CoreBundle\Repository; |
4 | 4 | ||
5 | use Doctrine\ORM\EntityRepository; | 5 | use Doctrine\ORM\EntityRepository; |
6 | use Doctrine\ORM\NoResultException; | ||
6 | use Doctrine\ORM\QueryBuilder; | 7 | use Doctrine\ORM\QueryBuilder; |
7 | use Pagerfanta\Adapter\DoctrineORMAdapter; | 8 | use Pagerfanta\Adapter\DoctrineORMAdapter; |
8 | use Pagerfanta\Pagerfanta; | 9 | use Pagerfanta\Pagerfanta; |
9 | use Wallabag\CoreBundle\Entity\Entry; | 10 | use Wallabag\CoreBundle\Entity\Entry; |
10 | use Wallabag\CoreBundle\Entity\Tag; | 11 | use Wallabag\CoreBundle\Entity\Tag; |
12 | use Wallabag\CoreBundle\Helper\UrlHasher; | ||
11 | 13 | ||
12 | class EntryRepository extends EntityRepository | 14 | class EntryRepository extends EntityRepository |
13 | { | 15 | { |
@@ -50,7 +52,7 @@ class EntryRepository extends EntityRepository | |||
50 | public function getBuilderForArchiveByUser($userId) | 52 | public function getBuilderForArchiveByUser($userId) |
51 | { | 53 | { |
52 | return $this | 54 | return $this |
53 | ->getSortedQueryBuilderByUser($userId) | 55 | ->getSortedQueryBuilderByUser($userId, 'archivedAt', 'desc') |
54 | ->andWhere('e.isArchived = true') | 56 | ->andWhere('e.isArchived = true') |
55 | ; | 57 | ; |
56 | } | 58 | } |
@@ -110,8 +112,7 @@ class EntryRepository extends EntityRepository | |||
110 | */ | 112 | */ |
111 | public function getBuilderForUntaggedByUser($userId) | 113 | public function getBuilderForUntaggedByUser($userId) |
112 | { | 114 | { |
113 | return $this | 115 | return $this->sortQueryBuilder($this->getRawBuilderForUntaggedByUser($userId)); |
114 | ->sortQueryBuilder($this->getRawBuilderForUntaggedByUser($userId)); | ||
115 | } | 116 | } |
116 | 117 | ||
117 | /** | 118 | /** |
@@ -139,15 +140,30 @@ class EntryRepository extends EntityRepository | |||
139 | * @param string $order | 140 | * @param string $order |
140 | * @param int $since | 141 | * @param int $since |
141 | * @param string $tags | 142 | * @param string $tags |
143 | * @param string $detail 'metadata' or 'full'. Include content field if 'full' | ||
144 | * | ||
145 | * @todo Breaking change: replace default detail=full by detail=metadata in a future version | ||
142 | * | 146 | * |
143 | * @return Pagerfanta | 147 | * @return Pagerfanta |
144 | */ | 148 | */ |
145 | public function findEntries($userId, $isArchived = null, $isStarred = null, $isPublic = null, $sort = 'created', $order = 'asc', $since = 0, $tags = '') | 149 | public function findEntries($userId, $isArchived = null, $isStarred = null, $isPublic = null, $sort = 'created', $order = 'asc', $since = 0, $tags = '', $detail = 'full') |
146 | { | 150 | { |
151 | if (!\in_array(strtolower($detail), ['full', 'metadata'], true)) { | ||
152 | throw new \Exception('Detail "' . $detail . '" parameter is wrong, allowed: full or metadata'); | ||
153 | } | ||
154 | |||
147 | $qb = $this->createQueryBuilder('e') | 155 | $qb = $this->createQueryBuilder('e') |
148 | ->leftJoin('e.tags', 't') | 156 | ->leftJoin('e.tags', 't') |
149 | ->where('e.user = :userId')->setParameter('userId', $userId); | 157 | ->where('e.user = :userId')->setParameter('userId', $userId); |
150 | 158 | ||
159 | if ('metadata' === $detail) { | ||
160 | $fieldNames = $this->getClassMetadata()->getFieldNames(); | ||
161 | $fields = array_filter($fieldNames, function ($k) { | ||
162 | return 'content' !== $k; | ||
163 | }); | ||
164 | $qb->select(sprintf('partial e.{%s}', implode(',', $fields))); | ||
165 | } | ||
166 | |||
151 | if (null !== $isArchived) { | 167 | if (null !== $isArchived) { |
152 | $qb->andWhere('e.isArchived = :isArchived')->setParameter('isArchived', (bool) $isArchived); | 168 | $qb->andWhere('e.isArchived = :isArchived')->setParameter('isArchived', (bool) $isArchived); |
153 | } | 169 | } |
@@ -193,6 +209,8 @@ class EntryRepository extends EntityRepository | |||
193 | $qb->orderBy('e.id', $order); | 209 | $qb->orderBy('e.id', $order); |
194 | } elseif ('updated' === $sort) { | 210 | } elseif ('updated' === $sort) { |
195 | $qb->orderBy('e.updatedAt', $order); | 211 | $qb->orderBy('e.updatedAt', $order); |
212 | } elseif ('archived' === $sort) { | ||
213 | $qb->orderBy('e.archivedAt', $order); | ||
196 | } | 214 | } |
197 | 215 | ||
198 | $pagerAdapter = new DoctrineORMAdapter($qb, true, false); | 216 | $pagerAdapter = new DoctrineORMAdapter($qb, true, false); |
@@ -324,15 +342,32 @@ class EntryRepository extends EntityRepository | |||
324 | * Find an entry by its url and its owner. | 342 | * Find an entry by its url and its owner. |
325 | * If it exists, return the entry otherwise return false. | 343 | * If it exists, return the entry otherwise return false. |
326 | * | 344 | * |
327 | * @param $url | 345 | * @param string $url |
328 | * @param $userId | 346 | * @param int $userId |
329 | * | 347 | * |
330 | * @return Entry|bool | 348 | * @return Entry|bool |
331 | */ | 349 | */ |
332 | public function findByUrlAndUserId($url, $userId) | 350 | public function findByUrlAndUserId($url, $userId) |
333 | { | 351 | { |
352 | return $this->findByHashedUrlAndUserId( | ||
353 | UrlHasher::hashUrl($url), | ||
354 | $userId | ||
355 | ); | ||
356 | } | ||
357 | |||
358 | /** | ||
359 | * Find an entry by its hashed url and its owner. | ||
360 | * If it exists, return the entry otherwise return false. | ||
361 | * | ||
362 | * @param string $hashedUrl Url hashed using sha1 | ||
363 | * @param int $userId | ||
364 | * | ||
365 | * @return Entry|bool | ||
366 | */ | ||
367 | public function findByHashedUrlAndUserId($hashedUrl, $userId) | ||
368 | { | ||
334 | $res = $this->createQueryBuilder('e') | 369 | $res = $this->createQueryBuilder('e') |
335 | ->where('e.url = :url')->setParameter('url', urldecode($url)) | 370 | ->where('e.hashedUrl = :hashed_url')->setParameter('hashed_url', $hashedUrl) |
336 | ->andWhere('e.user = :user_id')->setParameter('user_id', $userId) | 371 | ->andWhere('e.user = :user_id')->setParameter('user_id', $userId) |
337 | ->getQuery() | 372 | ->getQuery() |
338 | ->getResult(); | 373 | ->getResult(); |
@@ -416,8 +451,8 @@ class EntryRepository extends EntityRepository | |||
416 | /** | 451 | /** |
417 | * Find all entries by url and owner. | 452 | * Find all entries by url and owner. |
418 | * | 453 | * |
419 | * @param $url | 454 | * @param string $url |
420 | * @param $userId | 455 | * @param int $userId |
421 | * | 456 | * |
422 | * @return array | 457 | * @return array |
423 | */ | 458 | */ |
@@ -431,6 +466,49 @@ class EntryRepository extends EntityRepository | |||
431 | } | 466 | } |
432 | 467 | ||
433 | /** | 468 | /** |
469 | * Returns a random entry, filtering by status. | ||
470 | * | ||
471 | * @param int $userId | ||
472 | * @param string $type Can be unread, archive, starred, etc | ||
473 | * | ||
474 | * @throws NoResultException | ||
475 | * | ||
476 | * @return Entry | ||
477 | */ | ||
478 | public function getRandomEntry($userId, $type = '') | ||
479 | { | ||
480 | $qb = $this->getQueryBuilderByUser($userId) | ||
481 | ->select('e.id'); | ||
482 | |||
483 | switch ($type) { | ||
484 | case 'unread': | ||
485 | $qb->andWhere('e.isArchived = false'); | ||
486 | break; | ||
487 | case 'archive': | ||
488 | $qb->andWhere('e.isArchived = true'); | ||
489 | break; | ||
490 | case 'starred': | ||
491 | $qb->andWhere('e.isStarred = true'); | ||
492 | break; | ||
493 | case 'untagged': | ||
494 | $qb->leftJoin('e.tags', 't'); | ||
495 | $qb->andWhere('t.id is null'); | ||
496 | break; | ||
497 | } | ||
498 | |||
499 | $ids = $qb->getQuery()->getArrayResult(); | ||
500 | |||
501 | if (empty($ids)) { | ||
502 | throw new NoResultException(); | ||
503 | } | ||
504 | |||
505 | // random select one in the list | ||
506 | $randomId = $ids[mt_rand(0, \count($ids) - 1)]['id']; | ||
507 | |||
508 | return $this->find($randomId); | ||
509 | } | ||
510 | |||
511 | /** | ||
434 | * Return a query builder to be used by other getBuilderFor* method. | 512 | * Return a query builder to be used by other getBuilderFor* method. |
435 | * | 513 | * |
436 | * @param int $userId | 514 | * @param int $userId |
@@ -468,7 +546,6 @@ class EntryRepository extends EntityRepository | |||
468 | */ | 546 | */ |
469 | private function sortQueryBuilder(QueryBuilder $qb, $sortBy = 'createdAt', $direction = 'desc') | 547 | private function sortQueryBuilder(QueryBuilder $qb, $sortBy = 'createdAt', $direction = 'desc') |
470 | { | 548 | { |
471 | return $qb | 549 | return $qb->orderBy(sprintf('e.%s', $sortBy), $direction); |
472 | ->orderBy(sprintf('e.%s', $sortBy), $direction); | ||
473 | } | 550 | } |
474 | } | 551 | } |
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index 85306276..31986951 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml | |||
@@ -22,10 +22,10 @@ services: | |||
22 | tags: | 22 | tags: |
23 | - { name: form.type } | 23 | - { name: form.type } |
24 | 24 | ||
25 | wallabag_core.param_converter.username_rsstoken_converter: | 25 | wallabag_core.param_converter.username_feed_token_converter: |
26 | class: Wallabag\CoreBundle\ParamConverter\UsernameRssTokenConverter | 26 | class: Wallabag\CoreBundle\ParamConverter\UsernameFeedTokenConverter |
27 | tags: | 27 | tags: |
28 | - { name: request.param_converter, converter: username_rsstoken_converter } | 28 | - { name: request.param_converter, converter: username_feed_token_converter } |
29 | arguments: | 29 | arguments: |
30 | - "@doctrine" | 30 | - "@doctrine" |
31 | 31 | ||
@@ -42,7 +42,7 @@ services: | |||
42 | - | 42 | - |
43 | error_message: '%wallabag_core.fetching_error_message%' | 43 | error_message: '%wallabag_core.fetching_error_message%' |
44 | error_message_title: '%wallabag_core.fetching_error_message_title%' | 44 | error_message_title: '%wallabag_core.fetching_error_message_title%' |
45 | - "@wallabag_core.guzzle.http_client" | 45 | - "@wallabag_core.http_client" |
46 | - "@wallabag_core.graby.config_builder" | 46 | - "@wallabag_core.graby.config_builder" |
47 | calls: | 47 | calls: |
48 | - [ setLogger, [ "@logger" ] ] | 48 | - [ setLogger, [ "@logger" ] ] |
@@ -55,9 +55,8 @@ services: | |||
55 | - {} | 55 | - {} |
56 | - "@logger" | 56 | - "@logger" |
57 | 57 | ||
58 | wallabag_core.guzzle.http_client: | 58 | wallabag_core.http_client: |
59 | class: GuzzleHttp\ClientInterface | 59 | alias: 'httplug.client.wallabag_core' |
60 | factory: ["@wallabag_core.guzzle.http_client_factory", buildHttpClient] | ||
61 | 60 | ||
62 | wallabag_core.guzzle_authenticator.config_builder: | 61 | wallabag_core.guzzle_authenticator.config_builder: |
63 | class: Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder | 62 | class: Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder |
@@ -73,7 +72,7 @@ services: | |||
73 | bd_guzzle_site_authenticator.site_config_builder: | 72 | bd_guzzle_site_authenticator.site_config_builder: |
74 | alias: wallabag_core.guzzle_authenticator.config_builder | 73 | alias: wallabag_core.guzzle_authenticator.config_builder |
75 | 74 | ||
76 | wallabag_core.guzzle.http_client_factory: | 75 | wallabag_core.http_client_factory: |
77 | class: Wallabag\CoreBundle\Helper\HttpClientFactory | 76 | class: Wallabag\CoreBundle\Helper\HttpClientFactory |
78 | arguments: | 77 | arguments: |
79 | - "@wallabag_core.guzzle.cookie_jar" | 78 | - "@wallabag_core.guzzle.cookie_jar" |
@@ -181,6 +180,7 @@ services: | |||
181 | 180 | ||
182 | wallabag_core.exception_controller: | 181 | wallabag_core.exception_controller: |
183 | class: Wallabag\CoreBundle\Controller\ExceptionController | 182 | class: Wallabag\CoreBundle\Controller\ExceptionController |
183 | public: true | ||
184 | arguments: | 184 | arguments: |
185 | - '@twig' | 185 | - '@twig' |
186 | - '%kernel.debug%' | 186 | - '%kernel.debug%' |
@@ -211,10 +211,38 @@ services: | |||
211 | - "@logger" | 211 | - "@logger" |
212 | 212 | ||
213 | wallabag_core.entry.download_images.client: | 213 | wallabag_core.entry.download_images.client: |
214 | class: GuzzleHttp\Client | 214 | alias: 'httplug.client.wallabag_core.entry.download_images' |
215 | 215 | ||
216 | wallabag_core.helper.crypto_proxy: | 216 | wallabag_core.helper.crypto_proxy: |
217 | class: Wallabag\CoreBundle\Helper\CryptoProxy | 217 | class: Wallabag\CoreBundle\Helper\CryptoProxy |
218 | arguments: | 218 | arguments: |
219 | - "%wallabag_core.site_credentials.encryption_key_path%" | 219 | - "%wallabag_core.site_credentials.encryption_key_path%" |
220 | - "@logger" | 220 | - "@logger" |
221 | |||
222 | wallabag_core.command.clean_duplicates: | ||
223 | class: Wallabag\CoreBundle\Command\CleanDuplicatesCommand | ||
224 | tags: ['console.command'] | ||
225 | |||
226 | wallabag_core.command.export: | ||
227 | class: Wallabag\CoreBundle\Command\ExportCommand | ||
228 | tags: ['console.command'] | ||
229 | |||
230 | wallabag_core.command.install: | ||
231 | class: Wallabag\CoreBundle\Command\InstallCommand | ||
232 | tags: ['console.command'] | ||
233 | |||
234 | wallabag_core.command.list_user: | ||
235 | class: Wallabag\CoreBundle\Command\ListUserCommand | ||
236 | tags: ['console.command'] | ||
237 | |||
238 | wallabag_core.command.reload_entry: | ||
239 | class: Wallabag\CoreBundle\Command\ReloadEntryCommand | ||
240 | tags: ['console.command'] | ||
241 | |||
242 | wallabag_core.command.show_user: | ||
243 | class: Wallabag\CoreBundle\Command\ShowUserCommand | ||
244 | tags: ['console.command'] | ||
245 | |||
246 | wallabag_core.command.tag_all: | ||
247 | class: Wallabag\CoreBundle\Command\TagAllCommand | ||
248 | tags: ['console.command'] | ||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml index 6f842534..e04c2ff1 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'Tilføj ny artikel' | 37 | add_new_entry: 'Tilføj ny artikel' |
38 | search: 'Søg' | 38 | search: 'Søg' |
39 | filter_entries: 'Filtrer artikler' | 39 | filter_entries: 'Filtrer artikler' |
40 | # random_entry: Jump to a random entry from that list | ||
40 | # export: 'Export' | 41 | # export: 'Export' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'Indtast søgning' | 43 | input_label: 'Indtast søgning' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'Opsætning' | 54 | page_title: 'Opsætning' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'Indstillinger' | 56 | settings: 'Indstillinger' |
56 | rss: 'RSS' | 57 | feed: 'RSS' |
57 | user_info: 'Brugeroplysninger' | 58 | user_info: 'Brugeroplysninger' |
58 | password: 'Adgangskode' | 59 | password: 'Adgangskode' |
59 | # rules: 'Tagging rules' | 60 | # rules: 'Tagging rules' |
60 | new_user: 'Tilføj bruger' | 61 | new_user: 'Tilføj bruger' |
62 | # reset: 'Reset area' | ||
61 | form: | 63 | form: |
62 | save: 'Gem' | 64 | save: 'Gem' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,33 @@ config: | |||
83 | # help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." | 85 | # help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." |
84 | # help_language: "You can change the language of wallabag interface." | 86 | # help_language: "You can change the language of wallabag interface." |
85 | # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." | 87 | # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." |
86 | form_rss: | 88 | form_feed: |
87 | description: 'RSS-feeds fra wallabag gør det muligt at læse de artikler, der gemmes i wallabag, med din RSS-læser. Det kræver, at du genererer et token først.' | 89 | description: 'RSS-feeds fra wallabag gør det muligt at læse de artikler, der gemmes i wallabag, med din RSS-læser. Det kræver, at du genererer et token først.' |
88 | token_label: 'RSS-Token' | 90 | token_label: 'RSS-Token' |
89 | no_token: 'Intet token' | 91 | no_token: 'Intet token' |
90 | token_create: 'Opret token' | 92 | token_create: 'Opret token' |
91 | token_reset: 'Nulstil token' | 93 | token_reset: 'Nulstil token' |
92 | rss_links: 'RSS-Links' | 94 | feed_links: 'RSS-Links' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'Ulæst' | 96 | unread: 'Ulæst' |
95 | starred: 'Favoritter' | 97 | starred: 'Favoritter' |
96 | archive: 'Arkiv' | 98 | archive: 'Arkiv' |
97 | # all: 'All' | 99 | # all: 'All' |
98 | # rss_limit: 'Number of items in the feed' | 100 | # feed_limit: 'Number of items in the feed' |
99 | form_user: | 101 | form_user: |
100 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code on every new untrusted connexion" | 102 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'Navn' | 103 | name_label: 'Navn' |
102 | email_label: 'Emailadresse' | 104 | email_label: 'Emailadresse' |
103 | # twoFactorAuthentication_label: 'Two factor authentication' | 105 | two_factor: |
104 | # help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email." | 106 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
107 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' | ||
108 | # table_method: Method | ||
109 | # table_state: State | ||
110 | # table_action: Action | ||
111 | # state_enabled: Enabled | ||
112 | # state_disabled: Disabled | ||
113 | # action_email: Use email | ||
114 | # action_app: Use OTP App | ||
105 | delete: | 115 | delete: |
106 | # title: Delete my account (a.k.a danger zone) | 116 | # title: Delete my account (a.k.a danger zone) |
107 | # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. | 117 | # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. |
@@ -159,6 +169,15 @@ config: | |||
159 | # and: 'One rule AND another' | 169 | # and: 'One rule AND another' |
160 | # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' | 170 | # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' |
161 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' | 171 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' |
172 | otp: | ||
173 | # page_title: Two-factor authentication | ||
174 | # app: | ||
175 | # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
176 | # two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
177 | # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
178 | # two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
179 | # cancel: Cancel | ||
180 | # enable: Enable | ||
162 | 181 | ||
163 | entry: | 182 | entry: |
164 | # default_title: 'Title of the entry' | 183 | # default_title: 'Title of the entry' |
@@ -353,7 +372,7 @@ quickstart: | |||
353 | # title: 'Configure the application' | 372 | # title: 'Configure the application' |
354 | # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' | 373 | # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' |
355 | # language: 'Change language and design' | 374 | # language: 'Change language and design' |
356 | # rss: 'Enable RSS feeds' | 375 | # feed: 'Enable RSS feeds' |
357 | # tagging_rules: 'Write rules to automatically tag your articles' | 376 | # tagging_rules: 'Write rules to automatically tag your articles' |
358 | # admin: | 377 | # admin: |
359 | # title: 'Administration' | 378 | # title: 'Administration' |
@@ -404,6 +423,8 @@ tag: | |||
404 | new: | 423 | new: |
405 | # add: 'Add' | 424 | # add: 'Add' |
406 | # placeholder: 'You can add several tags, separated by a comma.' | 425 | # placeholder: 'You can add several tags, separated by a comma.' |
426 | rename: | ||
427 | # placeholder: 'You can update tag name.' | ||
407 | 428 | ||
408 | # export: | 429 | # export: |
409 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' | 430 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' |
@@ -529,7 +550,8 @@ user: | |||
529 | email_label: 'Emailadresse' | 550 | email_label: 'Emailadresse' |
530 | # enabled_label: 'Enabled' | 551 | # enabled_label: 'Enabled' |
531 | # last_login_label: 'Last login' | 552 | # last_login_label: 'Last login' |
532 | # twofactor_label: Two factor authentication | 553 | # twofactor_email_label: Two factor authentication by email |
554 | # twofactor_google_label: Two factor authentication by OTP app | ||
533 | # save: Save | 555 | # save: Save |
534 | # delete: Delete | 556 | # delete: Delete |
535 | # delete_confirm: Are you sure? | 557 | # delete_confirm: Are you sure? |
@@ -567,10 +589,10 @@ flashes: | |||
567 | password_updated: 'Adgangskode opdateret' | 589 | password_updated: 'Adgangskode opdateret' |
568 | # password_not_updated_demo: "In demonstration mode, you can't change password for this user." | 590 | # password_not_updated_demo: "In demonstration mode, you can't change password for this user." |
569 | user_updated: 'Oplysninger opdateret' | 591 | user_updated: 'Oplysninger opdateret' |
570 | rss_updated: 'RSS-oplysninger opdateret' | 592 | feed_updated: 'RSS-oplysninger opdateret' |
571 | # tagging_rules_updated: 'Tagging rules updated' | 593 | # tagging_rules_updated: 'Tagging rules updated' |
572 | # tagging_rules_deleted: 'Tagging rule deleted' | 594 | # tagging_rules_deleted: 'Tagging rule deleted' |
573 | # rss_token_updated: 'RSS token updated' | 595 | # feed_token_updated: 'RSS token updated' |
574 | # annotations_reset: Annotations reset | 596 | # annotations_reset: Annotations reset |
575 | # tags_reset: Tags reset | 597 | # tags_reset: Tags reset |
576 | # entries_reset: Entries reset | 598 | # entries_reset: Entries reset |
@@ -588,9 +610,11 @@ flashes: | |||
588 | entry_starred: 'Artikel markeret som favorit' | 610 | entry_starred: 'Artikel markeret som favorit' |
589 | entry_unstarred: 'Artikel ikke længere markeret som favorit' | 611 | entry_unstarred: 'Artikel ikke længere markeret som favorit' |
590 | entry_deleted: 'Artikel slettet' | 612 | entry_deleted: 'Artikel slettet' |
613 | # no_random_entry: 'No article with these criterias was found' | ||
591 | tag: | 614 | tag: |
592 | notice: | 615 | notice: |
593 | # tag_added: 'Tag added' | 616 | # tag_added: 'Tag added' |
617 | # tag_renamed: 'Tag renamed' | ||
594 | import: | 618 | import: |
595 | notice: | 619 | notice: |
596 | # failed: 'Import failed, please try again.' | 620 | # failed: 'Import failed, please try again.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml index 874908b9..5a9668a9 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'Neuen Artikel hinzufügen' | 37 | add_new_entry: 'Neuen Artikel hinzufügen' |
38 | search: 'Suche' | 38 | search: 'Suche' |
39 | filter_entries: 'Artikel filtern' | 39 | filter_entries: 'Artikel filtern' |
40 | # random_entry: Jump to a random entry from that list | ||
40 | export: 'Exportieren' | 41 | export: 'Exportieren' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'Suchbegriff hier eingeben' | 43 | input_label: 'Suchbegriff hier eingeben' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'Einstellungen' | 54 | page_title: 'Einstellungen' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'Einstellungen' | 56 | settings: 'Einstellungen' |
56 | rss: 'RSS' | 57 | feed: 'RSS' |
57 | user_info: 'Benutzerinformation' | 58 | user_info: 'Benutzerinformation' |
58 | password: 'Kennwort' | 59 | password: 'Kennwort' |
59 | rules: 'Tagging-Regeln' | 60 | rules: 'Tagging-Regeln' |
60 | new_user: 'Benutzer hinzufügen' | 61 | new_user: 'Benutzer hinzufügen' |
62 | reset: 'Zurücksetzen' | ||
61 | form: | 63 | form: |
62 | save: 'Speichern' | 64 | save: 'Speichern' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,33 @@ config: | |||
83 | help_reading_speed: "wallabag berechnet eine Lesezeit pro Artikel. Hier kannst du definieren, ob du ein schneller oder langsamer Leser bist. wallabag wird die Lesezeiten danach neu berechnen." | 85 | help_reading_speed: "wallabag berechnet eine Lesezeit pro Artikel. Hier kannst du definieren, ob du ein schneller oder langsamer Leser bist. wallabag wird die Lesezeiten danach neu berechnen." |
84 | help_language: "Du kannst die Sprache der wallabag-Oberfläche ändern." | 86 | help_language: "Du kannst die Sprache der wallabag-Oberfläche ändern." |
85 | help_pocket_consumer_key: "Nötig für den Pocket-Import. Du kannst ihn in deinem Pocket account einrichten." | 87 | help_pocket_consumer_key: "Nötig für den Pocket-Import. Du kannst ihn in deinem Pocket account einrichten." |
86 | form_rss: | 88 | form_feed: |
87 | description: 'Die RSS-Feeds von wallabag erlauben es dir, deine gespeicherten Artikel mit deinem bevorzugten RSS-Reader zu lesen. Vorher musst du jedoch einen Token erstellen.' | 89 | description: 'Die RSS-Feeds von wallabag erlauben es dir, deine gespeicherten Artikel mit deinem bevorzugten RSS-Reader zu lesen. Vorher musst du jedoch einen Token erstellen.' |
88 | token_label: 'RSS-Token' | 90 | token_label: 'RSS-Token' |
89 | no_token: 'Kein Token' | 91 | no_token: 'Kein Token' |
90 | token_create: 'Token erstellen' | 92 | token_create: 'Token erstellen' |
91 | token_reset: 'Token zurücksetzen' | 93 | token_reset: 'Token zurücksetzen' |
92 | rss_links: 'RSS-Links' | 94 | feed_links: 'RSS-Links' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'Ungelesene' | 96 | unread: 'Ungelesene' |
95 | starred: 'Favoriten' | 97 | starred: 'Favoriten' |
96 | archive: 'Archivierte' | 98 | archive: 'Archivierte' |
97 | all: 'Alle' | 99 | all: 'Alle' |
98 | rss_limit: 'Anzahl der Einträge pro Feed' | 100 | feed_limit: 'Anzahl der Einträge pro Feed' |
99 | form_user: | 101 | form_user: |
100 | two_factor_description: "Wenn du die Zwei-Faktor-Authentifizierung aktivierst, erhältst du eine E-Mail mit einem Code bei jeder nicht vertrauenswürdigen Verbindung" | 102 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'Name' | 103 | name_label: 'Name' |
102 | email_label: 'E-Mail-Adresse' | 104 | email_label: 'E-Mail-Adresse' |
103 | twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung' | 105 | two_factor: |
104 | help_twoFactorAuthentication: "Wenn du 2FA aktivierst, wirst du bei jedem Login einen Code per E-Mail bekommen." | 106 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
107 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' | ||
108 | # table_method: Method | ||
109 | # table_state: State | ||
110 | # table_action: Action | ||
111 | # state_enabled: Enabled | ||
112 | # state_disabled: Disabled | ||
113 | # action_email: Use email | ||
114 | # action_app: Use OTP App | ||
105 | delete: | 115 | delete: |
106 | title: 'Lösche mein Konto (a.k.a Gefahrenzone)' | 116 | title: 'Lösche mein Konto (a.k.a Gefahrenzone)' |
107 | description: 'Wenn du dein Konto löschst, werden ALL deine Artikel, ALL deine Tags, ALL deine Anmerkungen und dein Konto dauerhaft gelöscht (kann NICHT RÜCKGÄNGIG gemacht werden). Du wirst anschließend ausgeloggt.' | 117 | description: 'Wenn du dein Konto löschst, werden ALL deine Artikel, ALL deine Tags, ALL deine Anmerkungen und dein Konto dauerhaft gelöscht (kann NICHT RÜCKGÄNGIG gemacht werden). Du wirst anschließend ausgeloggt.' |
@@ -353,7 +363,7 @@ quickstart: | |||
353 | title: 'Anwendung konfigurieren' | 363 | title: 'Anwendung konfigurieren' |
354 | description: 'Um die Applikation für dich anzupassen, schau in die Konfiguration von wallabag.' | 364 | description: 'Um die Applikation für dich anzupassen, schau in die Konfiguration von wallabag.' |
355 | language: 'Sprache und Design ändern' | 365 | language: 'Sprache und Design ändern' |
356 | rss: 'RSS-Feeds aktivieren' | 366 | feed: 'RSS-Feeds aktivieren' |
357 | tagging_rules: 'Schreibe Regeln, um deine Beiträge automatisch zu taggen (verschlagworten)' | 367 | tagging_rules: 'Schreibe Regeln, um deine Beiträge automatisch zu taggen (verschlagworten)' |
358 | admin: | 368 | admin: |
359 | title: 'Administration' | 369 | title: 'Administration' |
@@ -404,6 +414,8 @@ tag: | |||
404 | new: | 414 | new: |
405 | add: 'Hinzufügen' | 415 | add: 'Hinzufügen' |
406 | placeholder: 'Du kannst verschiedene Tags, getrennt von einem Komma, hinzufügen.' | 416 | placeholder: 'Du kannst verschiedene Tags, getrennt von einem Komma, hinzufügen.' |
417 | rename: | ||
418 | # placeholder: 'You can update tag name.' | ||
407 | 419 | ||
408 | export: | 420 | export: |
409 | footer_template: '<div style="text-align:center;"><p>Generiert von wallabag mit Hilfe von %method%</p><p>Bitte öffne <a href="https://github.com/wallabag/wallabag/issues">ein Ticket</a> wenn du ein Problem mit der Darstellung von diesem E-Book auf deinem Gerät hast.</p></div>' | 421 | footer_template: '<div style="text-align:center;"><p>Generiert von wallabag mit Hilfe von %method%</p><p>Bitte öffne <a href="https://github.com/wallabag/wallabag/issues">ein Ticket</a> wenn du ein Problem mit der Darstellung von diesem E-Book auf deinem Gerät hast.</p></div>' |
@@ -529,7 +541,8 @@ user: | |||
529 | email_label: 'E-Mail-Adresse' | 541 | email_label: 'E-Mail-Adresse' |
530 | enabled_label: 'Aktiviert' | 542 | enabled_label: 'Aktiviert' |
531 | last_login_label: 'Letzter Login' | 543 | last_login_label: 'Letzter Login' |
532 | twofactor_label: 'Zwei-Faktor-Authentifizierung' | 544 | # twofactor_email_label: Two factor authentication by email |
545 | # twofactor_google_label: Two factor authentication by OTP app | ||
533 | save: 'Speichern' | 546 | save: 'Speichern' |
534 | delete: 'Löschen' | 547 | delete: 'Löschen' |
535 | delete_confirm: 'Bist du sicher?' | 548 | delete_confirm: 'Bist du sicher?' |
@@ -567,14 +580,14 @@ flashes: | |||
567 | password_updated: 'Kennwort aktualisiert' | 580 | password_updated: 'Kennwort aktualisiert' |
568 | password_not_updated_demo: 'Im Testmodus kannst du das Kennwort nicht ändern.' | 581 | password_not_updated_demo: 'Im Testmodus kannst du das Kennwort nicht ändern.' |
569 | user_updated: 'Information aktualisiert' | 582 | user_updated: 'Information aktualisiert' |
570 | rss_updated: 'RSS-Informationen aktualisiert' | 583 | feed_updated: 'RSS-Informationen aktualisiert' |
571 | tagging_rules_updated: 'Tagging-Regeln aktualisiert' | 584 | tagging_rules_updated: 'Tagging-Regeln aktualisiert' |
572 | tagging_rules_deleted: 'Tagging-Regel gelöscht' | 585 | tagging_rules_deleted: 'Tagging-Regel gelöscht' |
573 | rss_token_updated: 'RSS-Token aktualisiert' | 586 | feed_token_updated: 'RSS-Token aktualisiert' |
574 | annotations_reset: 'Anmerkungen zurücksetzen' | 587 | annotations_reset: Anmerkungen zurücksetzen |
575 | tags_reset: 'Tags zurücksetzen' | 588 | tags_reset: Tags zurücksetzen |
576 | entries_reset: 'Einträge zurücksetzen' | 589 | entries_reset: Einträge zurücksetzen |
577 | archived_reset: 'Archiverte Einträge zurücksetzen' | 590 | archived_reset: Archiverte Einträge zurücksetzen |
578 | entry: | 591 | entry: |
579 | notice: | 592 | notice: |
580 | entry_already_saved: 'Eintrag bereits am %date% gespeichert' | 593 | entry_already_saved: 'Eintrag bereits am %date% gespeichert' |
@@ -588,9 +601,11 @@ flashes: | |||
588 | entry_starred: 'Eintrag favorisiert' | 601 | entry_starred: 'Eintrag favorisiert' |
589 | entry_unstarred: 'Eintrag defavorisiert' | 602 | entry_unstarred: 'Eintrag defavorisiert' |
590 | entry_deleted: 'Eintrag gelöscht' | 603 | entry_deleted: 'Eintrag gelöscht' |
604 | # no_random_entry: 'No article with these criterias was found' | ||
591 | tag: | 605 | tag: |
592 | notice: | 606 | notice: |
593 | tag_added: 'Tag hinzugefügt' | 607 | tag_added: 'Tag hinzugefügt' |
608 | #tag_renamed: 'Tag renamed' | ||
594 | import: | 609 | import: |
595 | notice: | 610 | notice: |
596 | failed: 'Import fehlgeschlagen, bitte erneut probieren.' | 611 | failed: 'Import fehlgeschlagen, bitte erneut probieren.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml index 598ad58d..e2994f53 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'Add a new entry' | 37 | add_new_entry: 'Add a new entry' |
38 | search: 'Search' | 38 | search: 'Search' |
39 | filter_entries: 'Filter entries' | 39 | filter_entries: 'Filter entries' |
40 | random_entry: Jump to a random entry from that list | ||
40 | export: 'Export' | 41 | export: 'Export' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'Enter your search here' | 43 | input_label: 'Enter your search here' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'Config' | 54 | page_title: 'Config' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'Settings' | 56 | settings: 'Settings' |
56 | rss: 'RSS' | 57 | feed: 'Feeds' |
57 | user_info: 'User information' | 58 | user_info: 'User information' |
58 | password: 'Password' | 59 | password: 'Password' |
59 | rules: 'Tagging rules' | 60 | rules: 'Tagging rules' |
60 | new_user: 'Add a user' | 61 | new_user: 'Add a user' |
62 | reset: 'Reset area' | ||
61 | form: | 63 | form: |
62 | save: 'Save' | 64 | save: 'Save' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,33 @@ config: | |||
83 | help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." | 85 | help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." |
84 | help_language: "You can change the language of wallabag interface." | 86 | help_language: "You can change the language of wallabag interface." |
85 | help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." | 87 | help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." |
86 | form_rss: | 88 | form_feed: |
87 | description: 'RSS feeds provided by wallabag allow you to read your saved articles with your favourite RSS reader. You need to generate a token first.' | 89 | description: 'Atom feeds provided by wallabag allow you to read your saved articles with your favourite Atom reader. You need to generate a token first.' |
88 | token_label: 'RSS token' | 90 | token_label: 'Feed token' |
89 | no_token: 'No token' | 91 | no_token: 'No token' |
90 | token_create: 'Create your token' | 92 | token_create: 'Create your token' |
91 | token_reset: 'Regenerate your token' | 93 | token_reset: 'Regenerate your token' |
92 | rss_links: 'RSS links' | 94 | feed_links: 'Feed links' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'Unread' | 96 | unread: 'Unread' |
95 | starred: 'Starred' | 97 | starred: 'Starred' |
96 | archive: 'Archived' | 98 | archive: 'Archived' |
97 | all: 'All' | 99 | all: 'All' |
98 | rss_limit: 'Number of items in the feed' | 100 | feed_limit: 'Number of items in the feed' |
99 | form_user: | 101 | form_user: |
100 | two_factor_description: "Enabling two factor authentication means you'll receive an email with a code on every new untrusted connection." | 102 | two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'Name' | 103 | name_label: 'Name' |
102 | email_label: 'Email' | 104 | email_label: 'Email' |
103 | twoFactorAuthentication_label: 'Two factor authentication' | 105 | two_factor: |
104 | help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email." | 106 | emailTwoFactor_label: 'Using email (receive a code by email)' |
107 | googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' | ||
108 | table_method: Method | ||
109 | table_state: State | ||
110 | table_action: Action | ||
111 | state_enabled: Enabled | ||
112 | state_disabled: Disabled | ||
113 | action_email: Use email | ||
114 | action_app: Use OTP App | ||
105 | delete: | 115 | delete: |
106 | title: Delete my account (a.k.a danger zone) | 116 | title: Delete my account (a.k.a danger zone) |
107 | description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. | 117 | description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. |
@@ -159,6 +169,15 @@ config: | |||
159 | and: 'One rule AND another' | 169 | and: 'One rule AND another' |
160 | matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' | 170 | matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' |
161 | notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' | 171 | notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' |
172 | otp: | ||
173 | page_title: Two-factor authentication | ||
174 | app: | ||
175 | two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
176 | two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
177 | two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
178 | two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
179 | cancel: Cancel | ||
180 | enable: Enable | ||
162 | 181 | ||
163 | entry: | 182 | entry: |
164 | default_title: 'Title of the entry' | 183 | default_title: 'Title of the entry' |
@@ -353,7 +372,7 @@ quickstart: | |||
353 | title: 'Configure the application' | 372 | title: 'Configure the application' |
354 | description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' | 373 | description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' |
355 | language: 'Change language and design' | 374 | language: 'Change language and design' |
356 | rss: 'Enable RSS feeds' | 375 | feed: 'Enable feeds' |
357 | tagging_rules: 'Write rules to automatically tag your articles' | 376 | tagging_rules: 'Write rules to automatically tag your articles' |
358 | admin: | 377 | admin: |
359 | title: 'Administration' | 378 | title: 'Administration' |
@@ -404,6 +423,8 @@ tag: | |||
404 | new: | 423 | new: |
405 | add: 'Add' | 424 | add: 'Add' |
406 | placeholder: 'You can add several tags, separated by a comma.' | 425 | placeholder: 'You can add several tags, separated by a comma.' |
426 | rename: | ||
427 | placeholder: 'You can update tag name.' | ||
407 | 428 | ||
408 | export: | 429 | export: |
409 | footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' | 430 | footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' |
@@ -529,7 +550,8 @@ user: | |||
529 | email_label: 'Email' | 550 | email_label: 'Email' |
530 | enabled_label: 'Enabled' | 551 | enabled_label: 'Enabled' |
531 | last_login_label: 'Last login' | 552 | last_login_label: 'Last login' |
532 | twofactor_label: Two factor authentication | 553 | twofactor_email_label: Two factor authentication by email |
554 | twofactor_google_label: Two factor authentication by OTP app | ||
533 | save: Save | 555 | save: Save |
534 | delete: Delete | 556 | delete: Delete |
535 | delete_confirm: Are you sure? | 557 | delete_confirm: Are you sure? |
@@ -567,14 +589,15 @@ flashes: | |||
567 | password_updated: 'Password updated' | 589 | password_updated: 'Password updated' |
568 | password_not_updated_demo: "In demonstration mode, you can't change password for this user." | 590 | password_not_updated_demo: "In demonstration mode, you can't change password for this user." |
569 | user_updated: 'Information updated' | 591 | user_updated: 'Information updated' |
570 | rss_updated: 'RSS information updated' | 592 | feed_updated: 'Feed information updated' |
571 | tagging_rules_updated: 'Tagging rules updated' | 593 | tagging_rules_updated: 'Tagging rules updated' |
572 | tagging_rules_deleted: 'Tagging rule deleted' | 594 | tagging_rules_deleted: 'Tagging rule deleted' |
573 | rss_token_updated: 'RSS token updated' | 595 | feed_token_updated: 'Feed token updated' |
574 | annotations_reset: Annotations reset | 596 | annotations_reset: Annotations reset |
575 | tags_reset: Tags reset | 597 | tags_reset: Tags reset |
576 | entries_reset: Entries reset | 598 | entries_reset: Entries reset |
577 | archived_reset: Archived entries deleted | 599 | archived_reset: Archived entries deleted |
600 | otp_enabled: Two-factor authentication enabled | ||
578 | entry: | 601 | entry: |
579 | notice: | 602 | notice: |
580 | entry_already_saved: 'Entry already saved on %date%' | 603 | entry_already_saved: 'Entry already saved on %date%' |
@@ -588,9 +611,11 @@ flashes: | |||
588 | entry_starred: 'Entry starred' | 611 | entry_starred: 'Entry starred' |
589 | entry_unstarred: 'Entry unstarred' | 612 | entry_unstarred: 'Entry unstarred' |
590 | entry_deleted: 'Entry deleted' | 613 | entry_deleted: 'Entry deleted' |
614 | no_random_entry: 'No article with these criterias was found' | ||
591 | tag: | 615 | tag: |
592 | notice: | 616 | notice: |
593 | tag_added: 'Tag added' | 617 | tag_added: 'Tag added' |
618 | tag_renamed: 'Tag renamed' | ||
594 | import: | 619 | import: |
595 | notice: | 620 | notice: |
596 | failed: 'Import failed, please try again.' | 621 | failed: 'Import failed, please try again.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml index f8aa4109..d1ccfc81 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'Añadir un nuevo artículo' | 37 | add_new_entry: 'Añadir un nuevo artículo' |
38 | search: 'Buscar' | 38 | search: 'Buscar' |
39 | filter_entries: 'Filtrar los artículos' | 39 | filter_entries: 'Filtrar los artículos' |
40 | # random_entry: Jump to a random entry from that list | ||
40 | export: 'Exportar' | 41 | export: 'Exportar' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'Introduzca su búsqueda aquí' | 43 | input_label: 'Introduzca su búsqueda aquí' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'Configuración' | 54 | page_title: 'Configuración' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'Configuración' | 56 | settings: 'Configuración' |
56 | rss: 'RSS' | 57 | feed: 'RSS' |
57 | user_info: 'Información de usuario' | 58 | user_info: 'Información de usuario' |
58 | password: 'Contraseña' | 59 | password: 'Contraseña' |
59 | rules: 'Reglas de etiquetado automáticas' | 60 | rules: 'Reglas de etiquetado automáticas' |
60 | new_user: 'Añadir un usuario' | 61 | new_user: 'Añadir un usuario' |
62 | reset: 'Reiniciar mi cuenta' | ||
61 | form: | 63 | form: |
62 | save: 'Guardar' | 64 | save: 'Guardar' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,33 @@ config: | |||
83 | help_reading_speed: "wallabag calcula un tiempo de lectura para cada artículo. Puedes definir aquí, gracias a esta lista, si eres un lector rápido o lento. wallabag recalculará el tiempo de lectura para cada artículo." | 85 | help_reading_speed: "wallabag calcula un tiempo de lectura para cada artículo. Puedes definir aquí, gracias a esta lista, si eres un lector rápido o lento. wallabag recalculará el tiempo de lectura para cada artículo." |
84 | help_language: "Puedes cambiar el idioma de la interfaz de wallabag." | 86 | help_language: "Puedes cambiar el idioma de la interfaz de wallabag." |
85 | help_pocket_consumer_key: "Requerido para la importación desde Pocket. Puedes crearla en tu cuenta de Pocket." | 87 | help_pocket_consumer_key: "Requerido para la importación desde Pocket. Puedes crearla en tu cuenta de Pocket." |
86 | form_rss: | 88 | form_feed: |
87 | description: 'Los feeds RSS de wallabag permiten leer los artículos guardados con su lector RSS favorito. Primero necesitas generar un token.' | 89 | description: 'Los feeds RSS de wallabag permiten leer los artículos guardados con su lector RSS favorito. Primero necesitas generar un token.' |
88 | token_label: 'Token RSS' | 90 | token_label: 'Token RSS' |
89 | no_token: 'Sin token' | 91 | no_token: 'Sin token' |
90 | token_create: 'Crear token' | 92 | token_create: 'Crear token' |
91 | token_reset: 'Reiniciar token' | 93 | token_reset: 'Reiniciar token' |
92 | rss_links: 'URLs de feeds RSS' | 94 | feed_links: 'URLs de feeds RSS' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'sin leer' | 96 | unread: 'sin leer' |
95 | starred: 'favoritos' | 97 | starred: 'favoritos' |
96 | archive: 'archivados' | 98 | archive: 'archivados' |
97 | # all: 'All' | 99 | # all: 'All' |
98 | rss_limit: 'Límite de artículos en feed RSS' | 100 | feed_limit: 'Límite de artículos en feed RSS' |
99 | form_user: | 101 | form_user: |
100 | two_factor_description: "Con la autenticación en dos pasos recibirá código por e-mail en cada nueva conexión que no sea de confianza." | 102 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'Nombre' | 103 | name_label: 'Nombre' |
102 | email_label: 'Dirección de e-mail' | 104 | email_label: 'Dirección de e-mail' |
103 | twoFactorAuthentication_label: 'Autenticación en dos pasos' | 105 | two_factor: |
104 | help_twoFactorAuthentication: "Si activas la autenticación en dos pasos, cada vez que quieras iniciar sesión en wallabag recibirás un código por e-mail." | 106 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
107 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' | ||
108 | # table_method: Method | ||
109 | # table_state: State | ||
110 | # table_action: Action | ||
111 | # state_enabled: Enabled | ||
112 | # state_disabled: Disabled | ||
113 | # action_email: Use email | ||
114 | # action_app: Use OTP App | ||
105 | delete: | 115 | delete: |
106 | title: Eliminar mi cuenta (Zona peligrosa) | 116 | title: Eliminar mi cuenta (Zona peligrosa) |
107 | description: Si eliminas tu cuenta, TODOS tus artículos, TODAS tus etiquetas, TODAS tus anotaciones y tu cuenta serán eliminadas de forma PERMANENTE (no se puede deshacer). Después serás desconectado. | 117 | description: Si eliminas tu cuenta, TODOS tus artículos, TODAS tus etiquetas, TODAS tus anotaciones y tu cuenta serán eliminadas de forma PERMANENTE (no se puede deshacer). Después serás desconectado. |
@@ -159,6 +169,15 @@ config: | |||
159 | and: 'Una regla Y la otra' | 169 | and: 'Una regla Y la otra' |
160 | 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>' | 170 | 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>' |
161 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' | 171 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' |
172 | otp: | ||
173 | # page_title: Two-factor authentication | ||
174 | # app: | ||
175 | # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
176 | # two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
177 | # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
178 | # two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
179 | # cancel: Cancel | ||
180 | # enable: Enable | ||
162 | 181 | ||
163 | entry: | 182 | entry: |
164 | default_title: 'Título del artículo' | 183 | default_title: 'Título del artículo' |
@@ -353,7 +372,7 @@ quickstart: | |||
353 | title: 'Configure la aplicación' | 372 | title: 'Configure la aplicación' |
354 | description: 'Para que la aplicación se ajuste a tus necesidades, echa un vistazo a la configuración de wallabag.' | 373 | description: 'Para que la aplicación se ajuste a tus necesidades, echa un vistazo a la configuración de wallabag.' |
355 | language: 'Cambie el idioma y el diseño' | 374 | language: 'Cambie el idioma y el diseño' |
356 | rss: 'Activar los feeds RSS' | 375 | feed: 'Activar los feeds RSS' |
357 | tagging_rules: 'Escribe reglas para etiquetar automáticamente tus artículos' | 376 | tagging_rules: 'Escribe reglas para etiquetar automáticamente tus artículos' |
358 | admin: | 377 | admin: |
359 | title: 'Administración' | 378 | title: 'Administración' |
@@ -404,6 +423,8 @@ tag: | |||
404 | new: | 423 | new: |
405 | add: 'Añadir' | 424 | add: 'Añadir' |
406 | placeholder: 'Puedes añadir varias etiquetas, separadas por una coma.' | 425 | placeholder: 'Puedes añadir varias etiquetas, separadas por una coma.' |
426 | rename: | ||
427 | # placeholder: 'You can update tag name.' | ||
407 | 428 | ||
408 | # export: | 429 | # export: |
409 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' | 430 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' |
@@ -529,7 +550,8 @@ user: | |||
529 | email_label: 'E-mail' | 550 | email_label: 'E-mail' |
530 | enabled_label: 'Activado' | 551 | enabled_label: 'Activado' |
531 | last_login_label: 'Último inicio de sesión' | 552 | last_login_label: 'Último inicio de sesión' |
532 | twofactor_label: Autenticación en dos pasos | 553 | # twofactor_email_label: Two factor authentication by email |
554 | # twofactor_google_label: Two factor authentication by OTP app | ||
533 | save: Guardar | 555 | save: Guardar |
534 | delete: Eliminar | 556 | delete: Eliminar |
535 | delete_confirm: ¿Estás seguro? | 557 | delete_confirm: ¿Estás seguro? |
@@ -567,10 +589,10 @@ flashes: | |||
567 | password_updated: 'Contraseña actualizada' | 589 | password_updated: 'Contraseña actualizada' |
568 | password_not_updated_demo: "En el modo demo, no puede cambiar la contraseña del usuario." | 590 | password_not_updated_demo: "En el modo demo, no puede cambiar la contraseña del usuario." |
569 | user_updated: 'Información actualizada' | 591 | user_updated: 'Información actualizada' |
570 | rss_updated: 'Configuración RSS actualizada' | 592 | feed_updated: 'Configuración RSS actualizada' |
571 | tagging_rules_updated: 'Regla de etiquetado actualizada' | 593 | tagging_rules_updated: 'Regla de etiquetado actualizada' |
572 | tagging_rules_deleted: 'Regla de etiquetado eliminada' | 594 | tagging_rules_deleted: 'Regla de etiquetado eliminada' |
573 | rss_token_updated: 'Token RSS actualizado' | 595 | feed_token_updated: 'Token RSS actualizado' |
574 | annotations_reset: Anotaciones reiniciadas | 596 | annotations_reset: Anotaciones reiniciadas |
575 | tags_reset: Etiquetas reiniciadas | 597 | tags_reset: Etiquetas reiniciadas |
576 | entries_reset: Artículos reiniciados | 598 | entries_reset: Artículos reiniciados |
@@ -588,9 +610,11 @@ flashes: | |||
588 | entry_starred: 'Artículo marcado como favorito' | 610 | entry_starred: 'Artículo marcado como favorito' |
589 | entry_unstarred: 'Artículo desmarcado como favorito' | 611 | entry_unstarred: 'Artículo desmarcado como favorito' |
590 | entry_deleted: 'Artículo eliminado' | 612 | entry_deleted: 'Artículo eliminado' |
613 | # no_random_entry: 'No article with these criterias was found' | ||
591 | tag: | 614 | tag: |
592 | notice: | 615 | notice: |
593 | tag_added: 'Etiqueta añadida' | 616 | tag_added: 'Etiqueta añadida' |
617 | # tag_renamed: 'Tag renamed' | ||
594 | import: | 618 | import: |
595 | notice: | 619 | notice: |
596 | failed: 'Importación fallida, por favor, inténtelo de nuevo.' | 620 | failed: 'Importación fallida, por favor, inténtelo de nuevo.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml index 785e39ee..e5d36bd3 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'افزودن مقالهٔ تازه' | 37 | add_new_entry: 'افزودن مقالهٔ تازه' |
38 | search: 'جستجو' | 38 | search: 'جستجو' |
39 | filter_entries: 'فیلترکردن مقالهها' | 39 | filter_entries: 'فیلترکردن مقالهها' |
40 | # random_entry: Jump to a random entry from that list | ||
40 | export: 'برونبری' | 41 | export: 'برونبری' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'جستجوی خود را اینجا بنویسید:' | 43 | input_label: 'جستجوی خود را اینجا بنویسید:' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'پیکربندی' | 54 | page_title: 'پیکربندی' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'تنظیمات' | 56 | settings: 'تنظیمات' |
56 | rss: 'آر-اس-اس' | 57 | feed: 'آر-اس-اس' |
57 | user_info: 'اطلاعات کاربر' | 58 | user_info: 'اطلاعات کاربر' |
58 | password: 'رمز' | 59 | password: 'رمز' |
59 | rules: 'برچسبگذاری خودکار' | 60 | rules: 'برچسبگذاری خودکار' |
60 | new_user: 'افزودن کاربر' | 61 | new_user: 'افزودن کاربر' |
62 | # reset: 'Reset area' | ||
61 | form: | 63 | form: |
62 | save: 'ذخیره' | 64 | save: 'ذخیره' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,33 @@ config: | |||
83 | # help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." | 85 | # help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." |
84 | # help_language: "You can change the language of wallabag interface." | 86 | # help_language: "You can change the language of wallabag interface." |
85 | # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." | 87 | # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." |
86 | form_rss: | 88 | form_feed: |
87 | description: 'با خوراک آر-اس-اس که wallabag در اختیارتان میگذارد، میتوانید مقالههای ذخیرهشده را در نرمافزار آر-اس-اس دلخواه خود بخوانید. برای این کار نخست باید یک کد بسازید.' | 89 | description: 'با خوراک آر-اس-اس که wallabag در اختیارتان میگذارد، میتوانید مقالههای ذخیرهشده را در نرمافزار آر-اس-اس دلخواه خود بخوانید. برای این کار نخست باید یک کد بسازید.' |
88 | token_label: 'کد آر-اس-اس' | 90 | token_label: 'کد آر-اس-اس' |
89 | no_token: 'بدون کد' | 91 | no_token: 'بدون کد' |
90 | token_create: 'کد خود را بسازید' | 92 | token_create: 'کد خود را بسازید' |
91 | token_reset: 'بازنشانی کد' | 93 | token_reset: 'بازنشانی کد' |
92 | rss_links: 'پیوند آر-اس-اس' | 94 | feed_links: 'پیوند آر-اس-اس' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'خواندهنشده' | 96 | unread: 'خواندهنشده' |
95 | starred: 'برگزیده' | 97 | starred: 'برگزیده' |
96 | archive: 'بایگانی' | 98 | archive: 'بایگانی' |
97 | # all: 'All' | 99 | # all: 'All' |
98 | rss_limit: 'محدودیت آر-اس-اس' | 100 | feed_limit: 'محدودیت آر-اس-اس' |
99 | form_user: | 101 | form_user: |
100 | two_factor_description: "با فعالکردن تأیید ۲مرحلهای هر بار که اتصال تأییدنشدهای برقرار شد، به شما یک کد از راه ایمیل فرستاده میشود" | 102 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'نام' | 103 | name_label: 'نام' |
102 | email_label: 'نشانی ایمیل' | 104 | email_label: 'نشانی ایمیل' |
103 | twoFactorAuthentication_label: 'تأیید ۲مرحلهای' | 105 | two_factor: |
104 | # help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email." | 106 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
107 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' | ||
108 | # table_method: Method | ||
109 | # table_state: State | ||
110 | # table_action: Action | ||
111 | # state_enabled: Enabled | ||
112 | # state_disabled: Disabled | ||
113 | # action_email: Use email | ||
114 | # action_app: Use OTP App | ||
105 | delete: | 115 | delete: |
106 | # title: Delete my account (a.k.a danger zone) | 116 | # title: Delete my account (a.k.a danger zone) |
107 | # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. | 117 | # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. |
@@ -159,6 +169,15 @@ config: | |||
159 | # and: 'One rule AND another' | 169 | # and: 'One rule AND another' |
160 | # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' | 170 | # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' |
161 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' | 171 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' |
172 | otp: | ||
173 | # page_title: Two-factor authentication | ||
174 | # app: | ||
175 | # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
176 | # two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
177 | # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
178 | # two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
179 | # cancel: Cancel | ||
180 | # enable: Enable | ||
162 | 181 | ||
163 | entry: | 182 | entry: |
164 | # default_title: 'Title of the entry' | 183 | # default_title: 'Title of the entry' |
@@ -353,7 +372,7 @@ quickstart: | |||
353 | title: 'برنامه را تنظیم کنید' | 372 | title: 'برنامه را تنظیم کنید' |
354 | # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' | 373 | # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' |
355 | language: 'زبان و نمای برنامه را تغییر دهید' | 374 | language: 'زبان و نمای برنامه را تغییر دهید' |
356 | rss: 'خوراک آر-اس-اس را فعال کنید' | 375 | feed: 'خوراک آر-اس-اس را فعال کنید' |
357 | tagging_rules: 'قانونهای برچسبگذاری خودکار مقالههایتان را تعریف کنید' | 376 | tagging_rules: 'قانونهای برچسبگذاری خودکار مقالههایتان را تعریف کنید' |
358 | admin: | 377 | admin: |
359 | title: 'مدیریت' | 378 | title: 'مدیریت' |
@@ -404,6 +423,8 @@ tag: | |||
404 | new: | 423 | new: |
405 | # add: 'Add' | 424 | # add: 'Add' |
406 | # placeholder: 'You can add several tags, separated by a comma.' | 425 | # placeholder: 'You can add several tags, separated by a comma.' |
426 | rename: | ||
427 | # placeholder: 'You can update tag name.' | ||
407 | 428 | ||
408 | # export: | 429 | # export: |
409 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' | 430 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' |
@@ -529,7 +550,8 @@ user: | |||
529 | email_label: 'نشانی ایمیل' | 550 | email_label: 'نشانی ایمیل' |
530 | # enabled_label: 'Enabled' | 551 | # enabled_label: 'Enabled' |
531 | # last_login_label: 'Last login' | 552 | # last_login_label: 'Last login' |
532 | # twofactor_label: Two factor authentication | 553 | # twofactor_email_label: Two factor authentication by email |
554 | # twofactor_google_label: Two factor authentication by OTP app | ||
533 | # save: Save | 555 | # save: Save |
534 | # delete: Delete | 556 | # delete: Delete |
535 | # delete_confirm: Are you sure? | 557 | # delete_confirm: Are you sure? |
@@ -567,10 +589,10 @@ flashes: | |||
567 | password_updated: 'رمز بهروز شد' | 589 | password_updated: 'رمز بهروز شد' |
568 | password_not_updated_demo: "در حالت نمایشی نمیتوانید رمز کاربر را عوض کنید." | 590 | password_not_updated_demo: "در حالت نمایشی نمیتوانید رمز کاربر را عوض کنید." |
569 | user_updated: 'اطلاعات بهروز شد' | 591 | user_updated: 'اطلاعات بهروز شد' |
570 | rss_updated: 'اطلاعات آر-اس-اس بهروز شد' | 592 | feed_updated: 'اطلاعات آر-اس-اس بهروز شد' |
571 | tagging_rules_updated: 'برچسبگذاری خودکار بهروز شد' | 593 | tagging_rules_updated: 'برچسبگذاری خودکار بهروز شد' |
572 | tagging_rules_deleted: 'قانون برچسبگذاری پاک شد' | 594 | tagging_rules_deleted: 'قانون برچسبگذاری پاک شد' |
573 | rss_token_updated: 'کد آر-اس-اس بهروز شد' | 595 | feed_token_updated: 'کد آر-اس-اس بهروز شد' |
574 | # annotations_reset: Annotations reset | 596 | # annotations_reset: Annotations reset |
575 | # tags_reset: Tags reset | 597 | # tags_reset: Tags reset |
576 | # entries_reset: Entries reset | 598 | # entries_reset: Entries reset |
@@ -588,9 +610,11 @@ flashes: | |||
588 | entry_starred: 'مقاله برگزیده شد' | 610 | entry_starred: 'مقاله برگزیده شد' |
589 | entry_unstarred: 'مقاله نابرگزیده شد' | 611 | entry_unstarred: 'مقاله نابرگزیده شد' |
590 | entry_deleted: 'مقاله پاک شد' | 612 | entry_deleted: 'مقاله پاک شد' |
613 | # no_random_entry: 'No article with these criterias was found' | ||
591 | tag: | 614 | tag: |
592 | notice: | 615 | notice: |
593 | tag_added: 'برچسب افزوده شد' | 616 | tag_added: 'برچسب افزوده شد' |
617 | # tag_renamed: 'Tag renamed' | ||
594 | import: | 618 | import: |
595 | notice: | 619 | notice: |
596 | failed: 'درونریزی شکست خورد. لطفاً دوباره تلاش کنید.' | 620 | failed: 'درونریزی شکست خورد. لطفاً دوباره تلاش کنید.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml index b2fa1c50..0b1853a4 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: "Sauvegarder un nouvel article" | 37 | add_new_entry: "Sauvegarder un nouvel article" |
38 | search: "Rechercher" | 38 | search: "Rechercher" |
39 | filter_entries: "Filtrer les articles" | 39 | filter_entries: "Filtrer les articles" |
40 | random_entry: Aller à un article aléatoire de cette liste | ||
40 | export: "Exporter" | 41 | export: "Exporter" |
41 | search_form: | 42 | search_form: |
42 | input_label: "Saisissez votre terme de recherche" | 43 | input_label: "Saisissez votre terme de recherche" |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: "Configuration" | 54 | page_title: "Configuration" |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: "Paramètres" | 56 | settings: "Paramètres" |
56 | rss: "RSS" | 57 | feed: "Flux" |
57 | user_info: "Mon compte" | 58 | user_info: "Mon compte" |
58 | password: "Mot de passe" | 59 | password: "Mot de passe" |
59 | rules: "Règles de tag automatiques" | 60 | rules: "Règles de tag automatiques" |
60 | new_user: "Créer un compte" | 61 | new_user: "Créer un compte" |
62 | reset: "Réinitialisation" | ||
61 | form: | 63 | form: |
62 | save: "Enregistrer" | 64 | save: "Enregistrer" |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,33 @@ config: | |||
83 | 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." | 85 | 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." |
84 | help_language: "Vous pouvez définir la langue de l’interface de wallabag." | 86 | help_language: "Vous pouvez définir la langue de l’interface de wallabag." |
85 | help_pocket_consumer_key: "Nécessaire pour l’import depuis Pocket. Vous pouvez le créer depuis votre compte Pocket." | 87 | help_pocket_consumer_key: "Nécessaire pour l’import depuis Pocket. Vous pouvez le créer depuis votre compte Pocket." |
86 | form_rss: | 88 | form_feed: |
87 | 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." | 89 | description: "Les flux Atom 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." |
88 | token_label: "Jeton RSS" | 90 | token_label: "Jeton de flux" |
89 | no_token: "Aucun jeton généré" | 91 | no_token: "Aucun jeton généré" |
90 | token_create: "Créez votre jeton" | 92 | token_create: "Créez votre jeton" |
91 | token_reset: "Réinitialisez votre jeton" | 93 | token_reset: "Réinitialisez votre jeton" |
92 | rss_links: "Adresses de vos flux RSS" | 94 | feed_links: "Adresses de vos flux" |
93 | rss_link: | 95 | feed_link: |
94 | unread: "Non lus" | 96 | unread: "Non lus" |
95 | starred: "Favoris" | 97 | starred: "Favoris" |
96 | archive: "Lus" | 98 | archive: "Lus" |
97 | all: "Tous" | 99 | all: "Tous" |
98 | rss_limit: "Nombre d’articles dans le flux" | 100 | feed_limit: "Nombre d’articles dans le flux" |
99 | form_user: | 101 | form_user: |
100 | two_factor_description: "Activer l’authentification double-facteur veut dire que vous allez recevoir un code par courriel à chaque nouvelle connexion non approuvée." | 102 | two_factor_description: "Activer l’authentification double-facteur veut dire que vous allez recevoir un code par courriel OU que vous devriez utiliser une application de mot de passe à usage unique (comme Google Authenticator, Authy or FreeOTP) pour obtenir un code temporaire à chaque nouvelle connexion non approuvée. Vous ne pouvez pas choisir les deux options." |
101 | name_label: "Nom" | 103 | name_label: "Nom" |
102 | email_label: "Adresse courriel" | 104 | email_label: "Adresse courriel" |
103 | twoFactorAuthentication_label: "Double authentification" | 105 | two_factor: |
104 | help_twoFactorAuthentication: "Si vous activez 2FA, à chaque tentative de connexion à wallabag, vous recevrez un code par email." | 106 | emailTwoFactor_label: 'En utlisant l’email (recevez un code par email)' |
107 | googleTwoFactor_label: 'En utilisant une application de mot de passe à usage unique (ouvrez l’app, comme Google Authenticator, Authy or FreeOTP, pour obtenir un mot de passe à usage unique)' | ||
108 | table_method: Méthode | ||
109 | table_state: État | ||
110 | table_action: Action | ||
111 | state_enabled: Activé | ||
112 | state_disabled: Désactivé | ||
113 | action_email: Utiliser l'email | ||
114 | action_app: Utiliser une app OTP | ||
105 | delete: | 115 | delete: |
106 | title: "Supprimer mon compte (attention danger !)" | 116 | title: "Supprimer mon compte (attention danger !)" |
107 | 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é." | 117 | 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é." |
@@ -159,6 +169,15 @@ config: | |||
159 | and: "Une règle ET l’autre" | 169 | and: "Une règle ET l’autre" |
160 | matches: "Teste si un <i>sujet</i> correspond à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title matches \"football\"</code>" | 170 | matches: "Teste si un <i>sujet</i> correspond à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title matches \"football\"</code>" |
161 | 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>" | 171 | 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>" |
172 | otp: | ||
173 | page_title: Authentification double-facteur | ||
174 | app: | ||
175 | two_factor_code_description_1: Vous venez d’activer l’authentification double-facteur, ouvrez votre application OTP pour configurer la génération du mot de passe à usage unique. Ces informations disparaîtront après un rechargement de la page. | ||
176 | two_factor_code_description_2: 'Vous pouvez scanner le QR code avec votre application :' | ||
177 | two_factor_code_description_3: 'N’oubliez pas de sauvegarder ces codes de secours dans un endroit sûr, vous pourrez les utiliser si vous ne pouvez plus accéder à votre application OTP :' | ||
178 | two_factor_code_description_4: 'Testez un code généré par votre application OTP :' | ||
179 | cancel: Annuler | ||
180 | enable: Activer | ||
162 | 181 | ||
163 | entry: | 182 | entry: |
164 | default_title: "Titre de l’article" | 183 | default_title: "Titre de l’article" |
@@ -353,7 +372,7 @@ quickstart: | |||
353 | title: "Configurez l’application" | 372 | title: "Configurez l’application" |
354 | description: "Pour voir une application qui vous correspond, allez voir du côté de la configuration de wallabag." | 373 | description: "Pour voir une application qui vous correspond, allez voir du côté de la configuration de wallabag." |
355 | language: "Changez la langue et le design de l’application" | 374 | language: "Changez la langue et le design de l’application" |
356 | rss: "Activez les flux RSS" | 375 | feed: "Activez les flux Atom" |
357 | tagging_rules: "Écrivez des règles pour classer automatiquement vos articles" | 376 | tagging_rules: "Écrivez des règles pour classer automatiquement vos articles" |
358 | admin: | 377 | admin: |
359 | title: "Administration" | 378 | title: "Administration" |
@@ -404,6 +423,8 @@ tag: | |||
404 | new: | 423 | new: |
405 | add: "Ajouter" | 424 | add: "Ajouter" |
406 | placeholder: "Vous pouvez ajouter plusieurs tags, séparés par une virgule." | 425 | placeholder: "Vous pouvez ajouter plusieurs tags, séparés par une virgule." |
426 | rename: | ||
427 | placeholder: 'Vous pouvez changer le nom de votre tag.' | ||
407 | 428 | ||
408 | export: | 429 | export: |
409 | footer_template: '<div style="text-align:center;"><p>Généré par wallabag with %method%</p><p>Merci d''ouvrir <a href="https://github.com/wallabag/wallabag/issues">un ticket</a> si vous rencontrez des soucis d''affichage avec ce document sur votre support.</p></div>' | 430 | footer_template: '<div style="text-align:center;"><p>Généré par wallabag with %method%</p><p>Merci d''ouvrir <a href="https://github.com/wallabag/wallabag/issues">un ticket</a> si vous rencontrez des soucis d''affichage avec ce document sur votre support.</p></div>' |
@@ -530,6 +551,8 @@ user: | |||
530 | enabled_label: "Activé" | 551 | enabled_label: "Activé" |
531 | last_login_label: "Dernière connexion" | 552 | last_login_label: "Dernière connexion" |
532 | twofactor_label: "Double authentification" | 553 | twofactor_label: "Double authentification" |
554 | twofactor_email_label: Double authentification par email | ||
555 | twofactor_google_label: Double authentification par OTP app | ||
533 | save: "Sauvegarder" | 556 | save: "Sauvegarder" |
534 | delete: "Supprimer" | 557 | delete: "Supprimer" |
535 | delete_confirm: "Êtes-vous sûr ?" | 558 | delete_confirm: "Êtes-vous sûr ?" |
@@ -567,14 +590,15 @@ flashes: | |||
567 | password_updated: "Votre mot de passe a bien été mis à jour" | 590 | password_updated: "Votre mot de passe a bien été mis à jour" |
568 | password_not_updated_demo: "En démo, vous ne pouvez pas changer le mot de passe de cet utilisateur." | 591 | password_not_updated_demo: "En démo, vous ne pouvez pas changer le mot de passe de cet utilisateur." |
569 | user_updated: "Vos informations personnelles ont bien été mises à jour" | 592 | user_updated: "Vos informations personnelles ont bien été mises à jour" |
570 | rss_updated: "La configuration des flux RSS a bien été mise à jour" | 593 | feed_updated: "La configuration des flux a bien été mise à jour" |
571 | tagging_rules_updated: "Règles mises à jour" | 594 | tagging_rules_updated: "Règles mises à jour" |
572 | tagging_rules_deleted: "Règle supprimée" | 595 | tagging_rules_deleted: "Règle supprimée" |
573 | rss_token_updated: "Jeton RSS mis à jour" | 596 | feed_token_updated: "Jeton des flux mis à jour" |
574 | annotations_reset: "Annotations supprimées" | 597 | annotations_reset: "Annotations supprimées" |
575 | tags_reset: "Tags supprimés" | 598 | tags_reset: "Tags supprimés" |
576 | entries_reset: "Articles supprimés" | 599 | entries_reset: "Articles supprimés" |
577 | archived_reset: "Articles archivés supprimés" | 600 | archived_reset: "Articles archivés supprimés" |
601 | otp_enabled: "Authentification à double-facteur activée" | ||
578 | entry: | 602 | entry: |
579 | notice: | 603 | notice: |
580 | entry_already_saved: "Article déjà sauvegardé le %date%" | 604 | entry_already_saved: "Article déjà sauvegardé le %date%" |
@@ -588,9 +612,11 @@ flashes: | |||
588 | entry_starred: "Article ajouté dans les favoris" | 612 | entry_starred: "Article ajouté dans les favoris" |
589 | entry_unstarred: "Article retiré des favoris" | 613 | entry_unstarred: "Article retiré des favoris" |
590 | entry_deleted: "Article supprimé" | 614 | entry_deleted: "Article supprimé" |
615 | no_random_entry: "Aucun article correspond aux critères n'a été trouvé" | ||
591 | tag: | 616 | tag: |
592 | notice: | 617 | notice: |
593 | tag_added: "Tag ajouté" | 618 | tag_added: "Tag ajouté" |
619 | tag_renamed: "Tag renommé" | ||
594 | import: | 620 | import: |
595 | notice: | 621 | notice: |
596 | failed: "L’import a échoué, veuillez ré-essayer" | 622 | failed: "L’import a échoué, veuillez ré-essayer" |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml index ecaa3b60..0474d2bc 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'Aggiungi un nuovo contenuto' | 37 | add_new_entry: 'Aggiungi un nuovo contenuto' |
38 | search: 'Cerca' | 38 | search: 'Cerca' |
39 | filter_entries: 'Filtra contenuti' | 39 | filter_entries: 'Filtra contenuti' |
40 | # random_entry: Jump to a random entry from that list | ||
40 | export: 'Esporta' | 41 | export: 'Esporta' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'Inserisci qui la tua ricerca' | 43 | input_label: 'Inserisci qui la tua ricerca' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'Configurazione' | 54 | page_title: 'Configurazione' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'Impostazioni' | 56 | settings: 'Impostazioni' |
56 | rss: 'RSS' | 57 | feed: 'RSS' |
57 | user_info: 'Informazioni utente' | 58 | user_info: 'Informazioni utente' |
58 | password: 'Password' | 59 | password: 'Password' |
59 | rules: 'Regole di etichettatura' | 60 | rules: 'Regole di etichettatura' |
60 | new_user: 'Aggiungi utente' | 61 | new_user: 'Aggiungi utente' |
62 | reset: 'Area di reset' | ||
61 | form: | 63 | form: |
62 | save: 'Salva' | 64 | save: 'Salva' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,32 @@ config: | |||
83 | help_reading_speed: "wallabag calcola un tempo di lettura per ogni articolo. Puoi definire qui, grazie a questa lista, se sei un lettore lento o veloce. wallabag ricalcolerà la velocità di lettura per ogni articolo." | 85 | help_reading_speed: "wallabag calcola un tempo di lettura per ogni articolo. Puoi definire qui, grazie a questa lista, se sei un lettore lento o veloce. wallabag ricalcolerà la velocità di lettura per ogni articolo." |
84 | help_language: "Puoi cambiare la lingua dell'interfaccia di wallabag." | 86 | help_language: "Puoi cambiare la lingua dell'interfaccia di wallabag." |
85 | help_pocket_consumer_key: "Richiesta per importare da Pocket. La puoi creare nel tuo account Pocket." | 87 | help_pocket_consumer_key: "Richiesta per importare da Pocket. La puoi creare nel tuo account Pocket." |
86 | form_rss: | 88 | form_feed: |
87 | description: 'I feed RSS generati da wallabag ti permettono di leggere i tuoi contenuti salvati con il tuo lettore di RSS preferito. Prima, devi generare un token.' | 89 | description: 'I feed RSS generati da wallabag ti permettono di leggere i tuoi contenuti salvati con il tuo lettore di RSS preferito. Prima, devi generare un token.' |
88 | token_label: 'Token RSS' | 90 | token_label: 'Token RSS' |
89 | no_token: 'Nessun token' | 91 | no_token: 'Nessun token' |
90 | token_create: 'Crea il tuo token' | 92 | token_create: 'Crea il tuo token' |
91 | token_reset: 'Rigenera il tuo token' | 93 | token_reset: 'Rigenera il tuo token' |
92 | rss_links: 'Collegamenti RSS' | 94 | feed_links: 'Collegamenti RSS' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'Non letti' | 96 | unread: 'Non letti' |
95 | starred: 'Preferiti' | 97 | starred: 'Preferiti' |
96 | archive: 'Archiviati' | 98 | archive: 'Archiviati' |
97 | # all: 'All' | 99 | # all: 'All' |
98 | rss_limit: 'Numero di elementi nel feed' | 100 | feed_limit: 'Numero di elementi nel feed' |
99 | form_user: | 101 | form_user: |
100 | two_factor_description: "Abilitando l'autenticazione a due fattori riceverai una e-mail con un codice per ogni nuova connesione non verificata" | 102 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'Nome' | 103 | name_label: 'Nome' |
102 | email_label: 'E-mail' | 104 | email_label: 'E-mail' |
103 | twoFactorAuthentication_label: 'Autenticazione a due fattori' | 105 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
104 | help_twoFactorAuthentication: "Se abiliti l'autenticazione a due fattori, ogni volta che vorrai connetterti a wallabag, riceverai un codice via E-mail." | 106 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' |
107 | # table_method: Method | ||
108 | # table_state: State | ||
109 | # table_action: Action | ||
110 | # state_enabled: Enabled | ||
111 | # state_disabled: Disabled | ||
112 | # action_email: Use email | ||
113 | # action_app: Use OTP App | ||
105 | delete: | 114 | delete: |
106 | title: Cancella il mio account (zona pericolosa) | 115 | title: Cancella il mio account (zona pericolosa) |
107 | description: Rimuovendo il tuo account, TUTTI i tuoi articoli, TUTTE le tue etichette, TUTTE le tue annotazioni ed il tuo account verranno rimossi PERMANENTEMENTE (impossibile da ANNULLARE). Verrai poi disconnesso. | 116 | description: Rimuovendo il tuo account, TUTTI i tuoi articoli, TUTTE le tue etichette, TUTTE le tue annotazioni ed il tuo account verranno rimossi PERMANENTEMENTE (impossibile da ANNULLARE). Verrai poi disconnesso. |
@@ -159,6 +168,15 @@ config: | |||
159 | and: "Una regola E un'altra" | 168 | and: "Una regola E un'altra" |
160 | matches: 'Verifica che un <i>oggetto</i> risulti in una <i>ricerca</i> (case-insensitive).<br />Esempio: <code>titolo contiene "football"</code>' | 169 | matches: 'Verifica che un <i>oggetto</i> risulti in una <i>ricerca</i> (case-insensitive).<br />Esempio: <code>titolo contiene "football"</code>' |
161 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' | 170 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' |
171 | otp: | ||
172 | # page_title: Two-factor authentication | ||
173 | # app: | ||
174 | # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
175 | # two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
176 | # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
177 | # two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
178 | # cancel: Cancel | ||
179 | # enable: Enable | ||
162 | 180 | ||
163 | entry: | 181 | entry: |
164 | default_title: "Titolo del contenuto" | 182 | default_title: "Titolo del contenuto" |
@@ -353,7 +371,7 @@ quickstart: | |||
353 | title: "Configura l'applicazione" | 371 | title: "Configura l'applicazione" |
354 | description: "Per avere un'applicazione che ti soddisfi, dai un'occhiata alla configurazione di wallabag." | 372 | description: "Per avere un'applicazione che ti soddisfi, dai un'occhiata alla configurazione di wallabag." |
355 | language: 'Cambia lingua e design' | 373 | language: 'Cambia lingua e design' |
356 | rss: 'Abilita i feed RSS' | 374 | feed: 'Abilita i feed RSS' |
357 | tagging_rules: 'Scrivi delle regole per taggare automaticamente i contenuti' | 375 | tagging_rules: 'Scrivi delle regole per taggare automaticamente i contenuti' |
358 | admin: | 376 | admin: |
359 | title: 'Amministrazione' | 377 | title: 'Amministrazione' |
@@ -404,6 +422,8 @@ tag: | |||
404 | new: | 422 | new: |
405 | add: 'Aggiungi' | 423 | add: 'Aggiungi' |
406 | placeholder: 'Puoi aggiungere varie etichette, separate da una virgola.' | 424 | placeholder: 'Puoi aggiungere varie etichette, separate da una virgola.' |
425 | rename: | ||
426 | # placeholder: 'You can update tag name.' | ||
407 | 427 | ||
408 | # export: | 428 | # export: |
409 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' | 429 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' |
@@ -529,7 +549,8 @@ user: | |||
529 | email_label: 'E-mail' | 549 | email_label: 'E-mail' |
530 | enabled_label: 'Abilitato' | 550 | enabled_label: 'Abilitato' |
531 | last_login_label: 'Ultima connessione' | 551 | last_login_label: 'Ultima connessione' |
532 | twofactor_label: Autenticazione a due fattori | 552 | # twofactor_email_label: Two factor authentication by email |
553 | # twofactor_google_label: Two factor authentication by OTP app | ||
533 | save: Salva | 554 | save: Salva |
534 | delete: Cancella | 555 | delete: Cancella |
535 | delete_confirm: Sei sicuro? | 556 | delete_confirm: Sei sicuro? |
@@ -567,10 +588,10 @@ flashes: | |||
567 | password_updated: 'Password aggiornata' | 588 | password_updated: 'Password aggiornata' |
568 | password_not_updated_demo: "In modalità demo, non puoi cambiare la password dell'utente." | 589 | password_not_updated_demo: "In modalità demo, non puoi cambiare la password dell'utente." |
569 | user_updated: 'Informazioni aggiornate' | 590 | user_updated: 'Informazioni aggiornate' |
570 | rss_updated: 'Informazioni RSS aggiornate' | 591 | feed_updated: 'Informazioni RSS aggiornate' |
571 | tagging_rules_updated: 'Regole di etichettatura aggiornate' | 592 | tagging_rules_updated: 'Regole di etichettatura aggiornate' |
572 | tagging_rules_deleted: 'Regola di etichettatura eliminate' | 593 | tagging_rules_deleted: 'Regola di etichettatura eliminate' |
573 | rss_token_updated: 'RSS token aggiornato' | 594 | feed_token_updated: 'RSS token aggiornato' |
574 | annotations_reset: Reset annotazioni | 595 | annotations_reset: Reset annotazioni |
575 | tags_reset: Reset etichette | 596 | tags_reset: Reset etichette |
576 | entries_reset: Reset articoli | 597 | entries_reset: Reset articoli |
@@ -588,9 +609,11 @@ flashes: | |||
588 | entry_starred: 'Contenuto segnato come preferito' | 609 | entry_starred: 'Contenuto segnato come preferito' |
589 | entry_unstarred: 'Contenuto rimosso dai preferiti' | 610 | entry_unstarred: 'Contenuto rimosso dai preferiti' |
590 | entry_deleted: 'Contenuto eliminato' | 611 | entry_deleted: 'Contenuto eliminato' |
612 | # no_random_entry: 'No article with these criterias was found' | ||
591 | tag: | 613 | tag: |
592 | notice: | 614 | notice: |
593 | tag_added: 'Etichetta aggiunta' | 615 | tag_added: 'Etichetta aggiunta' |
616 | # tag_renamed: 'Tag renamed' | ||
594 | import: | 617 | import: |
595 | notice: | 618 | notice: |
596 | failed: 'Importazione fallita, riprova.' | 619 | failed: 'Importazione fallita, riprova.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml index 848c88d2..e761832e 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'Enregistrar un novèl article' | 37 | add_new_entry: 'Enregistrar un novèl article' |
38 | search: 'Cercar' | 38 | search: 'Cercar' |
39 | filter_entries: 'Filtrar los articles' | 39 | filter_entries: 'Filtrar los articles' |
40 | # random_entry: Jump to a random entry from that list | ||
40 | export: 'Exportar' | 41 | export: 'Exportar' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'Picatz vòstre mot-clau a cercar aquí' | 43 | input_label: 'Picatz vòstre mot-clau a cercar aquí' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'Configuracion' | 54 | page_title: 'Configuracion' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'Paramètres' | 56 | settings: 'Paramètres' |
56 | rss: 'RSS' | 57 | feed: 'RSS' |
57 | user_info: 'Mon compte' | 58 | user_info: 'Mon compte' |
58 | password: 'Senhal' | 59 | password: 'Senhal' |
59 | rules: "Règlas d'etiquetas automaticas" | 60 | rules: "Règlas d'etiquetas automaticas" |
60 | new_user: 'Crear un compte' | 61 | new_user: 'Crear un compte' |
62 | reset: 'Zòna de reïnicializacion' | ||
61 | form: | 63 | form: |
62 | save: 'Enregistrar' | 64 | save: 'Enregistrar' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,32 @@ config: | |||
83 | help_reading_speed: "wallabag calcula lo temps de lectura per cada article. Podètz lo definir aquí, gràcias a aquesta lista, se sètz un legeire rapid o lent. wallabag tornarà calcular lo temps de lectura per cada article." | 85 | help_reading_speed: "wallabag calcula lo temps de lectura per cada article. Podètz lo definir aquí, gràcias a aquesta lista, se sètz un legeire rapid o lent. wallabag tornarà calcular lo temps de lectura per cada article." |
84 | help_language: "Podètz cambiar la lenga de l'interfàcia de wallabag." | 86 | help_language: "Podètz cambiar la lenga de l'interfàcia de wallabag." |
85 | help_pocket_consumer_key: "Requesida per l'importacion de Pocket. Podètz la crear dins vòstre compte Pocket." | 87 | help_pocket_consumer_key: "Requesida per l'importacion de Pocket. Podètz la crear dins vòstre compte Pocket." |
86 | form_rss: | 88 | form_feed: |
87 | description: "Los fluxes RSS fornits per wallabag vos permeton de legir vòstres articles salvagardats dins vòstre lector de fluxes preferit. Per los poder emplegar, vos cal, d'en primièr crear un geton." | 89 | description: "Los fluxes RSS fornits per wallabag vos permeton de legir vòstres articles salvagardats dins vòstre lector de fluxes preferit. Per los poder emplegar, vos cal, d'en primièr crear un geton." |
88 | token_label: 'Geton RSS' | 90 | token_label: 'Geton RSS' |
89 | no_token: 'Pas cap de geton generat' | 91 | no_token: 'Pas cap de geton generat' |
90 | token_create: 'Creatz vòstre geton' | 92 | token_create: 'Creatz vòstre geton' |
91 | token_reset: 'Reïnicializatz vòstre geton' | 93 | token_reset: 'Reïnicializatz vòstre geton' |
92 | rss_links: 'URLs de vòstres fluxes RSS' | 94 | feed_links: 'URLs de vòstres fluxes RSS' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'Pas legits' | 96 | unread: 'Pas legits' |
95 | starred: 'Favorits' | 97 | starred: 'Favorits' |
96 | archive: 'Legits' | 98 | archive: 'Legits' |
97 | all: 'Totes' | 99 | all: 'Totes' |
98 | rss_limit: "Nombre d'articles dins un flux RSS" | 100 | feed_limit: "Nombre d'articles dins un flux" |
99 | form_user: | 101 | form_user: |
100 | two_factor_description: "Activar l'autentificacion en dos temps vòl dire que recebretz un còdi per corrièl per cada novèla connexion pas aprovada." | 102 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'Nom' | 103 | name_label: 'Nom' |
102 | email_label: 'Adreça de corrièl' | 104 | email_label: 'Adreça de corrièl' |
103 | twoFactorAuthentication_label: 'Dobla autentificacion' | 105 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
104 | help_twoFactorAuthentication: "S'avètz activat l'autentificacion en dos temps, cada còp que volètz vos connectar a wallabag, recebretz un còdi per corrièl." | 106 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' |
107 | # table_method: Method | ||
108 | # table_state: State | ||
109 | # table_action: Action | ||
110 | # state_enabled: Enabled | ||
111 | # state_disabled: Disabled | ||
112 | # action_email: Use email | ||
113 | # action_app: Use OTP App | ||
105 | delete: | 114 | delete: |
106 | title: Suprimir mon compte (Mèfi zòna perilhosa) | 115 | title: Suprimir mon compte (Mèfi zòna perilhosa) |
107 | description: Se confirmatz la supression de vòstre compte, TOTES vòstres articles, TOTAS vòstras etiquetas, TOTAS vòstras anotacions e vòstre compte seràn suprimits per totjorn. E aquò es IRREVERSIBLE. Puèi seretz desconnectat. | 116 | description: Se confirmatz la supression de vòstre compte, TOTES vòstres articles, TOTAS vòstras etiquetas, TOTAS vòstras anotacions e vòstre compte seràn suprimits per totjorn. E aquò es IRREVERSIBLE. Puèi seretz desconnectat. |
@@ -159,6 +168,15 @@ config: | |||
159 | and: "Una règla E l'autra" | 168 | and: "Una règla E l'autra" |
160 | 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>' | 169 | 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>' |
161 | 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>' | 170 | 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>' |
171 | otp: | ||
172 | # page_title: Two-factor authentication | ||
173 | # app: | ||
174 | # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
175 | # two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
176 | # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
177 | # two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
178 | # cancel: Cancel | ||
179 | # enable: Enable | ||
162 | 180 | ||
163 | entry: | 181 | entry: |
164 | default_title: "Títol de l'article" | 182 | default_title: "Títol de l'article" |
@@ -353,7 +371,7 @@ quickstart: | |||
353 | title: "Configuratz l'aplicacion" | 371 | title: "Configuratz l'aplicacion" |
354 | description: "Per fin d'aver una aplicacion que vos va ben, anatz veire la configuracion de wallabag." | 372 | description: "Per fin d'aver una aplicacion que vos va ben, anatz veire la configuracion de wallabag." |
355 | language: "Cambiatz la lenga e l'estil de l'aplicacion" | 373 | language: "Cambiatz la lenga e l'estil de l'aplicacion" |
356 | rss: 'Activatz los fluxes RSS' | 374 | feed: 'Activatz los fluxes RSS' |
357 | tagging_rules: 'Escrivètz de règlas per classar automaticament vòstres articles' | 375 | tagging_rules: 'Escrivètz de règlas per classar automaticament vòstres articles' |
358 | admin: | 376 | admin: |
359 | title: 'Administracion' | 377 | title: 'Administracion' |
@@ -404,6 +422,8 @@ tag: | |||
404 | new: | 422 | new: |
405 | add: 'Ajustar' | 423 | add: 'Ajustar' |
406 | placeholder: "Podètz ajustar mai qu'una etiqueta, separadas per de virgula." | 424 | placeholder: "Podètz ajustar mai qu'una etiqueta, separadas per de virgula." |
425 | rename: | ||
426 | # placeholder: 'You can update tag name.' | ||
407 | 427 | ||
408 | export: | 428 | export: |
409 | footer_template: '<div style="text-align:center;"><p>Produch per wallabag amb %method%</p><p>Mercés de dobrir <a href="https://github.com/wallabag/wallabag/issues">una sollicitacion</a> s’avètz de problèmas amb l’afichatge d’aqueste E-Book sus vòstre periferic.</p></div>' | 429 | footer_template: '<div style="text-align:center;"><p>Produch per wallabag amb %method%</p><p>Mercés de dobrir <a href="https://github.com/wallabag/wallabag/issues">una sollicitacion</a> s’avètz de problèmas amb l’afichatge d’aqueste E-Book sus vòstre periferic.</p></div>' |
@@ -529,7 +549,8 @@ user: | |||
529 | email_label: 'Adreça de corrièl' | 549 | email_label: 'Adreça de corrièl' |
530 | enabled_label: 'Actiu' | 550 | enabled_label: 'Actiu' |
531 | last_login_label: 'Darrièra connexion' | 551 | last_login_label: 'Darrièra connexion' |
532 | twofactor_label: 'Autentificacion doble-factor' | 552 | # twofactor_email_label: Two factor authentication by email |
553 | # twofactor_google_label: Two factor authentication by OTP app | ||
533 | save: 'Enregistrar' | 554 | save: 'Enregistrar' |
534 | delete: 'Suprimir' | 555 | delete: 'Suprimir' |
535 | delete_confirm: 'Sètz segur ?' | 556 | delete_confirm: 'Sètz segur ?' |
@@ -567,10 +588,10 @@ flashes: | |||
567 | password_updated: 'Vòstre senhal es ben estat mes a jorn' | 588 | password_updated: 'Vòstre senhal es ben estat mes a jorn' |
568 | password_not_updated_demo: "En demostracion, podètz pas cambiar lo senhal d'aqueste utilizaire." | 589 | password_not_updated_demo: "En demostracion, podètz pas cambiar lo senhal d'aqueste utilizaire." |
569 | user_updated: 'Vòstres informacions personnelas son ben estadas mesas a jorn' | 590 | user_updated: 'Vòstres informacions personnelas son ben estadas mesas a jorn' |
570 | rss_updated: 'La configuracion dels fluxes RSS es ben estada mesa a jorn' | 591 | feed_updated: 'La configuracion dels fluxes RSS es ben estada mesa a jorn' |
571 | tagging_rules_updated: 'Règlas misa a jorn' | 592 | tagging_rules_updated: 'Règlas misa a jorn' |
572 | tagging_rules_deleted: 'Règla suprimida' | 593 | tagging_rules_deleted: 'Règla suprimida' |
573 | rss_token_updated: 'Geton RSS mes a jorn' | 594 | feed_token_updated: 'Geton RSS mes a jorn' |
574 | annotations_reset: Anotacions levadas | 595 | annotations_reset: Anotacions levadas |
575 | tags_reset: Etiquetas levadas | 596 | tags_reset: Etiquetas levadas |
576 | entries_reset: Articles levats | 597 | entries_reset: Articles levats |
@@ -588,9 +609,11 @@ flashes: | |||
588 | entry_starred: 'Article ajustat dins los favorits' | 609 | entry_starred: 'Article ajustat dins los favorits' |
589 | entry_unstarred: 'Article quitat dels favorits' | 610 | entry_unstarred: 'Article quitat dels favorits' |
590 | entry_deleted: 'Article suprimit' | 611 | entry_deleted: 'Article suprimit' |
612 | # no_random_entry: 'No article with these criterias was found' | ||
591 | tag: | 613 | tag: |
592 | notice: | 614 | notice: |
593 | tag_added: 'Etiqueta ajustada' | 615 | tag_added: 'Etiqueta ajustada' |
616 | # tag_renamed: 'Tag renamed' | ||
594 | import: | 617 | import: |
595 | notice: | 618 | notice: |
596 | failed: "L'importacion a fracassat, mercés de tornar ensajar." | 619 | failed: "L'importacion a fracassat, mercés de tornar ensajar." |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml index a0032fe8..f3d506e5 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'Dodaj nowy wpis' | 37 | add_new_entry: 'Dodaj nowy wpis' |
38 | search: 'Szukaj' | 38 | search: 'Szukaj' |
39 | filter_entries: 'Filtruj wpisy' | 39 | filter_entries: 'Filtruj wpisy' |
40 | # random_entry: Jump to a random entry from that list | ||
40 | export: 'Eksportuj' | 41 | export: 'Eksportuj' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'Wpisz swoje zapytanie tutaj' | 43 | input_label: 'Wpisz swoje zapytanie tutaj' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'Konfiguracja' | 54 | page_title: 'Konfiguracja' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'Ustawienia' | 56 | settings: 'Ustawienia' |
56 | rss: 'Kanał RSS' | 57 | feed: 'Kanał RSS' |
57 | user_info: 'Informacje o użytkowniku' | 58 | user_info: 'Informacje o użytkowniku' |
58 | password: 'Hasło' | 59 | password: 'Hasło' |
59 | rules: 'Zasady tagowania' | 60 | rules: 'Zasady tagowania' |
60 | new_user: 'Dodaj użytkownika' | 61 | new_user: 'Dodaj użytkownika' |
62 | reset: 'Reset' | ||
61 | form: | 63 | form: |
62 | save: 'Zapisz' | 64 | save: 'Zapisz' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,32 @@ config: | |||
83 | help_reading_speed: "wallabag oblicza czas czytania każdego artykułu. Dzięki tej liście możesz określić swoje tempo. Wallabag przeliczy ponownie czas potrzebny, na przeczytanie każdego z artykułów." | 85 | help_reading_speed: "wallabag oblicza czas czytania każdego artykułu. Dzięki tej liście możesz określić swoje tempo. Wallabag przeliczy ponownie czas potrzebny, na przeczytanie każdego z artykułów." |
84 | help_language: "Możesz zmienić język interfejsu wallabag." | 86 | help_language: "Możesz zmienić język interfejsu wallabag." |
85 | help_pocket_consumer_key: "Wymagane dla importu z Pocket. Możesz go stworzyć na swoim koncie Pocket." | 87 | help_pocket_consumer_key: "Wymagane dla importu z Pocket. Możesz go stworzyć na swoim koncie Pocket." |
86 | form_rss: | 88 | form_feed: |
87 | description: 'Kanały RSS prowadzone przez wallabag pozwalają Ci na czytanie twoich zapisanych artykułów w twoim ulubionym czytniku RSS. Musisz najpierw wynegenerować tokena.' | 89 | description: 'Kanały RSS prowadzone przez wallabag pozwalają Ci na czytanie twoich zapisanych artykułów w twoim ulubionym czytniku RSS. Musisz najpierw wynegenerować tokena.' |
88 | token_label: 'Token RSS' | 90 | token_label: 'Token RSS' |
89 | no_token: 'Brak tokena' | 91 | no_token: 'Brak tokena' |
90 | token_create: 'Stwórz tokena' | 92 | token_create: 'Stwórz tokena' |
91 | token_reset: 'Zresetuj swojego tokena' | 93 | token_reset: 'Zresetuj swojego tokena' |
92 | rss_links: 'RSS links' | 94 | feed_links: 'RSS links' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'Nieprzeczytane' | 96 | unread: 'Nieprzeczytane' |
95 | starred: 'Oznaczone gwiazdką' | 97 | starred: 'Oznaczone gwiazdką' |
96 | archive: 'Archiwum' | 98 | archive: 'Archiwum' |
97 | all: 'Wszystkie' | 99 | all: 'Wszystkie' |
98 | rss_limit: 'Link do RSS' | 100 | feed_limit: 'Link do RSS' |
99 | form_user: | 101 | form_user: |
100 | two_factor_description: "Włączenie autoryzacji dwuetapowej oznacza, że będziesz otrzymywał maile z kodem przy każdym nowym, niezaufanym połączeniu" | 102 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'Nazwa' | 103 | name_label: 'Nazwa' |
102 | email_label: 'Adres email' | 104 | email_label: 'Adres email' |
103 | twoFactorAuthentication_label: 'Autoryzacja dwuetapowa' | 105 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
104 | help_twoFactorAuthentication: "Jeżeli włączysz autoryzację dwuetapową. Za każdym razem, kiedy będziesz chciał się zalogować, dostaniesz kod na swój e-mail." | 106 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' |
107 | # table_method: Method | ||
108 | # table_state: State | ||
109 | # table_action: Action | ||
110 | # state_enabled: Enabled | ||
111 | # state_disabled: Disabled | ||
112 | # action_email: Use email | ||
113 | # action_app: Use OTP App | ||
105 | delete: | 114 | delete: |
106 | title: Usuń moje konto (niebezpieczna strefa !) | 115 | title: Usuń moje konto (niebezpieczna strefa !) |
107 | description: Jeżeli usuniesz swoje konto, wszystkie twoje artykuły, tagi, adnotacje, oraz konto zostaną trwale usunięte (operacja jest NIEODWRACALNA). Następnie zostaniesz wylogowany. | 116 | description: Jeżeli usuniesz swoje konto, wszystkie twoje artykuły, tagi, adnotacje, oraz konto zostaną trwale usunięte (operacja jest NIEODWRACALNA). Następnie zostaniesz wylogowany. |
@@ -159,6 +168,15 @@ config: | |||
159 | and: 'Jedna reguła I inna' | 168 | and: 'Jedna reguła I inna' |
160 | 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>' | 169 | 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>' |
161 | 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>' | 170 | 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>' |
171 | otp: | ||
172 | # page_title: Two-factor authentication | ||
173 | # app: | ||
174 | # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
175 | # two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
176 | # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
177 | # two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
178 | # cancel: Cancel | ||
179 | # enable: Enable | ||
162 | 180 | ||
163 | entry: | 181 | entry: |
164 | default_title: 'Tytuł wpisu' | 182 | default_title: 'Tytuł wpisu' |
@@ -353,7 +371,7 @@ quickstart: | |||
353 | title: 'Konfiguruj aplikację' | 371 | title: 'Konfiguruj aplikację' |
354 | description: 'W celu dopasowania aplikacji do swoich upodobań, zobacz konfigurację aplikacji' | 372 | description: 'W celu dopasowania aplikacji do swoich upodobań, zobacz konfigurację aplikacji' |
355 | language: 'Zmień język i wygląd' | 373 | language: 'Zmień język i wygląd' |
356 | rss: 'Włącz kanały RSS' | 374 | feed: 'Włącz kanały RSS' |
357 | tagging_rules: 'Napisz reguły pozwalające na automatyczne otagowanie twoich artykułów' | 375 | tagging_rules: 'Napisz reguły pozwalające na automatyczne otagowanie twoich artykułów' |
358 | admin: | 376 | admin: |
359 | title: 'Administracja' | 377 | title: 'Administracja' |
@@ -404,6 +422,8 @@ tag: | |||
404 | new: | 422 | new: |
405 | add: 'Dodaj' | 423 | add: 'Dodaj' |
406 | placeholder: 'Możesz dodać kilka tagów, oddzielając je przecinkami.' | 424 | placeholder: 'Możesz dodać kilka tagów, oddzielając je przecinkami.' |
425 | rename: | ||
426 | placeholder: 'Możesz zaktualizować nazwę taga.' | ||
407 | 427 | ||
408 | export: | 428 | export: |
409 | footer_template: '<div style="text-align:center;"><p>Stworzone przez wallabag z %method%</p><p>Proszę zgłoś <a href="https://github.com/wallabag/wallabag/issues">sprawę</a>, jeżeli masz problem z wyświetleniem tego e-booka na swoim urządzeniu.</p></div>' | 429 | footer_template: '<div style="text-align:center;"><p>Stworzone przez wallabag z %method%</p><p>Proszę zgłoś <a href="https://github.com/wallabag/wallabag/issues">sprawę</a>, jeżeli masz problem z wyświetleniem tego e-booka na swoim urządzeniu.</p></div>' |
@@ -529,7 +549,8 @@ user: | |||
529 | email_label: 'Adres email' | 549 | email_label: 'Adres email' |
530 | enabled_label: 'Włączony' | 550 | enabled_label: 'Włączony' |
531 | last_login_label: 'Ostatnie logowanie' | 551 | last_login_label: 'Ostatnie logowanie' |
532 | twofactor_label: Autoryzacja dwuetapowa | 552 | # twofactor_email_label: Two factor authentication by email |
553 | # twofactor_google_label: Two factor authentication by OTP app | ||
533 | save: Zapisz | 554 | save: Zapisz |
534 | delete: Usuń | 555 | delete: Usuń |
535 | delete_confirm: Jesteś pewien? | 556 | delete_confirm: Jesteś pewien? |
@@ -567,10 +588,10 @@ flashes: | |||
567 | password_updated: 'Hasło zaktualizowane' | 588 | password_updated: 'Hasło zaktualizowane' |
568 | password_not_updated_demo: "In demonstration mode, you can't change password for this user." | 589 | password_not_updated_demo: "In demonstration mode, you can't change password for this user." |
569 | user_updated: 'Informacje zaktualizowane' | 590 | user_updated: 'Informacje zaktualizowane' |
570 | rss_updated: 'Informacje RSS zaktualizowane' | 591 | feed_updated: 'Informacje RSS zaktualizowane' |
571 | tagging_rules_updated: 'Reguły tagowania zaktualizowane' | 592 | tagging_rules_updated: 'Reguły tagowania zaktualizowane' |
572 | tagging_rules_deleted: 'Reguła tagowania usunięta' | 593 | tagging_rules_deleted: 'Reguła tagowania usunięta' |
573 | rss_token_updated: 'Token kanału RSS zaktualizowany' | 594 | feed_token_updated: 'Token kanału RSS zaktualizowany' |
574 | annotations_reset: Zresetuj adnotacje | 595 | annotations_reset: Zresetuj adnotacje |
575 | tags_reset: Zresetuj tagi | 596 | tags_reset: Zresetuj tagi |
576 | entries_reset: Zresetuj wpisy | 597 | entries_reset: Zresetuj wpisy |
@@ -588,9 +609,11 @@ flashes: | |||
588 | entry_starred: 'Wpis oznaczony gwiazdką' | 609 | entry_starred: 'Wpis oznaczony gwiazdką' |
589 | entry_unstarred: 'Wpis odznaczony gwiazdką' | 610 | entry_unstarred: 'Wpis odznaczony gwiazdką' |
590 | entry_deleted: 'Wpis usunięty' | 611 | entry_deleted: 'Wpis usunięty' |
612 | # no_random_entry: 'No article with these criterias was found' | ||
591 | tag: | 613 | tag: |
592 | notice: | 614 | notice: |
593 | tag_added: 'Tag dodany' | 615 | tag_added: 'Tag dodany' |
616 | tag_renamed: 'Nazwa taga zmieniona' | ||
594 | import: | 617 | import: |
595 | notice: | 618 | notice: |
596 | failed: 'Nieudany import, prosimy spróbować ponownie.' | 619 | failed: 'Nieudany import, prosimy spróbować ponownie.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml index 292fad61..6ddc1fc1 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'Adicionar uma nova entrada' | 37 | add_new_entry: 'Adicionar uma nova entrada' |
38 | search: 'Pesquisa' | 38 | search: 'Pesquisa' |
39 | filter_entries: 'Filtrar entradas' | 39 | filter_entries: 'Filtrar entradas' |
40 | # random_entry: Jump to a random entry from that list | ||
40 | export: 'Exportar' | 41 | export: 'Exportar' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'Digite aqui sua pesquisa' | 43 | input_label: 'Digite aqui sua pesquisa' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'Config' | 54 | page_title: 'Config' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'Configurações' | 56 | settings: 'Configurações' |
56 | rss: 'RSS' | 57 | feed: 'RSS' |
57 | user_info: 'Informação do Usuário' | 58 | user_info: 'Informação do Usuário' |
58 | password: 'Senha' | 59 | password: 'Senha' |
59 | rules: 'Regras de tags' | 60 | rules: 'Regras de tags' |
60 | new_user: 'Adicionar um usuário' | 61 | new_user: 'Adicionar um usuário' |
62 | # reset: 'Reset area' | ||
61 | form: | 63 | form: |
62 | save: 'Salvar' | 64 | save: 'Salvar' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,32 @@ config: | |||
83 | # help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." | 85 | # help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." |
84 | # help_language: "You can change the language of wallabag interface." | 86 | # help_language: "You can change the language of wallabag interface." |
85 | # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." | 87 | # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." |
86 | form_rss: | 88 | form_feed: |
87 | description: 'Feeds RSS providos pelo wallabag permitem que você leia seus artigos salvos em seu leitor de RSS favorito. Você precisa gerar um token primeiro.' | 89 | description: 'Feeds RSS providos pelo wallabag permitem que você leia seus artigos salvos em seu leitor de RSS favorito. Você precisa gerar um token primeiro.' |
88 | token_label: 'Token RSS' | 90 | token_label: 'Token RSS' |
89 | no_token: 'Nenhum Token' | 91 | no_token: 'Nenhum Token' |
90 | token_create: 'Criar seu token' | 92 | token_create: 'Criar seu token' |
91 | token_reset: 'Gerar novamente seu token' | 93 | token_reset: 'Gerar novamente seu token' |
92 | rss_links: 'Links RSS' | 94 | feed_links: 'Links RSS' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'Não lido' | 96 | unread: 'Não lido' |
95 | starred: 'Destacado' | 97 | starred: 'Destacado' |
96 | archive: 'Arquivado' | 98 | archive: 'Arquivado' |
97 | # all: 'All' | 99 | # all: 'All' |
98 | rss_limit: 'Número de itens no feed' | 100 | feed_limit: 'Número de itens no feed' |
99 | form_user: | 101 | form_user: |
100 | two_factor_description: 'Habilitar autenticação de dois passos significa que você receberá um e-mail com um código a cada nova conexão desconhecida.' | 102 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'Nome' | 103 | name_label: 'Nome' |
102 | email_label: 'E-mail' | 104 | email_label: 'E-mail' |
103 | twoFactorAuthentication_label: 'Autenticação de dois passos' | 105 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
104 | # help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email." | 106 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' |
107 | # table_method: Method | ||
108 | # table_state: State | ||
109 | # table_action: Action | ||
110 | # state_enabled: Enabled | ||
111 | # state_disabled: Disabled | ||
112 | # action_email: Use email | ||
113 | # action_app: Use OTP App | ||
105 | delete: | 114 | delete: |
106 | # title: Delete my account (a.k.a danger zone) | 115 | # title: Delete my account (a.k.a danger zone) |
107 | # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. | 116 | # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. |
@@ -159,6 +168,15 @@ config: | |||
159 | and: 'Uma regra E outra' | 168 | and: 'Uma regra E outra' |
160 | 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>' | 169 | 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>' |
161 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' | 170 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' |
171 | otp: | ||
172 | # page_title: Two-factor authentication | ||
173 | # app: | ||
174 | # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
175 | # two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
176 | # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
177 | # two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
178 | # cancel: Cancel | ||
179 | # enable: Enable | ||
162 | 180 | ||
163 | entry: | 181 | entry: |
164 | default_title: 'Título da entrada' | 182 | default_title: 'Título da entrada' |
@@ -353,7 +371,7 @@ quickstart: | |||
353 | title: 'Configurar a aplicação' | 371 | title: 'Configurar a aplicação' |
354 | description: 'Para ter uma aplicação que atende você, dê uma olhada na configuração do wallabag.' | 372 | description: 'Para ter uma aplicação que atende você, dê uma olhada na configuração do wallabag.' |
355 | language: 'Alterar idioma e design' | 373 | language: 'Alterar idioma e design' |
356 | rss: 'Habilitar feeds RSS' | 374 | feed: 'Habilitar feeds RSS' |
357 | tagging_rules: 'Escrever regras para acrescentar tags automaticamente em seus artigos' | 375 | tagging_rules: 'Escrever regras para acrescentar tags automaticamente em seus artigos' |
358 | admin: | 376 | admin: |
359 | title: 'Administração' | 377 | title: 'Administração' |
@@ -404,6 +422,8 @@ tag: | |||
404 | new: | 422 | new: |
405 | # add: 'Add' | 423 | # add: 'Add' |
406 | # placeholder: 'You can add several tags, separated by a comma.' | 424 | # placeholder: 'You can add several tags, separated by a comma.' |
425 | rename: | ||
426 | # placeholder: 'You can update tag name.' | ||
407 | 427 | ||
408 | # export: | 428 | # export: |
409 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' | 429 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' |
@@ -529,7 +549,8 @@ user: | |||
529 | email_label: 'E-mail' | 549 | email_label: 'E-mail' |
530 | enabled_label: 'Habilitado' | 550 | enabled_label: 'Habilitado' |
531 | last_login_label: 'Último login' | 551 | last_login_label: 'Último login' |
532 | twofactor_label: 'Autenticação de dois passos' | 552 | # twofactor_email_label: Two factor authentication by email |
553 | # twofactor_google_label: Two factor authentication by OTP app | ||
533 | save: 'Salvar' | 554 | save: 'Salvar' |
534 | delete: 'Apagar' | 555 | delete: 'Apagar' |
535 | delete_confirm: 'Tem certeza?' | 556 | delete_confirm: 'Tem certeza?' |
@@ -567,10 +588,10 @@ flashes: | |||
567 | password_updated: 'Senha atualizada' | 588 | password_updated: 'Senha atualizada' |
568 | password_not_updated_demo: 'Em modo de demonstração, você não pode alterar a senha deste usuário.' | 589 | password_not_updated_demo: 'Em modo de demonstração, você não pode alterar a senha deste usuário.' |
569 | # user_updated: 'Information updated' | 590 | # user_updated: 'Information updated' |
570 | rss_updated: 'Informação de RSS atualizada' | 591 | feed_updated: 'Informação de RSS atualizada' |
571 | tagging_rules_updated: 'Regras de tags atualizadas' | 592 | tagging_rules_updated: 'Regras de tags atualizadas' |
572 | tagging_rules_deleted: 'Regra de tag apagada' | 593 | tagging_rules_deleted: 'Regra de tag apagada' |
573 | rss_token_updated: 'Token RSS atualizado' | 594 | feed_token_updated: 'Token RSS atualizado' |
574 | # annotations_reset: Annotations reset | 595 | # annotations_reset: Annotations reset |
575 | # tags_reset: Tags reset | 596 | # tags_reset: Tags reset |
576 | # entries_reset: Entries reset | 597 | # entries_reset: Entries reset |
@@ -588,9 +609,11 @@ flashes: | |||
588 | entry_starred: 'Entrada destacada' | 609 | entry_starred: 'Entrada destacada' |
589 | entry_unstarred: 'Entrada não destacada' | 610 | entry_unstarred: 'Entrada não destacada' |
590 | entry_deleted: 'Entrada apagada' | 611 | entry_deleted: 'Entrada apagada' |
612 | # no_random_entry: 'No article with these criterias was found' | ||
591 | tag: | 613 | tag: |
592 | notice: | 614 | notice: |
593 | tag_added: 'Tag adicionada' | 615 | tag_added: 'Tag adicionada' |
616 | # tag_renamed: 'Tag renamed' | ||
594 | import: | 617 | import: |
595 | notice: | 618 | notice: |
596 | failed: 'Importação falhou, por favor tente novamente.' | 619 | failed: 'Importação falhou, por favor tente novamente.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml index 9e8d68b3..8c0791f0 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'Introdu un nou articol' | 37 | add_new_entry: 'Introdu un nou articol' |
38 | search: 'Căutare' | 38 | search: 'Căutare' |
39 | filter_entries: 'Filtrează articolele' | 39 | filter_entries: 'Filtrează articolele' |
40 | # random_entry: Jump to a random entry from that list | ||
40 | # export: 'Export' | 41 | # export: 'Export' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'Introdu căutarea ta' | 43 | input_label: 'Introdu căutarea ta' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'Configurație' | 54 | page_title: 'Configurație' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'Setări' | 56 | settings: 'Setări' |
56 | rss: 'RSS' | 57 | feed: 'RSS' |
57 | user_info: 'Informații despre utilizator' | 58 | user_info: 'Informații despre utilizator' |
58 | password: 'Parolă' | 59 | password: 'Parolă' |
59 | # rules: 'Tagging rules' | 60 | # rules: 'Tagging rules' |
60 | new_user: 'Crează un utilizator' | 61 | new_user: 'Crează un utilizator' |
62 | # reset: 'Reset area' | ||
61 | form: | 63 | form: |
62 | save: 'Salvează' | 64 | save: 'Salvează' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,32 @@ config: | |||
83 | # help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." | 85 | # help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." |
84 | # help_language: "You can change the language of wallabag interface." | 86 | # help_language: "You can change the language of wallabag interface." |
85 | # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." | 87 | # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." |
86 | form_rss: | 88 | form_feed: |
87 | description: 'Feed-urile RSS oferite de wallabag îți permit să-ți citești articolele salvate în reader-ul tău preferat RSS.' | 89 | description: 'Feed-urile RSS oferite de wallabag îți permit să-ți citești articolele salvate în reader-ul tău preferat RSS.' |
88 | token_label: 'RSS-Token' | 90 | token_label: 'RSS-Token' |
89 | no_token: 'Fără token' | 91 | no_token: 'Fără token' |
90 | token_create: 'Crează-ți token' | 92 | token_create: 'Crează-ți token' |
91 | token_reset: 'Resetează-ți token-ul' | 93 | token_reset: 'Resetează-ți token-ul' |
92 | rss_links: 'Link-uri RSS' | 94 | feed_links: 'Link-uri RSS' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'Unread' | 96 | unread: 'Unread' |
95 | starred: 'Starred' | 97 | starred: 'Starred' |
96 | archive: 'Archived' | 98 | archive: 'Archived' |
97 | # all: 'All' | 99 | # all: 'All' |
98 | rss_limit: 'Limită RSS' | 100 | feed_limit: 'Limită RSS' |
99 | form_user: | 101 | form_user: |
100 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code on every new untrusted connexion" | 102 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'Nume' | 103 | name_label: 'Nume' |
102 | email_label: 'E-mail' | 104 | email_label: 'E-mail' |
103 | # twoFactorAuthentication_label: 'Two factor authentication' | 105 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
104 | # help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email." | 106 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' |
107 | # table_method: Method | ||
108 | # table_state: State | ||
109 | # table_action: Action | ||
110 | # state_enabled: Enabled | ||
111 | # state_disabled: Disabled | ||
112 | # action_email: Use email | ||
113 | # action_app: Use OTP App | ||
105 | delete: | 114 | delete: |
106 | # title: Delete my account (a.k.a danger zone) | 115 | # title: Delete my account (a.k.a danger zone) |
107 | # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. | 116 | # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. |
@@ -159,6 +168,15 @@ config: | |||
159 | # and: 'One rule AND another' | 168 | # and: 'One rule AND another' |
160 | # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' | 169 | # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' |
161 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' | 170 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' |
171 | otp: | ||
172 | # page_title: Two-factor authentication | ||
173 | # app: | ||
174 | # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
175 | # two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
176 | # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
177 | # two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
178 | # cancel: Cancel | ||
179 | # enable: Enable | ||
162 | 180 | ||
163 | entry: | 181 | entry: |
164 | # default_title: 'Title of the entry' | 182 | # default_title: 'Title of the entry' |
@@ -353,7 +371,7 @@ quickstart: | |||
353 | # title: 'Configure the application' | 371 | # title: 'Configure the application' |
354 | # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' | 372 | # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' |
355 | # language: 'Change language and design' | 373 | # language: 'Change language and design' |
356 | # rss: 'Enable RSS feeds' | 374 | # feed: 'Enable RSS feeds' |
357 | # tagging_rules: 'Write rules to automatically tag your articles' | 375 | # tagging_rules: 'Write rules to automatically tag your articles' |
358 | # admin: | 376 | # admin: |
359 | # title: 'Administration' | 377 | # title: 'Administration' |
@@ -404,6 +422,8 @@ tag: | |||
404 | new: | 422 | new: |
405 | # add: 'Add' | 423 | # add: 'Add' |
406 | # placeholder: 'You can add several tags, separated by a comma.' | 424 | # placeholder: 'You can add several tags, separated by a comma.' |
425 | rename: | ||
426 | # placeholder: 'You can update tag name.' | ||
407 | 427 | ||
408 | # export: | 428 | # export: |
409 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' | 429 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' |
@@ -529,7 +549,8 @@ user: | |||
529 | email_label: 'E-mail' | 549 | email_label: 'E-mail' |
530 | # enabled_label: 'Enabled' | 550 | # enabled_label: 'Enabled' |
531 | # last_login_label: 'Last login' | 551 | # last_login_label: 'Last login' |
532 | # twofactor_label: Two factor authentication | 552 | # twofactor_email_label: Two factor authentication by email |
553 | # twofactor_google_label: Two factor authentication by OTP app | ||
533 | # save: Save | 554 | # save: Save |
534 | # delete: Delete | 555 | # delete: Delete |
535 | # delete_confirm: Are you sure? | 556 | # delete_confirm: Are you sure? |
@@ -567,10 +588,10 @@ flashes: | |||
567 | password_updated: 'Parolă actualizată' | 588 | password_updated: 'Parolă actualizată' |
568 | password_not_updated_demo: "In demonstration mode, you can't change password for this user." | 589 | password_not_updated_demo: "In demonstration mode, you can't change password for this user." |
569 | user_updated: 'Informație actualizată' | 590 | user_updated: 'Informație actualizată' |
570 | rss_updated: 'Informație RSS actualizată' | 591 | feed_updated: 'Informație RSS actualizată' |
571 | # tagging_rules_updated: 'Tagging rules updated' | 592 | # tagging_rules_updated: 'Tagging rules updated' |
572 | # tagging_rules_deleted: 'Tagging rule deleted' | 593 | # tagging_rules_deleted: 'Tagging rule deleted' |
573 | # rss_token_updated: 'RSS token updated' | 594 | # feed_token_updated: 'RSS token updated' |
574 | # annotations_reset: Annotations reset | 595 | # annotations_reset: Annotations reset |
575 | # tags_reset: Tags reset | 596 | # tags_reset: Tags reset |
576 | # entries_reset: Entries reset | 597 | # entries_reset: Entries reset |
@@ -588,9 +609,11 @@ flashes: | |||
588 | entry_starred: 'Articol adăugat la favorite' | 609 | entry_starred: 'Articol adăugat la favorite' |
589 | entry_unstarred: 'Articol șters de la favorite' | 610 | entry_unstarred: 'Articol șters de la favorite' |
590 | entry_deleted: 'Articol șters' | 611 | entry_deleted: 'Articol șters' |
612 | # no_random_entry: 'No article with these criterias was found' | ||
591 | tag: | 613 | tag: |
592 | notice: | 614 | notice: |
593 | # tag_added: 'Tag added' | 615 | # tag_added: 'Tag added' |
616 | # tag_renamed: 'Tag renamed' | ||
594 | import: | 617 | import: |
595 | notice: | 618 | notice: |
596 | # failed: 'Import failed, please try again.' | 619 | # failed: 'Import failed, please try again.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml index 48753b55..2ee2d83a 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml | |||
@@ -36,6 +36,7 @@ menu: | |||
36 | add_new_entry: 'Добавить новую запись' | 36 | add_new_entry: 'Добавить новую запись' |
37 | search: 'Поиск' | 37 | search: 'Поиск' |
38 | filter_entries: 'Фильтр записей' | 38 | filter_entries: 'Фильтр записей' |
39 | # random_entry: Jump to a random entry from that list | ||
39 | export: 'Экспорт' | 40 | export: 'Экспорт' |
40 | search_form: | 41 | search_form: |
41 | input_label: 'Введите текст для поиска' | 42 | input_label: 'Введите текст для поиска' |
@@ -52,11 +53,12 @@ config: | |||
52 | page_title: 'Настройки' | 53 | page_title: 'Настройки' |
53 | tab_menu: | 54 | tab_menu: |
54 | settings: 'Настройки' | 55 | settings: 'Настройки' |
55 | rss: 'RSS' | 56 | feed: 'RSS' |
56 | user_info: 'Информация о пользователе' | 57 | user_info: 'Информация о пользователе' |
57 | password: 'Пароль' | 58 | password: 'Пароль' |
58 | rules: 'Правила настройки простановки тегов' | 59 | rules: 'Правила настройки простановки тегов' |
59 | new_user: 'Добавить пользователя' | 60 | new_user: 'Добавить пользователя' |
61 | reset: 'Сброс данных' | ||
60 | form: | 62 | form: |
61 | save: 'Сохранить' | 63 | save: 'Сохранить' |
62 | form_settings: | 64 | form_settings: |
@@ -81,24 +83,31 @@ config: | |||
81 | help_reading_speed: "wallabag посчитает сколько времени занимает чтение каждой записи. Вы можете определить здесь, как быстро вы читаете. wallabag пересчитает время чтения для каждой записи." | 83 | help_reading_speed: "wallabag посчитает сколько времени занимает чтение каждой записи. Вы можете определить здесь, как быстро вы читаете. wallabag пересчитает время чтения для каждой записи." |
82 | help_language: "Вы можете изменить язык интерфейса wallabag." | 84 | help_language: "Вы можете изменить язык интерфейса wallabag." |
83 | help_pocket_consumer_key: "Обязательно для импорта из Pocket. Вы можете создать это в Вашем аккаунте на Pocket." | 85 | help_pocket_consumer_key: "Обязательно для импорта из Pocket. Вы можете создать это в Вашем аккаунте на Pocket." |
84 | form_rss: | 86 | form_feed: |
85 | description: 'RSS фид созданный с помощью wallabag позволяет читать Ваши записи через Ваш любимый RSS агрегатор. Для начала Вам потребуется создать ключ.' | 87 | description: 'RSS фид созданный с помощью wallabag позволяет читать Ваши записи через Ваш любимый RSS агрегатор. Для начала Вам потребуется создать ключ.' |
86 | token_label: 'RSS ключ' | 88 | token_label: 'RSS ключ' |
87 | no_token: 'Ключ не задан' | 89 | no_token: 'Ключ не задан' |
88 | token_create: 'Создать ключ' | 90 | token_create: 'Создать ключ' |
89 | token_reset: 'Пересоздать ключ' | 91 | token_reset: 'Пересоздать ключ' |
90 | rss_links: 'ссылка на RSS' | 92 | feed_links: 'ссылка на RSS' |
91 | rss_link: | 93 | feed_link: |
92 | unread: 'непрочитанные' | 94 | unread: 'непрочитанные' |
93 | starred: 'помеченные' | 95 | starred: 'помеченные' |
94 | archive: 'архивные' | 96 | archive: 'архивные' |
95 | rss_limit: 'Количество записей в фиде' | 97 | feed_limit: 'Количество записей в фиде' |
96 | form_user: | 98 | form_user: |
97 | two_factor_description: "Включить двухфакторную аутентификацию, Вы получите сообщение на указанный email с кодом, при каждом новом непроверенном подключении." | 99 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
98 | name_label: 'Имя' | 100 | name_label: 'Имя' |
99 | email_label: 'Email' | 101 | email_label: 'Email' |
100 | twoFactorAuthentication_label: 'Двухфакторная аутентификация' | 102 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
101 | help_twoFactorAuthentication: "Если Вы включите двухфакторную аутентификацию, то Вы будете получать код на указанный ранее email, каждый раз при входе в wallabag." | 103 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' |
104 | # table_method: Method | ||
105 | # table_state: State | ||
106 | # table_action: Action | ||
107 | # state_enabled: Enabled | ||
108 | # state_disabled: Disabled | ||
109 | # action_email: Use email | ||
110 | # action_app: Use OTP App | ||
102 | delete: | 111 | delete: |
103 | title: "Удалить мой аккаунт (или опасная зона)" | 112 | title: "Удалить мой аккаунт (или опасная зона)" |
104 | description: "Если Вы удалите ваш аккаунт, ВСЕ ваши записи, теги и другие данные, будут БЕЗВОЗВРАТНО удалены (операция не может быть отменена после). Затем Вы выйдете из системы." | 113 | description: "Если Вы удалите ваш аккаунт, ВСЕ ваши записи, теги и другие данные, будут БЕЗВОЗВРАТНО удалены (операция не может быть отменена после). Затем Вы выйдете из системы." |
@@ -154,6 +163,15 @@ config: | |||
154 | or: 'Одно правило ИЛИ другое' | 163 | or: 'Одно правило ИЛИ другое' |
155 | and: 'Одно правило И другое' | 164 | and: 'Одно правило И другое' |
156 | matches: 'Тесты, в которых <i> тема </i> соответствует <i> поиску </i> (без учета регистра). Пример: <code> title matches "футбол" </code>' | 165 | matches: 'Тесты, в которых <i> тема </i> соответствует <i> поиску </i> (без учета регистра). Пример: <code> title matches "футбол" </code>' |
166 | otp: | ||
167 | # page_title: Two-factor authentication | ||
168 | # app: | ||
169 | # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
170 | # two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
171 | # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
172 | # two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
173 | # cancel: Cancel | ||
174 | # enable: Enable | ||
157 | 175 | ||
158 | entry: | 176 | entry: |
159 | default_title: 'Название записи' | 177 | default_title: 'Название записи' |
@@ -341,7 +359,7 @@ quickstart: | |||
341 | title: 'Настроить приложение' | 359 | title: 'Настроить приложение' |
342 | description: 'Чтобы иметь приложение, которое вам подходит, ознакомьтесь с конфигурацией wallabag.' | 360 | description: 'Чтобы иметь приложение, которое вам подходит, ознакомьтесь с конфигурацией wallabag.' |
343 | language: 'Выбрать язык и дизайн' | 361 | language: 'Выбрать язык и дизайн' |
344 | rss: 'Включить RSS фид' | 362 | feed: 'Включить RSS фид' |
345 | tagging_rules: 'Создать правило для автоматической установки тегов' | 363 | tagging_rules: 'Создать правило для автоматической установки тегов' |
346 | admin: | 364 | admin: |
347 | title: 'Администрирование' | 365 | title: 'Администрирование' |
@@ -392,6 +410,8 @@ tag: | |||
392 | new: | 410 | new: |
393 | add: 'Добавить' | 411 | add: 'Добавить' |
394 | placeholder: 'Вы можете добавить несколько тегов, разделенных запятой.' | 412 | placeholder: 'Вы можете добавить несколько тегов, разделенных запятой.' |
413 | rename: | ||
414 | # placeholder: 'You can update tag name.' | ||
395 | 415 | ||
396 | # export: | 416 | # export: |
397 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' | 417 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' |
@@ -517,7 +537,8 @@ user: | |||
517 | email_label: 'Email' | 537 | email_label: 'Email' |
518 | enabled_label: 'Включить' | 538 | enabled_label: 'Включить' |
519 | last_login_label: 'Последний вход' | 539 | last_login_label: 'Последний вход' |
520 | twofactor_label: "Двухфакторная аутентификация" | 540 | # twofactor_email_label: Two factor authentication by email |
541 | # twofactor_google_label: Two factor authentication by OTP app | ||
521 | save: "Сохранить" | 542 | save: "Сохранить" |
522 | delete: "Удалить" | 543 | delete: "Удалить" |
523 | delete_confirm: "Вы уверены?" | 544 | delete_confirm: "Вы уверены?" |
@@ -533,10 +554,10 @@ flashes: | |||
533 | password_updated: 'Пароль обновлен' | 554 | password_updated: 'Пароль обновлен' |
534 | password_not_updated_demo: "В режиме демонстрации нельзя изменять пароль для этого пользователя." | 555 | password_not_updated_demo: "В режиме демонстрации нельзя изменять пароль для этого пользователя." |
535 | user_updated: 'Информация обновлена' | 556 | user_updated: 'Информация обновлена' |
536 | rss_updated: 'RSS информация обновлена' | 557 | feed_updated: 'RSS информация обновлена' |
537 | tagging_rules_updated: 'Правила тегировния обновлены' | 558 | tagging_rules_updated: 'Правила тегировния обновлены' |
538 | tagging_rules_deleted: 'Правила тегировния удалены' | 559 | tagging_rules_deleted: 'Правила тегировния удалены' |
539 | rss_token_updated: 'RSS ключ обновлен' | 560 | feed_token_updated: 'RSS ключ обновлен' |
540 | annotations_reset: "Аннотации сброшены" | 561 | annotations_reset: "Аннотации сброшены" |
541 | tags_reset: "Теги сброшены" | 562 | tags_reset: "Теги сброшены" |
542 | entries_reset: "Записи сброшены" | 563 | entries_reset: "Записи сброшены" |
@@ -553,9 +574,11 @@ flashes: | |||
553 | entry_starred: 'Запись помечена звездочкой' | 574 | entry_starred: 'Запись помечена звездочкой' |
554 | entry_unstarred: 'Пометка звездочкой у записи убрана' | 575 | entry_unstarred: 'Пометка звездочкой у записи убрана' |
555 | entry_deleted: 'Запись удалена' | 576 | entry_deleted: 'Запись удалена' |
577 | # no_random_entry: 'No article with these criterias was found' | ||
556 | tag: | 578 | tag: |
557 | notice: | 579 | notice: |
558 | tag_added: 'Тег добавлен' | 580 | tag_added: 'Тег добавлен' |
581 | # tag_renamed: 'Tag renamed' | ||
559 | import: | 582 | import: |
560 | notice: | 583 | notice: |
561 | failed: 'Во время импорта произошла ошибка, повторите попытку.' | 584 | failed: 'Во время импорта произошла ошибка, повторите попытку.' |
@@ -573,4 +596,4 @@ flashes: | |||
573 | notice: | 596 | notice: |
574 | added: 'Пользователь "%username%" добавлен' | 597 | added: 'Пользователь "%username%" добавлен' |
575 | updated: 'Пользователь "%username%" обновлен' | 598 | updated: 'Пользователь "%username%" обновлен' |
576 | deleted: 'Пользователь "%username%" удален' \ No newline at end of file | 599 | deleted: 'Пользователь "%username%" удален' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml index cb3b0f23..967ae427 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'เพิ่มรายการใหม่' | 37 | add_new_entry: 'เพิ่มรายการใหม่' |
38 | search: 'ค้นหา' | 38 | search: 'ค้นหา' |
39 | filter_entries: 'ตัวกรองรายการ' | 39 | filter_entries: 'ตัวกรองรายการ' |
40 | # random_entry: Jump to a random entry from that list | ||
40 | export: 'นำข้อมูลออก' | 41 | export: 'นำข้อมูลออก' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'ค้นหาที่นี้' | 43 | input_label: 'ค้นหาที่นี้' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'กำหนดค่า' | 54 | page_title: 'กำหนดค่า' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'ตั้งค่า' | 56 | settings: 'ตั้งค่า' |
56 | rss: 'RSS' | 57 | feed: 'RSS' |
57 | user_info: 'ข้อมูลผู้ใช้' | 58 | user_info: 'ข้อมูลผู้ใช้' |
58 | password: 'รหัสผ่าน' | 59 | password: 'รหัสผ่าน' |
59 | rules: 'การแท็กข้อบังคับ' | 60 | rules: 'การแท็กข้อบังคับ' |
60 | new_user: 'เพิ่มผู้ใช้' | 61 | new_user: 'เพิ่มผู้ใช้' |
62 | reset: 'รีเซ็ตพื้นที่ ' | ||
61 | form: | 63 | form: |
62 | save: 'บันทึก' | 64 | save: 'บันทึก' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,32 @@ config: | |||
83 | help_reading_speed: "wallabag จะคำนวณเวลาการอ่านในแต่ละรายการซึ่งคุณสามารถกำหนดได้ที่นี้,ต้องขอบคุณรายการนี้,หากคุณเป็นนักอ่านที่เร็วหรือช้า wallabag จะทำการคำนวณเวลาที่อ่านใหม่ในแต่ละรายการ" | 85 | help_reading_speed: "wallabag จะคำนวณเวลาการอ่านในแต่ละรายการซึ่งคุณสามารถกำหนดได้ที่นี้,ต้องขอบคุณรายการนี้,หากคุณเป็นนักอ่านที่เร็วหรือช้า wallabag จะทำการคำนวณเวลาที่อ่านใหม่ในแต่ละรายการ" |
84 | help_language: "คุณสามารถเปลี่ยภาษาของ wallabag interface ได้" | 86 | help_language: "คุณสามารถเปลี่ยภาษาของ wallabag interface ได้" |
85 | help_pocket_consumer_key: "การ้องขอการเก็บการนำข้อมูลเข้า คุณสามารถสร้างบัญชีการเก็บของคุณ" | 87 | help_pocket_consumer_key: "การ้องขอการเก็บการนำข้อมูลเข้า คุณสามารถสร้างบัญชีการเก็บของคุณ" |
86 | form_rss: | 88 | form_feed: |
87 | description: 'RSS จะเก็บเงื่อนไขโดย wallabag ต้องยอมรับการอ่านรายการของคุณกับผู้อ่านที่ชอบ RSS คุณต้องทำเครื่องหมายก่อน' | 89 | description: 'RSS จะเก็บเงื่อนไขโดย wallabag ต้องยอมรับการอ่านรายการของคุณกับผู้อ่านที่ชอบ RSS คุณต้องทำเครื่องหมายก่อน' |
88 | token_label: 'เครื่องหมาย RSS' | 90 | token_label: 'เครื่องหมาย RSS' |
89 | no_token: 'ไม่มีเครื่องหมาย' | 91 | no_token: 'ไม่มีเครื่องหมาย' |
90 | token_create: 'สร้างเครื่องหมาย' | 92 | token_create: 'สร้างเครื่องหมาย' |
91 | token_reset: 'ทำเครื่องหมาย' | 93 | token_reset: 'ทำเครื่องหมาย' |
92 | rss_links: 'ลิงค์ RSS' | 94 | feed_links: 'ลิงค์ RSS' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'ยังไมได้่อ่าน' | 96 | unread: 'ยังไมได้่อ่าน' |
95 | starred: 'ทำการแสดง' | 97 | starred: 'ทำการแสดง' |
96 | archive: 'เอกสาร' | 98 | archive: 'เอกสาร' |
97 | all: 'ทั้งหมด' | 99 | all: 'ทั้งหมด' |
98 | rss_limit: 'จำนวนไอเทมที่เก็บ' | 100 | feed_limit: 'จำนวนไอเทมที่เก็บ' |
99 | form_user: | 101 | form_user: |
100 | two_factor_description: "การเปิดใช้งาน two factor authentication คือคุณจะต้องได้รับอีเมลกับ code ที่ยังไม่ตรวจสอบในการเชื่อมต่อ" | 102 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'ชื่อ' | 103 | name_label: 'ชื่อ' |
102 | email_label: 'อีเมล' | 104 | email_label: 'อีเมล' |
103 | twoFactorAuthentication_label: 'Two factor authentication' | 105 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
104 | help_twoFactorAuthentication: "ถ้าคุณเปิด 2FA, ในแต่ละช่วงเวลาที่คุณต้องการลงชื่อเข้าใช wallabag, คุณจะต้องได้รับ code จากอีเมล" | 106 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' |
107 | # table_method: Method | ||
108 | # table_state: State | ||
109 | # table_action: Action | ||
110 | # state_enabled: Enabled | ||
111 | # state_disabled: Disabled | ||
112 | # action_email: Use email | ||
113 | # action_app: Use OTP App | ||
105 | delete: | 114 | delete: |
106 | title: ลบบัญชีของฉัน (โซนที่เป็นภัย!) | 115 | title: ลบบัญชีของฉัน (โซนที่เป็นภัย!) |
107 | description: ถ้าคุณลบบัญชีของคุณIf , รายการทั้งหมดของคุณ, แท็กทั้งหมดของคุณ, หมายเหตุทั้งหมดของคุณและบัญชีของคุณจะถูกลบอย่างถาวร (มันไม่สามารถยกเลิกได้) คุณจะต้องลงชื่อออก | 116 | description: ถ้าคุณลบบัญชีของคุณIf , รายการทั้งหมดของคุณ, แท็กทั้งหมดของคุณ, หมายเหตุทั้งหมดของคุณและบัญชีของคุณจะถูกลบอย่างถาวร (มันไม่สามารถยกเลิกได้) คุณจะต้องลงชื่อออก |
@@ -159,6 +168,15 @@ config: | |||
159 | and: 'หนึ่งข้อบังคับและอื่นๆ' | 168 | and: 'หนึ่งข้อบังคับและอื่นๆ' |
160 | matches: 'ทดสอบว่า <i>เรื่อง</i> นี้ตรงกับ <i>การต้นหา</i> (กรณีไม่ทราบ).<br />ตัวอย่าง: <code>หัวข้อที่ตรงกับ "football"</code>' | 169 | matches: 'ทดสอบว่า <i>เรื่อง</i> นี้ตรงกับ <i>การต้นหา</i> (กรณีไม่ทราบ).<br />ตัวอย่าง: <code>หัวข้อที่ตรงกับ "football"</code>' |
161 | notmatches: 'ทดสอบว่า <i>เรื่อง</i> นี้ไม่ตรงกับ <i>การต้นหา</i> (กรณีไม่ทราบ).<br />ตัวอย่าง: <code>หัวข้อทีไม่ตรงกับ "football"</code>' | 170 | notmatches: 'ทดสอบว่า <i>เรื่อง</i> นี้ไม่ตรงกับ <i>การต้นหา</i> (กรณีไม่ทราบ).<br />ตัวอย่าง: <code>หัวข้อทีไม่ตรงกับ "football"</code>' |
171 | otp: | ||
172 | # page_title: Two-factor authentication | ||
173 | # app: | ||
174 | # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
175 | # two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
176 | # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
177 | # two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
178 | # cancel: Cancel | ||
179 | # enable: Enable | ||
162 | 180 | ||
163 | entry: | 181 | entry: |
164 | default_title: 'หัวข้อรายการ' | 182 | default_title: 'หัวข้อรายการ' |
@@ -351,7 +369,7 @@ quickstart: | |||
351 | title: 'กำหนดค่าแอพพลิเคชั่น' | 369 | title: 'กำหนดค่าแอพพลิเคชั่น' |
352 | description: 'ภายใน order จะมี application suit ของคุณ, จะมองหาองค์ประกอบของ wallabag' | 370 | description: 'ภายใน order จะมี application suit ของคุณ, จะมองหาองค์ประกอบของ wallabag' |
353 | language: 'เปลี่ยนภาษาและออกแบบ' | 371 | language: 'เปลี่ยนภาษาและออกแบบ' |
354 | rss: 'เปิดใช้ RSS' | 372 | feed: 'เปิดใช้ RSS' |
355 | tagging_rules: 'เขียนข้อบังคับการแท็กอัตโนมัติของบทความของคุณ' | 373 | tagging_rules: 'เขียนข้อบังคับการแท็กอัตโนมัติของบทความของคุณ' |
356 | admin: | 374 | admin: |
357 | title: 'ผู้ดูแลระบบ' | 375 | title: 'ผู้ดูแลระบบ' |
@@ -402,6 +420,8 @@ tag: | |||
402 | new: | 420 | new: |
403 | add: 'เพิ่ม' | 421 | add: 'เพิ่ม' |
404 | placeholder: 'คุณสามารถเพิ่มได้หลายแท็ก, จากการแบ่งโดย comma' | 422 | placeholder: 'คุณสามารถเพิ่มได้หลายแท็ก, จากการแบ่งโดย comma' |
423 | rename: | ||
424 | # placeholder: 'You can update tag name.' | ||
405 | 425 | ||
406 | export: | 426 | export: |
407 | footer_template: '<div style="text-align:center;"><p>ผลิตโดย wallabag กับ %method%</p><p>ให้ทำการเปิด <a href="https://github.com/wallabag/wallabag/issues">ฉบับนี้</a> ถ้าคุณมีข้อบกพร่องif you have trouble with the display of this E-Book on your device.</p></div>' | 427 | footer_template: '<div style="text-align:center;"><p>ผลิตโดย wallabag กับ %method%</p><p>ให้ทำการเปิด <a href="https://github.com/wallabag/wallabag/issues">ฉบับนี้</a> ถ้าคุณมีข้อบกพร่องif you have trouble with the display of this E-Book on your device.</p></div>' |
@@ -527,7 +547,8 @@ user: | |||
527 | email_label: 'อีเมล' | 547 | email_label: 'อีเมล' |
528 | enabled_label: 'เปิดใช้งาน' | 548 | enabled_label: 'เปิดใช้งาน' |
529 | last_login_label: 'ลงชื้อเข้าใช้ครั้งสุดท้าย' | 549 | last_login_label: 'ลงชื้อเข้าใช้ครั้งสุดท้าย' |
530 | twofactor_label: Two factor authentication | 550 | # twofactor_email_label: Two factor authentication by email |
551 | # twofactor_google_label: Two factor authentication by OTP app | ||
531 | save: บันทึก | 552 | save: บันทึก |
532 | delete: ลบ | 553 | delete: ลบ |
533 | delete_confirm: ตุณแน่ใจหรือไม่? | 554 | delete_confirm: ตุณแน่ใจหรือไม่? |
@@ -565,10 +586,10 @@ flashes: | |||
565 | password_updated: 'อัปเดตรหัสผ่าน' | 586 | password_updated: 'อัปเดตรหัสผ่าน' |
566 | password_not_updated_demo: "In demonstration mode, you can't change password for this user." | 587 | password_not_updated_demo: "In demonstration mode, you can't change password for this user." |
567 | user_updated: 'อัปเดตข้อมูล' | 588 | user_updated: 'อัปเดตข้อมูล' |
568 | rss_updated: 'อัปเดตข้อมูล RSS' | 589 | feed_updated: 'อัปเดตข้อมูล RSS' |
569 | tagging_rules_updated: 'อัปเดตการแท็กข้อบังคับ' | 590 | tagging_rules_updated: 'อัปเดตการแท็กข้อบังคับ' |
570 | tagging_rules_deleted: 'การลบข้อบังคับของแท็ก' | 591 | tagging_rules_deleted: 'การลบข้อบังคับของแท็ก' |
571 | rss_token_updated: 'อัปเดตเครื่องหมาย RSS ' | 592 | feed_token_updated: 'อัปเดตเครื่องหมาย RSS ' |
572 | annotations_reset: รีเซ็ตหมายเหตุ | 593 | annotations_reset: รีเซ็ตหมายเหตุ |
573 | tags_reset: รีเซ็ตแท็ก | 594 | tags_reset: รีเซ็ตแท็ก |
574 | entries_reset: รีเซ็ตรายการ | 595 | entries_reset: รีเซ็ตรายการ |
@@ -586,9 +607,11 @@ flashes: | |||
586 | entry_starred: 'รายการที่แสดง' | 607 | entry_starred: 'รายการที่แสดง' |
587 | entry_unstarred: 'รายการที่ไม่ได้แสดง' | 608 | entry_unstarred: 'รายการที่ไม่ได้แสดง' |
588 | entry_deleted: 'รายการที่ถูกลบ' | 609 | entry_deleted: 'รายการที่ถูกลบ' |
610 | # no_random_entry: 'No article with these criterias was found' | ||
589 | tag: | 611 | tag: |
590 | notice: | 612 | notice: |
591 | tag_added: 'แท็กที่เพิ่ม' | 613 | tag_added: 'แท็กที่เพิ่ม' |
614 | # tag_renamed: 'Tag renamed' | ||
592 | import: | 615 | import: |
593 | notice: | 616 | notice: |
594 | failed: 'นำข้อมูลเข้าล้มเหลว, ลองใหม่อีกครั้ง' | 617 | failed: 'นำข้อมูลเข้าล้มเหลว, ลองใหม่อีกครั้ง' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml index e2156d47..2f86f25d 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml | |||
@@ -37,6 +37,7 @@ menu: | |||
37 | add_new_entry: 'Yeni bir makale ekle' | 37 | add_new_entry: 'Yeni bir makale ekle' |
38 | search: 'Ara' | 38 | search: 'Ara' |
39 | filter_entries: 'Filtrele' | 39 | filter_entries: 'Filtrele' |
40 | # random_entry: Jump to a random entry from that list | ||
40 | export: 'Dışa Aktar' | 41 | export: 'Dışa Aktar' |
41 | search_form: | 42 | search_form: |
42 | input_label: 'Aramak istediğiniz herhangi bir şey yazın' | 43 | input_label: 'Aramak istediğiniz herhangi bir şey yazın' |
@@ -53,11 +54,12 @@ config: | |||
53 | page_title: 'Yapılandırma' | 54 | page_title: 'Yapılandırma' |
54 | tab_menu: | 55 | tab_menu: |
55 | settings: 'Ayarlar' | 56 | settings: 'Ayarlar' |
56 | rss: 'RSS' | 57 | feed: 'RSS' |
57 | user_info: 'Kullanıcı bilgileri' | 58 | user_info: 'Kullanıcı bilgileri' |
58 | password: 'Şifre' | 59 | password: 'Şifre' |
59 | rules: 'Etiketleme kuralları' | 60 | rules: 'Etiketleme kuralları' |
60 | new_user: 'Bir kullanıcı ekle' | 61 | new_user: 'Bir kullanıcı ekle' |
62 | # reset: 'Reset area' | ||
61 | form: | 63 | form: |
62 | save: 'Kaydet' | 64 | save: 'Kaydet' |
63 | form_settings: | 65 | form_settings: |
@@ -83,25 +85,32 @@ config: | |||
83 | # help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." | 85 | # help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article." |
84 | # help_language: "You can change the language of wallabag interface." | 86 | # help_language: "You can change the language of wallabag interface." |
85 | # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." | 87 | # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." |
86 | form_rss: | 88 | form_feed: |
87 | description: 'wallabag RSS akışı kaydetmiş olduğunuz makalelerini favori RSS okuyucunuzda görüntülemenizi sağlar. Bunu yapabilmek için öncelikle belirteç (token) oluşturmalısınız.' | 89 | description: 'wallabag RSS akışı kaydetmiş olduğunuz makalelerini favori RSS okuyucunuzda görüntülemenizi sağlar. Bunu yapabilmek için öncelikle belirteç (token) oluşturmalısınız.' |
88 | token_label: 'RSS belirteci (token)' | 90 | token_label: 'RSS belirteci (token)' |
89 | no_token: 'Belirteç (token) yok' | 91 | no_token: 'Belirteç (token) yok' |
90 | token_create: 'Yeni belirteç (token) oluştur' | 92 | token_create: 'Yeni belirteç (token) oluştur' |
91 | token_reset: 'Belirteci (token) sıfırla' | 93 | token_reset: 'Belirteci (token) sıfırla' |
92 | rss_links: 'RSS akış bağlantıları' | 94 | feed_links: 'RSS akış bağlantıları' |
93 | rss_link: | 95 | feed_link: |
94 | unread: 'Okunmayan' | 96 | unread: 'Okunmayan' |
95 | starred: 'Favoriler' | 97 | starred: 'Favoriler' |
96 | archive: 'Arşiv' | 98 | archive: 'Arşiv' |
97 | # all: 'All' | 99 | # all: 'All' |
98 | rss_limit: 'RSS içeriğinden talep edilecek makale limiti' | 100 | feed_limit: 'RSS içeriğinden talep edilecek makale limiti' |
99 | form_user: | 101 | form_user: |
100 | two_factor_description: "İki adımlı doğrulamayı aktifleştirdiğinizde, her yeni güvenilmeyen bağlantılarda size e-posta ile bir kod alacaksınız." | 102 | # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." |
101 | name_label: 'İsim' | 103 | name_label: 'İsim' |
102 | email_label: 'E-posta' | 104 | email_label: 'E-posta' |
103 | twoFactorAuthentication_label: 'İki adımlı doğrulama' | 105 | # emailTwoFactor_label: 'Using email (receive a code by email)' |
104 | # help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email." | 106 | # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' |
107 | # table_method: Method | ||
108 | # table_state: State | ||
109 | # table_action: Action | ||
110 | # state_enabled: Enabled | ||
111 | # state_disabled: Disabled | ||
112 | # action_email: Use email | ||
113 | # action_app: Use OTP App | ||
105 | delete: | 114 | delete: |
106 | # title: Delete my account (a.k.a danger zone) | 115 | # title: Delete my account (a.k.a danger zone) |
107 | # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. | 116 | # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. |
@@ -159,6 +168,15 @@ config: | |||
159 | and: 'Bir kural ve diğeri' | 168 | and: 'Bir kural ve diğeri' |
160 | # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' | 169 | # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' |
161 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' | 170 | # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' |
171 | otp: | ||
172 | # page_title: Two-factor authentication | ||
173 | # app: | ||
174 | # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. | ||
175 | # two_factor_code_description_2: 'You can scan that QR Code with your app:' | ||
176 | # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' | ||
177 | # two_factor_code_description_4: 'Test an OTP code from your configured app:' | ||
178 | # cancel: Cancel | ||
179 | # enable: Enable | ||
162 | 180 | ||
163 | entry: | 181 | entry: |
164 | default_title: 'Makalenin başlığı' | 182 | default_title: 'Makalenin başlığı' |
@@ -351,7 +369,7 @@ quickstart: | |||
351 | title: 'Uygulamayı Yapılandırma' | 369 | title: 'Uygulamayı Yapılandırma' |
352 | # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' | 370 | # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.' |
353 | language: 'Dili ve tasarımı değiştirme' | 371 | language: 'Dili ve tasarımı değiştirme' |
354 | rss: 'RSS akışını aktifleştirme' | 372 | feed: 'RSS akışını aktifleştirme' |
355 | # tagging_rules: 'Write rules to automatically tag your articles' | 373 | # tagging_rules: 'Write rules to automatically tag your articles' |
356 | admin: | 374 | admin: |
357 | # title: 'Administration' | 375 | # title: 'Administration' |
@@ -402,6 +420,8 @@ tag: | |||
402 | new: | 420 | new: |
403 | # add: 'Add' | 421 | # add: 'Add' |
404 | # placeholder: 'You can add several tags, separated by a comma.' | 422 | # placeholder: 'You can add several tags, separated by a comma.' |
423 | rename: | ||
424 | # placeholder: 'You can update tag name.' | ||
405 | 425 | ||
406 | # export: | 426 | # export: |
407 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' | 427 | # footer_template: '<div style="text-align:center;"><p>Produced by wallabag with %method%</p><p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p></div>' |
@@ -527,7 +547,8 @@ user: | |||
527 | email_label: 'E-posta' | 547 | email_label: 'E-posta' |
528 | # enabled_label: 'Enabled' | 548 | # enabled_label: 'Enabled' |
529 | # last_login_label: 'Last login' | 549 | # last_login_label: 'Last login' |
530 | # twofactor_label: Two factor authentication | 550 | # twofactor_email_label: Two factor authentication by email |
551 | # twofactor_google_label: Two factor authentication by OTP app | ||
531 | # save: Save | 552 | # save: Save |
532 | # delete: Delete | 553 | # delete: Delete |
533 | # delete_confirm: Are you sure? | 554 | # delete_confirm: Are you sure? |
@@ -545,10 +566,10 @@ flashes: | |||
545 | password_updated: 'Şifre güncellendi' | 566 | password_updated: 'Şifre güncellendi' |
546 | password_not_updated_demo: "In demonstration mode, you can't change password for this user." | 567 | password_not_updated_demo: "In demonstration mode, you can't change password for this user." |
547 | user_updated: 'Bilgiler güncellendi' | 568 | user_updated: 'Bilgiler güncellendi' |
548 | rss_updated: 'RSS bilgiler güncellendi' | 569 | feed_updated: 'RSS bilgiler güncellendi' |
549 | tagging_rules_updated: 'Tagging rules updated' | 570 | tagging_rules_updated: 'Tagging rules updated' |
550 | tagging_rules_deleted: 'Tagging rule deleted' | 571 | tagging_rules_deleted: 'Tagging rule deleted' |
551 | rss_token_updated: 'RSS token updated' | 572 | feed_token_updated: 'RSS token updated' |
552 | # annotations_reset: Annotations reset | 573 | # annotations_reset: Annotations reset |
553 | # tags_reset: Tags reset | 574 | # tags_reset: Tags reset |
554 | # entries_reset: Entries reset | 575 | # entries_reset: Entries reset |
@@ -566,9 +587,11 @@ flashes: | |||
566 | entry_starred: 'Makale favorilere eklendi' | 587 | entry_starred: 'Makale favorilere eklendi' |
567 | entry_unstarred: 'Makale favorilerden çıkartıldı' | 588 | entry_unstarred: 'Makale favorilerden çıkartıldı' |
568 | entry_deleted: 'Makale silindi' | 589 | entry_deleted: 'Makale silindi' |
590 | # no_random_entry: 'No article with these criterias was found' | ||
569 | tag: | 591 | tag: |
570 | notice: | 592 | notice: |
571 | tag_added: 'Etiket eklendi' | 593 | tag_added: 'Etiket eklendi' |
594 | # tag_renamed: 'Tag renamed' | ||
572 | import: | 595 | import: |
573 | notice: | 596 | notice: |
574 | # failed: 'Import failed, please try again.' | 597 | # failed: 'Import failed, please try again.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.da.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.da.yml index c6a84209..c0438978 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.da.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.da.yml | |||
@@ -3,5 +3,5 @@ validator: | |||
3 | password_too_short: 'Adgangskoden skal være mindst 8 tegn' | 3 | password_too_short: 'Adgangskoden skal være mindst 8 tegn' |
4 | # password_wrong_value: 'Wrong value for your current password' | 4 | # password_wrong_value: 'Wrong value for your current password' |
5 | # item_per_page_too_high: 'This will certainly kill the app' | 5 | # item_per_page_too_high: 'This will certainly kill the app' |
6 | # rss_limit_too_high: 'This will certainly kill the app' | 6 | # feed_limit_too_high: 'This will certainly kill the app' |
7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' | 7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.de.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.de.yml index 907b67a5..4c675ef4 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.de.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.de.yml | |||
@@ -3,6 +3,5 @@ validator: | |||
3 | password_too_short: 'Kennwort-Mindestlänge von acht Zeichen nicht erfüllt' | 3 | password_too_short: 'Kennwort-Mindestlänge von acht Zeichen nicht erfüllt' |
4 | password_wrong_value: 'Falscher Wert für dein aktuelles Kennwort' | 4 | password_wrong_value: 'Falscher Wert für dein aktuelles Kennwort' |
5 | item_per_page_too_high: 'Dies wird die Anwendung möglicherweise beenden' | 5 | item_per_page_too_high: 'Dies wird die Anwendung möglicherweise beenden' |
6 | rss_limit_too_high: 'Dies wird die Anwendung möglicherweise beenden' | 6 | feed_limit_too_high: 'Dies wird die Anwendung möglicherweise beenden' |
7 | quote_length_too_high: 'Das Zitat ist zu lang. Es sollte nicht mehr als {{ limit }} Zeichen enthalten.' | 7 | quote_length_too_high: 'Das Zitat ist zu lang. Es sollte nicht mehr als {{ limit }} Zeichen enthalten.' |
8 | |||
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.en.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.en.yml index 8cc117fe..89d4c68a 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.en.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.en.yml | |||
@@ -3,5 +3,5 @@ validator: | |||
3 | password_too_short: 'Password should by at least 8 chars long' | 3 | password_too_short: 'Password should by at least 8 chars long' |
4 | password_wrong_value: 'Wrong value for your current password' | 4 | password_wrong_value: 'Wrong value for your current password' |
5 | item_per_page_too_high: 'This will certainly kill the app' | 5 | item_per_page_too_high: 'This will certainly kill the app' |
6 | rss_limit_too_high: 'This will certainly kill the app' | 6 | feed_limit_too_high: 'This will certainly kill the app' |
7 | quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' | 7 | quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.es.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.es.yml index 97a8edfa..ba34ee76 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.es.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.es.yml | |||
@@ -3,5 +3,5 @@ validator: | |||
3 | password_too_short: 'La contraseña debe tener al menos 8 carácteres' | 3 | password_too_short: 'La contraseña debe tener al menos 8 carácteres' |
4 | password_wrong_value: 'Entrada equivocada para su contraseña actual' | 4 | password_wrong_value: 'Entrada equivocada para su contraseña actual' |
5 | item_per_page_too_high: 'Esto matará la aplicación' | 5 | item_per_page_too_high: 'Esto matará la aplicación' |
6 | rss_limit_too_high: 'Esto matará la aplicación' | 6 | feed_limit_too_high: 'Esto matará la aplicación' |
7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' | 7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.fa.yml index ef677525..9b1a4af2 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.fa.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.fa.yml | |||
@@ -3,5 +3,5 @@ validator: | |||
3 | password_too_short: 'رمز شما باید ۸ حرف یا بیشتر باشد' | 3 | password_too_short: 'رمز شما باید ۸ حرف یا بیشتر باشد' |
4 | password_wrong_value: 'رمز فعلی را اشتباه وارد کردهاید' | 4 | password_wrong_value: 'رمز فعلی را اشتباه وارد کردهاید' |
5 | item_per_page_too_high: 'با این تعداد برنامه به فنا میرود' | 5 | item_per_page_too_high: 'با این تعداد برنامه به فنا میرود' |
6 | rss_limit_too_high: 'با این تعداد برنامه به فنا میرود' | 6 | feed_limit_too_high: 'با این تعداد برنامه به فنا میرود' |
7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' | 7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.fr.yml index f31b4ed2..92f69aa0 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.fr.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.fr.yml | |||
@@ -3,5 +3,5 @@ validator: | |||
3 | password_too_short: "Le mot de passe doit contenir au moins 8 caractères" | 3 | password_too_short: "Le mot de passe doit contenir au moins 8 caractères" |
4 | password_wrong_value: "Votre mot de passe actuel est faux" | 4 | password_wrong_value: "Votre mot de passe actuel est faux" |
5 | item_per_page_too_high: "Ça ne va pas plaire à l’application" | 5 | item_per_page_too_high: "Ça ne va pas plaire à l’application" |
6 | rss_limit_too_high: "Ça ne va pas plaire à l’application" | 6 | feed_limit_too_high: "Ça ne va pas plaire à l’application" |
7 | quote_length_too_high: "La citation est trop longue. Elle doit avoir au maximum {{ limit }} caractères." | 7 | quote_length_too_high: "La citation est trop longue. Elle doit avoir au maximum {{ limit }} caractères." |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.it.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.it.yml index d949cc3b..b20d6f51 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.it.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.it.yml | |||
@@ -3,5 +3,5 @@ validator: | |||
3 | password_too_short: 'La password deve essere lunga almeno 8 caratteri' | 3 | password_too_short: 'La password deve essere lunga almeno 8 caratteri' |
4 | password_wrong_value: 'Valore inserito per la password corrente errato' | 4 | password_wrong_value: 'Valore inserito per la password corrente errato' |
5 | item_per_page_too_high: 'Questo valore è troppo alto' | 5 | item_per_page_too_high: 'Questo valore è troppo alto' |
6 | rss_limit_too_high: 'Questo valore è troppo alto' | 6 | feed_limit_too_high: 'Questo valore è troppo alto' |
7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' | 7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.oc.yml index 87f00f10..cb57844f 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.oc.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.oc.yml | |||
@@ -3,5 +3,5 @@ validator: | |||
3 | password_too_short: 'Lo senhal deu aver almens 8 caractèrs' | 3 | password_too_short: 'Lo senhal deu aver almens 8 caractèrs' |
4 | password_wrong_value: 'Vòstre senhal actual es pas bon' | 4 | password_wrong_value: 'Vòstre senhal actual es pas bon' |
5 | item_per_page_too_high: "Aquò li agradarà pas a l'aplicacion" | 5 | item_per_page_too_high: "Aquò li agradarà pas a l'aplicacion" |
6 | rss_limit_too_high: "Aquò li agradarà pas a l'aplicacion" | 6 | feed_limit_too_high: "Aquò li agradarà pas a l'aplicacion" |
7 | quote_length_too_high: 'Aquesta citacion es tròpa longa. Cal que faga {{ limit }} caractèrs o mens.' | 7 | quote_length_too_high: 'Aquesta citacion es tròpa longa. Cal que faga {{ limit }} caractèrs o mens.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.pl.yml index e4165c14..94757cc5 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.pl.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.pl.yml | |||
@@ -3,5 +3,5 @@ validator: | |||
3 | password_too_short: 'Hasło powinno mieć minimum 8 znaków długości' | 3 | password_too_short: 'Hasło powinno mieć minimum 8 znaków długości' |
4 | password_wrong_value: 'Twoje obecne hasło jest błędne' | 4 | password_wrong_value: 'Twoje obecne hasło jest błędne' |
5 | item_per_page_too_high: 'To może spowodować problemy z aplikacją' | 5 | item_per_page_too_high: 'To może spowodować problemy z aplikacją' |
6 | rss_limit_too_high: 'To może spowodować problemy z aplikacją' | 6 | feed_limit_too_high: 'To może spowodować problemy z aplikacją' |
7 | quote_length_too_high: 'Cytat jest zbyt długi. powinien mieć {{ limit }} znaków lub mniej.' | 7 | quote_length_too_high: 'Cytat jest zbyt długi. powinien mieć {{ limit }} znaków lub mniej.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml index a8c1f9de..df2f3f35 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml | |||
@@ -3,5 +3,5 @@ validator: | |||
3 | password_too_short: 'A senha deve ter pelo menos 8 caracteres' | 3 | password_too_short: 'A senha deve ter pelo menos 8 caracteres' |
4 | password_wrong_value: 'A senha atual informada está errada' | 4 | password_wrong_value: 'A senha atual informada está errada' |
5 | item_per_page_too_high: 'Certamente isso pode matar a aplicação' | 5 | item_per_page_too_high: 'Certamente isso pode matar a aplicação' |
6 | rss_limit_too_high: 'Certamente isso pode matar a aplicação' | 6 | feed_limit_too_high: 'Certamente isso pode matar a aplicação' |
7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' | 7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.ro.yml index 6840cf11..e5c8a72f 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.ro.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.ro.yml | |||
@@ -3,5 +3,5 @@ validator: | |||
3 | password_too_short: 'Parola ar trebui să conțină cel puțin 8 caractere' | 3 | password_too_short: 'Parola ar trebui să conțină cel puțin 8 caractere' |
4 | # password_wrong_value: 'Wrong value for your current password' | 4 | # password_wrong_value: 'Wrong value for your current password' |
5 | # item_per_page_too_high: 'This will certainly kill the app' | 5 | # item_per_page_too_high: 'This will certainly kill the app' |
6 | # rss_limit_too_high: 'This will certainly kill the app' | 6 | # feed_limit_too_high: 'This will certainly kill the app' |
7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' | 7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.tr.yml index e1e7317f..881ffd3b 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/validators.tr.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/validators.tr.yml | |||
@@ -3,5 +3,5 @@ validator: | |||
3 | # password_too_short: 'Password should by at least 8 chars long' | 3 | # password_too_short: 'Password should by at least 8 chars long' |
4 | # password_wrong_value: 'Wrong value for your current password' | 4 | # password_wrong_value: 'Wrong value for your current password' |
5 | # item_per_page_too_high: 'This will certainly kill the app' | 5 | # item_per_page_too_high: 'This will certainly kill the app' |
6 | # rss_limit_too_high: 'This will certainly kill the app' | 6 | # feed_limit_too_high: 'This will certainly kill the app' |
7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' | 7 | # quote_length_too_high: 'The quote is too long. It should have {{ limit }} characters or less.' |
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 bcc57dac..4ef6ab3c 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 | |||
@@ -86,8 +86,7 @@ | |||
86 | <br/> | 86 | <br/> |
87 | <img id="androidQrcode" /> | 87 | <img id="androidQrcode" /> |
88 | <script> | 88 | <script> |
89 | const imgBase64 = jrQrcode.getQrBase64('wallabag://{{ app.user.username }}@{{ wallabag_url }}'); | 89 | document.getElementById('androidQrcode').src = jrQrcode.getQrBase64('wallabag://{{ app.user.username }}@{{ wallabag_url }}'); |
90 | document.getElementById('androidQrcode').src = imgBase64; | ||
91 | </script> | 90 | </script> |
92 | </div> | 91 | </div> |
93 | </fieldset> | 92 | </fieldset> |
@@ -95,43 +94,43 @@ | |||
95 | {{ form_rest(form.config) }} | 94 | {{ form_rest(form.config) }} |
96 | </form> | 95 | </form> |
97 | 96 | ||
98 | <h2>{{ 'config.tab_menu.rss'|trans }}</h2> | 97 | <h2>{{ 'config.tab_menu.feed'|trans }}</h2> |
99 | 98 | ||
100 | {{ form_start(form.rss) }} | 99 | {{ form_start(form.feed) }} |
101 | {{ form_errors(form.rss) }} | 100 | {{ form_errors(form.feed) }} |
102 | 101 | ||
103 | <div class="row"> | 102 | <div class="row"> |
104 | {{ 'config.form_rss.description'|trans }} | 103 | {{ 'config.form_feed.description'|trans }} |
105 | </div> | 104 | </div> |
106 | 105 | ||
107 | <fieldset class="w500p inline"> | 106 | <fieldset class="w500p inline"> |
108 | <div class="row"> | 107 | <div class="row"> |
109 | <label>{{ 'config.form_rss.token_label'|trans }}</label> | 108 | <label>{{ 'config.form_feed.token_label'|trans }}</label> |
110 | {% if rss.token %} | 109 | {% if feed.token %} |
111 | {{ rss.token }} | 110 | {{ feed.token }} |
112 | {% else %} | 111 | {% else %} |
113 | <em>{{ 'config.form_rss.no_token'|trans }}</em> | 112 | <em>{{ 'config.form_feed.no_token'|trans }}</em> |
114 | {% endif %} | 113 | {% endif %} |
115 | – | 114 | – |
116 | <a href="{{ path('generate_token') }}"> | 115 | <a href="{{ path('generate_token') }}"> |
117 | {% if rss.token %} | 116 | {% if feed.token %} |
118 | {{ 'config.form_rss.token_reset'|trans }} | 117 | {{ 'config.form_feed.token_reset'|trans }} |
119 | {% else %} | 118 | {% else %} |
120 | {{ 'config.form_rss.token_create'|trans }} | 119 | {{ 'config.form_feed.token_create'|trans }} |
121 | {% endif %} | 120 | {% endif %} |
122 | </a> | 121 | </a> |
123 | </div> | 122 | </div> |
124 | </fieldset> | 123 | </fieldset> |
125 | 124 | ||
126 | {% if rss.token %} | 125 | {% if feed.token %} |
127 | <fieldset class="w500p inline"> | 126 | <fieldset class="w500p inline"> |
128 | <div class="row"> | 127 | <div class="row"> |
129 | <label>{{ 'config.form_rss.rss_links'|trans }}</label> | 128 | <label>{{ 'config.form_feed.feed_links'|trans }}</label> |
130 | <ul> | 129 | <ul> |
131 | <li><a href="{{ path('unread_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.unread'|trans }}</a></li> | 130 | <li><a href="{{ path('unread_feed', {'username': feed.username, 'token': feed.token}) }}">{{ 'config.form_feed.feed_link.unread'|trans }}</a></li> |
132 | <li><a href="{{ path('starred_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.starred'|trans }}</a></li> | 131 | <li><a href="{{ path('starred_feed', {'username': feed.username, 'token': feed.token}) }}">{{ 'config.form_feed.feed_link.starred'|trans }}</a></li> |
133 | <li><a href="{{ path('archive_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.archive'|trans }}</a></li> | 132 | <li><a href="{{ path('archive_feed', {'username': feed.username, 'token': feed.token}) }}">{{ 'config.form_feed.feed_link.archive'|trans }}</a></li> |
134 | <li><a href="{{ path('all_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.all'|trans }}</a></li> | 133 | <li><a href="{{ path('all_feed', {'username': feed.username, 'token': feed.token}) }}">{{ 'config.form_feed.feed_link.all'|trans }}</a></li> |
135 | </ul> | 134 | </ul> |
136 | </div> | 135 | </div> |
137 | </fieldset> | 136 | </fieldset> |
@@ -139,13 +138,13 @@ | |||
139 | 138 | ||
140 | <fieldset class="w500p inline"> | 139 | <fieldset class="w500p inline"> |
141 | <div class="row"> | 140 | <div class="row"> |
142 | {{ form_label(form.rss.rss_limit) }} | 141 | {{ form_label(form.feed.feed_limit) }} |
143 | {{ form_errors(form.rss.rss_limit) }} | 142 | {{ form_errors(form.feed.feed_limit) }} |
144 | {{ form_widget(form.rss.rss_limit) }} | 143 | {{ form_widget(form.feed.feed_limit) }} |
145 | </div> | 144 | </div> |
146 | </fieldset> | 145 | </fieldset> |
147 | 146 | ||
148 | {{ form_rest(form.rss) }} | 147 | {{ form_rest(form.feed) }} |
149 | </form> | 148 | </form> |
150 | 149 | ||
151 | <h2>{{ 'config.tab_menu.user_info'|trans }}</h2> | 150 | <h2>{{ 'config.tab_menu.user_info'|trans }}</h2> |
@@ -169,52 +168,41 @@ | |||
169 | </div> | 168 | </div> |
170 | </fieldset> | 169 | </fieldset> |
171 | 170 | ||
171 | {{ form_widget(form.user.save) }} | ||
172 | |||
172 | {% if twofactor_auth %} | 173 | {% if twofactor_auth %} |
174 | <h5>{{ 'config.otp.page_title'|trans }}</h5> | ||
175 | |||
173 | <div class="row"> | 176 | <div class="row"> |
174 | {{ 'config.form_user.two_factor_description'|trans }} | 177 | {{ 'config.form_user.two_factor_description'|trans }} |
175 | </div> | 178 | </div> |
176 | 179 | ||
177 | <fieldset class="w500p inline"> | 180 | <table> |
178 | <div class="row"> | 181 | <thead> |
179 | {{ form_label(form.user.twoFactorAuthentication) }} | 182 | <tr> |
180 | {{ form_errors(form.user.twoFactorAuthentication) }} | 183 | <th>{{ 'config.form_user.two_factor.table_method'|trans }}</th> |
181 | {{ form_widget(form.user.twoFactorAuthentication) }} | 184 | <th>{{ 'config.form_user.two_factor.table_state'|trans }}</th> |
182 | </div> | 185 | <th>{{ 'config.form_user.two_factor.table_action'|trans }}</th> |
183 | <a href="#" title="{{ 'config.form_user.help_twoFactorAuthentication'|trans }}"> | 186 | </tr> |
184 | <i class="material-icons">live_help</i> | 187 | </thead> |
185 | </a> | ||
186 | </fieldset> | ||
187 | {% endif %} | ||
188 | 188 | ||
189 | <h2>{{ 'config.reset.title'|trans }}</h2> | 189 | <tbody> |
190 | <fieldset class="w500p inline"> | 190 | <tr> |
191 | <p>{{ 'config.reset.description'|trans }}</p> | 191 | <td>{{ 'config.form_user.two_factor.emailTwoFactor_label'|trans }}</td> |
192 | <ul> | 192 | <td>{% if app.user.isEmailTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td> |
193 | <li> | 193 | <td><a href="{{ path('config_otp_email') }}" class="waves-effect waves-light btn{% if app.user.isEmailTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_email'|trans }}</a></td> |
194 | <a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | 194 | </tr> |
195 | {{ 'config.reset.annotations'|trans }} | 195 | <tr> |
196 | </a> | 196 | <td>{{ 'config.form_user.two_factor.googleTwoFactor_label'|trans }}</td> |
197 | </li> | 197 | <td>{% if app.user.isGoogleTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td> |
198 | <li> | 198 | <td><a href="{{ path('config_otp_app') }}" class="waves-effect waves-light btn{% if app.user.isGoogleTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_app'|trans }}</a></td> |
199 | <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | 199 | </tr> |
200 | {{ 'config.reset.tags'|trans }} | 200 | </tbody> |
201 | </a> | 201 | </table> |
202 | </li> | 202 | |
203 | <li> | 203 | {% endif %} |
204 | <a href="{{ path('config_reset', { type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
205 | {{ 'config.reset.archived'|trans }} | ||
206 | </a> | ||
207 | </li> | ||
208 | <li> | ||
209 | <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
210 | {{ 'config.reset.entries'|trans }} | ||
211 | </a> | ||
212 | </li> | ||
213 | </ul> | ||
214 | </fieldset> | ||
215 | 204 | ||
216 | {{ form_widget(form.user._token) }} | 205 | {{ form_widget(form.user._token) }} |
217 | {{ form_widget(form.user.save) }} | ||
218 | </form> | 206 | </form> |
219 | 207 | ||
220 | {% if enabled_users > 1 %} | 208 | {% if enabled_users > 1 %} |
@@ -277,7 +265,7 @@ | |||
277 | {% endfor %} | 265 | {% endfor %} |
278 | </ul> | 266 | </ul> |
279 | 267 | ||
280 | {{ form_start(form.new_tagging_rule) }} | 268 | {{ form_start(form.new_tagging_rule) }} |
281 | {{ form_errors(form.new_tagging_rule) }} | 269 | {{ form_errors(form.new_tagging_rule) }} |
282 | 270 | ||
283 | <fieldset class="w500p inline"> | 271 | <fieldset class="w500p inline"> |
@@ -382,4 +370,31 @@ | |||
382 | </table> | 370 | </table> |
383 | </div> | 371 | </div> |
384 | </div> | 372 | </div> |
373 | |||
374 | <h2>{{ 'config.reset.title'|trans }}</h2> | ||
375 | <fieldset class="w500p inline"> | ||
376 | <p>{{ 'config.reset.description'|trans }}</p> | ||
377 | <ul> | ||
378 | <li> | ||
379 | <a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
380 | {{ 'config.reset.annotations'|trans }} | ||
381 | </a> | ||
382 | </li> | ||
383 | <li> | ||
384 | <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
385 | {{ 'config.reset.tags'|trans }} | ||
386 | </a> | ||
387 | </li> | ||
388 | <li> | ||
389 | <a href="{{ path('config_reset', { type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
390 | {{ 'config.reset.archived'|trans }} | ||
391 | </a> | ||
392 | </li> | ||
393 | <li> | ||
394 | <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
395 | {{ 'config.reset.entries'|trans }} | ||
396 | </a> | ||
397 | </li> | ||
398 | </ul> | ||
399 | </fieldset> | ||
385 | {% endblock %} | 400 | {% endblock %} |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/otp_app.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/otp_app.html.twig new file mode 100644 index 00000000..0919646e --- /dev/null +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/otp_app.html.twig | |||
@@ -0,0 +1,55 @@ | |||
1 | {% extends "WallabagCoreBundle::layout.html.twig" %} | ||
2 | |||
3 | {% block title %}{{ 'config.page_title'|trans }} > {{ 'config.otp.page_title'|trans }}{% endblock %} | ||
4 | |||
5 | {% block content %} | ||
6 | <h5>{{ 'config.otp.page_title'|trans }}</h5> | ||
7 | |||
8 | <ol> | ||
9 | <li> | ||
10 | <p>{{ 'config.otp.app.two_factor_code_description_1'|trans }}</p> | ||
11 | <p>{{ 'config.otp.app.two_factor_code_description_2'|trans }}</p> | ||
12 | |||
13 | <p> | ||
14 | <img id="2faQrcode" class="hide-on-med-and-down" /> | ||
15 | <script> | ||
16 | document.getElementById('2faQrcode').src = jrQrcode.getQrBase64('{{ qr_code }}'); | ||
17 | </script> | ||
18 | </p> | ||
19 | </li> | ||
20 | <li> | ||
21 | <p>{{ 'config.otp.app.two_factor_code_description_3'|trans }}</p> | ||
22 | |||
23 | <p><strong>{{ backupCodes|join("\n")|nl2br }}</strong></p> | ||
24 | </li> | ||
25 | <li> | ||
26 | <p>{{ 'config.otp.app.two_factor_code_description_4'|trans }}</p> | ||
27 | |||
28 | {% for flashMessage in app.session.flashbag.get("two_factor") %} | ||
29 | <div class="card-panel red darken-1 black-text"> | ||
30 | {{ flashMessage|trans }} | ||
31 | </div> | ||
32 | {% endfor %} | ||
33 | |||
34 | <form class="form" action="{{ path("config_otp_app_check") }}" method="post"> | ||
35 | <div class="card-content"> | ||
36 | <div class="row"> | ||
37 | <div class="input-field col s12"> | ||
38 | <label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label> | ||
39 | <input id="_auth_code" type="text" autocomplete="off" name="_auth_code" /> | ||
40 | </div> | ||
41 | </div> | ||
42 | </div> | ||
43 | <div class="card-action"> | ||
44 | <a href="{{ path('config_otp_app_cancel') }}" class="waves-effect waves-light grey btn"> | ||
45 | {{ 'config.otp.app.cancel'|trans }} | ||
46 | </a> | ||
47 | <button class="btn waves-effect waves-light" type="submit" name="send"> | ||
48 | {{ 'config.otp.app.enable'|trans }} | ||
49 | <i class="material-icons right">send</i> | ||
50 | </button> | ||
51 | </div> | ||
52 | </form> | ||
53 | </li> | ||
54 | </ol> | ||
55 | {% endblock %} | ||
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 832112be..6c5d2601 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 | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | {% block head %} | 3 | {% block head %} |
4 | {{ parent() }} | 4 | {{ parent() }} |
5 | {% if tag is defined and app.user.config.rssToken %} | 5 | {% if tag is defined and app.user.config.feedToken %} |
6 | <link rel="alternate" type="application/rss+xml" href="{{ path('tag_rss', {'username': app.user.username, 'token': app.user.config.rssToken, 'slug': tag.slug}) }}" /> | 6 | <link rel="alternate" type="application/atom+xml" href="{{ path('tag_feed', {'username': app.user.username, 'token': app.user.config.feedToken, 'slug': tag.slug}) }}" /> |
7 | {% endif %} | 7 | {% endif %} |
8 | {% endblock %} | 8 | {% endblock %} |
9 | 9 | ||
@@ -20,13 +20,19 @@ | |||
20 | 20 | ||
21 | {% block content %} | 21 | {% block content %} |
22 | {% set currentRoute = app.request.attributes.get('_route') %} | 22 | {% set currentRoute = app.request.attributes.get('_route') %} |
23 | {% if currentRoute == 'homepage' %} | ||
24 | {% set currentRoute = 'unread' %} | ||
25 | {% endif %} | ||
23 | {% set listMode = app.user.config.listMode %} | 26 | {% set listMode = app.user.config.listMode %} |
24 | <div class="results"> | 27 | <div class="results"> |
25 | <div class="nb-results">{{ 'entry.list.number_on_the_page'|transchoice(entries.count) }}</div> | 28 | <div class="nb-results">{{ 'entry.list.number_on_the_page'|transchoice(entries.count) }}</div> |
26 | <div class="pagination"> | 29 | <div class="pagination"> |
27 | <a href="{{ path('switch_view_mode') }}"><i class="listMode-btn material-icons md-24">{% if listMode == 0 %}list{% else %}view_module{% endif %}</i></a> | 30 | <a href="{{ path('switch_view_mode') }}"><i class="listMode-btn material-icons md-24">{% if listMode == 0 %}list{% else %}view_module{% endif %}</i></a> |
28 | {% if app.user.config.rssToken %} | 31 | {% if app.user.config.feedToken %} |
29 | {% include "@WallabagCore/themes/common/Entry/_rss_link.html.twig" %} | 32 | {% include "@WallabagCore/themes/common/Entry/_feed_link.html.twig" %} |
33 | {% endif %} | ||
34 | {% if currentRoute in ['unread', 'starred', 'archive', 'untagged', 'all'] %} | ||
35 | <a href="{{ path('random_entry', { 'type': currentRoute }) }}"><i class="btn-clickable material-icons md-24 js-random-action">casino</i></a> | ||
30 | {% endif %} | 36 | {% endif %} |
31 | <i class="btn-clickable download-btn material-icons md-24 js-export-action">file_download</i> | 37 | <i class="btn-clickable download-btn material-icons md-24 js-export-action">file_download</i> |
32 | <i class="btn-clickable filter-btn material-icons md-24 js-filters-action">filter_list</i> | 38 | <i class="btn-clickable filter-btn material-icons md-24 js-filters-action">filter_list</i> |
@@ -90,9 +96,6 @@ | |||
90 | {% if tag is defined %} | 96 | {% if tag is defined %} |
91 | {% set currentTag = tag %} | 97 | {% set currentTag = tag %} |
92 | {% endif %} | 98 | {% endif %} |
93 | {% if currentRoute == 'homepage' %} | ||
94 | {% set currentRoute = 'unread' %} | ||
95 | {% endif %} | ||
96 | <h2>{{ 'entry.list.export_title'|trans }}</h2> | 99 | <h2>{{ 'entry.list.export_title'|trans }}</h2> |
97 | <a href="javascript: void(null);" id="download-form-close" class="close-button--popup close-button">×</a> | 100 | <a href="javascript: void(null);" id="download-form-close" class="close-button--popup close-button">×</a> |
98 | <ul> | 101 | <ul> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Tag/tags.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Tag/tags.html.twig index 070d5629..ae8403bd 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Tag/tags.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Tag/tags.html.twig | |||
@@ -10,10 +10,22 @@ | |||
10 | <ul> | 10 | <ul> |
11 | {% for tag in tags %} | 11 | {% for tag in tags %} |
12 | <li id="tag-{{ tag.id|e }}"> | 12 | <li id="tag-{{ tag.id|e }}"> |
13 | <a href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{tag.label}} ({{ tag.nbEntries }})</a> | 13 | <a href="{{ path('tag_entries', {'slug': tag.slug}) }}" data-handle="tag-link">{{ tag.label }} ({{ tag.nbEntries }})</a> |
14 | <a rel="alternate" type="application/rss+xml" href="{{ path('tag_rss', {'username': app.user.username, 'token': app.user.config.rssToken, 'slug': tag.slug}) }}" class="right"> | 14 | |
15 | <i class="material-icons md-24">rss_feed</i> | 15 | {% if renameForms is defined and renameForms[tag.id] is defined %} |
16 | <form class="card-tag-form hidden" data-handle="tag-rename-form" action="{{ path('tag_rename', {'slug': tag.slug})}}" method="POST"> | ||
17 | {{ form_widget(renameForms[tag.id].label, {'attr': {'value': tag.label}}) }} | ||
18 | {{ form_rest(renameForms[tag.id]) }} | ||
19 | </form> | ||
20 | <a class="card-tag-rename" data-handler="tag-rename" href="javascript:void(0);"> | ||
21 | <i class="material-icons">mode_edit</i> | ||
16 | </a> | 22 | </a> |
23 | {% endif %} | ||
24 | {% if app.user.config.feedToken %} | ||
25 | <a rel="alternate" type="application/atom+xml" href="{{ path('tag_feed', {'username': app.user.username, 'token': app.user.config.feedToken, 'slug': tag.slug}) }}" class="right"> | ||
26 | <i class="material-icons md-24">rss_feed</i> | ||
27 | </a> | ||
28 | {% endif %} | ||
17 | </li> | 29 | </li> |
18 | {% endfor %} | 30 | {% endfor %} |
19 | </ul> | 31 | </ul> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_feed_link.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_feed_link.html.twig new file mode 100644 index 00000000..6df4c160 --- /dev/null +++ b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_feed_link.html.twig | |||
@@ -0,0 +1,11 @@ | |||
1 | {% if tag is defined %} | ||
2 | <a rel="alternate" type="application/atom+xml" href="{{ path('tag_feed', {'username': app.user.username, 'token': app.user.config.feedToken, 'slug': tag.slug}) }}" class="right"><i class="material-icons md-24">rss_feed</i></a> | ||
3 | {% elseif currentRoute in ['homepage', 'unread', 'starred', 'archive', 'all'] %} | ||
4 | {% set feedRoute = currentRoute %} | ||
5 | {% if currentRoute == 'homepage' %} | ||
6 | {% set feedRoute = 'unread' %} | ||
7 | {% endif %} | ||
8 | {% set feedRoute = feedRoute ~ '_feed' %} | ||
9 | |||
10 | <a rel="alternate" type="application/atom+xml" href="{{ path(feedRoute, {'username': app.user.username, 'token': app.user.config.feedToken}) }}" class="right"><i class="material-icons">rss_feed</i></a> | ||
11 | {% endif %} | ||
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_rss_link.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_rss_link.html.twig deleted file mode 100644 index eb26054c..00000000 --- a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_rss_link.html.twig +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | {% if tag is defined %} | ||
2 | <a rel="alternate" type="application/rss+xml" href="{{ path('tag_rss', {'username': app.user.username, 'token': app.user.config.rssToken, 'slug': tag.slug}) }}" class="right"><i class="material-icons md-24">rss_feed</i></a> | ||
3 | {% elseif currentRoute in ['homepage', 'unread', 'starred', 'archive', 'all'] %} | ||
4 | {% set rssRoute = currentRoute %} | ||
5 | {% if currentRoute == 'homepage' %} | ||
6 | {% set rssRoute = 'unread' %} | ||
7 | {% endif %} | ||
8 | {% set rssRoute = rssRoute ~ '_rss' %} | ||
9 | |||
10 | <a rel="alternate" type="application/rss+xml" href="{{ path(rssRoute, {'username': app.user.username, 'token': app.user.config.rssToken}) }}" class="right"><i class="material-icons">rss_feed</i></a> | ||
11 | {% endif %} | ||
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/entries.xml.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/entries.xml.twig index 25d09ec3..cf6f6571 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/entries.xml.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/entries.xml.twig | |||
@@ -1,34 +1,53 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
2 | <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/"> | 2 | <feed xmlns="http://www.w3.org/2005/Atom"> |
3 | <channel> | 3 | {% if type != 'tag' %} |
4 | <title>wallabag - {{ type }} feed</title> | 4 | <title>wallabag — {{type}} feed</title> |
5 | <link>{{ url_html }}</link> | 5 | <subtitle type="html">Atom feed for {{ type }} entries</subtitle> |
6 | <link rel="self" href="{{ app.request.uri }}"/> | 6 | <id>wallabag:{{ domainName | removeScheme | removeWww }}:{{ user }}:{{ type }}</id> |
7 | {% if entries.hasPreviousPage -%} | 7 | <link rel="alternate" type="text/html" href="{{ url(type) }}"/> |
8 | <link rel="previous" href="{{ url }}?page={{ entries.previousPage }}"/> | 8 | {% else %} |
9 | {% endif -%} | 9 | <id>wallabag:{{ domainName | removeScheme | removeWww }}:{{ user }}:{{ type }}:{{ tag }}</id> |
10 | {% if entries.hasNextPage -%} | 10 | <link rel="alternate" type="text/html" href="{{ url('tag_entries', {'slug': tag}) }}"/> |
11 | <link rel="next" href="{{ url }}?page={{ entries.nextPage }}"/> | 11 | <title>wallabag — {{type}} {{ tag }} feed</title> |
12 | {% endif -%} | 12 | <subtitle type="html">Atom feed for entries tagged with {{ tag }}</subtitle> |
13 | <link rel="last" href="{{ url }}?page={{ entries.nbPages }}"/> | 13 | {% endif %} |
14 | <pubDate>{{ "now"|date(constant('DATE_RSS')) }}</pubDate> | 14 | {% if entries | length > 0 %} |
15 | <generator>wallabag</generator> | 15 | <updated>{{ (entries | first).createdAt | date('c') }}</updated> {# Indicates the last time the feed was modified in a significant way. #} |
16 | <description>wallabag {{ type }} elements</description> | 16 | {% endif %} |
17 | 17 | <link rel="self" type="application/atom+xml" href="{{ app.request.uri }}"/> | |
18 | {% for entry in entries %} | 18 | {% if entries.hasPreviousPage %} |
19 | 19 | <link rel="previous" href="{{ url }}/{{ entries.previousPage }}"/> | |
20 | <item> | 20 | {% endif -%} |
21 | <title><![CDATA[{{ entry.title|e }}]]></title> | 21 | {% if entries.hasNextPage %} |
22 | <source url="{{ url('view', { 'id': entry.id }) }}">wallabag</source> | 22 | <link rel="next" href="{{ url }}/{{ entries.nextPage }}"/> |
23 | <link>{{ entry.url }}</link> | 23 | {% endif -%} |
24 | <guid>{{ entry.url }}</guid> | 24 | <link rel="last" href="{{ url }}/{{ entries.nbPages }}"/> |
25 | <pubDate>{{ entry.createdAt|date(constant('DATE_RSS')) }}</pubDate> | 25 | <generator uri="https://wallabag.org" version="{{ version }}">wallabag</generator> |
26 | <description> | 26 | <author> |
27 | <![CDATA[{%- if entry.readingTime > 0 -%}{{ 'entry.list.reading_time_minutes'|trans({'%readingTime%': entry.readingTime}) }}{%- else -%}{{ 'entry.list.reading_time_less_one_minute'|trans|raw }}{%- endif %}{{ entry.content|raw -}}]]> | 27 | <name>{{ user }}</name> |
28 | </description> | 28 | </author> |
29 | </item> | 29 | <icon>{{ asset('favicon.ico') }}</icon> |
30 | 30 | <logo>{{ asset('bundles/wallabagcore/themes/_global/img/logo-square.png') }}</logo> | |
31 | {% for entry in entries %} | ||
32 | <entry> | ||
33 | <title><![CDATA[{{ entry.title|e }}]]></title> | ||
34 | <link rel="alternate" type="text/html" | ||
35 | href="{{ url('view', {'id': entry.id}) }}"/> | ||
36 | <link rel="via">{{ entry.url }}</link> | ||
37 | <id>wallabag:{{ domainName | removeScheme | removeWww }}:{{ user }}:entry:{{ entry.id }}</id> | ||
38 | <updated>{{ entry.updatedAt|date('c') }}</updated> | ||
39 | <published>{{ entry.createdAt|date('c') }}</published> | ||
40 | {% for tag in entry.tags %} | ||
41 | <category term="{{ tag.slug }}" label="{{ tag.label }}" /> | ||
31 | {% endfor %} | 42 | {% endfor %} |
32 | 43 | {% for author in entry.publishedBy %} | |
33 | </channel> | 44 | <author> |
34 | </rss> | 45 | <name>{{ author }}</name> |
46 | </author> | ||
47 | {% endfor %} | ||
48 | <content type="html" {% if entry.language %}xml:lang="{{ entry.language[:2] }}"{% endif %}> | ||
49 | <![CDATA[{%- if entry.readingTime > 0 -%}{{ 'entry.list.reading_time_minutes'|trans({'%readingTime%': entry.readingTime}) }}{%- else -%}{{ 'entry.list.reading_time_less_one_minute'|trans|raw }}{%- endif %}{{ entry.content|raw -}}]]> | ||
50 | </content> | ||
51 | </entry> | ||
52 | {% endfor %} | ||
53 | </feed> | ||
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Static/quickstart.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Static/quickstart.html.twig index 4580813c..521b3eea 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/common/Static/quickstart.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/common/Static/quickstart.html.twig | |||
@@ -21,7 +21,7 @@ | |||
21 | <div class="card-action"> | 21 | <div class="card-action"> |
22 | <ul> | 22 | <ul> |
23 | <li><a href="{{ path('config') }}">{{ 'quickstart.configure.language'|trans }}</a></li> | 23 | <li><a href="{{ path('config') }}">{{ 'quickstart.configure.language'|trans }}</a></li> |
24 | <li><a href="{{ path('config') }}#set2">{{ 'quickstart.configure.rss'|trans }}</a></li> | 24 | <li><a href="{{ path('config') }}#set2">{{ 'quickstart.configure.feed'|trans }}</a></li> |
25 | <li><a href="{{ path('config') }}#set5">{{ 'quickstart.more'|trans }}</a></li> | 25 | <li><a href="{{ path('config') }}#set5">{{ 'quickstart.more'|trans }}</a></li> |
26 | </ul> | 26 | </ul> |
27 | </div> | 27 | </div> |
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 f896fe2d..818fc4e7 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 | |||
@@ -12,10 +12,11 @@ | |||
12 | <div class="div_tabs col s12"> | 12 | <div class="div_tabs col s12"> |
13 | <ul class="tabs"> | 13 | <ul class="tabs"> |
14 | <li class="tab col s12 m6 l3"><a class="active" href="#set1">{{ 'config.tab_menu.settings'|trans }}</a></li> | 14 | <li class="tab col s12 m6 l3"><a class="active" href="#set1">{{ 'config.tab_menu.settings'|trans }}</a></li> |
15 | <li class="tab col s12 m6 l3"><a href="#set2">{{ 'config.tab_menu.rss'|trans }}</a></li> | 15 | <li class="tab col s12 m6 l3"><a href="#set2">{{ 'config.tab_menu.feed'|trans }}</a></li> |
16 | <li class="tab col s12 m6 l3"><a href="#set3">{{ 'config.tab_menu.user_info'|trans }}</a></li> | 16 | <li class="tab col s12 m6 l3"><a href="#set3">{{ 'config.tab_menu.user_info'|trans }}</a></li> |
17 | <li class="tab col s12 m6 l3"><a href="#set4">{{ 'config.tab_menu.password'|trans }}</a></li> | 17 | <li class="tab col s12 m6 l3"><a href="#set4">{{ 'config.tab_menu.password'|trans }}</a></li> |
18 | <li class="tab col s12 m6 l3"><a href="#set5">{{ 'config.tab_menu.rules'|trans }}</a></li> | 18 | <li class="tab col s12 m6 l3"><a href="#set5">{{ 'config.tab_menu.rules'|trans }}</a></li> |
19 | <li class="tab col s12 m6 l3"><a href="#set6">{{ 'config.tab_menu.reset'|trans }}</a></li> | ||
19 | </ul> | 20 | </ul> |
20 | </div> | 21 | </div> |
21 | 22 | ||
@@ -111,8 +112,7 @@ | |||
111 | <img id="androidQrcode" class="hide-on-med-and-down" /> | 112 | <img id="androidQrcode" class="hide-on-med-and-down" /> |
112 | </div> | 113 | </div> |
113 | <script> | 114 | <script> |
114 | const imgBase64 = jrQrcode.getQrBase64('wallabag://{{ app.user.username }}@{{ wallabag_url }}'); | 115 | document.getElementById('androidQrcode').src = jrQrcode.getQrBase64('wallabag://{{ app.user.username }}@{{ wallabag_url }}'); |
115 | document.getElementById('androidQrcode').src = imgBase64; | ||
116 | </script> | 116 | </script> |
117 | </div> | 117 | </div> |
118 | 118 | ||
@@ -122,42 +122,42 @@ | |||
122 | </div> | 122 | </div> |
123 | 123 | ||
124 | <div id="set2" class="col s12"> | 124 | <div id="set2" class="col s12"> |
125 | {{ form_start(form.rss) }} | 125 | {{ form_start(form.feed) }} |
126 | {{ form_errors(form.rss) }} | 126 | {{ form_errors(form.feed) }} |
127 | 127 | ||
128 | <div class="row"> | 128 | <div class="row"> |
129 | <div class="input-field col s12"> | 129 | <div class="input-field col s12"> |
130 | {{ 'config.form_rss.description'|trans }} | 130 | {{ 'config.form_feed.description'|trans }} |
131 | </div> | 131 | </div> |
132 | </div> | 132 | </div> |
133 | 133 | ||
134 | <div class="row"> | 134 | <div class="row"> |
135 | <div class="col s12"> | 135 | <div class="col s12"> |
136 | <h6 class="grey-text">{{ 'config.form_rss.token_label'|trans }}</h6> | 136 | <h6 class="grey-text">{{ 'config.form_feed.token_label'|trans }}</h6> |
137 | <div> | 137 | <div> |
138 | {% if rss.token %} | 138 | {% if feed.token %} |
139 | {{ rss.token }} | 139 | {{ feed.token }} |
140 | {% else %} | 140 | {% else %} |
141 | <em>{{ 'config.form_rss.no_token'|trans }}</em> | 141 | <em>{{ 'config.form_feed.no_token'|trans }}</em> |
142 | {% endif %} | 142 | {% endif %} |
143 | – <a href="{{ path('generate_token') }}"> | 143 | – <a href="{{ path('generate_token') }}"> |
144 | {% if rss.token %} | 144 | {% if feed.token %} |
145 | {{ 'config.form_rss.token_reset'|trans }} | 145 | {{ 'config.form_feed.token_reset'|trans }} |
146 | {% else %} | 146 | {% else %} |
147 | {{ 'config.form_rss.token_create'|trans }} | 147 | {{ 'config.form_feed.token_create'|trans }} |
148 | {% endif %}</a> | 148 | {% endif %}</a> |
149 | </div> | 149 | </div> |
150 | </div> | 150 | </div> |
151 | </div> | 151 | </div> |
152 | {% if rss.token %} | 152 | {% if feed.token %} |
153 | <div class="row"> | 153 | <div class="row"> |
154 | <div class="col s12"> | 154 | <div class="col s12"> |
155 | <h6 class="grey-text">{{ 'config.form_rss.rss_links'|trans }}</h6> | 155 | <h6 class="grey-text">{{ 'config.form_feed.feed_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_feed', {'username': feed.username, 'token': feed.token}) }}">{{ 'config.form_feed.feed_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_feed', {'username': feed.username, 'token': feed.token}) }}">{{ 'config.form_feed.feed_link.starred'|trans }}</a></li> |
159 | <li><a href="{{ path('archive_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.archive'|trans }}</a></li> | 159 | <li><a href="{{ path('archive_feed', {'username': feed.username, 'token': feed.token}) }}">{{ 'config.form_feed.feed_link.archive'|trans }}</a></li> |
160 | <li><a href="{{ path('all_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.all'|trans }}</a></li> | 160 | <li><a href="{{ path('all_feed', {'username': feed.username, 'token': feed.token}) }}">{{ 'config.form_feed.feed_link.all'|trans }}</a></li> |
161 | </ul> | 161 | </ul> |
162 | </div> | 162 | </div> |
163 | </div> | 163 | </div> |
@@ -165,14 +165,14 @@ | |||
165 | 165 | ||
166 | <div class="row"> | 166 | <div class="row"> |
167 | <div class="input-field col s12"> | 167 | <div class="input-field col s12"> |
168 | {{ form_label(form.rss.rss_limit) }} | 168 | {{ form_label(form.feed.feed_limit) }} |
169 | {{ form_errors(form.rss.rss_limit) }} | 169 | {{ form_errors(form.feed.feed_limit) }} |
170 | {{ form_widget(form.rss.rss_limit) }} | 170 | {{ form_widget(form.feed.feed_limit) }} |
171 | </div> | 171 | </div> |
172 | </div> | 172 | </div> |
173 | 173 | ||
174 | {{ form_widget(form.rss.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} | 174 | {{ form_widget(form.feed.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} |
175 | {{ form_rest(form.rss) }} | 175 | {{ form_rest(form.feed) }} |
176 | </form> | 176 | </form> |
177 | </div> | 177 | </div> |
178 | 178 | ||
@@ -196,59 +196,42 @@ | |||
196 | </div> | 196 | </div> |
197 | </div> | 197 | </div> |
198 | 198 | ||
199 | {% if twofactor_auth %} | 199 | {{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} |
200 | <div class="row"> | ||
201 | <div class="input-field col s11"> | ||
202 | {{ 'config.form_user.two_factor_description'|trans }} | ||
203 | |||
204 | <br /> | ||
205 | 200 | ||
206 | {{ form_widget(form.user.twoFactorAuthentication) }} | 201 | {% if twofactor_auth %} |
207 | {{ form_label(form.user.twoFactorAuthentication) }} | 202 | <br/> |
208 | {{ form_errors(form.user.twoFactorAuthentication) }} | 203 | <br/> |
209 | </div> | 204 | <div class="row"> |
210 | <div class="input-field col s1"> | 205 | <h5>{{ 'config.otp.page_title'|trans }}</h5> |
211 | <a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_user.help_twoFactorAuthentication'|trans }}"> | 206 | |
212 | <i class="material-icons">live_help</i> | 207 | <p>{{ 'config.form_user.two_factor_description'|trans }}</p> |
213 | </a> | 208 | |
209 | <table> | ||
210 | <thead> | ||
211 | <tr> | ||
212 | <th>{{ 'config.form_user.two_factor.table_method'|trans }}</th> | ||
213 | <th>{{ 'config.form_user.two_factor.table_state'|trans }}</th> | ||
214 | <th>{{ 'config.form_user.two_factor.table_action'|trans }}</th> | ||
215 | </tr> | ||
216 | </thead> | ||
217 | |||
218 | <tbody> | ||
219 | <tr> | ||
220 | <td>{{ 'config.form_user.two_factor.emailTwoFactor_label'|trans }}</td> | ||
221 | <td>{% if app.user.isEmailTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td> | ||
222 | <td><a href="{{ path('config_otp_email') }}" class="waves-effect waves-light btn{% if app.user.isEmailTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_email'|trans }}</a></td> | ||
223 | </tr> | ||
224 | <tr> | ||
225 | <td>{{ 'config.form_user.two_factor.googleTwoFactor_label'|trans }}</td> | ||
226 | <td>{% if app.user.isGoogleTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td> | ||
227 | <td><a href="{{ path('config_otp_app') }}" class="waves-effect waves-light btn{% if app.user.isGoogleTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_app'|trans }}</a></td> | ||
228 | </tr> | ||
229 | </tbody> | ||
230 | </table> | ||
214 | </div> | 231 | </div> |
215 | </div> | ||
216 | {% endif %} | 232 | {% endif %} |
217 | |||
218 | {{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} | ||
219 | {{ form_widget(form.user._token) }} | 233 | {{ form_widget(form.user._token) }} |
220 | </form> | 234 | </form> |
221 | |||
222 | <br /><hr /><br /> | ||
223 | |||
224 | <div class="row"> | ||
225 | <h5>{{ 'config.reset.title'|trans }}</h5> | ||
226 | <p>{{ 'config.reset.description'|trans }}</p> | ||
227 | <a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
228 | {{ 'config.reset.annotations'|trans }} | ||
229 | </a> | ||
230 | <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
231 | {{ 'config.reset.tags'|trans }} | ||
232 | </a> | ||
233 | <a href="{{ path('config_reset', { type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
234 | {{ 'config.reset.archived'|trans }} | ||
235 | </a> | ||
236 | <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
237 | {{ 'config.reset.entries'|trans }} | ||
238 | </a> | ||
239 | </div> | ||
240 | |||
241 | {% if enabled_users > 1 %} | ||
242 | <br /><hr /><br /> | ||
243 | |||
244 | <div class="row"> | ||
245 | <h5>{{ 'config.form_user.delete.title'|trans }}</h5> | ||
246 | <p>{{ 'config.form_user.delete.description'|trans }}</p> | ||
247 | <a href="{{ path('delete_account') }}" onclick="return confirm('{{ 'config.form_user.delete.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red delete-account"> | ||
248 | {{ 'config.form_user.delete.button'|trans }} | ||
249 | </a> | ||
250 | </div> | ||
251 | {% endif %} | ||
252 | </div> | 235 | </div> |
253 | 236 | ||
254 | <div id="set4" class="col s12"> | 237 | <div id="set4" class="col s12"> |
@@ -422,6 +405,37 @@ | |||
422 | </div> | 405 | </div> |
423 | </div> | 406 | </div> |
424 | </div> | 407 | </div> |
408 | |||
409 | <div id="set6" class="col s12"> | ||
410 | <div class="row"> | ||
411 | <h5>{{ 'config.reset.title'|trans }}</h5> | ||
412 | <p>{{ 'config.reset.description'|trans }}</p> | ||
413 | <a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
414 | {{ 'config.reset.annotations'|trans }} | ||
415 | </a> | ||
416 | <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
417 | {{ 'config.reset.tags'|trans }} | ||
418 | </a> | ||
419 | <a href="{{ path('config_reset', { type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
420 | {{ 'config.reset.archived'|trans }} | ||
421 | </a> | ||
422 | <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red"> | ||
423 | {{ 'config.reset.entries'|trans }} | ||
424 | </a> | ||
425 | </div> | ||
426 | |||
427 | {% if enabled_users > 1 %} | ||
428 | <br /><hr /><br /> | ||
429 | |||
430 | <div class="row"> | ||
431 | <h5>{{ 'config.form_user.delete.title'|trans }}</h5> | ||
432 | <p>{{ 'config.form_user.delete.description'|trans }}</p> | ||
433 | <a href="{{ path('delete_account') }}" onclick="return confirm('{{ 'config.form_user.delete.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red delete-account"> | ||
434 | {{ 'config.form_user.delete.button'|trans }} | ||
435 | </a> | ||
436 | </div> | ||
437 | {% endif %} | ||
438 | </div> | ||
425 | </div> | 439 | </div> |
426 | 440 | ||
427 | </div> | 441 | </div> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/otp_app.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/otp_app.html.twig new file mode 100644 index 00000000..7875d787 --- /dev/null +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/otp_app.html.twig | |||
@@ -0,0 +1,63 @@ | |||
1 | {% extends "WallabagCoreBundle::layout.html.twig" %} | ||
2 | |||
3 | {% block title %}{{ 'config.page_title'|trans }} > {{ 'config.otp.page_title'|trans }}{% endblock %} | ||
4 | |||
5 | {% block content %} | ||
6 | <div class="row"> | ||
7 | <div class="col s12"> | ||
8 | <div class="card-panel settings"> | ||
9 | <div class="row"> | ||
10 | <h5>{{ 'config.otp.page_title'|trans }}</h5> | ||
11 | |||
12 | <ol> | ||
13 | <li> | ||
14 | <p>{{ 'config.otp.app.two_factor_code_description_1'|trans }}</p> | ||
15 | <p>{{ 'config.otp.app.two_factor_code_description_2'|trans }}</p> | ||
16 | |||
17 | <p> | ||
18 | <img id="2faQrcode" class="hide-on-med-and-down" /> | ||
19 | <script> | ||
20 | document.getElementById('2faQrcode').src = jrQrcode.getQrBase64('{{ qr_code }}'); | ||
21 | </script> | ||
22 | </p> | ||
23 | </li> | ||
24 | <li> | ||
25 | <p>{{ 'config.otp.app.two_factor_code_description_3'|trans }}</p> | ||
26 | |||
27 | <p><strong>{{ backupCodes|join("\n")|nl2br }}</strong></p> | ||
28 | </li> | ||
29 | <li> | ||
30 | <p>{{ 'config.otp.app.two_factor_code_description_4'|trans }}</p> | ||
31 | |||
32 | {% for flashMessage in app.session.flashbag.get("two_factor") %} | ||
33 | <div class="card-panel red darken-1 black-text"> | ||
34 | {{ flashMessage|trans }} | ||
35 | </div> | ||
36 | {% endfor %} | ||
37 | |||
38 | <form class="form" action="{{ path("config_otp_app_check") }}" method="post"> | ||
39 | <div class="card-content"> | ||
40 | <div class="row"> | ||
41 | <div class="input-field col s12"> | ||
42 | <label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label> | ||
43 | <input id="_auth_code" type="text" autocomplete="off" name="_auth_code" /> | ||
44 | </div> | ||
45 | </div> | ||
46 | </div> | ||
47 | <div class="card-action"> | ||
48 | <a href="{{ path('config_otp_app_cancel') }}" class="waves-effect waves-light grey btn"> | ||
49 | {{ 'config.otp.app.cancel'|trans }} | ||
50 | </a> | ||
51 | <button class="btn waves-effect waves-light" type="submit" name="send"> | ||
52 | {{ 'config.otp.app.enable'|trans }} | ||
53 | <i class="material-icons right">send</i> | ||
54 | </button> | ||
55 | </div> | ||
56 | </form> | ||
57 | </li> | ||
58 | </ol> | ||
59 | </div> | ||
60 | </div> | ||
61 | </div> | ||
62 | </div> | ||
63 | {% endblock %} | ||
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 742dd330..476d7403 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 | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | {% block head %} | 3 | {% block head %} |
4 | {{ parent() }} | 4 | {{ parent() }} |
5 | {% if tag is defined and app.user.config.rssToken %} | 5 | {% if tag is defined and app.user.config.feedToken %} |
6 | <link rel="alternate" type="application/rss+xml" href="{{ path('tag_rss', {'username': app.user.username, 'token': app.user.config.rssToken, 'slug': tag.slug}) }}" /> | 6 | <link rel="alternate" type="application/atom+xml" href="{{ path('tag_feed', {'username': app.user.username, 'token': app.user.config.feedToken, 'slug': tag.slug}) }}" /> |
7 | {% endif %} | 7 | {% endif %} |
8 | {% endblock %} | 8 | {% endblock %} |
9 | 9 | ||
@@ -21,12 +21,15 @@ | |||
21 | {% block content %} | 21 | {% block content %} |
22 | {% set listMode = app.user.config.listMode %} | 22 | {% set listMode = app.user.config.listMode %} |
23 | {% set currentRoute = app.request.attributes.get('_route') %} | 23 | {% set currentRoute = app.request.attributes.get('_route') %} |
24 | {% if currentRoute == 'homepage' %} | ||
25 | {% set currentRoute = 'unread' %} | ||
26 | {% endif %} | ||
24 | <div class="results"> | 27 | <div class="results"> |
25 | <div class="nb-results"> | 28 | <div class="nb-results"> |
26 | {{ 'entry.list.number_on_the_page'|transchoice(entries.count) }} | 29 | {{ 'entry.list.number_on_the_page'|transchoice(entries.count) }} |
27 | <a href="{{ path('switch_view_mode') }}"><i class="material-icons">{% if listMode == 0 %}view_list{% else %}view_module{% endif %}</i></a> | 30 | <a href="{{ path('switch_view_mode') }}"><i class="material-icons">{% if listMode == 0 %}view_list{% else %}view_module{% endif %}</i></a> |
28 | {% if app.user.config.rssToken %} | 31 | {% if app.user.config.feedToken %} |
29 | {% include "@WallabagCore/themes/common/Entry/_rss_link.html.twig" %} | 32 | {% include "@WallabagCore/themes/common/Entry/_feed_link.html.twig" %} |
30 | {% endif %} | 33 | {% endif %} |
31 | </div> | 34 | </div> |
32 | {% if entries.getNbPages > 1 %} | 35 | {% if entries.getNbPages > 1 %} |
@@ -60,9 +63,6 @@ | |||
60 | {% if tag is defined %} | 63 | {% if tag is defined %} |
61 | {% set currentTag = tag.slug %} | 64 | {% set currentTag = tag.slug %} |
62 | {% endif %} | 65 | {% endif %} |
63 | {% if currentRoute == 'homepage' %} | ||
64 | {% set currentRoute = 'unread' %} | ||
65 | {% endif %} | ||
66 | <h4 class="center">{{ 'entry.list.export_title'|trans }}</h4> | 66 | <h4 class="center">{{ 'entry.list.export_title'|trans }}</h4> |
67 | <ul> | 67 | <ul> |
68 | {% if craue_setting('export_epub') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', { 'category': currentRoute, 'format': 'epub', 'tag' : currentTag }) }}">EPUB</a></li>{% endif %} | 68 | {% if craue_setting('export_epub') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', { 'category': currentRoute, 'format': 'epub', 'tag' : currentTag }) }}">EPUB</a></li>{% endif %} |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Tag/tags.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Tag/tags.html.twig index c15b5146..79907bbb 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Tag/tags.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Tag/tags.html.twig | |||
@@ -13,9 +13,20 @@ | |||
13 | <ul class="card-tag-labels"> | 13 | <ul class="card-tag-labels"> |
14 | {% for tag in tags %} | 14 | {% for tag in tags %} |
15 | <li title="{{tag.label}} ({{ tag.nbEntries }})" id="tag-{{ tag.id }}"> | 15 | <li title="{{tag.label}} ({{ tag.nbEntries }})" id="tag-{{ tag.id }}"> |
16 | <a href="{{ path('tag_entries', {'slug': tag.slug}) }}" class="card-tag-link">{{tag.label}} ({{ tag.nbEntries }})</a> | 16 | <a href="{{ path('tag_entries', {'slug': tag.slug}) }}" class="card-tag-link" data-handle="tag-link"> |
17 | {% if app.user.config.rssToken %} | 17 | {{ tag.label }} ({{ tag.nbEntries }}) |
18 | <a rel="alternate" type="application/rss+xml" href="{{ path('tag_rss', {'username': app.user.username, 'token': app.user.config.rssToken, 'slug': tag.slug}) }}" class="card-tag-rss"><i class="material-icons">rss_feed</i></a> | 18 | </a> |
19 | {% if renameForms is defined and renameForms[tag.id] is defined %} | ||
20 | <form class="card-tag-form hidden" data-handle="tag-rename-form" action="{{ path('tag_rename', {'slug': tag.slug})}}" method="POST"> | ||
21 | {{ form_widget(renameForms[tag.id].label, {'attr': {'value': tag.label}}) }} | ||
22 | {{ form_rest(renameForms[tag.id]) }} | ||
23 | </form> | ||
24 | <a class="card-tag-rename" data-handler="tag-rename" href="javascript:void(0);"> | ||
25 | <i class="material-icons">mode_edit</i> | ||
26 | </a> | ||
27 | {% endif %} | ||
28 | {% if app.user.config.feedToken %} | ||
29 | <a rel="alternate" type="application/atom+xml" href="{{ path('tag_feed', {'username': app.user.username, 'token': app.user.config.feedToken, 'slug': tag.slug}) }}" class="card-tag-rss"><i class="material-icons">rss_feed</i></a> | ||
19 | {% endif %} | 30 | {% endif %} |
20 | </li> | 31 | </li> |
21 | {% endfor %} | 32 | {% endfor %} |
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 052a8c01..b9c45567 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig | |||
@@ -46,6 +46,8 @@ | |||
46 | {% set activeRoute = 'starred' %} | 46 | {% set activeRoute = 'starred' %} |
47 | {% elseif currentRoute == 'unread' or currentRoute == 'homepage' or currentRouteFromQueryParams == 'unread' %} | 47 | {% elseif currentRoute == 'unread' or currentRoute == 'homepage' or currentRouteFromQueryParams == 'unread' %} |
48 | {% set activeRoute = 'unread' %} | 48 | {% set activeRoute = 'unread' %} |
49 | {% elseif currentRoute == 'untagged' %} | ||
50 | {% set activeRoute = 'untagged' %} | ||
49 | {% endif %} | 51 | {% endif %} |
50 | 52 | ||
51 | <li class="bold {% if activeRoute == 'unread' %}active{% endif %}"> | 53 | <li class="bold {% if activeRoute == 'unread' %}active{% endif %}"> |
@@ -113,6 +115,13 @@ | |||
113 | <i class="material-icons">search</i> | 115 | <i class="material-icons">search</i> |
114 | </a> | 116 | </a> |
115 | </li> | 117 | </li> |
118 | {% if activeRoute %} | ||
119 | <li id="button_random"> | ||
120 | <a class="waves-effect tooltipped js-random-action" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.random_entry'|trans }}" href="{{ path('random_entry', { 'type': activeRoute }) }}"> | ||
121 | <i class="material-icons">casino</i> | ||
122 | </a> | ||
123 | </li> | ||
124 | {% endif %} | ||
116 | <li id="button_filters"> | 125 | <li id="button_filters"> |
117 | <a class="nav-panel-menu button-collapse-right tooltipped js-filters-action" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.filter_entries'|trans }}" href="#" data-activates="filters"> | 126 | <a class="nav-panel-menu button-collapse-right tooltipped js-filters-action" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.filter_entries'|trans }}" href="#" data-activates="filters"> |
118 | <i class="material-icons">filter_list</i> | 127 | <i class="material-icons">filter_list</i> |
@@ -125,7 +134,7 @@ | |||
125 | </li> | 134 | </li> |
126 | </ul> | 135 | </ul> |
127 | </div> | 136 | </div> |
128 | {{ render(controller("WallabagCoreBundle:Entry:searchForm", {'currentRoute': app.request.attributes.get('_route')})) }} | 137 | {{ render(controller("WallabagCoreBundle:Entry:searchForm", {'currentRoute': currentRoute})) }} |
129 | {{ render(controller("WallabagCoreBundle:Entry:addEntryForm")) }} | 138 | {{ render(controller("WallabagCoreBundle:Entry:addEntryForm")) }} |
130 | </div> | 139 | </div> |
131 | </nav> | 140 | </nav> |
diff --git a/src/Wallabag/CoreBundle/Tools/Utils.php b/src/Wallabag/CoreBundle/Tools/Utils.php index e56e251e..b7ad7966 100644 --- a/src/Wallabag/CoreBundle/Tools/Utils.php +++ b/src/Wallabag/CoreBundle/Tools/Utils.php | |||
@@ -5,7 +5,7 @@ namespace Wallabag\CoreBundle\Tools; | |||
5 | class Utils | 5 | class Utils |
6 | { | 6 | { |
7 | /** | 7 | /** |
8 | * Generate a token used for RSS. | 8 | * Generate a token used for Feeds. |
9 | * | 9 | * |
10 | * @param int $length Length of the token | 10 | * @param int $length Length of the token |
11 | * | 11 | * |
diff --git a/src/Wallabag/CoreBundle/Twig/WallabagExtension.php b/src/Wallabag/CoreBundle/Twig/WallabagExtension.php index 00b1e595..536185d4 100644 --- a/src/Wallabag/CoreBundle/Twig/WallabagExtension.php +++ b/src/Wallabag/CoreBundle/Twig/WallabagExtension.php | |||
@@ -28,6 +28,7 @@ class WallabagExtension extends \Twig_Extension implements \Twig_Extension_Globa | |||
28 | { | 28 | { |
29 | return [ | 29 | return [ |
30 | new \Twig_SimpleFilter('removeWww', [$this, 'removeWww']), | 30 | new \Twig_SimpleFilter('removeWww', [$this, 'removeWww']), |
31 | new \Twig_SimpleFilter('removeScheme', [$this, 'removeScheme']), | ||
31 | new \Twig_SimpleFilter('removeSchemeAndWww', [$this, 'removeSchemeAndWww']), | 32 | new \Twig_SimpleFilter('removeSchemeAndWww', [$this, 'removeSchemeAndWww']), |
32 | ]; | 33 | ]; |
33 | } | 34 | } |
@@ -46,11 +47,14 @@ class WallabagExtension extends \Twig_Extension implements \Twig_Extension_Globa | |||
46 | return preg_replace('/^www\./i', '', $url); | 47 | return preg_replace('/^www\./i', '', $url); |
47 | } | 48 | } |
48 | 49 | ||
50 | public function removeScheme($url) | ||
51 | { | ||
52 | return preg_replace('#^https?://#i', '', $url); | ||
53 | } | ||
54 | |||
49 | public function removeSchemeAndWww($url) | 55 | public function removeSchemeAndWww($url) |
50 | { | 56 | { |
51 | return $this->removeWww( | 57 | return $this->removeWww($this->removeScheme($url)); |
52 | preg_replace('@^https?://@i', '', $url) | ||
53 | ); | ||
54 | } | 58 | } |
55 | 59 | ||
56 | /** | 60 | /** |
diff --git a/src/Wallabag/ImportBundle/Controller/BrowserController.php b/src/Wallabag/ImportBundle/Controller/BrowserController.php index 6418925c..58d2a730 100644 --- a/src/Wallabag/ImportBundle/Controller/BrowserController.php +++ b/src/Wallabag/ImportBundle/Controller/BrowserController.php | |||
@@ -2,10 +2,10 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Controller; | 3 | namespace Wallabag\ImportBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 5 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
7 | use Symfony\Component\HttpFoundation\Request; | 6 | use Symfony\Component\HttpFoundation\Request; |
8 | use Symfony\Component\HttpFoundation\Response; | 7 | use Symfony\Component\HttpFoundation\Response; |
8 | use Symfony\Component\Routing\Annotation\Route; | ||
9 | use Wallabag\ImportBundle\Form\Type\UploadImportType; | 9 | use Wallabag\ImportBundle\Form\Type\UploadImportType; |
10 | 10 | ||
11 | abstract class BrowserController extends Controller | 11 | abstract class BrowserController extends Controller |
diff --git a/src/Wallabag/ImportBundle/Controller/ChromeController.php b/src/Wallabag/ImportBundle/Controller/ChromeController.php index 0cb418a1..6628cdb0 100644 --- a/src/Wallabag/ImportBundle/Controller/ChromeController.php +++ b/src/Wallabag/ImportBundle/Controller/ChromeController.php | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Controller; | 3 | namespace Wallabag\ImportBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Component\HttpFoundation\Request; | 5 | use Symfony\Component\HttpFoundation\Request; |
6 | use Symfony\Component\Routing\Annotation\Route; | ||
7 | 7 | ||
8 | class ChromeController extends BrowserController | 8 | class ChromeController extends BrowserController |
9 | { | 9 | { |
diff --git a/src/Wallabag/ImportBundle/Controller/FirefoxController.php b/src/Wallabag/ImportBundle/Controller/FirefoxController.php index 88697f9d..dce8455f 100644 --- a/src/Wallabag/ImportBundle/Controller/FirefoxController.php +++ b/src/Wallabag/ImportBundle/Controller/FirefoxController.php | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Controller; | 3 | namespace Wallabag\ImportBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Component\HttpFoundation\Request; | 5 | use Symfony\Component\HttpFoundation\Request; |
6 | use Symfony\Component\Routing\Annotation\Route; | ||
7 | 7 | ||
8 | class FirefoxController extends BrowserController | 8 | class FirefoxController extends BrowserController |
9 | { | 9 | { |
diff --git a/src/Wallabag/ImportBundle/Controller/ImportController.php b/src/Wallabag/ImportBundle/Controller/ImportController.php index 7e4fd174..fbd7434e 100644 --- a/src/Wallabag/ImportBundle/Controller/ImportController.php +++ b/src/Wallabag/ImportBundle/Controller/ImportController.php | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Controller; | 3 | namespace Wallabag\ImportBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 5 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
6 | use Symfony\Component\Routing\Annotation\Route; | ||
7 | 7 | ||
8 | class ImportController extends Controller | 8 | class ImportController extends Controller |
9 | { | 9 | { |
diff --git a/src/Wallabag/ImportBundle/Controller/InstapaperController.php b/src/Wallabag/ImportBundle/Controller/InstapaperController.php index f184baf9..faed3b72 100644 --- a/src/Wallabag/ImportBundle/Controller/InstapaperController.php +++ b/src/Wallabag/ImportBundle/Controller/InstapaperController.php | |||
@@ -2,9 +2,9 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Controller; | 3 | namespace Wallabag\ImportBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 5 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
7 | use Symfony\Component\HttpFoundation\Request; | 6 | use Symfony\Component\HttpFoundation\Request; |
7 | use Symfony\Component\Routing\Annotation\Route; | ||
8 | use Wallabag\ImportBundle\Form\Type\UploadImportType; | 8 | use Wallabag\ImportBundle\Form\Type\UploadImportType; |
9 | 9 | ||
10 | class InstapaperController extends Controller | 10 | class InstapaperController extends Controller |
diff --git a/src/Wallabag/ImportBundle/Controller/PinboardController.php b/src/Wallabag/ImportBundle/Controller/PinboardController.php index 6f54c69a..cc6fae79 100644 --- a/src/Wallabag/ImportBundle/Controller/PinboardController.php +++ b/src/Wallabag/ImportBundle/Controller/PinboardController.php | |||
@@ -2,9 +2,9 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Controller; | 3 | namespace Wallabag\ImportBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 5 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
7 | use Symfony\Component\HttpFoundation\Request; | 6 | use Symfony\Component\HttpFoundation\Request; |
7 | use Symfony\Component\Routing\Annotation\Route; | ||
8 | use Wallabag\ImportBundle\Form\Type\UploadImportType; | 8 | use Wallabag\ImportBundle\Form\Type\UploadImportType; |
9 | 9 | ||
10 | class PinboardController extends Controller | 10 | class PinboardController extends Controller |
diff --git a/src/Wallabag/ImportBundle/Controller/PocketController.php b/src/Wallabag/ImportBundle/Controller/PocketController.php index 9f28819a..71ceb427 100644 --- a/src/Wallabag/ImportBundle/Controller/PocketController.php +++ b/src/Wallabag/ImportBundle/Controller/PocketController.php | |||
@@ -2,10 +2,10 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Controller; | 3 | namespace Wallabag\ImportBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 5 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
7 | use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | 6 | use Symfony\Component\Form\Extension\Core\Type\CheckboxType; |
8 | use Symfony\Component\HttpFoundation\Request; | 7 | use Symfony\Component\HttpFoundation\Request; |
8 | use Symfony\Component\Routing\Annotation\Route; | ||
9 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | 9 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
10 | 10 | ||
11 | class PocketController extends Controller | 11 | class PocketController extends Controller |
diff --git a/src/Wallabag/ImportBundle/Controller/ReadabilityController.php b/src/Wallabag/ImportBundle/Controller/ReadabilityController.php index 729a97a3..b120ef96 100644 --- a/src/Wallabag/ImportBundle/Controller/ReadabilityController.php +++ b/src/Wallabag/ImportBundle/Controller/ReadabilityController.php | |||
@@ -2,9 +2,9 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Controller; | 3 | namespace Wallabag\ImportBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 5 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
7 | use Symfony\Component\HttpFoundation\Request; | 6 | use Symfony\Component\HttpFoundation\Request; |
7 | use Symfony\Component\Routing\Annotation\Route; | ||
8 | use Wallabag\ImportBundle\Form\Type\UploadImportType; | 8 | use Wallabag\ImportBundle\Form\Type\UploadImportType; |
9 | 9 | ||
10 | class ReadabilityController extends Controller | 10 | class ReadabilityController extends Controller |
diff --git a/src/Wallabag/ImportBundle/Controller/WallabagV1Controller.php b/src/Wallabag/ImportBundle/Controller/WallabagV1Controller.php index d700d8a8..e1c35343 100644 --- a/src/Wallabag/ImportBundle/Controller/WallabagV1Controller.php +++ b/src/Wallabag/ImportBundle/Controller/WallabagV1Controller.php | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Controller; | 3 | namespace Wallabag\ImportBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Component\HttpFoundation\Request; | 5 | use Symfony\Component\HttpFoundation\Request; |
6 | use Symfony\Component\Routing\Annotation\Route; | ||
7 | 7 | ||
8 | class WallabagV1Controller extends WallabagController | 8 | class WallabagV1Controller extends WallabagController |
9 | { | 9 | { |
diff --git a/src/Wallabag/ImportBundle/Controller/WallabagV2Controller.php b/src/Wallabag/ImportBundle/Controller/WallabagV2Controller.php index ab26400c..c4116c1d 100644 --- a/src/Wallabag/ImportBundle/Controller/WallabagV2Controller.php +++ b/src/Wallabag/ImportBundle/Controller/WallabagV2Controller.php | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Controller; | 3 | namespace Wallabag\ImportBundle\Controller; |
4 | 4 | ||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Component\HttpFoundation\Request; | 5 | use Symfony\Component\HttpFoundation\Request; |
6 | use Symfony\Component\Routing\Annotation\Route; | ||
7 | 7 | ||
8 | class WallabagV2Controller extends WallabagController | 8 | class WallabagV2Controller extends WallabagController |
9 | { | 9 | { |
diff --git a/src/Wallabag/ImportBundle/Import/BrowserImport.php b/src/Wallabag/ImportBundle/Import/BrowserImport.php index 811e3fb8..3987e80f 100644 --- a/src/Wallabag/ImportBundle/Import/BrowserImport.php +++ b/src/Wallabag/ImportBundle/Import/BrowserImport.php | |||
@@ -133,7 +133,7 @@ abstract class BrowserImport extends AbstractImport | |||
133 | ); | 133 | ); |
134 | } | 134 | } |
135 | 135 | ||
136 | $entry->setArchived($data['is_archived']); | 136 | $entry->updateArchived($data['is_archived']); |
137 | 137 | ||
138 | if (!empty($data['created_at'])) { | 138 | if (!empty($data['created_at'])) { |
139 | $dt = new \DateTime(); | 139 | $dt = new \DateTime(); |
diff --git a/src/Wallabag/ImportBundle/Import/InstapaperImport.php b/src/Wallabag/ImportBundle/Import/InstapaperImport.php index 5a18c7c0..f7bee9ef 100644 --- a/src/Wallabag/ImportBundle/Import/InstapaperImport.php +++ b/src/Wallabag/ImportBundle/Import/InstapaperImport.php | |||
@@ -62,7 +62,7 @@ class InstapaperImport extends AbstractImport | |||
62 | } | 62 | } |
63 | 63 | ||
64 | $entries = []; | 64 | $entries = []; |
65 | $handle = fopen($this->filepath, 'rb'); | 65 | $handle = fopen($this->filepath, 'r'); |
66 | while (false !== ($data = fgetcsv($handle, 10240))) { | 66 | while (false !== ($data = fgetcsv($handle, 10240))) { |
67 | if ('URL' === $data[0]) { | 67 | if ('URL' === $data[0]) { |
68 | continue; | 68 | continue; |
@@ -79,7 +79,6 @@ class InstapaperImport extends AbstractImport | |||
79 | $entries[] = [ | 79 | $entries[] = [ |
80 | 'url' => $data[0], | 80 | 'url' => $data[0], |
81 | 'title' => $data[1], | 81 | 'title' => $data[1], |
82 | 'status' => $data[3], | ||
83 | 'is_archived' => 'Archive' === $data[3] || 'Starred' === $data[3], | 82 | 'is_archived' => 'Archive' === $data[3] || 'Starred' === $data[3], |
84 | 'is_starred' => 'Starred' === $data[3], | 83 | 'is_starred' => 'Starred' === $data[3], |
85 | 'html' => false, | 84 | 'html' => false, |
@@ -94,6 +93,10 @@ class InstapaperImport extends AbstractImport | |||
94 | return false; | 93 | return false; |
95 | } | 94 | } |
96 | 95 | ||
96 | // most recent articles are first, which means we should create them at the end so they will show up first | ||
97 | // as Instapaper doesn't export the creation date of the article | ||
98 | $entries = array_reverse($entries); | ||
99 | |||
97 | if ($this->producer) { | 100 | if ($this->producer) { |
98 | $this->parseEntriesForProducer($entries); | 101 | $this->parseEntriesForProducer($entries); |
99 | 102 | ||
@@ -147,7 +150,7 @@ class InstapaperImport extends AbstractImport | |||
147 | ); | 150 | ); |
148 | } | 151 | } |
149 | 152 | ||
150 | $entry->setArchived($importedEntry['is_archived']); | 153 | $entry->updateArchived($importedEntry['is_archived']); |
151 | $entry->setStarred($importedEntry['is_starred']); | 154 | $entry->setStarred($importedEntry['is_starred']); |
152 | 155 | ||
153 | $this->em->persist($entry); | 156 | $this->em->persist($entry); |
diff --git a/src/Wallabag/ImportBundle/Import/PinboardImport.php b/src/Wallabag/ImportBundle/Import/PinboardImport.php index 995d1f2c..202eb1b3 100644 --- a/src/Wallabag/ImportBundle/Import/PinboardImport.php +++ b/src/Wallabag/ImportBundle/Import/PinboardImport.php | |||
@@ -131,7 +131,7 @@ class PinboardImport extends AbstractImport | |||
131 | ); | 131 | ); |
132 | } | 132 | } |
133 | 133 | ||
134 | $entry->setArchived($data['is_archived']); | 134 | $entry->updateArchived($data['is_archived']); |
135 | $entry->setStarred($data['is_starred']); | 135 | $entry->setStarred($data['is_starred']); |
136 | $entry->setCreatedAt(new \DateTime($data['created_at'])); | 136 | $entry->setCreatedAt(new \DateTime($data['created_at'])); |
137 | 137 | ||
diff --git a/src/Wallabag/ImportBundle/Import/PocketImport.php b/src/Wallabag/ImportBundle/Import/PocketImport.php index 5737928d..746120af 100644 --- a/src/Wallabag/ImportBundle/Import/PocketImport.php +++ b/src/Wallabag/ImportBundle/Import/PocketImport.php | |||
@@ -2,13 +2,22 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ImportBundle\Import; | 3 | namespace Wallabag\ImportBundle\Import; |
4 | 4 | ||
5 | use GuzzleHttp\Client; | 5 | use Http\Client\Common\HttpMethodsClient; |
6 | use GuzzleHttp\Exception\RequestException; | 6 | use Http\Client\Common\Plugin\ErrorPlugin; |
7 | use Http\Client\Common\PluginClient; | ||
8 | use Http\Client\Exception\RequestException; | ||
9 | use Http\Client\HttpClient; | ||
10 | use Http\Discovery\MessageFactoryDiscovery; | ||
11 | use Http\Message\MessageFactory; | ||
12 | use Psr\Http\Message\ResponseInterface; | ||
7 | use Wallabag\CoreBundle\Entity\Entry; | 13 | use Wallabag\CoreBundle\Entity\Entry; |
8 | 14 | ||
9 | class PocketImport extends AbstractImport | 15 | class PocketImport extends AbstractImport |
10 | { | 16 | { |
11 | const NB_ELEMENTS = 5000; | 17 | const NB_ELEMENTS = 5000; |
18 | /** | ||
19 | * @var HttpMethodsClient | ||
20 | */ | ||
12 | private $client; | 21 | private $client; |
13 | private $accessToken; | 22 | private $accessToken; |
14 | 23 | ||
@@ -55,24 +64,18 @@ class PocketImport extends AbstractImport | |||
55 | */ | 64 | */ |
56 | public function getRequestToken($redirectUri) | 65 | public function getRequestToken($redirectUri) |
57 | { | 66 | { |
58 | $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/oauth/request', | ||
59 | [ | ||
60 | 'body' => json_encode([ | ||
61 | 'consumer_key' => $this->user->getConfig()->getPocketConsumerKey(), | ||
62 | 'redirect_uri' => $redirectUri, | ||
63 | ]), | ||
64 | ] | ||
65 | ); | ||
66 | |||
67 | try { | 67 | try { |
68 | $response = $this->client->send($request); | 68 | $response = $this->client->post('https://getpocket.com/v3/oauth/request', [], json_encode([ |
69 | 'consumer_key' => $this->user->getConfig()->getPocketConsumerKey(), | ||
70 | 'redirect_uri' => $redirectUri, | ||
71 | ])); | ||
69 | } catch (RequestException $e) { | 72 | } catch (RequestException $e) { |
70 | $this->logger->error(sprintf('PocketImport: Failed to request token: %s', $e->getMessage()), ['exception' => $e]); | 73 | $this->logger->error(sprintf('PocketImport: Failed to request token: %s', $e->getMessage()), ['exception' => $e]); |
71 | 74 | ||
72 | return false; | 75 | return false; |
73 | } | 76 | } |
74 | 77 | ||
75 | return $response->json()['code']; | 78 | return $this->jsonDecode($response)['code']; |
76 | } | 79 | } |
77 | 80 | ||
78 | /** | 81 | /** |
@@ -85,24 +88,18 @@ class PocketImport extends AbstractImport | |||
85 | */ | 88 | */ |
86 | public function authorize($code) | 89 | public function authorize($code) |
87 | { | 90 | { |
88 | $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/oauth/authorize', | ||
89 | [ | ||
90 | 'body' => json_encode([ | ||
91 | 'consumer_key' => $this->user->getConfig()->getPocketConsumerKey(), | ||
92 | 'code' => $code, | ||
93 | ]), | ||
94 | ] | ||
95 | ); | ||
96 | |||
97 | try { | 91 | try { |
98 | $response = $this->client->send($request); | 92 | $response = $this->client->post('https://getpocket.com/v3/oauth/authorize', [], json_encode([ |
93 | 'consumer_key' => $this->user->getConfig()->getPocketConsumerKey(), | ||
94 | 'code' => $code, | ||
95 | ])); | ||
99 | } catch (RequestException $e) { | 96 | } catch (RequestException $e) { |
100 | $this->logger->error(sprintf('PocketImport: Failed to authorize client: %s', $e->getMessage()), ['exception' => $e]); | 97 | $this->logger->error(sprintf('PocketImport: Failed to authorize client: %s', $e->getMessage()), ['exception' => $e]); |
101 | 98 | ||
102 | return false; | 99 | return false; |
103 | } | 100 | } |
104 | 101 | ||
105 | $this->accessToken = $response->json()['access_token']; | 102 | $this->accessToken = $this->jsonDecode($response)['access_token']; |
106 | 103 | ||
107 | return true; | 104 | return true; |
108 | } | 105 | } |
@@ -114,29 +111,23 @@ class PocketImport extends AbstractImport | |||
114 | { | 111 | { |
115 | static $run = 0; | 112 | static $run = 0; |
116 | 113 | ||
117 | $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/get', | ||
118 | [ | ||
119 | 'body' => json_encode([ | ||
120 | 'consumer_key' => $this->user->getConfig()->getPocketConsumerKey(), | ||
121 | 'access_token' => $this->accessToken, | ||
122 | 'detailType' => 'complete', | ||
123 | 'state' => 'all', | ||
124 | 'sort' => 'newest', | ||
125 | 'count' => self::NB_ELEMENTS, | ||
126 | 'offset' => $offset, | ||
127 | ]), | ||
128 | ] | ||
129 | ); | ||
130 | |||
131 | try { | 114 | try { |
132 | $response = $this->client->send($request); | 115 | $response = $this->client->post('https://getpocket.com/v3/get', [], json_encode([ |
116 | 'consumer_key' => $this->user->getConfig()->getPocketConsumerKey(), | ||
117 | 'access_token' => $this->accessToken, | ||
118 | 'detailType' => 'complete', | ||
119 | 'state' => 'all', | ||
120 | 'sort' => 'newest', | ||
121 | 'count' => self::NB_ELEMENTS, | ||
122 | 'offset' => $offset, | ||
123 | ])); | ||
133 | } catch (RequestException $e) { | 124 | } catch (RequestException $e) { |
134 | $this->logger->error(sprintf('PocketImport: Failed to import: %s', $e->getMessage()), ['exception' => $e]); | 125 | $this->logger->error(sprintf('PocketImport: Failed to import: %s', $e->getMessage()), ['exception' => $e]); |
135 | 126 | ||
136 | return false; | 127 | return false; |
137 | } | 128 | } |
138 | 129 | ||
139 | $entries = $response->json(); | 130 | $entries = $this->jsonDecode($response); |
140 | 131 | ||
141 | if ($this->producer) { | 132 | if ($this->producer) { |
142 | $this->parseEntriesForProducer($entries['list']); | 133 | $this->parseEntriesForProducer($entries['list']); |
@@ -159,13 +150,14 @@ class PocketImport extends AbstractImport | |||
159 | } | 150 | } |
160 | 151 | ||
161 | /** | 152 | /** |
162 | * Set the Guzzle client. | 153 | * Set the Http client. |
163 | * | 154 | * |
164 | * @param Client $client | 155 | * @param HttpClient $client |
156 | * @param MessageFactory|null $messageFactory | ||
165 | */ | 157 | */ |
166 | public function setClient(Client $client) | 158 | public function setClient(HttpClient $client, MessageFactory $messageFactory = null) |
167 | { | 159 | { |
168 | $this->client = $client; | 160 | $this->client = new HttpMethodsClient(new PluginClient($client, [new ErrorPlugin()]), $messageFactory ?: MessageFactoryDiscovery::find()); |
169 | } | 161 | } |
170 | 162 | ||
171 | /** | 163 | /** |
@@ -206,7 +198,7 @@ class PocketImport extends AbstractImport | |||
206 | $this->fetchContent($entry, $url); | 198 | $this->fetchContent($entry, $url); |
207 | 199 | ||
208 | // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted | 200 | // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted |
209 | $entry->setArchived(1 === (int) $importedEntry['status'] || $this->markAsRead); | 201 | $entry->updateArchived(1 === (int) $importedEntry['status'] || $this->markAsRead); |
210 | 202 | ||
211 | // 0 or 1 - 1 if the item is starred | 203 | // 0 or 1 - 1 if the item is starred |
212 | $entry->setStarred(1 === (int) $importedEntry['favorite']); | 204 | $entry->setStarred(1 === (int) $importedEntry['favorite']); |
@@ -252,4 +244,15 @@ class PocketImport extends AbstractImport | |||
252 | 244 | ||
253 | return $importedEntry; | 245 | return $importedEntry; |
254 | } | 246 | } |
247 | |||
248 | protected function jsonDecode(ResponseInterface $response) | ||
249 | { | ||
250 | $data = json_decode((string) $response->getBody(), true); | ||
251 | |||
252 | if (JSON_ERROR_NONE !== json_last_error()) { | ||
253 | throw new \InvalidArgumentException('Unable to parse JSON data: ' . json_last_error_msg()); | ||
254 | } | ||
255 | |||
256 | return $data; | ||
257 | } | ||
255 | } | 258 | } |
diff --git a/src/Wallabag/ImportBundle/Import/ReadabilityImport.php b/src/Wallabag/ImportBundle/Import/ReadabilityImport.php index a5f3798e..c5abf189 100644 --- a/src/Wallabag/ImportBundle/Import/ReadabilityImport.php +++ b/src/Wallabag/ImportBundle/Import/ReadabilityImport.php | |||
@@ -123,7 +123,7 @@ class ReadabilityImport extends AbstractImport | |||
123 | // update entry with content (in case fetching failed, the given entry will be return) | 123 | // update entry with content (in case fetching failed, the given entry will be return) |
124 | $this->fetchContent($entry, $data['url'], $data); | 124 | $this->fetchContent($entry, $data['url'], $data); |
125 | 125 | ||
126 | $entry->setArchived($data['is_archived']); | 126 | $entry->updateArchived($data['is_archived']); |
127 | $entry->setStarred($data['is_starred']); | 127 | $entry->setStarred($data['is_starred']); |
128 | $entry->setCreatedAt(new \DateTime($data['created_at'])); | 128 | $entry->setCreatedAt(new \DateTime($data['created_at'])); |
129 | 129 | ||
diff --git a/src/Wallabag/ImportBundle/Import/WallabagImport.php b/src/Wallabag/ImportBundle/Import/WallabagImport.php index 58b6a970..75a28fbf 100644 --- a/src/Wallabag/ImportBundle/Import/WallabagImport.php +++ b/src/Wallabag/ImportBundle/Import/WallabagImport.php | |||
@@ -134,7 +134,7 @@ abstract class WallabagImport extends AbstractImport | |||
134 | $entry->setPreviewPicture($importedEntry['preview_picture']); | 134 | $entry->setPreviewPicture($importedEntry['preview_picture']); |
135 | } | 135 | } |
136 | 136 | ||
137 | $entry->setArchived($data['is_archived']); | 137 | $entry->updateArchived($data['is_archived']); |
138 | $entry->setStarred($data['is_starred']); | 138 | $entry->setStarred($data['is_starred']); |
139 | 139 | ||
140 | if (!empty($data['created_at'])) { | 140 | if (!empty($data['created_at'])) { |
diff --git a/src/Wallabag/ImportBundle/Import/WallabagV2Import.php b/src/Wallabag/ImportBundle/Import/WallabagV2Import.php index 3e085ecf..2ba26003 100644 --- a/src/Wallabag/ImportBundle/Import/WallabagV2Import.php +++ b/src/Wallabag/ImportBundle/Import/WallabagV2Import.php | |||
@@ -35,7 +35,9 @@ class WallabagV2Import extends WallabagImport | |||
35 | { | 35 | { |
36 | return [ | 36 | return [ |
37 | 'html' => $entry['content'], | 37 | 'html' => $entry['content'], |
38 | 'content_type' => $entry['mimetype'], | 38 | 'headers' => [ |
39 | 'content-type' => $entry['mimetype'], | ||
40 | ], | ||
39 | 'is_archived' => (bool) ($entry['is_archived'] || $this->markAsRead), | 41 | 'is_archived' => (bool) ($entry['is_archived'] || $this->markAsRead), |
40 | 'is_starred' => (bool) $entry['is_starred'], | 42 | 'is_starred' => (bool) $entry['is_starred'], |
41 | ] + $entry; | 43 | ] + $entry; |
diff --git a/src/Wallabag/ImportBundle/Resources/config/services.yml b/src/Wallabag/ImportBundle/Resources/config/services.yml index b224a6a2..973c0d03 100644 --- a/src/Wallabag/ImportBundle/Resources/config/services.yml +++ b/src/Wallabag/ImportBundle/Resources/config/services.yml | |||
@@ -7,13 +7,7 @@ services: | |||
7 | class: Wallabag\ImportBundle\Import\ImportChain | 7 | class: Wallabag\ImportBundle\Import\ImportChain |
8 | 8 | ||
9 | wallabag_import.pocket.client: | 9 | wallabag_import.pocket.client: |
10 | class: GuzzleHttp\Client | 10 | alias: 'httplug.client.wallabag_import.pocket.client' |
11 | arguments: | ||
12 | - | ||
13 | defaults: | ||
14 | headers: | ||
15 | content-type: "application/json" | ||
16 | X-Accept: "application/json" | ||
17 | 11 | ||
18 | wallabag_import.pocket.import: | 12 | wallabag_import.pocket.import: |
19 | class: Wallabag\ImportBundle\Import\PocketImport | 13 | class: Wallabag\ImportBundle\Import\PocketImport |
@@ -112,3 +106,11 @@ services: | |||
112 | - [ setLogger, [ "@logger" ]] | 106 | - [ setLogger, [ "@logger" ]] |
113 | tags: | 107 | tags: |
114 | - { name: wallabag_import.import, alias: chrome } | 108 | - { name: wallabag_import.import, alias: chrome } |
109 | |||
110 | wallabag_import.command.import: | ||
111 | class: Wallabag\ImportBundle\Command\ImportCommand | ||
112 | tags: ['console.command'] | ||
113 | |||
114 | wallabag_import.command.redis_worker: | ||
115 | class: Wallabag\ImportBundle\Command\RedisWorkerCommand | ||
116 | tags: ['console.command'] | ||
diff --git a/src/Wallabag/UserBundle/Controller/ManageController.php b/src/Wallabag/UserBundle/Controller/ManageController.php index f3de656f..63a06206 100644 --- a/src/Wallabag/UserBundle/Controller/ManageController.php +++ b/src/Wallabag/UserBundle/Controller/ManageController.php | |||
@@ -7,10 +7,9 @@ use FOS\UserBundle\FOSUserEvents; | |||
7 | use Pagerfanta\Adapter\DoctrineORMAdapter; | 7 | use Pagerfanta\Adapter\DoctrineORMAdapter; |
8 | use Pagerfanta\Exception\OutOfRangeCurrentPageException; | 8 | use Pagerfanta\Exception\OutOfRangeCurrentPageException; |
9 | use Pagerfanta\Pagerfanta; | 9 | use Pagerfanta\Pagerfanta; |
10 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; | ||
11 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
12 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 10 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
13 | use Symfony\Component\HttpFoundation\Request; | 11 | use Symfony\Component\HttpFoundation\Request; |
12 | use Symfony\Component\Routing\Annotation\Route; | ||
14 | use Wallabag\UserBundle\Entity\User; | 13 | use Wallabag\UserBundle\Entity\User; |
15 | use Wallabag\UserBundle\Form\SearchUserType; | 14 | use Wallabag\UserBundle\Form\SearchUserType; |
16 | 15 | ||
@@ -22,8 +21,7 @@ class ManageController extends Controller | |||
22 | /** | 21 | /** |
23 | * Creates a new User entity. | 22 | * Creates a new User entity. |
24 | * | 23 | * |
25 | * @Route("/new", name="user_new") | 24 | * @Route("/new", name="user_new", methods={"GET", "POST"}) |
26 | * @Method({"GET", "POST"}) | ||
27 | */ | 25 | */ |
28 | public function newAction(Request $request) | 26 | public function newAction(Request $request) |
29 | { | 27 | { |
@@ -60,19 +58,33 @@ class ManageController extends Controller | |||
60 | /** | 58 | /** |
61 | * Displays a form to edit an existing User entity. | 59 | * Displays a form to edit an existing User entity. |
62 | * | 60 | * |
63 | * @Route("/{id}/edit", name="user_edit") | 61 | * @Route("/{id}/edit", name="user_edit", methods={"GET", "POST"}) |
64 | * @Method({"GET", "POST"}) | ||
65 | */ | 62 | */ |
66 | public function editAction(Request $request, User $user) | 63 | public function editAction(Request $request, User $user) |
67 | { | 64 | { |
65 | $userManager = $this->container->get('fos_user.user_manager'); | ||
66 | |||
68 | $deleteForm = $this->createDeleteForm($user); | 67 | $deleteForm = $this->createDeleteForm($user); |
69 | $editForm = $this->createForm('Wallabag\UserBundle\Form\UserType', $user); | 68 | $form = $this->createForm('Wallabag\UserBundle\Form\UserType', $user); |
70 | $editForm->handleRequest($request); | 69 | $form->handleRequest($request); |
71 | 70 | ||
72 | if ($editForm->isSubmitted() && $editForm->isValid()) { | 71 | // `googleTwoFactor` isn't a field within the User entity, we need to define it's value in a different way |
73 | $em = $this->getDoctrine()->getManager(); | 72 | if ($this->getParameter('twofactor_auth') && true === $user->isGoogleAuthenticatorEnabled() && false === $form->isSubmitted()) { |
74 | $em->persist($user); | 73 | $form->get('googleTwoFactor')->setData(true); |
75 | $em->flush(); | 74 | } |
75 | |||
76 | if ($form->isSubmitted() && $form->isValid()) { | ||
77 | // handle creation / reset of the OTP secret if checkbox changed from the previous state | ||
78 | if ($this->getParameter('twofactor_auth')) { | ||
79 | if (true === $form->get('googleTwoFactor')->getData() && false === $user->isGoogleAuthenticatorEnabled()) { | ||
80 | $user->setGoogleAuthenticatorSecret($this->get('scheb_two_factor.security.google_authenticator')->generateSecret()); | ||
81 | $user->setEmailTwoFactor(false); | ||
82 | } elseif (false === $form->get('googleTwoFactor')->getData() && true === $user->isGoogleAuthenticatorEnabled()) { | ||
83 | $user->setGoogleAuthenticatorSecret(null); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | $userManager->updateUser($user); | ||
76 | 88 | ||
77 | $this->get('session')->getFlashBag()->add( | 89 | $this->get('session')->getFlashBag()->add( |
78 | 'notice', | 90 | 'notice', |
@@ -84,7 +96,7 @@ class ManageController extends Controller | |||
84 | 96 | ||
85 | return $this->render('WallabagUserBundle:Manage:edit.html.twig', [ | 97 | return $this->render('WallabagUserBundle:Manage:edit.html.twig', [ |
86 | 'user' => $user, | 98 | 'user' => $user, |
87 | 'edit_form' => $editForm->createView(), | 99 | 'edit_form' => $form->createView(), |
88 | 'delete_form' => $deleteForm->createView(), | 100 | 'delete_form' => $deleteForm->createView(), |
89 | 'twofactor_auth' => $this->getParameter('twofactor_auth'), | 101 | 'twofactor_auth' => $this->getParameter('twofactor_auth'), |
90 | ]); | 102 | ]); |
@@ -93,8 +105,7 @@ class ManageController extends Controller | |||
93 | /** | 105 | /** |
94 | * Deletes a User entity. | 106 | * Deletes a User entity. |
95 | * | 107 | * |
96 | * @Route("/{id}", name="user_delete") | 108 | * @Route("/{id}", name="user_delete", methods={"DELETE"}) |
97 | * @Method("DELETE") | ||
98 | */ | 109 | */ |
99 | public function deleteAction(Request $request, User $user) | 110 | public function deleteAction(Request $request, User $user) |
100 | { | 111 | { |
@@ -135,8 +146,6 @@ class ManageController extends Controller | |||
135 | $form->handleRequest($request); | 146 | $form->handleRequest($request); |
136 | 147 | ||
137 | if ($form->isSubmitted() && $form->isValid()) { | 148 | if ($form->isSubmitted() && $form->isValid()) { |
138 | $this->get('logger')->info('searching users'); | ||
139 | |||
140 | $searchTerm = (isset($request->get('search_user')['term']) ? $request->get('search_user')['term'] : ''); | 149 | $searchTerm = (isset($request->get('search_user')['term']) ? $request->get('search_user')['term'] : ''); |
141 | 150 | ||
142 | $qb = $em->getRepository('WallabagUserBundle:User')->getQueryBuilderForSearch($searchTerm); | 151 | $qb = $em->getRepository('WallabagUserBundle:User')->getQueryBuilderForSearch($searchTerm); |
@@ -161,7 +170,7 @@ class ManageController extends Controller | |||
161 | } | 170 | } |
162 | 171 | ||
163 | /** | 172 | /** |
164 | * Creates a form to delete a User entity. | 173 | * Create a form to delete a User entity. |
165 | * | 174 | * |
166 | * @param User $user The User entity | 175 | * @param User $user The User entity |
167 | * | 176 | * |
diff --git a/src/Wallabag/UserBundle/DataFixtures/ORM/LoadUserData.php b/src/Wallabag/UserBundle/DataFixtures/UserFixtures.php index 26dbda3b..1e375e09 100644 --- a/src/Wallabag/UserBundle/DataFixtures/ORM/LoadUserData.php +++ b/src/Wallabag/UserBundle/DataFixtures/UserFixtures.php | |||
@@ -1,13 +1,12 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Wallabag\UserBundle\DataFixtures\ORM; | 3 | namespace Wallabag\UserBundle\DataFixtures; |
4 | 4 | ||
5 | use Doctrine\Common\DataFixtures\AbstractFixture; | 5 | use Doctrine\Bundle\FixturesBundle\Fixture; |
6 | use Doctrine\Common\DataFixtures\OrderedFixtureInterface; | ||
7 | use Doctrine\Common\Persistence\ObjectManager; | 6 | use Doctrine\Common\Persistence\ObjectManager; |
8 | use Wallabag\UserBundle\Entity\User; | 7 | use Wallabag\UserBundle\Entity\User; |
9 | 8 | ||
10 | class LoadUserData extends AbstractFixture implements OrderedFixtureInterface | 9 | class UserFixtures extends Fixture |
11 | { | 10 | { |
12 | /** | 11 | /** |
13 | * {@inheritdoc} | 12 | * {@inheritdoc} |
@@ -50,12 +49,4 @@ class LoadUserData extends AbstractFixture implements OrderedFixtureInterface | |||
50 | 49 | ||
51 | $manager->flush(); | 50 | $manager->flush(); |
52 | } | 51 | } |
53 | |||
54 | /** | ||
55 | * {@inheritdoc} | ||
56 | */ | ||
57 | public function getOrder() | ||
58 | { | ||
59 | return 10; | ||
60 | } | ||
61 | } | 52 | } |
diff --git a/src/Wallabag/UserBundle/Entity/User.php b/src/Wallabag/UserBundle/Entity/User.php index 48446e3c..43fa6a80 100644 --- a/src/Wallabag/UserBundle/Entity/User.php +++ b/src/Wallabag/UserBundle/Entity/User.php | |||
@@ -8,8 +8,9 @@ use FOS\UserBundle\Model\User as BaseUser; | |||
8 | use JMS\Serializer\Annotation\Accessor; | 8 | use JMS\Serializer\Annotation\Accessor; |
9 | use JMS\Serializer\Annotation\Groups; | 9 | use JMS\Serializer\Annotation\Groups; |
10 | use JMS\Serializer\Annotation\XmlRoot; | 10 | use JMS\Serializer\Annotation\XmlRoot; |
11 | use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface; | 11 | use Scheb\TwoFactorBundle\Model\BackupCodeInterface; |
12 | use Scheb\TwoFactorBundle\Model\TrustedComputerInterface; | 12 | use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface as EmailTwoFactorInterface; |
13 | use Scheb\TwoFactorBundle\Model\Google\TwoFactorInterface as GoogleTwoFactorInterface; | ||
13 | use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; | 14 | use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; |
14 | use Symfony\Component\Security\Core\User\UserInterface; | 15 | use Symfony\Component\Security\Core\User\UserInterface; |
15 | use Wallabag\ApiBundle\Entity\Client; | 16 | use Wallabag\ApiBundle\Entity\Client; |
@@ -28,7 +29,7 @@ use Wallabag\CoreBundle\Helper\EntityTimestampsTrait; | |||
28 | * @UniqueEntity("email") | 29 | * @UniqueEntity("email") |
29 | * @UniqueEntity("username") | 30 | * @UniqueEntity("username") |
30 | */ | 31 | */ |
31 | class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterface | 32 | class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorInterface, BackupCodeInterface |
32 | { | 33 | { |
33 | use EntityTimestampsTrait; | 34 | use EntityTimestampsTrait; |
34 | 35 | ||
@@ -123,16 +124,21 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
123 | private $authCode; | 124 | private $authCode; |
124 | 125 | ||
125 | /** | 126 | /** |
126 | * @var bool | 127 | * @ORM\Column(name="googleAuthenticatorSecret", type="string", nullable=true) |
127 | * | ||
128 | * @ORM\Column(type="boolean") | ||
129 | */ | 128 | */ |
130 | private $twoFactorAuthentication = false; | 129 | private $googleAuthenticatorSecret; |
131 | 130 | ||
132 | /** | 131 | /** |
133 | * @ORM\Column(type="json_array", nullable=true) | 132 | * @ORM\Column(type="json_array", nullable=true) |
134 | */ | 133 | */ |
135 | private $trusted; | 134 | private $backupCodes; |
135 | |||
136 | /** | ||
137 | * @var bool | ||
138 | * | ||
139 | * @ORM\Column(type="boolean") | ||
140 | */ | ||
141 | private $emailTwoFactor = false; | ||
136 | 142 | ||
137 | public function __construct() | 143 | public function __construct() |
138 | { | 144 | { |
@@ -233,49 +239,119 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
233 | /** | 239 | /** |
234 | * @return bool | 240 | * @return bool |
235 | */ | 241 | */ |
236 | public function isTwoFactorAuthentication() | 242 | public function isEmailTwoFactor() |
237 | { | 243 | { |
238 | return $this->twoFactorAuthentication; | 244 | return $this->emailTwoFactor; |
239 | } | 245 | } |
240 | 246 | ||
241 | /** | 247 | /** |
242 | * @param bool $twoFactorAuthentication | 248 | * @param bool $emailTwoFactor |
243 | */ | 249 | */ |
244 | public function setTwoFactorAuthentication($twoFactorAuthentication) | 250 | public function setEmailTwoFactor($emailTwoFactor) |
245 | { | 251 | { |
246 | $this->twoFactorAuthentication = $twoFactorAuthentication; | 252 | $this->emailTwoFactor = $emailTwoFactor; |
247 | } | 253 | } |
248 | 254 | ||
249 | public function isEmailAuthEnabled() | 255 | /** |
256 | * Used in the user config form to be "like" the email option. | ||
257 | */ | ||
258 | public function isGoogleTwoFactor() | ||
259 | { | ||
260 | return $this->isGoogleAuthenticatorEnabled(); | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * {@inheritdoc} | ||
265 | */ | ||
266 | public function isEmailAuthEnabled(): bool | ||
250 | { | 267 | { |
251 | return $this->twoFactorAuthentication; | 268 | return $this->emailTwoFactor; |
252 | } | 269 | } |
253 | 270 | ||
254 | public function getEmailAuthCode() | 271 | /** |
272 | * {@inheritdoc} | ||
273 | */ | ||
274 | public function getEmailAuthCode(): string | ||
255 | { | 275 | { |
256 | return $this->authCode; | 276 | return $this->authCode; |
257 | } | 277 | } |
258 | 278 | ||
259 | public function setEmailAuthCode($authCode) | 279 | /** |
280 | * {@inheritdoc} | ||
281 | */ | ||
282 | public function setEmailAuthCode(string $authCode): void | ||
260 | { | 283 | { |
261 | $this->authCode = $authCode; | 284 | $this->authCode = $authCode; |
262 | } | 285 | } |
263 | 286 | ||
264 | public function addTrustedComputer($token, \DateTime $validUntil) | 287 | /** |
288 | * {@inheritdoc} | ||
289 | */ | ||
290 | public function getEmailAuthRecipient(): string | ||
265 | { | 291 | { |
266 | $this->trusted[$token] = $validUntil->format('r'); | 292 | return $this->email; |
267 | } | 293 | } |
268 | 294 | ||
269 | public function isTrustedComputer($token) | 295 | /** |
296 | * {@inheritdoc} | ||
297 | */ | ||
298 | public function isGoogleAuthenticatorEnabled(): bool | ||
270 | { | 299 | { |
271 | if (isset($this->trusted[$token])) { | 300 | return $this->googleAuthenticatorSecret ? true : false; |
272 | $now = new \DateTime(); | 301 | } |
273 | $validUntil = new \DateTime($this->trusted[$token]); | ||
274 | 302 | ||
275 | return $now < $validUntil; | 303 | /** |
276 | } | 304 | * {@inheritdoc} |
305 | */ | ||
306 | public function getGoogleAuthenticatorUsername(): string | ||
307 | { | ||
308 | return $this->username; | ||
309 | } | ||
277 | 310 | ||
278 | return false; | 311 | /** |
312 | * {@inheritdoc} | ||
313 | */ | ||
314 | public function getGoogleAuthenticatorSecret(): string | ||
315 | { | ||
316 | return $this->googleAuthenticatorSecret; | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * {@inheritdoc} | ||
321 | */ | ||
322 | public function setGoogleAuthenticatorSecret(?string $googleAuthenticatorSecret): void | ||
323 | { | ||
324 | $this->googleAuthenticatorSecret = $googleAuthenticatorSecret; | ||
325 | } | ||
326 | |||
327 | public function setBackupCodes(array $codes = null) | ||
328 | { | ||
329 | $this->backupCodes = $codes; | ||
330 | } | ||
331 | |||
332 | public function getBackupCodes() | ||
333 | { | ||
334 | return $this->backupCodes; | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * {@inheritdoc} | ||
339 | */ | ||
340 | public function isBackupCode(string $code): bool | ||
341 | { | ||
342 | return false === $this->findBackupCode($code) ? false : true; | ||
343 | } | ||
344 | |||
345 | /** | ||
346 | * {@inheritdoc} | ||
347 | */ | ||
348 | public function invalidateBackupCode(string $code): void | ||
349 | { | ||
350 | $key = $this->findBackupCode($code); | ||
351 | |||
352 | if (false !== $key) { | ||
353 | unset($this->backupCodes[$key]); | ||
354 | } | ||
279 | } | 355 | } |
280 | 356 | ||
281 | /** | 357 | /** |
@@ -309,4 +385,24 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
309 | return $this->clients->first(); | 385 | return $this->clients->first(); |
310 | } | 386 | } |
311 | } | 387 | } |
388 | |||
389 | /** | ||
390 | * Try to find a backup code from the list of backup codes of the current user. | ||
391 | * | ||
392 | * @param string $code Given code from the user | ||
393 | * | ||
394 | * @return string|false | ||
395 | */ | ||
396 | private function findBackupCode(string $code) | ||
397 | { | ||
398 | foreach ($this->backupCodes as $key => $backupCode) { | ||
399 | // backup code are hashed using `password_hash` | ||
400 | // see ConfigController->otpAppAction | ||
401 | if (password_verify($code, $backupCode)) { | ||
402 | return $key; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | return false; | ||
407 | } | ||
312 | } | 408 | } |
diff --git a/src/Wallabag/UserBundle/EventListener/CreateConfigListener.php b/src/Wallabag/UserBundle/EventListener/CreateConfigListener.php index e4d55c19..81954213 100644 --- a/src/Wallabag/UserBundle/EventListener/CreateConfigListener.php +++ b/src/Wallabag/UserBundle/EventListener/CreateConfigListener.php | |||
@@ -6,6 +6,7 @@ use Doctrine\ORM\EntityManager; | |||
6 | use FOS\UserBundle\Event\UserEvent; | 6 | use FOS\UserBundle\Event\UserEvent; |
7 | use FOS\UserBundle\FOSUserEvents; | 7 | use FOS\UserBundle\FOSUserEvents; |
8 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; | 8 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
9 | use Symfony\Component\HttpFoundation\Session\Session; | ||
9 | use Wallabag\CoreBundle\Entity\Config; | 10 | use Wallabag\CoreBundle\Entity\Config; |
10 | 11 | ||
11 | /** | 12 | /** |
@@ -17,22 +18,24 @@ class CreateConfigListener implements EventSubscriberInterface | |||
17 | private $em; | 18 | private $em; |
18 | private $theme; | 19 | private $theme; |
19 | private $itemsOnPage; | 20 | private $itemsOnPage; |
20 | private $rssLimit; | 21 | private $feedLimit; |
21 | private $language; | 22 | private $language; |
22 | private $readingSpeed; | 23 | private $readingSpeed; |
23 | private $actionMarkAsRead; | 24 | private $actionMarkAsRead; |
24 | private $listMode; | 25 | private $listMode; |
26 | private $session; | ||
25 | 27 | ||
26 | public function __construct(EntityManager $em, $theme, $itemsOnPage, $rssLimit, $language, $readingSpeed, $actionMarkAsRead, $listMode) | 28 | public function __construct(EntityManager $em, $theme, $itemsOnPage, $feedLimit, $language, $readingSpeed, $actionMarkAsRead, $listMode, Session $session) |
27 | { | 29 | { |
28 | $this->em = $em; | 30 | $this->em = $em; |
29 | $this->theme = $theme; | 31 | $this->theme = $theme; |
30 | $this->itemsOnPage = $itemsOnPage; | 32 | $this->itemsOnPage = $itemsOnPage; |
31 | $this->rssLimit = $rssLimit; | 33 | $this->feedLimit = $feedLimit; |
32 | $this->language = $language; | 34 | $this->language = $language; |
33 | $this->readingSpeed = $readingSpeed; | 35 | $this->readingSpeed = $readingSpeed; |
34 | $this->actionMarkAsRead = $actionMarkAsRead; | 36 | $this->actionMarkAsRead = $actionMarkAsRead; |
35 | $this->listMode = $listMode; | 37 | $this->listMode = $listMode; |
38 | $this->session = $session; | ||
36 | } | 39 | } |
37 | 40 | ||
38 | public static function getSubscribedEvents() | 41 | public static function getSubscribedEvents() |
@@ -51,8 +54,8 @@ class CreateConfigListener implements EventSubscriberInterface | |||
51 | $config = new Config($event->getUser()); | 54 | $config = new Config($event->getUser()); |
52 | $config->setTheme($this->theme); | 55 | $config->setTheme($this->theme); |
53 | $config->setItemsPerPage($this->itemsOnPage); | 56 | $config->setItemsPerPage($this->itemsOnPage); |
54 | $config->setRssLimit($this->rssLimit); | 57 | $config->setFeedLimit($this->feedLimit); |
55 | $config->setLanguage($this->language); | 58 | $config->setLanguage($this->session->get('_locale', $this->language)); |
56 | $config->setReadingSpeed($this->readingSpeed); | 59 | $config->setReadingSpeed($this->readingSpeed); |
57 | $config->setActionMarkAsRead($this->actionMarkAsRead); | 60 | $config->setActionMarkAsRead($this->actionMarkAsRead); |
58 | $config->setListMode($this->listMode); | 61 | $config->setListMode($this->listMode); |
diff --git a/src/Wallabag/UserBundle/Form/UserType.php b/src/Wallabag/UserBundle/Form/UserType.php index 56fea640..026db9a2 100644 --- a/src/Wallabag/UserBundle/Form/UserType.php +++ b/src/Wallabag/UserBundle/Form/UserType.php | |||
@@ -35,9 +35,14 @@ class UserType extends AbstractType | |||
35 | 'required' => false, | 35 | 'required' => false, |
36 | 'label' => 'user.form.enabled_label', | 36 | 'label' => 'user.form.enabled_label', |
37 | ]) | 37 | ]) |
38 | ->add('twoFactorAuthentication', CheckboxType::class, [ | 38 | ->add('emailTwoFactor', CheckboxType::class, [ |
39 | 'required' => false, | 39 | 'required' => false, |
40 | 'label' => 'user.form.twofactor_label', | 40 | 'label' => 'user.form.twofactor_email_label', |
41 | ]) | ||
42 | ->add('googleTwoFactor', CheckboxType::class, [ | ||
43 | 'required' => false, | ||
44 | 'label' => 'user.form.twofactor_google_label', | ||
45 | 'mapped' => false, | ||
41 | ]) | 46 | ]) |
42 | ->add('save', SubmitType::class, [ | 47 | ->add('save', SubmitType::class, [ |
43 | 'label' => 'user.form.save', | 48 | 'label' => 'user.form.save', |
diff --git a/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php b/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php index aed805c9..2797efde 100644 --- a/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php +++ b/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php | |||
@@ -78,7 +78,7 @@ class AuthCodeMailer implements AuthCodeMailerInterface | |||
78 | * | 78 | * |
79 | * @param TwoFactorInterface $user | 79 | * @param TwoFactorInterface $user |
80 | */ | 80 | */ |
81 | public function sendAuthCode(TwoFactorInterface $user) | 81 | public function sendAuthCode(TwoFactorInterface $user): void |
82 | { | 82 | { |
83 | $template = $this->twig->loadTemplate('WallabagUserBundle:TwoFactor:email_auth_code.html.twig'); | 83 | $template = $this->twig->loadTemplate('WallabagUserBundle:TwoFactor:email_auth_code.html.twig'); |
84 | 84 | ||
@@ -97,7 +97,7 @@ class AuthCodeMailer implements AuthCodeMailerInterface | |||
97 | 97 | ||
98 | $message = new \Swift_Message(); | 98 | $message = new \Swift_Message(); |
99 | $message | 99 | $message |
100 | ->setTo($user->getEmail()) | 100 | ->setTo($user->getEmailAuthRecipient()) |
101 | ->setFrom($this->senderEmail, $this->senderName) | 101 | ->setFrom($this->senderEmail, $this->senderName) |
102 | ->setSubject($subject) | 102 | ->setSubject($subject) |
103 | ->setBody($bodyText, 'text/plain') | 103 | ->setBody($bodyText, 'text/plain') |
diff --git a/src/Wallabag/UserBundle/Repository/UserRepository.php b/src/Wallabag/UserBundle/Repository/UserRepository.php index be693d3b..4abd55f1 100644 --- a/src/Wallabag/UserBundle/Repository/UserRepository.php +++ b/src/Wallabag/UserBundle/Repository/UserRepository.php | |||
@@ -9,18 +9,18 @@ use Wallabag\UserBundle\Entity\User; | |||
9 | class UserRepository extends EntityRepository | 9 | class UserRepository extends EntityRepository |
10 | { | 10 | { |
11 | /** | 11 | /** |
12 | * Find a user by its username and rss roken. | 12 | * Find a user by its username and Feed token. |
13 | * | 13 | * |
14 | * @param string $username | 14 | * @param string $username |
15 | * @param string $rssToken | 15 | * @param string $feedToken |
16 | * | 16 | * |
17 | * @return User|null | 17 | * @return User|null |
18 | */ | 18 | */ |
19 | public function findOneByUsernameAndRsstoken($username, $rssToken) | 19 | public function findOneByUsernameAndFeedtoken($username, $feedToken) |
20 | { | 20 | { |
21 | return $this->createQueryBuilder('u') | 21 | return $this->createQueryBuilder('u') |
22 | ->leftJoin('u.config', 'c') | 22 | ->leftJoin('u.config', 'c') |
23 | ->where('c.rssToken = :rss_token')->setParameter('rss_token', $rssToken) | 23 | ->where('c.feedToken = :feed_token')->setParameter('feed_token', $feedToken) |
24 | ->andWhere('u.username = :username')->setParameter('username', $username) | 24 | ->andWhere('u.username = :username')->setParameter('username', $username) |
25 | ->getQuery() | 25 | ->getQuery() |
26 | ->getOneOrNullResult(); | 26 | ->getOneOrNullResult(); |
diff --git a/src/Wallabag/UserBundle/Resources/config/services.yml b/src/Wallabag/UserBundle/Resources/config/services.yml index d3925de3..2dcf3011 100644 --- a/src/Wallabag/UserBundle/Resources/config/services.yml +++ b/src/Wallabag/UserBundle/Resources/config/services.yml | |||
@@ -28,11 +28,12 @@ services: | |||
28 | - "@doctrine.orm.entity_manager" | 28 | - "@doctrine.orm.entity_manager" |
29 | - "%wallabag_core.theme%" | 29 | - "%wallabag_core.theme%" |
30 | - "%wallabag_core.items_on_page%" | 30 | - "%wallabag_core.items_on_page%" |
31 | - "%wallabag_core.rss_limit%" | 31 | - "%wallabag_core.feed_limit%" |
32 | - "%wallabag_core.language%" | 32 | - "%wallabag_core.language%" |
33 | - "%wallabag_core.reading_speed%" | 33 | - "%wallabag_core.reading_speed%" |
34 | - "%wallabag_core.action_mark_as_read%" | 34 | - "%wallabag_core.action_mark_as_read%" |
35 | - "%wallabag_core.list_mode%" | 35 | - "%wallabag_core.list_mode%" |
36 | - "@session" | ||
36 | tags: | 37 | tags: |
37 | - { name: kernel.event_subscriber } | 38 | - { name: kernel.event_subscriber } |
38 | 39 | ||
diff --git a/src/Wallabag/UserBundle/Resources/views/Authentication/form.html.twig b/src/Wallabag/UserBundle/Resources/views/Authentication/form.html.twig index c8471bdd..47a5cb78 100644 --- a/src/Wallabag/UserBundle/Resources/views/Authentication/form.html.twig +++ b/src/Wallabag/UserBundle/Resources/views/Authentication/form.html.twig | |||
@@ -1,7 +1,8 @@ | |||
1 | {# Override `vendor/scheb/two-factor-bundle/Resources/views/Authentication/form.html.twig` #} | ||
1 | {% extends "WallabagUserBundle::layout.html.twig" %} | 2 | {% extends "WallabagUserBundle::layout.html.twig" %} |
2 | 3 | ||
3 | {% block fos_user_content %} | 4 | {% block fos_user_content %} |
4 | <form class="form" action="" method="post"> | 5 | <form class="form" action="{{ path("2fa_login_check") }}" method="post"> |
5 | <div class="card-content"> | 6 | <div class="card-content"> |
6 | <div class="row"> | 7 | <div class="row"> |
7 | 8 | ||
@@ -9,14 +10,19 @@ | |||
9 | <p class="error">{{ flashMessage|trans }}</p> | 10 | <p class="error">{{ flashMessage|trans }}</p> |
10 | {% endfor %} | 11 | {% endfor %} |
11 | 12 | ||
13 | {# Authentication errors #} | ||
14 | {% if authenticationError %} | ||
15 | <p class="error">{{ authenticationError|trans(authenticationErrorData) }}</p> | ||
16 | {% endif %} | ||
17 | |||
12 | <div class="input-field col s12"> | 18 | <div class="input-field col s12"> |
13 | <label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label> | 19 | <label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label> |
14 | <input id="_auth_code" type="text" autocomplete="off" name="_auth_code" /> | 20 | <input id="_auth_code" type="text" autocomplete="off" name="{{ authCodeParameterName }}" /> |
15 | </div> | 21 | </div> |
16 | 22 | ||
17 | {% if useTrustedOption %} | 23 | {% if displayTrustedOption %} |
18 | <div class="input-field col s12"> | 24 | <div class="input-field col s12"> |
19 | <input id="_trusted" type="checkbox" name="_trusted" /> | 25 | <input id="_trusted" type="checkbox" name="{{ trustedParameterName }}" /> |
20 | <label for="_trusted">{{ "scheb_two_factor.trusted"|trans }}</label> | 26 | <label for="_trusted">{{ "scheb_two_factor.trusted"|trans }}</label> |
21 | </div> | 27 | </div> |
22 | {% endif %} | 28 | {% endif %} |
diff --git a/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig b/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig index 3ffd15f5..2de8f3a5 100644 --- a/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig +++ b/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig | |||
@@ -50,9 +50,14 @@ | |||
50 | {% if twofactor_auth %} | 50 | {% if twofactor_auth %} |
51 | <div class="row"> | 51 | <div class="row"> |
52 | <div class="input-field col s12"> | 52 | <div class="input-field col s12"> |
53 | {{ form_widget(edit_form.twoFactorAuthentication) }} | 53 | {{ form_widget(edit_form.emailTwoFactor) }} |
54 | {{ form_label(edit_form.twoFactorAuthentication) }} | 54 | {{ form_label(edit_form.emailTwoFactor) }} |
55 | {{ form_errors(edit_form.twoFactorAuthentication) }} | 55 | {{ form_errors(edit_form.emailTwoFactor) }} |
56 | </div> | ||
57 | <div class="input-field col s12"> | ||
58 | {{ form_widget(edit_form.googleTwoFactor) }} | ||
59 | {{ form_label(edit_form.googleTwoFactor) }} | ||
60 | {{ form_errors(edit_form.googleTwoFactor) }} | ||
56 | </div> | 61 | </div> |
57 | </div> | 62 | </div> |
58 | {% endif %} | 63 | {% endif %} |
diff --git a/src/Wallabag/UserBundle/Resources/views/Registration/register_content.html.twig b/src/Wallabag/UserBundle/Resources/views/Registration/register_content.html.twig index d0a85fc7..85cd4f0d 100644 --- a/src/Wallabag/UserBundle/Resources/views/Registration/register_content.html.twig +++ b/src/Wallabag/UserBundle/Resources/views/Registration/register_content.html.twig | |||
@@ -3,7 +3,6 @@ | |||
3 | {{ form_start(form, {'method': 'post', 'action': path('fos_user_registration_register'), 'attr': {'class': 'fos_user_registration_register'}}) }} | 3 | {{ form_start(form, {'method': 'post', 'action': path('fos_user_registration_register'), 'attr': {'class': 'fos_user_registration_register'}}) }} |
4 | <div class="card-content"> | 4 | <div class="card-content"> |
5 | <div class="row"> | 5 | <div class="row"> |
6 | |||
7 | {{ form_widget(form._token) }} | 6 | {{ form_widget(form._token) }} |
8 | 7 | ||
9 | {% for flashMessage in app.session.flashbag.get('notice') %} | 8 | {% for flashMessage in app.session.flashbag.get('notice') %} |
diff --git a/src/Wallabag/UserBundle/Resources/views/layout.html.twig b/src/Wallabag/UserBundle/Resources/views/layout.html.twig index f97e9870..a47b31d0 100644 --- a/src/Wallabag/UserBundle/Resources/views/layout.html.twig +++ b/src/Wallabag/UserBundle/Resources/views/layout.html.twig | |||
@@ -15,6 +15,11 @@ | |||
15 | {% block fos_user_content %} | 15 | {% block fos_user_content %} |
16 | {% endblock fos_user_content %} | 16 | {% endblock fos_user_content %} |
17 | </div> | 17 | </div> |
18 | <div class="center"> | ||
19 | <a href="{{ path('changeLocale', {'language': 'de'}) }}">Deutsch</a> – | ||
20 | <a href="{{ path('changeLocale', {'language': 'en'}) }}">English</a> – | ||
21 | <a href="{{ path('changeLocale', {'language': 'fr'}) }}">Français</a> | ||
22 | </div> | ||
18 | </div> | 23 | </div> |
19 | </main> | 24 | </main> |
20 | {% endblock %} | 25 | {% endblock %} |