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\Entity\Tag
;
13 use Wallabag\CoreBundle\Helper\ContentProxy
;
15 class PocketImport
implements ImportInterface
19 private $contentProxy;
23 private $skippedEntries = 0;
24 private $importedEntries = 0;
25 protected $accessToken;
28 public function __construct(TokenStorageInterface
$tokenStorage, EntityManager
$em, ContentProxy
$contentProxy, $consumerKey)
30 $this->user
= $tokenStorage->getToken()->getUser();
32 $this->contentProxy
= $contentProxy;
33 $this->consumerKey
= $consumerKey;
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'];
130 public function import()
132 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/get',
134 'body' => json_encode([
135 'consumer_key' => $this->consumerKey
,
136 'access_token' => $this->accessToken
,
137 'detailType' => 'complete',
145 $response = $this->client
->send($request);
146 } catch (RequestException
$e) {
147 $this->logger
->error(sprintf('PocketImport: Failed to import: %s', $e->getMessage()), ['exception' => $e]);
152 $entries = $response->json();
154 $this->parseEntries($entries['list']);
162 public function getSummary()
165 'skipped' => $this->skippedEntries
,
166 'imported' => $this->importedEntries
,
171 * Set the Guzzle client.
173 * @param Client $client
175 public function setClient(Client
$client)
177 $this->client
= $client;
181 * @todo move that in a more global place
183 private function assignTagsToEntry(Entry
$entry, $tags)
185 foreach ($tags as $tag) {
186 $label = trim($tag['tag']);
187 $tagEntity = $this->em
188 ->getRepository('WallabagCoreBundle:Tag')
189 ->findOneByLabel($label);
191 if (is_object($tagEntity)) {
192 $entry->addTag($tagEntity);
195 $newTag->setLabel($label);
197 $entry->addTag($newTag);
204 * @see https://getpocket.com/developer/docs/v3/retrieve
208 private function parseEntries($entries)
212 foreach ($entries as $pocketEntry) {
213 $url = isset($pocketEntry['resolved_url']) && $pocketEntry['resolved_url'] != '' ? $pocketEntry['resolved_url'] : $pocketEntry['given_url'];
215 $existingEntry = $this->em
216 ->getRepository('WallabagCoreBundle:Entry')
217 ->findByUrlAndUserId($url, $this->user
->getId());
219 if (false !== $existingEntry) {
220 ++
$this->skippedEntries
;
224 $entry = new Entry($this->user
);
225 $entry = $this->contentProxy
->updateEntry($entry, $url);
227 // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted
228 if ($pocketEntry['status'] == 1) {
229 $entry->setArchived(true);
232 // 0 or 1 - 1 If the item is favorited
233 if ($pocketEntry['favorite'] == 1) {
234 $entry->setStarred(true);
238 if (isset($pocketEntry['resolved_title']) && $pocketEntry['resolved_title'] != '') {
239 $title = $pocketEntry['resolved_title'];
240 } elseif (isset($pocketEntry['given_title']) && $pocketEntry['given_title'] != '') {
241 $title = $pocketEntry['given_title'];
244 $entry->setTitle($title);
246 // 0, 1, or 2 - 1 if the item has images in it - 2 if the item is an image
247 if (isset($pocketEntry['has_image']) && $pocketEntry['has_image'] > 0 && isset($pocketEntry['images'][1])) {
248 $entry->setPreviewPicture($pocketEntry['images'][1]['src']);
251 if (isset($pocketEntry['tags']) && !empty($pocketEntry['tags'])) {
252 $this->assignTagsToEntry($entry, $pocketEntry['tags']);
255 $this->em
->persist($entry);
256 ++
$this->importedEntries
;
258 // flush every 20 entries
259 if (($i %
20) === 0) {