? 542260-5_multiple_mappings.patch
Index: feedapi_mapper.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feedapi_mapper/Attic/feedapi_mapper.admin.inc,v
retrieving revision 1.1.2.3
diff -u -p -r1.1.2.3 feedapi_mapper.admin.inc
--- feedapi_mapper.admin.inc	12 Aug 2009 09:57:37 -0000	1.1.2.3
+++ feedapi_mapper.admin.inc	13 Aug 2009 10:02:13 -0000
@@ -29,14 +29,8 @@ function theme_feedapi_mapper_form($form
   $output = '';
   _feedapi_mapper_load_mappers();
   $type_url_str = str_replace('_', '-', $form['#node']->type);
-  if (isset($form['#node']->nid)) {
-    $delete_path = 'node/' . $form['#node']->nid .'/map/delete/';
-    $toggle_unique_path = 'node/' . $form['#node']->nid .'/map/unique/';
-  }
-  else {
-    $delete_path = 'admin/content/node-type/'. $type_url_str .'/map/delete/';
-    $toggle_unique_path = 'admin/content/node-type/'. $type_url_str .'/map/unique/';
-  }
+  $delete_path = 'map/' .$form['#mapping']['id'] .'/delete/';
+  $toggle_unique_path = 'map/' . $form['#mapping']['id'].'/unique/';
   if (isset($form['#mapping']['mapping'])) {
     $feed_settings = feedapi_get_settings($form['#node']->type, $form['#node']->vid);
     $active_processors = array_keys($feed_settings['processors']);
@@ -79,24 +73,60 @@ function theme_feedapi_mapper_form($form
   return $output;
 }
 
+function theme_feedapi_mapper_overview($form) {
+
+  $output = '';
+  $header = array(
+    t('Name'),
+    t('Status'),
+    t('Active'),
+    t('Operations'),
+  );
+  ctools_include('export');
+  $objects = ctools_export_load_object('feedapi_mapper', 'conditions', array('default_param' => $form['param']['#value']));
+
+  if (empty($objects)) {
+    $output .= t('No mapping sets are defined. Create a new one');
+  }
+  $rows = array();
+  foreach ($objects as $mapping) {
+    if ($mapping->export_type === EXPORT_IN_DATABASE) {
+      $status = t('normal');
+    }
+    if ($mapping->export_type === EXPORT_IN_CODE) {
+      $status = t('default');
+    }
+    if ($mapping->export_type === (EXPORT_IN_CODE | EXPORT_IN_DATABASE)) {
+      $status = t('overridden');
+    }
+    if ($mapping->export_type === EXPORT_IN_CODE) {
+      $operations = l(t('Override'), "map/{$mapping->id}/override") .' | '. l(t('Copy'), "map/{$mapping->id}/copy");
+    }
+    else {
+      $operations = l(t('Edit'), "map/{$mapping->id}") .' | '. l(t('Copy'), "map/{$mapping->id}/copy");
+    }
+    $rows[] = array(
+      $mapping->id,
+      $status,
+      drupal_render($form['active'][$mapping->id]),
+      $operations,
+    );
+  }
+  $output .= theme('table', $header, $rows);
+  $output .= drupal_render($form['new']) . drupal_render($form['change']);
+  $output .= drupal_render($form);
+  return $output;
+}
+
 /**
  * Page callback for deleting field mapings.
  */
-function feedapi_mapper_delete_form($form_state, $param, $encoded_key) {
+function feedapi_mapper_delete_form($form_state, $mapping, $encoded_key) {
   $form = array();
   $key = base64_decode($encoded_key);
-  if (is_string($param)) {
-    $node = new stdClass();
-    $node->type = str_replace('-', '_', $param);
-    $path = 'admin/content/node-type/'. $param .'/map';
-  }
-  else {
-    $node = $param;
-    $path = "node/{$node->nid}/map";
-  }
 
-  $form['#node'] = $node;
-  $form['#redirect'] = $path;
+  $form['#mapping'] = $mapping;
+  $form['#redirect'] = "map/{$mapping['id']}";
   $form['#source'] = $key;
 
   return confirm_form($form,
@@ -111,8 +141,7 @@ function feedapi_mapper_delete_form($for
  * Submission callback for feedapi_mapper_delete_form.
  */
 function feedapi_mapper_delete_form_submit($form, &$form_state) {
-  $param = isset($form['#node']->nid) && _feedapi_mapper_is_overridden($form['#node']->nid) ? $form['#node']->nid : $form['#node']->type;
-  feedapi_mapper_delete_mapping($param, $form['#source']);
+  feedapi_mapper_delete_mapping($form['#mapping']['id'], $form['#source']);
   drupal_set_message(t('The mapping entry has been deleted successfully'));
 }
 
@@ -147,26 +176,15 @@ function feedapi_mapper_revert_submit($f
  * Toggles the value of the unique-ness of the given key
  * @see theme_feedapi_mapper_form()
  */
-function feedapi_mapper_unique_toggle($param, $encoded_key, $token) {
+function feedapi_mapper_unique_toggle($map, $encoded_key, $token) {
   $key = base64_decode($encoded_key);
   if (!drupal_valid_token($token, $key)) {
     drupal_set_message(t('Invalid request'), 'error');
     drupal_goto('');
   }
-  if (is_string($param)) {
-    $node = new stdClass();
-    $node->type = str_replace('-', '_', $param);
-    $path = 'admin/content/node-type/'. $param .'/map';
-  }
-  else {
-    $node = $param;
-    $path = "node/{$node->nid}/map";
-    $param = $node->nid;
-  }
-  $mapping = feedapi_mapper_load_mapping($node);
-  feedapi_mapper_delete_mapping($param, $key);
-  feedapi_mapper_add_mapping($param, $key, $mapping['mapping'][$key], !$mapping['unique'][$key]);
-  drupal_goto($path);
+  feedapi_mapper_delete_mapping($map['id'], $key);
+  feedapi_mapper_add_mapping($map['id'], $param, $key, $map['mapping'][$key], !$map['unique'][$key]);
+  drupal_goto("map/{$map['id']}");
 }
 
 /**
@@ -230,14 +248,112 @@ function feedapi_mapper_page($node) {
   }
   $names = node_get_types('names');
   drupal_set_title(check_plain($node->title ? $node->title : $names[$node->type]));
-  $output = drupal_get_form('feedapi_mapper_form', $node);
+  $output = drupal_get_form('feedapi_mapper_overview', $node);
   return $output;
 }
 
 /**
+ * Overview form to manage mapping sets
+ */
+function feedapi_mapper_overview($form_state, $feed_node) {
+  $param = isset($feed_node->nid) ? $feed_node->nid : $feed_node->type;
+  ctools_include('export');
+  $objects = ctools_export_load_object('feedapi_mapper', 'conditions', array('default_param' => $param));
+  $options = array();
+  foreach ($objects as $object) {
+    $options[$object->id] = '';
+  }
+  // Get the active one
+  $active = db_result(db_query("SELECT id FROM {feedapi_mapper_active} WHERE param = '%s'", $param));
+  $form['param'] = array(
+    '#type' => 'hidden',
+    '#value' => $param,
+  );
+  $form['active'] = array(
+    '#type' => 'radios',
+    '#default_value' => $active,
+    '#options' => $options,
+  );
+  $form['new'] = array(
+    '#type' => 'submit',
+    '#value' => t('New'),
+  );
+  $form['change'] = array(
+    '#type' => 'submit',
+    '#value' => t('Change active'),
+  );
+  return $form;
+}
+
+function feedapi_mapper_overview_submit($form, &$form_state) {
+  if ($form_state['values']['op'] == t('Change active') && !empty($form_state['values']['active'])) {
+    $mapping = map_load($form_state['values']['active']);
+    feedapi_mapper_activate_mapping($mapping);
+  }
+  if ($form_state['values']['op'] == t('New')) {
+    drupal_goto("map/add/{$form_state['values']['param']}");
+  }
+}
+
+
+function feedapi_mapper_add($form_state, $param) {
+  drupal_set_title(t('Create new mapping set'));
+  $form['default_param'] = array(
+    '#type' => 'hidden',
+    '#value' => $param,
+  );
+  $form['id'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Name',
+    '#description' => t('Site-wide unique identifier of the mapping set. Use only alphanumeric characters.'),
+    '#required' => TRUE,
+  );
+  $form['active'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Make it the active mapping after created'),
+  );
+  $form['add'] = array(
+    '#type' => 'submit',
+    '#value' => t('Add'),
+  );
+  return $form;
+}
+
+function feedapi_mapper_add_validate($form, &$form_state) {
+  $count = db_result(db_query("SELECT COUNT(*) FROM {feedapi_mapper} WHERE id = '%s'", $form_state['values']['id']));
+  if ($count > 0) {
+    form_set_error('id', t('This mapping set name is already in use.'));
+  }
+  if (!ctype_alnum($form_state['values']['id'])) {
+    form_set_error('id', t('The name should only contain alphanumeric characters.'));
+  }
+}
+
+function feedapi_mapper_add_submit($form, &$form_state) {
+  db_query("INSERT INTO {feedapi_mapper} (id, default_param) VALUES ('%s', '%s')", $form_state['values']['id'], $form_state['values']['default_param']);
+  if ($form_state['values']['active']) {
+    $mapping = map_load($form_state['values']['id']);
+    feedapi_mapper_activate_mapping($mapping);
+  }
+  if (is_numeric($form_state['values']['default_param'])) {
+    drupal_goto("node/{$form_state['values']['default_param']}/map");
+  }
+  else {
+    drupal_goto("admin/content/node-type/{$form_state['values']['default_param']}/map"); 
+  }
+}
+
+/**
  * Mapping form.
  */
-function feedapi_mapper_form($form_state, $feed_node) {
+function feedapi_mapper_form($form_state, $mapping) {
+  $feed_node = new stdClass();
+  if (is_numeric($mapping['default_param'])) {
+    $feed_node = node_load($mapping['default_param']);
+  }
+  else {
+   $feed_node->type = $mapping['default_param'];
+  }
 
   $field_map = _feedapi_mapper_get_field_mappers($feed_node);
 
@@ -251,9 +367,6 @@ function feedapi_mapper_form($form_state
   asort($elements);
   $feed_map = array_flip($elements);
 
-  // Load stored mapping.
-  $mapping = feedapi_mapper_load_mapping($feed_node);
-
   $form['#node'] = $feed_node;
 
   $form['#feed_map'] = $feed_map;
@@ -269,14 +382,14 @@ function feedapi_mapper_form($form_state
 
   // Override settings: if theis is a node we are on and there is no mapping at all,
   // we are operating on the content-type defaults. If not we are overriding.
-  if ($feed_node->nid && _feedapi_mapper_is_overridden($feed_node->nid)) {
+  /*if ($feed_node->nid && _feedapi_mapper_is_overridden($feed_node->nid)) {
     $override = t('This mapping is specific to this feed node.') .' '. l(t('Use content-type default.'), 'node/'. $feed_node->nid .'/map/default');
     $form['#override'] = TRUE;
   }
   elseif (isset($feed_node->nid)) {
     $override = t('This mapping is the standard content-type mapping. Any changes will affect all feeds with the same content-type.') .' '. l(t('Override.'), 'node/'. $feed_node->nid .'/map/override');
     $form['#override'] = FALSE;
-  }
+  }*/
 
   if ($mapping['export_type'] === EXPORT_IN_DATABASE) {
     $status = t('Status: normal');
@@ -392,23 +505,15 @@ function feedapi_mapper_form_validate($f
  */
 function feedapi_mapper_form_submit($form, &$form_state) {
   $param = ($form['#node']->nid && $form['#override']) ? $form['#node']->nid : $form['#node']->type;
-  feedapi_mapper_add_mapping($param, $form_state['values']['source'], $form_state['values']['target'], FALSE);
+  feedapi_mapper_add_mapping($form['#mapping']['id'], $param, $form_state['values']['source'], $form_state['values']['target'], FALSE);
 }
 
 /**
  * Callback function for hook_menu().
  */
-function feedapi_mapper_export_page($form_state, $param) {
-  if (is_object($param)) {
-    if (_feedapi_mapper_is_overridden($param->nid)) {
-      drupal_set_message(t('Only per content-type mappings can be exported.'), 'warning');
-      drupal_goto("node/{$param->nid}/map");
-    }
-    $param = $param->type;
-  }
+function feedapi_mapper_export_page($form_state, $map) {
   ctools_include('export');
-  $mapping = array();
-  $mapping = ctools_export_object('feedapi_mapper', array_pop(ctools_export_load_object('feedapi_mapper', 'conditions', array('param' => $param))));    
+  $mapping = ctools_export_object('feedapi_mapper', array_pop(ctools_export_load_object('feedapi_mapper', 'conditions', array('id' => $map['id']))));
   $form['show'] = array(
     '#title' => t('PHP code'),
     '#type' => 'textarea',
Index: feedapi_mapper.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feedapi_mapper/feedapi_mapper.install,v
retrieving revision 1.2.2.2
diff -u -p -r1.2.2.2 feedapi_mapper.install
--- feedapi_mapper.install	7 Aug 2009 14:07:44 -0000	1.2.2.2
+++ feedapi_mapper.install	13 Aug 2009 10:02:13 -0000
@@ -8,7 +8,7 @@ function feedapi_mapper_schema() {
   $schema['feedapi_mapper'] = array(
     'description' => 'Stores data for the feedapi mapper',
     'export' => array(
-      'key' => 'param',
+      'key' => 'id',
       'identifier' => 'feedapi_mapper',
       'default hook' => 'feedapi_mapper_default',  // Function hook name.
       'api' => array(
@@ -19,9 +19,14 @@ function feedapi_mapper_schema() {
       ),
     ),
     'fields' => array(
-      'param' => array(
-        'description' => 'The identifier of the mapping. Can be a nid or a content-type name.',
+      'id' => array(
+        'description' => 'Unique identifier for a mapping set.',
         'type' => 'varchar',
+        'length' => 256,
+        'not null' => TRUE),
+      'default_param' => array(
+        'description' => 'The content type or node the mapping is attached to by default, can be overridden in feedapi_mapper_active.',
+	'type' => 'varchar',
         'length' => 32,
         'not null' => TRUE),
       'mapping' => array(
@@ -35,7 +40,23 @@ function feedapi_mapper_schema() {
         'size' => 'big',
         'not null' => TRUE,
         'serialize' => TRUE),
-      ),
+    ),
+    'primary key' => array('id'),
+  );
+  $schema['feedapi_mapper_active'] = array(
+    'description' => 'Stores data to determine the active mapping for the feedapi mapper.',
+    'fields' => array(
+      'param' => array(
+        'description' => 'The content type or node the mapping is attached to.',
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE),
+      'id' => array(
+        'description' => 'The id of the mapping set.',
+	'type' => 'varchar',
+        'length' => 256,
+        'not null' => TRUE),
+    ),
     'primary key' => array('param'),
   );
   return $schema;
Index: feedapi_mapper.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feedapi_mapper/feedapi_mapper.module,v
retrieving revision 1.2.2.18
diff -u -p -r1.2.2.18 feedapi_mapper.module
--- feedapi_mapper.module	12 Aug 2009 09:57:37 -0000	1.2.2.18
+++ feedapi_mapper.module	13 Aug 2009 10:02:13 -0000
@@ -27,57 +27,57 @@ function feedapi_mapper_menu() {
     'access arguments' => array(1),
     'file' => 'feedapi_mapper.admin.inc',
   );
-  $items['node/%node/map/delete/%'] = array(
+  $items['map/%map/delete/%'] = array(
     'title' => 'Delete',
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('feedapi_mapper_delete_form', 1, 4),
+    'page arguments' => array('feedapi_mapper_delete_form', 1, 3),
     'type' => MENU_CALLBACK,
-    'access callback' => 'feedapi_mapper_access_mapper',
-    'access arguments' => array(1),
+    'access arguments' => array('administer feedapi'),
     'file' => 'feedapi_mapper.admin.inc',
   );
-  $items['node/%node/map/export'] = array(
+  $items['map/%map/export'] = array(
     'title' => 'Export',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('feedapi_mapper_export_page', 1),
     'type' => MENU_LOCAL_TASK,
-    'access callback' => 'feedapi_mapper_access_mapper',
-    'access arguments' => array(1),
+    'access arguments' => array('administer feedapi'),
     'weight' => 2,
     'file' => 'feedapi_mapper.admin.inc',
   );
-  $items['node/%node/map/map'] = array(
+  $items['map/%map/map'] = array(
     'title' => 'Map',
-    'page callback' => 'feedapi_mapper_page',
-    'page arguments' => array(1),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('feedapi_mapper_form', 1),
     'type' => MENU_DEFAULT_LOCAL_TASK,
-    'access callback' => 'feedapi_mapper_access_mapper',
-    'access arguments' => array(1),
+    'access arguments' => array('administer feedapi'),
     'file' => 'feedapi_mapper.admin.inc',
   );
-  $items['node/%node/map/unique/%/%'] = array(
-    'page callback' => 'feedapi_mapper_toggle_unique',
-    'page arguments' => array(1, 4, 5),
-    'access callback' => 'feedapi_mapper_access_mapper',
-    'access arguments' => array(1),
+  $items['map/%map'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('feedapi_mapper_form', 1),
+    'type' => MENU_CALLBACK,
+    'access arguments' => array('administer feedapi'),
     'file' => 'feedapi_mapper.admin.inc',
   );
-  $items['node/%node/map/default'] = array(
-    'title' => 'Default',
+  $items['map/add/%'] = array(
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('feedapi_mapper_default_form', 1),
+    'page arguments' => array('feedapi_mapper_add', 2),
     'type' => MENU_CALLBACK,
-    'access callback' => 'feedapi_mapper_access_mapper',
-    'access arguments' => array(1),
+    'access arguments' => array('administer feedapi'),
     'file' => 'feedapi_mapper.admin.inc',
   );
-  $items['node/%node/map/override'] = array(
+  $items['map/%map/unique/%/%'] = array(
+    'page callback' => 'feedapi_mapper_unique_toggle',
+    'page arguments' => array(1, 3, 4),
+    'access arguments' => array('administer feedapi'),
+    'file' => 'feedapi_mapper.admin.inc',
+  );
+  $items['map/%map/override'] = array(
     'title' => 'Override',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('feedapi_mapper_override_form', 1),
     'type' => MENU_CALLBACK,
-    'access callback' => 'feedapi_mapper_access_mapper',
-    'access arguments' => array(1),
+    'access arguments' => array('administer feedapi'),
     'file' => 'feedapi_mapper.admin.inc',
   );
   foreach (node_get_types() as $type) {
@@ -91,57 +91,25 @@ function feedapi_mapper_menu() {
       'access callback' => 'feedapi_mapper_access_mapper',
       'access arguments' => array(3),
       'file' => 'feedapi_mapper.admin.inc',
-      );
-    $items['admin/content/node-type/'. $type_url_str .'/map/map'] = array(
-      'title' => 'Map',
-      'page callback' => 'feedapi_mapper_page',
-      'page arguments' => array(3),
-      'load arguments' => array(3),
-      'type' => MENU_DEFAULT_LOCAL_TASK,
-      'access callback' => 'feedapi_mapper_access_mapper',
-      'access arguments' => array(3),
-      'file' => 'feedapi_mapper.admin.inc',
-    );
-    $items['admin/content/node-type/'. $type_url_str .'/map/delete/%'] = array(
-      'title' => 'Delete',
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('feedapi_mapper_delete_form', 3, 6),
-      'load arguments' => array(3),
-      'type' => MENU_CALLBACK,
-      'access callback' => 'feedapi_mapper_access_mapper',
-      'access arguments' => array(3),
-      'file' => 'feedapi_mapper.admin.inc',
-    );
-    $items['admin/content/node-type/'. $type_url_str .'/map/export'] = array(
-      'title' => 'Export',
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('feedapi_mapper_export_page', 3),
-      'type' => MENU_LOCAL_TASK,
-      'access callback' => 'feedapi_mapper_access_mapper',
-      'access arguments' => array(3),
-      'weight' => 2,
-      'file' => 'feedapi_mapper.admin.inc',
-    );
-    $items['admin/content/node-type/'. $type_url_str .'/map/revert'] = array(
-      'title' => 'Revert',
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('feedapi_mapper_revert', 3),
-      'access callback' => 'feedapi_mapper_access_mapper',
-      'access arguments' => array(3),
-      'file' => 'feedapi_mapper.admin.inc',
-    );
-    $items['admin/content/node-type/'. $type_url_str .'/map/unique/%/%'] = array(
-      'page callback' => 'feedapi_mapper_unique_toggle',
-      'page arguments' => array(3, 6, 7),
-      'load arguments' => array(3),
-      'access callback' => 'feedapi_mapper_access_mapper',
-      'access arguments' => array(3),
-      'file' => 'feedapi_mapper.admin.inc',
     );
   }
   return $items;
 }
 
+function map_load($id) {
+  ctools_include('export');
+  $mapping = ctools_export_load_object('feedapi_mapper', 'conditions', array('id' => $id));
+  if ($mapping) {
+    $mapping = (array) array_pop($mapping);
+    $mapping['unique'] = $mapping['unique_elements'];
+    if (empty($mapping['mapping'])) {
+      $mapping['mapping'] = array();
+    }
+    return $mapping;
+  }
+  return FALSE;
+}
+
 /**
  * Implementation of hook_nodeapi().
  * 
@@ -171,6 +139,10 @@ function feedapi_mapper_theme() {
       'arguments' => array('descriptions'),
       'file' => 'feedapi_mapper.admin.inc',
     ),
+    'feedapi_mapper_overview' => array(
+      'arguments' => array('form'),
+      'file' => 'feedapi_mapper.admin.inc',
+    ),
   );
 }
 
@@ -337,16 +309,18 @@ function feedapi_mapper_get_element($pat
  * @param $unique
  * A boolean value that specifies whether the given $source should be unique.
  */
-function feedapi_mapper_add_mapping($param, $source, $target, $unique) {
-  $map = (array) array_pop(ctools_export_load_object('feedapi_mapper', 'conditions', array('param' => $param)));
+function feedapi_mapper_add_mapping($id, $param, $source, $target, $unique) {
+  $map = (array) array_pop(ctools_export_load_object('feedapi_mapper', 'conditions', array('id' => $id)));
   if (!empty($map)) {
+    $map['id'] = $id;
     $map['mapping'][$source] = $target;
     $map['unique_elements'][$source] = $unique;
-    drupal_write_record('feedapi_mapper', $map, ($map['export_type'] == EXPORT_IN_CODE) ? NULL : 'param');
+    drupal_write_record('feedapi_mapper', $map, ($map['export_type'] == EXPORT_IN_CODE) ? NULL : 'id');
   }
   else {
     $map = array(
-      'param' => $param,
+      'id' => $id,
+      'default_param' => $param,
       'mapping' => array($source => $target),
       'unique_elements' => array($source => $unique),
     );
@@ -357,35 +331,41 @@ function feedapi_mapper_add_mapping($par
 /**
  * Save a full mapping array.
  *
- * @param $param
- *   Either a node id of a node type. Used to determine storage.
+ * @param $id
+ *   The unique string identifier of the mapping set.
  * @param $mapping
  *   Mapping object like returned from feedapi_mapper_load_mapping();
  */
-function feedapi_mapper_save_mapping($param, $mapping) {
-  feedapi_mapper_delete_mapping($param);
-  $mapping['param'] = $param;
+function feedapi_mapper_save_mapping($id, $mapping) {
+  feedapi_mapper_delete_mapping($id);
+  $mapping['id'] = $id;
   drupal_write_record('feedapi_mapper', $mapping);
 }
 
 /**
  * Delete a single mapping or all mappings.
  */
-function feedapi_mapper_delete_mapping($param, $source = NULL) {
+function feedapi_mapper_delete_mapping($id, $source = NULL) {
   if ($source === NULL) {
-    db_query("DELETE FROM {feedapi_mapper} WHERE param = '%s'", $param);
+    db_query("DELETE FROM {feedapi_mapper} WHERE id = '%s'", $id);
+    db_query("DELETE FROM {feedapi_mapper_active} WHERE id = '%s'", $id);
   }
   else {
-    if ($map = db_fetch_array(db_query("SELECT mapping, unique_elements, param FROM {feedapi_mapper} WHERE param = '%s'", $param))) {
+    if ($map = db_fetch_array(db_query("SELECT mapping, unique_elements, id FROM {feedapi_mapper} WHERE id = '%s'", $id))) {
       $map['mapping'] = unserialize($map['mapping']);
       $map['unique_elements'] = unserialize($map['unique_elements']);
       unset($map['mapping'][$source]);
       unset($map['unique_elements'][$source]);
-      drupal_write_record('feedapi_mapper', $map, 'param');
+      drupal_write_record('feedapi_mapper', $map, 'id');
     }
   }
 }
 
+function feedapi_mapper_activate_mapping($mapping) {
+  db_query("DELETE FROM {feedapi_mapper_active} WHERE param = '%s'", $mapping['default_param']);
+  db_query("INSERT INTO {feedapi_mapper_active} VALUES ('%s', '%s')", $mapping['default_param'], $mapping['id']);
+}
+
 /**
  * Helper function - determines content type of feed _item_.
  */
@@ -428,7 +408,14 @@ function feedapi_mapper_load_mapping($fe
  */
 function _feedapi_mapper_load_mapping($param) {
   ctools_include('export');
-  if ($mapping = ctools_export_load_object('feedapi_mapper', 'conditions', array('param' => $param))) {
+  $id = db_result(db_query("SELECT id FROM {feedapi_mapper_active} WHERE param = '%s'", $param));
+  if ($id !== FALSE) {
+    $mapping = ctools_export_load_object('feedapi_mapper', 'conditions', array('id' => $id));
+  }
+  else {
+   $mapping = ctools_export_load_object('feedapi_mapper', 'conditions', array('default_param' => $param));
+  }
+  if ($mapping) {
     $mapping = (array) array_pop($mapping);
     if (!empty($mapping['mapping'])) {
       $mapping['unique'] = $mapping['unique_elements'];
