aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJeremy Benoist <jeremy.benoist@gmail.com>2016-08-19 23:52:19 +0200
committerJeremy Benoist <jeremy.benoist@gmail.com>2016-08-20 01:17:26 +0200
commit19d9efab32b5c6403e9ee95fb70a2ce56a27f14b (patch)
tree325d2724ae5e5988b2ab77a33cf3f4cfe88c3647
parente408d7e895e784271a55c3a200666034db0af80a (diff)
downloadwallabag-19d9efab32b5c6403e9ee95fb70a2ce56a27f14b.tar.gz
wallabag-19d9efab32b5c6403e9ee95fb70a2ce56a27f14b.tar.zst
wallabag-19d9efab32b5c6403e9ee95fb70a2ce56a27f14b.zip
Avoid breaking import when fetching fail
graby will throw an Exception in some case (like a bad url, a restricted url or a secured pdf). Import doesn't handle that case and break the whole import. With that commit the import isn't stopped but the entry is just skipped. Also, as a bonus, I've added extra test on WallabagImportV2 when the json is empty.
-rw-r--r--src/Wallabag/ImportBundle/Import/AbstractImport.php47
-rw-r--r--src/Wallabag/ImportBundle/Import/PocketImport.php19
-rw-r--r--src/Wallabag/ImportBundle/Import/WallabagImport.php29
-rw-r--r--tests/Wallabag/ImportBundle/Import/PocketImportTest.php51
-rw-r--r--tests/Wallabag/ImportBundle/Import/WallabagV2ImportTest.php40
-rw-r--r--tests/Wallabag/ImportBundle/fixtures/wallabag-v2-empty.json0
6 files changed, 154 insertions, 32 deletions
diff --git a/src/Wallabag/ImportBundle/Import/AbstractImport.php b/src/Wallabag/ImportBundle/Import/AbstractImport.php
new file mode 100644
index 00000000..14377a35
--- /dev/null
+++ b/src/Wallabag/ImportBundle/Import/AbstractImport.php
@@ -0,0 +1,47 @@
1<?php
2
3namespace Wallabag\ImportBundle\Import;
4
5use Psr\Log\LoggerInterface;
6use Psr\Log\NullLogger;
7use Doctrine\ORM\EntityManager;
8use Wallabag\CoreBundle\Helper\ContentProxy;
9use Wallabag\CoreBundle\Entity\Entry;
10
11abstract class AbstractImport implements ImportInterface
12{
13 protected $em;
14 protected $logger;
15 protected $contentProxy;
16
17 public function __construct(EntityManager $em, ContentProxy $contentProxy)
18 {
19 $this->em = $em;
20 $this->logger = new NullLogger();
21 $this->contentProxy = $contentProxy;
22 }
23
24 public function setLogger(LoggerInterface $logger)
25 {
26 $this->logger = $logger;
27 }
28
29 /**
30 * Fetch content from the ContentProxy (using graby).
31 * If it fails return false instead of the updated entry.
32 *
33 * @param Entry $entry Entry to update
34 * @param string $url Url to grab content for
35 * @param array $content An array with AT LEAST keys title, html, url, language & content_type to skip the fetchContent from the url
36 *
37 * @return Entry|false
38 */
39 protected function fetchContent(Entry $entry, $url, array $content = [])
40 {
41 try {
42 return $this->contentProxy->updateEntry($entry, $url, $content);
43 } catch (\Exception $e) {
44 return false;
45 }
46 }
47}
diff --git a/src/Wallabag/ImportBundle/Import/PocketImport.php b/src/Wallabag/ImportBundle/Import/PocketImport.php
index 29361a32..678d016a 100644
--- a/src/Wallabag/ImportBundle/Import/PocketImport.php
+++ b/src/Wallabag/ImportBundle/Import/PocketImport.php
@@ -2,7 +2,6 @@
2 2
3namespace Wallabag\ImportBundle\Import; 3namespace Wallabag\ImportBundle\Import;
4 4
5use Psr\Log\LoggerInterface;
6use Psr\Log\NullLogger; 5use Psr\Log\NullLogger;
7use Doctrine\ORM\EntityManager; 6use Doctrine\ORM\EntityManager;
8use GuzzleHttp\Client; 7use GuzzleHttp\Client;
@@ -12,12 +11,9 @@ use Wallabag\CoreBundle\Entity\Entry;
12use Wallabag\CoreBundle\Helper\ContentProxy; 11use Wallabag\CoreBundle\Helper\ContentProxy;
13use Craue\ConfigBundle\Util\Config; 12use Craue\ConfigBundle\Util\Config;
14 13
15class PocketImport implements ImportInterface 14class PocketImport extends AbstractImport
16{ 15{
17 private $user; 16 private $user;
18 private $em;
19 private $contentProxy;
20 private $logger;
21 private $client; 17 private $client;
22 private $consumerKey; 18 private $consumerKey;
23 private $skippedEntries = 0; 19 private $skippedEntries = 0;
@@ -34,11 +30,6 @@ class PocketImport implements ImportInterface
34 $this->logger = new NullLogger(); 30 $this->logger = new NullLogger();
35 } 31 }
36 32
37 public function setLogger(LoggerInterface $logger)
38 {
39 $this->logger = $logger;
40 }
41
42 /** 33 /**
43 * {@inheritdoc} 34 * {@inheritdoc}
44 */ 35 */
@@ -219,7 +210,13 @@ class PocketImport implements ImportInterface
219 } 210 }
220 211
221 $entry = new Entry($this->user); 212 $entry = new Entry($this->user);
222 $entry = $this->contentProxy->updateEntry($entry, $url); 213 $entry = $this->fetchContent($entry, $url);
214
215 // jump to next entry in case of problem while getting content
216 if (false === $entry) {
217 ++$this->skippedEntries;
218 continue;
219 }
223 220
224 // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted 221 // 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted
225 if ($pocketEntry['status'] == 1 || $this->markAsRead) { 222 if ($pocketEntry['status'] == 1 || $this->markAsRead) {
diff --git a/src/Wallabag/ImportBundle/Import/WallabagImport.php b/src/Wallabag/ImportBundle/Import/WallabagImport.php
index 65803823..a1cc085b 100644
--- a/src/Wallabag/ImportBundle/Import/WallabagImport.php
+++ b/src/Wallabag/ImportBundle/Import/WallabagImport.php
@@ -2,19 +2,12 @@
2 2
3namespace Wallabag\ImportBundle\Import; 3namespace Wallabag\ImportBundle\Import;
4 4
5use Psr\Log\LoggerInterface;
6use Psr\Log\NullLogger;
7use Doctrine\ORM\EntityManager;
8use Wallabag\CoreBundle\Entity\Entry; 5use Wallabag\CoreBundle\Entity\Entry;
9use Wallabag\UserBundle\Entity\User; 6use Wallabag\UserBundle\Entity\User;
10use Wallabag\CoreBundle\Helper\ContentProxy;
11 7
12abstract class WallabagImport implements ImportInterface 8abstract class WallabagImport extends AbstractImport
13{ 9{
14 protected $user; 10 protected $user;
15 protected $em;
16 protected $logger;
17 protected $contentProxy;
18 protected $skippedEntries = 0; 11 protected $skippedEntries = 0;
19 protected $importedEntries = 0; 12 protected $importedEntries = 0;
20 protected $filepath; 13 protected $filepath;
@@ -35,18 +28,6 @@ abstract class WallabagImport implements ImportInterface
35 '', 28 '',
36 ]; 29 ];
37 30
38 public function __construct(EntityManager $em, ContentProxy $contentProxy)
39 {
40 $this->em = $em;
41 $this->logger = new NullLogger();
42 $this->contentProxy = $contentProxy;
43 }
44
45 public function setLogger(LoggerInterface $logger)
46 {
47 $this->logger = $logger;
48 }
49
50 /** 31 /**
51 * We define the user in a custom call because on the import command there is no logged in user. 32 * We define the user in a custom call because on the import command there is no logged in user.
52 * So we can't retrieve user from the `security.token_storage` service. 33 * So we can't retrieve user from the `security.token_storage` service.
@@ -159,12 +140,18 @@ abstract class WallabagImport implements ImportInterface
159 140
160 $data = $this->prepareEntry($importedEntry, $this->markAsRead); 141 $data = $this->prepareEntry($importedEntry, $this->markAsRead);
161 142
162 $entry = $this->contentProxy->updateEntry( 143 $entry = $this->fetchContent(
163 new Entry($this->user), 144 new Entry($this->user),
164 $importedEntry['url'], 145 $importedEntry['url'],
165 $data 146 $data
166 ); 147 );
167 148
149 // jump to next entry in case of problem while getting content
150 if (false === $entry) {
151 ++$this->skippedEntries;
152 continue;
153 }
154
168 if (array_key_exists('tags', $data)) { 155 if (array_key_exists('tags', $data)) {
169 $this->contentProxy->assignTagsToEntry( 156 $this->contentProxy->assignTagsToEntry(
170 $entry, 157 $entry,
diff --git a/tests/Wallabag/ImportBundle/Import/PocketImportTest.php b/tests/Wallabag/ImportBundle/Import/PocketImportTest.php
index 41f9b51f..8534e1c8 100644
--- a/tests/Wallabag/ImportBundle/Import/PocketImportTest.php
+++ b/tests/Wallabag/ImportBundle/Import/PocketImportTest.php
@@ -390,4 +390,55 @@ class PocketImportTest extends \PHPUnit_Framework_TestCase
390 $this->assertContains('PocketImport: Failed to import', $records[0]['message']); 390 $this->assertContains('PocketImport: Failed to import', $records[0]['message']);
391 $this->assertEquals('ERROR', $records[0]['level_name']); 391 $this->assertEquals('ERROR', $records[0]['level_name']);
392 } 392 }
393
394 public function testImportWithExceptionFromGraby()
395 {
396 $client = new Client();
397
398 $mock = new Mock([
399 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
400 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
401 {
402 "status": 1,
403 "list": {
404 "229279689": {
405 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview"
406 }
407 }
408 }
409 ')),
410 ]);
411
412 $client->getEmitter()->attach($mock);
413
414 $pocketImport = $this->getPocketImport();
415
416 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
417 ->disableOriginalConstructor()
418 ->getMock();
419
420 $entryRepo->expects($this->once())
421 ->method('findByUrlAndUserId')
422 ->will($this->onConsecutiveCalls(false, true));
423
424 $this->em
425 ->expects($this->once())
426 ->method('getRepository')
427 ->willReturn($entryRepo);
428
429 $entry = new Entry($this->user);
430
431 $this->contentProxy
432 ->expects($this->once())
433 ->method('updateEntry')
434 ->will($this->throwException(new \Exception()));
435
436 $pocketImport->setClient($client);
437 $pocketImport->authorize('wunderbar_code');
438
439 $res = $pocketImport->import();
440
441 $this->assertTrue($res);
442 $this->assertEquals(['skipped' => 1, 'imported' => 0], $pocketImport->getSummary());
443 }
393} 444}
diff --git a/tests/Wallabag/ImportBundle/Import/WallabagV2ImportTest.php b/tests/Wallabag/ImportBundle/Import/WallabagV2ImportTest.php
index 8ec66b12..4a45e0f0 100644
--- a/tests/Wallabag/ImportBundle/Import/WallabagV2ImportTest.php
+++ b/tests/Wallabag/ImportBundle/Import/WallabagV2ImportTest.php
@@ -143,4 +143,44 @@ class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
143 $this->assertContains('WallabagImport: user is not defined', $records[0]['message']); 143 $this->assertContains('WallabagImport: user is not defined', $records[0]['message']);
144 $this->assertEquals('ERROR', $records[0]['level_name']); 144 $this->assertEquals('ERROR', $records[0]['level_name']);
145 } 145 }
146
147 public function testImportEmptyFile()
148 {
149 $wallabagV2Import = $this->getWallabagV2Import();
150 $wallabagV2Import->setFilepath(__DIR__.'/../fixtures/wallabag-v2-empty.json');
151
152 $res = $wallabagV2Import->import();
153
154 $this->assertFalse($res);
155 $this->assertEquals(['skipped' => 0, 'imported' => 0], $wallabagV2Import->getSummary());
156 }
157
158 public function testImportWithExceptionFromGraby()
159 {
160 $wallabagV2Import = $this->getWallabagV2Import();
161 $wallabagV2Import->setFilepath(__DIR__.'/../fixtures/wallabag-v2.json');
162
163 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
164 ->disableOriginalConstructor()
165 ->getMock();
166
167 $entryRepo->expects($this->exactly(24))
168 ->method('findByUrlAndUserId')
169 ->will($this->onConsecutiveCalls(false, true, false));
170
171 $this->em
172 ->expects($this->any())
173 ->method('getRepository')
174 ->willReturn($entryRepo);
175
176 $this->contentProxy
177 ->expects($this->exactly(2))
178 ->method('updateEntry')
179 ->will($this->throwException(new \Exception()));
180
181 $res = $wallabagV2Import->import();
182
183 $this->assertTrue($res);
184 $this->assertEquals(['skipped' => 24, 'imported' => 0], $wallabagV2Import->getSummary());
185 }
146} 186}
diff --git a/tests/Wallabag/ImportBundle/fixtures/wallabag-v2-empty.json b/tests/Wallabag/ImportBundle/fixtures/wallabag-v2-empty.json
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/Wallabag/ImportBundle/fixtures/wallabag-v2-empty.json