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;
26 protected $accessToken;
28 public function __construct(TokenStorageInterface
$tokenStorage, EntityManager
$em, ContentProxy
$contentProxy, Config
$craueConfig)
30 $this->user
= $tokenStorage->getToken()->getUser();
32 $this->contentProxy
= $contentProxy;
33 $this->consumerKey
= $craueConfig->get('pocket_consumer_key');
34 $this->logger
= new NullLogger();
37 public function setLogger(LoggerInterface
$logger)
39 $this->logger
= $logger;
45 public function getName()
53 public function getUrl()
55 return 'import_pocket';
61 public function getDescription()
63 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.';
67 * Return the oauth url to authenticate the client.
69 * @param string $redirectUri Redirect url in case of error
71 * @return string request_token for callback method
73 public function getRequestToken($redirectUri)
75 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/oauth/request',
77 'body' => json_encode([
78 'consumer_key' => $this->consumerKey
,
79 'redirect_uri' => $redirectUri,
85 $response = $this->client
->send($request);
86 } catch (RequestException
$e) {
87 $this->logger
->error(sprintf('PocketImport: Failed to request token: %s', $e->getMessage()), ['exception' => $e]);
92 return $response->json()['code'];
96 * Usually called by the previous callback to authorize the client.
97 * Then it return a token that can be used for next requests.
99 * @param string $code request_token from getRequestToken
103 public function authorize($code)
105 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/oauth/authorize',
107 'body' => json_encode([
108 'consumer_key' => $this->consumerKey
,
115 $response = $this->client
->send($request);
116 } catch (RequestException
$e) {
117 $this->logger
->error(sprintf('PocketImport: Failed to authorize client: %s', $e->getMessage()), ['exception' => $e]);
122 $this->accessToken
= $response->json()['access_token'];
129 * Set whether articles must be all marked as read.
131 * @param bool $markAsRead
133 public function setMarkAsRead($markAsRead)
135 $this->markAsRead
= $markAsRead;
141 * Get whether articles must be all marked as read.
143 public function getRead()
145 return $this->markAsRead
;
151 public function import()
153 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/get',
155 'body' => json_encode([
156 'consumer_key' => $this->consumerKey
,
157 'access_token' => $this->accessToken
,
158 'detailType' => 'complete',
166 $response = $this->client
->send($request);
167 } catch (RequestException
$e) {
168 $this->logger
->error(sprintf('PocketImport: Failed to import: %s', $e->getMessage()), ['exception' => $e]);
173 $entries = $response->json();
175 $this->parseEntries($entries['list']);
183 public function getSummary()
186 'skipped' => $this->skippedEntries
,
187 'imported' => $this->importedEntries
,
192 * Set the Guzzle client.
194 * @param Client $client
196 public function setClient(Client
$client)
198 $this->client
= $client;
202 * @see https://getpocket.com/developer/docs/v3/retrieve
206 private function parseEntries($entries)
210 foreach ($entries as $pocketEntry) {
211 $url = isset($pocketEntry['resolved_url']) && $pocketEntry['resolved_url'] != '' ? $pocketEntry['resolved_url'] : $pocketEntry['given_url'];
213 $existingEntry = $this->em
214 ->getRepository('WallabagCoreBundle:Entry')
215 ->findByUrlAndUserId($url, $this->user
->getId());
217 if (false !== $existingEntry) {
218 ++
$this->skippedEntries
;
222 $entry = new Entry($this->user
);
223 $entry = $this->contentProxy
->updateEntry($entry, $url);
225 // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted
226 if ($pocketEntry['status'] == 1 | $this->markAsRead
) {
227 $entry->setArchived(true);
230 // 0 or 1 - 1 If the item is favorited
231 if ($pocketEntry['favorite'] == 1) {
232 $entry->setStarred(true);
236 if (isset($pocketEntry['resolved_title']) && $pocketEntry['resolved_title'] != '') {
237 $title = $pocketEntry['resolved_title'];
238 } elseif (isset($pocketEntry['given_title']) && $pocketEntry['given_title'] != '') {
239 $title = $pocketEntry['given_title'];
242 $entry->setTitle($title);
244 // 0, 1, or 2 - 1 if the item has images in it - 2 if the item is an image
245 if (isset($pocketEntry['has_image']) && $pocketEntry['has_image'] > 0 && isset($pocketEntry['images'][1])) {
246 $entry->setPreviewPicture($pocketEntry['images'][1]['src']);
249 if (isset($pocketEntry['tags']) && !empty($pocketEntry['tags'])) {
250 $this->contentProxy
->assignTagsToEntry(
252 array_keys($pocketEntry['tags'])
256 $this->em
->persist($entry);
257 ++
$this->importedEntries
;
259 // flush every 20 entries
260 if (($i %
20) === 0) {