3 namespace Wallabag\ImportBundle\Import
;
5 use Psr\Log\LoggerInterface
;
6 use Psr\Log\NullLogger
;
7 use Doctrine\ORM\EntityManager
;
9 use GuzzleHttp\Exception\RequestException
;
10 use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface
;
11 use Wallabag\CoreBundle\Entity\Entry
;
12 use Wallabag\CoreBundle\Helper\ContentProxy
;
13 use Craue\ConfigBundle\Util\Config
;
15 class PocketImport
implements ImportInterface
19 private $contentProxy;
23 private $skippedEntries = 0;
24 private $importedEntries = 0;
25 protected $accessToken;
27 public function __construct(TokenStorageInterface
$tokenStorage, EntityManager
$em, ContentProxy
$contentProxy, Config
$craueConfig)
29 $this->user
= $tokenStorage->getToken()->getUser();
31 $this->contentProxy
= $contentProxy;
32 $this->consumerKey
= $craueConfig->get('pocket_consumer_key');
33 $this->logger
= new NullLogger();
36 public function setLogger(LoggerInterface
$logger)
38 $this->logger
= $logger;
44 public function getName()
52 public function getUrl()
54 return 'import_pocket';
60 public function getDescription()
62 return 'This importer will import all your Pocket data. Pocket doesn\'t allow us to retrieve content from their service, so the readable content of each article will be re-fetched by wallabag.';
66 * Return the oauth url to authenticate the client.
68 * @param string $redirectUri Redirect url in case of error
70 * @return string request_token for callback method
72 public function getRequestToken($redirectUri)
74 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/oauth/request',
76 'body' => json_encode([
77 'consumer_key' => $this->consumerKey
,
78 'redirect_uri' => $redirectUri,
84 $response = $this->client
->send($request);
85 } catch (RequestException
$e) {
86 $this->logger
->error(sprintf('PocketImport: Failed to request token: %s', $e->getMessage()), ['exception' => $e]);
91 return $response->json()['code'];
95 * Usually called by the previous callback to authorize the client.
96 * Then it return a token that can be used for next requests.
98 * @param string $code request_token from getRequestToken
102 public function authorize($code)
104 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/oauth/authorize',
106 'body' => json_encode([
107 'consumer_key' => $this->consumerKey
,
114 $response = $this->client
->send($request);
115 } catch (RequestException
$e) {
116 $this->logger
->error(sprintf('PocketImport: Failed to authorize client: %s', $e->getMessage()), ['exception' => $e]);
121 $this->accessToken
= $response->json()['access_token'];
129 public function import()
131 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/get',
133 'body' => json_encode([
134 'consumer_key' => $this->consumerKey
,
135 'access_token' => $this->accessToken
,
136 'detailType' => 'complete',
144 $response = $this->client
->send($request);
145 } catch (RequestException
$e) {
146 $this->logger
->error(sprintf('PocketImport: Failed to import: %s', $e->getMessage()), ['exception' => $e]);
151 $entries = $response->json();
153 $this->parseEntries($entries['list']);
161 public function getSummary()
164 'skipped' => $this->skippedEntries
,
165 'imported' => $this->importedEntries
,
170 * Set the Guzzle client.
172 * @param Client $client
174 public function setClient(Client
$client)
176 $this->client
= $client;
180 * @see https://getpocket.com/developer/docs/v3/retrieve
184 private function parseEntries($entries)
188 foreach ($entries as $pocketEntry) {
189 $url = isset($pocketEntry['resolved_url']) && $pocketEntry['resolved_url'] != '' ? $pocketEntry['resolved_url'] : $pocketEntry['given_url'];
191 $existingEntry = $this->em
192 ->getRepository('WallabagCoreBundle:Entry')
193 ->findByUrlAndUserId($url, $this->user
->getId());
195 if (false !== $existingEntry) {
196 ++
$this->skippedEntries
;
200 $entry = new Entry($this->user
);
201 $entry = $this->contentProxy
->updateEntry($entry, $url);
203 // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted
204 if ($pocketEntry['status'] == 1) {
205 $entry->setArchived(true);
208 // 0 or 1 - 1 If the item is favorited
209 if ($pocketEntry['favorite'] == 1) {
210 $entry->setStarred(true);
214 if (isset($pocketEntry['resolved_title']) && $pocketEntry['resolved_title'] != '') {
215 $title = $pocketEntry['resolved_title'];
216 } elseif (isset($pocketEntry['given_title']) && $pocketEntry['given_title'] != '') {
217 $title = $pocketEntry['given_title'];
220 $entry->setTitle($title);
222 // 0, 1, or 2 - 1 if the item has images in it - 2 if the item is an image
223 if (isset($pocketEntry['has_image']) && $pocketEntry['has_image'] > 0 && isset($pocketEntry['images'][1])) {
224 $entry->setPreviewPicture($pocketEntry['images'][1]['src']);
227 if (isset($pocketEntry['tags']) && !empty($pocketEntry['tags'])) {
228 $this->contentProxy
->assignTagsToEntry(
230 array_keys($pocketEntry['tags'])
234 $this->em
->persist($entry);
235 ++
$this->importedEntries
;
237 // flush every 20 entries
238 if (($i %
20) === 0) {