Add Pinboard import

This commit is contained in:
Jeremy Benoist
2016-11-04 22:44:31 +01:00
parent b5571b52cc
commit 9ab024b4f5
24 changed files with 596 additions and 2 deletions

View File

@ -17,7 +17,7 @@ class ImportCommand extends ContainerAwareCommand
->setDescription('Import entries from a JSON export')
->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, v2, instapaper, readability, firefox or chrome', 'v1')
->addOption('importer', null, InputArgument::OPTIONAL, 'The importer to use: v1, v2, instapaper, pinboard, readability, firefox or chrome', 'v1')
->addOption('markAsRead', null, InputArgument::OPTIONAL, 'Mark all entries as read', false)
;
}
@ -56,6 +56,9 @@ class ImportCommand extends ContainerAwareCommand
case 'instapaper':
$import = $this->getContainer()->get('wallabag_import.instapaper.import');
break;
case 'pinboard':
$import = $this->getContainer()->get('wallabag_import.pinboard.import');
break;
default:
$import = $this->getContainer()->get('wallabag_import.wallabag_v1.import');
}

View File

@ -17,7 +17,7 @@ class RedisWorkerCommand extends ContainerAwareCommand
$this
->setName('wallabag:import:redis-worker')
->setDescription('Launch Redis worker')
->addArgument('serviceName', InputArgument::REQUIRED, 'Service to use: wallabag_v1, wallabag_v2, pocket, readability, firefox, chrome or instapaper')
->addArgument('serviceName', InputArgument::REQUIRED, 'Service to use: wallabag_v1, wallabag_v2, pocket, readability, pinboard, firefox, chrome or instapaper')
->addOption('maxIterations', '', InputOption::VALUE_OPTIONAL, 'Number of iterations before stoping', false)
;
}

View File

@ -42,6 +42,7 @@ class ImportController extends Controller
+ $this->getTotalMessageInRabbitQueue('firefox')
+ $this->getTotalMessageInRabbitQueue('chrome')
+ $this->getTotalMessageInRabbitQueue('instapaper')
+ $this->getTotalMessageInRabbitQueue('pinboard')
;
} catch (\Exception $e) {
$rabbitNotInstalled = true;
@ -57,6 +58,7 @@ class ImportController extends Controller
+ $redis->llen('wallabag.import.firefox')
+ $redis->llen('wallabag.import.chrome')
+ $redis->llen('wallabag.import.instapaper')
+ $redis->llen('wallabag.import.pinboard')
;
} catch (\Exception $e) {
$redisNotInstalled = true;

View File

@ -0,0 +1,77 @@
<?php
namespace Wallabag\ImportBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use Wallabag\ImportBundle\Form\Type\UploadImportType;
class PinboardController extends Controller
{
/**
* @Route("/pinboard", name="import_pinboard")
*/
public function indexAction(Request $request)
{
$form = $this->createForm(UploadImportType::class);
$form->handleRequest($request);
$pinboard = $this->get('wallabag_import.pinboard.import');
$pinboard->setUser($this->getUser());
if ($this->get('craue_config')->get('import_with_rabbitmq')) {
$pinboard->setProducer($this->get('old_sound_rabbit_mq.import_pinboard_producer'));
} elseif ($this->get('craue_config')->get('import_with_redis')) {
$pinboard->setProducer($this->get('wallabag_import.producer.redis.pinboard'));
}
if ($form->isValid()) {
$file = $form->get('file')->getData();
$markAsRead = $form->get('mark_as_read')->getData();
$name = 'pinboard_'.$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 = $pinboard
->setFilepath($this->getParameter('wallabag_import.resource_dir').'/'.$name)
->setMarkAsRead($markAsRead)
->import();
$message = 'flashes.import.notice.failed';
if (true === $res) {
$summary = $pinboard->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('WallabagImportBundle:Pinboard:index.html.twig', [
'form' => $form->createView(),
'import' => $pinboard,
]);
}
}

View File

@ -0,0 +1,143 @@
<?php
namespace Wallabag\ImportBundle\Import;
use Wallabag\CoreBundle\Entity\Entry;
class PinboardImport extends AbstractImport
{
private $filepath;
/**
* {@inheritdoc}
*/
public function getName()
{
return 'Pinboard';
}
/**
* {@inheritdoc}
*/
public function getUrl()
{
return 'import_pinboard';
}
/**
* {@inheritdoc}
*/
public function getDescription()
{
return 'import.pinboard.description';
}
/**
* Set file path to the json file.
*
* @param string $filepath
*/
public function setFilepath($filepath)
{
$this->filepath = $filepath;
return $this;
}
/**
* {@inheritdoc}
*/
public function import()
{
if (!$this->user) {
$this->logger->error('PinboardImport: user is not defined');
return false;
}
if (!file_exists($this->filepath) || !is_readable($this->filepath)) {
$this->logger->error('PinboardImport: unable to read file', ['filepath' => $this->filepath]);
return false;
}
$data = json_decode(file_get_contents($this->filepath), true);
if (empty($data)) {
$this->logger->error('PinboardImport: no entries in imported file');
return false;
}
if ($this->producer) {
$this->parseEntriesForProducer($data);
return true;
}
$this->parseEntries($data);
return true;
}
/**
* {@inheritdoc}
*/
public function parseEntry(array $importedEntry)
{
$existingEntry = $this->em
->getRepository('WallabagCoreBundle:Entry')
->findByUrlAndUserId($importedEntry['href'], $this->user->getId());
if (false !== $existingEntry) {
++$this->skippedEntries;
return;
}
$data = [
'title' => $importedEntry['description'],
'url' => $importedEntry['href'],
'content_type' => '',
'language' => '',
'is_archived' => ('no' === $importedEntry['toread']) || $this->markAsRead,
'is_starred' => false,
'created_at' => $importedEntry['time'],
'tags' => explode(' ', $importedEntry['tags']),
];
$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 (!empty($data['tags'])) {
$this->contentProxy->assignTagsToEntry(
$entry,
$data['tags'],
$this->em->getUnitOfWork()->getScheduledEntityInsertions()
);
}
$entry->setArchived($data['is_archived']);
$entry->setStarred($data['is_starred']);
$entry->setCreatedAt(new \DateTime($data['created_at']));
$this->em->persist($entry);
++$this->importedEntries;
return $entry;
}
/**
* {@inheritdoc}
*/
protected function setEntryAsRead(array $importedEntry)
{
$importedEntry['toread'] = 'no';
return $importedEntry;
}
}

View File

@ -24,6 +24,14 @@ services:
- "@wallabag_import.instapaper.import"
- "@event_dispatcher"
- "@logger"
wallabag_import.consumer.amqp.pinboard:
class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer
arguments:
- "@doctrine.orm.entity_manager"
- "@wallabag_user.user_repository"
- "@wallabag_import.pinboard.import"
- "@event_dispatcher"
- "@logger"
wallabag_import.consumer.amqp.wallabag_v1:
class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer
arguments:

View File

@ -42,6 +42,27 @@ services:
- "@event_dispatcher"
- "@logger"
# pinboard
wallabag_import.queue.redis.pinboard:
class: Simpleue\Queue\RedisQueue
arguments:
- "@wallabag_core.redis.client"
- "wallabag.import.pinboard"
wallabag_import.producer.redis.pinboard:
class: Wallabag\ImportBundle\Redis\Producer
arguments:
- "@wallabag_import.queue.redis.pinboard"
wallabag_import.consumer.redis.pinboard:
class: Wallabag\ImportBundle\Consumer\RedisEntryConsumer
arguments:
- "@doctrine.orm.entity_manager"
- "@wallabag_user.user_repository"
- "@wallabag_import.pinboard.import"
- "@event_dispatcher"
- "@logger"
# pocket
wallabag_import.queue.redis.pocket:
class: Simpleue\Queue\RedisQueue

View File

@ -71,6 +71,17 @@ services:
tags:
- { name: wallabag_import.import, alias: instapaper }
wallabag_import.pinboard.import:
class: Wallabag\ImportBundle\Import\PinboardImport
arguments:
- "@doctrine.orm.entity_manager"
- "@wallabag_core.content_proxy"
- "@event_dispatcher"
calls:
- [ setLogger, [ "@logger" ]]
tags:
- { name: wallabag_import.import, alias: pinboard }
wallabag_import.firefox.import:
class: Wallabag\ImportBundle\Import\FirefoxImport
arguments:

View File

@ -0,0 +1,45 @@
{% extends "WallabagCoreBundle::layout.html.twig" %}
{% block title %}{{ 'import.pinboard.page_title'|trans }}{% endblock %}
{% block content %}
<div class="row">
<div class="col s12">
<div class="card-panel settings">
{% include 'WallabagImportBundle:Import:_information.html.twig' %}
<div class="row">
<blockquote>{{ import.description|trans }}</blockquote>
<p>{{ 'import.pinboard.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 %}