aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag/ImportBundle/Import/PocketImport.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/Wallabag/ImportBundle/Import/PocketImport.php')
-rw-r--r--src/Wallabag/ImportBundle/Import/PocketImport.php154
1 files changed, 86 insertions, 68 deletions
diff --git a/src/Wallabag/ImportBundle/Import/PocketImport.php b/src/Wallabag/ImportBundle/Import/PocketImport.php
index e5c86f07..1710d9d3 100644
--- a/src/Wallabag/ImportBundle/Import/PocketImport.php
+++ b/src/Wallabag/ImportBundle/Import/PocketImport.php
@@ -2,29 +2,39 @@
2 2
3namespace Wallabag\ImportBundle\Import; 3namespace Wallabag\ImportBundle\Import;
4 4
5use Psr\Log\LoggerInterface;
6use Psr\Log\NullLogger;
5use Doctrine\ORM\EntityManager; 7use Doctrine\ORM\EntityManager;
6use GuzzleHttp\Client; 8use GuzzleHttp\Client;
7use Symfony\Component\HttpFoundation\Session\Session; 9use GuzzleHttp\Exception\RequestException;
8use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; 10use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
9use Wallabag\CoreBundle\Entity\Entry; 11use Wallabag\CoreBundle\Entity\Entry;
10use Wallabag\CoreBundle\Entity\Tag; 12use Wallabag\CoreBundle\Entity\Tag;
11use Wallabag\CoreBundle\Tools\Utils; 13use Wallabag\CoreBundle\Helper\ContentProxy;
12 14
13class PocketImport implements ImportInterface 15class PocketImport implements ImportInterface
14{ 16{
15 private $user; 17 private $user;
16 private $session;
17 private $em; 18 private $em;
19 private $contentProxy;
20 private $logger;
18 private $consumerKey; 21 private $consumerKey;
19 private $skippedEntries = 0; 22 private $skippedEntries = 0;
20 private $importedEntries = 0; 23 private $importedEntries = 0;
24 protected $accessToken;
21 25
22 public function __construct(TokenStorageInterface $tokenStorage, Session $session, EntityManager $em, $consumerKey) 26 public function __construct(TokenStorageInterface $tokenStorage, EntityManager $em, ContentProxy $contentProxy, $consumerKey)
23 { 27 {
24 $this->user = $tokenStorage->getToken()->getUser(); 28 $this->user = $tokenStorage->getToken()->getUser();
25 $this->session = $session;
26 $this->em = $em; 29 $this->em = $em;
30 $this->contentProxy = $contentProxy;
27 $this->consumerKey = $consumerKey; 31 $this->consumerKey = $consumerKey;
32 $this->logger = new NullLogger();
33 }
34
35 public function setLogger(LoggerInterface $logger)
36 {
37 $this->logger = $logger;
28 } 38 }
29 39
30 /** 40 /**
@@ -44,9 +54,13 @@ class PocketImport implements ImportInterface
44 } 54 }
45 55
46 /** 56 /**
47 * {@inheritdoc} 57 * Return the oauth url to authenticate the client.
58 *
59 * @param string $redirectUri Redirect url in case of error
60 *
61 * @return string request_token for callback method
48 */ 62 */
49 public function oAuthRequest($redirectUri, $callbackUri) 63 public function getRequestToken($redirectUri)
50 { 64 {
51 $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/oauth/request', 65 $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/oauth/request',
52 [ 66 [
@@ -57,44 +71,59 @@ class PocketImport implements ImportInterface
57 ] 71 ]
58 ); 72 );
59 73
60 $response = $this->client->send($request); 74 try {
61 $values = $response->json(); 75 $response = $this->client->send($request);
76 } catch (RequestException $e) {
77 $this->logger->error(sprintf('PocketImport: Failed to request token: %s', $e->getMessage()), ['exception' => $e]);
62 78
63 // store code in session for callback method 79 return false;
64 $this->session->set('pocketCode', $values['code']); 80 }
65 81
66 return 'https://getpocket.com/auth/authorize?request_token='.$values['code'].'&redirect_uri='.$callbackUri; 82 return $response->json()['code'];
67 } 83 }
68 84
69 /** 85 /**
70 * {@inheritdoc} 86 * Usually called by the previous callback to authorize the client.
87 * Then it return a token that can be used for next requests.
88 *
89 * @param string $code request_token from getRequestToken
90 *
91 * @return bool
71 */ 92 */
72 public function oAuthAuthorize() 93 public function authorize($code)
73 { 94 {
74 $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/oauth/authorize', 95 $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/oauth/authorize',
75 [ 96 [
76 'body' => json_encode([ 97 'body' => json_encode([
77 'consumer_key' => $this->consumerKey, 98 'consumer_key' => $this->consumerKey,
78 'code' => $this->session->get('pocketCode'), 99 'code' => $code,
79 ]), 100 ]),
80 ] 101 ]
81 ); 102 );
82 103
83 $response = $this->client->send($request); 104 try {
105 $response = $this->client->send($request);
106 } catch (RequestException $e) {
107 $this->logger->error(sprintf('PocketImport: Failed to authorize client: %s', $e->getMessage()), ['exception' => $e]);
84 108
85 return $response->json()['access_token']; 109 return false;
110 }
111
112 $this->accessToken = $response->json()['access_token'];
113
114 return true;
86 } 115 }
87 116
88 /** 117 /**
89 * {@inheritdoc} 118 * {@inheritdoc}
90 */ 119 */
91 public function import($accessToken) 120 public function import()
92 { 121 {
93 $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/get', 122 $request = $this->client->createRequest('POST', 'https://getpocket.com/v3/get',
94 [ 123 [
95 'body' => json_encode([ 124 'body' => json_encode([
96 'consumer_key' => $this->consumerKey, 125 'consumer_key' => $this->consumerKey,
97 'access_token' => $accessToken, 126 'access_token' => $this->accessToken,
98 'detailType' => 'complete', 127 'detailType' => 'complete',
99 'state' => 'all', 128 'state' => 'all',
100 'sort' => 'oldest', 129 'sort' => 'oldest',
@@ -102,61 +131,45 @@ class PocketImport implements ImportInterface
102 ] 131 ]
103 ); 132 );
104 133
105 $response = $this->client->send($request); 134 try {
135 $response = $this->client->send($request);
136 } catch (RequestException $e) {
137 $this->logger->error(sprintf('PocketImport: Failed to import: %s', $e->getMessage()), ['exception' => $e]);
138
139 return false;
140 }
141
106 $entries = $response->json(); 142 $entries = $response->json();
107 143
108 $this->parsePocketEntries($entries['list']); 144 $this->parsePocketEntries($entries['list']);
109 145
110 $this->session->getFlashBag()->add( 146 return true;
111 'notice',
112 $this->importedEntries.' entries imported, '.$this->skippedEntries.' already saved.'
113 );
114 } 147 }
115 148
116 /** 149 /**
117 * Set the Guzzle client. 150 * {@inheritdoc}
118 *
119 * @param Client $client
120 */ 151 */
121 public function setClient(Client $client) 152 public function getSummary()
122 { 153 {
123 $this->client = $client; 154 return [
155 'skipped' => $this->skippedEntries,
156 'imported' => $this->importedEntries,
157 ];
124 } 158 }
125 159
126 /** 160 /**
127 * Returns the good title for current entry. 161 * Set the Guzzle client.
128 *
129 * @param $pocketEntry
130 * 162 *
131 * @return string 163 * @param Client $client
132 */ 164 */
133 private function guessTitle($pocketEntry) 165 public function setClient(Client $client)
134 { 166 {
135 if (isset($pocketEntry['resolved_title']) && $pocketEntry['resolved_title'] != '') { 167 $this->client = $client;
136 return $pocketEntry['resolved_title'];
137 } elseif (isset($pocketEntry['given_title']) && $pocketEntry['given_title'] != '') {
138 return $pocketEntry['given_title'];
139 }
140
141 return 'Untitled';
142 } 168 }
143 169
144 /** 170 /**
145 * Returns the good URL for current entry. 171 * @todo move that in a more global place
146 *
147 * @param $pocketEntry
148 *
149 * @return string
150 */ 172 */
151 private function guessURL($pocketEntry)
152 {
153 if (isset($pocketEntry['resolved_url']) && $pocketEntry['resolved_url'] != '') {
154 return $pocketEntry['resolved_url'];
155 }
156
157 return $pocketEntry['given_url'];
158 }
159
160 private function assignTagsToEntry(Entry $entry, $tags) 173 private function assignTagsToEntry(Entry $entry, $tags)
161 { 174 {
162 foreach ($tags as $tag) { 175 foreach ($tags as $tag) {
@@ -177,13 +190,16 @@ class PocketImport implements ImportInterface
177 } 190 }
178 191
179 /** 192 /**
193 * @see https://getpocket.com/developer/docs/v3/retrieve
194 *
180 * @param $entries 195 * @param $entries
181 */ 196 */
182 private function parsePocketEntries($entries) 197 private function parsePocketEntries($entries)
183 { 198 {
184 foreach ($entries as $pocketEntry) { 199 foreach ($entries as $pocketEntry) {
185 $entry = new Entry($this->user); 200 $entry = new Entry($this->user);
186 $url = $this->guessURL($pocketEntry); 201
202 $url = isset($pocketEntry['resolved_url']) && $pocketEntry['resolved_url'] != '' ? $pocketEntry['resolved_url'] : $pocketEntry['given_url'];
187 203
188 $existingEntry = $this->em 204 $existingEntry = $this->em
189 ->getRepository('WallabagCoreBundle:Entry') 205 ->getRepository('WallabagCoreBundle:Entry')
@@ -194,31 +210,33 @@ class PocketImport implements ImportInterface
194 continue; 210 continue;
195 } 211 }
196 212
197 $entry->setUrl($url); 213 $entry = $this->contentProxy->updateEntry($entry, $url);
198 $entry->setDomainName(parse_url($url, PHP_URL_HOST));
199 214
215 // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted
200 if ($pocketEntry['status'] == 1) { 216 if ($pocketEntry['status'] == 1) {
201 $entry->setArchived(true); 217 $entry->setArchived(true);
202 } 218 }
219
220 // 0 or 1 - 1 If the item is favorited
203 if ($pocketEntry['favorite'] == 1) { 221 if ($pocketEntry['favorite'] == 1) {
204 $entry->setStarred(true); 222 $entry->setStarred(true);
205 } 223 }
206 224
207 $entry->setTitle($this->guessTitle($pocketEntry)); 225 $title = 'Untitled';
208 226 if (isset($pocketEntry['resolved_title']) && $pocketEntry['resolved_title'] != '') {
209 if (isset($pocketEntry['excerpt'])) { 227 $title = $pocketEntry['resolved_title'];
210 $entry->setContent($pocketEntry['excerpt']); 228 } elseif (isset($pocketEntry['given_title']) && $pocketEntry['given_title'] != '') {
229 $title = $pocketEntry['given_title'];
211 } 230 }
212 231
213 if (isset($pocketEntry['has_image']) && $pocketEntry['has_image'] > 0) { 232 $entry->setTitle($title);
214 $entry->setPreviewPicture($pocketEntry['image']['src']);
215 }
216 233
217 if (isset($pocketEntry['word_count'])) { 234 // 0, 1, or 2 - 1 if the item has images in it - 2 if the item is an image
218 $entry->setReadingTime(Utils::convertWordsToMinutes($pocketEntry['word_count'])); 235 if (isset($pocketEntry['has_image']) && $pocketEntry['has_image'] > 0 && isset($pocketEntry['images'][1])) {
236 $entry->setPreviewPicture($pocketEntry['images'][1]['src']);
219 } 237 }
220 238
221 if (!empty($pocketEntry['tags'])) { 239 if (isset($pocketEntry['tags']) && !empty($pocketEntry['tags'])) {
222 $this->assignTagsToEntry($entry, $pocketEntry['tags']); 240 $this->assignTagsToEntry($entry, $pocketEntry['tags']);
223 } 241 }
224 242