diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php new file mode 100644 index 0000000..648a171 --- /dev/null +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php @@ -0,0 +1,102 @@ +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; + } + +} diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/UriLinkFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/UriLinkFormatter.php new file mode 100644 index 0000000..8209e1e --- /dev/null +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/UriLinkFormatter.php @@ -0,0 +1,44 @@ + $item) { + $elements[$delta] = array( + '#type' => 'link', + '#href' => $item->value, + '#title' => $item->value, + ); + } + + return $elements; + } + +} diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php index dbef995..f67eb9f 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php @@ -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 { diff --git a/core/modules/aggregator/aggregator.module b/core/modules/aggregator/aggregator.module index 64eb275..053dcd3 100644 --- a/core/modules/aggregator/aggregator.module +++ b/core/modules/aggregator/aggregator.module @@ -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,10 +75,6 @@ function aggregator_theme() { 'variables' => array('feeds' => NULL), 'file' => 'aggregator.theme.inc', ), - 'aggregator_page_rss' => array( - 'variables' => array('feeds' => NULL), - 'file' => 'aggregator.theme.inc', - ), ); } @@ -107,6 +93,58 @@ function aggregator_permission() { } /** + * 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; +} + +/** * Implements hook_cron(). * * Queues news feeds for updates once their refresh interval has elapsed. diff --git a/core/modules/aggregator/aggregator.routing.yml b/core/modules/aggregator/aggregator.routing.yml index 00766eb..40f1e94 100644 --- a/core/modules/aggregator/aggregator.routing.yml +++ b/core/modules/aggregator/aggregator.routing.yml @@ -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' diff --git a/core/modules/aggregator/aggregator.theme.inc b/core/modules/aggregator/aggregator.theme.inc index 605025c..e90a798 100644 --- a/core/modules/aggregator/aggregator.theme.inc +++ b/core/modules/aggregator/aggregator.theme.inc @@ -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()); } /** diff --git a/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.default.yml b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.default.yml new file mode 100644 index 0000000..9474720 --- /dev/null +++ b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.default.yml @@ -0,0 +1,34 @@ +id: aggregator_feed.aggregator_feed.default +label: null +targetEntityType: aggregator_feed +bundle: aggregator_feed +mode: default +langcode: en +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 +third_party_settings: { } +dependencies: + module: + - aggregator diff --git a/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.summary.yml b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.summary.yml new file mode 100644 index 0000000..5278f31 --- /dev/null +++ b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.summary.yml @@ -0,0 +1,21 @@ +id: aggregator_feed.aggregator_feed.summary +targetEntityType: aggregator_feed +bundle: aggregator_feed +mode: summary +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 diff --git a/core/modules/aggregator/config/install/core.entity_view_display.aggregator_item.aggregator_item.summary.yml b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_item.aggregator_item.summary.yml new file mode 100644 index 0000000..bffdb9c --- /dev/null +++ b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_item.aggregator_item.summary.yml @@ -0,0 +1,19 @@ +id: aggregator_item.aggregator_item.summary +targetEntityType: aggregator_item +bundle: aggregator_item +mode: summary +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 diff --git a/core/modules/aggregator/config/install/core.entity_view_mode.aggregator_feed.summary.yml b/core/modules/aggregator/config/install/core.entity_view_mode.aggregator_feed.summary.yml new file mode 100644 index 0000000..c1b4bb8 --- /dev/null +++ b/core/modules/aggregator/config/install/core.entity_view_mode.aggregator_feed.summary.yml @@ -0,0 +1,8 @@ +id: aggregator_feed.summary +label: Summary +status: true +cache: true +targetEntityType: aggregator_feed +dependencies: + module: + - aggregator diff --git a/core/modules/aggregator/src/Controller/AggregatorController.php b/core/modules/aggregator/src/Controller/AggregatorController.php index 1cedb04..6c46b2a 100644 --- a/core/modules/aggregator/src/Controller/AggregatorController.php +++ b/core/modules/aggregator/src/Controller/AggregatorController.php @@ -61,26 +61,6 @@ public function feedAdd() { } /** - * 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. * * @param \Drupal\aggregator\ItemInterface[] $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', diff --git a/core/modules/aggregator/src/Entity/Feed.php b/core/modules/aggregator/src/Entity/Feed.php index a706470..5a33b71 100644 --- a/core/modules/aggregator/src/Entity/Feed.php +++ b/core/modules/aggregator/src/Entity/Feed.php @@ -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', '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')) diff --git a/core/modules/aggregator/src/Entity/Item.php b/core/modules/aggregator/src/Entity/Item.php index 3f6cba0..5df7013 100644 --- a/core/modules/aggregator/src/Entity/Item.php +++ b/core/modules/aggregator/src/Entity/Item.php @@ -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.')); + ->setDescription(t('The link of the feed item.')) + ->setDisplayOptions('view', array( + 'type' => 'hidden', + )) + ->setDisplayConfigurable('view', TRUE); $fields['author'] = BaseFieldDefinition::create('string') ->setLabel(t('Author')) - ->setDescription(t('The author of the feed item.')); + ->setDescription(t('The author of the feed item.')) + ->setDisplayOptions('view', array( + 'label' => 'hidden', + 'weight' => 3, + )) + ->setDisplayConfigurable('view', TRUE); $fields['description'] = BaseFieldDefinition::create('string_long') ->setLabel(t('Description')) ->setDescription(t('The body of the feed item.')); $fields['timestamp'] = BaseFieldDefinition::create('created') - ->setLabel(t('Posted timestamp')) - ->setDescription(t('Posted date of the feed item, as a Unix timestamp.')); + ->setLabel(t('Posted on')) + ->setDescription(t('Posted date of the feed item, as a Unix timestamp.')) + ->setDisplayOptions('view', array( + 'label' => 'hidden', + 'type' => 'timestamp_ago', + 'weight' => 1, + )) + ->setDisplayConfigurable('view', TRUE); // @todo Convert to a real UUID field in https://drupal.org/node/2149851. $fields['guid'] = BaseFieldDefinition::create('string_long') diff --git a/core/modules/aggregator/src/FeedViewBuilder.php b/core/modules/aggregator/src/FeedViewBuilder.php index 853122f..d42641a 100644 --- a/core/modules/aggregator/src/FeedViewBuilder.php +++ b/core/modules/aggregator/src/FeedViewBuilder.php @@ -8,7 +8,12 @@ namespace Drupal\aggregator; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityViewBuilder; +use Drupal\Core\Config\Config; +use Drupal\Core\Language\LanguageManagerInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Render controller for aggregator feed items. @@ -16,12 +21,122 @@ class FeedViewBuilder extends EntityViewBuilder { /** + * Constructs a new FeedViewBuilder. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type definition. + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager service. + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager + * The language manager. + * @param \Drupal\Core\Config\Config $config + * The 'aggregator.settings' config. + */ + public function __construct(EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, Config $config) { + parent::__construct($entity_type, $entity_manager, $language_manager); + $this->config = $config; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { + return new static( + $entity_type, + $container->get('entity.manager'), + $container->get('language_manager'), + $container->get('config.factory')->get('aggregator.settings') + ); + } + + /** * {@inheritdoc} */ - protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langcode) { - $defaults = parent::getBuildDefaults($entity, $view_mode, $langcode); - $defaults['#theme'] = 'aggregator_feed_source'; - return $defaults; + public function buildComponents(array &$build, array $entities, array $displays, $view_mode, $langcode = NULL) { + parent::buildComponents($build, $entities, $displays, $view_mode, $langcode); + + foreach ($entities as $id => $entity) { + $bundle = $entity->bundle(); + $display = $displays[$bundle]; + + if ($display->getComponent('items')) { + // When in summary view mode, respect the list_max setting. + $limit = $view_mode == 'summary' ? $this->config->get('source.list_max') : 20; + // Retrieve the items attached to this feed. + $items = $this->entityManager + ->getStorage('aggregator_item') + ->loadByFeed($entity->id(), $limit); + + $build[$id]['items'] = $this->entityManager + ->getViewBuilder('aggregator_item') + ->viewMultiple($items, $view_mode, $langcode); + + if ($view_mode == 'full') { + // Also add the pager. + $build[$id]['pager'] = array('#theme' => 'pager'); + } + } + + if ($display->getComponent('description')) { + $build[$id]['description'] = array( + '#markup' => aggregator_filter_xss($entity->getDescription()), + '#prefix' => '
', + '#suffix' => '
', + ); + } + + if ($display->getComponent('image')) { + $image_link = array(); + // Render the image as link if it is available. + $image = $entity->getImage(); + $label = $entity->label(); + $link_href = $entity->getWebsiteUrl(); + if ($image && $label && $link_href) { + $link_title = array( + '#theme' => 'image', + '#path' => $image, + '#alt' => $label, + ); + $image_link = array( + '#type' => 'link', + '#title' => $link_title, + '#href' => $link_href, + '#options' => array( + 'attributes' => array('class' => array('feed-image')), + 'html' => TRUE, + ), + ); + } + $build[$id]['image'] = $image_link; + } + + if ($display->getComponent('feed_icon')) { + $build[$id]['feed_icon'] = array( + '#theme' => 'feed_icon', + '#url' => $entity->getUrl(), + '#title' => t('!title feed', array('!title' => $entity->label())), + ); + } + + if ($display->getComponent('more_link')) { + $title_stripped = strip_tags($entity->label()); + $build[$id]['more_link'] = array( + '#type' => 'link', + '#title' => t('More posts about @title', array( + '@title' => $title_stripped, + )), + '#route_name' => 'entity.aggregator_feed.canonical', + '#route_parameters' => array('aggregator_feed' => $entity->id()), + '#options' => array( + 'html' => TRUE, + 'attributes' => array( + 'title' => $title_stripped, + ), + ), + ); + } + + } } } diff --git a/core/modules/aggregator/src/ItemViewBuilder.php b/core/modules/aggregator/src/ItemViewBuilder.php index 7d3f919..a6488bb 100644 --- a/core/modules/aggregator/src/ItemViewBuilder.php +++ b/core/modules/aggregator/src/ItemViewBuilder.php @@ -7,7 +7,7 @@ namespace Drupal\aggregator; -use Drupal\Core\Entity\EntityInterface; +use Drupal\Component\Utility\String; use Drupal\Core\Entity\EntityViewBuilder; /** @@ -18,14 +18,21 @@ class ItemViewBuilder extends EntityViewBuilder { /** * {@inheritdoc} */ - protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langcode) { - $defaults = parent::getBuildDefaults($entity, $view_mode, $langcode); + public function buildComponents(array &$build, array $entities, array $displays, $view_mode, $langcode = NULL) { + parent::buildComponents($build, $entities, $displays, $view_mode, $langcode); - // Use a different template for the summary view mode. - if ($view_mode == 'summary') { - $defaults['#theme'] = 'aggregator_summary_item'; + foreach ($entities as $id => $entity) { + $bundle = $entity->bundle(); + $display = $displays[$bundle]; + + if ($display->getComponent('description')) { + $build[$id]['description'] = array( + '#markup' => aggregator_filter_xss($entity->getDescription()), + '#prefix' => '
', + '#suffix' => '
', + ); + } } - return $defaults; } } diff --git a/core/modules/aggregator/templates/aggregator-feed-source.html.twig b/core/modules/aggregator/templates/aggregator-feed-source.html.twig deleted file mode 100644 index d492904..0000000 --- a/core/modules/aggregator/templates/aggregator-feed-source.html.twig +++ /dev/null @@ -1,32 +0,0 @@ -{# -/** - * @file - * Default theme implementation to present the source of the feed. - * - * The contents are rendered below feed listings when browsing source feeds. - * For example, "example.com/aggregator/sources/1". - * - * Available variables: - * - source_icon: Feed icon linked to the source. Rendered through - * feed-icon.html.twig. - * - source_image: Image set by the feed source. - * - source_description: Description set by the feed source. - * - source_url: URL to the feed source. - * - last_checked: How long ago the feed was checked locally. - * - * @see template_preprocess_aggregator_feed_source() - * - * @ingroup themeable - */ -#} - - {{ source_icon }} - {{ source_image }} -

{{ source_description }}

-
-
{{ 'URL'|t }}
-
{{ source_url }}
-
{{ 'Updated'|t }}
-
{{ last_checked }}
-
- diff --git a/core/modules/aggregator/templates/aggregator-feed.html.twig b/core/modules/aggregator/templates/aggregator-feed.html.twig new file mode 100644 index 0000000..1876c45 --- /dev/null +++ b/core/modules/aggregator/templates/aggregator-feed.html.twig @@ -0,0 +1,31 @@ +{# +/** + * @file + * Default theme implementation to present an aggregator feed. + * + * The contents are rendered above feed listings when browsing source feeds. + * For example, "example.com/aggregator/sources/1". + * + * Available variables: + * - title: Title of the feed item. + * - content: All field items. Use {{ content }} to print them all, + * or print a subset such as {{ content.field_example }}. Use + * {{ content|without('field_example') }} to temporarily suppress the printing + * of a given element. + * + * @see template_preprocess_aggregator_feed() + * + * @ingroup themeable + */ +#} + + + {{ title_prefix }} + {% if not full %} + {{ title }} + {% endif %} + {{ title_suffix }} + + {{ content }} + + diff --git a/core/modules/aggregator/templates/aggregator-item.html.twig b/core/modules/aggregator/templates/aggregator-item.html.twig index 8c23106..8f31937 100644 --- a/core/modules/aggregator/templates/aggregator-item.html.twig +++ b/core/modules/aggregator/templates/aggregator-item.html.twig @@ -4,33 +4,25 @@ * Default theme implementation to present a feed item in an aggregator page. * * Available variables: - * - feed_url: URL to the originating feed item. - * - feed_title: Title of the feed item. - * - source_url: Link to the local source section. - * - source_title: Title of the remote source. - * - source_date: Date the feed was posted on the remote source. - * - content: Feed item content. + * - url: URL to the originating feed item. + * - title: Title of the feed item. + * - content: All field items. Use {{ content }} to print them all, + * or print a subset such as {{ content.field_example }}. Use + * {{ content|without('field_example') }} to temporarily suppress the printing + * of a given element. * * @see template_preprocess_aggregator_item() * * @ingroup themeable */ #} - + + {{ title_prefix }}

- {{ feed_title }} + {{ title }}

+ {{ title_suffix }} -
- {% if source_url %} - {{ source_title }} - - {% endif %} - {{ source_date }} -
+ {{ content }} - {% if content %} -
- {{ content }} -
- {% endif %} diff --git a/core/modules/aggregator/templates/aggregator-summary-item.html.twig b/core/modules/aggregator/templates/aggregator-summary-item.html.twig deleted file mode 100644 index 3cb2279..0000000 --- a/core/modules/aggregator/templates/aggregator-summary-item.html.twig +++ /dev/null @@ -1,15 +0,0 @@ -{# -/** - * @file - * Default theme implementation for a single feed in a list of feed items. - * - * Available variables: - * - url: URL of item. - * - age: Age of the item. - * - * @see template_preprocess_aggregator_summary_item() - * - * @ingroup themeable - */ -#} -{{ url }} {{ age }} diff --git a/core/modules/aggregator/templates/aggregator-summary-items.html.twig b/core/modules/aggregator/templates/aggregator-summary-items.html.twig deleted file mode 100644 index a00b8dc..0000000 --- a/core/modules/aggregator/templates/aggregator-summary-items.html.twig +++ /dev/null @@ -1,23 +0,0 @@ -{# -/** - * @file - * Default theme implementation to present feeds as list items. - * - * Each iteration generates a single feed source. - * - * Available variables: - * - title: Title of the feed. - * - summary_list: Unordered list of linked feed items generated through - * theme_item_list(). - * - source_url: URL to the local source. - * - * @see template_preprocess_aggregator_summary_items() - * - * @ingroup themeable - */ -#} -

{{ title }}

-{{ summary_list }} -