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.30
diff -u -r1.30 feeds_ui.admin.inc
--- feeds_ui/feeds_ui.admin.inc	5 May 2010 23:52:48 -0000	1.30
+++ feeds_ui/feeds_ui.admin.inc	5 Jul 2010 10:40:44 -0000
@@ -383,7 +383,6 @@
   if (feeds_get_config_form($importer->processor)) {
     $actions[] = l(t('Settings'), $path .'/settings/'. $config['processor']['plugin_key']);
   }
-  $actions[] = l(t('Mapping'), $path .'/mapping');
   $info['title'] = t('Processor');
   $info['body'] = array(
     array(
@@ -473,174 +472,6 @@
 }
 
 /**
- * Edit mapping.
- *
- * @todo Completely merge this into config form handling. This is just a
- *   shared form of configuration, most of the common functionality can live in
- *   FeedsProcessor, a flag can tell whether mapping is supported or not.
- */
-function feeds_ui_mapping_form(&$form_state, $importer) {
-  drupal_add_js(drupal_get_path('module', 'feeds_ui') .'/feeds_ui.js');
-
-  $form = array();
-  $form['#importer'] = $importer;
-  $form['help']['#value'] = feeds_ui_mapping_help();
-
-  // Get mapping sources from parsers and targets from processor, format them
-  // for output.
-  // Some parsers do not define mapping sources but let them define on the fly.
-  if ($sources = $importer->parser->getMappingSources()) {
-    $source_options = _feeds_ui_format_options($sources);
-    foreach ($sources as $k => $source) {
-      $legend['sources'][$k]['name']['#value'] = empty($source['name']) ? $k : $source['name'];
-      $legend['sources'][$k]['description']['#value'] = empty($source['description']) ? '' : $source['description'];
-    }
-  }
-  else {
-    $legend['sources']['#value'] = t('This parser supports free source definitions. Enter the name of the source field in lower case into the Source text field above.');
-  }
-  $targets = $importer->processor->getMappingTargets();
-  $target_options = _feeds_ui_format_options($targets);
-  foreach ($targets as $k => $target) {
-    $legend['targets'][$k]['name']['#value'] = empty($target['name']) ? $k : $target['name'];
-    $legend['targets'][$k]['description']['#value'] = empty($target['description']) ? '' : $target['description'];
-  }
-
-  $form['legendset'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Legend'),
-    '#collapsible' => TRUE,
-    '#collapsed' => TRUE,
-    '#tree' => TRUE,
-  );
-  $form['legendset']['legend'] = $legend;
-
-  // Add unique and remove forms to mappings.
-  $mappings = $importer->processor->getMappings();
-  $form['unique_flags'] = $form['remove_flags'] = array(
-    '#tree' => TRUE,
-  );
-
-  if (is_array($mappings)) {
-    foreach ($mappings as $i => $mapping) {
-
-      $mappings[$i]['source'] = isset($source_options) ? $source_options[$mappings[$i]['source']] : $mappings[$i]['source'];
-      $mappings[$i]['target'] = $target_options[$mappings[$i]['target']];
-      $param = array(
-        'processor' => $importer->processor,
-        'mapping' => $mapping,
-      );
-
-      if (isset($targets[$mapping['target']]['optional_unique']) && $targets[$mapping['target']]['optional_unique'] === TRUE) {
-
-        $form['unique_flags'][$i] = array(
-          '#type' => 'checkbox',
-          '#default_value' => !empty($mapping['unique']),
-          '#attributes' => array('class' => 'feeds-ui-trigger-submit'),
-        );
-      }
-      $form['remove_flags'][$i] = array(
-        '#type' => 'checkbox',
-        '#title' => t('Remove'),
-        '#prefix' => '<div class="feeds-ui-checkbox-link">',
-        '#suffix' => '</div>',
-      );
-    }
-  }
-
-  $form['#mappings'] = $mappings;
-  $form['#targets'] = $targets;
-  if ($sources) {
-    $form['source'] = array(
-      '#type' => 'select',
-      '#options' => array('' => t('Select a source')) + $source_options,
-    );
-  }
-  else {
-    $form['source'] = array(
-      '#type' => 'textfield',
-      '#size' => 20,
-      '#default_value' => t('Name of source field'),
-      '#attributes' => array('class' => 'hide-text-on-focus'),
-    );
-  }
-  $form['target'] = array(
-    '#type' => 'select',
-    '#options' => array('' => t('Select a target')) + _feeds_ui_format_options($targets),
-  );
-  $form['add'] = array(
-    '#type' => 'submit',
-    '#value' => t('Add'),
-    '#submit' => array('feeds_ui_mapping_form_add_submit'),
-  );
-  $form['save'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save'),
-    '#attributes' => array('class' => 'feeds-ui-hidden-submit'),
-  );
-  return $form;
-}
-
-/**
- * Submit handler for add button on feeds_ui_mapping_form().
- */
-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']);
-    $importer->processor->save();
-    drupal_set_message(t('Mapping has been added.'));
-  }
-  catch (Exception $e) {
-    drupal_set_message($e->getMessage(), 'error');
-  }
-}
-
-/**
- * Submit handler for save button on feeds_ui_mapping_form().
- */
-function feeds_ui_mapping_form_submit($form, &$form_state) {
-  $processor = $form['#importer']->processor;
-  $mappings = $processor->config['mappings'];
-  // We may set some unique flags to mappings that we remove in the subsequent
-  // 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);
-    }
-  }
-
-  foreach ($form_state['values']['remove_flags'] as $k => $v) {
-    if ($v) {
-      $processor->removeMapping($mappings[$k]['source'], $mappings[$k]['target']);
-    }
-  }
-  drupal_set_message(t('Your changes have been saved.'));
-  $processor->save();
-}
-
-/**
- * Walk the result of FeedsParser::getMappingSources() or
- * FeedsProcessor::getMappingTargets() and format them into
- * a Form API options array.
- */
-function _feeds_ui_format_options($options) {
-  $result = array();
-  foreach ($options as $k => $v) {
-    if (is_array($v) && !empty($v['name'])) {
-      $result[$k] = $v['name'];
-    }
-    elseif (is_array($v)) {
-      $result[$k] = $k;
-    }
-    else {
-      $result[$k] = $v;
-    }
-  }
-  return $result;
-}
-
-/**
  * Theme feeds_ui_overview_form().
  */
 function theme_feeds_ui_overview_form($form) {
@@ -753,8 +584,7 @@
 /**
  * Theme function for feeds_ui_mapping_form().
  */
-function theme_feeds_ui_mapping_form($form) {
-
+function theme_feeds_ui_mapping_form($form) {  
   // Build the actual mapping table.
   $header = array(
     t('Source'),
Index: includes/FeedsConfigurable.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/includes/FeedsConfigurable.inc,v
retrieving revision 1.12
diff -u -r1.12 FeedsConfigurable.inc
--- includes/FeedsConfigurable.inc	28 Feb 2010 17:16:25 -0000	1.12
+++ includes/FeedsConfigurable.inc	5 Jul 2010 10:40:44 -0000
@@ -178,6 +178,14 @@
    */
   public function configFormValidate(&$values) {
   }
+  
+  /**
+   * Flag whether to render mapping form within the configForm.
+   * default value is false, override this as necessary.
+   */
+  public function embedMappingForm() {
+    return FALSE;
+  }
 }
 
 /**
@@ -212,7 +220,17 @@
  *   The object to perform the save() operation on.
  */
 function feeds_config_form(&$form_state, $configurable) {
-  $form = $configurable->configForm($form_state);
+  // Embed mapping form into the config form depend on
+  // FeedsConfigurable::embedMappingForm() value.
+  if ($configurable->embedMappingForm()) {
+    $form = feeds_mapping_form($configurable);
+  }
+  else {
+    $form = array();
+  }
+  
+  $form = array_merge($form, $configurable->configForm($form_state));
+  
   $form['#configurable'] = $configurable;
   $form['#validate'] = array('feeds_config_form_validate');
   $form['#submit'] = array('feeds_config_form_submit');
@@ -221,6 +239,7 @@
     '#value' => t('Save'),
     '#weight' => 100,
   );
+  
   return $form;
 }
 
@@ -234,9 +253,192 @@
 /**
  * Submit handler for feeds_config_form().
  */
-function feeds_config_form_submit($form, &$form_state) {
+function feeds_config_form_submit($form, &$form_state) {      
   $form['#configurable']->addConfig($form_state['values']);
   $form['#configurable']->save();
+  
+  // Add special submit handling only if there mappingForm is embedded
+  // Assumption: Only FeedsProcessor set embedMappingForm() into TRUE
+  if ($form['#configurable']->embedMappingForm()) {
+    $processor = $form['#configurable'];
+    
+    $mappings = $processor->config['mappings'];
+    // We may set some unique flags to mappings that we remove in the subsequent
+    // 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);
+      }
+    }
+  
+    if (isset($form_state['values']['remove_flags'])) {
+      foreach ($form_state['values']['remove_flags'] as $k => $v) {
+        if ($v) {
+          $processor->removeMapping($mappings[$k]['source'], $mappings[$k]['target']);
+        }
+      }
+    }
+    $processor->save();
+  }
+  
   drupal_set_message(t('Your changes have been saved.'));
   feeds_cache_clear(FALSE);
 }
+
+/**
+ * Definition of the mapping form.
+ * All FeedsProcessor must call this before adding items into the form.
+ */
+function feeds_mapping_form($configurable) {
+	drupal_add_js(drupal_get_path('module', 'feeds_ui') .'/feeds_ui.js');  	
+	
+	// Get the FeedsImporter object
+	$importer = feeds_importer($configurable->id);	
+	
+  $form = array();  
+
+  // Mapping on Import checkbox
+  $form['mapping_on_import'] = array(
+    '#type' => 'checkbox',
+    '#title' => 'Mapping on Import',
+    '#description' => 'If this is checked, the mapping form here will be disabled and instead user will be asked for the mapping configuration after the first import.',
+    '#attributes' => array('class' => 'feeds-ui-trigger-submit'),
+    '#weight' => -100,
+    '#default_value' => $importer->processor->config['mapping_on_import'],
+  );
+
+  if (!$importer->processor->config['mapping_on_import']) {
+    $form['#theme'] = 'feeds_ui_mapping_form';
+    $form['help']['#value'] = feeds_ui_mapping_help();
+  
+    // Get mapping sources from parsers and targets from processor, format them
+    // for output.
+    // Some parsers do not define mapping sources but let them define on the fly.
+    if ($sources = $importer->parser->getMappingSources()) {      
+      $source_options = _feeds_processor_format_options($sources);
+      foreach ($sources as $k => $source) {
+        $legend['sources'][$k]['name']['#value'] = empty($source['name']) ? $k : $source['name'];
+        $legend['sources'][$k]['description']['#value'] = empty($source['description']) ? '' : $source['description'];
+      }
+    }
+    else {
+      $legend['sources']['#value'] = t('This parser supports free source definitions. Enter the name of the source field in lower case into the Source text field above.');
+    }        
+    $targets = $importer->processor->getMappingTargets();
+    $target_options = _feeds_mapping_form_format_options($targets);
+    foreach ($targets as $k => $target) {
+      $legend['targets'][$k]['name']['#value'] = empty($target['name']) ? $k : $target['name'];
+      $legend['targets'][$k]['description']['#value'] = empty($target['description']) ? '' : $target['description'];
+    }
+  
+    $form['legendset'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Legend'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#tree' => TRUE,
+    );
+    $form['legendset']['legend'] = $legend;
+  
+    // Add unique and remove forms to mappings.
+    $mappings = $importer->processor->getMappings();
+    $form['unique_flags'] = $form['remove_flags'] = array(
+      '#tree' => TRUE,
+    );
+  
+    if (is_array($mappings)) {
+      foreach ($mappings as $i => $mapping) {
+  
+        $mappings[$i]['source'] = isset($source_options) ? $source_options[$mappings[$i]['source']] : $mappings[$i]['source'];
+        $mappings[$i]['target'] = $target_options[$mappings[$i]['target']];
+        $param = array(
+          'processor' => $importer->processor,
+          'mapping' => $mapping,
+        );
+  
+        if (isset($targets[$mapping['target']]['optional_unique']) && $targets[$mapping['target']]['optional_unique'] === TRUE) {
+  
+          $form['unique_flags'][$i] = array(
+            '#type' => 'checkbox',
+            '#default_value' => !empty($mapping['unique']),
+            '#attributes' => array('class' => 'feeds-ui-trigger-submit'),
+          );
+        }
+        $form['remove_flags'][$i] = array(
+          '#type' => 'checkbox',
+          '#title' => t('Remove'),
+          '#prefix' => '<div class="feeds-ui-checkbox-link">',
+          '#suffix' => '</div>',
+        );
+      }
+    }
+  
+    $form['#mappings'] = $mappings;
+    $form['#targets'] = $targets;
+    if ($sources) {
+      $form['source'] = array(
+        '#type' => 'select',
+        '#options' => array('' => t('Select a source')) + $source_options,
+      );
+    }
+    else {
+      $form['source'] = array(
+        '#type' => 'textfield',
+        '#size' => 20,
+        '#default_value' => t('Name of source field'),
+        '#attributes' => array('class' => 'hide-text-on-focus'),
+      );
+    }
+    $form['target'] = array(
+      '#type' => 'select',
+      '#options' => array('' => t('Select a target')) + _feeds_mapping_form_format_options($targets),
+    );
+    $form['add'] = array(
+      '#type' => 'submit',
+      '#value' => t('Add'),
+      '#submit' => array('feeds_mapping_form_add_submit'),
+    );
+  }  
+  $form['save'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save'),
+    '#attributes' => array('class' => 'feeds-ui-hidden-submit'),
+  );
+  
+  return $form;
+}
+
+/**
+ * Submit handler for add button on feeds_ui_mapping_form().
+ */
+function feeds_mapping_form_add_submit($form, &$form_state) {
+  try {
+    $form['#configurable']->addMapping($form_state['values']['source'], $form_state['values']['target']);
+    $form['#configurable']->save();
+    drupal_set_message(t('Mapping has been added.'));
+  }
+  catch (Exception $e) {
+    drupal_set_message($e->getMessage(), 'error');
+  }
+}
+
+/**
+ * Walk the result of FeedsParser::getMappingSources() or
+ * FeedsProcessor::getMappingTargets() and format them into
+ * a Form API options array.
+ */
+function _feeds_mapping_form_format_options($options) {
+  $result = array();
+  foreach ($options as $k => $v) {
+    if (is_array($v) && !empty($v['name'])) {
+      $result[$k] = $v['name'];
+    }
+    elseif (is_array($v)) {
+      $result[$k] = $k;
+    }
+    else {
+      $result[$k] = $v;
+    }
+  }
+  return $result;
+}
\ No newline at end of file
Index: plugins/FeedsDataProcessor.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsDataProcessor.inc,v
retrieving revision 1.13
diff -u -r1.13 FeedsDataProcessor.inc
--- plugins/FeedsDataProcessor.inc	16 May 2010 21:51:58 -0000	1.13
+++ plugins/FeedsDataProcessor.inc	5 Jul 2010 10:45:10 -0000
@@ -255,6 +255,7 @@
       'update_existing' => 0,
       'expire' => FEEDS_EXPIRE_NEVER, // Don't expire items by default.
       'mappings' => array(),
+      'mapping_on_import' => 0,
     );
   }
 
Index: plugins/FeedsFeedNodeProcessor.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsFeedNodeProcessor.inc,v
retrieving revision 1.12
diff -u -r1.12 FeedsFeedNodeProcessor.inc
--- plugins/FeedsFeedNodeProcessor.inc	28 Apr 2010 22:18:30 -0000	1.12
+++ plugins/FeedsFeedNodeProcessor.inc	5 Jul 2010 10:45:20 -0000
@@ -107,6 +107,7 @@
       'content_type' => '',
       'update_existing' => 0,
       'mappings' => array(),
+      'mapping_on_import' => 0,
     );
   }
 
Index: plugins/FeedsNodeProcessor.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsNodeProcessor.inc,v
retrieving revision 1.38
diff -u -r1.38 FeedsNodeProcessor.inc
--- plugins/FeedsNodeProcessor.inc	19 Jun 2010 18:03:41 -0000	1.38
+++ plugins/FeedsNodeProcessor.inc	5 Jul 2010 10:45:31 -0000
@@ -146,6 +146,7 @@
       'expire' => FEEDS_EXPIRE_NEVER,
       'mappings' => array(),
       'author' => 0,
+      'mapping_on_import' => 0,
     );
   }
 
Index: plugins/FeedsProcessor.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsProcessor.inc,v
retrieving revision 1.11
diff -u -r1.11 FeedsProcessor.inc
--- plugins/FeedsProcessor.inc	19 Jun 2010 15:57:13 -0000	1.11
+++ plugins/FeedsProcessor.inc	5 Jul 2010 10:45:38 -0000
@@ -130,7 +130,10 @@
    * Declare default configuration.
    */
   public function configDefaults() {
-    return array('mappings' => array());
+    return array(
+      'mappings' => array(),
+      'mapping_on_import' => 0,
+    );
   }
 
   /**
@@ -272,5 +275,11 @@
       module_implements('', FALSE, TRUE);
     }
     $loaded = TRUE;
-  }
+  }  
+  
+  /**
+   * Override FeedsConfigurable::embedMappingForm()
+   * Embed mapping form in the FeedsProcessor configuration form
+   */
+  public function embedMappingForm() { return TRUE; }
 }
Index: plugins/FeedsTermProcessor.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsTermProcessor.inc,v
retrieving revision 1.9
diff -u -r1.9 FeedsTermProcessor.inc
--- plugins/FeedsTermProcessor.inc	28 Apr 2010 22:18:30 -0000	1.9
+++ plugins/FeedsTermProcessor.inc	5 Jul 2010 10:45:45 -0000
@@ -126,6 +126,7 @@
       'vocabulary' => 0,
       'update_existing' => 0,
       'mappings' => array(),
+      'mapping_on_import' => 0,
     );
   }
 
Index: plugins/FeedsUserProcessor.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsUserProcessor.inc,v
retrieving revision 1.12
diff -u -r1.12 FeedsUserProcessor.inc
--- plugins/FeedsUserProcessor.inc	19 Jun 2010 15:57:13 -0000	1.12
+++ plugins/FeedsUserProcessor.inc	5 Jul 2010 10:45:52 -0000
@@ -117,6 +117,7 @@
       'update_existing' => FALSE,
       'status' => 1,
       'mappings' => array(),
+      'mapping_on_import' => 0,
     );
   }
 

