aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorThomas Citharel <tcit@tcit.fr>2016-07-12 13:51:05 +0200
committerJeremy Benoist <jeremy.benoist@gmail.com>2016-09-25 12:28:54 +0200
commitae669126e718ede5dbf76929215d8514cd960976 (patch)
treef7da9fa833014eaec0cc2cfade514df2cc117188
parent9d7dd6b0d2480d3efff5b0ab1461f2ef99bfd57a (diff)
downloadwallabag-ae669126e718ede5dbf76929215d8514cd960976.tar.gz
wallabag-ae669126e718ede5dbf76929215d8514cd960976.tar.zst
wallabag-ae669126e718ede5dbf76929215d8514cd960976.zip
Import Firefox & Chrome bookmarks into wallabag
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.da.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.de.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.en.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.es.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml6
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.it.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml4
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml4
-rw-r--r--src/Wallabag/ImportBundle/Command/ImportCommand.php19
-rw-r--r--src/Wallabag/ImportBundle/Controller/BrowserController.php91
-rw-r--r--src/Wallabag/ImportBundle/Import/BrowserImport.php227
-rw-r--r--src/Wallabag/ImportBundle/Resources/config/services.yml10
-rw-r--r--src/Wallabag/ImportBundle/Resources/views/Browser/index.html.twig43
-rw-r--r--src/Wallabag/ImportBundle/Resources/views/Import/index.html.twig2
-rw-r--r--tests/Wallabag/ImportBundle/Controller/BrowserControllerTest.php94
-rw-r--r--tests/Wallabag/ImportBundle/fixtures/Bookmarks61
19 files changed, 586 insertions, 7 deletions
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:
349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.' 349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
350 worker: 350 worker:
351 # 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:" 351 # 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:"
352 # browser:
353 # page_title: 'Import > Browser'
354 # description: "This importer will import all your Firefox or Chrome bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file. </p>For Chrome, the location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at ...</li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
355 # 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."
352 356
353developer: 357developer:
354 # page_title: 'Developer' 358 # 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:
349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.' 349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
350 worker: 350 worker:
351 # 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:" 351 # 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:"
352 # browser:
353 # page_title: 'Import > Browser'
354 # description: "This importer will import all your Firefox or Chrome bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file. </p>For Chrome, the location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at ...</li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
355 # 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."
352 356
353developer: 357developer:
354 page_title: 'Entwickler' 358 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:
349 how_to: 'Please select your Readability export and click on the below button to upload and import it.' 349 how_to: 'Please select your Readability export and click on the below button to upload and import it.'
350 worker: 350 worker:
351 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:" 351 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:"
352 browser:
353 page_title: 'Import > Browser'
354 description: "This importer will import all your Firefox or Chrome bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file. </p>For Chrome, the location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at ...</li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
355 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."
352 356
353developer: 357developer:
354 page_title: 'Developer' 358 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:
349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.' 349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
350 worker: 350 worker:
351 # 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:" 351 # 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:"
352 # browser:
353 # page_title: 'Import > Browser'
354 # description: "This importer will import all your Firefox or Chrome bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file. </p>For Chrome, the location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at ...</li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
355 # 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."
352 356
353developer: 357developer:
354 page_title: 'Promotor' 358 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:
349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.' 349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
350 worker: 350 worker:
351 # 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:" 351 # 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:"
352 # browser:
353 # page_title: 'Import > Browser'
354 # description: "This importer will import all your Firefox or Chrome bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file. </p>For Chrome, the location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at ...</li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
355 # 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."
352 356
353developer: 357developer:
354 # page_title: 'Developer' 358 # 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:
349 how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l'importer." 349 how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l'importer."
350 worker: 350 worker:
351 enabled: "Les imports sont asynchrones. Une fois l'import commencé un worker externe traitera les messages un par un. Le service activé est :" 351 enabled: "Les imports sont asynchrones. Une fois l'import commencé un worker externe traitera les messages un par un. Le service activé est :"
352 browser:
353 page_title: 'Import > Navigateur'
354 description: "Cet outil va vous permettre d'importer tous vos marques-pages de Firefox ou de Google Chrome/Chromium. <p>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. </p>Pour Google Chrome, la situation du fichier dépend de votre système d'exploitation : <ul><li>Sur GNU/Linux, allez dans le répertoire <code>~/.config/google-chrome/Default/</code></li><li>Sous Windows, il devrait se trouver à <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>Sur OS X, il devrait se trouver à...</li></ul>Une fois que vous y êtes, copiez le fichier Bookmarks à un endroit où vous le retrouverez.<em><br>Notez que si vous utilisez Chromium à la place de Chrome, vous devez corriger les chemins en conséquence.</em></p>"
355 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."
352 356
353developer: 357developer:
354 page_title: 'Développeur' 358 page_title: 'Développeur'
@@ -432,7 +436,7 @@ flashes:
432 notice: 436 notice:
433 failed: "L'import a échoué, veuillez ré-essayer" 437 failed: "L'import a échoué, veuillez ré-essayer"
434 failed_on_file: "Erreur lors du traitement de l'import. Vérifier votre fichier." 438 failed_on_file: "Erreur lors du traitement de l'import. Vérifier votre fichier."
435 summary: "Rapport d'import: %imported% importés, %skipped% déjà présent." 439 summary: "Rapport d'import: %imported% importés, %skipped% déjà présents."
436 summary_with_queue: "Rapport d'import: %queued% en cours de traitement." 440 summary_with_queue: "Rapport d'import: %queued% en cours de traitement."
437 error: 441 error:
438 redis_enabled_not_installed: Redis est activé pour les imports asynchrones mais <u>impossible de s'y connecter</u>. Vérifier la configuration de Redis. 442 redis_enabled_not_installed: Redis est activé pour les imports asynchrones mais <u>impossible de s'y connecter</u>. 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:
348 # how_to: 'Please select your Readability export and click on the below button to upload and import it.' 348 # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
349 worker: 349 worker:
350 # 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:" 350 # 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:"
351 # browser:
352 # page_title: 'Import > Browser'
353 # description: "This importer will import all your Firefox or Chrome bookmarks. <p>For Firefox, go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file. </p>For Chrome, the location of the file depends on your operating system : <ul><li>On Linux, go into the .config/chromium/Default/ directory</li><li>On Windows, it should be at %LOCALAPPDATA%\Google\Chrome\User Data\Default</li>On OS X, it should be at ...</li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em>Note that you may have Chromium instead of Chrome and have to correct paths accordingly.</em></p>"
354 # 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"
351 355
352developer: 356developer:
353 page_title: 'Sviluppatori' 357 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:
349 how_to: "Mercés de seleccionar vòstre Readability fichièr e de clicar sul boton dejós per lo telecargar e l'importar." 349 how_to: "Mercés de seleccionar vòstre Readability fichièr e de clicar sul boton dejós per lo telecargar e l'importar."
350 worker: 350 worker:
351 # 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:" 351 # 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:"
352 # browser:
353 # page_title: 'Import > Browser'
354 # description: "This importer will import all your Firefox or Chrome bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file. </p>For Chrome, the location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at ...</li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
355 # 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."
352 356
353developer: 357developer:
354 page_title: 'Desvolopador' 358 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:
349 how_to: 'Wybierz swój plik eksportu z Readability i kliknij poniższy przycisk, aby go załadować.' 349 how_to: 'Wybierz swój plik eksportu z Readability i kliknij poniższy przycisk, aby go załadować.'
350 worker: 350 worker:
351 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:" 351 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:"
352 # browser:
353 # page_title: 'Import > Browser'
354 # description: "This importer will import all your Firefox or Chrome bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file. </p>For Chrome, the location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at ...</li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
355 # 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."
352 356
353developer: 357developer:
354 page_title: 'Deweloper' 358 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:
349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.' 349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
350 worker: 350 worker:
351 # 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:" 351 # 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:"
352 # browser:
353 # page_title: 'Import > Browser'
354 # description: "This importer will import all your Firefox or Chrome bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file. </p>For Chrome, the location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at ...</li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
355 # 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."
352 356
353developer: 357developer:
354 # page_title: 'Developer' 358 # 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:
349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.' 349 # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
350 worker: 350 worker:
351 # 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:" 351 # 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:"
352 # browser:
353 # page_title: 'Import > Browser'
354 # description: "This importer will import all your Firefox or Chrome bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file. </p>For Chrome, the location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at ...</li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
355 # 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."
352 356
353developer: 357developer:
354 # page_title: 'Developer' 358 # 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
17 ->setDescription('Import entries from a JSON export from a wallabag v1 instance') 17 ->setDescription('Import entries from a JSON export from a wallabag v1 instance')
18 ->addArgument('userId', InputArgument::REQUIRED, 'User ID to populate') 18 ->addArgument('userId', InputArgument::REQUIRED, 'User ID to populate')
19 ->addArgument('filepath', InputArgument::REQUIRED, 'Path to the JSON file') 19 ->addArgument('filepath', InputArgument::REQUIRED, 'Path to the JSON file')
20 ->addOption('importer', null, InputArgument::OPTIONAL, 'The importer to use: v1 or v2', 'v1') 20 ->addOption('importer', null, InputArgument::OPTIONAL, 'The importer to use: wallabag v1, v2 or browser', 'v1')
21 ->addOption('markAsRead', null, InputArgument::OPTIONAL, 'Mark all entries as read', false) 21 ->addOption('markAsRead', null, InputArgument::OPTIONAL, 'Mark all entries as read', false)
22 ; 22 ;
23 } 23 }
@@ -40,10 +40,19 @@ class ImportCommand extends ContainerAwareCommand
40 throw new Exception(sprintf('User with id "%s" not found', $input->getArgument('userId'))); 40 throw new Exception(sprintf('User with id "%s" not found', $input->getArgument('userId')));
41 } 41 }
42 42
43 $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v1.import'); 43 switch ($input->getOption('importer')) {
44 44 case 'v2':
45 if ('v2' === $input->getOption('importer')) { 45 $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v2.import');
46 $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v2.import'); 46 break;
47 case 'v1':
48 $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v1.import');
49 break;
50 case 'browser':
51 $wallabag = $this->getContainer()->get('wallabag_import.browser.import');
52 break;
53 default:
54 $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v1.import');
55 break;
47 } 56 }
48 57
49 $wallabag->setMarkAsRead($input->getOption('markAsRead')); 58 $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 @@
1<?php
2
3namespace Wallabag\ImportBundle\Controller;
4
5use Symfony\Bundle\FrameworkBundle\Controller\Controller;
6use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
7use Symfony\Component\HttpFoundation\Request;
8use Symfony\Component\HttpFoundation\Response;
9use Wallabag\ImportBundle\Form\Type\UploadImportType;
10
11class BrowserController extends Controller
12{
13 /**
14 * Return the service to handle the import.
15 *
16 * @return \Wallabag\ImportBundle\Import\ImportInterface
17 */
18 protected function getImportService()
19 {
20 return $this->get('wallabag_import.browser.import');
21 }
22
23 /**
24 * Return the template used for the form.
25 *
26 * @return string
27 */
28 protected function getImportTemplate()
29 {
30 return 'WallabagImportBundle:Browser:index.html.twig';
31 }
32
33 /**
34 * @Route("/browser", name="import_browser")
35 *
36 * @param Request $request
37 *
38 * @return Response
39 */
40 public function indexAction(Request $request)
41 {
42 $form = $this->createForm(UploadImportType::class);
43 $form->handleRequest($request);
44
45 $wallabag = $this->getImportService();
46
47 if ($form->isValid()) {
48 $file = $form->get('file')->getData();
49 $markAsRead = $form->get('mark_as_read')->getData();
50 $name = $this->getUser()->getId().'.json';
51
52 if (in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes')) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) {
53 $res = $wallabag
54 ->setUser($this->getUser())
55 ->setFilepath($this->getParameter('wallabag_import.resource_dir').'/'.$name)
56 ->setMarkAsRead($markAsRead)
57 ->import();
58
59 $message = 'flashes.import.notice.failed';
60
61 if (true === $res) {
62 $summary = $wallabag->getSummary();
63 // TODO : Pluralize these messages
64 $message = $this->get('translator')->trans('flashes.import.notice.summary', [
65 '%imported%' => $summary['imported'],
66 '%skipped%' => $summary['skipped'],
67 ]);
68
69 unlink($this->getParameter('wallabag_import.resource_dir').'/'.$name);
70 }
71
72 $this->get('session')->getFlashBag()->add(
73 'notice',
74 $message
75 );
76
77 return $this->redirect($this->generateUrl('homepage'));
78 } else {
79 $this->get('session')->getFlashBag()->add(
80 'notice',
81 'flashes.import.notice.failed_on_file'
82 );
83 }
84 }
85
86 return $this->render($this->getImportTemplate(), [
87 'form' => $form->createView(),
88 'import' => $wallabag,
89 ]);
90 }
91}
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
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}
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:
56 - [ setLogger, [ "@logger" ]] 56 - [ setLogger, [ "@logger" ]]
57 tags: 57 tags:
58 - { name: wallabag_import.import, alias: readability } 58 - { name: wallabag_import.import, alias: readability }
59
60 wallabag_import.browser.import:
61 class: Wallabag\ImportBundle\Import\BrowserImport
62 arguments:
63 - "@doctrine.orm.entity_manager"
64 - "@wallabag_core.content_proxy"
65 calls:
66 - [ setLogger, [ "@logger" ]]
67 tags:
68 - { 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 @@
1{% extends "WallabagCoreBundle::layout.html.twig" %}
2
3{% block title %}{{ 'import.browser.page_title'|trans }}{% endblock %}
4
5{% block content %}
6<div class="row">
7 <div class="col s12">
8 <div class="card-panel settings">
9 <div class="row">
10 <blockquote>{{ import.description|trans|raw }}</blockquote>
11 <p>{{ 'import.browser.how_to'|trans }}</p>
12
13 <div class="col s12">
14 {{ form_start(form, {'method': 'POST'}) }}
15 {{ form_errors(form) }}
16 <div class="row">
17 <div class="file-field input-field col s12">
18 {{ form_errors(form.file) }}
19 <div class="btn">
20 <span>{{ form.file.vars.label|trans }}</span>
21 {{ form_widget(form.file) }}
22 </div>
23 <div class="file-path-wrapper">
24 <input class="file-path validate" type="text">
25 </div>
26 </div>
27 <div class="input-field col s6 with-checkbox">
28 <h6>{{ 'import.form.mark_as_read_title'|trans }}</h6>
29 {{ form_widget(form.mark_as_read) }}
30 {{ form_label(form.mark_as_read) }}
31 </div>
32 </div>
33
34 {{ form_widget(form.save, { 'attr': {'class': 'btn waves-effect waves-light'} }) }}
35
36 {{ form_rest(form) }}
37 </form>
38 </div>
39 </div>
40 </div>
41 </div>
42</div>
43{% 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 @@
11 {% for import in imports %} 11 {% for import in imports %}
12 <li> 12 <li>
13 <h5>{{ import.name }}</h5> 13 <h5>{{ import.name }}</h5>
14 <blockquote>{{ import.description|trans }}</blockquote> 14 <blockquote>{{ import.description|trans|raw }}</blockquote>
15 <p><a class="waves-effect waves-light btn" href="{{ path(import.url) }}">{{ 'import.action.import_contents'|trans }}</a></p> 15 <p><a class="waves-effect waves-light btn" href="{{ path(import.url) }}">{{ 'import.action.import_contents'|trans }}</a></p>
16 </li> 16 </li>
17 {% endfor %} 17 {% 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 @@
1<?php
2
3namespace Tests\Wallabag\ImportBundle\Controller;
4
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Symfony\Component\HttpFoundation\File\UploadedFile;
7
8class BrowserControllerTest extends WallabagCoreTestCase
9{
10 public function testImportWallabag()
11 {
12 $this->logInAs('admin');
13 $client = $this->getClient();
14
15 $crawler = $client->request('GET', '/import/browser');
16
17 $this->assertEquals(200, $client->getResponse()->getStatusCode());
18 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
19 $this->assertEquals(1, $crawler->filter('input[type=file]')->count());
20 }
21
22 public function testImportWallabagWithFile()
23 {
24 $this->logInAs('admin');
25 $client = $this->getClient();
26
27 $crawler = $client->request('GET', '/import/browser');
28 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
29
30 $file = new UploadedFile(__DIR__.'/../fixtures/Bookmarks', 'Bookmarks');
31
32 $data = [
33 'upload_import_file[file]' => $file,
34 ];
35
36 $client->submit($form, $data);
37
38 $this->assertEquals(302, $client->getResponse()->getStatusCode());
39
40 $crawler = $client->followRedirect();
41
42 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
43 $this->assertContains('flashes.import.notice.summary', $body[0]);
44
45 $content = $client->getContainer()
46 ->get('doctrine.orm.entity_manager')
47 ->getRepository('WallabagCoreBundle:Entry')
48 ->findByUrlAndUserId(
49 'http://lexpansion.lexpress.fr/high-tech/orange-offre-un-meilleur-reseau-mobile-que-bouygues-et-sfr-free-derriere_1811554.html',
50 $this->getLoggedInUserId()
51 );
52
53 $this->assertNotEmpty($content->getMimetype());
54 $this->assertNotEmpty($content->getPreviewPicture());
55 $this->assertNotEmpty($content->getLanguage());
56 $this->assertEquals(0, count($content->getTags()));
57
58 $content = $client->getContainer()
59 ->get('doctrine.orm.entity_manager')
60 ->getRepository('WallabagCoreBundle:Entry')
61 ->findByUrlAndUserId(
62 'http://stackoverflow.com/questions/15017163/parser-for-exported-bookmarks-html-file-of-google-chrome-and-mozilla-in-java',
63 $this->getLoggedInUserId()
64 );
65
66 $this->assertNotEmpty($content->getMimetype());
67 $this->assertNotEmpty($content->getPreviewPicture());
68 $this->assertEmpty($content->getLanguage());
69 }
70
71 public function testImportWallabagWithEmptyFile()
72 {
73 $this->logInAs('admin');
74 $client = $this->getClient();
75
76 $crawler = $client->request('GET', '/import/browser');
77 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
78
79 $file = new UploadedFile(__DIR__.'/../fixtures/test.txt', 'test.txt');
80
81 $data = [
82 'upload_import_file[file]' => $file,
83 ];
84
85 $client->submit($form, $data);
86
87 $this->assertEquals(302, $client->getResponse()->getStatusCode());
88
89 $crawler = $client->followRedirect();
90
91 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
92 $this->assertContains('flashes.import.notice.failed', $body[0]);
93 }
94}
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 @@
1{
2 "checksum": "ef1e30cddf64cb94c63d7835640165be",
3 "roots": {
4 "bookmark_bar": {
5 "children": [ {
6 "date_added": "13112787540531997",
7 "id": "7",
8 "name": "Terrorisme: les sombres prédictions du directeur de la DGSI",
9 "type": "url",
10 "url": "http://www.lefigaro.fr/actualite-france/2016/07/12/01016-20160712ARTFIG00016-terrorisme-les-sombres-perspectives-de-patrick-calvar-directeur-de-la-dgsi.php"
11 } ],
12 "date_added": "13112787380480144",
13 "date_modified": "13112787542724942",
14 "id": "1",
15 "name": "Bookmarks bar",
16 "type": "folder"
17 },
18 "other": {
19 "children": [ {
20 "date_added": "13112787503900822",
21 "id": "6",
22 "name": "Parser for Exported Bookmarks HTML file of Google Chrome and Mozilla in Java - Stack Overflow",
23 "type": "url",
24 "url": "http://stackoverflow.com/questions/15017163/parser-for-exported-bookmarks-html-file-of-google-chrome-and-mozilla-in-java"
25 }, {
26 "children": [ {
27 "date_added": "13112787564443378",
28 "id": "9",
29 "name": "Orange offre un meilleur réseau mobile que Bouygues et SFR, Free derrière - L'Express L'Expansion",
30 "type": "url",
31 "url": "http://lexpansion.lexpress.fr/high-tech/orange-offre-un-meilleur-reseau-mobile-que-bouygues-et-sfr-free-derriere_1811554.html"
32 } ],
33 "date_added": "13112787556763735",
34 "date_modified": "13112794390493325",
35 "id": "8",
36 "name": "test",
37 "type": "folder"
38 }, {
39 "date_added": "13112794390493325",
40 "id": "12",
41 "name": "JSON Formatter & Validator",
42 "type": "url",
43 "url": "https://jsonformatter.curiousconcept.com/"
44 } ],
45 "date_added": "13112787380480151",
46 "date_modified": "13112794393509988",
47 "id": "2",
48 "name": "Other bookmarks",
49 "type": "folder"
50 },
51 "synced": {
52 "children": [ ],
53 "date_added": "13112787380480155",
54 "date_modified": "0",
55 "id": "3",
56 "name": "Mobile bookmarks",
57 "type": "folder"
58 }
59 },
60 "version": 1
61}