? feeds.849840.7.patch ? feeds.849840.8.patch Index: feeds_ui/feeds_ui.admin.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/feeds_ui/feeds_ui.admin.inc,v retrieving revision 1.34 diff -u -p -r1.34 feeds_ui.admin.inc --- feeds_ui/feeds_ui.admin.inc 10 Jul 2010 23:30:19 -0000 1.34 +++ feeds_ui/feeds_ui.admin.inc 9 Sep 2010 01:05:51 -0000 @@ -530,6 +530,7 @@ function feeds_ui_mapping_form(&$form_st ); if (is_array($mappings)) { + $form['mappings']['#tree'] = TRUE; foreach ($mappings as $i => $mapping) { $mappings[$i]['source'] = isset($source_options) ? $source_options[$mappings[$i]['source']] : $mappings[$i]['source']; @@ -553,6 +554,15 @@ function feeds_ui_mapping_form(&$form_st '#prefix' => '', ); + + // Declare the mappings data in the hidden field, so later + // the full mapping data will be submitted in $form_state['values']['mappings']. + foreach($mapping as $k => $v) { + $form['mappings'][$i][$k] = array ( + '#type' => 'hidden', + '#value' => $v, + ); + } } } @@ -595,7 +605,19 @@ function feeds_ui_mapping_form(&$form_st function feeds_ui_mapping_form_add_submit($form, &$form_state) { $importer = $form['#importer']; try { - $importer->processor->addMapping($form_state['values']['source'], $form_state['values']['target']); + // addMapping method is now used for custom FeedsProcessor + // to declare what they want to do when mapping is added + // e.g. FeedsDataProcessor + if (method_exists($importer->processor, 'addMapping')) { + $importer->processor->addMapping($form_state['values']['source'], $form_state['values']['target']); + } + + $form_state['values']['mappings'][] = array( + 'source' => $form_state['values']['source'], + 'target' => $form_state['values']['target'], + 'unique' => FALSE, + ); + $importer->processor->addConfig($form_state['values']); $importer->processor->save(); drupal_set_message(t('Mapping has been added.')); } @@ -614,16 +636,23 @@ function feeds_ui_mapping_form_submit($f // step, that's fine. if (isset($form_state['values']['unique_flags'])) { foreach ($form_state['values']['unique_flags'] as $k => $v) { - $processor->setUnique($mappings[$k]['source'], $mappings[$k]['target'], $v); + $form_state['values']['mappings'][$k]['unique'] = $v; } } foreach ($form_state['values']['remove_flags'] as $k => $v) { if ($v) { - $processor->removeMapping($mappings[$k]['source'], $mappings[$k]['target']); + unset($form_state['values']['mappings'][$k]); + // Keep or keys clean. + $form_state['values']['mappings'] = array_values($form_state['values']['mappings']); } } drupal_set_message(t('Your changes have been saved.')); + + // Because now full mapping is submitted, so no further validation for + // out of sync mappings is needed (i.e. the mapping is modified by other people while + // we are at it). Simply replace it. + $processor->addConfig($form_state['values']); $processor->save(); } Index: plugins/FeedsDataProcessor.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsDataProcessor.inc,v retrieving revision 1.21 diff -u -p -r1.21 FeedsDataProcessor.inc --- plugins/FeedsDataProcessor.inc 8 Sep 2010 22:02:08 -0000 1.21 +++ plugins/FeedsDataProcessor.inc 9 Sep 2010 01:05:51 -0000 @@ -104,41 +104,6 @@ class FeedsDataProcessor extends FeedsPr } /** - * Override parent::addMapping() and create a new field for new mapping - * targets. - * - * @see getMappingTargets(). - */ - public function addMapping($source, $target, $unique = FALSE) { - if (empty($source) || empty($target)) { - return; - } - - // Create a new field with targets that start with "new:" - @list($new, $type) = explode(':', $target); - - if ($new == 'new') { - // Build a field name from the source key. - $field_name = data_safe_name($source); - // Get the full schema spec from data. - $type = data_get_field_definition($type); - // Add the field to the table. - $schema = $this->table()->get('table_schema'); - if (!isset($schema['fields'][$field_name])) { - $target = $this->table()->addField($field_name, $type); - // Let the user know. - drupal_set_message(t('Created new field "!name".', array('!name' => $field_name))); - } - else { - throw new Exception(t('Field !field_name already exists as a mapping target. Remove it from mapping if you would like to map another source to it. Remove it from !data_table table if you would like to change its definition.', array('!field_name' => $field_name, '!data_table' => l($this->table()->get('name'), 'admin/content/data')))); - } - } - - // Let parent populate the mapping configuration. - parent::addMapping($source, $target, $unique); - } - - /** * Return available mapping targets. */ public function getMappingTargets() { @@ -362,4 +327,58 @@ class FeedsDataProcessor extends FeedsPr ), ); } + + public function addConfig($config) { + if(!empty($config['mappings'])) { + foreach ($config['mappings'] as &$mapping) { + @list($new, $type) = explode(':', $mapping['target']); + + // Create a new field with targets that start with "new:" + if ($new == 'new') { + // Build a field name from the source key. + $field_name = data_safe_name($mapping['source']); + // Get the full schema spec from data. + $type = data_get_field_definition($type); + // Add the field to the table. + $schema = $this->table()->get('table_schema'); + if (!isset($schema['fields'][$field_name])) { + $mapping['target'] = $this->table()->addField($field_name, $type); + // Let the user know. + drupal_set_message(t('Created new field "!name".', array('!name' => $field_name))); + } + else { + throw new Exception(t('Field !field_name already exists as a mapping target. Remove it from mapping if you would like to map another source to it. Remove it from !data_table table if you would like to change its definition.', array('!field_name' => $field_name, '!data_table' => l($this->table()->get('name'), 'admin/content/data')))); + } + } + } + } + return parent::addConfig($config); + } + + public function setConfig($config) { + if (!empty($config['mappings'])) { + foreach ($config['mappings'] as &$mapping) { + @list($new, $type) = explode(':', $mapping['target']); + + // Create a new field with targets that start with "new:" + if ($new == 'new') { + // Build a field name from the source key. + $field_name = data_safe_name($mapping['source']); + // Get the full schema spec from data. + $type = data_get_field_definition($type); + // Add the field to the table. + $schema = $this->table()->get('table_schema'); + if (!isset($schema['fields'][$field_name])) { + $mapping['target'] = $this->table()->addField($field_name, $type); + // Let the user know. + drupal_set_message(t('Created new field "!name".', array('!name' => $field_name))); + } + else { + throw new Exception(t('Field !field_name already exists as a mapping target. Remove it from mapping if you would like to map another source to it. Remove it from !data_table table if you would like to change its definition.', array('!field_name' => $field_name, '!data_table' => l($this->table()->get('name'), 'admin/content/data')))); + } + } + } + } + return parent::setConfig($config); + } } Index: plugins/FeedsProcessor.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsProcessor.inc,v retrieving revision 1.17 diff -u -p -r1.17 FeedsProcessor.inc --- plugins/FeedsProcessor.inc 7 Sep 2010 17:57:15 -0000 1.17 +++ plugins/FeedsProcessor.inc 9 Sep 2010 01:05:51 -0000 @@ -169,54 +169,6 @@ abstract class FeedsProcessor extends Fe } /** - * Add a mapping to existing mappings. - * - * @param $source - * A string that identifies a source element. - * @param $target - * A string that identifies a target element. - * @param $unique - * A boolean that defines whether the target value should be unique. If - * TRUE only one item with a given target value can exist on the local - * system. Compare with existingItemId() and uniqueTargets(). - */ - public function addMapping($source, $target, $unique = FALSE) { - if (!empty($source) && !empty($target)) { - $this->config['mappings'][] = array( - 'source' => $source, - 'target' => $target, - 'unique' => $unique, - ); - } - } - - /** - * Set unique state of a mapping target. - */ - public function setUnique($source, $target, $unique) { - if (!empty($source) && !empty($target)) { - foreach ($this->config['mappings'] as $k => $mapping) { - if ($mapping['source'] == $source && $mapping['target'] == $target) { - $this->config['mappings'][$k]['unique'] = $unique; - } - } - } - } - - /** - * Remove a mapping. - */ - public function removeMapping($source, $target) { - foreach ($this->config['mappings'] as $k => $mapping) { - if ($mapping['source'] == $source && $mapping['target'] == $target) { - unset($this->config['mappings'][$k]); - } - } - // Keep or keys clean. - $this->config['mappings'] = array_values($this->config['mappings']); - } - - /** * Get mappings. */ public function getMappings() {