aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Wallabag/ApiBundle/Controller/EntryRestController.php4
-rw-r--r--src/Wallabag/CoreBundle/Helper/ContentProxy.php49
-rw-r--r--src/Wallabag/CoreBundle/Helper/DownloadImages.php52
-rw-r--r--src/Wallabag/CoreBundle/Helper/HttpClientFactory.php51
-rw-r--r--src/Wallabag/CoreBundle/Resources/config/services.yml11
-rw-r--r--src/Wallabag/ImportBundle/Import/InstapaperImport.php4
-rw-r--r--src/Wallabag/ImportBundle/Import/PocketImport.php91
-rw-r--r--src/Wallabag/ImportBundle/Import/WallabagV2Import.php4
-rw-r--r--src/Wallabag/ImportBundle/Resources/config/services.yml8
9 files changed, 158 insertions, 116 deletions
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
index bdd02129..aaacdcdc 100644
--- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
@@ -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 );
diff --git a/src/Wallabag/CoreBundle/Helper/ContentProxy.php b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
index bc257ffb..c6fa0d98 100644
--- a/src/Wallabag/CoreBundle/Helper/ContentProxy.php
+++ b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
@@ -12,8 +12,8 @@ use Wallabag\CoreBundle\Entity\Entry;
12use Wallabag\CoreBundle\Tools\Utils; 12use 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 */
18class ContentProxy 18class ContentProxy
19{ 19{
@@ -54,7 +54,11 @@ class ContentProxy
54 54
55 if ((empty($content) || false === $this->validateContent($content)) && false === $disableContentUpdate) { 55 if ((empty($content) || false === $this->validateContent($content)) && false === $disableContentUpdate) {
56 $fetchedContent = $this->graby->fetchContent($url); 56 $fetchedContent = $this->graby->fetchContent($url);
57 $fetchedContent['title'] = $this->sanitizeContentTitle($fetchedContent['title'], $fetchedContent['content_type']); 57
58 $fetchedContent['title'] = $this->sanitizeContentTitle(
59 $fetchedContent['title'],
60 isset($fetchedContent['headers']['content-type']) ? $fetchedContent['headers']['content-type'] : ''
61 );
58 62
59 // when content is imported, we have information in $content 63 // when content is imported, we have information in $content
60 // in case fetching content goes bad, we'll keep the imported information instead of overriding them 64 // in case fetching content goes bad, we'll keep the imported information instead of overriding them
@@ -188,8 +192,8 @@ class ContentProxy
188 /** 192 /**
189 * Try to sanitize the title of the fetched content from wrong character encodings and invalid UTF-8 character. 193 * Try to sanitize the title of the fetched content from wrong character encodings and invalid UTF-8 character.
190 * 194 *
191 * @param $title 195 * @param string $title
192 * @param $contentType 196 * @param string $contentType
193 * 197 *
194 * @return string 198 * @return string
195 */ 199 */
@@ -253,16 +257,14 @@ class ContentProxy
253 257
254 if (!empty($content['title'])) { 258 if (!empty($content['title'])) {
255 $entry->setTitle($content['title']); 259 $entry->setTitle($content['title']);
256 } elseif (!empty($content['open_graph']['og_title'])) {
257 $entry->setTitle($content['open_graph']['og_title']);
258 } 260 }
259 261
260 if (empty($content['html'])) { 262 if (empty($content['html'])) {
261 $content['html'] = $this->fetchingErrorMessage; 263 $content['html'] = $this->fetchingErrorMessage;
262 264
263 if (!empty($content['open_graph']['og_description'])) { 265 if (!empty($content['description'])) {
264 $content['html'] .= '<p><i>But we found a short description: </i></p>'; 266 $content['html'] .= '<p><i>But we found a short description: </i></p>';
265 $content['html'] .= $content['open_graph']['og_description']; 267 $content['html'] .= $content['description'];
266 } 268 }
267 } 269 }
268 270
@@ -277,8 +279,8 @@ class ContentProxy
277 $entry->setPublishedBy($content['authors']); 279 $entry->setPublishedBy($content['authors']);
278 } 280 }
279 281
280 if (!empty($content['all_headers']) && $this->storeArticleHeaders) { 282 if (!empty($content['headers'])) {
281 $entry->setHeaders($content['all_headers']); 283 $entry->setHeaders($content['headers']);
282 } 284 }
283 285
284 if (!empty($content['date'])) { 286 if (!empty($content['date'])) {
@@ -289,17 +291,30 @@ class ContentProxy
289 $this->updateLanguage($entry, $content['language']); 291 $this->updateLanguage($entry, $content['language']);
290 } 292 }
291 293
292 if (!empty($content['open_graph']['og_image'])) { 294 $previewPictureUrl = '';
293 $this->updatePreviewPicture($entry, $content['open_graph']['og_image']); 295 if (!empty($content['image'])) {
296 $previewPictureUrl = $content['image'];
294 } 297 }
295 298
296 // if content is an image, define it as a preview too 299 // if content is an image, define it as a preview too
297 if (!empty($content['content_type']) && \in_array($this->mimeGuesser->guess($content['content_type']), ['jpeg', 'jpg', 'gif', 'png'], true)) { 300 if (!empty($content['headers']['content-type']) && \in_array($this->mimeGuesser->guess($content['headers']['content-type']), ['jpeg', 'jpg', 'gif', 'png'], true)) {
298 $this->updatePreviewPicture($entry, $content['url']); 301 $previewPictureUrl = $content['url'];
302 } elseif (empty($previewPictureUrl)) {
303 $this->logger->debug('Extracting images from content to provide a default preview picture');
304 $imagesUrls = DownloadImages::extractImagesUrlsFromHtml($content['html']);
305 $this->logger->debug(\count($imagesUrls) . ' pictures found');
306
307 if (!empty($imagesUrls)) {
308 $previewPictureUrl = $imagesUrls[0];
309 }
310 }
311
312 if (!empty($content['headers']['content-type'])) {
313 $entry->setMimetype($content['headers']['content-type']);
299 } 314 }
300 315
301 if (!empty($content['content_type'])) { 316 if (!empty($previewPictureUrl)) {
302 $entry->setMimetype($content['content_type']); 317 $this->updatePreviewPicture($entry, $previewPictureUrl);
303 } 318 }
304 319
305 try { 320 try {
diff --git a/src/Wallabag/CoreBundle/Helper/DownloadImages.php b/src/Wallabag/CoreBundle/Helper/DownloadImages.php
index 9a7e9828..7a39a2e4 100644
--- a/src/Wallabag/CoreBundle/Helper/DownloadImages.php
+++ b/src/Wallabag/CoreBundle/Helper/DownloadImages.php
@@ -2,8 +2,13 @@
2 2
3namespace Wallabag\CoreBundle\Helper; 3namespace Wallabag\CoreBundle\Helper;
4 4
5use GuzzleHttp\Client; 5use Http\Client\Common\HttpMethodsClient;
6use GuzzleHttp\Message\Response; 6use Http\Client\Common\Plugin\ErrorPlugin;
7use Http\Client\Common\PluginClient;
8use Http\Client\HttpClient;
9use Http\Discovery\MessageFactoryDiscovery;
10use Http\Message\MessageFactory;
11use Psr\Http\Message\ResponseInterface;
7use Psr\Log\LoggerInterface; 12use Psr\Log\LoggerInterface;
8use Symfony\Component\DomCrawler\Crawler; 13use Symfony\Component\DomCrawler\Crawler;
9use Symfony\Component\Finder\Finder; 14use Symfony\Component\Finder\Finder;
@@ -19,9 +24,9 @@ class DownloadImages
19 private $mimeGuesser; 24 private $mimeGuesser;
20 private $wallabagUrl; 25 private $wallabagUrl;
21 26
22 public function __construct(Client $client, $baseFolder, $wallabagUrl, LoggerInterface $logger) 27 public function __construct(HttpClient $client, $baseFolder, $wallabagUrl, LoggerInterface $logger, MessageFactory $messageFactory = null)
23 { 28 {
24 $this->client = $client; 29 $this->client = new HttpMethodsClient(new PluginClient($client, [new ErrorPlugin()]), $messageFactory ?: MessageFactoryDiscovery::find());
25 $this->baseFolder = $baseFolder; 30 $this->baseFolder = $baseFolder;
26 $this->wallabagUrl = rtrim($wallabagUrl, '/'); 31 $this->wallabagUrl = rtrim($wallabagUrl, '/');
27 $this->logger = $logger; 32 $this->logger = $logger;
@@ -31,23 +36,36 @@ class DownloadImages
31 } 36 }
32 37
33 /** 38 /**
34 * Process the html and extract image from it, save them to local and return the updated html. 39 * Process the html and extract images URLs from it.
35 * 40 *
36 * @param int $entryId ID of the entry
37 * @param string $html 41 * @param string $html
38 * @param string $url Used as a base path for relative image and folder
39 * 42 *
40 * @return string 43 * @return string[]
41 */ 44 */
42 public function processHtml($entryId, $html, $url) 45 public static function extractImagesUrlsFromHtml($html)
43 { 46 {
44 $crawler = new Crawler($html); 47 $crawler = new Crawler($html);
45 $imagesCrawler = $crawler 48 $imagesCrawler = $crawler
46 ->filterXpath('//img'); 49 ->filterXpath('//img');
47 $imagesUrls = $imagesCrawler 50 $imagesUrls = $imagesCrawler
48 ->extract(['src']); 51 ->extract(['src']);
49 $imagesSrcsetUrls = $this->getSrcsetUrls($imagesCrawler); 52 $imagesSrcsetUrls = self::getSrcsetUrls($imagesCrawler);
50 $imagesUrls = array_unique(array_merge($imagesUrls, $imagesSrcsetUrls)); 53
54 return array_unique(array_merge($imagesUrls, $imagesSrcsetUrls));
55 }
56
57 /**
58 * Process the html and extract image from it, save them to local and return the updated html.
59 *
60 * @param int $entryId ID of the entry
61 * @param string $html
62 * @param string $url Used as a base path for relative image and folder
63 *
64 * @return string
65 */
66 public function processHtml($entryId, $html, $url)
67 {
68 $imagesUrls = self::extractImagesUrlsFromHtml($html);
51 69
52 $relativePath = $this->getRelativePath($entryId); 70 $relativePath = $this->getRelativePath($entryId);
53 71
@@ -122,7 +140,7 @@ class DownloadImages
122 $localPath = $folderPath . '/' . $hashImage . '.' . $ext; 140 $localPath = $folderPath . '/' . $hashImage . '.' . $ext;
123 141
124 try { 142 try {
125 $im = imagecreatefromstring($res->getBody()); 143 $im = imagecreatefromstring((string) $res->getBody());
126 } catch (\Exception $e) { 144 } catch (\Exception $e) {
127 $im = false; 145 $im = false;
128 } 146 }
@@ -199,7 +217,7 @@ 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
@@ -293,14 +311,14 @@ class DownloadImages
293 /** 311 /**
294 * Retrieve and validate the extension from the response of the url of the image. 312 * Retrieve and validate the extension from the response of the url of the image.
295 * 313 *
296 * @param Response $res Guzzle Response 314 * @param ResponseInterface $res Http Response
297 * @param string $imagePath Path from the src image from the content (used for log only) 315 * @param string $imagePath Path from the src image from the content (used for log only)
298 * 316 *
299 * @return string|false Extension name or false if validation failed 317 * @return string|false Extension name or false if validation failed
300 */ 318 */
301 private function getExtensionFromResponse(Response $res, $imagePath) 319 private function getExtensionFromResponse(ResponseInterface $res, $imagePath)
302 { 320 {
303 $ext = $this->mimeGuesser->guess($res->getHeader('content-type')); 321 $ext = $this->mimeGuesser->guess(current($res->getHeader('content-type')));
304 $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]); 322 $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]);
305 323
306 // ok header doesn't have the extension, try a different way 324 // ok header doesn't have the extension, try a different way
diff --git a/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php b/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php
index 4602a684..b8e95381 100644
--- a/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php
+++ b/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php
@@ -2,16 +2,18 @@
2 2
3namespace Wallabag\CoreBundle\Helper; 3namespace Wallabag\CoreBundle\Helper;
4 4
5use Graby\Ring\Client\SafeCurlHandler; 5use GuzzleHttp\Client as GuzzleClient;
6use GuzzleHttp\Client;
7use GuzzleHttp\Cookie\CookieJar; 6use GuzzleHttp\Cookie\CookieJar;
8use GuzzleHttp\Event\SubscriberInterface; 7use GuzzleHttp\Event\SubscriberInterface;
8use Http\Adapter\Guzzle5\Client as GuzzleAdapter;
9use Http\Client\HttpClient;
10use Http\HttplugBundle\ClientFactory\ClientFactory;
9use Psr\Log\LoggerInterface; 11use Psr\Log\LoggerInterface;
10 12
11/** 13/**
12 * Builds and configures the Guzzle HTTP client. 14 * Builds and configures the HTTP client.
13 */ 15 */
14class HttpClientFactory 16class 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/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/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
3namespace Wallabag\ImportBundle\Import; 3namespace Wallabag\ImportBundle\Import;
4 4
5use GuzzleHttp\Client; 5use Http\Client\Common\HttpMethodsClient;
6use GuzzleHttp\Exception\RequestException; 6use Http\Client\Common\Plugin\ErrorPlugin;
7use Http\Client\Common\PluginClient;
8use Http\Client\Exception\RequestException;
9use Http\Client\HttpClient;
10use Http\Discovery\MessageFactoryDiscovery;
11use Http\Message\MessageFactory;
12use Psr\Http\Message\ResponseInterface;
7use Wallabag\CoreBundle\Entity\Entry; 13use Wallabag\CoreBundle\Entity\Entry;
8 14
9class PocketImport extends AbstractImport 15class 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