]> git.immae.eu Git - github/wallabag/wallabag.git/blame - src/Wallabag/ImportBundle/Import/PocketImport.php
Fix `findOneByUrl` side effect in tests
[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;
d1af8ad4 26 private $translator;
ff7b031d 27
b88cf91f 28 public function __construct(TokenStorageInterface $tokenStorage, EntityManager $em, ContentProxy $contentProxy, $consumerKey)
ff7b031d
NL
29 {
30 $this->user = $tokenStorage->getToken()->getUser();
ff7b031d 31 $this->em = $em;
252ebd60 32 $this->contentProxy = $contentProxy;
ff7b031d 33 $this->consumerKey = $consumerKey;
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
180 /**
252ebd60 181 * @todo move that in a more global place
dda57bb9 182 */
87f23b00
NL
183 private function assignTagsToEntry(Entry $entry, $tags)
184 {
185 foreach ($tags as $tag) {
186 $label = trim($tag['tag']);
187 $tagEntity = $this->em
188 ->getRepository('WallabagCoreBundle:Tag')
c5c7f90a 189 ->findOneByLabel($label);
87f23b00
NL
190
191 if (is_object($tagEntity)) {
192 $entry->addTag($tagEntity);
193 } else {
c5c7f90a 194 $newTag = new Tag();
87f23b00 195 $newTag->setLabel($label);
c5c7f90a 196
87f23b00
NL
197 $entry->addTag($newTag);
198 }
199 $this->em->flush();
200 }
201 }
202
ff7b031d 203 /**
252ebd60
JB
204 * @see https://getpocket.com/developer/docs/v3/retrieve
205 *
ff7b031d
NL
206 * @param $entries
207 */
b1d05721 208 private function parseEntries($entries)
ff7b031d 209 {
7019c7cf
JB
210 $i = 1;
211
87f23b00 212 foreach ($entries as $pocketEntry) {
252ebd60 213 $url = isset($pocketEntry['resolved_url']) && $pocketEntry['resolved_url'] != '' ? $pocketEntry['resolved_url'] : $pocketEntry['given_url'];
dda57bb9
NL
214
215 $existingEntry = $this->em
216 ->getRepository('WallabagCoreBundle:Entry')
78833672 217 ->findByUrlAndUserId($url, $this->user->getId());
dda57bb9 218
5a4bbcc9 219 if (false !== $existingEntry) {
dda57bb9
NL
220 ++$this->skippedEntries;
221 continue;
222 }
223
b1d05721 224 $entry = new Entry($this->user);
252ebd60 225 $entry = $this->contentProxy->updateEntry($entry, $url);
dda57bb9 226
252ebd60 227 // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted
87f23b00
NL
228 if ($pocketEntry['status'] == 1) {
229 $entry->setArchived(true);
230 }
252ebd60
JB
231
232 // 0 or 1 - 1 If the item is favorited
87f23b00
NL
233 if ($pocketEntry['favorite'] == 1) {
234 $entry->setStarred(true);
235 }
236
252ebd60
JB
237 $title = 'Untitled';
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'];
87f23b00 242 }
ff7b031d 243
252ebd60 244 $entry->setTitle($title);
ff7b031d 245
252ebd60
JB
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']);
ff7b031d
NL
249 }
250
252ebd60 251 if (isset($pocketEntry['tags']) && !empty($pocketEntry['tags'])) {
303768df 252 $this->assignTagsToEntry($entry, $pocketEntry['tags']);
ff7b031d
NL
253 }
254
87f23b00 255 $this->em->persist($entry);
dda57bb9 256 ++$this->importedEntries;
7019c7cf
JB
257
258 // flush every 20 entries
259 if (($i % 20) === 0) {
8eedc8cf 260 $this->em->flush();
7019c7cf
JB
261 }
262 ++$i;
ff7b031d
NL
263 }
264
265 $this->em->flush();
266 }
ff7b031d 267}