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