diff options
Diffstat (limited to 'src/Wallabag')
44 files changed, 501 insertions, 234 deletions
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php index 06520af9..9f933adb 100644 --- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php +++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php | |||
@@ -14,6 +14,7 @@ use Wallabag\CoreBundle\Entity\Entry; | |||
14 | use Wallabag\CoreBundle\Entity\Tag; | 14 | use Wallabag\CoreBundle\Entity\Tag; |
15 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; | 15 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; |
16 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | 16 | use Wallabag\CoreBundle\Event\EntrySavedEvent; |
17 | use Wallabag\CoreBundle\Helper\UrlHasher; | ||
17 | 18 | ||
18 | class EntryRestController extends WallabagRestController | 19 | class EntryRestController extends WallabagRestController |
19 | { | 20 | { |
@@ -43,50 +44,45 @@ class EntryRestController extends WallabagRestController | |||
43 | 44 | ||
44 | $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'); |
45 | 46 | ||
46 | $urls = $request->query->get('urls', []); | ||
47 | $hashedUrls = $request->query->get('hashed_urls', []); | 47 | $hashedUrls = $request->query->get('hashed_urls', []); |
48 | $hashedUrl = $request->query->get('hashed_url', ''); | ||
49 | if (!empty($hashedUrl)) { | ||
50 | $hashedUrls[] = $hashedUrl; | ||
51 | } | ||
48 | 52 | ||
49 | // handle multiple urls first | 53 | $urls = $request->query->get('urls', []); |
50 | if (!empty($hashedUrls)) { | 54 | $url = $request->query->get('url', ''); |
51 | $results = []; | 55 | if (!empty($url)) { |
52 | foreach ($hashedUrls as $hashedUrl) { | 56 | $urls[] = $url; |
53 | $res = $repo->findByHashedUrlAndUserId($hashedUrl, $this->getUser()->getId()); | 57 | } |
54 | |||
55 | $results[$hashedUrl] = $this->returnExistInformation($res, $returnId); | ||
56 | } | ||
57 | 58 | ||
58 | return $this->sendResponse($results); | 59 | $urlHashMap = []; |
60 | foreach ($urls as $urlToHash) { | ||
61 | $urlHash = UrlHasher::hashUrl($urlToHash); | ||
62 | $hashedUrls[] = $urlHash; | ||
63 | $urlHashMap[$urlHash] = $urlToHash; | ||
59 | } | 64 | } |
60 | 65 | ||
61 | // @deprecated, to be remove in 3.0 | 66 | if (empty($hashedUrls)) { |
62 | if (!empty($urls)) { | 67 | throw $this->createAccessDeniedException('URL is empty?, logged user id: ' . $this->getUser()->getId()); |
63 | $results = []; | 68 | } |
64 | foreach ($urls as $url) { | ||
65 | $res = $repo->findByUrlAndUserId($url, $this->getUser()->getId()); | ||
66 | 69 | ||
67 | $results[$url] = $this->returnExistInformation($res, $returnId); | 70 | $results = []; |
68 | } | 71 | foreach ($hashedUrls as $hashedUrlToSearch) { |
72 | $res = $repo->findByHashedUrlAndUserId($hashedUrlToSearch, $this->getUser()->getId()); | ||
69 | 73 | ||
70 | return $this->sendResponse($results); | 74 | $results[$hashedUrlToSearch] = $this->returnExistInformation($res, $returnId); |
71 | } | 75 | } |
72 | 76 | ||
73 | // let's see if it is a simple url? | 77 | $results = $this->replaceUrlHashes($results, $urlHashMap); |
74 | $url = $request->query->get('url', ''); | ||
75 | $hashedUrl = $request->query->get('hashed_url', ''); | ||
76 | 78 | ||
77 | if (empty($url) && empty($hashedUrl)) { | 79 | if (!empty($url) || !empty($hashedUrl)) { |
78 | throw $this->createAccessDeniedException('URL is empty?, logged user id: ' . $this->getUser()->getId()); | 80 | $hu = array_keys($results)[0]; |
79 | } | ||
80 | 81 | ||
81 | $method = 'findByUrlAndUserId'; | 82 | return $this->sendResponse(['exists' => $results[$hu]]); |
82 | if (!empty($hashedUrl)) { | ||
83 | $method = 'findByHashedUrlAndUserId'; | ||
84 | $url = $hashedUrl; | ||
85 | } | 83 | } |
86 | 84 | ||
87 | $res = $repo->$method($url, $this->getUser()->getId()); | 85 | return $this->sendResponse($results); |
88 | |||
89 | return $this->sendResponse(['exists' => $this->returnExistInformation($res, $returnId)]); | ||
90 | } | 86 | } |
91 | 87 | ||
92 | /** | 88 | /** |
@@ -103,6 +99,7 @@ class EntryRestController extends WallabagRestController | |||
103 | * {"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."}, |
104 | * {"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."}, |
105 | * {"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."}, | ||
106 | * } | 103 | * } |
107 | * ) | 104 | * ) |
108 | * | 105 | * |
@@ -121,6 +118,7 @@ class EntryRestController extends WallabagRestController | |||
121 | $perPage = (int) $request->query->get('perPage', 30); | 118 | $perPage = (int) $request->query->get('perPage', 30); |
122 | $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', ''); |
123 | $since = $request->query->get('since', 0); | 120 | $since = $request->query->get('since', 0); |
121 | $detail = strtolower($request->query->get('detail', 'full')); | ||
124 | 122 | ||
125 | try { | 123 | try { |
126 | /** @var \Pagerfanta\Pagerfanta $pager */ | 124 | /** @var \Pagerfanta\Pagerfanta $pager */ |
@@ -132,7 +130,8 @@ class EntryRestController extends WallabagRestController | |||
132 | $sort, | 130 | $sort, |
133 | $order, | 131 | $order, |
134 | $since, | 132 | $since, |
135 | $tags | 133 | $tags, |
134 | $detail | ||
136 | ); | 135 | ); |
137 | } catch (\Exception $e) { | 136 | } catch (\Exception $e) { |
138 | throw new BadRequestHttpException($e->getMessage()); | 137 | throw new BadRequestHttpException($e->getMessage()); |
@@ -156,6 +155,7 @@ class EntryRestController extends WallabagRestController | |||
156 | 'perPage' => $perPage, | 155 | 'perPage' => $perPage, |
157 | 'tags' => $tags, | 156 | 'tags' => $tags, |
158 | 'since' => $since, | 157 | 'since' => $since, |
158 | 'detail' => $detail, | ||
159 | ], | 159 | ], |
160 | true | 160 | true |
161 | ) | 161 | ) |
@@ -365,9 +365,7 @@ class EntryRestController extends WallabagRestController | |||
365 | 'language' => !empty($data['language']) ? $data['language'] : $entry->getLanguage(), | 365 | 'language' => !empty($data['language']) ? $data['language'] : $entry->getLanguage(), |
366 | 'date' => !empty($data['publishedAt']) ? $data['publishedAt'] : $entry->getPublishedAt(), | 366 | 'date' => !empty($data['publishedAt']) ? $data['publishedAt'] : $entry->getPublishedAt(), |
367 | // faking the open graph preview picture | 367 | // faking the open graph preview picture |
368 | 'open_graph' => [ | 368 | 'image' => !empty($data['picture']) ? $data['picture'] : $entry->getPreviewPicture(), |
369 | 'og_image' => !empty($data['picture']) ? $data['picture'] : $entry->getPreviewPicture(), | ||
370 | ], | ||
371 | 'authors' => \is_string($data['authors']) ? explode(',', $data['authors']) : $entry->getPublishedBy(), | 369 | 'authors' => \is_string($data['authors']) ? explode(',', $data['authors']) : $entry->getPublishedBy(), |
372 | ] | 370 | ] |
373 | ); | 371 | ); |
@@ -566,7 +564,7 @@ class EntryRestController extends WallabagRestController | |||
566 | } | 564 | } |
567 | 565 | ||
568 | // if refreshing entry failed, don't save it | 566 | // if refreshing entry failed, don't save it |
569 | if ($this->getParameter('wallabag_core.fetching_error_message') === $entry->getContent()) { | 567 | if ($this->container->getParameter('wallabag_core.fetching_error_message') === $entry->getContent()) { |
570 | return new JsonResponse([], 304); | 568 | return new JsonResponse([], 304); |
571 | } | 569 | } |
572 | 570 | ||
@@ -803,6 +801,24 @@ class EntryRestController extends WallabagRestController | |||
803 | } | 801 | } |
804 | 802 | ||
805 | /** | 803 | /** |
804 | * Replace the hashedUrl keys in $results with the unhashed URL from the | ||
805 | * request, as recorded in $urlHashMap. | ||
806 | */ | ||
807 | private function replaceUrlHashes(array $results, array $urlHashMap) | ||
808 | { | ||
809 | $newResults = []; | ||
810 | foreach ($results as $hash => $res) { | ||
811 | if (isset($urlHashMap[$hash])) { | ||
812 | $newResults[$urlHashMap[$hash]] = $res; | ||
813 | } else { | ||
814 | $newResults[$hash] = $res; | ||
815 | } | ||
816 | } | ||
817 | |||
818 | return $newResults; | ||
819 | } | ||
820 | |||
821 | /** | ||
806 | * Retrieve value from the request. | 822 | * Retrieve value from the request. |
807 | * Used for POST & PATCH on a an entry. | 823 | * Used for POST & PATCH on a an entry. |
808 | * | 824 | * |
@@ -830,8 +846,8 @@ class EntryRestController extends WallabagRestController | |||
830 | /** | 846 | /** |
831 | * 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. |
832 | * | 848 | * |
833 | * @param Entry|null $entry | 849 | * @param Entry|bool|null $entry |
834 | * @param bool $returnId | 850 | * @param bool $returnId |
835 | * | 851 | * |
836 | * @return bool|int | 852 | * @return bool|int |
837 | */ | 853 | */ |
diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php index 3a4dafcd..1b10a076 100644 --- a/src/Wallabag/ApiBundle/Controller/UserRestController.php +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php | |||
@@ -45,7 +45,7 @@ class UserRestController extends WallabagRestController | |||
45 | */ | 45 | */ |
46 | public function putUserAction(Request $request) | 46 | public function putUserAction(Request $request) |
47 | { | 47 | { |
48 | if (!$this->getParameter('fosuser_registration') || !$this->get('craue_config')->get('api_user_registration')) { | 48 | if (!$this->container->getParameter('fosuser_registration') || !$this->get('craue_config')->get('api_user_registration')) { |
49 | $json = $this->get('jms_serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json'); | 49 | $json = $this->get('jms_serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json'); |
50 | 50 | ||
51 | return (new JsonResponse()) | 51 | return (new JsonResponse()) |
diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php index f18b0910..44fd9683 100644 --- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php | |||
@@ -2,13 +2,13 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\ApiBundle\Controller; | 3 | namespace Wallabag\ApiBundle\Controller; |
4 | 4 | ||
5 | use FOS\RestBundle\Controller\FOSRestController; | 5 | use FOS\RestBundle\Controller\AbstractFOSRestController; |
6 | use JMS\Serializer\SerializationContext; | 6 | use JMS\Serializer\SerializationContext; |
7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | 7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; |
8 | use Symfony\Component\HttpFoundation\JsonResponse; | 8 | use Symfony\Component\HttpFoundation\JsonResponse; |
9 | use Symfony\Component\Security\Core\Exception\AccessDeniedException; | 9 | use Symfony\Component\Security\Core\Exception\AccessDeniedException; |
10 | 10 | ||
11 | class WallabagRestController extends FOSRestController | 11 | class WallabagRestController extends AbstractFOSRestController |
12 | { | 12 | { |
13 | /** | 13 | /** |
14 | * Retrieve version number. | 14 | * Retrieve version number. |
diff --git a/src/Wallabag/ApiBundle/Entity/AccessToken.php b/src/Wallabag/ApiBundle/Entity/AccessToken.php index 5e4099dd..98e0af3e 100644 --- a/src/Wallabag/ApiBundle/Entity/AccessToken.php +++ b/src/Wallabag/ApiBundle/Entity/AccessToken.php | |||
@@ -42,6 +42,7 @@ class AccessToken extends BaseAccessToken | |||
42 | 42 | ||
43 | /** | 43 | /** |
44 | * @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") | ||
45 | */ | 46 | */ |
46 | protected $user; | 47 | protected $user; |
47 | } | 48 | } |
diff --git a/src/Wallabag/ApiBundle/Entity/AuthCode.php b/src/Wallabag/ApiBundle/Entity/AuthCode.php index 5fa205ac..7c9c8539 100644 --- a/src/Wallabag/ApiBundle/Entity/AuthCode.php +++ b/src/Wallabag/ApiBundle/Entity/AuthCode.php | |||
@@ -42,6 +42,7 @@ class AuthCode extends BaseAuthCode | |||
42 | 42 | ||
43 | /** | 43 | /** |
44 | * @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") | ||
45 | */ | 46 | */ |
46 | protected $user; | 47 | protected $user; |
47 | } | 48 | } |
diff --git a/src/Wallabag/ApiBundle/Entity/RefreshToken.php b/src/Wallabag/ApiBundle/Entity/RefreshToken.php index dd8e9c63..55a507e1 100644 --- a/src/Wallabag/ApiBundle/Entity/RefreshToken.php +++ b/src/Wallabag/ApiBundle/Entity/RefreshToken.php | |||
@@ -42,6 +42,7 @@ class RefreshToken extends BaseRefreshToken | |||
42 | 42 | ||
43 | /** | 43 | /** |
44 | * @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") | ||
45 | */ | 46 | */ |
46 | protected $user; | 47 | protected $user; |
47 | } | 48 | } |
diff --git a/src/Wallabag/CoreBundle/Command/GenerateUrlHashesCommand.php b/src/Wallabag/CoreBundle/Command/GenerateUrlHashesCommand.php index 45bd8c5f..8f2bff11 100644 --- a/src/Wallabag/CoreBundle/Command/GenerateUrlHashesCommand.php +++ b/src/Wallabag/CoreBundle/Command/GenerateUrlHashesCommand.php | |||
@@ -7,6 +7,7 @@ use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; | |||
7 | use Symfony\Component\Console\Input\InputArgument; | 7 | use Symfony\Component\Console\Input\InputArgument; |
8 | use Symfony\Component\Console\Input\InputInterface; | 8 | use Symfony\Component\Console\Input\InputInterface; |
9 | use Symfony\Component\Console\Output\OutputInterface; | 9 | use Symfony\Component\Console\Output\OutputInterface; |
10 | use Wallabag\CoreBundle\Helper\UrlHasher; | ||
10 | use Wallabag\UserBundle\Entity\User; | 11 | use Wallabag\UserBundle\Entity\User; |
11 | 12 | ||
12 | class GenerateUrlHashesCommand extends ContainerAwareCommand | 13 | class GenerateUrlHashesCommand extends ContainerAwareCommand |
@@ -65,7 +66,7 @@ class GenerateUrlHashesCommand extends ContainerAwareCommand | |||
65 | 66 | ||
66 | $i = 1; | 67 | $i = 1; |
67 | foreach ($entries as $entry) { | 68 | foreach ($entries as $entry) { |
68 | $entry->setHashedUrl(hash('sha1', $entry->getUrl())); | 69 | $entry->setHashedUrl(UrlHasher::hashUrl($entry->getUrl())); |
69 | $em->persist($entry); | 70 | $em->persist($entry); |
70 | 71 | ||
71 | if (0 === ($i % 20)) { | 72 | if (0 === ($i % 20)) { |
@@ -84,7 +85,7 @@ class GenerateUrlHashesCommand extends ContainerAwareCommand | |||
84 | * | 85 | * |
85 | * @param string $username | 86 | * @param string $username |
86 | * | 87 | * |
87 | * @return \Wallabag\UserBundle\Entity\User | 88 | * @return User |
88 | */ | 89 | */ |
89 | private function getUser($username) | 90 | private function getUser($username) |
90 | { | 91 | { |
diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php index 3b281d48..cea41303 100644 --- a/src/Wallabag/CoreBundle/Controller/ConfigController.php +++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php | |||
@@ -300,6 +300,34 @@ class ConfigController extends Controller | |||
300 | } | 300 | } |
301 | 301 | ||
302 | /** | 302 | /** |
303 | * @param Request $request | ||
304 | * | ||
305 | * @Route("/revoke-token", name="revoke_token") | ||
306 | * | ||
307 | * @return RedirectResponse|JsonResponse | ||
308 | */ | ||
309 | public function revokeTokenAction(Request $request) | ||
310 | { | ||
311 | $config = $this->getConfig(); | ||
312 | $config->setFeedToken(null); | ||
313 | |||
314 | $em = $this->getDoctrine()->getManager(); | ||
315 | $em->persist($config); | ||
316 | $em->flush(); | ||
317 | |||
318 | if ($request->isXmlHttpRequest()) { | ||
319 | return new JsonResponse(); | ||
320 | } | ||
321 | |||
322 | $this->addFlash( | ||
323 | 'notice', | ||
324 | 'flashes.config.notice.feed_token_revoked' | ||
325 | ); | ||
326 | |||
327 | return $this->redirect($this->generateUrl('config') . '#set2'); | ||
328 | } | ||
329 | |||
330 | /** | ||
303 | * Deletes a tagging rule and redirect to the config homepage. | 331 | * Deletes a tagging rule and redirect to the config homepage. |
304 | * | 332 | * |
305 | * @param TaggingRule $rule | 333 | * @param TaggingRule $rule |
diff --git a/src/Wallabag/CoreBundle/DataFixtures/SiteCredentialFixtures.php b/src/Wallabag/CoreBundle/DataFixtures/SiteCredentialFixtures.php index c73173e8..9a7d116f 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/SiteCredentialFixtures.php +++ b/src/Wallabag/CoreBundle/DataFixtures/SiteCredentialFixtures.php | |||
@@ -5,20 +5,39 @@ namespace Wallabag\CoreBundle\DataFixtures; | |||
5 | use Doctrine\Bundle\FixturesBundle\Fixture; | 5 | use Doctrine\Bundle\FixturesBundle\Fixture; |
6 | use Doctrine\Common\DataFixtures\DependentFixtureInterface; | 6 | use Doctrine\Common\DataFixtures\DependentFixtureInterface; |
7 | use Doctrine\Common\Persistence\ObjectManager; | 7 | use Doctrine\Common\Persistence\ObjectManager; |
8 | use Symfony\Component\DependencyInjection\ContainerAwareInterface; | ||
9 | use Symfony\Component\DependencyInjection\ContainerInterface; | ||
8 | use Wallabag\CoreBundle\Entity\SiteCredential; | 10 | use Wallabag\CoreBundle\Entity\SiteCredential; |
9 | use Wallabag\UserBundle\DataFixtures\UserFixtures; | 11 | use Wallabag\UserBundle\DataFixtures\UserFixtures; |
10 | 12 | ||
11 | class SiteCredentialFixtures extends Fixture implements DependentFixtureInterface | 13 | class SiteCredentialFixtures extends Fixture implements DependentFixtureInterface, ContainerAwareInterface |
12 | { | 14 | { |
13 | /** | 15 | /** |
16 | * @var ContainerInterface | ||
17 | */ | ||
18 | private $container; | ||
19 | |||
20 | public function setContainer(ContainerInterface $container = null) | ||
21 | { | ||
22 | $this->container = $container; | ||
23 | } | ||
24 | |||
25 | /** | ||
14 | * {@inheritdoc} | 26 | * {@inheritdoc} |
15 | */ | 27 | */ |
16 | public function load(ObjectManager $manager) | 28 | public function load(ObjectManager $manager) |
17 | { | 29 | { |
18 | $credential = new SiteCredential($this->getReference('admin-user')); | 30 | $credential = new SiteCredential($this->getReference('admin-user')); |
19 | $credential->setHost('example.com'); | 31 | $credential->setHost('.super.com'); |
20 | $credential->setUsername('foo'); | 32 | $credential->setUsername($this->container->get('wallabag_core.helper.crypto_proxy')->crypt('.super')); |
21 | $credential->setPassword('bar'); | 33 | $credential->setPassword($this->container->get('wallabag_core.helper.crypto_proxy')->crypt('bar')); |
34 | |||
35 | $manager->persist($credential); | ||
36 | |||
37 | $credential = new SiteCredential($this->getReference('admin-user')); | ||
38 | $credential->setHost('paywall.example.com'); | ||
39 | $credential->setUsername($this->container->get('wallabag_core.helper.crypto_proxy')->crypt('paywall.example')); | ||
40 | $credential->setPassword($this->container->get('wallabag_core.helper.crypto_proxy')->crypt('bar')); | ||
22 | 41 | ||
23 | $manager->persist($credential); | 42 | $manager->persist($credential); |
24 | 43 | ||
diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index c3fb87d2..4d5e6fc9 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 | /** |
@@ -26,7 +27,8 @@ use Wallabag\UserBundle\Entity\User; | |||
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"}), |
29 | * @ORM\Index(name="hashed_url_user_id", columns={"user_id", "hashed_url"}, options={"lengths"={null, 40}}) | 30 | * @ORM\Index(name="hashed_url_user_id", columns={"user_id", "hashed_url"}, options={"lengths"={null, 40}}), |
31 | * @ORM\Index(name="hashed_given_url_user_id", columns={"user_id", "hashed_given_url"}, options={"lengths"={null, 40}}) | ||
30 | * } | 32 | * } |
31 | * ) | 33 | * ) |
32 | * @ORM\HasLifecycleCallbacks() | 34 | * @ORM\HasLifecycleCallbacks() |
@@ -67,6 +69,8 @@ class Entry | |||
67 | private $title; | 69 | private $title; |
68 | 70 | ||
69 | /** | 71 | /** |
72 | * Define the url fetched by wallabag (the final url after potential redirections). | ||
73 | * | ||
70 | * @var string | 74 | * @var string |
71 | * | 75 | * |
72 | * @Assert\NotBlank() | 76 | * @Assert\NotBlank() |
@@ -84,6 +88,35 @@ class Entry | |||
84 | private $hashedUrl; | 88 | private $hashedUrl; |
85 | 89 | ||
86 | /** | 90 | /** |
91 | * From where user retrieved/found the url (an other article, a twitter, or the given_url if non are provided). | ||
92 | * | ||
93 | * @var string | ||
94 | * | ||
95 | * @ORM\Column(name="origin_url", type="text", nullable=true) | ||
96 | * | ||
97 | * @Groups({"entries_for_user", "export_all"}) | ||
98 | */ | ||
99 | private $originUrl; | ||
100 | |||
101 | /** | ||
102 | * Define the url entered by the user (without redirections). | ||
103 | * | ||
104 | * @var string | ||
105 | * | ||
106 | * @ORM\Column(name="given_url", type="text", nullable=true) | ||
107 | * | ||
108 | * @Groups({"entries_for_user", "export_all"}) | ||
109 | */ | ||
110 | private $givenUrl; | ||
111 | |||
112 | /** | ||
113 | * @var string | ||
114 | * | ||
115 | * @ORM\Column(name="hashed_given_url", type="string", length=40, nullable=true) | ||
116 | */ | ||
117 | private $hashedGivenUrl; | ||
118 | |||
119 | /** | ||
87 | * @var bool | 120 | * @var bool |
88 | * | 121 | * |
89 | * @Exclude | 122 | * @Exclude |
@@ -262,15 +295,6 @@ class Entry | |||
262 | */ | 295 | */ |
263 | private $tags; | 296 | private $tags; |
264 | 297 | ||
265 | /** | ||
266 | * @var string | ||
267 | * | ||
268 | * @ORM\Column(name="origin_url", type="text", nullable=true) | ||
269 | * | ||
270 | * @Groups({"entries_for_user", "export_all"}) | ||
271 | */ | ||
272 | private $originUrl; | ||
273 | |||
274 | /* | 298 | /* |
275 | * @param User $user | 299 | * @param User $user |
276 | */ | 300 | */ |
@@ -324,7 +348,7 @@ class Entry | |||
324 | public function setUrl($url) | 348 | public function setUrl($url) |
325 | { | 349 | { |
326 | $this->url = $url; | 350 | $this->url = $url; |
327 | $this->hashedUrl = hash('sha1', $url); | 351 | $this->hashedUrl = UrlHasher::hashUrl($url); |
328 | 352 | ||
329 | return $this; | 353 | return $this; |
330 | } | 354 | } |
@@ -770,7 +794,7 @@ class Entry | |||
770 | } | 794 | } |
771 | 795 | ||
772 | /** | 796 | /** |
773 | * @return string | 797 | * @return string|null |
774 | */ | 798 | */ |
775 | public function getUid() | 799 | public function getUid() |
776 | { | 800 | { |
@@ -922,6 +946,31 @@ class Entry | |||
922 | } | 946 | } |
923 | 947 | ||
924 | /** | 948 | /** |
949 | * Set given url. | ||
950 | * | ||
951 | * @param string $givenUrl | ||
952 | * | ||
953 | * @return Entry | ||
954 | */ | ||
955 | public function setGivenUrl($givenUrl) | ||
956 | { | ||
957 | $this->givenUrl = $givenUrl; | ||
958 | $this->hashedGivenUrl = UrlHasher::hashUrl($givenUrl); | ||
959 | |||
960 | return $this; | ||
961 | } | ||
962 | |||
963 | /** | ||
964 | * Get given url. | ||
965 | * | ||
966 | * @return string | ||
967 | */ | ||
968 | public function getGivenUrl() | ||
969 | { | ||
970 | return $this->givenUrl; | ||
971 | } | ||
972 | |||
973 | /** | ||
925 | * @return string | 974 | * @return string |
926 | */ | 975 | */ |
927 | public function getHashedUrl() | 976 | public function getHashedUrl() |
diff --git a/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php b/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php index 90e00c62..c7502bac 100644 --- a/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php +++ b/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php | |||
@@ -62,11 +62,24 @@ class GrabySiteConfigBuilder implements SiteConfigBuilder | |||
62 | $host = substr($host, 4); | 62 | $host = substr($host, 4); |
63 | } | 63 | } |
64 | 64 | ||
65 | $credentials = null; | 65 | if (!$this->currentUser) { |
66 | if ($this->currentUser) { | 66 | $this->logger->debug('Auth: no current user defined.'); |
67 | $credentials = $this->credentialRepository->findOneByHostAndUser($host, $this->currentUser->getId()); | 67 | |
68 | return false; | ||
69 | } | ||
70 | |||
71 | $hosts = [$host]; | ||
72 | // will try to see for a host without the first subdomain (fr.example.org & .example.org) | ||
73 | $split = explode('.', $host); | ||
74 | |||
75 | if (\count($split) > 1) { | ||
76 | // remove first subdomain | ||
77 | array_shift($split); | ||
78 | $hosts[] = '.' . implode('.', $split); | ||
68 | } | 79 | } |
69 | 80 | ||
81 | $credentials = $this->credentialRepository->findOneByHostsAndUser($hosts, $this->currentUser->getId()); | ||
82 | |||
70 | if (null === $credentials) { | 83 | if (null === $credentials) { |
71 | $this->logger->debug('Auth: no credentials available for host.', ['host' => $host]); | 84 | $this->logger->debug('Auth: no credentials available for host.', ['host' => $host]); |
72 | 85 | ||
diff --git a/src/Wallabag/CoreBundle/Helper/ContentProxy.php b/src/Wallabag/CoreBundle/Helper/ContentProxy.php index 31953f12..5901df8b 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 | { |
@@ -47,13 +47,18 @@ class ContentProxy | |||
47 | */ | 47 | */ |
48 | public function updateEntry(Entry $entry, $url, array $content = [], $disableContentUpdate = false) | 48 | public function updateEntry(Entry $entry, $url, array $content = [], $disableContentUpdate = false) |
49 | { | 49 | { |
50 | $this->graby->toggleImgNoReferrer(true); | ||
50 | if (!empty($content['html'])) { | 51 | if (!empty($content['html'])) { |
51 | $content['html'] = $this->graby->cleanupHtml($content['html'], $url); | 52 | $content['html'] = $this->graby->cleanupHtml($content['html'], $url); |
52 | } | 53 | } |
53 | 54 | ||
54 | if ((empty($content) || false === $this->validateContent($content)) && false === $disableContentUpdate) { | 55 | if ((empty($content) || false === $this->validateContent($content)) && false === $disableContentUpdate) { |
55 | $fetchedContent = $this->graby->fetchContent($url); | 56 | $fetchedContent = $this->graby->fetchContent($url); |
56 | $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 | ); | ||
57 | 62 | ||
58 | // when content is imported, we have information in $content | 63 | // when content is imported, we have information in $content |
59 | // 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 |
@@ -73,6 +78,8 @@ class ContentProxy | |||
73 | $entry->setUrl($url); | 78 | $entry->setUrl($url); |
74 | } | 79 | } |
75 | 80 | ||
81 | $entry->setGivenUrl($url); | ||
82 | |||
76 | $this->stockEntry($entry, $content); | 83 | $this->stockEntry($entry, $content); |
77 | } | 84 | } |
78 | 85 | ||
@@ -187,8 +194,8 @@ class ContentProxy | |||
187 | /** | 194 | /** |
188 | * Try to sanitize the title of the fetched content from wrong character encodings and invalid UTF-8 character. | 195 | * Try to sanitize the title of the fetched content from wrong character encodings and invalid UTF-8 character. |
189 | * | 196 | * |
190 | * @param $title | 197 | * @param string $title |
191 | * @param $contentType | 198 | * @param string $contentType |
192 | * | 199 | * |
193 | * @return string | 200 | * @return string |
194 | */ | 201 | */ |
@@ -252,16 +259,14 @@ class ContentProxy | |||
252 | 259 | ||
253 | if (!empty($content['title'])) { | 260 | if (!empty($content['title'])) { |
254 | $entry->setTitle($content['title']); | 261 | $entry->setTitle($content['title']); |
255 | } elseif (!empty($content['open_graph']['og_title'])) { | ||
256 | $entry->setTitle($content['open_graph']['og_title']); | ||
257 | } | 262 | } |
258 | 263 | ||
259 | if (empty($content['html'])) { | 264 | if (empty($content['html'])) { |
260 | $content['html'] = $this->fetchingErrorMessage; | 265 | $content['html'] = $this->fetchingErrorMessage; |
261 | 266 | ||
262 | if (!empty($content['open_graph']['og_description'])) { | 267 | if (!empty($content['description'])) { |
263 | $content['html'] .= '<p><i>But we found a short description: </i></p>'; | 268 | $content['html'] .= '<p><i>But we found a short description: </i></p>'; |
264 | $content['html'] .= $content['open_graph']['og_description']; | 269 | $content['html'] .= $content['description']; |
265 | } | 270 | } |
266 | } | 271 | } |
267 | 272 | ||
@@ -276,8 +281,8 @@ class ContentProxy | |||
276 | $entry->setPublishedBy($content['authors']); | 281 | $entry->setPublishedBy($content['authors']); |
277 | } | 282 | } |
278 | 283 | ||
279 | if (!empty($content['all_headers']) && $this->storeArticleHeaders) { | 284 | if (!empty($content['headers'])) { |
280 | $entry->setHeaders($content['all_headers']); | 285 | $entry->setHeaders($content['headers']); |
281 | } | 286 | } |
282 | 287 | ||
283 | if (!empty($content['date'])) { | 288 | if (!empty($content['date'])) { |
@@ -288,17 +293,30 @@ class ContentProxy | |||
288 | $this->updateLanguage($entry, $content['language']); | 293 | $this->updateLanguage($entry, $content['language']); |
289 | } | 294 | } |
290 | 295 | ||
291 | if (!empty($content['open_graph']['og_image'])) { | 296 | $previewPictureUrl = ''; |
292 | $this->updatePreviewPicture($entry, $content['open_graph']['og_image']); | 297 | if (!empty($content['image'])) { |
298 | $previewPictureUrl = $content['image']; | ||
293 | } | 299 | } |
294 | 300 | ||
295 | // if content is an image, define it as a preview too | 301 | // if content is an image, define it as a preview too |
296 | if (!empty($content['content_type']) && \in_array($this->mimeGuesser->guess($content['content_type']), ['jpeg', 'jpg', 'gif', 'png'], true)) { | 302 | if (!empty($content['headers']['content-type']) && \in_array($this->mimeGuesser->guess($content['headers']['content-type']), ['jpeg', 'jpg', 'gif', 'png'], true)) { |
297 | $this->updatePreviewPicture($entry, $content['url']); | 303 | $previewPictureUrl = $content['url']; |
304 | } elseif (empty($previewPictureUrl)) { | ||
305 | $this->logger->debug('Extracting images from content to provide a default preview picture'); | ||
306 | $imagesUrls = DownloadImages::extractImagesUrlsFromHtml($content['html']); | ||
307 | $this->logger->debug(\count($imagesUrls) . ' pictures found'); | ||
308 | |||
309 | if (!empty($imagesUrls)) { | ||
310 | $previewPictureUrl = $imagesUrls[0]; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | if (!empty($content['headers']['content-type'])) { | ||
315 | $entry->setMimetype($content['headers']['content-type']); | ||
298 | } | 316 | } |
299 | 317 | ||
300 | if (!empty($content['content_type'])) { | 318 | if (!empty($previewPictureUrl)) { |
301 | $entry->setMimetype($content['content_type']); | 319 | $this->updatePreviewPicture($entry, $previewPictureUrl); |
302 | } | 320 | } |
303 | 321 | ||
304 | try { | 322 | try { |
diff --git a/src/Wallabag/CoreBundle/Helper/DownloadImages.php b/src/Wallabag/CoreBundle/Helper/DownloadImages.php index 9a7e9828..1d361d6d 100644 --- a/src/Wallabag/CoreBundle/Helper/DownloadImages.php +++ b/src/Wallabag/CoreBundle/Helper/DownloadImages.php | |||
@@ -2,8 +2,15 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\Helper; | 3 | namespace Wallabag\CoreBundle\Helper; |
4 | 4 | ||
5 | use GuzzleHttp\Client; | 5 | use GuzzleHttp\Psr7\Uri; |
6 | use GuzzleHttp\Message\Response; | 6 | use GuzzleHttp\Psr7\UriResolver; |
7 | use Http\Client\Common\HttpMethodsClient; | ||
8 | use Http\Client\Common\Plugin\ErrorPlugin; | ||
9 | use Http\Client\Common\PluginClient; | ||
10 | use Http\Client\HttpClient; | ||
11 | use Http\Discovery\MessageFactoryDiscovery; | ||
12 | use Http\Message\MessageFactory; | ||
13 | use Psr\Http\Message\ResponseInterface; | ||
7 | use Psr\Log\LoggerInterface; | 14 | use Psr\Log\LoggerInterface; |
8 | use Symfony\Component\DomCrawler\Crawler; | 15 | use Symfony\Component\DomCrawler\Crawler; |
9 | use Symfony\Component\Finder\Finder; | 16 | use Symfony\Component\Finder\Finder; |
@@ -19,9 +26,9 @@ class DownloadImages | |||
19 | private $mimeGuesser; | 26 | private $mimeGuesser; |
20 | private $wallabagUrl; | 27 | private $wallabagUrl; |
21 | 28 | ||
22 | public function __construct(Client $client, $baseFolder, $wallabagUrl, LoggerInterface $logger) | 29 | public function __construct(HttpClient $client, $baseFolder, $wallabagUrl, LoggerInterface $logger, MessageFactory $messageFactory = null) |
23 | { | 30 | { |
24 | $this->client = $client; | 31 | $this->client = new HttpMethodsClient(new PluginClient($client, [new ErrorPlugin()]), $messageFactory ?: MessageFactoryDiscovery::find()); |
25 | $this->baseFolder = $baseFolder; | 32 | $this->baseFolder = $baseFolder; |
26 | $this->wallabagUrl = rtrim($wallabagUrl, '/'); | 33 | $this->wallabagUrl = rtrim($wallabagUrl, '/'); |
27 | $this->logger = $logger; | 34 | $this->logger = $logger; |
@@ -31,6 +38,23 @@ class DownloadImages | |||
31 | } | 38 | } |
32 | 39 | ||
33 | /** | 40 | /** |
41 | * Process the html and extract images URLs from it. | ||
42 | * | ||
43 | * @param string $html | ||
44 | * | ||
45 | * @return string[] | ||
46 | */ | ||
47 | public static function extractImagesUrlsFromHtml($html) | ||
48 | { | ||
49 | $crawler = new Crawler($html); | ||
50 | $imagesCrawler = $crawler->filterXpath('//img'); | ||
51 | $imagesUrls = $imagesCrawler->extract(['src']); | ||
52 | $imagesSrcsetUrls = self::getSrcsetUrls($imagesCrawler); | ||
53 | |||
54 | return array_unique(array_merge($imagesUrls, $imagesSrcsetUrls)); | ||
55 | } | ||
56 | |||
57 | /** | ||
34 | * Process the html and extract image from it, save them to local and return the updated html. | 58 | * Process the html and extract image from it, save them to local and return the updated html. |
35 | * | 59 | * |
36 | * @param int $entryId ID of the entry | 60 | * @param int $entryId ID of the entry |
@@ -41,13 +65,7 @@ class DownloadImages | |||
41 | */ | 65 | */ |
42 | public function processHtml($entryId, $html, $url) | 66 | public function processHtml($entryId, $html, $url) |
43 | { | 67 | { |
44 | $crawler = new Crawler($html); | 68 | $imagesUrls = self::extractImagesUrlsFromHtml($html); |
45 | $imagesCrawler = $crawler | ||
46 | ->filterXpath('//img'); | ||
47 | $imagesUrls = $imagesCrawler | ||
48 | ->extract(['src']); | ||
49 | $imagesSrcsetUrls = $this->getSrcsetUrls($imagesCrawler); | ||
50 | $imagesUrls = array_unique(array_merge($imagesUrls, $imagesSrcsetUrls)); | ||
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 | } |
@@ -199,25 +217,28 @@ class DownloadImages | |||
199 | * | 217 | * |
200 | * @return array An array of urls | 218 | * @return array An array of urls |
201 | */ | 219 | */ |
202 | private function getSrcsetUrls(Crawler $imagesCrawler) | 220 | private static function getSrcsetUrls(Crawler $imagesCrawler) |
203 | { | 221 | { |
204 | $urls = []; | 222 | $urls = []; |
205 | $iterator = $imagesCrawler | 223 | $iterator = $imagesCrawler->getIterator(); |
206 | ->getIterator(); | 224 | |
207 | while ($iterator->valid()) { | 225 | while ($iterator->valid()) { |
208 | $srcsetAttribute = $iterator->current()->getAttribute('srcset'); | 226 | $srcsetAttribute = $iterator->current()->getAttribute('srcset'); |
227 | |||
209 | if ('' !== $srcsetAttribute) { | 228 | if ('' !== $srcsetAttribute) { |
210 | // Couldn't start with " OR ' OR a white space | 229 | // Couldn't start with " OR ' OR a white space |
211 | // Could be one or more white space | 230 | // Could be one or more white space |
212 | // Must be one or more digits followed by w OR x | 231 | // Must be one or more digits followed by w OR x |
213 | $pattern = "/(?:[^\"'\s]+\s*(?:\d+[wx])+)/"; | 232 | $pattern = "/(?:[^\"'\s]+\s*(?:\d+[wx])+)/"; |
214 | preg_match_all($pattern, $srcsetAttribute, $matches); | 233 | preg_match_all($pattern, $srcsetAttribute, $matches); |
234 | |||
215 | $srcset = \call_user_func_array('array_merge', $matches); | 235 | $srcset = \call_user_func_array('array_merge', $matches); |
216 | $srcsetUrls = array_map(function ($src) { | 236 | $srcsetUrls = array_map(function ($src) { |
217 | return trim(explode(' ', $src, 2)[0]); | 237 | return trim(explode(' ', $src, 2)[0]); |
218 | }, $srcset); | 238 | }, $srcset); |
219 | $urls = array_merge($srcsetUrls, $urls); | 239 | $urls = array_merge($srcsetUrls, $urls); |
220 | } | 240 | } |
241 | |||
221 | $iterator->next(); | 242 | $iterator->next(); |
222 | } | 243 | } |
223 | 244 | ||
@@ -274,33 +295,29 @@ class DownloadImages | |||
274 | return $url; | 295 | return $url; |
275 | } | 296 | } |
276 | 297 | ||
277 | $base = new \SimplePie_IRI($base); | 298 | $base = new Uri($base); |
278 | 299 | ||
279 | // remove '//' in URL path (causes URLs not to resolve properly) | 300 | // in case the url has no scheme & host |
280 | if (isset($base->ipath)) { | 301 | if ('' === $base->getAuthority() || '' === $base->getScheme()) { |
281 | $base->ipath = preg_replace('!//+!', '/', $base->ipath); | 302 | $this->logger->error('DownloadImages: Can not make an absolute link', ['base' => $base, 'url' => $url]); |
282 | } | ||
283 | 303 | ||
284 | if ($absolute = \SimplePie_IRI::absolutize($base, $url)) { | 304 | return false; |
285 | return $absolute->get_uri(); | ||
286 | } | 305 | } |
287 | 306 | ||
288 | $this->logger->error('DownloadImages: Can not make an absolute link', ['base' => $base, 'url' => $url]); | 307 | return (string) UriResolver::resolve($base, new Uri($url)); |
289 | |||
290 | return false; | ||
291 | } | 308 | } |
292 | 309 | ||
293 | /** | 310 | /** |
294 | * Retrieve and validate the extension from the response of the url of the image. | 311 | * Retrieve and validate the extension from the response of the url of the image. |
295 | * | 312 | * |
296 | * @param Response $res Guzzle Response | 313 | * @param ResponseInterface $res Http Response |
297 | * @param string $imagePath Path from the src image from the content (used for log only) | 314 | * @param string $imagePath Path from the src image from the content (used for log only) |
298 | * | 315 | * |
299 | * @return string|false Extension name or false if validation failed | 316 | * @return string|false Extension name or false if validation failed |
300 | */ | 317 | */ |
301 | private function getExtensionFromResponse(Response $res, $imagePath) | 318 | private function getExtensionFromResponse(ResponseInterface $res, $imagePath) |
302 | { | 319 | { |
303 | $ext = $this->mimeGuesser->guess($res->getHeader('content-type')); | 320 | $ext = $this->mimeGuesser->guess(current($res->getHeader('content-type'))); |
304 | $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]); | 321 | $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]); |
305 | 322 | ||
306 | // ok header doesn't have the extension, try a different way | 323 | // 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/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/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index f5089729..16c44885 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php | |||
@@ -9,6 +9,7 @@ use Pagerfanta\Adapter\DoctrineORMAdapter; | |||
9 | use Pagerfanta\Pagerfanta; | 9 | use Pagerfanta\Pagerfanta; |
10 | use Wallabag\CoreBundle\Entity\Entry; | 10 | use Wallabag\CoreBundle\Entity\Entry; |
11 | use Wallabag\CoreBundle\Entity\Tag; | 11 | use Wallabag\CoreBundle\Entity\Tag; |
12 | use Wallabag\CoreBundle\Helper\UrlHasher; | ||
12 | 13 | ||
13 | class EntryRepository extends EntityRepository | 14 | class EntryRepository extends EntityRepository |
14 | { | 15 | { |
@@ -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 | } |
@@ -329,21 +345,14 @@ class EntryRepository extends EntityRepository | |||
329 | * @param string $url | 345 | * @param string $url |
330 | * @param int $userId | 346 | * @param int $userId |
331 | * | 347 | * |
332 | * @return Entry|bool | 348 | * @return Entry|false |
333 | */ | 349 | */ |
334 | public function findByUrlAndUserId($url, $userId) | 350 | public function findByUrlAndUserId($url, $userId) |
335 | { | 351 | { |
336 | $res = $this->createQueryBuilder('e') | 352 | return $this->findByHashedUrlAndUserId( |
337 | ->where('e.url = :url')->setParameter('url', urldecode($url)) | 353 | UrlHasher::hashUrl($url), |
338 | ->andWhere('e.user = :user_id')->setParameter('user_id', $userId) | 354 | $userId |
339 | ->getQuery() | 355 | ); |
340 | ->getResult(); | ||
341 | |||
342 | if (\count($res)) { | ||
343 | return current($res); | ||
344 | } | ||
345 | |||
346 | return false; | ||
347 | } | 356 | } |
348 | 357 | ||
349 | /** | 358 | /** |
@@ -353,10 +362,11 @@ class EntryRepository extends EntityRepository | |||
353 | * @param string $hashedUrl Url hashed using sha1 | 362 | * @param string $hashedUrl Url hashed using sha1 |
354 | * @param int $userId | 363 | * @param int $userId |
355 | * | 364 | * |
356 | * @return Entry|bool | 365 | * @return Entry|false |
357 | */ | 366 | */ |
358 | public function findByHashedUrlAndUserId($hashedUrl, $userId) | 367 | public function findByHashedUrlAndUserId($hashedUrl, $userId) |
359 | { | 368 | { |
369 | // try first using hashed_url (to use the database index) | ||
360 | $res = $this->createQueryBuilder('e') | 370 | $res = $this->createQueryBuilder('e') |
361 | ->where('e.hashedUrl = :hashed_url')->setParameter('hashed_url', $hashedUrl) | 371 | ->where('e.hashedUrl = :hashed_url')->setParameter('hashed_url', $hashedUrl) |
362 | ->andWhere('e.user = :user_id')->setParameter('user_id', $userId) | 372 | ->andWhere('e.user = :user_id')->setParameter('user_id', $userId) |
@@ -367,6 +377,17 @@ class EntryRepository extends EntityRepository | |||
367 | return current($res); | 377 | return current($res); |
368 | } | 378 | } |
369 | 379 | ||
380 | // then try using hashed_given_url (to use the database index) | ||
381 | $res = $this->createQueryBuilder('e') | ||
382 | ->where('e.hashedGivenUrl = :hashed_given_url')->setParameter('hashed_given_url', $hashedUrl) | ||
383 | ->andWhere('e.user = :user_id')->setParameter('user_id', $userId) | ||
384 | ->getQuery() | ||
385 | ->getResult(); | ||
386 | |||
387 | if (\count($res)) { | ||
388 | return current($res); | ||
389 | } | ||
390 | |||
370 | return false; | 391 | return false; |
371 | } | 392 | } |
372 | 393 | ||
diff --git a/src/Wallabag/CoreBundle/Repository/SiteCredentialRepository.php b/src/Wallabag/CoreBundle/Repository/SiteCredentialRepository.php index b2e212a4..aeadd770 100644 --- a/src/Wallabag/CoreBundle/Repository/SiteCredentialRepository.php +++ b/src/Wallabag/CoreBundle/Repository/SiteCredentialRepository.php | |||
@@ -19,16 +19,16 @@ class SiteCredentialRepository extends \Doctrine\ORM\EntityRepository | |||
19 | /** | 19 | /** |
20 | * Retrieve one username/password for the given host and userId. | 20 | * Retrieve one username/password for the given host and userId. |
21 | * | 21 | * |
22 | * @param string $host | 22 | * @param array $hosts An array of host to look for |
23 | * @param int $userId | 23 | * @param int $userId |
24 | * | 24 | * |
25 | * @return array|null | 25 | * @return array|null |
26 | */ | 26 | */ |
27 | public function findOneByHostAndUser($host, $userId) | 27 | public function findOneByHostsAndUser($hosts, $userId) |
28 | { | 28 | { |
29 | $res = $this->createQueryBuilder('s') | 29 | $res = $this->createQueryBuilder('s') |
30 | ->select('s.username', 's.password') | 30 | ->select('s.username', 's.password') |
31 | ->where('s.host = :hostname')->setParameter('hostname', $host) | 31 | ->where('s.host IN (:hosts)')->setParameter('hosts', $hosts) |
32 | ->andWhere('s.user = :userId')->setParameter('userId', $userId) | 32 | ->andWhere('s.user = :userId')->setParameter('userId', $userId) |
33 | ->setMaxResults(1) | 33 | ->setMaxResults(1) |
34 | ->getQuery() | 34 | ->getQuery() |
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index 280d779d..31986951 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml | |||
@@ -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" |
@@ -212,7 +211,7 @@ services: | |||
212 | - "@logger" | 211 | - "@logger" |
213 | 212 | ||
214 | wallabag_core.entry.download_images.client: | 213 | wallabag_core.entry.download_images.client: |
215 | class: GuzzleHttp\Client | 214 | alias: 'httplug.client.wallabag_core.entry.download_images' |
216 | 215 | ||
217 | wallabag_core.helper.crypto_proxy: | 216 | wallabag_core.helper.crypto_proxy: |
218 | class: Wallabag\CoreBundle\Helper\CryptoProxy | 217 | class: Wallabag\CoreBundle\Helper\CryptoProxy |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml index 61ef3b8f..c6a91cd1 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'Tilbage til de ulæste artikler' | 33 | back_to_unread: 'Tilbage til de ulæste artikler' |
34 | # users_management: 'Users management' | 34 | # users_management: 'Users management' |
35 | # site_credentials: 'Site credentials' | 35 | # site_credentials: 'Site credentials' |
36 | # quickstart: "Quickstart" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'Tilføj ny artikel' | 38 | add_new_entry: 'Tilføj ny artikel' |
38 | search: 'Søg' | 39 | search: 'Søg' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'Intet token' | 92 | no_token: 'Intet token' |
92 | token_create: 'Opret token' | 93 | token_create: 'Opret token' |
93 | token_reset: 'Nulstil token' | 94 | token_reset: 'Nulstil token' |
95 | # token_revoke: 'Revoke the token' | ||
94 | feed_links: 'RSS-Links' | 96 | feed_links: 'RSS-Links' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'Ulæst' | 98 | unread: 'Ulæst' |
@@ -572,7 +574,7 @@ site_credential: | |||
572 | # create_new_one: Create a new credential | 574 | # create_new_one: Create a new credential |
573 | # form: | 575 | # form: |
574 | # username_label: 'Username' | 576 | # username_label: 'Username' |
575 | # host_label: 'Host' | 577 | # host_label: 'Host (subdomain.example.org, .example.org, etc.)' |
576 | # password_label: 'Password' | 578 | # password_label: 'Password' |
577 | # save: Save | 579 | # save: Save |
578 | # delete: Delete | 580 | # delete: Delete |
@@ -593,6 +595,7 @@ flashes: | |||
593 | # tagging_rules_updated: 'Tagging rules updated' | 595 | # tagging_rules_updated: 'Tagging rules updated' |
594 | # tagging_rules_deleted: 'Tagging rule deleted' | 596 | # tagging_rules_deleted: 'Tagging rule deleted' |
595 | # feed_token_updated: 'RSS token updated' | 597 | # feed_token_updated: 'RSS token updated' |
598 | # feed_token_revoked: 'RSS token revoked' | ||
596 | # annotations_reset: Annotations reset | 599 | # annotations_reset: Annotations reset |
597 | # tags_reset: Tags reset | 600 | # tags_reset: Tags reset |
598 | # entries_reset: Entries reset | 601 | # entries_reset: Entries reset |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml index 991e00f1..4b785306 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'Zurück zu ungelesenen Artikeln' | 33 | back_to_unread: 'Zurück zu ungelesenen Artikeln' |
34 | users_management: 'Benutzerverwaltung' | 34 | users_management: 'Benutzerverwaltung' |
35 | site_credentials: 'Zugangsdaten' | 35 | site_credentials: 'Zugangsdaten' |
36 | quickstart: "Schnelleinstieg" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'Neuen Artikel hinzufügen' | 38 | add_new_entry: 'Neuen Artikel hinzufügen' |
38 | search: 'Suche' | 39 | search: 'Suche' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'Kein Token' | 92 | no_token: 'Kein Token' |
92 | token_create: 'Token erstellen' | 93 | token_create: 'Token erstellen' |
93 | token_reset: 'Token zurücksetzen' | 94 | token_reset: 'Token zurücksetzen' |
95 | # token_revoke: 'Revoke the token' | ||
94 | feed_links: 'RSS-Links' | 96 | feed_links: 'RSS-Links' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'Ungelesene' | 98 | unread: 'Ungelesene' |
@@ -563,7 +565,7 @@ site_credential: | |||
563 | create_new_one: 'Einen neuen Seitenzugang anlegen' | 565 | create_new_one: 'Einen neuen Seitenzugang anlegen' |
564 | form: | 566 | form: |
565 | username_label: 'Benutzername' | 567 | username_label: 'Benutzername' |
566 | host_label: 'Host' | 568 | host_label: 'Host (subdomain.example.org, .example.org, etc.)' |
567 | password_label: 'Passwort' | 569 | password_label: 'Passwort' |
568 | save: 'Speichern' | 570 | save: 'Speichern' |
569 | delete: 'Löschen' | 571 | delete: 'Löschen' |
@@ -584,6 +586,7 @@ flashes: | |||
584 | tagging_rules_updated: 'Tagging-Regeln aktualisiert' | 586 | tagging_rules_updated: 'Tagging-Regeln aktualisiert' |
585 | tagging_rules_deleted: 'Tagging-Regel gelöscht' | 587 | tagging_rules_deleted: 'Tagging-Regel gelöscht' |
586 | feed_token_updated: 'RSS-Token aktualisiert' | 588 | feed_token_updated: 'RSS-Token aktualisiert' |
589 | # feed_token_revoked: 'RSS token revoked' | ||
587 | annotations_reset: Anmerkungen zurücksetzen | 590 | annotations_reset: Anmerkungen zurücksetzen |
588 | tags_reset: Tags zurücksetzen | 591 | tags_reset: Tags zurücksetzen |
589 | entries_reset: Einträge zurücksetzen | 592 | entries_reset: Einträge zurücksetzen |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml index 5b875652..1f8c47aa 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'Back to unread articles' | 33 | back_to_unread: 'Back to unread articles' |
34 | users_management: 'Users management' | 34 | users_management: 'Users management' |
35 | site_credentials: 'Site credentials' | 35 | site_credentials: 'Site credentials' |
36 | quickstart: "Quickstart" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'Add a new entry' | 38 | add_new_entry: 'Add a new entry' |
38 | search: 'Search' | 39 | search: 'Search' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'No token' | 92 | no_token: 'No token' |
92 | token_create: 'Create your token' | 93 | token_create: 'Create your token' |
93 | token_reset: 'Regenerate your token' | 94 | token_reset: 'Regenerate your token' |
95 | token_revoke: 'Revoke the token' | ||
94 | feed_links: 'Feed links' | 96 | feed_links: 'Feed links' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'Unread' | 98 | unread: 'Unread' |
@@ -572,7 +574,7 @@ site_credential: | |||
572 | create_new_one: Create a new credential | 574 | create_new_one: Create a new credential |
573 | form: | 575 | form: |
574 | username_label: 'Username' | 576 | username_label: 'Username' |
575 | host_label: 'Host' | 577 | host_label: 'Host (subdomain.example.org, .example.org, etc.)' |
576 | password_label: 'Password' | 578 | password_label: 'Password' |
577 | save: Save | 579 | save: Save |
578 | delete: Delete | 580 | delete: Delete |
@@ -593,6 +595,7 @@ flashes: | |||
593 | tagging_rules_updated: 'Tagging rules updated' | 595 | tagging_rules_updated: 'Tagging rules updated' |
594 | tagging_rules_deleted: 'Tagging rule deleted' | 596 | tagging_rules_deleted: 'Tagging rule deleted' |
595 | feed_token_updated: 'Feed token updated' | 597 | feed_token_updated: 'Feed token updated' |
598 | feed_token_revoked: 'RSS token revoked' | ||
596 | annotations_reset: Annotations reset | 599 | annotations_reset: Annotations reset |
597 | tags_reset: Tags reset | 600 | tags_reset: Tags reset |
598 | entries_reset: Entries reset | 601 | entries_reset: Entries reset |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml index 562b4191..06fa1e48 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'Volver a los artículos sin leer' | 33 | back_to_unread: 'Volver a los artículos sin leer' |
34 | users_management: 'Configuración de usuarios' | 34 | users_management: 'Configuración de usuarios' |
35 | # site_credentials: 'Site credentials' | 35 | # site_credentials: 'Site credentials' |
36 | quickstart: "Inicio rápido" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'Añadir un nuevo artículo' | 38 | add_new_entry: 'Añadir un nuevo artículo' |
38 | search: 'Buscar' | 39 | search: 'Buscar' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'Sin token' | 92 | no_token: 'Sin token' |
92 | token_create: 'Crear token' | 93 | token_create: 'Crear token' |
93 | token_reset: 'Reiniciar token' | 94 | token_reset: 'Reiniciar token' |
95 | # token_revoke: 'Revoke the token' | ||
94 | feed_links: 'URLs de feeds RSS' | 96 | feed_links: 'URLs de feeds RSS' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'sin leer' | 98 | unread: 'sin leer' |
@@ -572,7 +574,7 @@ site_credential: | |||
572 | # create_new_one: Create a new credential | 574 | # create_new_one: Create a new credential |
573 | # form: | 575 | # form: |
574 | # username_label: 'Username' | 576 | # username_label: 'Username' |
575 | # host_label: 'Host' | 577 | # host_label: 'Host (subdomain.example.org, .example.org, etc.)' |
576 | # password_label: 'Password' | 578 | # password_label: 'Password' |
577 | # save: Save | 579 | # save: Save |
578 | # delete: Delete | 580 | # delete: Delete |
@@ -593,6 +595,7 @@ flashes: | |||
593 | tagging_rules_updated: 'Regla de etiquetado actualizada' | 595 | tagging_rules_updated: 'Regla de etiquetado actualizada' |
594 | tagging_rules_deleted: 'Regla de etiquetado eliminada' | 596 | tagging_rules_deleted: 'Regla de etiquetado eliminada' |
595 | feed_token_updated: 'Token RSS actualizado' | 597 | feed_token_updated: 'Token RSS actualizado' |
598 | # feed_token_revoked: 'RSS token revoked' | ||
596 | annotations_reset: Anotaciones reiniciadas | 599 | annotations_reset: Anotaciones reiniciadas |
597 | tags_reset: Etiquetas reiniciadas | 600 | tags_reset: Etiquetas reiniciadas |
598 | entries_reset: Artículos reiniciados | 601 | entries_reset: Artículos reiniciados |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml index f360e0d6..5c1eaccc 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'بازگشت به خواندهنشدهها' | 33 | back_to_unread: 'بازگشت به خواندهنشدهها' |
34 | # users_management: 'Users management' | 34 | # users_management: 'Users management' |
35 | # site_credentials: 'Site credentials' | 35 | # site_credentials: 'Site credentials' |
36 | quickstart: "Quickstart" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'افزودن مقالهٔ تازه' | 38 | add_new_entry: 'افزودن مقالهٔ تازه' |
38 | search: 'جستجو' | 39 | search: 'جستجو' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'بدون کد' | 92 | no_token: 'بدون کد' |
92 | token_create: 'کد خود را بسازید' | 93 | token_create: 'کد خود را بسازید' |
93 | token_reset: 'بازنشانی کد' | 94 | token_reset: 'بازنشانی کد' |
95 | # token_revoke: 'Revoke the token' | ||
94 | feed_links: 'پیوند آر-اس-اس' | 96 | feed_links: 'پیوند آر-اس-اس' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'خواندهنشده' | 98 | unread: 'خواندهنشده' |
@@ -572,7 +574,7 @@ site_credential: | |||
572 | # create_new_one: Create a new credential | 574 | # create_new_one: Create a new credential |
573 | # form: | 575 | # form: |
574 | # username_label: 'Username' | 576 | # username_label: 'Username' |
575 | # host_label: 'Host' | 577 | # host_label: 'Host (subdomain.example.org, .example.org, etc.)' |
576 | # password_label: 'Password' | 578 | # password_label: 'Password' |
577 | # save: Save | 579 | # save: Save |
578 | # delete: Delete | 580 | # delete: Delete |
@@ -593,6 +595,7 @@ flashes: | |||
593 | tagging_rules_updated: 'برچسبگذاری خودکار بهروز شد' | 595 | tagging_rules_updated: 'برچسبگذاری خودکار بهروز شد' |
594 | tagging_rules_deleted: 'قانون برچسبگذاری پاک شد' | 596 | tagging_rules_deleted: 'قانون برچسبگذاری پاک شد' |
595 | feed_token_updated: 'کد آر-اس-اس بهروز شد' | 597 | feed_token_updated: 'کد آر-اس-اس بهروز شد' |
598 | # feed_token_revoked: 'RSS token revoked' | ||
596 | # annotations_reset: Annotations reset | 599 | # annotations_reset: Annotations reset |
597 | # tags_reset: Tags reset | 600 | # tags_reset: Tags reset |
598 | # entries_reset: Entries reset | 601 | # entries_reset: Entries reset |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml index 79f15154..09c1cc8f 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: "Retour aux articles non lus" | 33 | back_to_unread: "Retour aux articles non lus" |
34 | users_management: "Gestion des utilisateurs" | 34 | users_management: "Gestion des utilisateurs" |
35 | site_credentials: 'Accès aux sites' | 35 | site_credentials: 'Accès aux sites' |
36 | quickstart: "Pour bien débuter" | ||
36 | top: | 37 | top: |
37 | add_new_entry: "Sauvegarder un nouvel article" | 38 | add_new_entry: "Sauvegarder un nouvel article" |
38 | search: "Rechercher" | 39 | search: "Rechercher" |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: "Aucun jeton généré" | 92 | no_token: "Aucun jeton généré" |
92 | token_create: "Créez votre jeton" | 93 | token_create: "Créez votre jeton" |
93 | token_reset: "Réinitialisez votre jeton" | 94 | token_reset: "Réinitialisez votre jeton" |
95 | token_revoke: 'Supprimer le jeton' | ||
94 | feed_links: "Adresses de vos flux" | 96 | feed_links: "Adresses de vos flux" |
95 | feed_link: | 97 | feed_link: |
96 | unread: "Non lus" | 98 | unread: "Non lus" |
@@ -573,7 +575,7 @@ site_credential: | |||
573 | create_new_one: Créer un nouvel accès à un site | 575 | create_new_one: Créer un nouvel accès à un site |
574 | form: | 576 | form: |
575 | username_label: 'Identifiant' | 577 | username_label: 'Identifiant' |
576 | host_label: 'Domaine' | 578 | host_label: 'Domaine (subdomain.example.org, .example.org, etc.)' |
577 | password_label: 'Mot de passe' | 579 | password_label: 'Mot de passe' |
578 | save: "Sauvegarder" | 580 | save: "Sauvegarder" |
579 | delete: "Supprimer" | 581 | delete: "Supprimer" |
@@ -594,6 +596,7 @@ flashes: | |||
594 | tagging_rules_updated: "Règles mises à jour" | 596 | tagging_rules_updated: "Règles mises à jour" |
595 | tagging_rules_deleted: "Règle supprimée" | 597 | tagging_rules_deleted: "Règle supprimée" |
596 | feed_token_updated: "Jeton des flux mis à jour" | 598 | feed_token_updated: "Jeton des flux mis à jour" |
599 | feed_token_revoked: 'Jeton des flux supprimé' | ||
597 | annotations_reset: "Annotations supprimées" | 600 | annotations_reset: "Annotations supprimées" |
598 | tags_reset: "Tags supprimés" | 601 | tags_reset: "Tags supprimés" |
599 | entries_reset: "Articles supprimés" | 602 | entries_reset: "Articles supprimés" |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml index daef359f..92f2415b 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'Torna ai contenuti non letti' | 33 | back_to_unread: 'Torna ai contenuti non letti' |
34 | users_management: 'Gestione utenti' | 34 | users_management: 'Gestione utenti' |
35 | site_credentials: 'Credenziali sito' | 35 | site_credentials: 'Credenziali sito' |
36 | quickstart: "Introduzione" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'Aggiungi un nuovo contenuto' | 38 | add_new_entry: 'Aggiungi un nuovo contenuto' |
38 | search: 'Cerca' | 39 | search: 'Cerca' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'Nessun token' | 92 | no_token: 'Nessun token' |
92 | token_create: 'Crea il tuo token' | 93 | token_create: 'Crea il tuo token' |
93 | token_reset: 'Rigenera il tuo token' | 94 | token_reset: 'Rigenera il tuo token' |
95 | # token_revoke: 'Revoke the token' | ||
94 | feed_links: 'Collegamenti RSS' | 96 | feed_links: 'Collegamenti RSS' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'Non letti' | 98 | unread: 'Non letti' |
@@ -571,7 +573,7 @@ site_credential: | |||
571 | # create_new_one: Create a new credential | 573 | # create_new_one: Create a new credential |
572 | # form: | 574 | # form: |
573 | # username_label: 'Username' | 575 | # username_label: 'Username' |
574 | # host_label: 'Host' | 576 | # host_label: 'Host (subdomain.example.org, .example.org, etc.)' |
575 | # password_label: 'Password' | 577 | # password_label: 'Password' |
576 | # save: Save | 578 | # save: Save |
577 | # delete: Delete | 579 | # delete: Delete |
@@ -592,6 +594,7 @@ flashes: | |||
592 | tagging_rules_updated: 'Regole di etichettatura aggiornate' | 594 | tagging_rules_updated: 'Regole di etichettatura aggiornate' |
593 | tagging_rules_deleted: 'Regola di etichettatura eliminate' | 595 | tagging_rules_deleted: 'Regola di etichettatura eliminate' |
594 | feed_token_updated: 'RSS token aggiornato' | 596 | feed_token_updated: 'RSS token aggiornato' |
597 | # feed_token_revoked: 'RSS token revoked' | ||
595 | annotations_reset: Reset annotazioni | 598 | annotations_reset: Reset annotazioni |
596 | tags_reset: Reset etichette | 599 | tags_reset: Reset etichette |
597 | entries_reset: Reset articoli | 600 | entries_reset: Reset articoli |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml index 980ddeb4..4439cbcd 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'Tornar als articles pas legits' | 33 | back_to_unread: 'Tornar als articles pas legits' |
34 | users_management: 'Gestion dels utilizaires' | 34 | users_management: 'Gestion dels utilizaires' |
35 | site_credentials: 'Identificants del site' | 35 | site_credentials: 'Identificants del site' |
36 | quickstart: "Per ben començar" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'Enregistrar un novèl article' | 38 | add_new_entry: 'Enregistrar un novèl article' |
38 | search: 'Cercar' | 39 | search: 'Cercar' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'Pas cap de geton generat' | 92 | no_token: 'Pas cap de geton generat' |
92 | token_create: 'Creatz vòstre geton' | 93 | token_create: 'Creatz vòstre geton' |
93 | token_reset: 'Reïnicializatz vòstre geton' | 94 | token_reset: 'Reïnicializatz vòstre geton' |
95 | # token_revoke: 'Revoke the token' | ||
94 | feed_links: 'URLs de vòstres fluxes RSS' | 96 | feed_links: 'URLs de vòstres fluxes RSS' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'Pas legits' | 98 | unread: 'Pas legits' |
@@ -571,7 +573,7 @@ site_credential: | |||
571 | create_new_one: Crear un novèl identificant | 573 | create_new_one: Crear un novèl identificant |
572 | form: | 574 | form: |
573 | username_label: "Nom d'utilizaire" | 575 | username_label: "Nom d'utilizaire" |
574 | host_label: 'Òste' | 576 | host_label: 'Òste (subdomain.example.org, .example.org, etc.)' |
575 | password_label: 'Senhal' | 577 | password_label: 'Senhal' |
576 | save: 'Enregistrar' | 578 | save: 'Enregistrar' |
577 | delete: 'Suprimir' | 579 | delete: 'Suprimir' |
@@ -592,6 +594,7 @@ flashes: | |||
592 | tagging_rules_updated: 'Règlas misa a jorn' | 594 | tagging_rules_updated: 'Règlas misa a jorn' |
593 | tagging_rules_deleted: 'Règla suprimida' | 595 | tagging_rules_deleted: 'Règla suprimida' |
594 | feed_token_updated: 'Geton RSS mes a jorn' | 596 | feed_token_updated: 'Geton RSS mes a jorn' |
597 | # feed_token_revoked: 'RSS token revoked' | ||
595 | annotations_reset: Anotacions levadas | 598 | annotations_reset: Anotacions levadas |
596 | tags_reset: Etiquetas levadas | 599 | tags_reset: Etiquetas levadas |
597 | entries_reset: Articles levats | 600 | entries_reset: Articles levats |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml index 3813ac37..8311770f 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'Powrót do nieprzeczytanych artykułów' | 33 | back_to_unread: 'Powrót do nieprzeczytanych artykułów' |
34 | users_management: 'Zarządzanie użytkownikami' | 34 | users_management: 'Zarządzanie użytkownikami' |
35 | site_credentials: 'Poświadczenia strony' | 35 | site_credentials: 'Poświadczenia strony' |
36 | quickstart: "Szybki start" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'Dodaj nowy wpis' | 38 | add_new_entry: 'Dodaj nowy wpis' |
38 | search: 'Szukaj' | 39 | search: 'Szukaj' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'Brak tokena' | 92 | no_token: 'Brak tokena' |
92 | token_create: 'Stwórz tokena' | 93 | token_create: 'Stwórz tokena' |
93 | token_reset: 'Zresetuj swojego tokena' | 94 | token_reset: 'Zresetuj swojego tokena' |
95 | # token_revoke: 'Revoke the token' | ||
94 | feed_links: 'RSS links' | 96 | feed_links: 'RSS links' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'Nieprzeczytane' | 98 | unread: 'Nieprzeczytane' |
@@ -571,7 +573,7 @@ site_credential: | |||
571 | create_new_one: Stwórz nowe poświadczenie | 573 | create_new_one: Stwórz nowe poświadczenie |
572 | form: | 574 | form: |
573 | username_label: 'Nazwa użytkownika' | 575 | username_label: 'Nazwa użytkownika' |
574 | host_label: 'Host' | 576 | host_label: 'Host (subdomain.example.org, .example.org, etc.)' |
575 | password_label: 'Hasło' | 577 | password_label: 'Hasło' |
576 | save: Zapisz | 578 | save: Zapisz |
577 | delete: Usuń | 579 | delete: Usuń |
@@ -592,6 +594,7 @@ flashes: | |||
592 | tagging_rules_updated: 'Reguły tagowania zaktualizowane' | 594 | tagging_rules_updated: 'Reguły tagowania zaktualizowane' |
593 | tagging_rules_deleted: 'Reguła tagowania usunięta' | 595 | tagging_rules_deleted: 'Reguła tagowania usunięta' |
594 | feed_token_updated: 'Token kanału RSS zaktualizowany' | 596 | feed_token_updated: 'Token kanału RSS zaktualizowany' |
597 | # feed_token_revoked: 'RSS token revoked' | ||
595 | annotations_reset: Zresetuj adnotacje | 598 | annotations_reset: Zresetuj adnotacje |
596 | tags_reset: Zresetuj tagi | 599 | tags_reset: Zresetuj tagi |
597 | entries_reset: Zresetuj wpisy | 600 | entries_reset: Zresetuj wpisy |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml index 96943c05..c83bf6c1 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'Voltar para os artigos não lidos' | 33 | back_to_unread: 'Voltar para os artigos não lidos' |
34 | users_management: 'Gestão de Usuários' | 34 | users_management: 'Gestão de Usuários' |
35 | # site_credentials: 'Site credentials' | 35 | # site_credentials: 'Site credentials' |
36 | quickstart: "Começo Rápido" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'Adicionar uma nova entrada' | 38 | add_new_entry: 'Adicionar uma nova entrada' |
38 | search: 'Pesquisa' | 39 | search: 'Pesquisa' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'Nenhum Token' | 92 | no_token: 'Nenhum Token' |
92 | token_create: 'Criar seu token' | 93 | token_create: 'Criar seu token' |
93 | token_reset: 'Gerar novamente seu token' | 94 | token_reset: 'Gerar novamente seu token' |
95 | # token_revoke: 'Revoke the token' | ||
94 | feed_links: 'Links RSS' | 96 | feed_links: 'Links RSS' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'Não lido' | 98 | unread: 'Não lido' |
@@ -571,7 +573,7 @@ site_credential: | |||
571 | # create_new_one: Create a new credential | 573 | # create_new_one: Create a new credential |
572 | form: | 574 | form: |
573 | # username_label: 'Username' | 575 | # username_label: 'Username' |
574 | # host_label: 'Host' | 576 | # host_label: 'Host (subdomain.example.org, .example.org, etc.)' |
575 | # password_label: 'Password' | 577 | # password_label: 'Password' |
576 | save: 'Salvar' | 578 | save: 'Salvar' |
577 | delete: 'Apagar' | 579 | delete: 'Apagar' |
@@ -592,6 +594,7 @@ flashes: | |||
592 | tagging_rules_updated: 'Regras de tags atualizadas' | 594 | tagging_rules_updated: 'Regras de tags atualizadas' |
593 | tagging_rules_deleted: 'Regra de tag apagada' | 595 | tagging_rules_deleted: 'Regra de tag apagada' |
594 | feed_token_updated: 'Token RSS atualizado' | 596 | feed_token_updated: 'Token RSS atualizado' |
597 | # feed_token_revoked: 'RSS token revoked' | ||
595 | # annotations_reset: Annotations reset | 598 | # annotations_reset: Annotations reset |
596 | # tags_reset: Tags reset | 599 | # tags_reset: Tags reset |
597 | # entries_reset: Entries reset | 600 | # entries_reset: Entries reset |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml index 0ce11e74..c8bf8083 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'Înapoi la articolele necitite' | 33 | back_to_unread: 'Înapoi la articolele necitite' |
34 | # users_management: 'Users management' | 34 | # users_management: 'Users management' |
35 | # site_credentials: 'Site credentials' | 35 | # site_credentials: 'Site credentials' |
36 | # quickstart: "Quickstart" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'Introdu un nou articol' | 38 | add_new_entry: 'Introdu un nou articol' |
38 | search: 'Căutare' | 39 | search: 'Căutare' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'Fără token' | 92 | no_token: 'Fără token' |
92 | token_create: 'Crează-ți token' | 93 | token_create: 'Crează-ți token' |
93 | token_reset: 'Resetează-ți token-ul' | 94 | token_reset: 'Resetează-ți token-ul' |
95 | # token_revoke: 'Revoke the token' | ||
94 | feed_links: 'Link-uri RSS' | 96 | feed_links: 'Link-uri RSS' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'Unread' | 98 | unread: 'Unread' |
@@ -571,7 +573,7 @@ site_credential: | |||
571 | # create_new_one: Create a new credential | 573 | # create_new_one: Create a new credential |
572 | # form: | 574 | # form: |
573 | # username_label: 'Username' | 575 | # username_label: 'Username' |
574 | # host_label: 'Host' | 576 | # host_label: 'Host (subdomain.example.org, .example.org, etc.)' |
575 | # password_label: 'Password' | 577 | # password_label: 'Password' |
576 | # save: Save | 578 | # save: Save |
577 | # delete: Delete | 579 | # delete: Delete |
@@ -592,6 +594,7 @@ flashes: | |||
592 | # tagging_rules_updated: 'Tagging rules updated' | 594 | # tagging_rules_updated: 'Tagging rules updated' |
593 | # tagging_rules_deleted: 'Tagging rule deleted' | 595 | # tagging_rules_deleted: 'Tagging rule deleted' |
594 | # feed_token_updated: 'RSS token updated' | 596 | # feed_token_updated: 'RSS token updated' |
597 | # feed_token_revoked: 'RSS token revoked' | ||
595 | # annotations_reset: Annotations reset | 598 | # annotations_reset: Annotations reset |
596 | # tags_reset: Tags reset | 599 | # tags_reset: Tags reset |
597 | # entries_reset: Entries reset | 600 | # entries_reset: Entries reset |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml index 2ee2d83a..5d0e70c9 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml | |||
@@ -32,6 +32,8 @@ menu: | |||
32 | save_link: 'Сохранить ссылку' | 32 | save_link: 'Сохранить ссылку' |
33 | back_to_unread: 'Назад к непрочитанным записям' | 33 | back_to_unread: 'Назад к непрочитанным записям' |
34 | users_management: 'Управление пользователями' | 34 | users_management: 'Управление пользователями' |
35 | site_credentials: 'Site credentials' | ||
36 | quickstart: "Быстрый старт" | ||
35 | top: | 37 | top: |
36 | add_new_entry: 'Добавить новую запись' | 38 | add_new_entry: 'Добавить новую запись' |
37 | search: 'Поиск' | 39 | search: 'Поиск' |
@@ -89,6 +91,7 @@ config: | |||
89 | no_token: 'Ключ не задан' | 91 | no_token: 'Ключ не задан' |
90 | token_create: 'Создать ключ' | 92 | token_create: 'Создать ключ' |
91 | token_reset: 'Пересоздать ключ' | 93 | token_reset: 'Пересоздать ключ' |
94 | # token_revoke: 'Revoke the token' | ||
92 | feed_links: 'ссылка на RSS' | 95 | feed_links: 'ссылка на RSS' |
93 | feed_link: | 96 | feed_link: |
94 | unread: 'непрочитанные' | 97 | unread: 'непрочитанные' |
@@ -558,6 +561,7 @@ flashes: | |||
558 | tagging_rules_updated: 'Правила тегировния обновлены' | 561 | tagging_rules_updated: 'Правила тегировния обновлены' |
559 | tagging_rules_deleted: 'Правила тегировния удалены' | 562 | tagging_rules_deleted: 'Правила тегировния удалены' |
560 | feed_token_updated: 'RSS ключ обновлен' | 563 | feed_token_updated: 'RSS ключ обновлен' |
564 | # feed_token_revoked: 'RSS token revoked' | ||
561 | annotations_reset: "Аннотации сброшены" | 565 | annotations_reset: "Аннотации сброшены" |
562 | tags_reset: "Теги сброшены" | 566 | tags_reset: "Теги сброшены" |
563 | entries_reset: "Записи сброшены" | 567 | entries_reset: "Записи сброшены" |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml index e04eee68..66426d53 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'กลับไปยังรายการที่ไม่ได้อ่าน' | 33 | back_to_unread: 'กลับไปยังรายการที่ไม่ได้อ่าน' |
34 | users_management: 'การจัดการผู้ใช้' | 34 | users_management: 'การจัดการผู้ใช้' |
35 | site_credentials: 'การรับรองไซต์' | 35 | site_credentials: 'การรับรองไซต์' |
36 | quickstart: "เริ่มแบบด่วน" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'เพิ่มรายการใหม่' | 38 | add_new_entry: 'เพิ่มรายการใหม่' |
38 | search: 'ค้นหา' | 39 | search: 'ค้นหา' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'ไม่มีเครื่องหมาย' | 92 | no_token: 'ไม่มีเครื่องหมาย' |
92 | token_create: 'สร้างเครื่องหมาย' | 93 | token_create: 'สร้างเครื่องหมาย' |
93 | token_reset: 'ทำเครื่องหมาย' | 94 | token_reset: 'ทำเครื่องหมาย' |
95 | # token_revoke: 'Revoke the token' | ||
94 | feed_links: 'ลิงค์ RSS' | 96 | feed_links: 'ลิงค์ RSS' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'ยังไมได้่อ่าน' | 98 | unread: 'ยังไมได้่อ่าน' |
@@ -569,7 +571,7 @@ site_credential: | |||
569 | create_new_one: สร้างข้อมูลส่วนตัวใหม่ | 571 | create_new_one: สร้างข้อมูลส่วนตัวใหม่ |
570 | form: | 572 | form: |
571 | username_label: 'ชื่อผู้ใช้' | 573 | username_label: 'ชื่อผู้ใช้' |
572 | host_label: 'โฮส' | 574 | host_label: 'โฮส (subdomain.example.org, .example.org, etc.)' |
573 | password_label: 'รหัสผ่าน' | 575 | password_label: 'รหัสผ่าน' |
574 | save: บันทึก | 576 | save: บันทึก |
575 | delete: ลบ | 577 | delete: ลบ |
@@ -590,6 +592,7 @@ flashes: | |||
590 | tagging_rules_updated: 'อัปเดตการแท็กข้อบังคับ' | 592 | tagging_rules_updated: 'อัปเดตการแท็กข้อบังคับ' |
591 | tagging_rules_deleted: 'การลบข้อบังคับของแท็ก' | 593 | tagging_rules_deleted: 'การลบข้อบังคับของแท็ก' |
592 | feed_token_updated: 'อัปเดตเครื่องหมาย RSS ' | 594 | feed_token_updated: 'อัปเดตเครื่องหมาย RSS ' |
595 | # feed_token_revoked: 'RSS token revoked' | ||
593 | annotations_reset: รีเซ็ตหมายเหตุ | 596 | annotations_reset: รีเซ็ตหมายเหตุ |
594 | tags_reset: รีเซ็ตแท็ก | 597 | tags_reset: รีเซ็ตแท็ก |
595 | entries_reset: รีเซ็ตรายการ | 598 | entries_reset: รีเซ็ตรายการ |
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml index 2f86f25d..50bd38e3 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml | |||
@@ -33,6 +33,7 @@ menu: | |||
33 | back_to_unread: 'Okunmayan makalelere geri dön' | 33 | back_to_unread: 'Okunmayan makalelere geri dön' |
34 | # users_management: 'Users management' | 34 | # users_management: 'Users management' |
35 | # site_credentials: 'Site credentials' | 35 | # site_credentials: 'Site credentials' |
36 | quickstart: "Hızlı başlangıç" | ||
36 | top: | 37 | top: |
37 | add_new_entry: 'Yeni bir makale ekle' | 38 | add_new_entry: 'Yeni bir makale ekle' |
38 | search: 'Ara' | 39 | search: 'Ara' |
@@ -91,6 +92,7 @@ config: | |||
91 | no_token: 'Belirteç (token) yok' | 92 | no_token: 'Belirteç (token) yok' |
92 | token_create: 'Yeni belirteç (token) oluştur' | 93 | token_create: 'Yeni belirteç (token) oluştur' |
93 | token_reset: 'Belirteci (token) sıfırla' | 94 | token_reset: 'Belirteci (token) sıfırla' |
95 | # token_revoke: 'Revoke the token' | ||
94 | feed_links: 'RSS akış bağlantıları' | 96 | feed_links: 'RSS akış bağlantıları' |
95 | feed_link: | 97 | feed_link: |
96 | unread: 'Okunmayan' | 98 | unread: 'Okunmayan' |
diff --git a/src/Wallabag/CoreBundle/Resources/views/base.html.twig b/src/Wallabag/CoreBundle/Resources/views/base.html.twig index aa388bcb..c0eecd57 100644 --- a/src/Wallabag/CoreBundle/Resources/views/base.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/base.html.twig | |||
@@ -8,6 +8,7 @@ | |||
8 | {% block head %} | 8 | {% block head %} |
9 | <meta name="viewport" content="initial-scale=1.0"> | 9 | <meta name="viewport" content="initial-scale=1.0"> |
10 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | 10 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
11 | <meta name="referrer" content="strict-origin-when-cross-origin"> | ||
11 | <!--[if IE]> | 12 | <!--[if IE]> |
12 | <meta http-equiv="X-UA-Compatible" content="IE=10"> | 13 | <meta http-equiv="X-UA-Compatible" content="IE=10"> |
13 | <![endif]--> | 14 | <![endif]--> |
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 4ef6ab3c..a1caf242 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 | |||
@@ -111,14 +111,14 @@ | |||
111 | {% else %} | 111 | {% else %} |
112 | <em>{{ 'config.form_feed.no_token'|trans }}</em> | 112 | <em>{{ 'config.form_feed.no_token'|trans }}</em> |
113 | {% endif %} | 113 | {% endif %} |
114 | – | 114 | |
115 | <a href="{{ path('generate_token') }}"> | 115 | {% if feed.token %} |
116 | {% if feed.token %} | 116 | – <a href="{{ path('generate_token') }}">{{ 'config.form_feed.token_reset'|trans }}</a> |
117 | {{ 'config.form_feed.token_reset'|trans }} | 117 | – <a href="{{ path('revoke_token') }}">{{ 'config.form_feed.token_revoke'|trans }}</a> |
118 | {% else %} | 118 | {% else %} |
119 | {{ 'config.form_feed.token_create'|trans }} | 119 | – <a href="{{ path('generate_token') }}">{{ 'config.form_feed.token_create'|trans }}</a> |
120 | {% endif %} | 120 | {% endif %} |
121 | </a> | 121 | |
122 | </div> | 122 | </div> |
123 | </fieldset> | 123 | </fieldset> |
124 | 124 | ||
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig index 35a54daf..6b1e2bd7 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig | |||
@@ -50,6 +50,7 @@ | |||
50 | <li class="menu howto"><a href="{{ path('howto') }}">{{ 'menu.left.howto'|trans }}</a></li> | 50 | <li class="menu howto"><a href="{{ path('howto') }}">{{ 'menu.left.howto'|trans }}</a></li> |
51 | <li class="menu developer"><a href="{{ path('developer') }}">{{ 'menu.left.developer'|trans }}</a></li> | 51 | <li class="menu developer"><a href="{{ path('developer') }}">{{ 'menu.left.developer'|trans }}</a></li> |
52 | <li class="menu about"><a href="{{ path('about') }}">{{ 'footer.wallabag.about'|trans }}</a></li> | 52 | <li class="menu about"><a href="{{ path('about') }}">{{ 'footer.wallabag.about'|trans }}</a></li> |
53 | <li class="menu quickstart"><a href="{{ path('quickstart') }}">{{ 'menu.left.quickstart'|trans }}</a></li> | ||
53 | <li class="menu logout"><a class="icon icon-power" href="{{ path('fos_user_security_logout') }}">{{ 'menu.left.logout'|trans }}</a></li> | 54 | <li class="menu logout"><a class="icon icon-power" href="{{ path('fos_user_security_logout') }}">{{ 'menu.left.logout'|trans }}</a></li> |
54 | </ul> | 55 | </ul> |
55 | {% endblock %} | 56 | {% endblock %} |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/share.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/share.html.twig index e1c7aad9..4294a60d 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/share.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/share.html.twig | |||
@@ -29,9 +29,6 @@ | |||
29 | <h1>{{ entry.title|e|raw }}</h1> | 29 | <h1>{{ entry.title|e|raw }}</h1> |
30 | <a href="{{ entry.url|e }}" target="_blank" rel="noopener" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|e|raw }}" class="tool">{{ entry.domainName|removeWww }}</a> | 30 | <a href="{{ entry.url|e }}" target="_blank" rel="noopener" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|e|raw }}" class="tool">{{ entry.domainName|removeWww }}</a> |
31 | <p class="shared-by">{{ "entry.public.shared_by_wallabag"|trans({'%wallabag_instance%': url('homepage'), '%username%': entry.user.username})|raw }}.</p> | 31 | <p class="shared-by">{{ "entry.public.shared_by_wallabag"|trans({'%wallabag_instance%': url('homepage'), '%username%': entry.user.username})|raw }}.</p> |
32 | {% if entry.previewPicture is not null %} | ||
33 | <img class="preview" src="{{ entry.previewPicture }}" alt="{{ entry.title|striptags|e('html_attr') }}" /> | ||
34 | {% endif %} | ||
35 | </header> | 32 | </header> |
36 | <article class="block"> | 33 | <article class="block"> |
37 | {{ entry.content | raw }} | 34 | {{ entry.content | raw }} |
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 818fc4e7..a48c9e28 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 | |||
@@ -140,12 +140,13 @@ | |||
140 | {% else %} | 140 | {% else %} |
141 | <em>{{ 'config.form_feed.no_token'|trans }}</em> | 141 | <em>{{ 'config.form_feed.no_token'|trans }}</em> |
142 | {% endif %} | 142 | {% endif %} |
143 | – <a href="{{ path('generate_token') }}"> | 143 | |
144 | {% if feed.token %} | 144 | {% if feed.token %} |
145 | {{ 'config.form_feed.token_reset'|trans }} | 145 | – <a href="{{ path('generate_token') }}">{{ 'config.form_feed.token_reset'|trans }}</a> |
146 | – <a href="{{ path('revoke_token') }}">{{ 'config.form_feed.token_revoke'|trans }}</a> | ||
146 | {% else %} | 147 | {% else %} |
147 | {{ 'config.form_feed.token_create'|trans }} | 148 | – <a href="{{ path('generate_token') }}">{{ 'config.form_feed.token_create'|trans }}</a> |
148 | {% endif %}</a> | 149 | {% endif %} |
149 | </div> | 150 | </div> |
150 | </div> | 151 | </div> |
151 | </div> | 152 | </div> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/Card/_content.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/Card/_content.html.twig index 1f3cd1a7..1102a0bd 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/Card/_content.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/Card/_content.html.twig | |||
@@ -8,8 +8,11 @@ | |||
8 | 8 | ||
9 | <div class="{{ subClass|default('original grey-text') }}"> | 9 | <div class="{{ subClass|default('original grey-text') }}"> |
10 | <a href="{{ entry.url|e }}" target="_blank" title="{{ entry.domainName|removeWww }}" class="tool grey-text">{{ entry.domainName|removeWww }}</a> | 10 | <a href="{{ entry.url|e }}" target="_blank" title="{{ entry.domainName|removeWww }}" class="tool grey-text">{{ entry.domainName|removeWww }}</a> |
11 | {% if withTags is defined %} | 11 | {% if withMetadata is defined %} |
12 | {% include "@WallabagCore/themes/material/Entry/_tags.html.twig" with {'tags': entry.tags | slice(0, 3), 'entryId': entry.id, 'listClass': ' hide-on-med-and-down'} only %} | 12 | {% include "@WallabagCore/themes/material/Entry/_tags.html.twig" with {'tags': entry.tags | slice(0, 3), 'entryId': entry.id, 'listClass': ' hide-on-med-and-down'} only %} |
13 | <div class="reading-time grey-text"> | ||
14 | <div class="card-reading-time">{% include "@WallabagCore/themes/material/Entry/_reading_time.html.twig" with {'entry': entry} only %}</div> | ||
15 | </div> | ||
13 | {% endif %} | 16 | {% endif %} |
14 | </div> | 17 | </div> |
15 | </div> | 18 | </div> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_list.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_list.html.twig index 1c00f2fa..6a095035 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_list.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_card_list.html.twig | |||
@@ -5,7 +5,7 @@ | |||
5 | <span class="preview{{ previewClassModifier }}" style="background-image: url({{ entry.previewPicture | default(asset('wallassets/themes/_global/img/logo-square.svg')) }})"></span> | 5 | <span class="preview{{ previewClassModifier }}" style="background-image: url({{ entry.previewPicture | default(asset('wallassets/themes/_global/img/logo-square.svg')) }})"></span> |
6 | </a> | 6 | </a> |
7 | </div> | 7 | </div> |
8 | {% include "@WallabagCore/themes/material/Entry/Card/_content.html.twig" with {'entry': entry, 'withTags': true, 'subClass': 'metadata'} only %} | 8 | {% include "@WallabagCore/themes/material/Entry/Card/_content.html.twig" with {'entry': entry, 'withMetadata': true, 'subClass': 'metadata'} only %} |
9 | <ul class="tools-list hide-on-small-only"> | 9 | <ul class="tools-list hide-on-small-only"> |
10 | <li> | 10 | <li> |
11 | <a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i></a> | 11 | <a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i></a> |
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 b9c45567..c51d07fc 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig | |||
@@ -91,6 +91,9 @@ | |||
91 | <li class="bold {% if currentRoute == 'howto' %}active{% endif %}"> | 91 | <li class="bold {% if currentRoute == 'howto' %}active{% endif %}"> |
92 | <a class="waves-effect" href="{{ path('howto') }}">{{ 'menu.left.howto'|trans }}</a> | 92 | <a class="waves-effect" href="{{ path('howto') }}">{{ 'menu.left.howto'|trans }}</a> |
93 | </li> | 93 | </li> |
94 | <li class="bold {% if currentRoute == 'quickstart' %}active{% endif %}"> | ||
95 | <a class="waves-effect" href="{{ path('quickstart') }}">{{ 'menu.left.quickstart'|trans }}</a> | ||
96 | </li> | ||
94 | <li class="bold"> | 97 | <li class="bold"> |
95 | <a class="waves-effect icon icon-power" href="{{ path('fos_user_security_logout') }}">{{ 'menu.left.logout'|trans }}</a> | 98 | <a class="waves-effect icon icon-power" href="{{ path('fos_user_security_logout') }}">{{ 'menu.left.logout'|trans }}</a> |
96 | </li> | 99 | </li> |
diff --git a/src/Wallabag/ImportBundle/Import/InstapaperImport.php b/src/Wallabag/ImportBundle/Import/InstapaperImport.php index 439c978c..f7bee9ef 100644 --- a/src/Wallabag/ImportBundle/Import/InstapaperImport.php +++ b/src/Wallabag/ImportBundle/Import/InstapaperImport.php | |||
@@ -93,6 +93,10 @@ class InstapaperImport extends AbstractImport | |||
93 | return false; | 93 | return false; |
94 | } | 94 | } |
95 | 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 | |||
96 | if ($this->producer) { | 100 | if ($this->producer) { |
97 | $this->parseEntriesForProducer($entries); | 101 | $this->parseEntriesForProducer($entries); |
98 | 102 | ||
diff --git a/src/Wallabag/ImportBundle/Import/PocketImport.php b/src/Wallabag/ImportBundle/Import/PocketImport.php index a39d8156..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 | /** |
@@ -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/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 2dd7dff8..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 |