Newer
Older
Angie Byron
committed
<?php
/**
* @file
* Contains \Drupal\aggregator\Plugin\aggregator\processor\DefaultProcessor.
*/
namespace Drupal\aggregator\Plugin\aggregator\processor;
catch
committed
use Drupal\aggregator\ItemStorageInterface;
Alex Pott
committed
use Drupal\aggregator\Plugin\AggregatorPluginSettingsBase;
Angie Byron
committed
use Drupal\aggregator\Plugin\ProcessorInterface;
use Drupal\aggregator\FeedInterface;
use Drupal\Component\Utility\Unicode;
Alex Pott
committed
use Drupal\Core\Config\ConfigFactoryInterface;
Alex Pott
committed
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Form\ConfigFormBaseTrait;
Dries Buytaert
committed
use Drupal\Core\Form\FormStateInterface;
Alex Pott
committed
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
Angie Byron
committed
use Drupal\Core\Routing\UrlGeneratorTrait;
Alex Pott
committed
use Symfony\Component\DependencyInjection\ContainerInterface;
Angie Byron
committed
/**
* Defines a default processor implementation.
*
* Creates lightweight records from feed items.
*
Dries Buytaert
committed
* @AggregatorProcessor(
Angie Byron
committed
* id = "aggregator",
* title = @Translation("Default processor"),
* description = @Translation("Creates lightweight records from feed items.")
* )
*/
Alex Pott
committed
class DefaultProcessor extends AggregatorPluginSettingsBase implements ProcessorInterface, ContainerFactoryPluginInterface {
use ConfigFormBaseTrait;
Angie Byron
committed
use UrlGeneratorTrait;
Alex Pott
committed
/**
* Contains the configuration object factory.
*
Alex Pott
committed
* @var \Drupal\Core\Config\ConfigFactoryInterface
Alex Pott
committed
*/
protected $configFactory;
/**
* The entity query object for feed items.
*
* @var \Drupal\Core\Entity\Query\QueryInterface
*/
protected $itemQuery;
/**
catch
committed
* The entity storage for items.
catch
committed
* @var \Drupal\aggregator\ItemStorageInterface
*/
protected $itemStorage;
/**
* The date formatter service.
*
Alex Pott
committed
* @var \Drupal\Core\Datetime\DateFormatterInterface
*/
protected $dateFormatter;
Alex Pott
committed
/**
* Constructs a DefaultProcessor object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
Alex Pott
committed
* The plugin implementation definition.
Alex Pott
committed
* @param \Drupal\Core\Config\ConfigFactoryInterface $config
Alex Pott
committed
* The configuration factory object.
* @param \Drupal\Core\Entity\Query\QueryInterface $item_query
* The entity query object for feed items.
catch
committed
* @param \Drupal\aggregator\ItemStorageInterface $item_storage
* The entity storage for feed items.
Alex Pott
committed
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
* The date formatter service.
Alex Pott
committed
*/
Alex Pott
committed
public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config, QueryInterface $item_query, ItemStorageInterface $item_storage, DateFormatterInterface $date_formatter) {
Alex Pott
committed
$this->configFactory = $config;
$this->itemStorage = $item_storage;
$this->itemQuery = $item_query;
$this->dateFormatter = $date_formatter;
Alex Pott
committed
// @todo Refactor aggregator plugins to ConfigEntity so merging
// the configuration here is not needed.
parent::__construct($configuration + $this->getConfiguration(), $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
Alex Pott
committed
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('config.factory'),
$container->get('entity.query')->get('aggregator_item'),
$container->get('entity.manager')->getStorage('aggregator_item'),
Alex Pott
committed
$container->get('date.formatter')
Alex Pott
committed
);
}
Angie Byron
committed
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return ['aggregator.settings'];
}
Angie Byron
committed
/**
Alex Pott
committed
* {@inheritdoc}
Angie Byron
committed
*/
Dries Buytaert
committed
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$config = $this->config('aggregator.settings');
$processors = $config->get('processors');
Alex Pott
committed
$info = $this->getPluginDefinition();
catch
committed
$counts = array(3, 5, 10, 15, 20, 25);
$items = array_map(function ($count) {
Alex Pott
committed
return $this->formatPlural($count, '1 item', '@count items');
catch
committed
}, array_combine($counts, $counts));
$intervals = array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800);
$period = array_map(array($this->dateFormatter, 'formatInterval'), array_combine($intervals, $intervals));
Angie Byron
committed
$period[AGGREGATOR_CLEAR_NEVER] = t('Never');
$form['processors'][$info['id']] = array();
// Only wrap into details if there is a basic configuration.
if (isset($form['basic_conf'])) {
$form['processors'][$info['id']] = array(
'#type' => 'details',
'#title' => t('Default processor settings'),
'#description' => $info['description'],
Angie Byron
committed
'#open' => in_array($info['id'], $processors),
Angie Byron
committed
);
}
$form['processors'][$info['id']]['aggregator_summary_items'] = array(
'#type' => 'select',
'#title' => t('Number of items shown in listing pages'),
'#default_value' => $config->get('source.list_max'),
Angie Byron
committed
'#empty_value' => 0,
'#options' => $items,
);
$form['processors'][$info['id']]['aggregator_clear'] = array(
'#type' => 'select',
'#title' => t('Discard items older than'),
'#default_value' => $config->get('items.expire'),
Angie Byron
committed
'#options' => $period,
'#description' => t('Requires a correctly configured <a href=":cron">cron maintenance task</a>.', array(':cron' => $this->url('system.status'))),
Angie Byron
committed
);
catch
committed
$lengths = array(0, 200, 400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000);
$options = array_map(function($length) {
return ($length == 0) ? t('Unlimited') : $this->formatPlural($length, '1 character', '@count characters');
catch
committed
}, array_combine($lengths, $lengths));
Angie Byron
committed
$form['processors'][$info['id']]['aggregator_teaser_length'] = array(
'#type' => 'select',
'#title' => t('Length of trimmed description'),
'#default_value' => $config->get('items.teaser_length'),
catch
committed
'#options' => $options,
Alex Pott
committed
'#description' => t('The maximum number of characters used in the trimmed version of content.'),
Angie Byron
committed
);
return $form;
}
/**
Alex Pott
committed
* {@inheritdoc}
Angie Byron
committed
*/
Dries Buytaert
committed
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
Alex Pott
committed
$this->configuration['items']['expire'] = $form_state->getValue('aggregator_clear');
$this->configuration['items']['teaser_length'] = $form_state->getValue('aggregator_teaser_length');
$this->configuration['source']['list_max'] = $form_state->getValue('aggregator_summary_items');
Alex Pott
committed
// @todo Refactor aggregator plugins to ConfigEntity so this is not needed.
$this->setConfiguration($this->configuration);
Angie Byron
committed
}
/**
Alex Pott
committed
* {@inheritdoc}
Angie Byron
committed
*/
public function process(FeedInterface $feed) {
Angie Byron
committed
if (!is_array($feed->items)) {
return;
}
foreach ($feed->items as $item) {
Alex Pott
committed
// @todo: The default entity view builder always returns an empty
Angie Byron
committed
// array, which is ignored in aggregator_save_item() currently. Should
// probably be fixed.
if (empty($item['title'])) {
continue;
}
// Save this item. Try to avoid duplicate entries as much as possible. If
// we find a duplicate entry, we resolve it and pass along its ID is such
// that we can update it if needed.
if (!empty($item['guid'])) {
$values = array('fid' => $feed->id(), 'guid' => $item['guid']);
}
elseif ($item['link'] && $item['link'] != $feed->link && $item['link'] != $feed->url) {
$values = array('fid' => $feed->id(), 'link' => $item['link']);
}
else {
$values = array('fid' => $feed->id(), 'title' => $item['title']);
}
// Try to load an existing entry.
if ($entry = entity_load_multiple_by_properties('aggregator_item', $values)) {
$entry = reset($entry);
}
else {
$entry = entity_create('aggregator_item', array('langcode' => $feed->language()->getId()));
Angie Byron
committed
}
if ($item['timestamp']) {
$entry->setPostedTime($item['timestamp']);
Angie Byron
committed
}
// Make sure the item title and author fit in the 255 varchar column.
$entry->setTitle(Unicode::truncate($item['title'], 255, TRUE, TRUE));
$entry->setAuthor(Unicode::truncate($item['author'], 255, TRUE, TRUE));
Angie Byron
committed
$entry->setFeedId($feed->id());
$entry->setLink($item['link']);
$entry->setGuid($item['guid']);
Alex Pott
committed
$description = '';
if (!empty($item['description'])) {
$description = $item['description'];
}
$entry->setDescription($description);
Angie Byron
committed
$entry->save();
}
}
/**
Alex Pott
committed
* {@inheritdoc}
Angie Byron
committed
*/
public function delete(FeedInterface $feed) {
if ($items = $this->itemStorage->loadByFeed($feed->id())) {
$this->itemStorage->delete($items);
Angie Byron
committed
}
// @todo This should be moved out to caller with a different message maybe.
drupal_set_message(t('The news items from %site have been deleted.', array('%site' => $feed->label())));
Angie Byron
committed
}
/**
* Implements \Drupal\aggregator\Plugin\ProcessorInterface::postProcess().
*
* Expires items from a feed depending on expiration settings.
*/
public function postProcess(FeedInterface $feed) {
Alex Pott
committed
$aggregator_clear = $this->configuration['items']['expire'];
Angie Byron
committed
if ($aggregator_clear != AGGREGATOR_CLEAR_NEVER) {
// Delete all items that are older than flush item timer.
Angie Byron
committed
$age = REQUEST_TIME - $aggregator_clear;
$result = $this->itemQuery
->condition('fid', $feed->id())
->condition('timestamp', $age, '<')
->execute();
if ($result) {
$entities = $this->itemStorage->loadMultiple($result);
$this->itemStorage->delete($entities);
Angie Byron
committed
}
}
}
Alex Pott
committed
/**
* {@inheritdoc}
*/
public function getConfiguration() {
return $this->configFactory->get('aggregator.settings')->get();
}
/**
* {@inheritdoc}
*/
public function setConfiguration(array $configuration) {
$config = $this->config('aggregator.settings');
Alex Pott
committed
foreach ($configuration as $key => $value) {
$config->set($key, $value);
}
$config->save();
}