diff --git a/core/modules/aggregator/aggregator.module b/core/modules/aggregator/aggregator.module index d2c07af..cad1b8f 100644 --- a/core/modules/aggregator/aggregator.module +++ b/core/modules/aggregator/aggregator.module @@ -191,12 +191,9 @@ function aggregator_menu() { 'file' => 'aggregator.admin.inc', ); $items['aggregator/sources/%aggregator_feed'] = array( - 'title callback' => 'entity_page_label', + 'title callback' => '_aggregator_page_label', 'title arguments' => array(2), - 'page callback' => 'aggregator_page_source', - 'page arguments' => array(2), - 'access arguments' => array('access news feeds'), - 'file' => 'aggregator.pages.inc', + 'route_name' => 'aggregator_page_source', ); $items['aggregator/sources/%aggregator_feed/view'] = array( 'title' => 'View', @@ -242,6 +239,24 @@ function aggregator_menu() { } /** + * Title callback: Returns a title for Aggregator feed view pages. + * + * @param int $fid + * Aggregator Feed Id for which to generate a label. + * @param $langcode + * (optional) The language code of the language that should be used for + * getting the label. If set to NULL, the entity's default language is + * used. + * + * @return string The label of the Aggregator Feed, or NULL if there is no label + * defined.@see aggregator_menu() + */ +function _aggregator_page_label($fid, $langcode = NULL) { + $feed = aggregator_feed_load($fid); + return ($feed) ? entity_page_label($feed, $langcode) : ''; +} + +/** * Title callback: Returns a title for aggregator category pages. * * @param $category diff --git a/core/modules/aggregator/aggregator.routing.yml b/core/modules/aggregator/aggregator.routing.yml index e25527c..74bbfdd 100644 --- a/core/modules/aggregator/aggregator.routing.yml +++ b/core/modules/aggregator/aggregator.routing.yml @@ -47,6 +47,13 @@ aggregator_opml_add: requirements: _permission: 'administer news feeds' +aggregator_page_source: + pattern: 'aggregator/sources/{aggregator_feed}' + defaults: + _content: '\Drupal\aggregator\Routing\AggregatorController::viewFeed' + requirements: + _permission: 'access news feeds' + aggregator_page_last: pattern: '/aggregator' defaults: diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php b/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php index eac277c..dd084c5 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php @@ -14,6 +14,7 @@ use Drupal\Core\Entity\EntityManager; use Drupal\Core\Extension\ModuleHandlerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\aggregator\Plugin\Core\Entity\Feed; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -100,6 +101,110 @@ public function feedAdd() { return $this->entityManager->getForm($feed); } +/** + * Displays all the items captured from the particular feed. + * + * @param \Drupal\aggregator\Plugin\Core\Entity\Feed $aggregator_feed + * The feed for which to display all items. + * + * @return string + * The rendered list of items for the feed. + */ + public function viewFeed(Feed $aggregator_feed = NULL) { + $feed_source = $this->entityManager->getRenderController($aggregator_feed->entityType()) + ->view($aggregator_feed, 'default'); + // Load aggregator feed item for the particular feed id. + $items = $this->loadFeedItems('source', $aggregator_feed); + // Print the feed items. + return $this->buildPageList($items, $feed_source); + } + + /** + * Loads and optionally filters feed items. + * + * @param $type + * The type of filter for the items. Possible values are: + * - sum: No filtering. + * - source: Filter the feed items, limiting the result to items from a + * single source. + * - category: Filter the feed items by category. + * @param $data + * Feed or category data used for filtering. The type and value of $data + * depends on $type: + * - source: $data is an object with $data->fid identifying the feed used to + * as filter. + * - category: $data is an array with $data['cid'] being the category id to + * filter on. + * The $data parameter is not used when $type is 'sum'. + * @param $limit + * Limit for fetching the number of feed items. + * + * @return mixed An array of the feed items. + */ + public function loadFeedItems($type, $data = NULL, $limit = 20) { + switch ($type) { + case 'sum': + $query = $this->database->select('aggregator_item', 'i'); + $query->join('aggregator_feed', 'f', 'i.fid = f.fid'); + $query->fields('i', array('iid')); + break; + case 'source': + $query = $this->database->select('aggregator_item', 'i'); + $query + ->fields('i', array('iid')) + ->condition('i.fid', $data->id()); + break; + case 'category': + $query = $this->database->select('aggregator_category_item', 'c'); + $query->leftJoin('aggregator_item', 'i', 'c.iid = i.iid'); + $query->leftJoin('aggregator_feed', 'f', 'i.fid = f.fid'); + $query + ->fields('i', array('iid')) + ->condition('cid', $data->cid); + break; + } + + $result = $query + ->extend('Drupal\Core\Database\Query\PagerSelectExtender') + ->limit($limit) + ->orderBy('i.timestamp', 'DESC') + ->orderBy('i.iid', 'DESC') + ->execute() + ->fetchCol(); + + $feed_items = $this->entityManager + ->getStorageController('aggregator_item')->load($result); + + return $feed_items; + } + + /** + * Prints an aggregator page listing a number of feed items. + * + * @param \Drupal\aggregator\Plugin\Core\Entity\Item $items + * The items to be listed. + * @param array|string $feed_source + * The feed source URL. + * + * @return array + * The rendered list of items for the feed. + */ + protected function buildPageList($items, $feed_source = '') { + // Assemble output. + $build = array( + '#type' => 'container', + '#attributes' => array('class' => array('aggregator-wrapper')), + ); + $build['feed_source'] = is_array($feed_source) ? $feed_source : array('#markup' => $feed_source); + if ($items) { + $build['items'] = $this->entityManager->getRenderController(reset($items)->entityType()) + ->viewMultiple($items, 'default'); + $build['pager']['#markup'] = theme('pager'); + } + return $build; + } + + /** * Refreshes a feed, then redirects to the overview page. *