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 c6fcb355f..f9f4a9586 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 c0e82b59b..c1196be58 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 6f262209a..99bd40799 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 7b9810697..5ffeab076 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 99fcc3781..fa2c3ca93 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 dd82e7f59..b24cfa267 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 d3ce30c9e..f6aa245e9 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 d040daea6..596c764ff 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 a51ed1f27..bf0da0222 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 de21f0b35..928589cbc 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 d4b7a7a22..723b1edb0 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 20ecc6e18..537dffc20 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 000000000..3b54a72e8
--- /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 000000000..263a11d52
--- /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 f03404ae5..d8be5c28f 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 000000000..bfc74e9de
--- /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 aebbfa208..6ea5e0f42 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 000000000..8016227c4
--- /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 000000000..8b78b8a44
--- /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
+}