diff options
Diffstat (limited to 'src/Wallabag/ImportBundle/Import/BrowserImport.php')
-rw-r--r-- | src/Wallabag/ImportBundle/Import/BrowserImport.php | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/src/Wallabag/ImportBundle/Import/BrowserImport.php b/src/Wallabag/ImportBundle/Import/BrowserImport.php new file mode 100644 index 00000000..263a11d5 --- /dev/null +++ b/src/Wallabag/ImportBundle/Import/BrowserImport.php | |||
@@ -0,0 +1,227 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\ImportBundle\Import; | ||
4 | |||
5 | use Psr\Log\LoggerInterface; | ||
6 | use Psr\Log\NullLogger; | ||
7 | use Doctrine\ORM\EntityManager; | ||
8 | use Wallabag\CoreBundle\Entity\Entry; | ||
9 | use Wallabag\UserBundle\Entity\User; | ||
10 | use Wallabag\CoreBundle\Helper\ContentProxy; | ||
11 | |||
12 | class BrowserImport 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 $totalEntries = 0; | ||
21 | protected $filepath; | ||
22 | protected $markAsRead; | ||
23 | private $nbEntries; | ||
24 | |||
25 | public function __construct(EntityManager $em, ContentProxy $contentProxy) | ||
26 | { | ||
27 | $this->em = $em; | ||
28 | $this->logger = new NullLogger(); | ||
29 | $this->contentProxy = $contentProxy; | ||
30 | } | ||
31 | |||
32 | public function setLogger(LoggerInterface $logger) | ||
33 | { | ||
34 | $this->logger = $logger; | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * We define the user in a custom call because on the import command there is no logged in user. | ||
39 | * So we can't retrieve user from the `security.token_storage` service. | ||
40 | * | ||
41 | * @param User $user | ||
42 | * | ||
43 | * @return $this | ||
44 | */ | ||
45 | public function setUser(User $user) | ||
46 | { | ||
47 | $this->user = $user; | ||
48 | |||
49 | return $this; | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * {@inheritdoc} | ||
54 | */ | ||
55 | public function getName() | ||
56 | { | ||
57 | return 'Firefox & Google Chrome'; | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * {@inheritdoc} | ||
62 | */ | ||
63 | public function getUrl() | ||
64 | { | ||
65 | return 'import_browser'; | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * {@inheritdoc} | ||
70 | */ | ||
71 | public function getDescription() | ||
72 | { | ||
73 | return 'import.browser.description'; | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * {@inheritdoc} | ||
78 | */ | ||
79 | public function import() | ||
80 | { | ||
81 | if (!$this->user) { | ||
82 | $this->logger->error('WallabagImport: user is not defined'); | ||
83 | |||
84 | return false; | ||
85 | } | ||
86 | |||
87 | if (!file_exists($this->filepath) || !is_readable($this->filepath)) { | ||
88 | $this->logger->error('WallabagImport: unable to read file', ['filepath' => $this->filepath]); | ||
89 | |||
90 | return false; | ||
91 | } | ||
92 | |||
93 | $data = json_decode(file_get_contents($this->filepath), true); | ||
94 | |||
95 | if (empty($data)) { | ||
96 | return false; | ||
97 | } | ||
98 | |||
99 | $this->nbEntries = 1; | ||
100 | $this->parseEntries($data); | ||
101 | $this->em->flush(); | ||
102 | |||
103 | return true; | ||
104 | } | ||
105 | |||
106 | private function parseEntries($data) | ||
107 | { | ||
108 | foreach ($data as $importedEntry) { | ||
109 | $this->parseEntry($importedEntry); | ||
110 | } | ||
111 | $this->totalEntries += count($data); | ||
112 | } | ||
113 | |||
114 | private function parseEntry($importedEntry) | ||
115 | { | ||
116 | if (!is_array($importedEntry)) { | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | /* Firefox uses guid while Chrome uses id */ | ||
121 | |||
122 | if ((!key_exists('guid', $importedEntry) || (!key_exists('id', $importedEntry))) && is_array(reset($importedEntry))) { | ||
123 | $this->parseEntries($importedEntry); | ||
124 | |||
125 | return; | ||
126 | } | ||
127 | if (key_exists('children', $importedEntry)) { | ||
128 | $this->parseEntries($importedEntry['children']); | ||
129 | |||
130 | return; | ||
131 | } | ||
132 | if (key_exists('uri', $importedEntry) || key_exists('url', $importedEntry)) { | ||
133 | |||
134 | /* Firefox uses uri while Chrome uses url */ | ||
135 | |||
136 | $firefox = key_exists('uri', $importedEntry); | ||
137 | |||
138 | $existingEntry = $this->em | ||
139 | ->getRepository('WallabagCoreBundle:Entry') | ||
140 | ->findByUrlAndUserId(($firefox) ? $importedEntry['uri'] : $importedEntry['url'], $this->user->getId()); | ||
141 | |||
142 | if (false !== $existingEntry) { | ||
143 | ++$this->skippedEntries; | ||
144 | |||
145 | return; | ||
146 | } | ||
147 | |||
148 | if (false === parse_url(($firefox) ? $importedEntry['uri'] : $importedEntry['url']) || false === filter_var(($firefox) ? $importedEntry['uri'] : $importedEntry['url'], FILTER_VALIDATE_URL)) { | ||
149 | $this->logger->warning('Imported URL '.($firefox) ? $importedEntry['uri'] : $importedEntry['url'].' is not valid'); | ||
150 | ++$this->skippedEntries; | ||
151 | |||
152 | return; | ||
153 | } | ||
154 | |||
155 | try { | ||
156 | $entry = $this->contentProxy->updateEntry( | ||
157 | new Entry($this->user), | ||
158 | ($firefox) ? $importedEntry['uri'] : $importedEntry['url'] | ||
159 | ); | ||
160 | } catch (\Exception $e) { | ||
161 | $this->logger->warning('Error while saving '.($firefox) ? $importedEntry['uri'] : $importedEntry['url']); | ||
162 | ++$this->skippedEntries; | ||
163 | |||
164 | return; | ||
165 | } | ||
166 | |||
167 | $entry->setArchived($this->markAsRead); | ||
168 | |||
169 | $this->em->persist($entry); | ||
170 | ++$this->importedEntries; | ||
171 | |||
172 | // flush every 20 entries | ||
173 | if (($this->nbEntries % 20) === 0) { | ||
174 | $this->em->flush(); | ||
175 | $this->em->clear($entry); | ||
176 | } | ||
177 | ++$this->nbEntries; | ||
178 | |||
179 | /* | ||
180 | |||
181 | Maybe not useful. Delete at will. | ||
182 | |||
183 | */ | ||
184 | |||
185 | $this->logger->info($this->nbEntries.' / '.$this->totalEntries); | ||
186 | } | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * Set whether articles must be all marked as read. | ||
191 | * | ||
192 | * @param bool $markAsRead | ||
193 | * | ||
194 | * @return $this | ||
195 | */ | ||
196 | public function setMarkAsRead($markAsRead) | ||
197 | { | ||
198 | $this->markAsRead = $markAsRead; | ||
199 | |||
200 | return $this; | ||
201 | } | ||
202 | |||
203 | /** | ||
204 | * Set file path to the json file. | ||
205 | * | ||
206 | * @param string $filepath | ||
207 | * | ||
208 | * @return $this | ||
209 | */ | ||
210 | public function setFilepath($filepath) | ||
211 | { | ||
212 | $this->filepath = $filepath; | ||
213 | |||
214 | return $this; | ||
215 | } | ||
216 | |||
217 | /** | ||
218 | * {@inheritdoc} | ||
219 | */ | ||
220 | public function getSummary() | ||
221 | { | ||
222 | return [ | ||
223 | 'skipped' => $this->skippedEntries, | ||
224 | 'imported' => $this->importedEntries, | ||
225 | ]; | ||
226 | } | ||
227 | } | ||