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