Index: modules/aggregator/aggregator.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.admin.inc,v retrieving revision 1.22 diff -u -p -r1.22 aggregator.admin.inc --- modules/aggregator/aggregator.admin.inc 22 Dec 2008 19:38:30 -0000 1.22 +++ modules/aggregator/aggregator.admin.inc 27 Dec 2008 16:05:15 -0000 @@ -10,24 +10,14 @@ * Menu callback; displays the aggregator administration page. */ function aggregator_admin_overview() { - return aggregator_view(); -} - -/** - * Displays the aggregator administration page. - * - * @return - * The page HTML. - */ -function aggregator_view() { - $result = db_query('SELECT f.*, COUNT(i.iid) AS items FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.hash, f.etag, f.modified, f.image, f.block ORDER BY f.title'); - + $result = db_query('SELECT f.*, n.title, COUNT(i.iid) AS items FROM {aggregator_feed} f LEFT JOIN {node} n ON n.nid = f.nid LEFT JOIN {aggregator_item} i ON i.nid = f.nid WHERE n.status = 1 GROUP BY f.nid, n.title, f.url, f.refresh, f.checked, f.link, f.description, f.etag, f.modified, f.image, f.block ORDER BY n.title'); + $output = '

' . t('Feed overview') . '

'; $header = array(t('Title'), t('Items'), t('Last update'), t('Next update'), array('data' => t('Operations'), 'colspan' => '3')); $rows = array(); foreach ($result as $feed) { - $rows[] = array(l($feed->title, "aggregator/sources/$feed->fid"), format_plural($feed->items, '1 item', '@count items'), ($feed->checked ? t('@time ago', array('@time' => format_interval(REQUEST_TIME - $feed->checked))) : t('never')), ($feed->checked ? t('%time left', array('%time' => format_interval($feed->checked + $feed->refresh - REQUEST_TIME))) : t('never')), l(t('edit'), "admin/content/aggregator/edit/feed/$feed->fid"), l(t('remove items'), "admin/content/aggregator/remove/$feed->fid"), l(t('update items'), "admin/content/aggregator/update/$feed->fid")); + $rows[] = array(l($feed->title, "node/$feed->nid"), format_plural($feed->items, '1 item', '@count items'), ($feed->checked ? t('@time ago', array('@time' => format_interval(REQUEST_TIME - $feed->checked))) : t('never')), ($feed->checked ? t('%time left', array('%time' => format_interval($feed->checked + $feed->refresh - REQUEST_TIME))) : t('never')), l(t('edit'), "node/$feed->nid/edit"), l(t('remove items'), "admin/content/aggregator/remove/$feed->nid"), l(t('update items'), "admin/content/aggregator/update/$feed->nid")); } $output .= theme('table', $header, $rows); @@ -45,154 +35,6 @@ function aggregator_view() { return $output; } -/** - * Form builder; Generate a form to add/edit feed sources. - * - * @ingroup forms - * @see aggregator_form_feed_validate() - * @see aggregator_form_feed_submit() - */ -function aggregator_form_feed(&$form_state, $feed = NULL) { - $period = drupal_map_assoc(array(900, 1800, 3600, 7200, 10800, 21600, 32400, 43200, 64800, 86400, 172800, 259200, 604800, 1209600, 2419200), 'format_interval'); - - if (empty($feed->refresh)) { - $feed->refresh = 3600; - } - - $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' => 'textfield', - '#title' => t('URL'), - '#default_value' => isset($feed->url) ? $feed->url : '', - '#maxlength' => 255, - '#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 : 900, - '#options' => $period, - '#description' => t('The length of time between feed updates. Requires a correctly configured cron maintenance task.', 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 configure blocks 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/build/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['submit'] = array( - '#type' => 'submit', - '#value' => t('Save'), - ); - - if (!empty($feed->fid)) { - $form['delete'] = array( - '#type' => 'submit', - '#value' => t('Delete'), - ); - $form['fid'] = array( - '#type' => 'hidden', - '#value' => $feed->fid, - ); - } - - return $form; -} - -/** - * Validate aggregator_form_feed() form submissions. - */ -function aggregator_form_feed_validate($form, &$form_state) { - if ($form_state['values']['op'] == t('Save')) { - // Ensure URL is valid. - if (!valid_url($form_state['values']['url'], TRUE)) { - form_set_error('url', t('The URL %url is invalid. Please enter a fully-qualified URL, such as http://www.example.com/feed.xml.', array('%url' => $form_state['values']['url']))); - } - // 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. Please 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. Please enter a unique URL.', array('%url' => $form_state['values']['url']))); - } - } - } -} - -/** - * Process aggregator_form_feed() form submissions. - * - * @todo Add delete confirmation dialog. - */ -function aggregator_form_feed_submit($form, &$form_state) { - 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/content/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/content/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/content/aggregator')); - drupal_set_message(t('The feed %feed has been added.', array('%feed' => $form_state['values']['title']))); - } -} - function aggregator_admin_remove_feed($form_state, $feed) { return confirm_form( array( @@ -259,7 +101,7 @@ function aggregator_form_opml(&$form_sta // Handling of categories. $options = array_map('check_plain', db_query("SELECT cid, title FROM {aggregator_category} ORDER BY title")->fetchAllKeyed()); if ($options) { - $form['category'] = array( + $form['categories'] = array( '#type' => 'checkboxes', '#title' => t('Categorize news items'), '#options' => $options, @@ -293,6 +135,8 @@ function aggregator_form_opml_validate($ * Process aggregator_form_opml form submissions. */ function aggregator_form_opml_submit($form, &$form_state) { + global $user; + $data = ''; if ($file = file_save_upload('upload')) { $data = file_get_contents($file->filepath); @@ -320,7 +164,7 @@ function aggregator_form_opml_submit($fo } // Check for duplicate titles or URLs. - $result = db_query("SELECT title, url FROM {aggregator_feed} WHERE title = :title OR url = :url", array(':title' => $feed['title'], ':url' => $feed['url'])); + $result = db_query("SELECT n.title, f.url FROM {aggregator_feed} f LEFT JOIN {node} n ON f.nid = n.nid WHERE title = :title OR url = :url", array(':title' => $feed['title'], ':url' => $feed['url'])); foreach ($result as $old) { if (strcasecmp($old->title, $feed['title']) == 0) { drupal_set_message(t('A feed named %title already exists.', array('%title' => $old->title)), 'warning'); @@ -334,7 +178,8 @@ function aggregator_form_opml_submit($fo $form_state['values']['title'] = $feed['title']; $form_state['values']['url'] = $feed['url']; - drupal_execute('aggregator_form_feed', $form_state); + $node = array('type' => 'feed'); + drupal_execute('feed_node_form', $form_state, $node); } $form_state['redirect'] = 'admin/content/aggregator'; @@ -364,6 +209,9 @@ function _aggregator_parse_opml($opml) { if (!empty($item['XMLURL']) && !empty($item['TEXT'])) { $feeds[] = array('title' => $item['TEXT'], 'url' => $item['XMLURL']); } + if (!empty($item['URL']) && !empty($item['TEXT'])) { + $feeds[] = array('title' => $item['TEXT'], 'url' => $item['URL']); + } } } } Index: modules/aggregator/aggregator.fetcher.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.fetcher.inc,v retrieving revision 1.2 diff -u -p -r1.2 aggregator.fetcher.inc --- modules/aggregator/aggregator.fetcher.inc 26 Dec 2008 21:01:57 -0000 1.2 +++ modules/aggregator/aggregator.fetcher.inc 27 Dec 2008 16:05:15 -0000 @@ -40,7 +40,7 @@ function aggregator_aggregator_fetch($fe case 304: db_update('aggregator_feed') ->fields(array('checked' => REQUEST_TIME)) - ->condition('fid', $feed->fid) + ->condition('nid', $feed->nid) ->execute(); drupal_set_message(t('There is no new syndicated content from %site.', array('%site' => $feed->title))); break; @@ -63,7 +63,7 @@ function aggregator_aggregator_fetch($fe $md5 = md5($result->data); if ($feed->hash == $md5) { db_update('aggregator_feed') - ->condition('fid', $feed->fid) + ->condition('nid', $feed->nid) ->fields(array('checked' => REQUEST_TIME)) ->execute(); drupal_set_message(t('There is no new syndicated content from %site.', array('%site' => $feed->title))); Index: modules/aggregator/aggregator.install =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.install,v retrieving revision 1.20 diff -u -p -r1.20 aggregator.install --- modules/aggregator/aggregator.install 22 Dec 2008 19:38:31 -0000 1.20 +++ modules/aggregator/aggregator.install 27 Dec 2008 16:05:15 -0000 @@ -67,11 +67,12 @@ function aggregator_schema() { $schema['aggregator_category_feed'] = array( 'description' => 'Bridge table; maps feeds to categories.', 'fields' => array( - 'fid' => array( + 'nid' => array( 'type' => 'int', + 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, - 'description' => "The feed's {aggregator_feed}.fid.", + 'description' => t("The feed's {aggregator_feed}.nid."), ), 'cid' => array( 'type' => 'int', @@ -80,9 +81,9 @@ function aggregator_schema() { 'description' => 'The {aggregator_category}.cid to which the feed is being assigned.', ) ), - 'primary key' => array('cid', 'fid'), + 'primary key' => array('cid', 'nid'), 'indexes' => array( - 'fid' => array('fid'), + 'nid' => array('nid'), ), ); @@ -111,17 +112,12 @@ function aggregator_schema() { $schema['aggregator_feed'] = array( 'description' => 'Stores feeds to be parsed by the aggregator.', 'fields' => array( - 'fid' => array( - 'type' => 'serial', - 'not null' => TRUE, - 'description' => 'Primary Key: Unique feed ID.', - ), - 'title' => array( - 'type' => 'varchar', - 'length' => 255, + 'nid' => array( + 'type' => 'int', + 'unsigned' => TRUE, 'not null' => TRUE, - 'default' => '', - 'description' => 'Title of the feed.', + 'default' => 0, + 'description' => t("The feed's {node}.nid."), ), 'url' => array( 'type' => 'varchar', @@ -189,10 +185,9 @@ function aggregator_schema() { 'description' => "Number of items to display in the feed's block.", ) ), - 'primary key' => array('fid'), + 'primary key' => array('nid'), 'unique keys' => array( 'url' => array('url'), - 'title' => array('title'), ), ); @@ -204,11 +199,12 @@ function aggregator_schema() { 'not null' => TRUE, 'description' => 'Primary Key: Unique ID for feed item.', ), - 'fid' => array( + 'nid' => array( 'type' => 'int', + 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, - 'description' => 'The {aggregator_feed}.fid to which this item belongs.', + 'description' => t('The {aggregator_feed}.nid to which this item belongs.'), ), 'title' => array( 'type' => 'varchar', @@ -251,7 +247,7 @@ function aggregator_schema() { ), 'primary key' => array('iid'), 'indexes' => array( - 'fid' => array('fid'), + 'nid' => array('nid'), ), ); Index: modules/aggregator/aggregator.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v retrieving revision 1.403 diff -u -p -r1.403 aggregator.module --- modules/aggregator/aggregator.module 22 Dec 2008 19:38:31 -0000 1.403 +++ modules/aggregator/aggregator.module 27 Dec 2008 16:05:15 -0000 @@ -87,14 +87,6 @@ function aggregator_menu() { 'page callback' => 'aggregator_admin_overview', 'access arguments' => array('administer news feeds'), ); - $items['admin/content/aggregator/add/feed'] = array( - 'title' => 'Add feed', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_feed'), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_LOCAL_TASK, - 'parent' => 'admin/content/aggregator', - ); $items['admin/content/aggregator/add/category'] = array( 'title' => 'Add category', 'page callback' => 'drupal_get_form', @@ -194,39 +186,6 @@ function aggregator_menu() { 'type' => MENU_LOCAL_TASK, 'weight' => 1, ); - $items['aggregator/sources/%aggregator_feed'] = array( - 'page callback' => 'aggregator_page_source', - 'page arguments' => array(2), - 'access arguments' => array('access news feeds'), - 'type' => MENU_CALLBACK, - ); - $items['aggregator/sources/%aggregator_feed/view'] = array( - 'title' => 'View', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['aggregator/sources/%aggregator_feed/categorize'] = array( - 'title' => 'Categorize', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_page_source', 2), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_LOCAL_TASK, - ); - $items['aggregator/sources/%aggregator_feed/configure'] = array( - 'title' => 'Configure', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_feed', 2), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 1, - ); - $items['admin/content/aggregator/edit/feed/%aggregator_feed'] = array( - 'title' => 'Edit feed', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_feed', 5), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_CALLBACK, - ); $items['admin/content/aggregator/edit/category/%aggregator_category'] = array( 'title' => 'Edit category', 'page callback' => 'drupal_get_form', @@ -235,6 +194,14 @@ function aggregator_menu() { 'type' => MENU_CALLBACK, ); + $items['node/%node/categorize'] = array( + 'title' => 'Categorize', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_page_source', 1, 'categorize'), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_LOCAL_TASK, + ); + return $items; } @@ -269,7 +236,8 @@ function _aggregator_has_categories() { * Implementation of hook_perm(). */ function aggregator_perm() { - return array( + $perms = node_list_permissions('feed'); + $perms += array( 'administer news feeds' => array( 'title' => t('Administer news feeds'), 'description' => t('Add, edit or delete news feeds that are aggregated to your site.'), @@ -279,6 +247,7 @@ function aggregator_perm() { 'description' => t('View aggregated news feed items.'), ), ); + return $perms; } /** @@ -287,7 +256,7 @@ function aggregator_perm() { * Checks news feeds for updates once their refresh interval has elapsed. */ function aggregator_cron() { - $result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time', array(':time' => REQUEST_TIME)); + $result = db_query('SELECT f.*, n.title FROM {aggregator_feed} f LEFT JOIN {node} n ON n.nid = f.nid WHERE checked + refresh < :time', array(':time' => REQUEST_TIME)); foreach ($result as $feed) { aggregator_refresh($feed); } @@ -302,9 +271,9 @@ function aggregator_block_list() { foreach ($result as $category) { $block['category-' . $category->cid]['info'] = t('!title category latest items', array('!title' => $category->title)); } - $result = db_query('SELECT fid, title FROM {aggregator_feed} WHERE block <> 0 ORDER BY fid'); + $result = db_query('SELECT f.nid, n.title FROM {aggregator_feed} f LEFT JOIN {node} n ON n.nid = f.nid WHERE block <> 0 ORDER BY f.nid'); foreach ($result as $feed) { - $block['feed-' . $feed->fid]['info'] = t('!title feed latest items', array('!title' => $feed->title)); + $block['feed-' . $feed->nid]['info'] = t('!title feed latest items', array('!title' => $feed->title)); } return $block; } @@ -350,10 +319,10 @@ function aggregator_block_view($delta = list($type, $id) = explode('-', $delta); switch ($type) { case 'feed': - if ($feed = db_query('SELECT fid, title, block FROM {aggregator_feed} WHERE block <> 0 AND fid = :fid', array(':fid' => $id))->fetchObject()) { + if ($feed = db_query('SELECT f.nid, n.title, f.block FROM {aggregator_feed} f LEFT JOIN {node} n ON n.nid = f.nid WHERE block <> 0 AND f.nid = :nid', array(':nid' => $id))->fetchObject()) { $block['subject'] = check_plain($feed->title); - $result = db_query_range("SELECT * FROM {aggregator_item} WHERE fid = :fid ORDER BY timestamp DESC, iid DESC", array(':fid' => $id), 0, $feed->block); - $read_more = theme('more_link', url('aggregator/sources/' . $feed->fid), t("View this feed's recent news.")); + $result = db_query_range("SELECT * FROM {aggregator_item} WHERE nid = :nid ORDER BY timestamp DESC, iid DESC", array(':nid' => $id), 0, $feed->block); + $read_more = theme('more_link', url('aggregator/sources/' . $feed->nid), t("View this feed's recent news.")); } break; @@ -379,6 +348,177 @@ function aggregator_block_view($delta = } /** + * Implementation of hook_node_info(). + */ +function aggregator_node_info() { + return array( + 'feed' => array( + 'name' => t('Feed'), + 'base' => 'aggregator', + 'description' => t("Add a feed in RSS, RDF or Atom format."), + 'has_title' => TRUE, + 'title_label' => t('Title'), + 'has_body' => FALSE, + ) + ); +} + +/** + * Implementation of hook_access(). + */ +function aggregator_access($op, $node, $account) { + switch ($op) { + case 'create': + return user_access('create feed content', $account); + case 'update': + return user_access('edit any feed content', $account) || (user_access('edit own feed content', $account) && ($node->uid == $account->uid)); + case 'delete': + return user_access('delete any feed content', $account) || (user_access('delete own feed content', $account) && ($node->uid == $account->uid)); + } +} + +/** + * Implementation of hook_insert(). + */ +function aggregator_insert($node) { + db_insert('aggregator_feed') + ->fields(array( + 'nid' => $node->nid, + 'url' => $node->url, + 'refresh' => $node->refresh, + 'block' => 5, + 'description' => '', + 'image' => '', + )) + ->execute(); + + // The feed is being saved, save the categories as well. + if (!empty($node->categories)) { + foreach ($node->categories as $cid => $value) { + if ($value) { + db_merge('aggregator_category_feed') + ->key(array('nid' => $node->nid)) + ->fields(array( + 'cid' => $cid, + )) + ->execute(); + } + } + } +} + +/** + * Implementation of hook_update(). + */ +function aggregator_update($node) { + // An existing feed is being modified, delete the category listings. + db_delete('aggregator_category_feed') + ->condition('nid', $node->nid) + ->execute(); + + db_update('aggregator_feed') + ->condition('nid', $node->nid) + ->fields(array( + 'url' => $node->url, + 'refresh' => $node->refresh, + )) + ->execute(); + + // The feed is being saved, save the categories as well. + if (!empty($node->categories)) { + foreach ($node->categories as $cid => $value) { + if ($value) { + db_merge('aggregator_category_feed') + ->key(array('nid' => $node->nid)) + ->fields(array( + 'cid' => $cid, + )) + ->execute(); + } + } + } +} + +/** + * Implementation of hook_delete(). + */ +function aggregator_delete($node) { + $iids = db_query('SELECT iid FROM {aggregator_item} WHERE nid = :nid', array(':nid' => $node->nid))->fetchCol(); + if ($iids) { + db_delete('aggregator_category_item') + ->condition('iid', $iids, 'IN') + ->execute(); + } + db_delete('aggregator_feed')-> + condition('nid', $node->nid) + ->execute(); + db_delete('aggregator_item') + ->condition('nid', $node->nid) + ->execute(); + // Make sure there is no active block for this feed. + db_delete('block') + ->condition('module', 'aggregator') + ->condition('delta', 'feed-' . $node->nid) + ->execute(); +} + +/** + * Implementation of hook_load(). + */ +function aggregator_load($nodes) { + /**/ + $result_feeds = db_select('aggregator_feed', 'af') + ->condition('nid', array_keys($nodes), 'IN') + ->fields('af', array('nid', 'url', 'refresh', 'checked', 'link', 'description', 'image', 'etag', 'modified', 'block', 'hash')) + ->execute(); + $result_categories = db_select('aggregator_category_feed', 'ac') + ->condition('nid', array_keys($nodes), 'IN') + ->fields('ac', array('nid', 'cid')) + ->execute(); + + foreach ($result_feeds as $feed) { + $nodes[$feed->nid]->url = $feed->url; + $nodes[$feed->nid]->refresh = $feed->refresh; + $nodes[$feed->nid]->checked = $feed->checked; + $nodes[$feed->nid]->link = $feed->link; + $nodes[$feed->nid]->description = $feed->description; + $nodes[$feed->nid]->image = $feed->image; + $nodes[$feed->nid]->etag = $feed->etag; + $nodes[$feed->nid]->modified = $feed->modified; + $nodes[$feed->nid]->block = $feed->block; + $nodes[$feed->nid]->hash = $feed->hash; + } + + foreach($result_categories as $category) { + $nodes[$feed->nid]->categories = array(); + $nodes[$feed->nid]->categories[] = $category->cid; + } +} + +/** + * Implementation of hook_view(). + */ +function aggregator_view($node, $teaser = FALSE, $page = FALSE) { + $node->content['body'] = array( + '#markup' => theme('aggregator_feed_source', $node), + '#weight' => 1, + ); + + if ($page && isset($node->nid)) { + // It is safe to include the nid in the query because it's loaded from the + // database by aggregator_feed_load. + $items = aggregator_feed_items_load('source', $node); + + $node->content['items'] = array( + '#markup' => _aggregator_page_list($items, arg(3)), + '#weight' => 2, + ); + } + + return $node; +} + +/** * Add/edit/delete aggregator categories. * * @param $edit @@ -428,79 +568,6 @@ function aggregator_save_category($edit) } /** - * Add/edit/delete an aggregator feed. - * - * @param $edit - * An associative array describing the feed to be added/edited/deleted. - */ -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. - db_delete('block') - ->condition('module', 'aggregator') - ->condition('delta', 'feed-' . $edit['fid']) - ->execute(); - } - elseif (!empty($edit['title'])) { - $edit['fid'] = db_insert('aggregator_feed') - ->fields(array( - 'title' => $edit['title'], - 'url' => $edit['url'], - 'refresh' => $edit['refresh'], - 'block' => $edit['block'], - '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_merge('aggregator_category_feed') - ->key(array('fid' => $edit['fid'])) - ->fields(array( - 'cid' => $cid, - )) - ->execute(); - } - } - } - } -} - -/** * Removes all items from a feed. * * @param $feed @@ -511,10 +578,11 @@ function aggregator_remove($feed) { module_invoke_all('aggregator_remove', $feed); // Reset feed. db_merge('aggregator_feed') - ->key(array('fid' => $feed->fid)) + ->key(array('nid' => $feed->nid)) ->fields(array( 'checked' => 0, 'hash' => '', + 'etag' => '', 'modified' => 0, 'description' => $feed->description, 'image' => $feed->image, @@ -555,18 +623,18 @@ function aggregator_refresh($feed) { /** * Load an aggregator feed. * - * @param $fid - * The feed id. + * @param $nid + * The feed nid. * @return * An object describing the feed. */ -function aggregator_feed_load($fid) { +function aggregator_feed_load($nid) { static $feeds; - if (!isset($feeds[$fid])) { - $feeds[$fid] = db_query('SELECT * FROM {aggregator_feed} WHERE fid = :fid', array(':fid' => $fid))->fetchObject(); + if (!isset($feeds[$nid])) { + $feeds[$nid] = node_load($nid); } - return $feeds[$fid]; + return $feeds[$nid]; } /** Index: modules/aggregator/aggregator.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.pages.inc,v retrieving revision 1.23 diff -u -p -r1.23 aggregator.pages.inc --- modules/aggregator/aggregator.pages.inc 22 Dec 2008 19:38:31 -0000 1.23 +++ modules/aggregator/aggregator.pages.inc 27 Dec 2008 16:05:15 -0000 @@ -7,6 +7,115 @@ */ /** + * Implementation of hook_form(). + */ +function aggregator_form(&$node) { + global $user; + + $admin = user_access('administer nodes') || user_access('edit any feed content') || (user_access('edit own feed content') && $user->uid == $node->uid); + + // The site admin can decide if this node type has a title and body, and how + // the fields should be labeled. We need to load these settings so we can + // build the node form correctly. + $type = node_get_types('type', $node); + + if ($type->has_title) { + $form['title'] = array( + '#type' => 'textfield', + '#title' => check_plain($type->title_label), + '#description' => t('The name of the feed (or the name of the website providing the feed).'), + '#default_value' => $node->title, + '#maxlength' => 255, + '#required' => TRUE, + '#weight' => -5 + ); + } + + if ($type->has_body) { + // In Drupal 6, we can use node_body_field() to get the body and filter + // elements. This replaces the old textarea + filter_form() method of + // setting this up. It will also ensure the teaser splitter gets set up + // properly. + $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count); + } + + $period = drupal_map_assoc(array(900, 1800, 3600, 7200, 10800, 21600, 32400, 43200, 64800, 86400, 172800, 259200, 604800, 1209600, 2419200), 'format_interval'); + + $form['url'] = array( + '#type' => 'textfield', + '#title' => t('URL'), + '#default_value' => isset($node->url) ? $node->url : '', + '#maxlength' => 255, + '#description' => t('The fully-qualified URL of the feed.'), + '#required' => TRUE, + '#weight' => -4 + ); + + $form['settings'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#title' => t('Feed settings'), + '#weight' => -3, + '#access' => $admin, + ); + $form['settings']['refresh'] = array( + '#type' => 'select', + '#title' => t('Update interval'), + '#default_value' => isset($node->refresh) ? $node->refresh : 3600, + '#options' => $period, + '#description' => t('The length of time between feed updates. (Requires a correctly configured cron maintenance task.)', array('@cron' => url('admin/reports/status'))), + ); + + // Handling of categories. + $options = array(); + $values = isset($node->categories) ? $node->categories : array(); + $categories = db_query('SELECT cid, title FROM {aggregator_category} ORDER BY title'); + while ($category = db_fetch_object($categories)) { + $options[$category->cid] = check_plain($category->title); + if (isset($node->categories) && in_array($category->cid, $node->categories)) { + $values[] = $category->cid; + } + } + if ($options) { + $form['settings']['categories'] = 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.'), + ); + } + + return $form; +} + +/** + * Implementation of hook_validate(). + */ +function aggregator_validate(&$node) { + // Ensure URL is valid. + if (!valid_url($node->url, TRUE)) { + form_set_error('url', t('The URL %url is invalid. Please enter a fully-qualified URL, such as http://www.example.com/feed.xml.', array('%url' => $node->url))); + } + // Check for duplicate titles. + if (isset($node->nid)) { + $result_title = db_query("SELECT title FROM {node} WHERE title = '%s' AND nid <> %d AND type = 'feed'", $node->title, $node->nid)->fetchField(); + $result_url = db_query("SELECT url FROM {aggregator_feed} WHERE url = '%s' AND nid <> %d", $node->url, $node->nid)->fetchField(); + } + else { + $result_title = db_query("SELECT title FROM {node} WHERE title = '%s' AND type = 'feed'", $node->title)->fetchField(); + $result_url = db_query("SELECT url FROM {aggregator_feed} WHERE url = '%s'", $node->url)->fetchField(); + } + + if (strcasecmp($result_title, $node->title) == 0) { + form_set_error('title', t('A feed named %feed already exists. Please enter a unique title.', array('%feed' => $node->title))); + } + if (strcasecmp($result_url, $node->url) == 0) { + form_set_error('url', t('A feed with this URL %url already exists. Please enter a unique URL.', array('%url' => $node->url))); + } +} + +/** * Menu callback; displays the most recent items gathered from any feed. * * @return @@ -43,7 +152,7 @@ function aggregator_page_source($arg1, $ // database by aggregator_feed_load. $items = aggregator_feed_items_load('source', $feed); - return _aggregator_page_list($items, arg(3), $feed_source); + return _aggregator_page_list($items, arg(2), $feed_source); } /** @@ -87,13 +196,13 @@ function aggregator_feed_items_load($typ $range_limit = 20; switch ($type) { case 'sum': - $result = db_query_range('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_item} i INNER JOIN {aggregator_feed} f ON i.fid = f.fid ORDER BY i.timestamp DESC, i.iid DESC', 0, $range_limit); + $result = db_query_range('SELECT i.*, n.title AS ftitle, f.link AS flink FROM {aggregator_item} i INNER JOIN {aggregator_feed} f ON i.nid = f.nid LEFT JOIN {node} n ON f.nid = n.nid ORDER BY i.timestamp DESC, i.iid DESC', 0, $range_limit); break; case 'source': - $result = db_query_range('SELECT * FROM {aggregator_item} WHERE fid = :fid ORDER BY timestamp DESC, iid DESC', array(':fid' => $data->fid), 0, $range_limit); + $result = db_query_range('SELECT * FROM {aggregator_item} WHERE nid = :nid ORDER BY timestamp DESC, iid DESC', array(':nid' => $data->nid), 0, $range_limit); break; case 'category': - $result = db_query_range('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_category_item} c LEFT JOIN {aggregator_item} i ON c.iid = i.iid LEFT JOIN {aggregator_feed} f ON i.fid = f.fid WHERE cid = :cid ORDER BY timestamp DESC, i.iid DESC', array(':cid' => $data['cid']), 0, $range_limit); + $result = db_query_range('SELECT i.*, n.title AS ftitle, f.link AS flink FROM {aggregator_category_item} c LEFT JOIN {aggregator_item} i ON c.iid = i.iid LEFT JOIN {aggregator_feed} f ON i.nid = f.nid LEFT JOIN {node} n ON f.nid = n.nid WHERE cid = :cid ORDER BY timestamp DESC, i.iid DESC', array(':cid' => $data['cid']), 0, $range_limit); break; } @@ -278,8 +387,8 @@ function template_preprocess_aggregator_ $variables['source_url'] = ''; $variables['source_title'] = ''; - if (isset($item->ftitle) && isset($item->fid)) { - $variables['source_url'] = url("aggregator/sources/$item->fid"); + if (isset($item->ftitle) && isset($item->nid)) { + $variables['source_url'] = url("node/$item->nid"); $variables['source_title'] = check_plain($item->ftitle); } if (date('Ymd', $item->timestamp) == date('Ymd')) { @@ -299,19 +408,19 @@ function template_preprocess_aggregator_ * Menu callback; displays all the feeds used by the aggregator. */ function aggregator_page_sources() { - $result = db_query('SELECT f.fid, f.title, f.description, f.image, MAX(i.timestamp) AS last FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.description, f.image ORDER BY last DESC, f.title'); + $result = db_query('SELECT f.nid, n.title, f.description, f.image, MAX(i.timestamp) AS last FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.nid = i.nid LEFT JOIN {node} n ON f.nid = n.nid GROUP BY f.nid, n.title, f.description, f.image ORDER BY last DESC, n.title'); $output = ''; foreach ($result as $feed) { // Most recent items: $summary_items = array(); if (variable_get('aggregator_summary_items', 3)) { - $items = db_query_range('SELECT i.title, i.timestamp, i.link FROM {aggregator_item} i WHERE i.fid = :fid ORDER BY i.timestamp DESC', array(':fid' => $feed->fid), 0, variable_get('aggregator_summary_items', 3)); + $items = db_query_range('SELECT i.title, i.timestamp, i.link FROM {aggregator_item} i WHERE i.nid = :nid ORDER BY i.timestamp DESC', array(':nid' => $feed->nid), 0, variable_get('aggregator_summary_items', 3)); foreach ($items as $item) { $summary_items[] = theme('aggregator_summary_item', $item); } } - $feed->url = url('aggregator/sources/' . $feed->fid); + $feed->url = url('node/' . $feed->nid); $output .= theme('aggregator_summary_items', $summary_items, $feed); } $output .= theme('feed_icon', url('aggregator/opml'), t('OPML feed')); @@ -329,7 +438,7 @@ function aggregator_page_categories() { foreach ($result as $category) { if (variable_get('aggregator_summary_items', 3)) { $summary_items = array(); - $items = db_query_range('SELECT i.title, i.timestamp, i.link, f.title as feed_title, f.link as feed_link FROM {aggregator_category_item} ci LEFT JOIN {aggregator_item} i ON i.iid = ci.iid LEFT JOIN {aggregator_feed} f ON i.fid = f.fid WHERE ci.cid = :cid ORDER BY i.timestamp DESC', array(':cid' => $category->cid), 0, variable_get('aggregator_summary_items', 3)); + $items = db_query_range('SELECT i.title, i.timestamp, i.link, n.title as feed_title, f.link as feed_link FROM {aggregator_category_item} ci LEFT JOIN {aggregator_item} i ON i.iid = ci.iid LEFT JOIN {aggregator_feed} f ON i.nid = f.nid LEFT JOIN {node} n ON n.nid = f.nid WHERE ci.cid = :cid ORDER BY i.timestamp DESC', array(':cid' => $category->cid), 0, variable_get('aggregator_summary_items', 3)); foreach ($items as $item) { $summary_items[] = theme('aggregator_summary_item', $item); } @@ -349,12 +458,12 @@ function aggregator_page_rss() { // arg(2) is the passed cid, only select for that category. if (arg(2)) { $category = db_query('SELECT cid, title FROM {aggregator_category} WHERE cid = :cid', array(':cid' => arg(2)))->fetchObject(); - $result = db_query_range('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_category_item} c LEFT JOIN {aggregator_item} i ON c.iid = i.iid LEFT JOIN {aggregator_feed} f ON i.fid = f.fid WHERE cid = :cid ORDER BY timestamp DESC, i.iid DESC', array(':cid' => $category->cid), 0, variable_get('feed_default_items', 10)); + $result = db_query_range('SELECT i.*, n.title AS ftitle, f.link AS flink FROM {aggregator_category_item} c LEFT JOIN {aggregator_item} i ON c.iid = i.iid LEFT JOIN {aggregator_feed} f ON i.nid = f.nid LEFT JOIN {node} n ON n.nid = f.nid WHERE cid = :cid ORDER BY timestamp DESC, i.iid DESC', array(':cid' => $category->cid), 0, variable_get('feed_default_items', 10)); } // Or, get the default aggregator items. else { $category = NULL; - $result = db_query_range('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_item} i INNER JOIN {aggregator_feed} f ON i.fid = f.fid ORDER BY i.timestamp DESC, i.iid DESC', 0, variable_get('feed_default_items', 10)); + $result = db_query_range('SELECT i.*, n.title AS ftitle, f.link AS flink FROM {aggregator_item} i INNER JOIN {aggregator_feed} f ON i.nid = f.nid LEFT JOIN {node} n ON f.nid = n.nid ORDER BY i.timestamp DESC, i.iid DESC', 0, variable_get('feed_default_items', 10)); } $feeds = $result->fetchAll(); @@ -413,10 +522,10 @@ function theme_aggregator_page_rss($feed */ function aggregator_page_opml($cid = NULL) { if ($cid) { - $result = db_query('SELECT f.title, f.url FROM {aggregator_feed} f LEFT JOIN {aggregator_category_feed} c on f.fid = c.fid WHERE c.cid = :cid ORDER BY title', array(':cid' => $cid)); + $result = db_query('SELECT n.title, f.url FROM {aggregator_feed} f LEFT JOIN {aggregator_category_feed} c on f.nid = c.nid LEFT JOIN {node} n ON n.nid = f.nid WHERE c.cid = :cid ORDER BY title', array(':cid' => $cid)); } else { - $result = db_query('SELECT * FROM {aggregator_feed} ORDER BY title'); + $result = db_query('SELECT * FROM {aggregator_feed} f LEFT JOIN {node} n ON n.nid = f.nid'); } $feeds = $result->fetchAll(); Index: modules/aggregator/aggregator.parser.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.parser.inc,v retrieving revision 1.1 diff -u -p -r1.1 aggregator.parser.inc --- modules/aggregator/aggregator.parser.inc 22 Dec 2008 19:38:31 -0000 1.1 +++ modules/aggregator/aggregator.parser.inc 27 Dec 2008 16:05:16 -0000 @@ -46,7 +46,7 @@ function aggregator_aggregator_parse($fe $etag = empty($feed->http_headers['ETag']) ? '' : $feed->http_headers['ETag']; // Update the feed data. db_merge('aggregator_feed') - ->key(array('fid' => $feed->fid)) + ->key(array('nid' => $feed->nid)) ->fields(array( 'url' => $feed->url, 'checked' => REQUEST_TIME, Index: modules/aggregator/aggregator.processor.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.processor.inc,v retrieving revision 1.1 diff -u -p -r1.1 aggregator.processor.inc --- modules/aggregator/aggregator.processor.inc 22 Dec 2008 19:38:31 -0000 1.1 +++ modules/aggregator/aggregator.processor.inc 27 Dec 2008 16:05:16 -0000 @@ -27,18 +27,18 @@ function aggregator_aggregator_process($ // 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'])) { - $entry = db_query("SELECT iid, timestamp FROM {aggregator_item} WHERE fid = :fid AND guid = :guid", array(':fid' => $feed->fid, ':guid' => $item['GUID']))->fetchObject(); + $entry = db_query("SELECT iid, timestamp FROM {aggregator_item} WHERE nid = :nid AND guid = :guid", array(':nid' => $feed->nid, ':guid' => $item['GUID']))->fetchObject(); } elseif ($item['LINK'] && $item['LINK'] != $feed->link && $item['LINK'] != $feed->url) { - $entry = db_query("SELECT iid, timestamp FROM {aggregator_item} WHERE fid = :fid AND link = :link", array(':fid' => $feed->fid, ':link' => $item['LINK']))->fetchObject(); + $entry = db_query("SELECT iid, timestamp FROM {aggregator_item} WHERE nid = :nid AND link = :link", array(':nid' => $feed->nid, ':link' => $item['LINK']))->fetchObject(); } else { - $entry = db_query("SELECT iid, timestamp FROM {aggregator_item} WHERE fid = :fid AND title = :title", array(':fid' => $feed->fid, ':title' => $item['TITLE']))->fetchObject(); + $entry = db_query("SELECT iid, timestamp FROM {aggregator_item} WHERE nid = :nid AND title = :title", array(':nid' => $feed->nid, ':title' => $item['TITLE']))->fetchObject(); } if (!$item['TIMESTAMP']) { $item['TIMESTAMP'] = isset($entry->timestamp) ? $entry->timestamp : REQUEST_TIME; } - aggregator_save_item(array('iid' => (isset($entry->iid) ? $entry->iid : ''), 'fid' => $feed->fid, 'timestamp' => $item['TIMESTAMP'], 'title' => $item['TITLE'], 'link' => $item['LINK'], 'author' => $item['AUTHOR'], 'description' => $item['DESCRIPTION'], 'guid' => $item['GUID'])); + aggregator_save_item(array('iid' => (isset($entry->iid) ? $entry->iid : ''), 'nid' => $feed->nid, 'timestamp' => $item['TIMESTAMP'], 'title' => $item['TITLE'], 'link' => $item['LINK'], 'author' => $item['AUTHOR'], 'description' => $item['DESCRIPTION'], 'guid' => $item['GUID'])); } } } @@ -48,14 +48,14 @@ function aggregator_aggregator_process($ * Implementation of hook_aggregator_remove(). */ function aggregator_aggregator_remove($feed) { - $iids = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchCol(); + $iids = db_query('SELECT iid FROM {aggregator_item} WHERE nid = :nid', array(':nid' => $feed->nid))->fetchCol(); if ($iids) { db_delete('aggregator_category_item') ->condition('iid', $iids, 'IN') ->execute(); } db_delete('aggregator_item') - ->condition('fid', $feed->fid) + ->condition('nid', $feed->nid) ->execute(); drupal_set_message(t('The news items from %site have been removed.', array('%site' => $feed->title))); @@ -130,7 +130,7 @@ function aggregator_save_item($edit) { 'description' => $edit['description'], 'guid' => $edit['guid'], 'timestamp' => $edit['timestamp'], - 'fid' => $edit['fid'], + 'nid' => $edit['nid'], )) ->execute(); } @@ -144,11 +144,11 @@ function aggregator_save_item($edit) { } elseif ($edit['title'] && $edit['link']) { // file the items in the categories indicated by the feed - $result = db_query('SELECT cid FROM {aggregator_category_feed} WHERE fid = :fid', array(':fid' => $edit['fid'])); + $result = db_query('SELECT cid FROM {aggregator_category_feed} WHERE nid = :nid', array(':nid' => $edit['nid'])); foreach ($result as $category) { db_merge('aggregator_category_item') + ->key(array('cid' => $category->cid)) ->fields(array( - 'cid' => $category->cid, 'iid' => $edit['iid'], )) ->execute(); @@ -165,7 +165,7 @@ function aggregator_save_item($edit) { function aggregator_expire($feed) { // Remove all items that are older than flush item timer. $age = REQUEST_TIME - variable_get('aggregator_clear', 9676800); - $iids = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid AND timestamp < :timestamp', array(':fid' => $feed->fid, ':timestamp' => $age))->fetchCol(); + $iids = db_query('SELECT iid FROM {aggregator_item} WHERE nid = :nid AND timestamp < :timestamp', array(':nid' => $feed->nid, ':timestamp' => $age))->fetchCol(); if ($iids) { db_delete('aggregator_category_item') ->condition('iid', $iids, 'IN') Index: modules/aggregator/aggregator.test =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.test,v retrieving revision 1.17 diff -u -p -r1.17 aggregator.test --- modules/aggregator/aggregator.test 4 Dec 2008 11:11:59 -0000 1.17 +++ modules/aggregator/aggregator.test 27 Dec 2008 16:05:16 -0000 @@ -6,7 +6,7 @@ class AggregatorTestCase extends DrupalW function setUp() { parent::setUp('aggregator'); - $web_user = $this->drupalCreateUser(array('administer news feeds', 'access news feeds')); + $web_user = $this->drupalCreateUser(array('administer news feeds', 'access news feeds', 'create feed content', 'delete any feed content', 'edit any feed content')); $this->drupalLogin($web_user); } @@ -17,10 +17,10 @@ class AggregatorTestCase extends DrupalW */ function createFeed() { $edit = $this->getFeedEditArray(); - $this->drupalPost('admin/content/aggregator/add/feed', $edit, t('Save')); - $this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), t('The feed !name has been added.', array('!name' => $edit['title']))); + $this->drupalPost('node/add/feed', $edit, t('Save')); + $this->assertRaw(t('Feed %name has been created.', array('%name' => $edit['title'])), t('The feed !name has been added.', array('!name' => $edit['title']))); - $feed = db_query("SELECT * FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $edit['title'], ':url' => $edit['url']))->fetch(); + $feed = db_query("SELECT f.*, n.title FROM {aggregator_feed} f LEFT JOIN {node} n ON n.nid = f.nid WHERE n.title = :title AND f.url = :url", array(':title' => $edit['title'], ':url' => $edit['url']))->fetch(); $this->assertTrue(!empty($feed), t('The feed found in database.')); return $feed; } @@ -31,8 +31,8 @@ class AggregatorTestCase extends DrupalW * @param object $feed Feed object representing the feed. */ function deleteFeed($feed) { - $this->drupalPost('admin/content/aggregator/edit/feed/' . $feed->fid, array(), t('Delete')); - $this->assertRaw(t('The feed %title has been deleted.', array('%title' => $feed->title)), t('Feed deleted successfully.')); + $this->drupalPost("node/$feed->nid/delete", array(), t('Delete')); + $this->assertRaw(t('Feed %title has been deleted.', array('%title' => $feed->title)), t('Feed deleted successfully.')); } /** @@ -52,7 +52,7 @@ class AggregatorTestCase extends DrupalW } /** - * Update feed items (simulate click to admin/content/aggregator/update/$fid). + * Update feed items (simulate click to admin/content/aggregator/update/$nid). * * @param object $feed Feed object representing the feed. */ @@ -67,11 +67,10 @@ class AggregatorTestCase extends DrupalW $feed_count = $feed_count > 10 ? 10 : $feed_count; // Refresh the feed (simulated link click). - $this->drupalGet('admin/content/aggregator/update/' . $feed->fid); + $this->drupalGet('admin/content/aggregator/update/' . $feed->nid); // Ensure we have the right number of items. - $result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid)); - $items = array(); + $result = db_query('SELECT iid FROM {aggregator_item} WHERE nid = :nid', array(':nid' => $feed->nid)); $feed->items = array(); foreach ($result as $item) { $feed->items[] = $item->iid; @@ -86,7 +85,7 @@ class AggregatorTestCase extends DrupalW * @param object $feed Feed object representing the feed. */ function removeFeedItems($feed) { - $this->drupalPost('admin/content/aggregator/remove/' . $feed->fid, array(), t('Remove items')); + $this->drupalPost('admin/content/aggregator/remove/' . $feed->nid, array(), t('Remove items')); $this->assertRaw(t('The news items from %title have been removed.', array('%title' => $feed->title)), t('Feed items removed.')); } @@ -97,7 +96,7 @@ class AggregatorTestCase extends DrupalW */ function getFeedCategories($feed) { // add the categories to the feed so we can use them - $result = db_query('SELECT cid FROM {aggregator_category_feed} WHERE fid = :fid', array(':fid' => $feed->fid)); + $result = db_query('SELECT cid FROM {aggregator_category_feed} WHERE nid = :nid', array(':nid' => $feed->nid)); foreach ($result as $category) { $feed->categories[] = $category->cid; } @@ -111,7 +110,7 @@ class AggregatorTestCase extends DrupalW * @return boolean Feed is unique. */ function uniqueFeed($feed_name, $feed_url) { - $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed_name, ':url' => $feed_url))->fetchField(); + $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} f LEFT JOIN {node} n ON f.nid = n.nid WHERE n.title = :title AND f.url = :url", array(':title' => $feed_name, ':url' => $feed_url))->fetchField(); return (1 == $result); } @@ -182,7 +181,8 @@ EOF; - + + EOF; @@ -241,11 +241,11 @@ class AddFeedTestCase extends Aggregator $feed = $this->createFeed(); // Check feed data. - $this->assertEqual($this->getUrl(), url('admin/content/aggregator/add/feed', array('absolute' => TRUE)), t('Directed to correct url.')); + $this->assertEqual($this->getUrl(), url('node/' . $feed->nid, array('absolute' => TRUE)), t('Directed to correct url.')); $this->assertTrue($this->uniqueFeed($feed->title, $feed->url), t('The feed is unique.')); // Check feed source. - $this->drupalGet('aggregator/sources/' . $feed->fid); + $this->drupalGet('node/' . $feed->nid); $this->assertResponse(200, t('Feed source exists.')); $this->assertText($feed->title, t('Page title')); @@ -277,15 +277,15 @@ class UpdateFeedTestCase extends Aggrega if (isset($feed->{$same_field})) { $edit[$same_field] = $feed->{$same_field}; } - $this->drupalPost('admin/content/aggregator/edit/feed/' . $feed->fid, $edit, t('Save')); - $this->assertRaw(t('The feed %name has been updated.', array('%name' => $edit['title'])), t('The feed %name has been updated.', array('%name' => $edit['title']))); + $this->drupalPost('node/' . $feed->nid . '/edit', $edit, t('Save')); + $this->assertRaw(t('Feed %name has been updated.', array('%name' => $edit['title'])), t('The feed %name has been updated.', array('%name' => $edit['title']))); // Check feed data. - $this->assertEqual($this->getUrl(), url('admin/content/aggregator/', array('absolute' => TRUE))); + $this->assertEqual($this->getUrl(), url('node/' . $feed->nid, array('absolute' => TRUE))); $this->assertTrue($this->uniqueFeed($edit['title'], $edit['url']), t('The feed is unique.')); // Check feed source. - $this->drupalGet('aggregator/sources/' . $feed->fid); + $this->drupalGet('node/' . $feed->nid); $this->assertResponse(200, t('Feed source exists.')); $this->assertText($edit['title'], t('Page title')); @@ -315,11 +315,11 @@ class RemoveFeedTestCase extends Aggrega $this->deleteFeed($feed); // Check feed source. - $this->drupalGet('aggregator/sources/' . $feed->fid); + $this->drupalGet('node/' . $feed->nid); $this->assertResponse(404, t('Deleted feed source does not exists.')); // Check database for feed. - $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed->title, ':url' => $feed->url))->fetchField(); + $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} f LEFT JOIN {node} n ON f.nid = n.nid WHERE n.title = :title AND f.url = :url", array(':title' => $feed->title, ':url' => $feed->url))->fetchField(); $this->assertFalse($result, t('Feed not found in database')); } } @@ -355,18 +355,18 @@ class UpdateFeedItemTestCase extends Agg $this->drupalGet($edit['url']); $this->assertResponse(array(200), t('URL !url is accessible', array('!url' => $edit['url']))); - $this->drupalPost('admin/content/aggregator/add/feed', $edit, t('Save')); - $this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), t('The feed !name has been added.', array('!name' => $edit['title']))); + $this->drupalPost('node/add/feed', $edit, t('Save')); + $this->assertRaw(t('Feed %name has been created.', array('%name' => $edit['title'])), t('The feed !name has been added.', array('!name' => $edit['title']))); $feed = db_query("SELECT * FROM {aggregator_feed} WHERE url = :url", array(':url' => $edit['url']))->fetchObject(); - $this->drupalGet('admin/content/aggregator/update/' . $feed->fid); + $this->drupalGet('admin/content/aggregator/update/' . $feed->nid); - $before = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(); + $before = db_query('SELECT timestamp FROM {aggregator_item} WHERE nid = :nid', array(':nid' => $feed->nid))->fetchField(); // Sleep for 3 second. sleep(3); db_update('aggregator_feed') - ->condition('fid', $feed->fid) + ->condition('nid', $feed->nid) ->fields(array( 'checked' => 0, 'hash' => '', @@ -374,9 +374,9 @@ class UpdateFeedItemTestCase extends Agg 'modified' => 0, )) ->execute(); - $this->drupalGet('admin/content/aggregator/update/' . $feed->fid); + $this->drupalGet('admin/content/aggregator/update/' . $feed->nid); - $after = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(); + $after = db_query('SELECT timestamp FROM {aggregator_item} WHERE nid = :nid', array(':nid' => $feed->nid))->fetchField(); $this->assertTrue($before === $after, t('Publish timestamp of feed item was not updated (!before === !after)', array('!before' => $before, '!after' => $after))); } @@ -400,7 +400,7 @@ class RemoveFeedItemTestCase extends Agg // Add and remove feed items and ensure that the count is zero. $this->updateFeedItems($feed); $this->removeFeedItems($feed); - $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(); + $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE nid = :nid', array(':nid' => $feed->nid))->fetchField(); $this->assertTrue($count == 0); // Delete feed. @@ -489,7 +489,7 @@ class ImportOPMLTestCase extends Aggrega $this->assertFieldByName('files[upload]', '', t('Looking for file upload field.')); $this->assertFieldByName('remote', '', t('Looking for remote URL field.')); $this->assertFieldByName('refresh', '', t('Looking for refresh field.')); - $this->assertFieldByName("category[$cid]", $cid, t('Looking for category field.')); + $this->assertFieldByName("categories[$cid]", $cid, t('Looking for category field.')); } /** @@ -554,7 +554,7 @@ class ImportOPMLTestCase extends Aggrega $form = array( 'files[upload]' => $this->getValidOpml($feeds), 'refresh' => '900', - 'category[1]' => $category, + 'categories[1]' => $category, ); $this->drupalPost('admin/content/aggregator/add/opml', $form, t('Import')); $this->assertRaw(t('A feed with the URL %url already exists.', array('%url' => $feeds[0]['url'])), t('Verifying that a duplicate URL was identified')); @@ -563,7 +563,7 @@ class ImportOPMLTestCase extends Aggrega $after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField(); $this->assertEqual($after, 2, t('Verifying that two distinct feeds were added.')); - $feeds_from_db = db_query("SELECT f.title, f.url, f.refresh, cf.cid FROM {aggregator_feed} f LEFT JOIN {aggregator_category_feed} cf ON f.fid = cf.fid"); + $feeds_from_db = db_query("SELECT n.title, f.url, f.refresh, cf.cid FROM {aggregator_feed} f LEFT JOIN {aggregator_category_feed} cf ON cf.nid = f.nid LEFT JOIN {node} n ON n.nid = f.nid"); $refresh = $category = TRUE; foreach ($feeds_from_db as $feed) { $title[$feed->url] = $feed->title;