Merge pull request #2192 from wallabag/import-browser-bookmarks

Import Firefox & Chrome bookmarks into wallabag
This commit is contained in:
Jeremy Benoist 2016-09-26 14:47:02 +02:00 committed by GitHub
commit d6de23a100
35 changed files with 1657 additions and 11 deletions

View file

@ -246,6 +246,16 @@ old_sound_rabbit_mq:
exchange_options:
name: 'wallabag.import.wallabag_v2'
type: topic
import_firefox:
connection: default
exchange_options:
name: 'wallabag.import.firefox'
type: topic
import_chrome:
connection: default
exchange_options:
name: 'wallabag.import.chrome'
type: topic
consumers:
import_pocket:
connection: default
@ -279,3 +289,19 @@ old_sound_rabbit_mq:
queue_options:
name: 'wallabag.import.wallabag_v2'
callback: wallabag_import.consumer.amqp.wallabag_v2
import_firefox:
connection: default
exchange_options:
name: 'wallabag.import.firefox'
type: topic
queue_options:
name: 'wallabag.import.firefox'
callback: wallabag_import.consumer.amqp.firefox
import_chrome:
connection: default
exchange_options:
name: 'wallabag.import.chrome'
type: topic
queue_options:
name: 'wallabag.import.chrome'
callback: wallabag_import.consumer.amqp.chrome

View file

@ -349,6 +349,14 @@ 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:"
# firefox:
# page_title: 'Import > Firefox'
# description: "This importer will import all your Firefox 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."
# 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."
#chrome:
# page_title: 'Import > Chrome'
# description: "This importer will import all your Chrome bookmarks. 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 <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></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>"
# 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'

View file

@ -349,6 +349,14 @@ 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:"
# firefox:
# page_title: 'Import > Firefox'
# description: "This importer will import all your Firefox 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."
# 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."
# chrome:
# page_title: 'Import > Chrome'
# description: "This importer will import all your Chrome bookmarks. 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 <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></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>"
# 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'

View file

@ -349,6 +349,14 @@ 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:"
firefox:
page_title: 'Import > Firefox'
description: "This importer will import all your Firefox 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."
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."
chrome:
page_title: 'Import > Chrome'
description: "This importer will import all your Chrome bookmarks. 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 <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></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>"
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'

View file

@ -349,6 +349,14 @@ 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:"
# firefox:
# page_title: 'Import > Firefox'
# description: "This importer will import all your Firefox 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."
# 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."
# chrome:
# page_title: 'Import > Chrome'
# description: "This importer will import all your Chrome bookmarks. 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 <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></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>"
# 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'

View file

@ -349,6 +349,14 @@ 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:"
# firefox:
# page_title: 'Import > Firefox'
# description: "This importer will import all your Firefox 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."
# 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."
# chrome:
# page_title: 'Import > Chrome'
# description: "This importer will import all your Chrome bookmarks. 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 <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></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>"
# 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'

View file

@ -349,6 +349,14 @@ 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 :"
firefox:
page_title: 'Import > Firefox'
description: "Cet outil va vous permettre d'importer tous vos marques-pages de Firefox. <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>"
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."
chrome:
page_title: 'Import > Chrome'
description: "Cet outil va vous permettre d'importer tous vos marques-pages de Google Chrome/Chromium. 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 dans le fichier <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></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>"
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 +440,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 <u>impossible de s'y connecter</u>. Vérifier la configuration de Redis.

View file

@ -348,6 +348,14 @@ 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:"
# firefox:
# page_title: 'Import > Firefox'
# description: "This importer will import all your Firefox 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."
# 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."
# chrome:
# page_title: 'Import > Chrome'
# description: "This importer will import all your Chrome bookmarks. 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 <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></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>"
# 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'

View file

@ -349,6 +349,14 @@ 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:"
# firefox:
# page_title: 'Import > Firefox'
# description: "This importer will import all your Firefox 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."
# 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."
# chrome:
# page_title: 'Import > Chrome'
# description: "This importer will import all your Chrome bookmarks. 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 <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></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>"
# 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'

View file

@ -349,6 +349,14 @@ 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:"
# firefox:
# page_title: 'Import > Firefox'
# description: "This importer will import all your Firefox 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."
# 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."
# chrome:
# page_title: 'Import > Chrome'
# description: "This importer will import all your Chrome bookmarks. 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 <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></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>"
# 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'

View file

@ -349,6 +349,14 @@ 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:"
# firefox:
# page_title: 'Import > Firefox'
# description: "This importer will import all your Firefox 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."
# 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."
# chrome:
# page_title: 'Import > Chrome'
# description: "This importer will import all your Chrome bookmarks. 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 <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></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>"
# 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'

View file

@ -349,6 +349,14 @@ 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:"
# firefox:
# page_title: 'Import > Firefox'
# description: "This importer will import all your Firefox 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."
# 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."
# chrome:
# page_title: 'Import > Chrome'
# description: "This importer will import all your Chrome bookmarks. 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 <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></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>"
# 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'

View file

@ -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, firefox or chrome', 'v1')
->addOption('markAsRead', null, InputArgument::OPTIONAL, 'Mark all entries as read', false)
;
}
@ -40,10 +40,20 @@ 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 'firefox':
$wallabag = $this->getContainer()->get('wallabag_import.firefox.import');
break;
case 'chrome':
$wallabag = $this->getContainer()->get('wallabag_import.chrome.import');
break;
case 'v1':
default:
$wallabag = $this->getContainer()->get('wallabag_import.wallabag_v1.import');
break;
}
$wallabag->setMarkAsRead($input->getOption('markAsRead'));

View file

@ -0,0 +1,90 @@
<?php
namespace Wallabag\ImportBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Wallabag\ImportBundle\Form\Type\UploadImportType;
abstract class BrowserController extends Controller
{
/**
* Return the service to handle the import.
*
* @return \Wallabag\ImportBundle\Import\ImportInterface
*/
abstract protected function getImportService();
/**
* Return the template used for the form.
*
* @return string
*/
abstract protected function getImportTemplate();
/**
* @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();
$wallabag->setUser($this->getUser());
if ($form->isValid()) {
$file = $form->get('file')->getData();
$markAsRead = $form->get('mark_as_read')->getData();
$name = $this->getUser()->getId().'.json';
if (null !== $file && in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes')) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) {
$res = $wallabag
->setFilepath($this->getParameter('wallabag_import.resource_dir').'/'.$name)
->setMarkAsRead($markAsRead)
->import();
$message = 'flashes.import.notice.failed';
if (true === $res) {
$summary = $wallabag->getSummary();
$message = $this->get('translator')->trans('flashes.import.notice.summary', [
'%imported%' => $summary['imported'],
'%skipped%' => $summary['skipped'],
]);
if (0 < $summary['queued']) {
$message = $this->get('translator')->trans('flashes.import.notice.summary_with_queue', [
'%queued%' => $summary['queued'],
]);
}
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,
]);
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace Wallabag\ImportBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
class ChromeController extends BrowserController
{
/**
* {@inheritdoc}
*/
protected function getImportService()
{
$service = $this->get('wallabag_import.chrome.import');
if ($this->get('craue_config')->get('import_with_rabbitmq')) {
$service->setProducer($this->get('old_sound_rabbit_mq.import_chrome_producer'));
} elseif ($this->get('craue_config')->get('import_with_redis')) {
$service->setProducer($this->get('wallabag_import.producer.redis.chrome'));
}
return $service;
}
/**
* {@inheritdoc}
*/
protected function getImportTemplate()
{
return 'WallabagImportBundle:Chrome:index.html.twig';
}
/**
* @Route("/chrome", name="import_chrome")
*/
public function indexAction(Request $request)
{
return parent::indexAction($request);
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace Wallabag\ImportBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
class FirefoxController extends BrowserController
{
/**
* {@inheritdoc}
*/
protected function getImportService()
{
$service = $this->get('wallabag_import.firefox.import');
if ($this->get('craue_config')->get('import_with_rabbitmq')) {
$service->setProducer($this->get('old_sound_rabbit_mq.import_firefox_producer'));
} elseif ($this->get('craue_config')->get('import_with_redis')) {
$service->setProducer($this->get('wallabag_import.producer.redis.firefox'));
}
return $service;
}
/**
* {@inheritdoc}
*/
protected function getImportTemplate()
{
return 'WallabagImportBundle:Firefox:index.html.twig';
}
/**
* @Route("/firefox", name="import_firefox")
*/
public function indexAction(Request $request)
{
return parent::indexAction($request);
}
}

View file

@ -0,0 +1,205 @@
<?php
namespace Wallabag\ImportBundle\Import;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\UserBundle\Entity\User;
use Wallabag\CoreBundle\Helper\ContentProxy;
abstract class BrowserImport extends AbstractImport
{
protected $filepath;
/**
* {@inheritdoc}
*/
abstract public function getName();
/**
* {@inheritdoc}
*/
abstract public function getUrl();
/**
* {@inheritdoc}
*/
abstract public function getDescription();
/**
* {@inheritdoc}
*/
public function import()
{
if (!$this->user) {
$this->logger->error('Wallabag Browser Import: user is not defined');
return false;
}
if (!file_exists($this->filepath) || !is_readable($this->filepath)) {
$this->logger->error('Wallabag Browser Import: unable to read file', ['filepath' => $this->filepath]);
return false;
}
$data = json_decode(file_get_contents($this->filepath), true);
if (empty($data)) {
return false;
}
if ($this->producer) {
$this->parseEntriesForProducer($data);
return true;
}
$this->parseEntries($data);
return true;
}
/**
* Set file path to the json file.
*
* @param string $filepath
*/
public function setFilepath($filepath)
{
$this->filepath = $filepath;
return $this;
}
/**
* Parse and insert all given entries.
*
* @param $entries
*/
protected function parseEntries($entries)
{
$i = 1;
foreach ($entries as $importedEntry) {
if ((array) $importedEntry !== $importedEntry) {
continue;
}
$entry = $this->parseEntry($importedEntry);
if (null === $entry) {
continue;
}
// flush every 20 entries
if (($i % 20) === 0) {
$this->em->flush();
}
++$i;
}
$this->em->flush();
}
/**
* Parse entries and send them to the queue.
* It should just be a simple loop on all item, no call to the database should be done
* to speedup queuing.
*
* Faster parse entries for Producer.
* We don't care to make check at this time. They'll be done by the consumer.
*
* @param array $entries
*/
protected function parseEntriesForProducer(array $entries)
{
foreach ($entries as $importedEntry) {
if ((array) $importedEntry !== $importedEntry) {
continue;
}
// set userId for the producer (it won't know which user is connected)
$importedEntry['userId'] = $this->user->getId();
if ($this->markAsRead) {
$importedEntry = $this->setEntryAsRead($importedEntry);
}
++$this->queuedEntries;
$this->producer->publish(json_encode($importedEntry));
}
}
/**
* {@inheritdoc}
*/
public function parseEntry(array $importedEntry)
{
if ((!array_key_exists('guid', $importedEntry) || (!array_key_exists('id', $importedEntry))) && is_array(reset($importedEntry))) {
$this->parseEntries($importedEntry);
return;
}
if (array_key_exists('children', $importedEntry)) {
$this->parseEntries($importedEntry['children']);
return;
}
if (!array_key_exists('uri', $importedEntry) && !array_key_exists('url', $importedEntry)) {
return;
}
$url = array_key_exists('uri', $importedEntry) ? $importedEntry['uri'] : $importedEntry['url'];
$existingEntry = $this->em
->getRepository('WallabagCoreBundle:Entry')
->findByUrlAndUserId($url, $this->user->getId());
if (false !== $existingEntry) {
++$this->skippedEntries;
return;
}
$data = $this->prepareEntry($importedEntry);
$entry = new Entry($this->user);
$entry->setUrl($data['url']);
$entry->setTitle($data['title']);
// update entry with content (in case fetching failed, the given entry will be return)
$entry = $this->fetchContent($entry, $data['url'], $data);
if (array_key_exists('tags', $data)) {
$this->contentProxy->assignTagsToEntry(
$entry,
$data['tags']
);
}
$entry->setArchived($data['is_archived']);
if (!empty($data['created_at'])) {
$dt = new \DateTime();
$entry->setCreatedAt($dt->setTimestamp($data['created_at']));
}
$this->em->persist($entry);
++$this->importedEntries;
return $entry;
}
/**
* {@inheritdoc}
*/
protected function setEntryAsRead(array $importedEntry)
{
$importedEntry['is_archived'] = 1;
return $importedEntry;
}
}

View file

@ -0,0 +1,53 @@
<?php
namespace Wallabag\ImportBundle\Import;
class ChromeImport extends BrowserImport
{
protected $filepath;
/**
* {@inheritdoc}
*/
public function getName()
{
return 'Chrome';
}
/**
* {@inheritdoc}
*/
public function getUrl()
{
return 'import_chrome';
}
/**
* {@inheritdoc}
*/
public function getDescription()
{
return 'import.chrome.description';
}
/**
* {@inheritdoc}
*/
protected function prepareEntry(array $entry = [])
{
$data = [
'title' => $entry['name'],
'html' => '',
'url' => $entry['url'],
'is_archived' => $this->markAsRead,
'tags' => '',
'created_at' => substr($entry['date_added'], 0, 10),
];
if (array_key_exists('tags', $entry) && $entry['tags'] != '') {
$data['tags'] = $entry['tags'];
}
return $data;
}
}

View file

@ -0,0 +1,53 @@
<?php
namespace Wallabag\ImportBundle\Import;
class FirefoxImport extends BrowserImport
{
protected $filepath;
/**
* {@inheritdoc}
*/
public function getName()
{
return 'Firefox';
}
/**
* {@inheritdoc}
*/
public function getUrl()
{
return 'import_firefox';
}
/**
* {@inheritdoc}
*/
public function getDescription()
{
return 'import.firefox.description';
}
/**
* {@inheritdoc}
*/
protected function prepareEntry(array $entry = [])
{
$data = [
'title' => $entry['title'],
'html' => '',
'url' => $entry['uri'],
'is_archived' => $this->markAsRead,
'tags' => '',
'created_at' => substr($entry['dateAdded'], 0, 10),
];
if (array_key_exists('tags', $entry) && $entry['tags'] != '') {
$data['tags'] = $entry['tags'];
}
return $data;
}
}

View file

@ -28,3 +28,17 @@ services:
- "@wallabag_user.user_repository"
- "@wallabag_import.wallabag_v2.import"
- "@logger"
wallabag_import.consumer.amqp.firefox:
class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer
arguments:
- "@doctrine.orm.entity_manager"
- "@wallabag_user.user_repository"
- "@wallabag_import.firefox.import"
- "@logger"
wallabag_import.consumer.amqp.chrome:
class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer
arguments:
- "@doctrine.orm.entity_manager"
- "@wallabag_user.user_repository"
- "@wallabag_import.chrome.import"
- "@logger"

View file

@ -79,3 +79,43 @@ services:
- "@wallabag_user.user_repository"
- "@wallabag_import.wallabag_v2.import"
- "@logger"
# firefox
wallabag_import.queue.redis.firefox:
class: Simpleue\Queue\RedisQueue
arguments:
- "@wallabag_core.redis.client"
- "wallabag.import.firefox"
wallabag_import.producer.redis.firefox:
class: Wallabag\ImportBundle\Redis\Producer
arguments:
- "@wallabag_import.queue.redis.firefox"
wallabag_import.consumer.redis.firefox:
class: Wallabag\ImportBundle\Consumer\RedisEntryConsumer
arguments:
- "@doctrine.orm.entity_manager"
- "@wallabag_user.user_repository"
- "@wallabag_import.firefox.import"
- "@logger"
# chrome
wallabag_import.queue.redis.chrome:
class: Simpleue\Queue\RedisQueue
arguments:
- "@wallabag_core.redis.client"
- "wallabag.import.chrome"
wallabag_import.producer.redis.chrome:
class: Wallabag\ImportBundle\Redis\Producer
arguments:
- "@wallabag_import.queue.redis.chrome"
wallabag_import.consumer.redis.chrome:
class: Wallabag\ImportBundle\Consumer\RedisEntryConsumer
arguments:
- "@doctrine.orm.entity_manager"
- "@wallabag_user.user_repository"
- "@wallabag_import.chrome.import"
- "@logger"

View file

@ -56,3 +56,22 @@ services:
- [ setLogger, [ "@logger" ]]
tags:
- { name: wallabag_import.import, alias: readability }
wallabag_import.firefox.import:
class: Wallabag\ImportBundle\Import\FirefoxImport
arguments:
- "@doctrine.orm.entity_manager"
- "@wallabag_core.content_proxy"
calls:
- [ setLogger, [ "@logger" ]]
tags:
- { name: wallabag_import.import, alias: firefox }
wallabag_import.chrome.import:
class: Wallabag\ImportBundle\Import\ChromeImport
arguments:
- "@doctrine.orm.entity_manager"
- "@wallabag_core.content_proxy"
calls:
- [ setLogger, [ "@logger" ]]
tags:
- { name: wallabag_import.import, alias: chrome }

View file

@ -0,0 +1,43 @@
{% extends "WallabagCoreBundle::layout.html.twig" %}
{% block title %}{{ 'import.chrome.page_title'|trans }}{% endblock %}
{% block content %}
<div class="row">
<div class="col s12">
<div class="card-panel settings">
<div class="row">
<blockquote>{{ import.description|trans|raw }}</blockquote>
<p>{{ 'import.chrome.how_to'|trans }}</p>
<div class="col s12">
{{ form_start(form, {'method': 'POST'}) }}
{{ form_errors(form) }}
<div class="row">
<div class="file-field input-field col s12">
{{ form_errors(form.file) }}
<div class="btn">
<span>{{ form.file.vars.label|trans }}</span>
{{ form_widget(form.file) }}
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text">
</div>
</div>
<div class="input-field col s6 with-checkbox">
<h6>{{ 'import.form.mark_as_read_title'|trans }}</h6>
{{ form_widget(form.mark_as_read) }}
{{ form_label(form.mark_as_read) }}
</div>
</div>
{{ form_widget(form.save, { 'attr': {'class': 'btn waves-effect waves-light'} }) }}
{{ form_rest(form) }}
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,43 @@
{% extends "WallabagCoreBundle::layout.html.twig" %}
{% block title %}{{ 'import.firefox.page_title'|trans }}{% endblock %}
{% block content %}
<div class="row">
<div class="col s12">
<div class="card-panel settings">
<div class="row">
<blockquote>{{ import.description|trans|raw }}</blockquote>
<p>{{ 'import.firefox.how_to'|trans }}</p>
<div class="col s12">
{{ form_start(form, {'method': 'POST'}) }}
{{ form_errors(form) }}
<div class="row">
<div class="file-field input-field col s12">
{{ form_errors(form.file) }}
<div class="btn">
<span>{{ form.file.vars.label|trans }}</span>
{{ form_widget(form.file) }}
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text">
</div>
</div>
<div class="input-field col s6 with-checkbox">
<h6>{{ 'import.form.mark_as_read_title'|trans }}</h6>
{{ form_widget(form.mark_as_read) }}
{{ form_label(form.mark_as_read) }}
</div>
</div>
{{ form_widget(form.save, { 'attr': {'class': 'btn waves-effect waves-light'} }) }}
{{ form_rest(form) }}
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -11,7 +11,7 @@
{% for import in imports %}
<li>
<h5>{{ import.name }}</h5>
<blockquote>{{ import.description|trans }}</blockquote>
<blockquote>{{ import.description|trans|raw }}</blockquote>
<p><a class="waves-effect waves-light btn" href="{{ path(import.url) }}">{{ 'import.action.import_contents'|trans }}</a></p>
</li>
{% endfor %}

View file

@ -80,7 +80,7 @@ class WallabagRestControllerTest extends WallabagApiTestCase
public function testGetStarredEntries()
{
$this->client->request('GET', '/api/entries', ['star' => 1, 'sort' => 'updated']);
$this->client->request('GET', '/api/entries', ['starred' => 1, 'sort' => 'updated']);
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());

View file

@ -6,7 +6,6 @@ use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use Wallabag\ImportBundle\Command\ImportCommand;
use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
use M6Web\Component\RedisMock\RedisMockFactory;
class ImportCommandTest extends WallabagCoreTestCase
{

View file

@ -0,0 +1,152 @@
<?php
namespace Tests\Wallabag\ImportBundle\Controller;
use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class ChromeControllerTest extends WallabagCoreTestCase
{
public function testImportChrome()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/import/chrome');
$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 testImportChromeWithRabbitEnabled()
{
$this->logInAs('admin');
$client = $this->getClient();
$client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 1);
$crawler = $client->request('GET', '/import/chrome');
$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());
$client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0);
}
public function testImportChromeBadFile()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/import/chrome');
$form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
$data = [
'upload_import_file[file]' => '',
];
$client->submit($form, $data);
$this->assertEquals(200, $client->getResponse()->getStatusCode());
}
public function testImportChromeWithRedisEnabled()
{
$this->logInAs('admin');
$client = $this->getClient();
$client->getContainer()->get('craue_config')->set('import_with_redis', 1);
$crawler = $client->request('GET', '/import/chrome');
$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());
$form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
$file = new UploadedFile(__DIR__.'/../fixtures/chrome-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]);
$this->assertNotEmpty($client->getContainer()->get('wallabag_core.redis.client')->lpop('wallabag.import.chrome'));
$client->getContainer()->get('craue_config')->set('import_with_redis', 0);
}
public function testImportWallabagWithChromeFile()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/import/chrome');
$form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
$file = new UploadedFile(__DIR__.'/../fixtures/chrome-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://www.usinenouvelle.com/article/la-multiplication-des-chefs-de-projet-est-une-catastrophe-manageriale-majeure-affirme-le-sociologue-francois-dupuy.N307730',
$this->getLoggedInUserId()
);
$this->assertNotEmpty($content->getPreviewPicture());
$this->assertNotEmpty($content->getLanguage());
$this->assertEquals(0, count($content->getTags()));
$createdAt = $content->getCreatedAt();
$this->assertEquals('2011', $createdAt->format('Y'));
$this->assertEquals('07', $createdAt->format('m'));
}
public function testImportWallabagWithEmptyFile()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/import/chrome');
$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]);
}
}

View file

@ -0,0 +1,165 @@
<?php
namespace Tests\Wallabag\ImportBundle\Controller;
use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class FirefoxControllerTest extends WallabagCoreTestCase
{
public function testImportFirefox()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/import/firefox');
$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 testImportFirefoxWithRabbitEnabled()
{
$this->logInAs('admin');
$client = $this->getClient();
$client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 1);
$crawler = $client->request('GET', '/import/firefox');
$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());
$client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0);
}
public function testImportFirefoxBadFile()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/import/firefox');
$form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
$data = [
'upload_import_file[file]' => '',
];
$client->submit($form, $data);
$this->assertEquals(200, $client->getResponse()->getStatusCode());
}
public function testImportFirefoxWithRedisEnabled()
{
$this->logInAs('admin');
$client = $this->getClient();
$client->getContainer()->get('craue_config')->set('import_with_redis', 1);
$crawler = $client->request('GET', '/import/firefox');
$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());
$form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
$file = new UploadedFile(__DIR__.'/../fixtures/firefox-bookmarks.json', '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]);
$this->assertNotEmpty($client->getContainer()->get('wallabag_core.redis.client')->lpop('wallabag.import.firefox'));
$client->getContainer()->get('craue_config')->set('import_with_redis', 0);
}
public function testImportWallabagWithFirefoxFile()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/import/firefox');
$form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
$file = new UploadedFile(__DIR__.'/../fixtures/firefox-bookmarks.json', '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(2, 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());
$createdAt = $content->getCreatedAt();
$this->assertEquals('2013', $createdAt->format('Y'));
$this->assertEquals('12', $createdAt->format('m'));
}
public function testImportWallabagWithEmptyFile()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/import/firefox');
$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]);
}
}

View file

@ -24,6 +24,6 @@ class ImportControllerTest extends WallabagCoreTestCase
$crawler = $client->request('GET', '/import/');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$this->assertEquals(4, $crawler->filter('blockquote')->count());
$this->assertEquals(6, $crawler->filter('blockquote')->count());
}
}

View file

@ -57,7 +57,6 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
$this->checkRedis();
$this->logInAs('admin');
$client = $this->getClient();
$client->getContainer()->get('craue_config')->set('import_with_redis', 1);
$crawler = $client->request('GET', '/import/readability');

View file

@ -0,0 +1,233 @@
<?php
namespace Tests\Wallabag\ImportBundle\Import;
use Wallabag\ImportBundle\Import\ChromeImport;
use Wallabag\UserBundle\Entity\User;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\ImportBundle\Redis\Producer;
use Monolog\Logger;
use Monolog\Handler\TestHandler;
use Simpleue\Queue\RedisQueue;
use M6Web\Component\RedisMock\RedisMockFactory;
class ChromeImportTest extends \PHPUnit_Framework_TestCase
{
protected $user;
protected $em;
protected $logHandler;
protected $contentProxy;
private function getChromeImport($unsetUser = false)
{
$this->user = new User();
$this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock();
$this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
->disableOriginalConstructor()
->getMock();
$wallabag = new ChromeImport($this->em, $this->contentProxy);
$this->logHandler = new TestHandler();
$logger = new Logger('test', [$this->logHandler]);
$wallabag->setLogger($logger);
if (false === $unsetUser) {
$wallabag->setUser($this->user);
}
return $wallabag;
}
public function testInit()
{
$chromeImport = $this->getChromeImport();
$this->assertEquals('Chrome', $chromeImport->getName());
$this->assertNotEmpty($chromeImport->getUrl());
$this->assertEquals('import.chrome.description', $chromeImport->getDescription());
}
public function testImport()
{
$chromeImport = $this->getChromeImport();
$chromeImport->setFilepath(__DIR__.'/../fixtures/chrome-bookmarks');
$entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->exactly(1))
->method('findByUrlAndUserId')
->willReturn(false);
$this->em
->expects($this->any())
->method('getRepository')
->willReturn($entryRepo);
$entry = $this->getMockBuilder('Wallabag\CoreBundle\Entity\Entry')
->disableOriginalConstructor()
->getMock();
$this->contentProxy
->expects($this->exactly(1))
->method('updateEntry')
->willReturn($entry);
$res = $chromeImport->import();
$this->assertTrue($res);
$this->assertEquals(['skipped' => 0, 'imported' => 1, 'queued' => 0], $chromeImport->getSummary());
}
public function testImportAndMarkAllAsRead()
{
$chromeImport = $this->getChromeImport();
$chromeImport->setFilepath(__DIR__.'/../fixtures/chrome-bookmarks');
$entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->exactly(1))
->method('findByUrlAndUserId')
->will($this->onConsecutiveCalls(false, true));
$this->em
->expects($this->any())
->method('getRepository')
->willReturn($entryRepo);
$this->contentProxy
->expects($this->exactly(1))
->method('updateEntry')
->willReturn(new Entry($this->user));
// check that every entry persisted are archived
$this->em
->expects($this->any())
->method('persist')
->with($this->callback(function ($persistedEntry) {
return $persistedEntry->isArchived();
}));
$res = $chromeImport->setMarkAsRead(true)->import();
$this->assertTrue($res);
$this->assertEquals(['skipped' => 0, 'imported' => 1, 'queued' => 0], $chromeImport->getSummary());
}
public function testImportWithRabbit()
{
$chromeImport = $this->getChromeImport();
$chromeImport->setFilepath(__DIR__.'/../fixtures/chrome-bookmarks');
$entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->never())
->method('findByUrlAndUserId');
$this->em
->expects($this->never())
->method('getRepository');
$entry = $this->getMockBuilder('Wallabag\CoreBundle\Entity\Entry')
->disableOriginalConstructor()
->getMock();
$this->contentProxy
->expects($this->never())
->method('updateEntry');
$producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
->disableOriginalConstructor()
->getMock();
$producer
->expects($this->exactly(1))
->method('publish');
$chromeImport->setProducer($producer);
$res = $chromeImport->setMarkAsRead(true)->import();
$this->assertTrue($res);
$this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $chromeImport->getSummary());
}
public function testImportWithRedis()
{
$chromeImport = $this->getChromeImport();
$chromeImport->setFilepath(__DIR__.'/../fixtures/chrome-bookmarks');
$entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->never())
->method('findByUrlAndUserId');
$this->em
->expects($this->never())
->method('getRepository');
$entry = $this->getMockBuilder('Wallabag\CoreBundle\Entity\Entry')
->disableOriginalConstructor()
->getMock();
$this->contentProxy
->expects($this->never())
->method('updateEntry');
$factory = new RedisMockFactory();
$redisMock = $factory->getAdapter('Predis\Client', true);
$queue = new RedisQueue($redisMock, 'chrome');
$producer = new Producer($queue);
$chromeImport->setProducer($producer);
$res = $chromeImport->setMarkAsRead(true)->import();
$this->assertTrue($res);
$this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $chromeImport->getSummary());
$this->assertNotEmpty($redisMock->lpop('chrome'));
}
public function testImportBadFile()
{
$chromeImport = $this->getChromeImport();
$chromeImport->setFilepath(__DIR__.'/../fixtures/wallabag-v1.jsonx');
$res = $chromeImport->import();
$this->assertFalse($res);
$records = $this->logHandler->getRecords();
$this->assertContains('Wallabag Browser Import: unable to read file', $records[0]['message']);
$this->assertEquals('ERROR', $records[0]['level_name']);
}
public function testImportUserNotDefined()
{
$chromeImport = $this->getChromeImport(true);
$chromeImport->setFilepath(__DIR__.'/../fixtures/chrome-bookmarks');
$res = $chromeImport->import();
$this->assertFalse($res);
$records = $this->logHandler->getRecords();
$this->assertContains('Wallabag Browser Import: user is not defined', $records[0]['message']);
$this->assertEquals('ERROR', $records[0]['level_name']);
}
}

View file

@ -0,0 +1,233 @@
<?php
namespace Tests\Wallabag\ImportBundle\Import;
use Wallabag\ImportBundle\Import\FirefoxImport;
use Wallabag\UserBundle\Entity\User;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\ImportBundle\Redis\Producer;
use Monolog\Logger;
use Monolog\Handler\TestHandler;
use Simpleue\Queue\RedisQueue;
use M6Web\Component\RedisMock\RedisMockFactory;
class FirefoxImportTest extends \PHPUnit_Framework_TestCase
{
protected $user;
protected $em;
protected $logHandler;
protected $contentProxy;
private function getFirefoxImport($unsetUser = false)
{
$this->user = new User();
$this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock();
$this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
->disableOriginalConstructor()
->getMock();
$wallabag = new FirefoxImport($this->em, $this->contentProxy);
$this->logHandler = new TestHandler();
$logger = new Logger('test', [$this->logHandler]);
$wallabag->setLogger($logger);
if (false === $unsetUser) {
$wallabag->setUser($this->user);
}
return $wallabag;
}
public function testInit()
{
$firefoxImport = $this->getFirefoxImport();
$this->assertEquals('Firefox', $firefoxImport->getName());
$this->assertNotEmpty($firefoxImport->getUrl());
$this->assertEquals('import.firefox.description', $firefoxImport->getDescription());
}
public function testImport()
{
$firefoxImport = $this->getFirefoxImport();
$firefoxImport->setFilepath(__DIR__.'/../fixtures/firefox-bookmarks.json');
$entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->exactly(2))
->method('findByUrlAndUserId')
->willReturn(false);
$this->em
->expects($this->any())
->method('getRepository')
->willReturn($entryRepo);
$entry = $this->getMockBuilder('Wallabag\CoreBundle\Entity\Entry')
->disableOriginalConstructor()
->getMock();
$this->contentProxy
->expects($this->exactly(2))
->method('updateEntry')
->willReturn($entry);
$res = $firefoxImport->import();
$this->assertTrue($res);
$this->assertEquals(['skipped' => 0, 'imported' => 2, 'queued' => 0], $firefoxImport->getSummary());
}
public function testImportAndMarkAllAsRead()
{
$firefoxImport = $this->getFirefoxImport();
$firefoxImport->setFilepath(__DIR__.'/../fixtures/firefox-bookmarks.json');
$entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->exactly(2))
->method('findByUrlAndUserId')
->will($this->onConsecutiveCalls(false, true));
$this->em
->expects($this->any())
->method('getRepository')
->willReturn($entryRepo);
$this->contentProxy
->expects($this->exactly(1))
->method('updateEntry')
->willReturn(new Entry($this->user));
// check that every entry persisted are archived
$this->em
->expects($this->any())
->method('persist')
->with($this->callback(function ($persistedEntry) {
return $persistedEntry->isArchived();
}));
$res = $firefoxImport->setMarkAsRead(true)->import();
$this->assertTrue($res);
$this->assertEquals(['skipped' => 1, 'imported' => 1, 'queued' => 0], $firefoxImport->getSummary());
}
public function testImportWithRabbit()
{
$firefoxImport = $this->getFirefoxImport();
$firefoxImport->setFilepath(__DIR__.'/../fixtures/firefox-bookmarks.json');
$entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->never())
->method('findByUrlAndUserId');
$this->em
->expects($this->never())
->method('getRepository');
$entry = $this->getMockBuilder('Wallabag\CoreBundle\Entity\Entry')
->disableOriginalConstructor()
->getMock();
$this->contentProxy
->expects($this->never())
->method('updateEntry');
$producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
->disableOriginalConstructor()
->getMock();
$producer
->expects($this->exactly(1))
->method('publish');
$firefoxImport->setProducer($producer);
$res = $firefoxImport->setMarkAsRead(true)->import();
$this->assertTrue($res);
$this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $firefoxImport->getSummary());
}
public function testImportWithRedis()
{
$firefoxImport = $this->getFirefoxImport();
$firefoxImport->setFilepath(__DIR__.'/../fixtures/firefox-bookmarks.json');
$entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->never())
->method('findByUrlAndUserId');
$this->em
->expects($this->never())
->method('getRepository');
$entry = $this->getMockBuilder('Wallabag\CoreBundle\Entity\Entry')
->disableOriginalConstructor()
->getMock();
$this->contentProxy
->expects($this->never())
->method('updateEntry');
$factory = new RedisMockFactory();
$redisMock = $factory->getAdapter('Predis\Client', true);
$queue = new RedisQueue($redisMock, 'firefox');
$producer = new Producer($queue);
$firefoxImport->setProducer($producer);
$res = $firefoxImport->setMarkAsRead(true)->import();
$this->assertTrue($res);
$this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $firefoxImport->getSummary());
$this->assertNotEmpty($redisMock->lpop('firefox'));
}
public function testImportBadFile()
{
$firefoxImport = $this->getFirefoxImport();
$firefoxImport->setFilepath(__DIR__.'/../fixtures/wallabag-v1.jsonx');
$res = $firefoxImport->import();
$this->assertFalse($res);
$records = $this->logHandler->getRecords();
$this->assertContains('Wallabag Browser Import: unable to read file', $records[0]['message']);
$this->assertEquals('ERROR', $records[0]['level_name']);
}
public function testImportUserNotDefined()
{
$firefoxImport = $this->getFirefoxImport(true);
$firefoxImport->setFilepath(__DIR__.'/../fixtures/firefox-bookmarks.json');
$res = $firefoxImport->import();
$this->assertFalse($res);
$records = $this->logHandler->getRecords();
$this->assertContains('Wallabag Browser Import: user is not defined', $records[0]['message']);
$this->assertEquals('ERROR', $records[0]['level_name']);
}
}

View file

@ -0,0 +1,36 @@
{
"checksum": "f3aa0e9c0edad632a246f7e98ec64918",
"roots": {
"bookmark_bar": {
"children": [ {
"date_added": "13118850929335823",
"id": "6",
"name": "\"La multiplication des chefs de projet est une catastrophe managériale majeure\", affirme le sociologue François Dupuy - Ressources humaines",
"type": "url",
"url": "http://www.usinenouvelle.com/article/la-multiplication-des-chefs-de-projet-est-une-catastrophe-manageriale-majeure-affirme-le-sociologue-francois-dupuy.N307730"
} ],
"date_added": "13118829474385693",
"date_modified": "13118850929335823",
"id": "1",
"name": "Barre de favoris",
"type": "folder"
},
"other": {
"children": [ ],
"date_added": "13118829474385701",
"date_modified": "0",
"id": "2",
"name": "Autres favoris",
"type": "folder"
},
"synced": {
"children": [ ],
"date_added": "13118829474385702",
"date_modified": "0",
"id": "3",
"name": "Favoris sur mobile",
"type": "folder"
}
},
"version": 1
}

View file

@ -0,0 +1,63 @@
{
"guid": "root________",
"title": "",
"index": 0,
"dateAdded": 1388166091504000,
"lastModified": 1472897622350000,
"id": 1,
"type": "text/x-moz-place-container",
"root": "placesRoot",
"children": [
{
"guid": "toolbar_____",
"title": "Barre personnelle",
"index": 1,
"dateAdded": 1388166091504000,
"lastModified": 1472897622263000,
"id": 3,
"annos": [
{
"name": "bookmarkProperties/description",
"flags": 0,
"expires": 4,
"value": "Ajoutez des marque-pages dans ce dossier pour les voir apparaître sur votre barre personnelle"
}
],
"type": "text/x-moz-place-container",
"root": "toolbarFolder",
"children": [
{
"guid": "tard77lzbC5H",
"title": "Orange offre un meilleur réseau mobile que Bouygues et SFR, Free derrière - L'Express L'Expansion",
"index": 1,
"dateAdded": 1388166091644000,
"lastModified": 1388166091644000,
"tags":"test,tag",
"id": 4,
"type": "text/x-moz-place",
"uri": "http://lexpansion.lexpress.fr/high-tech/orange-offre-un-meilleur-reseau-mobile-que-bouygues-et-sfr-free-derriere_1811554.html"
},
{
"guid": "E385l9vZ_LVn",
"title": "Parser for Exported Bookmarks HTML file of Google Chrome and Mozilla in Java",
"index": 1,
"dateAdded": 1388166091544000,
"lastModified": 1388166091545000,
"id": 5,
"type": "text/x-moz-place",
"uri": "http://stackoverflow.com/questions/15017163/parser-for-exported-bookmarks-html-file-of-google-chrome-and-mozilla-in-java"
}
]
},
{
"guid": "unfiled_____",
"title": "Autres marque-pages",
"index": 3,
"dateAdded": 1388166091504000,
"lastModified": 1388166091542000,
"id": 6,
"type": "text/x-moz-place-container",
"root": "unfiledBookmarksFolder"
}
]
}