Commit cf882741 authored by Dries's avatar Dries

Issue #293318 by alex_b, Berdir, rootatwc, Aron Novak, mustafau, akahn:...

Issue #293318 by alex_b, Berdir, rootatwc, Aron Novak, mustafau, akahn: Convert Aggregator feeds into entities.
parent 8a4e0eb9
......@@ -7,6 +7,7 @@
namespace Drupal\Core\Entity;
use Drupal\Core\Language\Language;
use Drupal\Core\TypedData\ContextAwareInterface;
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\Component\Uuid\Uuid;
......@@ -264,8 +265,11 @@ public function isEmpty() {
* Implements \Drupal\Core\TypedData\TranslatableInterface::language().
*/
public function language() {
// Get the language code if the property exists.
if ($this->getPropertyDefinition('langcode')) {
$language = $this->get('langcode')->language;
if (!$language) {
}
if (!isset($language)) {
// Make sure we return a proper language object.
$language = new Language(array('langcode' => LANGUAGE_NOT_SPECIFIED));
}
......
<?php
/**
* @file
* Contains \Drupal\Core\Entity\Field\Type\UriItem.
*/
namespace Drupal\Core\Entity\Field\Type;
use Drupal\Core\Entity\Field\FieldItemBase;
/**
* Defines the 'uri_field' entity field item.
*/
class UriItem extends FieldItemBase {
/**
* Field definitions of the contained properties.
*
* @see self::getPropertyDefinitions()
*
* @var array
*/
static $propertyDefinitions;
/**
* Implements ComplexDataInterface::getPropertyDefinitions().
*/
public function getPropertyDefinitions() {
if (!isset(self::$propertyDefinitions)) {
self::$propertyDefinitions['value'] = array(
'type' => 'string',
'label' => t('Text value'),
);
}
return self::$propertyDefinitions;
}
}
......@@ -7,6 +7,7 @@
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Drupal\aggregator\Plugin\FetcherManager;
use Drupal\aggregator\Plugin\Core\Entity\Feed;
/**
* Page callback: Displays the aggregator administration page.
......@@ -92,172 +93,31 @@ function aggregator_view() {
}
/**
* Form constructor for adding and editing feed sources.
* Page callback: Presents the aggregator feed creation form.
*
* @param $feed
* (optional) If editing a feed, the feed to edit as a PHP stdClass value; if
* adding a new feed, NULL. Defaults to NULL.
* @return array
* A form array as expected by drupal_render().
*
* @ingroup forms
* @see aggregator_menu()
* @see aggregator_form_feed_validate()
* @see aggregator_form_feed_submit()
*/
function aggregator_form_feed($form, &$form_state, stdClass $feed = NULL) {
$period = drupal_map_assoc(array(900, 1800, 3600, 7200, 10800, 21600, 32400, 43200, 64800, 86400, 172800, 259200, 604800, 1209600, 2419200), 'format_interval');
$period[AGGREGATOR_CLEAR_NEVER] = t('Never');
$form['title'] = array('#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => isset($feed->title) ? $feed->title : '',
'#maxlength' => 255,
'#description' => t('The name of the feed (or the name of the website providing the feed).'),
'#required' => TRUE,
);
$form['url'] = array(
'#type' => 'url',
'#title' => t('URL'),
'#default_value' => isset($feed->url) ? $feed->url : '',
'#maxlength' => NULL,
'#description' => t('The fully-qualified URL of the feed.'),
'#required' => TRUE,
);
$form['refresh'] = array('#type' => 'select',
'#title' => t('Update interval'),
'#default_value' => isset($feed->refresh) ? $feed->refresh : 3600,
'#options' => $period,
'#description' => t('The length of time between feed updates. Requires a correctly configured <a href="@cron">cron maintenance task</a>.', array('@cron' => url('admin/reports/status'))),
);
$form['block'] = array('#type' => 'select',
'#title' => t('News items in block'),
'#default_value' => isset($feed->block) ? $feed->block : 5,
'#options' => drupal_map_assoc(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)),
'#description' => t("Drupal can make a block with the most recent news items of this feed. You can <a href=\"@block-admin\">configure blocks</a> to be displayed in the sidebar of your page. This setting lets you configure the number of news items to show in this feed's block. If you choose '0' this feed's block will be disabled.", array('@block-admin' => url('admin/structure/block'))),
);
// Handling of categories.
$options = array();
$values = array();
$categories = db_query('SELECT c.cid, c.title, f.fid FROM {aggregator_category} c LEFT JOIN {aggregator_category_feed} f ON c.cid = f.cid AND f.fid = :fid ORDER BY title', array(':fid' => isset($feed->fid) ? $feed->fid : NULL));
foreach ($categories as $category) {
$options[$category->cid] = check_plain($category->title);
if ($category->fid) $values[] = $category->cid;
}
if ($options) {
$form['category'] = array(
'#type' => 'checkboxes',
'#title' => t('Categorize news items'),
'#default_value' => $values,
'#options' => $options,
'#description' => t('New feed items are automatically filed in the checked categories.'),
);
}
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
if (!empty($feed->fid)) {
$form['actions']['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete'),
);
$form['fid'] = array(
'#type' => 'hidden',
'#value' => $feed->fid,
);
}
return $form;
}
/**
* Form validation handler for aggregator_form_feed().
*
* @see aggregator_form_feed_submit()
*/
function aggregator_form_feed_validate($form, &$form_state) {
if ($form_state['values']['op'] == t('Save')) {
// Check for duplicate titles.
if (isset($form_state['values']['fid'])) {
$result = db_query("SELECT title, url FROM {aggregator_feed} WHERE (title = :title OR url = :url) AND fid <> :fid", array(':title' => $form_state['values']['title'], ':url' => $form_state['values']['url'], ':fid' => $form_state['values']['fid']));
}
else {
$result = db_query("SELECT title, url FROM {aggregator_feed} WHERE title = :title OR url = :url", array(':title' => $form_state['values']['title'], ':url' => $form_state['values']['url']));
}
foreach ($result as $feed) {
if (strcasecmp($feed->title, $form_state['values']['title']) == 0) {
form_set_error('title', t('A feed named %feed already exists. Enter a unique title.', array('%feed' => $form_state['values']['title'])));
}
if (strcasecmp($feed->url, $form_state['values']['url']) == 0) {
form_set_error('url', t('A feed with this URL %url already exists. Enter a unique URL.', array('%url' => $form_state['values']['url'])));
}
}
}
}
/**
* Form submission handler for aggregator_form_feed().
*
* @see aggregator_form_feed_validate()
*
* @todo Add delete confirmation dialog.
*/
function aggregator_form_feed_submit($form, &$form_state) {
// @todo Replicate this cache invalidation when these ops are separated.
// Invalidate the block cache to update aggregator feed-based derivatives.
if (module_exists('block')) {
drupal_container()->get('plugin.manager.block')->clearCachedDefinitions();
}
if ($form_state['values']['op'] == t('Delete')) {
$title = $form_state['values']['title'];
// Unset the title.
unset($form_state['values']['title']);
}
aggregator_save_feed($form_state['values']);
if (isset($form_state['values']['fid'])) {
if (isset($form_state['values']['title'])) {
drupal_set_message(t('The feed %feed has been updated.', array('%feed' => $form_state['values']['title'])));
if (arg(0) == 'admin') {
$form_state['redirect'] = 'admin/config/services/aggregator/';
return;
}
else {
$form_state['redirect'] = 'aggregator/sources/' . $form_state['values']['fid'];
return;
}
}
else {
watchdog('aggregator', 'Feed %feed deleted.', array('%feed' => $title));
drupal_set_message(t('The feed %feed has been deleted.', array('%feed' => $title)));
if (arg(0) == 'admin') {
$form_state['redirect'] = 'admin/config/services/aggregator/';
return;
}
else {
$form_state['redirect'] = 'aggregator/sources/';
return;
}
}
}
else {
watchdog('aggregator', 'Feed %feed added.', array('%feed' => $form_state['values']['title']), WATCHDOG_NOTICE, l(t('view'), 'admin/config/services/aggregator'));
drupal_set_message(t('The feed %feed has been added.', array('%feed' => $form_state['values']['title'])));
}
function aggregator_feed_add() {
$feed = entity_create('aggregator_feed', array(
'refresh' => 3600,
'block' => 5,
));
return entity_get_form($feed);
}
/**
* Page callback: Deletes a feed.
*
* @param $feed
* An associative array describing the feed to be cleared.
* @param \Drupal\aggregator\Plugin\Core\Entity\Feed $feed
* A feed object describing the feed to be cleared.
*
* @see aggregator_admin_remove_feed_submit()
* @see aggregator_menu()
*/
function aggregator_admin_remove_feed($form, $form_state, $feed) {
function aggregator_admin_remove_feed($form, $form_state, Feed $feed) {
return confirm_form(
array(
'feed' => array(
......@@ -265,7 +125,7 @@ function aggregator_admin_remove_feed($form, $form_state, $feed) {
'#value' => $feed,
),
),
t('Are you sure you want to remove all items from the feed %feed?', array('%feed' => $feed->title)),
t('Are you sure you want to remove all items from the feed %feed?', array('%feed' => $feed->label())),
'admin/config/services/aggregator',
t('This action cannot be undone.'),
t('Remove items'),
......@@ -377,8 +237,6 @@ function aggregator_form_opml_submit($form, &$form_state) {
return;
}
$form_state['values']['op'] = t('Save');
foreach ($feeds as $feed) {
// Ensure URL is valid.
if (!valid_url($feed['url'], TRUE)) {
......@@ -399,9 +257,14 @@ function aggregator_form_opml_submit($form, &$form_state) {
}
}
$form_state['values']['title'] = $feed['title'];
$form_state['values']['url'] = $feed['url'];
drupal_form_submit('aggregator_form_feed', $form_state);
$new_feed = entity_create('aggregator_feed', array(
'title' => $feed['title'],
'url' => $feed['url'],
'refresh' => $form_state['values']['refresh'],
'block' => $form_state['values']['block'],
));
$new_feed->categories = $form_state['values']['category'];
$new_feed->save();
}
$form_state['redirect'] = 'admin/config/services/aggregator';
......@@ -443,17 +306,17 @@ function _aggregator_parse_opml($opml) {
/**
* Page callback: Refreshes a feed, then redirects to the overview page.
*
* @param $feed
* @param \Drupal\aggregator\Plugin\Core\Entity\Feed $feed
* An object describing the feed to be refreshed.
*
* @see aggregator_menu()
*/
function aggregator_admin_refresh_feed($feed) {
function aggregator_admin_refresh_feed(Feed $feed) {
// @todo CSRF tokens are validated in page callbacks rather than access
// callbacks, because access callbacks are also invoked during menu link
// generation. Add token support to routing: http://drupal.org/node/755584.
$token = drupal_container()->get('request')->query->get('token');
if (!isset($token) || !drupal_valid_token($token, 'aggregator/update/' . $feed->fid)) {
if (!isset($token) || !drupal_valid_token($token, 'aggregator/update/' . $feed->id())) {
throw new AccessDeniedHttpException();
}
......@@ -590,7 +453,7 @@ function aggregator_admin_form_submit($form, &$form_state) {
* Form constructor to add/edit/delete aggregator categories.
*
* @param $edit
* An associative array containing:
* An object containing:
* - title: A string to use for the category title.
* - description: A string to use for the category description.
* - cid: The category ID.
......@@ -600,22 +463,22 @@ function aggregator_admin_form_submit($form, &$form_state) {
* @see aggregator_form_category_validate()
* @see aggregator_form_category_submit()
*/
function aggregator_form_category($form, &$form_state, $edit = array('title' => '', 'description' => '', 'cid' => NULL)) {
function aggregator_form_category($form, &$form_state, $edit = NULL) {
$form['title'] = array('#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => $edit['title'],
'#default_value' => isset($edit->title) ? $edit->title : '',
'#maxlength' => 64,
'#required' => TRUE,
);
$form['description'] = array('#type' => 'textarea',
'#title' => t('Description'),
'#default_value' => $edit['description'],
'#default_value' => isset($edit->description) ? $edit->description : '',
);
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
if ($edit['cid']) {
if (!empty($edit->cid)) {
$form['actions']['delete'] = array('#type' => 'submit', '#value' => t('Delete'));
$form['cid'] = array('#type' => 'hidden', '#value' => $edit['cid']);
$form['cid'] = array('#type' => 'hidden', '#value' => $edit->cid);
}
return $form;
......
......@@ -6,6 +6,7 @@
*/
use Drupal\aggregator\Plugin\FetcherManager;
use Drupal\aggregator\Plugin\Core\Entity\Feed;
/**
* Denotes that a feed's items should never expire.
......@@ -51,17 +52,12 @@ function aggregator_help($path, $arg) {
*/
function aggregator_theme() {
return array(
'aggregator_wrapper' => array(
'variables' => array('content' => NULL),
'file' => 'aggregator.pages.inc',
'template' => 'aggregator-wrapper',
),
'aggregator_categorize_items' => array(
'render element' => 'form',
'file' => 'aggregator.pages.inc',
),
'aggregator_feed_source' => array(
'variables' => array('feed' => NULL),
'variables' => array('aggregator_feed' => NULL, 'view_mode' => NULL),
'file' => 'aggregator.pages.inc',
'template' => 'aggregator-feed-source',
),
......@@ -74,11 +70,11 @@ function aggregator_theme() {
'template' => 'aggregator-summary-items',
),
'aggregator_summary_item' => array(
'variables' => array('item' => NULL),
'variables' => array('aggregator_item' => NULL, 'view_mode' => NULL),
'file' => 'aggregator.pages.inc',
),
'aggregator_item' => array(
'variables' => array('item' => NULL),
'variables' => array('aggregator_item' => NULL, 'view_mode' => NULL),
'file' => 'aggregator.pages.inc',
'template' => 'aggregator-item',
),
......@@ -107,8 +103,7 @@ function aggregator_menu() {
);
$items['admin/config/services/aggregator/add/feed'] = array(
'title' => 'Add feed',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_form_feed'),
'page callback' => 'aggregator_feed_add',
'access arguments' => array('administer news feeds'),
'type' => MENU_LOCAL_ACTION,
'file' => 'aggregator.admin.inc',
......@@ -221,6 +216,8 @@ function aggregator_menu() {
'file' => 'aggregator.admin.inc',
);
$items['aggregator/sources/%aggregator_feed'] = array(
'title callback' => 'entity_page_label',
'title arguments' => array(2),
'page callback' => 'aggregator_page_source',
'page arguments' => array(2),
'access arguments' => array('access news feeds'),
......@@ -241,8 +238,8 @@ function aggregator_menu() {
);
$items['aggregator/sources/%aggregator_feed/configure'] = array(
'title' => 'Configure',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_form_feed', 2),
'page callback' => 'entity_get_form',
'page arguments' => array(2),
'access arguments' => array('administer news feeds'),
'type' => MENU_LOCAL_TASK,
'weight' => 1,
......@@ -250,8 +247,8 @@ function aggregator_menu() {
);
$items['admin/config/services/aggregator/edit/feed/%aggregator_feed'] = array(
'title' => 'Edit feed',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_form_feed', 6),
'page callback' => 'entity_get_form',
'page arguments' => array(6),
'access arguments' => array('administer news feeds'),
'file' => 'aggregator.admin.inc',
);
......@@ -276,7 +273,7 @@ function aggregator_menu() {
* A string with the aggregator category title.
*/
function _aggregator_category_title($category) {
return $category['title'];
return $category->title;
}
/**
......@@ -310,17 +307,18 @@ function aggregator_permission() {
* Queues news feeds for updates once their refresh interval has elapsed.
*/
function aggregator_cron() {
$result = db_query('SELECT * FROM {aggregator_feed} WHERE queued = 0 AND checked + refresh < :time AND refresh <> :never', array(
$result = db_query('SELECT fid FROM {aggregator_feed} WHERE queued = 0 AND checked + refresh < :time AND refresh <> :never', array(
':time' => REQUEST_TIME,
':never' => AGGREGATOR_CLEAR_NEVER
));
$queue = queue('aggregator_feeds');
foreach ($result as $feed) {
foreach ($result->fetchCol() as $fid) {
$feed = aggregator_feed_load($fid);
if ($queue->createItem($feed)) {
// Add timestamp to avoid queueing item more than once.
db_update('aggregator_feed')
->fields(array('queued' => REQUEST_TIME))
->condition('fid', $feed->fid)
->condition('fid', $feed->id())
->execute();
}
}
......@@ -396,99 +394,19 @@ function aggregator_save_category($edit) {
}
}
/**
* Adds/edits/deletes an aggregator feed.
*
* @param $edit
* An associative array describing the feed to be added/edited/deleted.
*
* @return
* The ID of the feed.
*/
function aggregator_save_feed($edit) {
if (!empty($edit['fid'])) {
// An existing feed is being modified, delete the category listings.
db_delete('aggregator_category_feed')
->condition('fid', $edit['fid'])
->execute();
}
if (!empty($edit['fid']) && !empty($edit['title'])) {
db_update('aggregator_feed')
->condition('fid', $edit['fid'])
->fields(array(
'title' => $edit['title'],
'url' => $edit['url'],
'refresh' => $edit['refresh'],
'block' => $edit['block'],
))
->execute();
}
elseif (!empty($edit['fid'])) {
$iids = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $edit['fid']))->fetchCol();
if ($iids) {
db_delete('aggregator_category_item')
->condition('iid', $iids, 'IN')
->execute();
}
db_delete('aggregator_feed')->
condition('fid', $edit['fid'])
->execute();
db_delete('aggregator_item')
->condition('fid', $edit['fid'])
->execute();
// Make sure there is no active block for this feed.
if (module_exists('block')) {
foreach (entity_load_multiple_by_properties('block', array('plugin' => 'aggregator_feed_block:' . $edit['fid'])) as $block) {
$block->delete();
}
}
}
elseif (!empty($edit['title'])) {
$edit['fid'] = db_insert('aggregator_feed')
->fields(array(
'title' => $edit['title'],
'url' => $edit['url'],
'refresh' => $edit['refresh'],
'block' => $edit['block'],
'link' => '',
'description' => '',
'image' => '',
))
->execute();
}
if (!empty($edit['title'])) {
// The feed is being saved, save the categories as well.
if (!empty($edit['category'])) {
foreach ($edit['category'] as $cid => $value) {
if ($value) {
db_insert('aggregator_category_feed')
->fields(array(
'fid' => $edit['fid'],
'cid' => $cid,
))
->execute();
}
}
}
}
return $edit['fid'];
}
/**
* Removes all items from a feed.
*
* @param $feed
* @param \Drupal\aggregator\Plugin\Core\Entity\Feed $feed
* An object describing the feed to be cleared.
*/
function aggregator_remove($feed) {
function aggregator_remove(Feed $feed) {
_aggregator_get_variables();
// Call hook_aggregator_remove() on all modules.
module_invoke_all('aggregator_remove', $feed);
// Reset feed.
db_update('aggregator_feed')
->condition('fid', $feed->fid)
->condition('fid', $feed->id())
->fields(array(
'checked' => 0,
'hash' => '',
......@@ -524,12 +442,12 @@ function _aggregator_get_variables() {
/**
* Checks a news feed for new items.
*
* @param $feed
* @param \Drupal\aggregator\Plugin\Core\Entity\Feed $feed
* An object describing the feed to be refreshed.
*/
function aggregator_refresh($feed) {
function aggregator_refresh(Feed $feed) {
// Store feed URL to track changes.
$feed_url = $feed->url;
$feed_url = $feed->url->value;
list($fetcher, $parser, $processors) = _aggregator_get_variables();
......@@ -547,30 +465,23 @@ function aggregator_refresh($feed) {
// data. If both are equal we say that feed is not updated.
$hash = hash('sha256', $feed->source_string);
if ($success && ($feed->hash != $hash)) {
if ($success && ($feed->hash->value != $hash)) {
// Parse the feed.
if (module_invoke($parser, 'aggregator_parse', $feed)) {
if (empty($feed->link->value)) {
$feed->link->value = $feed->url->value;
}
$feed->hash->value = $hash;
// Update feed with parsed data.
db_merge('aggregator_feed')
->key(array('fid' => $feed->fid))
->fields(array(
'url' => $feed->url,
'link' => empty($feed->link) ? $feed->url : $feed->link,
'description' => empty($feed->description) ? '' : $feed->description,
'image' => empty($feed->image) ? '' : $feed->image,
'hash' => $hash,
'etag' => empty($feed->etag) ? '' : $feed->etag,
'modified' => empty($feed->modified) ? 0 : $feed->modified,
))
->execute();
$feed->save();
// Log if feed URL has changed.
if ($feed->url != $feed_url) {
watchdog('aggregator', 'Updated URL for feed %title to %url.', array('%title' => $feed->title, '%url' => $feed->url));
if ($feed->url->value != $feed_url) {
watchdog('aggregator', 'Updated URL for feed %title to %url.', array('%title' => $feed->label(), '%url' => $feed->url->value));
}
watchdog('aggregator', 'There is new syndicated content from %site.', array('%site' => $feed->title));
drupal_set_message(t('There is new syndicated content from %site.', array('%site' => $feed->title)));
watchdog('aggregator', 'There is new syndicated content from %site.', array('%site' => $feed->label()));
drupal_set_message(t('There is new syndicated content from %site.', array('%site' => $feed->label())));
// If there are items on the feed, let all enabled processors do their work on it.
if (@count($feed->items)) {
......@@ -581,13 +492,13 @@ function aggregator_refresh($feed) {
}
}
else {
drupal_set_message(t('There is no new syndicated content from %site.', array('%site' => $feed->title)));
drupal_set_message(t('There is no new syndicated content from %site.', array('%site' => $feed->label())));
}
// Regardless of successful or not, indicate that this feed has been checked.
db_update('aggregator_feed')
->fields(array('checked' => REQUEST_TIME, 'queued' => 0))
->condition('fid', $feed->fid)
->condition('fid', $feed->id())
->execute();
// Expire old feed items.
......@@ -599,19 +510,14 @@ function aggregator_refresh($feed) {
/**
* Loads an aggregator feed.
*
* @param $fid
* @param int $fid
* The feed id.
*
* @return
* @return \Drupal\aggregator\Plugin\Core\Entity\Feed
* An object describing the feed.
*/
function aggregator_feed_load($fid) {
$feeds = &drupal_static(__FUNCTION__);
if (!isset($feeds[$fid])) {
$feeds[$fid] = db_query('SELECT * FROM {aggregator_feed} WHERE fid = :fid', array(':fid' => $fid))->fetchObject();
}
return $feeds[$fid];
return entity_load('aggregator_feed', $fid);
}
/**
......@@ -626,7 +532,7 @@ function aggregator_feed_load($fid) {
function aggregator_category_load($cid) {
$categories = &drupal_static(__FUNCTION__);
if (!isset($categories[$cid])) {
$categories[$cid] = db_query('SELECT * FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $cid))->fetchAssoc();
$categories[$cid] = db_query('SELECT * FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $cid))->fetchObject();
}
return $categories[$cid];
......
......@@ -5,6 +5,8 @@
* User page callbacks for the Aggregator module.
*/
use Drupal\aggregator\Plugin\Core\Entity\Feed;
/**
* Page callback: Displays the most recent items gathered from any feed.
*
......@@ -24,7 +26,7 @@ function aggregator_page_last() {
/**
* Page callback: Displays all the items captured from the particular feed.
*
* @param $feed
* @param \Drupal\aggregator\Plugin\Core\Entity\Feed $feed
* The feed for which to display all items.
*
* @return string
......@@ -32,9 +34,8 @@ function aggregator_page_last() {
*
* @see aggregator_menu()
*/
function aggregator_page_source($feed) {
drupal_set_title($feed->title);
$feed_source = theme('aggregator_feed_source', array('feed' => $feed));
function aggregator_page_source(Feed $feed) {
$feed_source = entity_view($feed, 'default');
// It is safe to include the fid in the query because it's loaded from the
// database by aggregator_feed_load().
......@@ -73,7 +74,7 @@ function aggregator_page_source_form($form, $form_state, $feed) {
* @ingroup forms
*/
function aggregator_page_category($category) {
drupal_add_feed('aggregator/rss/' . $category['cid'], config('system.site')->get('name') . ' ' . t('aggregator - @title', array('@title' => $category['title'])));
drupal_add_feed('aggregator/rss/' . $category->cid, config('system.site')->get('name') . ' ' . t('aggregator - @title', array('@title' => $category->title)));
// It is safe to include the cid in the query because it's loaded from the
// database by aggregator_category_load().
......@@ -120,46 +121,38 @@ function aggregator_page_category_form($form, $form_state, $category) {
* @return
* An array of the feed items.