aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag/ImportBundle/Import
diff options
context:
space:
mode:
Diffstat (limited to 'src/Wallabag/ImportBundle/Import')
-rw-r--r--src/Wallabag/ImportBundle/Import/PocketImport.php6
-rw-r--r--src/Wallabag/ImportBundle/Import/WallabagImport.php204
-rw-r--r--src/Wallabag/ImportBundle/Import/WallabagV1Import.php174
-rw-r--r--src/Wallabag/ImportBundle/Import/WallabagV2Import.php57
4 files changed, 237 insertions, 204 deletions
diff --git a/src/Wallabag/ImportBundle/Import/PocketImport.php b/src/Wallabag/ImportBundle/Import/PocketImport.php
index 238ddbd1..f598e611 100644
--- a/src/Wallabag/ImportBundle/Import/PocketImport.php
+++ b/src/Wallabag/ImportBundle/Import/PocketImport.php
@@ -60,7 +60,7 @@ class PocketImport implements ImportInterface
60 */ 60 */
61 public function getDescription() 61 public function getDescription()
62 { 62 {
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.'; 63 return 'import.pocket.description';
64 } 64 }
65 65
66 /** 66 /**
@@ -68,7 +68,7 @@ class PocketImport implements ImportInterface
68 * 68 *
69 * @param string $redirectUri Redirect url in case of error 69 * @param string $redirectUri Redirect url in case of error
70 * 70 *
71 * @return string request_token for callback method 71 * @return string|false request_token for callback method
72 */ 72 */
73 public function getRequestToken($redirectUri) 73 public function getRequestToken($redirectUri)
74 { 74 {
@@ -139,7 +139,7 @@ class PocketImport implements ImportInterface
139 /** 139 /**
140 * Get whether articles must be all marked as read. 140 * Get whether articles must be all marked as read.
141 */ 141 */
142 public function getRead() 142 public function getMarkAsRead()
143 { 143 {
144 return $this->markAsRead; 144 return $this->markAsRead;
145 } 145 }
diff --git a/src/Wallabag/ImportBundle/Import/WallabagImport.php b/src/Wallabag/ImportBundle/Import/WallabagImport.php
new file mode 100644
index 00000000..d65bc530
--- /dev/null
+++ b/src/Wallabag/ImportBundle/Import/WallabagImport.php
@@ -0,0 +1,204 @@
1<?php
2
3namespace Wallabag\ImportBundle\Import;
4
5use Psr\Log\LoggerInterface;
6use Psr\Log\NullLogger;
7use Doctrine\ORM\EntityManager;
8use Wallabag\CoreBundle\Entity\Entry;
9use Wallabag\UserBundle\Entity\User;
10use Wallabag\CoreBundle\Helper\ContentProxy;
11
12abstract class WallabagImport implements ImportInterface
13{
14 protected $user;
15 protected $em;
16 protected $logger;
17 protected $contentProxy;
18 protected $skippedEntries = 0;
19 protected $importedEntries = 0;
20 protected $filepath;
21 protected $markAsRead;
22 // untitled in all languages from v1
23 protected $untitled = [
24 'Untitled',
25 'Sans titre',
26 'podle nadpisu',
27 'Sin título',
28 'با عنوان',
29 'per titolo',
30 'Sem título',
31 'Без названия',
32 'po naslovu',
33 'Без назви',
34 'No title found',
35 '',
36 ];
37
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 /**
51 * 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.
53 *
54 * @param User $user
55 */
56 public function setUser(User $user)
57 {
58 $this->user = $user;
59
60 return $this;
61 }
62
63 /**
64 * {@inheritdoc}
65 */
66 abstract public function getName();
67
68 /**
69 * {@inheritdoc}
70 */
71 abstract public function getUrl();
72
73 /**
74 * {@inheritdoc}
75 */
76 abstract public function getDescription();
77
78 /**
79 * {@inheritdoc}
80 */
81 public function import()
82 {
83 if (!$this->user) {
84 $this->logger->error('WallabagImport: user is not defined');
85
86 return false;
87 }
88
89 if (!file_exists($this->filepath) || !is_readable($this->filepath)) {
90 $this->logger->error('WallabagImport: unable to read file', ['filepath' => $this->filepath]);
91
92 return false;
93 }
94
95 $data = json_decode(file_get_contents($this->filepath), true);
96
97 if (empty($data)) {
98 return false;
99 }
100
101 $this->parseEntries($data);
102
103 return true;
104 }
105
106 /**
107 * {@inheritdoc}
108 */
109 public function getSummary()
110 {
111 return [
112 'skipped' => $this->skippedEntries,
113 'imported' => $this->importedEntries,
114 ];
115 }
116
117 /**
118 * Set file path to the json file.
119 *
120 * @param string $filepath
121 */
122 public function setFilepath($filepath)
123 {
124 $this->filepath = $filepath;
125
126 return $this;
127 }
128
129 /**
130 * Set whether articles must be all marked as read.
131 *
132 * @param bool $markAsRead
133 */
134 public function setMarkAsRead($markAsRead)
135 {
136 $this->markAsRead = $markAsRead;
137
138 return $this;
139 }
140
141 /**
142 * Parse and insert all given entries.
143 *
144 * @param $entries
145 */
146 protected function parseEntries($entries)
147 {
148 $i = 1;
149
150 foreach ($entries as $importedEntry) {
151 $existingEntry = $this->em
152 ->getRepository('WallabagCoreBundle:Entry')
153 ->findByUrlAndUserId($importedEntry['url'], $this->user->getId());
154
155 if (false !== $existingEntry) {
156 ++$this->skippedEntries;
157 continue;
158 }
159
160 $data = $this->prepareEntry($importedEntry, $this->markAsRead);
161
162 $entry = $this->contentProxy->updateEntry(
163 new Entry($this->user),
164 $importedEntry['url'],
165 $data
166 );
167
168 if (array_key_exists('tags', $data)) {
169 $this->contentProxy->assignTagsToEntry(
170 $entry,
171 $data['tags']
172 );
173 }
174
175 if (isset($importedEntry['preview_picture'])) {
176 $entry->setPreviewPicture($importedEntry['preview_picture']);
177 }
178
179 $entry->setArchived($data['is_archived']);
180 $entry->setStarred($data['is_starred']);
181
182 $this->em->persist($entry);
183 ++$this->importedEntries;
184
185 // flush every 20 entries
186 if (($i % 20) === 0) {
187 $this->em->flush();
188 }
189 ++$i;
190 }
191
192 $this->em->flush();
193 }
194
195 /**
196 * This should return a cleaned array for a given entry to be given to `updateEntry`.
197 *
198 * @param array $entry Data from the imported file
199 * @param bool $markAsRead Should we mark as read content?
200 *
201 * @return array
202 */
203 abstract protected function prepareEntry($entry = [], $markAsRead = false);
204}
diff --git a/src/Wallabag/ImportBundle/Import/WallabagV1Import.php b/src/Wallabag/ImportBundle/Import/WallabagV1Import.php
index 1d773d3b..6cf3467a 100644
--- a/src/Wallabag/ImportBundle/Import/WallabagV1Import.php
+++ b/src/Wallabag/ImportBundle/Import/WallabagV1Import.php
@@ -2,50 +2,8 @@
2 2
3namespace Wallabag\ImportBundle\Import; 3namespace Wallabag\ImportBundle\Import;
4 4
5use Psr\Log\LoggerInterface; 5class WallabagV1Import extends WallabagImport
6use Psr\Log\NullLogger;
7use Doctrine\ORM\EntityManager;
8use Wallabag\CoreBundle\Entity\Entry;
9use Wallabag\UserBundle\Entity\User;
10use Wallabag\CoreBundle\Tools\Utils;
11use Wallabag\CoreBundle\Helper\ContentProxy;
12
13class WallabagV1Import implements ImportInterface
14{ 6{
15 protected $user;
16 protected $em;
17 protected $logger;
18 protected $contentProxy;
19 protected $skippedEntries = 0;
20 protected $importedEntries = 0;
21 protected $filepath;
22 protected $markAsRead;
23
24 public function __construct(EntityManager $em, ContentProxy $contentProxy)
25 {
26 $this->em = $em;
27 $this->logger = new NullLogger();
28 $this->contentProxy = $contentProxy;
29 }
30
31 public function setLogger(LoggerInterface $logger)
32 {
33 $this->logger = $logger;
34 }
35
36 /**
37 * We define the user in a custom call because on the import command there is no logged in user.
38 * So we can't retrieve user from the `security.token_storage` service.
39 *
40 * @param User $user
41 */
42 public function setUser(User $user)
43 {
44 $this->user = $user;
45
46 return $this;
47 }
48
49 /** 7 /**
50 * {@inheritdoc} 8 * {@inheritdoc}
51 */ 9 */
@@ -67,125 +25,35 @@ class WallabagV1Import implements ImportInterface
67 */ 25 */
68 public function getDescription() 26 public function getDescription()
69 { 27 {
70 return 'This importer will import all your wallabag v1 articles. On your config page, click on "JSON export" in the "Export your wallabag data" section. You will have a "wallabag-export-1-xxxx-xx-xx.json" file.'; 28 return 'import.wallabag_v1.description';
71 }
72
73 /**
74 * {@inheritdoc}
75 */
76 public function import()
77 {
78 if (!$this->user) {
79 $this->logger->error('WallabagImport: user is not defined');
80
81 return false;
82 }
83
84 if (!file_exists($this->filepath) || !is_readable($this->filepath)) {
85 $this->logger->error('WallabagImport: unable to read file', array('filepath' => $this->filepath));
86
87 return false;
88 }
89
90 $data = json_decode(file_get_contents($this->filepath), true);
91
92 if (empty($data)) {
93 return false;
94 }
95
96 $this->parseEntries($data);
97
98 return true;
99 } 29 }
100 30
101 /** 31 /**
102 * {@inheritdoc} 32 * {@inheritdoc}
103 */ 33 */
104 public function getSummary() 34 protected function prepareEntry($entry = [], $markAsRead = false)
105 { 35 {
106 return [ 36 $data = [
107 'skipped' => $this->skippedEntries, 37 'title' => $entry['title'],
108 'imported' => $this->importedEntries, 38 'html' => $entry['content'],
39 'url' => $entry['url'],
40 'content_type' => '',
41 'language' => '',
42 'is_archived' => $entry['is_read'] || $markAsRead,
43 'is_starred' => $entry['is_fav'],
44 'tags' => '',
109 ]; 45 ];
110 }
111
112 /**
113 * Set file path to the json file.
114 *
115 * @param string $filepath
116 */
117 public function setFilepath($filepath)
118 {
119 $this->filepath = $filepath;
120
121 return $this;
122 }
123
124 /**
125 * Set whether articles must be all marked as read.
126 *
127 * @param bool $markAsRead
128 */
129 public function setMarkAsRead($markAsRead)
130 {
131 $this->markAsRead = $markAsRead;
132 46
133 return $this; 47 // force content to be refreshed in case on bad fetch in the v1 installation
134 } 48 if (in_array($entry['title'], $this->untitled)) {
135 49 $data['title'] = '';
136 /** 50 $data['html'] = '';
137 * @param $entries 51 }
138 */
139 protected function parseEntries($entries)
140 {
141 $i = 1;
142
143 //Untitled in all languages from v1. This should never have been translated
144 $untitled = array('Untitled', 'Sans titre', 'podle nadpisu', 'Sin título', 'با عنوان', 'per titolo', 'Sem título', 'Без названия', 'po naslovu', 'Без назви', 'No title found', '');
145
146 foreach ($entries as $importedEntry) {
147 $existingEntry = $this->em
148 ->getRepository('WallabagCoreBundle:Entry')
149 ->findByUrlAndUserId($importedEntry['url'], $this->user->getId());
150
151 if (false !== $existingEntry) {
152 ++$this->skippedEntries;
153 continue;
154 }
155
156 // @see ContentProxy->updateEntry
157 $entry = new Entry($this->user);
158 $entry->setUrl($importedEntry['url']);
159
160 if (in_array($importedEntry['title'], $untitled)) {
161 $entry = $this->contentProxy->updateEntry($entry, $importedEntry['url']);
162 } else {
163 $entry->setContent($importedEntry['content']);
164 $entry->setTitle($importedEntry['title']);
165 $entry->setReadingTime(Utils::getReadingTime($importedEntry['content']));
166 $entry->setDomainName(parse_url($importedEntry['url'], PHP_URL_HOST));
167 }
168
169 if (array_key_exists('tags', $importedEntry) && $importedEntry['tags'] != '') {
170 $this->contentProxy->assignTagsToEntry(
171 $entry,
172 $importedEntry['tags']
173 );
174 }
175
176 $entry->setArchived($importedEntry['is_read'] || $this->markAsRead);
177 $entry->setStarred($importedEntry['is_fav']);
178
179 $this->em->persist($entry);
180 ++$this->importedEntries;
181 52
182 // flush every 20 entries 53 if (array_key_exists('tags', $entry) && $entry['tags'] != '') {
183 if (($i % 20) === 0) { 54 $data['tags'] = $entry['tags'];
184 $this->em->flush();
185 }
186 ++$i;
187 } 55 }
188 56
189 $this->em->flush(); 57 return $data;
190 } 58 }
191} 59}
diff --git a/src/Wallabag/ImportBundle/Import/WallabagV2Import.php b/src/Wallabag/ImportBundle/Import/WallabagV2Import.php
index c4bac561..d0035b63 100644
--- a/src/Wallabag/ImportBundle/Import/WallabagV2Import.php
+++ b/src/Wallabag/ImportBundle/Import/WallabagV2Import.php
@@ -2,9 +2,7 @@
2 2
3namespace Wallabag\ImportBundle\Import; 3namespace Wallabag\ImportBundle\Import;
4 4
5use Wallabag\CoreBundle\Entity\Entry; 5class WallabagV2Import extends WallabagImport
6
7class WallabagV2Import extends WallabagV1Import implements ImportInterface
8{ 6{
9 /** 7 /**
10 * {@inheritdoc} 8 * {@inheritdoc}
@@ -27,55 +25,18 @@ class WallabagV2Import extends WallabagV1Import implements ImportInterface
27 */ 25 */
28 public function getDescription() 26 public function getDescription()
29 { 27 {
30 return 'This importer will import all your wallabag v2 articles. Go to All articles, then, on the export sidebar, click on "JSON". You will have a "All articles.json" file.'; 28 return 'import.wallabag_v2.description';
31 } 29 }
32 30
33 /** 31 /**
34 * @param $entries 32 * {@inheritdoc}
35 */ 33 */
36 protected function parseEntries($entries) 34 protected function prepareEntry($entry = [], $markAsRead = false)
37 { 35 {
38 $i = 1; 36 return [
39 37 'html' => $entry['content'],
40 foreach ($entries as $importedEntry) { 38 'content_type' => $entry['mimetype'],
41 $existingEntry = $this->em 39 'is_archived' => ($entry['is_archived'] || $markAsRead),
42 ->getRepository('WallabagCoreBundle:Entry') 40 ] + $entry;
43 ->findByUrlAndUserId($importedEntry['url'], $this->user->getId());
44
45 if (false !== $existingEntry) {
46 ++$this->skippedEntries;
47 continue;
48 }
49
50 // @see ContentProxy->updateEntry
51 $entry = new Entry($this->user);
52 $entry->setUrl($importedEntry['url']);
53 $entry->setTitle($importedEntry['title']);
54 $entry->setArchived($importedEntry['is_archived'] || $this->markAsRead);
55 $entry->setStarred($importedEntry['is_starred']);
56 $entry->setContent($importedEntry['content']);
57 $entry->setReadingTime($importedEntry['reading_time']);
58 $entry->setDomainName($importedEntry['domain_name']);
59 if (isset($importedEntry['mimetype'])) {
60 $entry->setMimetype($importedEntry['mimetype']);
61 }
62 if (isset($importedEntry['language'])) {
63 $entry->setLanguage($importedEntry['language']);
64 }
65 if (isset($importedEntry['preview_picture'])) {
66 $entry->setPreviewPicture($importedEntry['preview_picture']);
67 }
68
69 $this->em->persist($entry);
70 ++$this->importedEntries;
71
72 // flush every 20 entries
73 if (($i % 20) === 0) {
74 $this->em->flush();
75 }
76 ++$i;
77 }
78
79 $this->em->flush();
80 } 41 }
81} 42}