diff --git a/feeds.module b/feeds.module index 7cded50..78d9485 100644 --- a/feeds.module +++ b/feeds.module @@ -427,26 +427,34 @@ function feeds_theme() { * Node object or FeedsImporter id. */ function feeds_access($action, $param) { + $importer_ids = array(); if (!in_array($action, array('import', 'clear', 'unlock'))) { // If $action is not one of the supported actions, we return access denied. return FALSE; } - $importer_id = FALSE; if (is_string($param)) { - $importer_id = $param; + // If checking the access of a single importer build the array manually. + $importer_ids[$param] = $param; } elseif ($param instanceof FeedsImporter) { - $importer_id = $param->id; + $importer_ids[$param->id] = $param->id; } elseif ($param->type) { - $importer_id = feeds_get_importer_id($param->type); - } - - // Check for permissions if feed id is present, otherwise return FALSE. - if ($importer_id) { - if (user_access('administer feeds') || user_access("{$action} {$importer_id} feeds")) { - return TRUE; + // If checking the access for a content type, + // check all importers available for it. + $importer_ids = feeds_get_importer_ids($param->type); + } + + // Loop through all importers. if the user has access to one, + // they have access to the item. + $administer_feeds = user_access('administer feeds'); + foreach ($importer_ids as $importer_id) { + // Check for permissions if feed id is present, otherwise return FALSE. + if ($importer_id) { + if ($administer_feeds || user_access($action . ' ' . $importer_id . ' feeds')) { + return TRUE; + } } } return FALSE; @@ -486,7 +494,7 @@ function feeds_exit() { foreach ($jobs as $job) { if (!isset($job['fetcher']) || !isset($job['source'])) { continue; - } + } $job['fetcher']->subscribe($job['source']); } @@ -581,10 +589,24 @@ function feeds_entity_delete($entity, $type) { } /** + * Implements hook_node_prepare(). + */ +function feeds_node_prepare($node) { + if ($importer_ids = feeds_get_importer_ids($node->type)) { + $node->feeds = array(); + foreach ($importer_ids as $importer_id) { + $source = feeds_source($importer_id, empty($node->nid) ? 0 : $node->nid); + $node->feeds[$importer_id] = array(); + $node->feeds[$importer_id] += $source->configDefaults(); + } + } +} + +/** * Implements hook_node_validate(). */ function feeds_node_validate($node, $form, &$form_state) { - if (!$importer_id = feeds_get_importer_id($node->type)) { + if (!$importer_ids = feeds_get_importer_ids($node->type)) { return; } // Keep a copy of the title for subsequent node creation stages. @@ -593,32 +615,35 @@ function feeds_node_validate($node, $form, &$form_state) { $last_title = &drupal_static('feeds_node_last_title'); $last_feeds = &drupal_static('feeds_node_last_feeds'); + // Node module magically moved $form['feeds'] to $node->feeds :P. + // configFormValidate may modify $last_feed, smuggle it to update/insert stage + // through a static variable. + $last_feeds = isset($node->feeds) ? $node->feeds : array(); + + $trimmed_node_title = trim($node->title); // On validation stage we are working with a FeedsSource object that is // not tied to a nid - when creating a new node there is no // $node->nid at this stage. $source = feeds_source($importer_id); - - // Node module magically moved $form['feeds'] to $node->feeds :P. - // configFormValidate may modify $last_feed, smuggle it to update/insert stage - // through a static variable. - $last_feeds = $node->feeds; - $source->configFormValidate($last_feeds); - - // Check if title form element is hidden. - $title_hidden = (isset($form['title']['#access']) && !$form['title']['#access']); - - // If the node title is empty and the title form element wasn't hidden, try to - // retrieve the title from the feed. - if (isset($node->title) && trim($node->title) == '' && !$title_hidden) { - try { - $source->addConfig($last_feeds); - if (!$last_title = $source->preview()->title) { - throw new Exception(); + foreach ($importer_ids as $importer_id) { + $class = get_class(feeds_importer($importer_id)->fetcher); + if (!$form['feeds'][$importer_id][$class]['source']['#required']) break; + + $source = feeds_source($importer_id); + $source->configFormValidate($last_feeds[$importer_id]); + + // If node title is empty, try to retrieve title from feed. + if ($trimmed_node_title == '') { + try { + $source->addConfig($last_feeds[$importer_id]); + if (!$last_title = $source->preview()->title) { + throw new Exception(t('Could not retrieve title from feed')); + } + } + catch (Exception $e) { + drupal_set_message($e->getMessage(), 'error'); + form_set_error('title', t('Could not retrieve title from feed.'), array('error' => array('title'))); } - } - catch (Exception $e) { - drupal_set_message($e->getMessage(), 'error'); - form_set_error('title', t('Could not retrieve title from feed.')); } } } @@ -651,14 +676,16 @@ function feeds_node_presave($node) { function feeds_node_insert($node) { // Source attached to node. feeds_node_update($node); - if (isset($node->feeds) && $importer_id = feeds_get_importer_id($node->type)) { - $source = feeds_source($importer_id, $node->nid); - // Start import if requested. - if (feeds_importer($importer_id)->config['import_on_create'] && !isset($node->feeds['suppress_import'])) { - $source->startImport(); + if (isset($node->feeds) && ($importer_ids = feeds_get_importer_ids($node->type, $node->nid))) { + foreach ($importer_ids as $importer_id) { + $source = feeds_source($importer_id, $node->nid); + // Start import if requested. + if (feeds_importer($importer_id)->config['import_on_create'] && !isset($node->feeds['suppress_import'])) { + $source->startImport(); + } + // Schedule the source. + $source->schedule(); } - // Schedule the source. - $source->schedule(); } } @@ -667,10 +694,15 @@ function feeds_node_insert($node) { */ function feeds_node_update($node) { // Source attached to node. - if (isset($node->feeds) && $importer_id = feeds_get_importer_id($node->type)) { - $source = feeds_source($importer_id, $node->nid); - $source->addConfig($node->feeds); - $source->save(); + if (isset($node->feeds) && ($importer_ids = feeds_get_importer_ids($node->type))) { + foreach ($importer_ids as $importer_id) { + $source = feeds_source($importer_id, $node->nid); + // Config may be empty if defined so by importer. + if ($node->feeds[$importer_id]) { + $source->addConfig($node->feeds[$importer_id]); + } + $source->save(); + } } } @@ -682,8 +714,10 @@ function feeds_node_delete($node) { // Make sure we don't leave any orphans behind: Do not use // feeds_get_importer_id() to determine importer id as the importer may have // been deleted. - if ($importer_id = db_query("SELECT id FROM {feeds_source} WHERE feed_nid = :nid", array(':nid' => $node->nid))->fetchField()) { - feeds_source($importer_id, $node->nid)->delete(); + if ($importer_ids = db_query("SELECT id FROM {feeds_source} WHERE feed_nid = :nid", array(':nid' => $node->nid))) { + foreach ($importer_ids as $row) { + feeds_source($row->id, $node->nid)->delete(); + } } } @@ -691,20 +725,34 @@ function feeds_node_delete($node) { * Implements hook_form_BASE_FORM_ID_alter(). */ function feeds_form_node_form_alter(&$form, $form_state) { - if ($importer_id = feeds_get_importer_id($form['#node']->type)) { - // Enable uploads. - $form['#attributes']['enctype'] = 'multipart/form-data'; - - // Build form. - $source = feeds_source($importer_id, empty($form['#node']->nid) ? 0 : $form['#node']->nid); + if ($importer_ids = feeds_get_importer_ids($form['#node']->type)) { $form['feeds'] = array( '#type' => 'fieldset', '#title' => t('Feed'), '#tree' => TRUE, '#weight' => 0, ); - $form['feeds'] += $source->configForm($form_state); - $form['#feed_id'] = $importer_id; + + // Enable uploads. + if (count($importer_ids)) { + $form['#attributes']['enctype'] = 'multipart/form-data'; + } + + foreach ($importer_ids as $importer_id) { + // Set title to not required, try to retrieve it from feed. + if (isset($form['title'])) { + $form['title']['#required'] = FALSE; + } + + // Build form. + $source = feeds_source($importer_id, empty($form['#node']->nid) ? 0 : $form['#node']->nid); + $form['feeds'][$importer_id] = $source->configForm($form_state); + $class = get_class(feeds_importer($importer_id)->fetcher); + $form['feeds'][$importer_id][$class]['source']['#title'] = $form['feeds'][$importer_id][$class]['source']['#title'] + . ' - ' + . $source->importer->config['name']; + $form['feeds'][$importer_id][$class]['source']['#required'] = FALSE; + } // If the parser has support for delivering a source title, set node title // to not required and try to retrieve it from the source if the node title @@ -927,11 +975,11 @@ function feeds_menu_local_tasks_alter(&$data, $router_item, $root_path) { /** * Loads all importers. * - * @param $load_disabled + * @param bool $load_disabled * Pass TRUE to load all importers, enabled or disabled, pass FALSE to only * retrieve enabled importers. * - * @return + * @return array * An array of all feed configurations available. */ function feeds_importer_load_all($load_disabled = FALSE) { @@ -981,10 +1029,10 @@ function feeds_enabled_importers() { /** * Gets an enabled importer configuration by content type. * - * @param $content_type + * @param string $content_type * A node type string. * - * @return + * @return array * A FeedsImporter id if there is an importer for the given content type, * FALSE otherwise. */ @@ -994,6 +1042,57 @@ function feeds_get_importer_id($content_type) { } /** + * Gets an enabled importer configuration by content type. + * + * @param string $content_type + * A node type string. + * @param int $feed_nid + * Nid for feed. + * + * @return array + * A list of FeedsImporters attached to the given content type. + */ +function feeds_get_importer_ids($content_type, $feed_nid = NULL) { + $all_importers = _feeds_importer_digest(); + $importers = array(); + foreach ($all_importers as $importer => $type) { + if ($type == $content_type) { + $importers[$importer] = $importer; + } + } + // Sort those importers by weight. + if (!empty($importers)) { + $weights = _feeds_get_importer_weights($importers); + // Sort these arrays by key, then sort together. + ksort($weights); + ksort($importers); + array_multisort($weights, $importers); + } + return $importers; +} + +/** + * Get importer. + * + * @param array $importers + * @param bool|TRUE $sorted + * + * @return mixed + */ +function _feeds_get_importer_weights($importers, $sorted = TRUE) { + foreach (feeds_importer_load_all() as $importer) { + if (isset($importers[$importer->id])) { + $importer_weights[$importer->id] = isset($importer->config['weight']) ? + $importer->config['weight'] : '0'; + } + } + if ($sorted) { + asort($importer_weights); + } + return $importer_weights; +} + +/** * Helper function for feeds_get_importer_id() and feeds_enabled_importers(). */ function _feeds_importer_digest() { @@ -1005,7 +1104,8 @@ function _feeds_importer_digest() { else { $importers = array(); foreach (feeds_importer_load_all() as $importer) { - $importers[$importer->id] = isset($importer->config['content_type']) ? $importer->config['content_type'] : ''; + $importers[$importer->id] = isset($importer->config['content_type']) ? + $importer->config['content_type'] : ''; } cache_set(__FUNCTION__, $importers); } @@ -1259,6 +1359,9 @@ function feeds_include_library($file, $library) { * The name of the library. If libraries module is installed, * feeds_library_exists() will look for libraries with this name managed by * libraries module. + * + * @return bool + * If library exists or not. */ function feeds_library_exists($file, $library) { $path = module_exists('libraries') ? libraries_get_path($library) : FALSE; @@ -1280,7 +1383,7 @@ function feeds_library_exists($file, $library) { return FALSE; } - /** +/** * Checks whether simplepie exists. */ function feeds_simplepie_exists() { @@ -1345,7 +1448,7 @@ function feeds_alter($type, &$data) { /** * Copy of valid_url() that supports the webcal scheme. * - * @see valid_url(). + * @see valid_url() * * @todo Replace with valid_url() when http://drupal.org/node/295021 is fixed. */ @@ -1380,7 +1483,7 @@ function feeds_valid_url($url, $absolute = FALSE) { * Information about a new job to queue; or if set to NULL (default), leaves * the current queued jobs unchanged. * - * @return + * @return array * An array of subscribe jobs to process. * * @see feeds_exit() @@ -1397,7 +1500,7 @@ function feeds_set_subscription_job(array $job = NULL) { /** * Returns the list of queued jobs to be run. * - * @return + * @return array * An array of subscribe jobs to process. * * @see feeds_set_subscription_job() @@ -1431,7 +1534,7 @@ function feeds_entity_property_info_alter(&$info) { * Gets the feed_nid for an entity for use in entity metadata. */ function feeds_get_feed_nid_entity_callback($entity, array $options, $name, $entity_type) { - list($entity_id, , ) = entity_extract_ids($entity_type, $entity); + list($entity_id, ,) = entity_extract_ids($entity_type, $entity); $feed_nid = NULL; if ($entity_id) { @@ -1459,7 +1562,7 @@ function feeds_file_download($uri) { return; } - // Get the file record based on the URI. If not in the database just return. + // Get the file record based on the URI. If not in the database just return. $files = file_load_multiple(array(), array('uri' => $uri)); foreach ($files as $item) { // Since some database servers sometimes use a case-insensitive comparison diff --git a/feeds.pages.inc b/feeds.pages.inc index 6eddf47..cb4e6d3 100644 --- a/feeds.pages.inc +++ b/feeds.pages.inc @@ -131,25 +131,64 @@ function feeds_import_form_submit($form, &$form_state) { * Render a feeds import form on node/id/import pages. */ function feeds_import_tab_form($form, &$form_state, $node) { - $importer_id = feeds_get_importer_id($node->type); - $source = feeds_source($importer_id, $node->nid); + $total_progress = 0; + + $importer_ids = feeds_get_importer_ids($node->type, $node->nid); $form = array(); - $form['#feed_nid'] = $node->nid; - $form['#importer_id'] = $importer_id; - $form['#redirect'] = 'node/' . $node->nid; - $form['source_status'] = array( - '#type' => 'fieldset', - '#title' => t('Status'), - '#tree' => TRUE, - '#value' => feeds_source_status($source), - ); - $form = confirm_form($form, t('Import all content from source?'), 'node/' . $node->nid, '', t('Import'), t('Cancel'), 'confirm feeds update'); - $progress = $source->progressImporting(); - if ($progress !== FEEDS_BATCH_COMPLETE) { - $form['actions']['submit']['#disabled'] = TRUE; - $form['actions']['submit']['#value'] = - t('Importing (@progress %)', array('@progress' => number_format(100 * $progress, 0))); + if ($importer_ids) { + $form['#feed_nid'] = $node->nid; + $form['#redirect'] = 'node/' . $node->nid; + $form = confirm_form($form, t('Import all content from source?'), + 'node/' . $node->nid, '', t('Import'), t('Cancel'), + 'confirm feeds update'); + foreach ($importer_ids as $importer_id => $weight) { + $source = feeds_source($importer_id, $node->nid); + $form[$importer_id]['source_status'] = array( + '#type' => 'fieldset', + '#title' => t('@source_name: Status', array( + '@source_name' => $source->importer->config['name'], + )), + '#tree' => TRUE, + '#value' => feeds_source_status($source), + ); + $progress = $source->progressImporting(); + $total_progress += $progress; + } + if (count($importer_ids) == 1) { + $form['importer_ids'] = array( + '#type' => 'value', + '#value' => array($importer_id), + ); + } + else { + $options = array(); + foreach ($importer_ids as $importer_id => $weight) { + $source = feeds_source($importer_id, $node->nid); + $options[$importer_id] = $source->importer->config['name']; + } + $form['importer_ids'] = array( + '#type' => 'checkboxes', + '#options' => $options, + '#default_value' => array_keys($options), + '#title' => t('Sources'), + '#description' => t('Select the sources to import.'), + ); + } + + if (count($importer_ids)) { + $progress = $total_progress / count($importer_ids); + if ($progress !== FEEDS_BATCH_COMPLETE) { + $form['actions']['submit']['#disabled'] = TRUE; + $form['actions']['submit']['#value'] = t('Importing (@progress %)', + array('@progress' => number_format(100 * $progress, 0))); + } + } + } + else { + $form['no_source'] = array( + '#markup' => t('No feeds sources added to node.'), + ); } return $form; } @@ -159,7 +198,9 @@ function feeds_import_tab_form($form, &$form_state, $node) { */ function feeds_import_tab_form_submit($form, &$form_state) { $form_state['redirect'] = $form['#redirect']; - feeds_source($form['#importer_id'], $form['#feed_nid'])->startImport(); + foreach (array_filter($form_state['values']['importer_ids']) as $importer_id) { + feeds_source($importer_id, $form['#feed_nid'])->startImport(); + } } /** @@ -169,30 +210,86 @@ function feeds_import_tab_form_submit($form, &$form_state) { * Therefore $node may be missing. */ function feeds_delete_tab_form(array $form, array &$form_state, FeedsImporter $importer = NULL, $node = NULL) { + $total_progress = 0; if (empty($node)) { $source = feeds_source($importer->id); $form['#redirect'] = 'import/' . $source->id; + $importer_ids = array($importer->id); } else { - $importer_id = feeds_get_importer_id($node->type); - $source = feeds_source($importer_id, $node->nid); - $form['#redirect'] = 'node/' . $source->feed_nid; + $importer_ids = feeds_get_importer_ids($node->type, $node->nid); + $form['#redirect'] = 'node/' . $node->nid; } - // Form cannot pass on source object. - $form['#importer_id'] = $source->id; - $form['#feed_nid'] = $source->feed_nid; - $form['source_status'] = array( - '#type' => 'fieldset', - '#title' => t('Status'), - '#tree' => TRUE, - '#value' => feeds_source_status($source), - ); - $form = confirm_form($form, t('Delete all items from source?'), $form['#redirect'], '', t('Delete'), t('Cancel'), 'confirm feeds update'); - $progress = $source->progressClearing(); - if ($progress !== FEEDS_BATCH_COMPLETE) { - $form['actions']['submit']['#disabled'] = TRUE; - $form['actions']['submit']['#value'] = - t('Deleting (@progress %)', array('@progress' => number_format(100 * $progress, 0))); + if ($importer_ids) { + // Form cannot pass on source object. + $form['#feed_nid'] = empty($node) ? '' : $node->nid; + foreach ($importer_ids as $import_id => $weight) { + $source = empty($node) ? $source : feeds_source($import_id, $node->nid); + if (!empty($node)) { + $form[$import_id]['source_status'] = array( + '#type' => 'fieldset', + '#title' => t('@source_name: Status', array( + '@source_name' => $source->importer->config['name'], + )), + '#tree' => TRUE, + '#value' => feeds_source_status($source), + ); + } + else { + $form['source_status'] = array( + '#type' => 'fieldset', + '#title' => t('@source_name: Status', array( + '@source_name' => $source->importer->config['name'], + )), + '#tree' => TRUE, + '#value' => feeds_source_status($source), + ); + } + $progress = $source->progressClearing(); + $total_progress += $progress; + } + + // Set importer ids. + // If this is a stand-alone form then importer will be passed. + if ($importer) { + $form['importer_ids'] = array( + '#type' => 'value', + '#value' => array($importer->id => $importer->id), + ); + } + else { + $options = array(); + foreach ($importer_ids as $importer_id => $weight) { + $source = feeds_source($importer_id, $node->nid); + $options[$importer_id] = $source->importer->config['name']; + } + $form['importer_ids'] = array( + '#type' => 'checkboxes', + '#options' => $options, + '#default_value' => array_keys($options), + '#title' => t('Sources'), + '#description' => t('Select the sources to delete items from.'), + ); + } + + $form = confirm_form($form, t('Delete all items from source?'), + $form['#redirect'], '', t('Delete'), t('Cancel'), 'confirm feeds update'); + + if (count($importer_ids)) { + $progress = $total_progress / count($importer_ids); + if ($progress !== FEEDS_BATCH_COMPLETE) { + $form['actions']['submit']['#disabled'] = TRUE; + $form['actions']['submit']['#value'] = t('Deleting (@progress %)', + array( + '@progress' => number_format(100 * $progress, 0), + )); + } + } + } + else { + $form['no_source'] = array( + '#markup' => t('No feeds sources added to node.'), + ); } return $form; } @@ -203,7 +300,9 @@ function feeds_delete_tab_form(array $form, array &$form_state, FeedsImporter $i function feeds_delete_tab_form_submit($form, &$form_state) { $form_state['redirect'] = $form['#redirect']; $feed_nid = empty($form['#feed_nid']) ? 0 : $form['#feed_nid']; - feeds_source($form['#importer_id'], $feed_nid)->startClear(); + foreach (array_filter($form_state['values']['importer_ids']) as $importer_id) { + feeds_source($importer_id, $feed_nid)->startClear(); + } } /** @@ -231,7 +330,8 @@ function feeds_unlock_tab_form($form, &$form_state, FeedsImporter $importer = NU '#tree' => TRUE, '#value' => feeds_source_status($source), ); - $form = confirm_form($form, t('Unlock this importer?'), $form['#redirect'], '', t('Delete'), t('Cancel'), 'confirm feeds update'); + $form = confirm_form($form, t('Unlock this importer?'), + $form['#redirect'], '', t('Delete'), t('Cancel'), 'confirm feeds update'); if ($source->progressImporting() == FEEDS_BATCH_COMPLETE && $source->progressClearing() == FEEDS_BATCH_COMPLETE) { $form['source_locked'] = array( '#type' => 'markup', @@ -257,7 +357,7 @@ function feeds_unlock_tab_form_submit($form, &$form_state) { $feed_nid = empty($form['#feed_nid']) ? 0 : $form['#feed_nid']; $importer_id = $form['#importer_id']; - //Is there a more API-friendly way to set the state? + // Is there a more API-friendly way to set the state? db_update('feeds_source') ->condition('id', $importer_id) ->condition('feed_nid', $feed_nid) @@ -281,7 +381,7 @@ function feeds_fetcher_callback($importer, $feed_nid = 0) { } /** - * Template generation + * Template generation. */ function feeds_importer_template(FeedsImporter $importer) { if ($importer->parser instanceof FeedsCSVParser) { @@ -318,18 +418,26 @@ function theme_feeds_source_status($v) { $items = array(); if ($v['progress_importing']) { $progress = number_format(100.0 * $v['progress_importing'], 0); - $items[] = t('Importing - @progress % complete.', array('@progress' => $progress)); + $items[] = t('Importing - @progress % complete.', array( + '@progress' => $progress, + )); } if ($v['progress_clearing']) { $progress = number_format(100.0 * $v['progress_clearing'], 0); - $items[] = t('Deleting items - @progress % complete.', array('@progress' => $progress)); + $items[] = t('Deleting items - @progress % complete.', array( + '@progress' => $progress, + )); } if (!count($items)) { if ($v['count']) { if ($v['imported']) { - $items[] = t('Last import: @ago ago.', array('@ago' => format_interval(REQUEST_TIME - $v['imported'], 1))); + $items[] = t('Last import: @ago ago.', array( + '@ago' => format_interval(REQUEST_TIME - $v['imported'], 1), + )); } - $items[] = t('@count imported items total.', array('@count' => $v['count'])); + $items[] = t('@count imported items total.', array( + '@count' => $v['count'], + )); } else { $items[] = t('No imported items.'); @@ -357,7 +465,9 @@ function theme_feeds_upload($variables) { $summary .= l($file->filename, $wrapper->getExternalUrl()); } else { - $summary .= t('URI scheme %scheme not available.', array('%scheme' => file_uri_scheme($uri))); + $summary .= t('URI scheme %scheme not available.', array( + '%scheme' => file_uri_scheme($uri), + )); } $summary .= ''; $summary .= '
'; @@ -369,7 +479,8 @@ function theme_feeds_upload($variables) { $summary .= '
'; } // Prepend the summary to the form field. - $element['#children'] = '
' . $summary . '
' . $element['#children']; + $element['#children'] = '
' . $summary . + '
' . $element['#children']; // Render file upload field using theme_form_element(). $output = theme('form_element', $element); // Close "feeds-file" and "feeds-file-upload" divs. diff --git a/feeds_import/feeds_import.test b/feeds_import/feeds_import.test index ee62de0..e5a1f7a 100644 --- a/feeds_import/feeds_import.test +++ b/feeds_import/feeds_import.test @@ -100,9 +100,10 @@ class FeedsExamplesNodeTestCase extends FeedsWebTestCase { $this->assertText('Updated 7 nodes'); // Import a tab separated file. + $this->drupalGet('import/node/delete-items'); $this->drupalPost('import/node/delete-items', array(), 'Delete'); $edit = array( - 'files[feeds]' => $this->absolutePath() . '/tests/feeds/nodes.tsv', + 'files[node]' => $this->absolutePath() . '/tests/feeds/nodes.tsv', 'feeds[FeedsCSVParser][delimiter]' => "TAB", ); $this->drupalPost('import/node', $edit, 'Import'); diff --git a/feeds_news/feeds_news.feeds_importer_default.inc b/feeds_news/feeds_news.feeds_importer_default.inc index 3fa5ee7..2820269 100644 --- a/feeds_news/feeds_news.feeds_importer_default.inc +++ b/feeds_news/feeds_news.feeds_importer_default.inc @@ -106,7 +106,7 @@ function feeds_news_feeds_importer_default() { ), 1 => array( 'source' => 'xmlurl', - 'target' => 'feeds_source', + 'target' => 'feeds_source_feed', 'unique' => 1, ), ), diff --git a/feeds_ui/feeds_ui.test b/feeds_ui/feeds_ui.test index 7378b91..58ac0cd 100644 --- a/feeds_ui/feeds_ui.test +++ b/feeds_ui/feeds_ui.test @@ -108,8 +108,10 @@ class FeedsUIUserInterfaceTestCase extends FeedsWebTestCase { // Create a feed node. $edit = array( 'title' => 'Development Seed', - 'feeds[FeedsHTTPFetcher][source]' => $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/developmentseed.rss2', - ); + 'feeds[test_feed][FeedsHTTPFetcher][source]' => + $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . + '/tests/feeds/developmentseed.rss2', + ); $this->drupalPost('node/add/page', $edit, 'Save'); $this->assertText('Basic page Development Seed has been created.'); diff --git a/includes/FeedsImporter.inc b/includes/FeedsImporter.inc index cad7695..a111224 100644 --- a/includes/FeedsImporter.inc +++ b/includes/FeedsImporter.inc @@ -193,6 +193,7 @@ class FeedsImporter extends FeedsConfigurable { 'plugin_key' => 'FeedsNodeProcessor', ), 'content_type' => '', + 'weight' => 0, 'update' => 0, 'import_period' => 1800, // Refresh every 30 minutes by default. 'expire_period' => 3600, // Expire every hour by default, this is a hidden setting. @@ -220,6 +221,12 @@ class FeedsImporter extends FeedsConfigurable { '#description' => t('A description of this importer.'), '#default_value' => $config['description'], ); + $form['weight'] = array( + '#type' => 'textfield', + '#title' => t('Weight'), + '#description' => t('Determines the effective processing order of this feed relative to others that might run at the same time.'), + '#default_value' => $config['weight'], + ); $node_types = node_type_get_names(); array_walk($node_types, 'check_plain'); $form['content_type'] = array( diff --git a/includes/FeedsSource.inc b/includes/FeedsSource.inc index b5577a1..6dded29 100644 --- a/includes/FeedsSource.inc +++ b/includes/FeedsSource.inc @@ -33,7 +33,7 @@ interface FeedsSourceInterface { * * @see FeedsPlugin class. * - * @return + * @return bool * TRUE if a plugin handles source specific configuration, FALSE otherwise. */ public function hasSourceConfig(); @@ -124,9 +124,9 @@ class FeedsState { * - $progress is larger than $total * - $progress approximates $total so that $finished rounds to 1.0 * - * @param $total + * @param int $total * A natural number that is the total to be worked off. - * @param $progress + * @param int $progress * A natural number that is the progress made on $total. */ public function progress($total, $progress) { @@ -217,7 +217,8 @@ class FeedsSource extends FeedsConfigurable { } /** - * Returns the FeedsImporter object that this source is expected to be used with. + * Returns the FeedsImporter object that this source is expected + * to be used with. */ public function importer() { return $this->importer; @@ -226,7 +227,7 @@ class FeedsSource extends FeedsConfigurable { /** * Preview = fetch and parse a feed. * - * @return + * @return object * FeedsParserResult object. * * @throws @@ -368,7 +369,7 @@ class FeedsSource extends FeedsConfigurable { * This method only executes the current batch chunk, then returns. If you are * looking to import an entire source, use FeedsSource::startImport() instead. * - * @return + * @return float * FEEDS_BATCH_COMPLETE if the import process finished. A decimal between * 0.0 and 0.9 periodic if import is still in progress. * @@ -496,7 +497,7 @@ class FeedsSource extends FeedsConfigurable { * looking to delete all items of a source, use FeedsSource::startClear() * instead. * - * @return + * @return float * FEEDS_BATCH_COMPLETE if the clearing process finished. A decimal between * 0.0 and 0.9 periodic if clearing is still in progress. * @@ -594,10 +595,10 @@ class FeedsSource extends FeedsConfigurable { * * @todo Rename getConfigFor() accordingly to config(). * - * @param $stage + * @param string $stage * One of FEEDS_FETCH, FEEDS_PARSE, FEEDS_PROCESS or FEEDS_PROCESS_CLEAR. * - * @return + * @return object * The FeedsState object for the given stage. */ public function state($stage) { @@ -629,24 +630,31 @@ class FeedsSource extends FeedsConfigurable { // Store the source property of the fetcher in a separate column so that we // can do fast lookups on it. + // Only save if there is a source so they can be optional on entities. $source = ''; - if (isset($config[get_class($this->importer->fetcher)]['source'])) { - $source = $config[get_class($this->importer->fetcher)]['source']; - } - $object = array( - 'id' => $this->id, - 'feed_nid' => $this->feed_nid, - 'imported' => $this->imported, - 'config' => $config, - 'source' => $source, - 'state' => isset($this->state) ? $this->state : FALSE, - 'fetcher_result' => isset($this->fetcher_result) ? $this->fetcher_result : FALSE, - ); - if (db_query_range("SELECT 1 FROM {feeds_source} WHERE id = :id AND feed_nid = :nid", 0, 1, array(':id' => $this->id, ':nid' => $this->feed_nid))->fetchField()) { - drupal_write_record('feeds_source', $object, array('id', 'feed_nid')); - } - else { - drupal_write_record('feeds_source', $object); + if (isset($config[get_class($this->importer->fetcher)]['source']) && + $source = $config[get_class($this->importer->fetcher)]['source']) { + $object = array( + 'id' => $this->id, + 'feed_nid' => $this->feed_nid, + 'imported' => $this->imported, + 'config' => $config, + 'source' => $source, + 'state' => isset($this->state) ? $this->state : FALSE, + 'fetcher_result' => isset($this->fetcher_result) ? $this->fetcher_result : FALSE, + ); + if (db_query_range("SELECT 1 FROM {feeds_source} WHERE id = :id AND feed_nid = :nid", + 0, 1, + array( + ':id' => $this->id, + ':nid' => $this->feed_nid, + ) + )->fetchField()) { + drupal_write_record('feeds_source', $object, array('id', 'feed_nid')); + } + else { + drupal_write_record('feeds_source', $object); + } } } @@ -656,7 +664,12 @@ class FeedsSource extends FeedsConfigurable { * @todo Patch CTools to move constants from export.inc to ctools.module. */ public function load() { - if ($record = db_query("SELECT imported, config, state, fetcher_result FROM {feeds_source} WHERE id = :id AND feed_nid = :nid", array(':id' => $this->id, ':nid' => $this->feed_nid))->fetchObject()) { + if ($record = db_query("SELECT imported, config, state, fetcher_result FROM {feeds_source} WHERE id = :id AND feed_nid = :nid", + array( + ':id' => $this->id, + ':nid' => $this->feed_nid, + ) + )->fetchObject()) { // While FeedsSource cannot be exported, we still use CTool's export.inc // export definitions. ctools_include('export'); @@ -701,7 +714,7 @@ class FeedsSource extends FeedsConfigurable { /** * Only return source if configuration is persistent and valid. * - * @see FeedsConfigurable::existing(). + * @see FeedsConfigurable::existing() */ public function existing() { // If there is no feed nid given, there must be no content type specified. @@ -738,7 +751,7 @@ class FeedsSource extends FeedsConfigurable { * @param $config * The configuration for $client. * - * @return + * @return array * An array stored for $client. */ public function setConfigFor(FeedsSourceInterface $client, $config) { @@ -805,10 +818,10 @@ class FeedsSource extends FeedsConfigurable { * submits a source for import or clearing, we will leave her without any * visual indicators of an ongoing job. * - * @see FeedsSource::startImport(). - * @see FeedsSource::startClear(). + * @see FeedsSource::startImport() + * @see FeedsSource::startClear() * - * @param $method + * @param string $method * Method to execute on importer; one of 'import' or 'clear'. * * @throws Exception $e @@ -828,13 +841,13 @@ class FeedsSource extends FeedsConfigurable { /** * Batch API helper. Starts a Batch API job. * - * @see FeedsSource::startImport(). - * @see FeedsSource::startClear(). + * @see FeedsSource::startImport() + * @see FeedsSource::startClear() * @see feeds_batch() * - * @param $title + * @param string $title * Title to show to user when executing batch. - * @param $method + * @param string $method * Method to execute on importer; one of 'import' or 'clear'. */ protected function startBatchAPIJob($title, $method) { diff --git a/plugins/FeedsFileFetcher.inc b/plugins/FeedsFileFetcher.inc index 88292ae..6ed8ac3 100644 --- a/plugins/FeedsFileFetcher.inc +++ b/plugins/FeedsFileFetcher.inc @@ -30,7 +30,11 @@ class FeedsFileFetcherResult extends FeedsFetcherResult { */ public function getFilePath() { if (!is_readable($this->file_path)) { - throw new Exception(t('File @filepath is not accessible.', array('@filepath' => $this->file_path))); + throw new Exception(t('File @filepath is not accessible.', + array( + '@filepath' => $this->file_path, + ) + )); } return $this->sanitizeFile($this->file_path); } @@ -65,14 +69,15 @@ class FeedsFileFetcher extends FeedsFetcher { return new FeedsFileFetcherResult($file); } - throw new Exception(t('Resource is not a file or it is an empty directory: %source', array('%source' => $source_config['source']))); + throw new Exception(t('Resource is not a file or it is an empty directory: %source', + array('%source' => $source_config['source']))); } /** * Returns an array of files in a directory. * * @param string $dir - * A stream wreapper URI that is a directory. + * A stream wrapper URI that is a directory. * * @return array * An array of stream wrapper URIs pointing to files. The array is empty if @@ -107,10 +112,14 @@ class FeedsFileFetcher extends FeedsFetcher { ); $form['upload'] = array( '#type' => 'file', + '#name' => 'files[' . $this->id . ']', '#title' => empty($this->config['direct']) ? t('File') : NULL, - '#description' => empty($source_config['source']) ? t('Select a file from your local system.') : t('Select a different file from your local system.'), + '#description' => empty($source_config['source']) ? + t('Select a file from your local system.') : + t('Select a different file from your local system.'), '#theme_wrappers' => array('feeds_upload'), - '#file_info' => empty($source_config['fid']) ? NULL : file_load($source_config['fid']), + '#file_info' => empty($source_config['fid']) ? + NULL : file_load($source_config['fid']), '#size' => 10, ); } @@ -118,8 +127,10 @@ class FeedsFileFetcher extends FeedsFetcher { $form['source'] = array( '#type' => 'textfield', '#title' => t('File'), - '#description' => t('Specify a path to a file or a directory. Prefix the path with a scheme. Available schemes: @schemes.', array('@schemes' => implode(', ', $this->config['allowed_schemes']))), - '#default_value' => empty($source_config['source']) ? '' : $source_config['source'], + '#description' => t('Specify a path to a file or a directory. Prefix the path with a scheme. Available schemes: @schemes.', + array('@schemes' => implode(', ', $this->config['allowed_schemes']))), + '#default_value' => empty($source_config['source']) ? + '' : $source_config['source'], ); } return $form; @@ -139,15 +150,27 @@ class FeedsFileFetcher extends FeedsFetcher { if (user_access('administer feeds')) { $plugin_key = feeds_importer($this->id)->config[$this->pluginType()]['plugin_key']; $link = url('admin/structure/feeds/' . $this->id . '/settings/' . $plugin_key); - form_set_error('feeds][FeedsFileFetcher][source', t('Upload failed. Please check the upload settings.', array('@link' => $link))); + form_set_error('feeds][FeedsFileFetcher][source', + t('Upload failed. Please check the upload settings.', + array('@link' => $link)) + ); } else { - form_set_error('feeds][FeedsFileFetcher][source', t('Upload failed. Please contact your site administrator.')); + form_set_error('feeds][FeedsFileFetcher][source', + t('Upload failed. Please contact your site administrator.') + ); } - watchdog('feeds', 'The upload directory %directory required by a feed could not be created or is not accessible. A newly uploaded file could not be saved in this directory as a consequence, and the upload was canceled.', array('%directory' => $feed_dir)); + watchdog('feeds', 'The upload directory %directory required by a feed could not be created or is not accessible. A newly uploaded file could not be saved in this directory as a consequence, and the upload was canceled.', + array('%directory' => $feed_dir) + ); } // Validate and save uploaded file. - elseif ($file = file_save_upload('feeds', array('file_validate_extensions' => array(0 => $this->config['allowed_extensions'])), $feed_dir)) { + elseif ($file = file_save_upload($this->id, + array( + 'file_validate_extensions' => array( + 0 => $this->config['allowed_extensions'], + ), + ), $feed_dir)) { $values['source'] = $file->uri; $values['file'] = $file; } @@ -162,11 +185,17 @@ class FeedsFileFetcher extends FeedsFetcher { // Check if chosen url scheme is allowed. $scheme = file_uri_scheme($values['source']); if (!$scheme || !in_array($scheme, $this->config['allowed_schemes'])) { - form_set_error('feeds][FeedsFileFetcher][source', t("The file needs to reside within the site's files directory, its path needs to start with scheme://. Available schemes: @schemes.", array('@schemes' => implode(', ', $this->config['allowed_schemes'])))); + form_set_error('feeds][FeedsFileFetcher][source', + t("The file needs to reside within the site's files directory, its path needs to start with scheme://. Available schemes: @schemes.", + array( + '@schemes' => implode(', ', $this->config['allowed_schemes']), + )) + ); } // Check whether the given path is readable. elseif (!is_readable($values['source'])) { - form_set_error('feeds][FeedsFileFetcher][source', t('The specified file or directory does not exist.')); + form_set_error('feeds][FeedsFileFetcher][source', + t('The specified file or directory does not exist.')); } } } @@ -255,11 +284,17 @@ class FeedsFileFetcher extends FeedsFetcher { $form['directory'] = array( '#type' => 'textfield', '#title' => t('Upload directory'), - '#description' => t('Directory where uploaded files get stored. Prefix the path with a scheme. Available schemes: @schemes.', array('@schemes' => implode(', ', $this->getSchemes()))), + '#description' => t('Directory where uploaded files get stored. Prefix the path with a scheme. Available schemes: @schemes.', + array('@schemes' => implode(', ', $this->getSchemes())) + ), '#default_value' => $this->config['directory'], '#states' => array( - 'visible' => array(':input[name="direct"]' => array('checked' => FALSE)), - 'required' => array(':input[name="direct"]' => array('checked' => FALSE)), + 'visible' => array( + ':input[name="direct"]' => array('checked' => FALSE), + ), + 'required' => array( + ':input[name="direct"]' => array('checked' => FALSE), + ), ), ); if ($options = $this->getSchemeOptions()) { @@ -270,7 +305,9 @@ class FeedsFileFetcher extends FeedsFetcher { '#options' => $options, '#description' => t('Select the schemes you want to allow for direct upload.'), '#states' => array( - 'visible' => array(':input[name="direct"]' => array('checked' => TRUE)), + 'visible' => array( + ':input[name="direct"]' => array('checked' => TRUE), + ), ), ); } @@ -300,7 +337,8 @@ class FeedsFileFetcher extends FeedsFetcher { // Validate the URI scheme of the upload directory. $scheme = file_uri_scheme($values['directory']); if (!$scheme || !in_array($scheme, $this->getSchemes())) { - form_set_error('directory', t('Please enter a valid scheme into the directory location.')); + form_set_error('directory', + t('Please enter a valid scheme into the directory location.')); // Return here so that attempts to create the directory below don't // throw warnings. @@ -309,7 +347,8 @@ class FeedsFileFetcher extends FeedsFetcher { // Ensure that the upload directory exists. if (!file_prepare_directory($values['directory'], FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) { - form_set_error('directory', t('The chosen directory does not exist and attempts to create it failed.')); + form_set_error('directory', + t('The chosen directory does not exist and attempts to create it failed.')); } } } diff --git a/plugins/FeedsHTTPFetcher.inc b/plugins/FeedsHTTPFetcher.inc index cd91b63..0c2667c 100644 --- a/plugins/FeedsHTTPFetcher.inc +++ b/plugins/FeedsHTTPFetcher.inc @@ -238,7 +238,7 @@ class FeedsHTTPFetcher extends FeedsFetcher { } if (!feeds_valid_url($values['source'], TRUE)) { - $form_key = 'feeds][' . get_class($this) . '][source'; + $form_key = 'feeds][' . $this->id . '][' . get_class($this) . '][source'; form_set_error($form_key, t('The URL %source is invalid.', array('%source' => $original_url))); } elseif ($this->config['auto_detect_feeds']) { diff --git a/plugins/FeedsNodeProcessor.inc b/plugins/FeedsNodeProcessor.inc index 0087d2d..d3912fe 100644 --- a/plugins/FeedsNodeProcessor.inc +++ b/plugins/FeedsNodeProcessor.inc @@ -96,7 +96,9 @@ class FeedsNodeProcessor extends FeedsProcessor { // could be invalid. if (!$author) { $message = 'User %uid is not a valid user.'; - throw new FeedsAccessException(t($message, array('%uid' => $entity->uid))); + throw new FeedsAccessException(t($message, + array('%uid' => $entity->uid)) + ); } if (empty($entity->nid) || !empty($entity->is_new)) { @@ -129,7 +131,7 @@ class FeedsNodeProcessor extends FeedsProcessor { parent::entityValidate($entity); if (!isset($entity->uid) || !is_numeric($entity->uid)) { - $entity->uid = $this->config['author']; + $entity->uid = $this->config['author']; } } @@ -186,7 +188,7 @@ class FeedsNodeProcessor extends FeedsProcessor { '#title' => t('Author'), '#description' => t('Select the author of the nodes to be created - leave empty to assign "anonymous".'), '#autocomplete_path' => 'user/autocomplete', - '#default_value' => empty($author->name) ? 'anonymous' : check_plain($author->name), + '#default_value' => empty($author->name) ? 'anonymous' : check_plain($author->name), ); $form['authorize'] = array( '#type' => 'checkbox', @@ -194,7 +196,10 @@ class FeedsNodeProcessor extends FeedsProcessor { '#description' => t('Check that the author has permission to create the node.'), '#default_value' => $this->config['authorize'], ); - $period = drupal_map_assoc(array(FEEDS_EXPIRE_NEVER, 3600, 10800, 21600, 43200, 86400, 259200, 604800, 2592000, 2592000 * 3, 2592000 * 6, 31536000), 'feeds_format_expire'); + $period = drupal_map_assoc(array( + FEEDS_EXPIRE_NEVER, 3600, 10800, 21600, 43200, 86400, 259200, 604800, + 2592000, 2592000 * 3, 2592000 * 6, 31536000, + ), 'feeds_format_expire'); $form['expire'] = array( '#type' => 'select', '#title' => t('Expire nodes'), @@ -235,6 +240,24 @@ class FeedsNodeProcessor extends FeedsProcessor { * Override setTargetElement to operate on a target item that is a node. */ public function setTargetElement(FeedsSource $source, $target_node, $target_element, $value) { + $id = $this->bundle(); + if ($target_element == 'feeds_source_' . $id) { + // Get the class of the feed node importer's fetcher and set the source + // property. See feeds_node_update() how $node->feeds gets stored. + $class = get_class(feeds_importer($id)->fetcher); + $target_node->feeds[$id][$class]['source'] = $value; + // This effectively suppresses 'import on submission' feature. + // See feeds_node_insert(). + $target_node->feeds['suppress_import'] = TRUE; + } + if (substr($target_element, 0, 13) == 'feeds_source_') { + foreach ($target_node->feeds as $key => $feed) { + if ($target_element == 'feeds_source_' . $key) { + $class = get_class(feeds_importer($id)->fetcher); + $target_node->feeds[$key][$class]['source'] = $value; + } + } + } switch ($target_element) { case 'created': $target_node->created = feeds_to_unixtime($value, REQUEST_TIME); @@ -245,17 +268,6 @@ class FeedsNodeProcessor extends FeedsProcessor { // before invoking hook_node_presave()). $target_node->feeds_item->node_changed = feeds_to_unixtime($value, REQUEST_TIME); break; - case 'feeds_source': - // Get the class of the feed node importer's fetcher and set the source - // property. See feeds_node_update() how $node->feeds gets stored. - if ($id = feeds_get_importer_id($this->bundle())) { - $class = get_class(feeds_importer($id)->fetcher); - $target_node->feeds[$class]['source'] = $value; - // This effectively suppresses 'import on submission' feature. - // See feeds_node_insert(). - $target_node->feeds['suppress_import'] = TRUE; - } - break; case 'user_name': if ($user = user_load_by_name($value)) { $target_node->uid = $user->uid; @@ -341,13 +353,15 @@ class FeedsNodeProcessor extends FeedsProcessor { } // If the target content type is a Feed node, expose its source field. - if ($id = feeds_get_importer_id($this->bundle())) { - $name = feeds_importer($id)->config['name']; - $targets['feeds_source'] = array( - 'name' => t('Feed source'), - 'description' => t('The content type created by this processor is a Feed Node, it represents a source itself. Depending on the fetcher selected on the importer "@importer", this field is expected to be for example a URL or a path to a file.', array('@importer' => $name)), - 'optional_unique' => TRUE, - ); + if ($ids = feeds_get_importer_ids($this->config['bundle'])) { + foreach ($ids as $id) { + $name = feeds_importer($id)->config['name']; + $targets['feeds_source_' . $id] = array( + 'name' => t('Feed source ' . $name), + 'description' => t('The content type created by this processor is a Feed Node, it represents a source itself. Depending on the fetcher selected on the importer "@importer", this field is expected to be for example a URL or a path to a file.', array('@importer' => $name)), + 'optional_unique' => TRUE, + ); + } } $this->getHookTargets($targets); @@ -368,16 +382,24 @@ class FeedsNodeProcessor extends FeedsProcessor { foreach ($this->uniqueTargets($source, $result) as $target => $value) { switch ($target) { case 'nid': - $nid = db_query("SELECT nid FROM {node} WHERE nid = :nid", array(':nid' => $value))->fetchField(); + $nid = db_query("SELECT nid FROM {node} WHERE nid = :nid", + array(':nid' => $value))->fetchField(); break; + case 'title': - $nid = db_query("SELECT nid FROM {node} WHERE title = :title AND type = :type", array(':title' => $value, ':type' => $this->bundle()))->fetchField(); + $nid = db_query("SELECT nid FROM {node} WHERE title = :title AND type = :type", + array(':title' => $value, ':type' => $this->bundle())) + ->fetchField(); break; - case 'feeds_source': - if ($id = feeds_get_importer_id($this->bundle())) { - $nid = db_query("SELECT fs.feed_nid FROM {node} n JOIN {feeds_source} fs ON n.nid = fs.feed_nid WHERE fs.id = :id AND fs.source = :source", array(':id' => $id, ':source' => $value))->fetchField(); + } + if (isset($this->config['content_type']) && + $ids = feeds_get_importer_ids($this->config['content_type'])) { + foreach ($ids as $id) { + if ($target == 'feeds_source_' . $id) { + $nid = db_query("SELECT fs.feed_nid FROM {node} n JOIN {feeds_source} fs ON n.nid = fs.feed_nid WHERE fs.id = :id AND fs.source = :source", + array(':id' => $id, ':source' => $value))->fetchField(); } - break; + } } if ($nid) { // Return with the first nid found. diff --git a/tests/feeds.test b/tests/feeds.test index c486773..7915ed5 100644 --- a/tests/feeds.test +++ b/tests/feeds.test @@ -298,10 +298,10 @@ class FeedsWebTestCase extends DrupalWebTestCase { * @param $title * Optional parameter to change title of feed node. */ - public function editFeedNode($nid, $feed_url, $title = '') { + public function editFeedNode($nid, $feed_url, $id = 'syndication', $title = '') { $edit = array( 'title' => $title, - 'feeds[FeedsHTTPFetcher][source]' => $feed_url, + 'feeds[' . $id . '][FeedsHTTPFetcher][source]' => $feed_url, ); // Check that the update was saved. $this->drupalPost('node/' . $nid . '/edit', $edit, 'Save'); @@ -336,7 +336,7 @@ class FeedsWebTestCase extends DrupalWebTestCase { $feed_url = $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/developmentseed.rss2'; } $edit = array( - 'feeds[FeedsHTTPFetcher][source]' => $feed_url, + 'feeds[' . $id . '][FeedsHTTPFetcher][source]' => $feed_url, ); $nid = $this->drupalPost('import/' . $id, $edit, 'Import'); @@ -364,7 +364,7 @@ class FeedsWebTestCase extends DrupalWebTestCase { $this->assertTrue(file_exists($file), 'Source file exists'); $edit = array( - 'files[feeds]' => $file, + "files[$id]" => $file, ); $this->drupalPost('import/' . $id, $edit, 'Import'); } diff --git a/tests/feeds_processor_node.test b/tests/feeds_processor_node.test index 25ec79a..171a960 100644 --- a/tests/feeds_processor_node.test +++ b/tests/feeds_processor_node.test @@ -24,7 +24,8 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase { public function setUp() { parent::setUp(); - // Set the front page to show 20 nodes so we can easily see what is aggregated. + // Set the front page to show 20 nodes so we can easily see what + // is aggregated. variable_set('default_nodes_main', 20); // Set the teaser length display to unlimited otherwise tests looking for @@ -356,7 +357,8 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase { // Create a feed node. $edit = array( - 'files[feeds]' => $this->absolutePath() . '/tests/feeds/drupalplanet.rss2', + 'files[syndication_standalone]' => $this->absolutePath() . + '/tests/feeds/drupalplanet.rss2', ); $this->drupalPost('import/syndication_standalone', $edit, 'Import'); $this->assertText('Created 25 nodes'); @@ -409,8 +411,8 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase { /** * Test validation of feed URLs. */ - public function testFeedURLValidation() { - $edit['feeds[FeedsHTTPFetcher][source]'] = 'invalid://url'; + public function testFeedURLValidation($id = 'syndication') { + $edit['feeds[' . $id . '][FeedsHTTPFetcher][source]'] = 'invalid://url'; $this->drupalPost('node/add/page', $edit, 'Save'); $this->assertText('The URL invalid://url is invalid.'); } @@ -418,15 +420,18 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase { /** * Test using non-normal URLs like feed:// and webcal://. */ - public function testOddFeedSchemes() { + public function testOddFeedSchemes($id = 'syndication') { $url = $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/developmentseed.rss2'; $schemes = array('feed', 'webcal'); $item_count = 0; foreach ($schemes as $scheme) { - $feed_url = strtr($url, array('http://' => $scheme . '://', 'https://' => $scheme . '://')); + $feed_url = strtr($url, array( + 'http://' => $scheme . '://', + 'https://' => $scheme . '://', + )); - $edit['feeds[FeedsHTTPFetcher][source]'] = $feed_url; + $edit['feeds[' . $id . '][FeedsHTTPFetcher][source]'] = $feed_url; $this->drupalPost('node/add/page', $edit, 'Save'); $this->assertText('Basic page Development Seed - Technological Solutions for Progressive Organizations has been created.'); $this->assertText('Created 10 nodes.'); @@ -438,7 +443,7 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase { /** * Test that feed elements and links are not found on non-feed nodes. */ - public function testNonFeedNodeUI() { + public function testNonFeedNodeUI($id = 'syndication') { // There should not be feed links on an article node. $non_feed_node = $this->drupalCreateNode(array('type' => 'article')); $this->drupalGet('node/' . $non_feed_node->nid); @@ -447,7 +452,7 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase { // Navigate to a non-feed node form, there should be no Feed field visible. $this->drupalGet('node/add/article'); - $this->assertNoFieldByName('feeds[FeedsHTTPFetcher][source]'); + $this->assertNoFieldByName('feeds[' . $id . '][FeedsHTTPFetcher][source]'); } /**