]> git.immae.eu Git - github/wallabag/wallabag.git/blame - src/Wallabag/ImportBundle/Import/PocketImport.php
Merge pull request #1693 from wallabag/v2-issue-template
[github/wallabag/wallabag.git] / src / Wallabag / ImportBundle / Import / PocketImport.php
CommitLineData
ff7b031d
NL
1<?php
2
3namespace Wallabag\ImportBundle\Import;
4
252ebd60
JB
5use Psr\Log\LoggerInterface;
6use Psr\Log\NullLogger;
ff7b031d
NL
7use Doctrine\ORM\EntityManager;
8use GuzzleHttp\Client;
252ebd60 9use GuzzleHttp\Exception\RequestException;
0aa344dc 10use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
ff7b031d 11use Wallabag\CoreBundle\Entity\Entry;
87f23b00 12use Wallabag\CoreBundle\Entity\Tag;
252ebd60 13use Wallabag\CoreBundle\Helper\ContentProxy;
63e40f2d 14use Craue\ConfigBundle\Util\Config;
ff7b031d
NL
15
16class PocketImport implements ImportInterface
17{
18 private $user;
ff7b031d 19 private $em;
252ebd60
JB
20 private $contentProxy;
21 private $logger;
8eedc8cf 22 private $client;
ff7b031d 23 private $consumerKey;
303768df
NL
24 private $skippedEntries = 0;
25 private $importedEntries = 0;
252ebd60 26 protected $accessToken;
ff7b031d 27
63e40f2d 28 public function __construct(TokenStorageInterface $tokenStorage, EntityManager $em, ContentProxy $contentProxy, Config $craueConfig)
ff7b031d
NL
29 {
30 $this->user = $tokenStorage->getToken()->getUser();
ff7b031d 31 $this->em = $em;
252ebd60 32 $this->contentProxy = $contentProxy;
63e40f2d 33 $this->consumerKey = $craueConfig->get('pocket_consumer_key');
252ebd60
JB
34 $this->logger = new NullLogger();
35 }
36
37 public function setLogger(LoggerInterface $logger)
38 {
39 $this->logger = $logger;
ff7b031d
NL
40 }
41
0aa344dc
JB
42 /**
43 * {@inheritdoc}
44 */
d51b38ed
NL
45 public function getName()
46 {
47 return 'Pocket';
48 }
49
7019c7cf
JB
50 /**
51 * {@inheritdoc}
52 */
53 public function getUrl()
54 {
55 return 'import_pocket';
56 }
57
0aa344dc
JB
58 /**
59 * {@inheritdoc}
60 */
d51b38ed
NL
61 public function getDescription()
62 {
b88cf91f 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.';
d51b38ed
NL
64 }
65
ff7b031d 66 /**
252ebd60
JB
67 * Return the oauth url to authenticate the client.
68 *
69 * @param string $redirectUri Redirect url in case of error
70 *
71 * @return string request_token for callback method
7ec2897e 72 */
252ebd60 73 public function getRequestToken($redirectUri)
7ec2897e
JB
74 {
75 $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/oauth/request',
76 [
77 'body' => json_encode([
78 'consumer_key' => $this->consumerKey,
79 'redirect_uri' => $redirectUri,
80 ]),
81 ]
82 );
83
252ebd60
JB
84 try {
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]);
7ec2897e 88
252ebd60
JB
89 return false;
90 }
7ec2897e 91
252ebd60 92 return $response->json()['code'];
7ec2897e
JB
93 }
94
95 /**
252ebd60
JB
96 * Usually called by the previous callback to authorize the client.
97 * Then it return a token that can be used for next requests.
98 *
99 * @param string $code request_token from getRequestToken
100 *
101 * @return bool
7ec2897e 102 */
252ebd60 103 public function authorize($code)
7ec2897e
JB
104 {
105 $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/oauth/authorize',
106 [
107 'body' => json_encode([
108 'consumer_key' => $this->consumerKey,
252ebd60 109 'code' => $code,
7ec2897e
JB
110 ]),
111 ]
112 );
113
252ebd60
JB
114 try {
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]);
7ec2897e 118
252ebd60
JB
119 return false;
120 }
121
122 $this->accessToken = $response->json()['access_token'];
123
124 return true;
7ec2897e
JB
125 }
126
127 /**
128 * {@inheritdoc}
129 */
252ebd60 130 public function import()
7ec2897e
JB
131 {
132 $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/get',
133 [
134 'body' => json_encode([
135 'consumer_key' => $this->consumerKey,
252ebd60 136 'access_token' => $this->accessToken,
7ec2897e
JB
137 'detailType' => 'complete',
138 'state' => 'all',
139 'sort' => 'oldest',
140 ]),
141 ]
142 );
143
252ebd60
JB
144 try {
145 $response = $this->client->send($request);
146 } catch (RequestException $e) {
147 $this->logger->error(sprintf('PocketImport: Failed to import: %s', $e->getMessage()), ['exception' => $e]);
148
149 return false;
150 }
151
7ec2897e
JB
152 $entries = $response->json();
153
b1d05721 154 $this->parseEntries($entries['list']);
7ec2897e 155
252ebd60 156 return true;
7ec2897e
JB
157 }
158
159 /**
252ebd60 160 * {@inheritdoc}
ff7b031d 161 */
252ebd60 162 public function getSummary()
ff7b031d 163 {
252ebd60
JB
164 return [
165 'skipped' => $this->skippedEntries,
166 'imported' => $this->importedEntries,
167 ];
ff7b031d
NL
168 }
169
87f23b00 170 /**
252ebd60 171 * Set the Guzzle client.
87f23b00 172 *
252ebd60 173 * @param Client $client
87f23b00 174 */
252ebd60 175 public function setClient(Client $client)
87f23b00 176 {
252ebd60 177 $this->client = $client;
dda57bb9
NL
178 }
179
87f23b00
NL
180 private function assignTagsToEntry(Entry $entry, $tags)
181 {
182 foreach ($tags as $tag) {
183 $label = trim($tag['tag']);
184 $tagEntity = $this->em
185 ->getRepository('WallabagCoreBundle:Tag')
c5c7f90a 186 ->findOneByLabel($label);
87f23b00
NL
187
188 if (is_object($tagEntity)) {
189 $entry->addTag($tagEntity);
190 } else {
c5c7f90a 191 $newTag = new Tag();
87f23b00 192 $newTag->setLabel($label);
c5c7f90a 193
87f23b00
NL
194 $entry->addTag($newTag);
195 }
196 $this->em->flush();
197 }
198 }
199
ff7b031d 200 /**
252ebd60
JB
201 * @see https://getpocket.com/developer/docs/v3/retrieve
202 *
ff7b031d
NL
203 * @param $entries
204 */
b1d05721 205 private function parseEntries($entries)
ff7b031d 206 {
7019c7cf
JB
207 $i = 1;
208
87f23b00 209 foreach ($entries as $pocketEntry) {
252ebd60 210 $url = isset($pocketEntry['resolved_url']) && $pocketEntry['resolved_url'] != '' ? $pocketEntry['resolved_url'] : $pocketEntry['given_url'];
dda57bb9
NL
211
212 $existingEntry = $this->em
213 ->getRepository('WallabagCoreBundle:Entry')
78833672 214 ->findByUrlAndUserId($url, $this->user->getId());
dda57bb9 215
5a4bbcc9 216 if (false !== $existingEntry) {
dda57bb9
NL
217 ++$this->skippedEntries;
218 continue;
219 }
220
b1d05721 221 $entry = new Entry($this->user);
252ebd60 222 $entry = $this->contentProxy->updateEntry($entry, $url);
dda57bb9 223
252ebd60 224 // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted
87f23b00
NL
225 if ($pocketEntry['status'] == 1) {
226 $entry->setArchived(true);
227 }
252ebd60
JB
228
229 // 0 or 1 - 1 If the item is favorited
87f23b00
NL
230 if ($pocketEntry['favorite'] == 1) {
231 $entry->setStarred(true);
232 }
233
252ebd60
JB
234 $title = 'Untitled';
235 if (isset($pocketEntry['resolved_title']) && $pocketEntry['resolved_title'] != '') {
236 $title = $pocketEntry['resolved_title'];
237 } elseif (isset($pocketEntry['given_title']) && $pocketEntry['given_title'] != '') {
238 $title = $pocketEntry['given_title'];
87f23b00 239 }
ff7b031d 240
252ebd60 241 $entry->setTitle($title);
ff7b031d 242
252ebd60
JB
243 // 0, 1, or 2 - 1 if the item has images in it - 2 if the item is an image
244 if (isset($pocketEntry['has_image']) && $pocketEntry['has_image'] > 0 && isset($pocketEntry['images'][1])) {
245 $entry->setPreviewPicture($pocketEntry['images'][1]['src']);
ff7b031d
NL
246 }
247
252ebd60 248 if (isset($pocketEntry['tags']) && !empty($pocketEntry['tags'])) {
303768df 249 $this->assignTagsToEntry($entry, $pocketEntry['tags']);
ff7b031d
NL
250 }
251
87f23b00 252 $this->em->persist($entry);
dda57bb9 253 ++$this->importedEntries;
7019c7cf
JB
254
255 // flush every 20 entries
256 if (($i % 20) === 0) {
8eedc8cf 257 $this->em->flush();
7019c7cf
JB
258 }
259 ++$i;
ff7b031d
NL
260 }
261
262 $this->em->flush();
263 }
ff7b031d 264}