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
;
14 use Craue\ConfigBundle\Util\Config
;
16 class PocketImport
implements ImportInterface
20 private $contentProxy;
24 private $skippedEntries = 0;
25 private $importedEntries = 0;
26 protected $accessToken;
29 public function __construct(TokenStorageInterface
$tokenStorage, EntityManager
$em, ContentProxy
$contentProxy, Config
$craueConfig)
31 $this->user
= $tokenStorage->getToken()->getUser();
33 $this->contentProxy
= $contentProxy;
34 $this->consumerKey
= $craueConfig->get('pocket_consumer_key');
35 $this->logger
= new NullLogger();
38 public function setLogger(LoggerInterface
$logger)
40 $this->logger
= $logger;
46 public function getName()
54 public function getUrl()
56 return 'import_pocket';
62 public function getDescription()
64 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.';
68 * Return the oauth url to authenticate the client.
70 * @param string $redirectUri Redirect url in case of error
72 * @return string request_token for callback method
74 public function getRequestToken($redirectUri)
76 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/oauth/request',
78 'body' => json_encode([
79 'consumer_key' => $this->consumerKey
,
80 'redirect_uri' => $redirectUri,
86 $response = $this->client
->send($request);
87 } catch (RequestException
$e) {
88 $this->logger
->error(sprintf('PocketImport: Failed to request token: %s', $e->getMessage()), ['exception' => $e]);
93 return $response->json()['code'];
97 * Usually called by the previous callback to authorize the client.
98 * Then it return a token that can be used for next requests.
100 * @param string $code request_token from getRequestToken
104 public function authorize($code)
106 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/oauth/authorize',
108 'body' => json_encode([
109 'consumer_key' => $this->consumerKey
,
116 $response = $this->client
->send($request);
117 } catch (RequestException
$e) {
118 $this->logger
->error(sprintf('PocketImport: Failed to authorize client: %s', $e->getMessage()), ['exception' => $e]);
123 $this->accessToken
= $response->json()['access_token'];
131 public function import()
133 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/get',
135 'body' => json_encode([
136 'consumer_key' => $this->consumerKey
,
137 'access_token' => $this->accessToken
,
138 'detailType' => 'complete',
146 $response = $this->client
->send($request);
147 } catch (RequestException
$e) {
148 $this->logger
->error(sprintf('PocketImport: Failed to import: %s', $e->getMessage()), ['exception' => $e]);
153 $entries = $response->json();
155 $this->parseEntries($entries['list']);
163 public function getSummary()
166 'skipped' => $this->skippedEntries
,
167 'imported' => $this->importedEntries
,
172 * Set the Guzzle client.
174 * @param Client $client
176 public function setClient(Client
$client)
178 $this->client
= $client;
182 * @todo move that in a more global place
184 private function assignTagsToEntry(Entry
$entry, $tags)
186 foreach ($tags as $tag) {
187 $label = trim($tag['tag']);
188 $tagEntity = $this->em
189 ->getRepository('WallabagCoreBundle:Tag')
190 ->findOneByLabel($label);
192 if (is_object($tagEntity)) {
193 $entry->addTag($tagEntity);
196 $newTag->setLabel($label);
198 $entry->addTag($newTag);
205 * @see https://getpocket.com/developer/docs/v3/retrieve
209 private function parseEntries($entries)
213 foreach ($entries as $pocketEntry) {
214 $url = isset($pocketEntry['resolved_url']) && $pocketEntry['resolved_url'] != '' ? $pocketEntry['resolved_url'] : $pocketEntry['given_url'];
216 $existingEntry = $this->em
217 ->getRepository('WallabagCoreBundle:Entry')
218 ->findByUrlAndUserId($url, $this->user
->getId());
220 if (false !== $existingEntry) {
221 ++
$this->skippedEntries
;
225 $entry = new Entry($this->user
);
226 $entry = $this->contentProxy
->updateEntry($entry, $url);
228 // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted
229 if ($pocketEntry['status'] == 1) {
230 $entry->setArchived(true);
233 // 0 or 1 - 1 If the item is favorited
234 if ($pocketEntry['favorite'] == 1) {
235 $entry->setStarred(true);
239 if (isset($pocketEntry['resolved_title']) && $pocketEntry['resolved_title'] != '') {
240 $title = $pocketEntry['resolved_title'];
241 } elseif (isset($pocketEntry['given_title']) && $pocketEntry['given_title'] != '') {
242 $title = $pocketEntry['given_title'];
245 $entry->setTitle($title);
247 // 0, 1, or 2 - 1 if the item has images in it - 2 if the item is an image
248 if (isset($pocketEntry['has_image']) && $pocketEntry['has_image'] > 0 && isset($pocketEntry['images'][1])) {
249 $entry->setPreviewPicture($pocketEntry['images'][1]['src']);
252 if (isset($pocketEntry['tags']) && !empty($pocketEntry['tags'])) {
253 $this->assignTagsToEntry($entry, $pocketEntry['tags']);
256 $this->em
->persist($entry);
257 ++
$this->importedEntries
;
259 // flush every 20 entries
260 if (($i %
20) === 0) {