Commit c554974c authored by alexpott's avatar alexpott

Issue #2261425 by ParisLiakos, alexpott: Streamline aggregator's entities...

Issue #2261425 by ParisLiakos, alexpott: Streamline aggregator's entities rendering with rest of core.
parent bc8ffe31
......@@ -244,3 +244,23 @@ entity_view_display.field.number_unformatted:
label: 'Settings'
sequence:
- type: string
entity_view_display.field.uri_link:
type: entity_field_view_display_base
label: 'URI as link display format settings'
mapping:
settings:
type: sequence
label: 'Settings'
sequence:
- type: string
entity_view_display.field.timestamp_ago:
type: entity_field_view_display_base
label: 'Timestamp ago display format settings'
mapping:
settings:
type: sequence
label: 'Settings'
sequence:
- type: string
<?php
/**
* @file
* Contains \Drupal\Core\Field\Plugin\Field\FieldFormatter\TimestampAgoFormatter.
*/
namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Plugin implementation of the 'timestamp' formatter as time ago.
*
* @FieldFormatter(
* id = "timestamp_ago",
* label = @Translation("Time ago"),
* field_types = {
* "timestamp",
* "created",
* "updated",
* }
* )
*/
class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
/**
* The date formatter service.
*
* @var \Drupal\Core\Datetime\DateFormatter
*/
protected $dateFormatter;
/**
* Constructs a TimestampAgoFormatter object.
*
* @param string $plugin_id
* The plugin_id for the formatter.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The definition of the field to which the formatter is associated.
* @param array $settings
* The formatter settings.
* @param string $label
* The formatter label display setting.
* @param string $view_mode
* The view mode.
* @param array $third_party_settings
* Any third party settings settings.
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
* The date formatter service.
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, DateFormatter $date_formatter) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
$this->dateFormatter = $date_formatter;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
// @see \Drupal\Core\Field\FormatterPluginManager::createInstance().
return new static(
$plugin_id,
$plugin_definition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['label'],
$configuration['view_mode'],
$configuration['third_party_settings'],
$container->get('date.formatter')
);
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items) {
$elements = array();
foreach ($items as $delta => $item) {
if ($item->value) {
$updated = $this->t('@time ago', array('@time' => $this->dateFormatter->formatInterval(REQUEST_TIME - $item->value)));
}
else {
$updated = $this->t('never');
}
$elements[$delta] = array('#markup' => $updated);
}
return $elements;
}
}
<?php
/**
* @file
* Contains \Drupal\Core\Field\Plugin\Field\FieldFormatter\UriLinkFormatter.
*/
namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Field\FieldItemListInterface;
/**
* Plugin implementation of the 'uri_link' formatter.
*
* @FieldFormatter(
* id = "uri_link",
* label = @Translation("Link to URI"),
* field_types = {
* "uri",
* }
* )
*/
class UriLinkFormatter extends FormatterBase {
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items) {
$elements = array();
foreach ($items as $delta => $item) {
$elements[$delta] = array(
'#type' => 'link',
'#href' => $item->value,
'#title' => $item->value,
);
}
return $elements;
}
}
......@@ -21,7 +21,8 @@
* id = "uri",
* label = @Translation("URI"),
* description = @Translation("An entity field containing a URI."),
* no_ui = TRUE
* no_ui = TRUE,
* default_formatter = "uri_link",
* )
*/
class UriItem extends StringItem {
......
......@@ -56,28 +56,18 @@ function aggregator_help($route_name, RouteMatchInterface $route_match) {
*/
function aggregator_theme() {
return array(
'aggregator_feed_source' => array(
'variables' => array('aggregator_feed' => NULL, 'view_mode' => NULL),
'aggregator_feed' => array(
'render element' => 'elements',
'file' => 'aggregator.theme.inc',
'template' => 'aggregator-feed-source',
'template' => 'aggregator-feed',
),
'aggregator_block_item' => array(
'variables' => array('item' => NULL, 'feed' => 0),
'file' => 'aggregator.theme.inc',
'template' => 'aggregator-block-item',
),
'aggregator_summary_items' => array(
'variables' => array('summary_items' => NULL, 'source' => NULL),
'file' => 'aggregator.theme.inc',
'template' => 'aggregator-summary-items',
),
'aggregator_summary_item' => array(
'variables' => array('aggregator_item' => NULL, 'view_mode' => NULL),
'file' => 'aggregator.theme.inc',
'template' => 'aggregator-summary-item',
),
'aggregator_item' => array(
'variables' => array('aggregator_item' => NULL, 'view_mode' => NULL),
'render element' => 'elements',
'file' => 'aggregator.theme.inc',
'template' => 'aggregator-item',
),
......@@ -85,11 +75,59 @@ function aggregator_theme() {
'variables' => array('feeds' => NULL),
'file' => 'aggregator.theme.inc',
),
'aggregator_page_rss' => array(
'variables' => array('feeds' => NULL),
'file' => 'aggregator.theme.inc',
);
}
/**
* Implements hook_entity_extra_field_info().
*/
function aggregator_entity_extra_field_info() {
$extra = array();
$extra['aggregator_feed']['aggregator_feed'] = array(
'display' => array(
'items' => array(
'label' => t('Items'),
'description' => t('Items associated with this feed'),
'weight' => 0,
),
// @todo Move to a formatter at https://www.drupal.org/node/2339917.
'image' => array(
'label' => t('Image'),
'description' => t('The feed image'),
'weight' => 2,
),
// @todo Move to a formatter at https://drupal.org/node/2149845.
'description' => array(
'label' => t('Description'),
'description' => t('The description of this feed'),
'weight' => 3,
),
'more_link' => array(
'label' => t('More link'),
'description' => t('A more link to the feed detail page'),
'weight' => 5,
),
'feed_icon' => array(
'label' => t('Feed icon'),
'description' => t('An icon that links to the feed url'),
'weight' => 6,
),
),
);
$extra['aggregator_item']['aggregator_item'] = array(
'display' => array(
// @todo Move to a formatter at https://drupal.org/node/2149845.
'description' => array(
'label' => t('Description'),
'description' => t('The description of this feed item'),
'weight' => 2,
),
),
);
return $extra;
}
/**
......
......@@ -52,7 +52,7 @@ aggregator.feed_add:
entity.aggregator_feed.canonical:
path: '/aggregator/sources/{aggregator_feed}'
defaults:
_content: '\Drupal\aggregator\Controller\AggregatorController::viewFeed'
_entity_view: 'aggregator_feed'
_title_callback: '\Drupal\aggregator\Controller\AggregatorController::feedTitle'
requirements:
_permission: 'access news feeds'
......
......@@ -15,31 +15,18 @@
*
* @param array $variables
* An associative array containing:
* - aggregator_item: An individual feed item for display on the aggregator
* page.
* - elements: An array of elements to display in view mode.
*/
function template_preprocess_aggregator_item(&$variables) {
$item = $variables['aggregator_item'];
$item = $variables['elements']['#aggregator_item'];
$variables['feed_url'] = check_url($item->getLink());
$variables['feed_title'] = String::checkPlain($item->getTitle());
$variables['content'] = aggregator_filter_xss($item->getDescription());
$variables['source_url'] = '';
$variables['source_title'] = '';
$fid = $item->getFeedId();
if (isset($item->ftitle) && $fid !== NULL) {
$variables['source_url'] = url('aggregator/sources/' . $fid);
$variables['source_title'] = String::checkPlain($item->ftitle);
}
if (date('Ymd', $item->getPostedTime()) == date('Ymd')) {
$variables['source_date'] = t('%ago ago', array('%ago' => \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $item->getPostedTime())));
}
else {
$variables['source_date'] = format_date($item->getPostedTime(), 'medium');
// Helpful $content variable for templates.
foreach (Element::children($variables['elements']) as $key) {
$variables['content'][$key] = $variables['elements'][$key];
}
$variables['attributes']['class'][] = 'feed-item';
$variables['url'] = check_url($item->getLink());
$variables['title'] = String::checkPlain($item->label());
}
/**
......@@ -74,104 +61,23 @@ function theme_aggregator_page_opml($variables) {
}
/**
* Prepares variables for aggregator summary templates.
*
* Default template: aggregator-summary-items.html.twig.
*
* @param array $variables
* An associative array containing:
* - source: A Drupal\aggregator\FeedInterface object representing the feed
* source.
* - summary_items: An array of feed items.
*/
function template_preprocess_aggregator_summary_items(&$variables) {
$variables['title'] = String::checkPlain($variables['source']->label());
$summary_items = array();
foreach (Element::children($variables['summary_items']) as $key) {
$summary_items[] = $variables['summary_items'][$key];
}
$variables['summary_list'] = array(
'#theme' => 'item_list',
'#items' => $summary_items,
);
$variables['source_url'] = $variables['source']->getUrl();
}
/**
* Processes variables for aggregator summary item templates.
* Prepares variables for aggregator feed templates.
*
* Default template: aggregator-summary-item.html.twig.
* Default template: aggregator-feed.html.twig.
*
* @param array $variables
* An associative array containing:
* - aggregator_item: The feed item.
* - view_mode: How the item is being displayed.
* - elements: An array of elements to display in view mode.
*/
function template_preprocess_aggregator_summary_item(&$variables) {
$item = $variables['aggregator_item'];
$variables['url'] = l(String::checkPlain($item->label()), check_url(url($item->getLink(), array('absolute' => TRUE))), array(
'attributes' => array(
'class' => array('feed-item-url'),
),
));
$variables['age'] = array(
'#theme' => 'time',
'#attributes' => array(
'datetime' => format_date($item->getPostedTime(), 'html_datetime', '', 'UTC'),
'class' => array('feed-item-age',),
),
'#text' => t('%age old', array('%age' => \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $item->getPostedTime()))),
'#html' => TRUE,
);
}
function template_preprocess_aggregator_feed(&$variables) {
$feed = $variables['elements']['#aggregator_feed'];
/**
* Prepares variables for aggregator feed source templates.
*
* Default template: aggregator-feed-source.html.twig.
*
* @param array $variables
* An associative array containing:
* - aggregator_feed: A Drupal\aggregator\FeedInterface object representing
* the feed source.
*/
function template_preprocess_aggregator_feed_source(&$variables) {
$feed = $variables['aggregator_feed'];
$feed_icon = array(
'#theme' => 'feed_icon',
'#url' => $feed->getUrl(),
'#title' => t('!title feed', array('!title' => $feed->label())),
);
$variables['source_icon'] = drupal_render($feed_icon);
if ($feed->getImage() && $feed->label() && $feed->getWebsiteUrl()) {
$image = array(
'#theme' => 'image',
'#path' => $feed->getImage(),
'#alt' => $feed->label(),
);
$variables['source_image'] = l($image, $feed->getWebsiteUrl(), array('html' => TRUE, 'attributes' => array('class' => 'feed-image')));
// Helpful $content variable for templates.
foreach (Element::children($variables['elements']) as $key) {
$variables['content'][$key] = $variables['elements'][$key];
}
else {
$variables['source_image'] = '';
}
$variables['source_description'] = aggregator_filter_xss($feed->getDescription());
$variables['source_url'] = check_url(url($feed->getWebsiteUrl(), array('absolute' => TRUE)));
if ($feed->checked) {
$variables['last_checked'] = t('@time ago', array('@time' => \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $feed->getLastCheckedTime())));
}
else {
$variables['last_checked'] = t('never');
}
if (\Drupal::currentUser()->hasPermission('administer news feeds')) {
$variables['last_checked'] = l($variables['last_checked'], 'admin/config/services/aggregator');
}
$variables['attributes']['class'][] = 'feed-source';
$variables['full'] = $variables['elements']['#view_mode'] == 'full';
$variables['title'] = String::checkPlain($feed->label());
}
/**
......
id: aggregator_feed.aggregator_feed.default
targetEntityType: aggregator_feed
bundle: aggregator_feed
mode: default
status: true
content:
items:
weight: 0
checked:
type: timestamp_ago
weight: 1
settings: { }
third_party_settings: { }
label: inline
image:
weight: 2
description:
weight: 3
link:
type: uri_link
weight: 4
settings: { }
third_party_settings: { }
label: inline
feed_icon:
weight: 5
hidden:
more_link: true
dependencies:
module:
- aggregator
id: aggregator_feed.aggregator_feed.summary
targetEntityType: aggregator_feed
bundle: aggregator_feed
mode: summary
status: true
content:
items:
weight: 0
more_link:
weight: 1
hidden:
link: true
checked: true
description: true
image: true
feed_icon: true
status: true
dependencies:
entity:
- core.entity_view_mode.aggregator_feed.summary
module:
- aggregator
id: aggregator_item.aggregator_item.summary
targetEntityType: aggregator_item
bundle: aggregator_item
mode: summary
status: true
content:
timestamp:
weight: 0
hidden:
link: true
author: true
feed: true
description: true
status: true
dependencies:
entity:
- core.entity_view_mode.aggregator_item.summary
module:
- aggregator
- entity_reference
id: aggregator_feed.summary
label: Summary
status: true
cache: true
targetEntityType: aggregator_feed
dependencies:
module:
- aggregator
......@@ -60,26 +60,6 @@ public function feedAdd() {
return $this->entityFormBuilder()->getForm($feed);
}
/**
* Displays all the items captured from the particular feed.
*
* @param \Drupal\aggregator\FeedInterface $aggregator_feed
* The feed for which to display all items.
*
* @return array
* The rendered list of items for the feed.
*/
public function viewFeed(FeedInterface $aggregator_feed) {
$entity_manager = $this->entityManager();
$feed_source = $entity_manager->getViewBuilder('aggregator_feed')
->view($aggregator_feed, 'default');
// Load aggregator feed item for the particular feed id.
$items = $entity_manager->getStorage('aggregator_item')->loadByFeed($aggregator_feed->id(), 20);
// Print the feed items.
$build = $this->buildPageList($items, $feed_source);
return $build;
}
/**
* Builds a listing of aggregator feed items.
*
......@@ -210,35 +190,8 @@ public function sources() {
$feeds = $entity_manager->getStorage('aggregator_feed')->loadMultiple();
$build = array(
'#type' => 'container',
'#attributes' => array('class' => array('aggregator-wrapper')),
'#sorted' => TRUE,
);
foreach ($feeds as $feed) {
// Most recent items:
$summary_items = array();
$aggregator_summary_items = $this->config('aggregator.settings')
->get('source.list_max');
if ($aggregator_summary_items) {
$items = $entity_manager->getStorage('aggregator_item')
->loadByFeed($feed->id(), 20);
if ($items) {
$summary_items = $entity_manager->getViewBuilder('aggregator_item')
->viewMultiple($items, 'summary');
}
}
$feed->url = $this->url('entity.aggregator_feed.canonical', array('aggregator_feed' => $feed->id()));
$build[$feed->id()] = array(
'#theme' => 'aggregator_summary_items',
'#summary_items' => $summary_items,
'#source' => $feed,
'#cache' => array(
'tags' => $feed->getCacheTag(),
),
);
}
$build = $entity_manager->getViewBuilder('aggregator_feed')
->viewMultiple($feeds, 'summary');
$build['feed_icon'] = array(
'#theme' => 'feed_icon',
'#url' => 'aggregator/opml',
......
......@@ -37,6 +37,7 @@
* "edit-form" = "entity.aggregator_feed.edit_form",
* "delete-form" = "entity.aggregator_feed.delete_form",
* },
* field_ui_base_route = "aggregator.admin_overview",
* base_table = "aggregator_feed",
* fieldable = TRUE,
* render_cache = FALSE,
......@@ -148,7 +149,8 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setDisplayOptions('form', array(
'type' => 'string_textfield',
'weight' => -5,
));
))
->setDisplayConfigurable('form', TRUE);
$fields['langcode'] = BaseFieldDefinition::create('language')
->setLabel(t('Language code'))
......@@ -161,7 +163,8 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setDisplayOptions('form', array(
'type' => 'uri',
'weight' => -3,
));
))
->setDisplayConfigurable('form', TRUE);
$intervals = array(900, 1800, 3600, 7200, 10800, 21600, 32400, 43200, 64800, 86400, 172800, 259200, 604800, 1209600, 2419200);
$period = array_map(array(\Drupal::service('date.formatter'), 'formatInterval'), array_combine($intervals, $intervals));
......@@ -176,12 +179,19 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setDisplayOptions('form', array(
'type' => 'options_select',
'weight' => -2,
));
))
->setDisplayConfigurable('form', TRUE);
$fields['checked'] = BaseFieldDefinition::create('timestamp')
->setLabel(t('Checked'))
->setDescription(t('Last time feed was checked for new items, as Unix timestamp.'))
->setDefaultValue(0);
->setDefaultValue(0)
->setDisplayOptions('view', array(
'label' => 'inline',
'type' => 'timestamp_ago',
'weight' => 1,
))
->setDisplayConfigurable('view', TRUE);
$fields['queued'] = BaseFieldDefinition::create('timestamp')
->setLabel(t('Queued'))
......@@ -189,8 +199,13 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setDefaultValue(0);
$fields['link'] = BaseFieldDefinition::create('uri')
->setLabel(t('Link'))
->setDescription(t('The link of the feed.'));
->setLabel(t('URL'))
->setDescription(t('The link of the feed.'))
->setDisplayOptions('view', array(
'label' => 'inline',
'weight' => 4,
))
->setDisplayConfigurable('view', TRUE);
$fields['description'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Description'))
......
......@@ -58,9 +58,15 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setSetting('unsigned', TRUE);
$fields['fid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Aggregator feed ID'))
->setDescription(t('The ID of the aggregator feed.'))
->setSetting('target_type', 'aggregator_feed');
->setLabel(t('Source feed'))
->setDescription(t('The aggregator feed entity associated with this item.'))
->setSetting('target_type', 'aggregator_feed')
->setDisplayOptions('view', array(
'label' => 'hidden',
'type' => 'entity_reference_label',
'weight' => 0,
))
->setDisplayConfigurable('form', TRUE);
$fields['title'] = BaseFieldDefinition::create('string')
->setLabel(t('Title'))
......@@ -72,19 +78,34 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['link'] = BaseFieldDefinition::create('uri')
->setLabel(t('Link'))
->setDescription(t('The link of the feed item.'));