3 namespace Wallabag\ImportBundle\Import
;
5 use OldSound\RabbitMqBundle\RabbitMq\Producer
;
6 use Psr\Log\NullLogger
;
7 use Doctrine\ORM\EntityManager
;
9 use GuzzleHttp\Exception\RequestException
;
10 use Symfony\Component\Security\Core\User\UserInterface
;
11 use Wallabag\CoreBundle\Entity\Entry
;
12 use Wallabag\CoreBundle\Helper\ContentProxy
;
13 use Craue\ConfigBundle\Util\Config
;
15 class PocketImport
extends AbstractImport
20 private $skippedEntries = 0;
21 private $importedEntries = 0;
24 protected $accessToken;
26 public function __construct(EntityManager
$em, ContentProxy
$contentProxy, Config
$craueConfig)
29 $this->contentProxy
= $contentProxy;
30 $this->consumerKey
= $craueConfig->get('pocket_consumer_key');
31 $this->logger
= new NullLogger();
35 * Set RabbitMQ Producer to send each entry to a queue.
36 * This method should be called when user has enabled RabbitMQ.
38 * @param Producer $producer
40 public function setRabbitmqProducer(Producer
$producer)
42 $this->producer
= $producer;
47 * Could the current *connected* user or one retrieve by the consumer.
49 * @param UserInterface $user
51 public function setUser(UserInterface
$user)
59 public function getName()
67 public function getUrl()
69 return 'import_pocket';
75 public function getDescription()
77 return 'import.pocket.description';
81 * Return the oauth url to authenticate the client.
83 * @param string $redirectUri Redirect url in case of error
85 * @return string|false request_token for callback method
87 public function getRequestToken($redirectUri)
89 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/oauth/request',
91 'body' => json_encode([
92 'consumer_key' => $this->consumerKey
,
93 'redirect_uri' => $redirectUri,
99 $response = $this->client
->send($request);
100 } catch (RequestException
$e) {
101 $this->logger
->error(sprintf('PocketImport: Failed to request token: %s', $e->getMessage()), ['exception' => $e]);
106 return $response->json()['code'];
110 * Usually called by the previous callback to authorize the client.
111 * Then it return a token that can be used for next requests.
113 * @param string $code request_token from getRequestToken
117 public function authorize($code)
119 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/oauth/authorize',
121 'body' => json_encode([
122 'consumer_key' => $this->consumerKey
,
129 $response = $this->client
->send($request);
130 } catch (RequestException
$e) {
131 $this->logger
->error(sprintf('PocketImport: Failed to authorize client: %s', $e->getMessage()), ['exception' => $e]);
136 $this->accessToken
= $response->json()['access_token'];
142 * Set whether articles must be all marked as read.
144 * @param bool $markAsRead
146 public function setMarkAsRead($markAsRead)
148 $this->markAsRead
= $markAsRead;
154 * Get whether articles must be all marked as read.
156 public function getMarkAsRead()
158 return $this->markAsRead
;
164 public function import()
166 $request = $this->client
->createRequest('POST', 'https://getpocket.com/v3/get',
168 'body' => json_encode([
169 'consumer_key' => $this->consumerKey
,
170 'access_token' => $this->accessToken
,
171 'detailType' => 'complete',
179 $response = $this->client
->send($request);
180 } catch (RequestException
$e) {
181 $this->logger
->error(sprintf('PocketImport: Failed to import: %s', $e->getMessage()), ['exception' => $e]);
186 $entries = $response->json();
188 if ($this->producer
) {
189 $this->parseEntriesForProducer($entries['list']);
194 $this->parseEntries($entries['list']);
202 public function getSummary()
205 'skipped' => $this->skippedEntries
,
206 'imported' => $this->importedEntries
,
211 * Set the Guzzle client.
213 * @param Client $client
215 public function setClient(Client
$client)
217 $this->client
= $client;
221 * @see https://getpocket.com/developer/docs/v3/retrieve
223 * @param array $entries
225 private function parseEntries(array $entries)
229 foreach ($entries as $pocketEntry) {
230 $entry = $this->parseEntry($pocketEntry);
232 if (null === $entry) {
236 // flush every 20 entries
237 if (($i %
20) === 0) {
239 $this->em
->clear($entry);
248 public function parseEntry(array $pocketEntry)
250 $url = isset($pocketEntry['resolved_url']) && $pocketEntry['resolved_url'] != '' ? $pocketEntry['resolved_url'] : $pocketEntry['given_url'];
252 $existingEntry = $this->em
253 ->getRepository('WallabagCoreBundle:Entry')
254 ->findByUrlAndUserId($url, $this->user
->getId());
256 if (false !== $existingEntry) {
257 ++
$this->skippedEntries
;
262 $entry = new Entry($this->user
);
263 $entry = $this->fetchContent($entry, $url);
265 // jump to next entry in case of problem while getting content
266 if (false === $entry) {
267 ++
$this->skippedEntries
;
272 // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted
273 if ($pocketEntry['status'] == 1 || $this->markAsRead
) {
274 $entry->setArchived(true);
277 // 0 or 1 - 1 If the item is starred
278 if ($pocketEntry['favorite'] == 1) {
279 $entry->setStarred(true);
283 if (isset($pocketEntry['resolved_title']) && $pocketEntry['resolved_title'] != '') {
284 $title = $pocketEntry['resolved_title'];
285 } elseif (isset($pocketEntry['given_title']) && $pocketEntry['given_title'] != '') {
286 $title = $pocketEntry['given_title'];
289 $entry->setTitle($title);
290 $entry->setUrl($url);
292 // 0, 1, or 2 - 1 if the item has images in it - 2 if the item is an image
293 if (isset($pocketEntry['has_image']) && $pocketEntry['has_image'] > 0 && isset($pocketEntry['images'][1])) {
294 $entry->setPreviewPicture($pocketEntry['images'][1]['src']);
297 if (isset($pocketEntry['tags']) && !empty($pocketEntry['tags'])) {
298 $this->contentProxy
->assignTagsToEntry(
300 array_keys($pocketEntry['tags'])
304 $this->em
->persist($entry);
305 ++
$this->importedEntries
;
311 * Faster parse entries for Producer.
312 * We don't care to make check at this time. They'll be done by the consumer.
314 * @param array $entries
316 public function parseEntriesForProducer($entries)
318 foreach ($entries as $pocketEntry) {
319 // set userId for the producer (it won't know which user is connected)
320 $pocketEntry['userId'] = $this->user
->getId();
322 if ($this->markAsRead
) {
323 $pocketEntry['status'] = 1;
326 ++
$this->importedEntries
;
328 $this->producer
->publish(json_encode($pocketEntry));