From ae669126e718ede5dbf76929215d8514cd960976 Mon Sep 17 00:00:00 2001
From: Thomas Citharel
Date: Tue, 12 Jul 2016 13:51:05 +0200
Subject: [PATCH] Import Firefox & Chrome bookmarks into wallabag
---
.../Resources/translations/messages.da.yml | 4 +
.../Resources/translations/messages.de.yml | 4 +
.../Resources/translations/messages.en.yml | 4 +
.../Resources/translations/messages.es.yml | 4 +
.../Resources/translations/messages.fa.yml | 4 +
.../Resources/translations/messages.fr.yml | 6 +-
.../Resources/translations/messages.it.yml | 4 +
.../Resources/translations/messages.oc.yml | 4 +
.../Resources/translations/messages.pl.yml | 4 +
.../Resources/translations/messages.ro.yml | 4 +
.../Resources/translations/messages.tr.yml | 4 +
.../ImportBundle/Command/ImportCommand.php | 19 +-
.../Controller/BrowserController.php | 91 +++++++
.../ImportBundle/Import/BrowserImport.php | 227 ++++++++++++++++++
.../Resources/config/services.yml | 10 +
.../Resources/views/Browser/index.html.twig | 43 ++++
.../Resources/views/Import/index.html.twig | 2 +-
.../Controller/BrowserControllerTest.php | 94 ++++++++
.../Wallabag/ImportBundle/fixtures/Bookmarks | 61 +++++
19 files changed, 586 insertions(+), 7 deletions(-)
create mode 100644 src/Wallabag/ImportBundle/Controller/BrowserController.php
create mode 100644 src/Wallabag/ImportBundle/Import/BrowserImport.php
create mode 100644 src/Wallabag/ImportBundle/Resources/views/Browser/index.html.twig
create mode 100644 tests/Wallabag/ImportBundle/Controller/BrowserControllerTest.php
create mode 100644 tests/Wallabag/ImportBundle/fixtures/Bookmarks
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
index c6fcb355..f9f4a958 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
@@ -349,6 +349,10 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # browser:
+ # page_title: 'Import > Browser'
+ # description: "This importer will import all your Firefox or Chrome bookmarks. For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file.
For Chrome, the location of the file depends on your operating system : - On Linux, go into the
~/.config/chromium/Default/
directory - On Windows, it should be at
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- On OS X, it should be at ...
Once you got there, copy the Bookmarks file someplace you'll find.
Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.
"
+ # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
developer:
# page_title: 'Developer'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
index c0e82b59..c1196be5 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
@@ -349,6 +349,10 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # browser:
+ # page_title: 'Import > Browser'
+ # description: "This importer will import all your Firefox or Chrome bookmarks. For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file.
For Chrome, the location of the file depends on your operating system : - On Linux, go into the
~/.config/chromium/Default/
directory - On Windows, it should be at
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- On OS X, it should be at ...
Once you got there, copy the Bookmarks file someplace you'll find.
Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly."
+ # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
developer:
page_title: 'Entwickler'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
index 6f262209..99bd4079 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
@@ -349,6 +349,10 @@ import:
how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ browser:
+ page_title: 'Import > Browser'
+ description: "This importer will import all your Firefox or Chrome bookmarks. For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file.
For Chrome, the location of the file depends on your operating system : - On Linux, go into the
~/.config/chromium/Default/
directory - On Windows, it should be at
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- On OS X, it should be at ...
Once you got there, copy the Bookmarks file someplace you'll find.
Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly."
+ how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
developer:
page_title: 'Developer'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
index 7b981069..5ffeab07 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
@@ -349,6 +349,10 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # browser:
+ # page_title: 'Import > Browser'
+ # description: "This importer will import all your Firefox or Chrome bookmarks. For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file.
For Chrome, the location of the file depends on your operating system : - On Linux, go into the
~/.config/chromium/Default/
directory - On Windows, it should be at
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- On OS X, it should be at ...
Once you got there, copy the Bookmarks file someplace you'll find.
Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly."
+ # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
developer:
page_title: 'Promotor'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
index 99fcc378..fa2c3ca9 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
@@ -349,6 +349,10 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # browser:
+ # page_title: 'Import > Browser'
+ # description: "This importer will import all your Firefox or Chrome bookmarks. For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file.
For Chrome, the location of the file depends on your operating system : - On Linux, go into the
~/.config/chromium/Default/
directory - On Windows, it should be at
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- On OS X, it should be at ...
Once you got there, copy the Bookmarks file someplace you'll find.
Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly."
+ # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
developer:
# page_title: 'Developer'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index dd82e7f5..b24cfa26 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -349,6 +349,10 @@ import:
how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l'importer."
worker:
enabled: "Les imports sont asynchrones. Une fois l'import commencé un worker externe traitera les messages un par un. Le service activé est :"
+ browser:
+ page_title: 'Import > Navigateur'
+ description: "Cet outil va vous permettre d'importer tous vos marques-pages de Firefox ou de Google Chrome/Chromium. Pour Firefox, ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde... ». Vous allez récupérer un fichier .json.
Pour Google Chrome, la situation du fichier dépend de votre système d'exploitation : - Sur GNU/Linux, allez dans le répertoire
~/.config/google-chrome/Default/
- Sous Windows, il devrait se trouver Ã
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- Sur OS X, il devrait se trouver à ...
Une fois que vous y êtes, copiez le fichier Bookmarks à un endroit où vous le retrouverez.
Notez que si vous utilisez Chromium à la place de Chrome, vous devez corriger les chemins en conséquence."
+ how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour l'importer. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
developer:
page_title: 'Développeur'
@@ -432,7 +436,7 @@ flashes:
notice:
failed: "L'import a échoué, veuillez ré-essayer"
failed_on_file: "Erreur lors du traitement de l'import. Vérifier votre fichier."
- summary: "Rapport d'import: %imported% importés, %skipped% déjà présent."
+ summary: "Rapport d'import: %imported% importés, %skipped% déjà présents."
summary_with_queue: "Rapport d'import: %queued% en cours de traitement."
error:
redis_enabled_not_installed: Redis est activé pour les imports asynchrones mais impossible de s'y connecter. Vérifier la configuration de Redis.
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
index d3ce30c9..f6aa245e 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
@@ -348,6 +348,10 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # browser:
+ # page_title: 'Import > Browser'
+ # description: "This importer will import all your Firefox or Chrome bookmarks. For Firefox, go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file.
For Chrome, the location of the file depends on your operating system : - On Linux, go into the .config/chromium/Default/ directory
- On Windows, it should be at %LOCALAPPDATA%\Google\Chrome\User Data\Default
On OS X, it should be at ...
Once you got there, copy the Bookmarks file someplace you'll find.Note that you may have Chromium instead of Chrome and have to correct paths accordingly."
+ # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched"
developer:
page_title: 'Sviluppatori'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
index d040daea..596c764f 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
@@ -349,6 +349,10 @@ import:
how_to: "Mercés de seleccionar vòstre Readability fichièr e de clicar sul boton dejós per lo telecargar e l'importar."
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # browser:
+ # page_title: 'Import > Browser'
+ # description: "This importer will import all your Firefox or Chrome bookmarks. For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file.
For Chrome, the location of the file depends on your operating system : - On Linux, go into the
~/.config/chromium/Default/
directory - On Windows, it should be at
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- On OS X, it should be at ...
Once you got there, copy the Bookmarks file someplace you'll find.
Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly."
+ # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
developer:
page_title: 'Desvolopador'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
index a51ed1f2..bf0da022 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
@@ -349,6 +349,10 @@ import:
how_to: 'Wybierz swój plik eksportu z Readability i kliknij poniższy przycisk, aby go zaÅadowaÄ.'
worker:
enabled: "Import jest wykonywany asynchronicznie. Od momentu rozpoczÄcia importu, zewnÄtrzna usÅuga może zajmowaÄ siÄ na raz tylko jednym zadaniem. BieżÄ
cÄ
usÅugÄ
jest:"
+ # browser:
+ # page_title: 'Import > Browser'
+ # description: "This importer will import all your Firefox or Chrome bookmarks. For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file.
For Chrome, the location of the file depends on your operating system : - On Linux, go into the
~/.config/chromium/Default/
directory - On Windows, it should be at
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- On OS X, it should be at ...
Once you got there, copy the Bookmarks file someplace you'll find.
Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly."
+ # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
developer:
page_title: 'Deweloper'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
index de21f0b3..928589cb 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
@@ -349,6 +349,10 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # browser:
+ # page_title: 'Import > Browser'
+ # description: "This importer will import all your Firefox or Chrome bookmarks. For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file.
For Chrome, the location of the file depends on your operating system : - On Linux, go into the
~/.config/chromium/Default/
directory - On Windows, it should be at
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- On OS X, it should be at ...
Once you got there, copy the Bookmarks file someplace you'll find.
Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly."
+ # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
developer:
# page_title: 'Developer'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
index d4b7a7a2..723b1edb 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
@@ -349,6 +349,10 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # browser:
+ # page_title: 'Import > Browser'
+ # description: "This importer will import all your Firefox or Chrome bookmarks. For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file.
For Chrome, the location of the file depends on your operating system : - On Linux, go into the
~/.config/chromium/Default/
directory - On Windows, it should be at
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- On OS X, it should be at ...
Once you got there, copy the Bookmarks file someplace you'll find.
Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly."
+ # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
developer:
# page_title: 'Developer'
diff --git a/src/Wallabag/ImportBundle/Command/ImportCommand.php b/src/Wallabag/ImportBundle/Command/ImportCommand.php
index 20ecc6e1..537dffc2 100644
--- a/src/Wallabag/ImportBundle/Command/ImportCommand.php
+++ b/src/Wallabag/ImportBundle/Command/ImportCommand.php
@@ -17,7 +17,7 @@ class ImportCommand extends ContainerAwareCommand
->setDescription('Import entries from a JSON export from a wallabag v1 instance')
->addArgument('userId', InputArgument::REQUIRED, 'User ID to populate')
->addArgument('filepath', InputArgument::REQUIRED, 'Path to the JSON file')
- ->addOption('importer', null, InputArgument::OPTIONAL, 'The importer to use: v1 or v2', 'v1')
+ ->addOption('importer', null, InputArgument::OPTIONAL, 'The importer to use: wallabag v1, v2 or browser', 'v1')
->addOption('markAsRead', null, InputArgument::OPTIONAL, 'Mark all entries as read', false)
;
}
@@ -40,10 +40,19 @@ class ImportCommand extends ContainerAwareCommand
throw new Exception(sprintf('User with id "%s" not found', $input->getArgument('userId')));
}
- $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v1.import');
-
- if ('v2' === $input->getOption('importer')) {
- $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v2.import');
+ switch ($input->getOption('importer')) {
+ case 'v2':
+ $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v2.import');
+ break;
+ case 'v1':
+ $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v1.import');
+ break;
+ case 'browser':
+ $wallabag = $this->getContainer()->get('wallabag_import.browser.import');
+ break;
+ default:
+ $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v1.import');
+ break;
}
$wallabag->setMarkAsRead($input->getOption('markAsRead'));
diff --git a/src/Wallabag/ImportBundle/Controller/BrowserController.php b/src/Wallabag/ImportBundle/Controller/BrowserController.php
new file mode 100644
index 00000000..3b54a72e
--- /dev/null
+++ b/src/Wallabag/ImportBundle/Controller/BrowserController.php
@@ -0,0 +1,91 @@
+get('wallabag_import.browser.import');
+ }
+
+ /**
+ * Return the template used for the form.
+ *
+ * @return string
+ */
+ protected function getImportTemplate()
+ {
+ return 'WallabagImportBundle:Browser:index.html.twig';
+ }
+
+ /**
+ * @Route("/browser", name="import_browser")
+ *
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function indexAction(Request $request)
+ {
+ $form = $this->createForm(UploadImportType::class);
+ $form->handleRequest($request);
+
+ $wallabag = $this->getImportService();
+
+ if ($form->isValid()) {
+ $file = $form->get('file')->getData();
+ $markAsRead = $form->get('mark_as_read')->getData();
+ $name = $this->getUser()->getId().'.json';
+
+ if (in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes')) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) {
+ $res = $wallabag
+ ->setUser($this->getUser())
+ ->setFilepath($this->getParameter('wallabag_import.resource_dir').'/'.$name)
+ ->setMarkAsRead($markAsRead)
+ ->import();
+
+ $message = 'flashes.import.notice.failed';
+
+ if (true === $res) {
+ $summary = $wallabag->getSummary();
+ // TODO : Pluralize these messages
+ $message = $this->get('translator')->trans('flashes.import.notice.summary', [
+ '%imported%' => $summary['imported'],
+ '%skipped%' => $summary['skipped'],
+ ]);
+
+ unlink($this->getParameter('wallabag_import.resource_dir').'/'.$name);
+ }
+
+ $this->get('session')->getFlashBag()->add(
+ 'notice',
+ $message
+ );
+
+ return $this->redirect($this->generateUrl('homepage'));
+ } else {
+ $this->get('session')->getFlashBag()->add(
+ 'notice',
+ 'flashes.import.notice.failed_on_file'
+ );
+ }
+ }
+
+ return $this->render($this->getImportTemplate(), [
+ 'form' => $form->createView(),
+ 'import' => $wallabag,
+ ]);
+ }
+}
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 @@
+em = $em;
+ $this->logger = new NullLogger();
+ $this->contentProxy = $contentProxy;
+ }
+
+ public function setLogger(LoggerInterface $logger)
+ {
+ $this->logger = $logger;
+ }
+
+ /**
+ * We define the user in a custom call because on the import command there is no logged in user.
+ * So we can't retrieve user from the `security.token_storage` service.
+ *
+ * @param User $user
+ *
+ * @return $this
+ */
+ public function setUser(User $user)
+ {
+ $this->user = $user;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'Firefox & Google Chrome';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getUrl()
+ {
+ return 'import_browser';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDescription()
+ {
+ return 'import.browser.description';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function import()
+ {
+ if (!$this->user) {
+ $this->logger->error('WallabagImport: user is not defined');
+
+ return false;
+ }
+
+ if (!file_exists($this->filepath) || !is_readable($this->filepath)) {
+ $this->logger->error('WallabagImport: unable to read file', ['filepath' => $this->filepath]);
+
+ return false;
+ }
+
+ $data = json_decode(file_get_contents($this->filepath), true);
+
+ if (empty($data)) {
+ return false;
+ }
+
+ $this->nbEntries = 1;
+ $this->parseEntries($data);
+ $this->em->flush();
+
+ return true;
+ }
+
+ private function parseEntries($data)
+ {
+ foreach ($data as $importedEntry) {
+ $this->parseEntry($importedEntry);
+ }
+ $this->totalEntries += count($data);
+ }
+
+ private function parseEntry($importedEntry)
+ {
+ if (!is_array($importedEntry)) {
+ return;
+ }
+
+ /* Firefox uses guid while Chrome uses id */
+
+ if ((!key_exists('guid', $importedEntry) || (!key_exists('id', $importedEntry))) && is_array(reset($importedEntry))) {
+ $this->parseEntries($importedEntry);
+
+ return;
+ }
+ if (key_exists('children', $importedEntry)) {
+ $this->parseEntries($importedEntry['children']);
+
+ return;
+ }
+ if (key_exists('uri', $importedEntry) || key_exists('url', $importedEntry)) {
+
+ /* Firefox uses uri while Chrome uses url */
+
+ $firefox = key_exists('uri', $importedEntry);
+
+ $existingEntry = $this->em
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findByUrlAndUserId(($firefox) ? $importedEntry['uri'] : $importedEntry['url'], $this->user->getId());
+
+ if (false !== $existingEntry) {
+ ++$this->skippedEntries;
+
+ return;
+ }
+
+ if (false === parse_url(($firefox) ? $importedEntry['uri'] : $importedEntry['url']) || false === filter_var(($firefox) ? $importedEntry['uri'] : $importedEntry['url'], FILTER_VALIDATE_URL)) {
+ $this->logger->warning('Imported URL '.($firefox) ? $importedEntry['uri'] : $importedEntry['url'].' is not valid');
+ ++$this->skippedEntries;
+
+ return;
+ }
+
+ try {
+ $entry = $this->contentProxy->updateEntry(
+ new Entry($this->user),
+ ($firefox) ? $importedEntry['uri'] : $importedEntry['url']
+ );
+ } catch (\Exception $e) {
+ $this->logger->warning('Error while saving '.($firefox) ? $importedEntry['uri'] : $importedEntry['url']);
+ ++$this->skippedEntries;
+
+ return;
+ }
+
+ $entry->setArchived($this->markAsRead);
+
+ $this->em->persist($entry);
+ ++$this->importedEntries;
+
+ // flush every 20 entries
+ if (($this->nbEntries % 20) === 0) {
+ $this->em->flush();
+ $this->em->clear($entry);
+ }
+ ++$this->nbEntries;
+
+ /*
+
+ Maybe not useful. Delete at will.
+
+ */
+
+ $this->logger->info($this->nbEntries.' / '.$this->totalEntries);
+ }
+ }
+
+ /**
+ * Set whether articles must be all marked as read.
+ *
+ * @param bool $markAsRead
+ *
+ * @return $this
+ */
+ public function setMarkAsRead($markAsRead)
+ {
+ $this->markAsRead = $markAsRead;
+
+ return $this;
+ }
+
+ /**
+ * Set file path to the json file.
+ *
+ * @param string $filepath
+ *
+ * @return $this
+ */
+ public function setFilepath($filepath)
+ {
+ $this->filepath = $filepath;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSummary()
+ {
+ return [
+ 'skipped' => $this->skippedEntries,
+ 'imported' => $this->importedEntries,
+ ];
+ }
+}
diff --git a/src/Wallabag/ImportBundle/Resources/config/services.yml b/src/Wallabag/ImportBundle/Resources/config/services.yml
index f03404ae..d8be5c28 100644
--- a/src/Wallabag/ImportBundle/Resources/config/services.yml
+++ b/src/Wallabag/ImportBundle/Resources/config/services.yml
@@ -56,3 +56,13 @@ services:
- [ setLogger, [ "@logger" ]]
tags:
- { name: wallabag_import.import, alias: readability }
+
+ wallabag_import.browser.import:
+ class: Wallabag\ImportBundle\Import\BrowserImport
+ arguments:
+ - "@doctrine.orm.entity_manager"
+ - "@wallabag_core.content_proxy"
+ calls:
+ - [ setLogger, [ "@logger" ]]
+ tags:
+ - { name: wallabag_import.import, alias: browser }
diff --git a/src/Wallabag/ImportBundle/Resources/views/Browser/index.html.twig b/src/Wallabag/ImportBundle/Resources/views/Browser/index.html.twig
new file mode 100644
index 00000000..bfc74e9d
--- /dev/null
+++ b/src/Wallabag/ImportBundle/Resources/views/Browser/index.html.twig
@@ -0,0 +1,43 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'import.browser.page_title'|trans }}{% endblock %}
+
+{% block content %}
+
+
+
+
+
{{ import.description|trans|raw }}
+
{{ 'import.browser.how_to'|trans }}
+
+
+ {{ form_start(form, {'method': 'POST'}) }}
+ {{ form_errors(form) }}
+
+
+
+
{{ 'import.form.mark_as_read_title'|trans }}
+ {{ form_widget(form.mark_as_read) }}
+ {{ form_label(form.mark_as_read) }}
+
+
+
+ {{ form_widget(form.save, { 'attr': {'class': 'btn waves-effect waves-light'} }) }}
+
+ {{ form_rest(form) }}
+
+
+
+
+
+
+{% endblock %}
diff --git a/src/Wallabag/ImportBundle/Resources/views/Import/index.html.twig b/src/Wallabag/ImportBundle/Resources/views/Import/index.html.twig
index aebbfa20..6ea5e0f4 100644
--- a/src/Wallabag/ImportBundle/Resources/views/Import/index.html.twig
+++ b/src/Wallabag/ImportBundle/Resources/views/Import/index.html.twig
@@ -11,7 +11,7 @@
{% for import in imports %}
{{ import.name }}
- {{ import.description|trans }}
+ {{ import.description|trans|raw }}
{{ 'import.action.import_contents'|trans }}
{% endfor %}
diff --git a/tests/Wallabag/ImportBundle/Controller/BrowserControllerTest.php b/tests/Wallabag/ImportBundle/Controller/BrowserControllerTest.php
new file mode 100644
index 00000000..8016227c
--- /dev/null
+++ b/tests/Wallabag/ImportBundle/Controller/BrowserControllerTest.php
@@ -0,0 +1,94 @@
+logInAs('admin');
+ $client = $this->getClient();
+
+ $crawler = $client->request('GET', '/import/browser');
+
+ $this->assertEquals(200, $client->getResponse()->getStatusCode());
+ $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
+ $this->assertEquals(1, $crawler->filter('input[type=file]')->count());
+ }
+
+ public function testImportWallabagWithFile()
+ {
+ $this->logInAs('admin');
+ $client = $this->getClient();
+
+ $crawler = $client->request('GET', '/import/browser');
+ $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
+
+ $file = new UploadedFile(__DIR__.'/../fixtures/Bookmarks', 'Bookmarks');
+
+ $data = [
+ 'upload_import_file[file]' => $file,
+ ];
+
+ $client->submit($form, $data);
+
+ $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+ $crawler = $client->followRedirect();
+
+ $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
+ $this->assertContains('flashes.import.notice.summary', $body[0]);
+
+ $content = $client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findByUrlAndUserId(
+ 'http://lexpansion.lexpress.fr/high-tech/orange-offre-un-meilleur-reseau-mobile-que-bouygues-et-sfr-free-derriere_1811554.html',
+ $this->getLoggedInUserId()
+ );
+
+ $this->assertNotEmpty($content->getMimetype());
+ $this->assertNotEmpty($content->getPreviewPicture());
+ $this->assertNotEmpty($content->getLanguage());
+ $this->assertEquals(0, count($content->getTags()));
+
+ $content = $client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findByUrlAndUserId(
+ 'http://stackoverflow.com/questions/15017163/parser-for-exported-bookmarks-html-file-of-google-chrome-and-mozilla-in-java',
+ $this->getLoggedInUserId()
+ );
+
+ $this->assertNotEmpty($content->getMimetype());
+ $this->assertNotEmpty($content->getPreviewPicture());
+ $this->assertEmpty($content->getLanguage());
+ }
+
+ public function testImportWallabagWithEmptyFile()
+ {
+ $this->logInAs('admin');
+ $client = $this->getClient();
+
+ $crawler = $client->request('GET', '/import/browser');
+ $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
+
+ $file = new UploadedFile(__DIR__.'/../fixtures/test.txt', 'test.txt');
+
+ $data = [
+ 'upload_import_file[file]' => $file,
+ ];
+
+ $client->submit($form, $data);
+
+ $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+ $crawler = $client->followRedirect();
+
+ $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
+ $this->assertContains('flashes.import.notice.failed', $body[0]);
+ }
+}
diff --git a/tests/Wallabag/ImportBundle/fixtures/Bookmarks b/tests/Wallabag/ImportBundle/fixtures/Bookmarks
new file mode 100644
index 00000000..8b78b8a4
--- /dev/null
+++ b/tests/Wallabag/ImportBundle/fixtures/Bookmarks
@@ -0,0 +1,61 @@
+{
+ "checksum": "ef1e30cddf64cb94c63d7835640165be",
+ "roots": {
+ "bookmark_bar": {
+ "children": [ {
+ "date_added": "13112787540531997",
+ "id": "7",
+ "name": "Terrorisme: les sombres prédictions du directeur de la DGSI",
+ "type": "url",
+ "url": "http://www.lefigaro.fr/actualite-france/2016/07/12/01016-20160712ARTFIG00016-terrorisme-les-sombres-perspectives-de-patrick-calvar-directeur-de-la-dgsi.php"
+ } ],
+ "date_added": "13112787380480144",
+ "date_modified": "13112787542724942",
+ "id": "1",
+ "name": "Bookmarks bar",
+ "type": "folder"
+ },
+ "other": {
+ "children": [ {
+ "date_added": "13112787503900822",
+ "id": "6",
+ "name": "Parser for Exported Bookmarks HTML file of Google Chrome and Mozilla in Java - Stack Overflow",
+ "type": "url",
+ "url": "http://stackoverflow.com/questions/15017163/parser-for-exported-bookmarks-html-file-of-google-chrome-and-mozilla-in-java"
+ }, {
+ "children": [ {
+ "date_added": "13112787564443378",
+ "id": "9",
+ "name": "Orange offre un meilleur réseau mobile que Bouygues et SFR, Free derrière - L'Express L'Expansion",
+ "type": "url",
+ "url": "http://lexpansion.lexpress.fr/high-tech/orange-offre-un-meilleur-reseau-mobile-que-bouygues-et-sfr-free-derriere_1811554.html"
+ } ],
+ "date_added": "13112787556763735",
+ "date_modified": "13112794390493325",
+ "id": "8",
+ "name": "test",
+ "type": "folder"
+ }, {
+ "date_added": "13112794390493325",
+ "id": "12",
+ "name": "JSON Formatter & Validator",
+ "type": "url",
+ "url": "https://jsonformatter.curiousconcept.com/"
+ } ],
+ "date_added": "13112787380480151",
+ "date_modified": "13112794393509988",
+ "id": "2",
+ "name": "Other bookmarks",
+ "type": "folder"
+ },
+ "synced": {
+ "children": [ ],
+ "date_added": "13112787380480155",
+ "date_modified": "0",
+ "id": "3",
+ "name": "Mobile bookmarks",
+ "type": "folder"
+ }
+ },
+ "version": 1
+}
--
2.41.0