]> git.immae.eu Git - github/wallabag/wallabag.git/blame - src/Wallabag/ImportBundle/Import/BrowserImport.php
Import Firefox & Chrome bookmarks into wallabag
[github/wallabag/wallabag.git] / src / Wallabag / ImportBundle / Import / BrowserImport.php
CommitLineData
ae669126
TC
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
12class 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}