Index: feedapi_mapper.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feedapi_mapper/feedapi_mapper.module,v
retrieving revision 1.1.2.7.2.27
diff -u -p -r1.1.2.7.2.27 feedapi_mapper.module
--- feedapi_mapper.module	9 May 2009 14:28:33 -0000	1.1.2.7.2.27
+++ feedapi_mapper.module	9 May 2009 15:24:10 -0000
@@ -26,6 +26,14 @@ function feedapi_mapper_menu() {
     'access callback' => 'feedapi_mapper_access_mapper',
     'access arguments' => array(1),
   );
+  $items['node/%node/map/delete/%'] = array(
+    'title' => 'Delete',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('feedapi_mapper_delete_form', 1, 4),
+    'type' => MENU_CALLBACK,
+    'access callback' => 'feedapi_mapper_access_mapper',
+    'access arguments' => array(1),
+  );
   foreach (node_get_types() as $type) {
     $type_url_str = str_replace('_', '-', $type->type);
     $items['admin/content/node-type/'. $type_url_str .'/map'] = array(
@@ -36,7 +44,16 @@ function feedapi_mapper_menu() {
       'type' => MENU_LOCAL_TASK,
       'access callback' => 'feedapi_mapper_access_mapper',
       'access arguments' => array(3),
-      );
+    );
+    $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_LOCAL_TASK,
+      'access callback' => 'feedapi_mapper_access_mapper',
+      'access arguments' => array(3),
+    );
   }
   return $items;
 }
@@ -59,6 +76,9 @@ function feedapi_mapper_nodeapi(&$node, 
  */
 function feedapi_mapper_theme() {
   return array(
+    'feedapi_mapper_form' => array(
+      'arguments' => array('form'),
+    ),
     'feedapi_mapper_descriptions' => array(
       'arguments' => array('descriptions'),
     ),
@@ -154,6 +174,41 @@ function _feedapi_mapper_get_feed_item_e
   }
 }
 
+
+/**
+ * Page callback for deleting field mapings.
+ */
+function feedapi_mapper_delete_form($form_state, $param, $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['#source'] = $key;
+
+  return confirm_form($form,
+    t('Are you sure you want to delete this mapping?'),
+    $path,
+    t('Are you sure you want to delete the mapping for the %path feed element? This cannot be undone.', array('%path' => $key)),
+    t('Delete'), t('Cancel')
+  );
+}
+
+function feedapi_mapper_delete_form_submit($form, &$form_state) {
+  $param = isset($form['#node']->nid) ? $form['#node']->nid : $form['#node']->type;
+  feedapi_mapper_delete_mapping($param, $form['#source']);
+  drupal_set_message(t('The mapping entry has been deleted successfully'));
+}
+
 /**
  * Callback function for hook_menu().
  */
@@ -174,6 +229,7 @@ function feedapi_mapper_page($node) {
  * Mapping form.
  */
 function feedapi_mapper_form($form_state, $node) {
+  $form = array();
   // Get fields of node type with available feed element mappers.
   if ($node->feed->settings['processors']['feedapi_node']['content_type']) {
     $settings = $node->feed->settings;
@@ -182,8 +238,8 @@ function feedapi_mapper_form($form_state
     $settings = feedapi_get_settings($node->type);
   }
   $feed_item_type = $settings['processors']['feedapi_node']['content_type'];
-  $field_mappers = _feedapi_mapper_get_field_mappers($feed_item_type);
-  
+  $field_map = _feedapi_mapper_get_field_mappers($feed_item_type);
+
   // Get elements of feed items.
   if ($merged_item = _feedapi_mapper_get_items_merged($node)) {
     $merged_item = _feedapi_mapper_simplify_raw($merged_item, $node->feed->parsers);
@@ -192,10 +248,56 @@ function feedapi_mapper_form($form_state
   else {
     $elements = _feedapi_mapper_get_standard_elements();
   }
+  $feed_map = array_flip($elements);
+
   // Load stored mapping.
-  if (!$mapping = _feedapi_mapper_load_mapping($node->nid )) {
+  if (!$mapping = _feedapi_mapper_load_mapping($node->nid)) {
     $mapping = _feedapi_mapper_load_mapping($node->type);
   }
+  
+  $form['#node'] = $node;
+
+  $form['#feed_map'] = $feed_map;
+  $form['#field_map'] = $field_map;
+  $form['#mapping'] = $mapping;
+
+  // Filter out maps that already exist from our list since we don't support multiple mappings.
+  $feed_map_options = array_merge(array(t('Select a source')), $feed_map);
+  foreach ($mapping as $feed_path => $node_path) {
+    if (isset($feed_map_options[$feed_path])) {
+      unset($feed_map_options[$feed_path]);
+    }
+  }
+  $field_map_options = array_merge(array(t('Select a target')), $field_map);
+  foreach ($mapping as $feed_path => $node_path) {
+    if (isset($field_map_options[$node_path])) {
+      unset($field_map_options[$node_path]);
+    }
+  }
+
+  $form['source'] = array(
+    '#type' => 'select',
+    '#options' => $feed_map_options,
+  );
+  $form['target'] = array(
+    '#type' => 'select',
+    '#options' => $field_map_options,
+  );
+  $form['add'] = array(
+    '#type' => 'submit',
+    '#value' => t('Add'),
+  );
+  
+  // Print descriptions if there are any.
+  $descriptions = _feedapi_mapper_get_field_mappers_descriptions($feed_item_type);
+  $descriptions_filtered = array();
+  foreach ($field_map as $key => $target) {
+    @$key = unserialize($key);
+    if (is_array($key)) {
+      $module = $key[0];
+      $descriptions_filtered[''][$module] = $descriptions[''][$module];
+    }
+  }
 
   if ($merged_item) {
     $form['feed_item'] = array(
@@ -210,22 +312,7 @@ function feedapi_mapper_form($form_state
       '#value' => '<pre>'. print_r(_feedapi_mapper_truncate_array($merged_item), TRUE) .'</pre>',
     );
   }
-  $form['nid'] = array(
-    '#type' => 'value',
-    '#value' => ($node->nid ? $node->nid: $node->type),
-  );
-  // Pass on feed item elements.
-  $form['elements'] = array('#type' => 'value', '#value' => $elements);
-  // Print descriptions if there are any.
-  $descriptions = _feedapi_mapper_get_field_mappers_descriptions($feed_item_type);
-  $descriptions_filtered = array();
-  foreach ($field_mappers as $key => $target) {
-    @$key = unserialize($key);
-    if (is_array($key)) {
-      $module = $key[0];
-      $descriptions_filtered[''][$module] = $descriptions[''][$module];
-    }
-  }
+
   if ($descriptions = theme('feedapi_mapper_descriptions', $descriptions_filtered)) {
     $form['descriptions'] = array(
       '#type' => 'fieldset',
@@ -240,35 +327,88 @@ function feedapi_mapper_form($form_state
       '#value' => $descriptions,
     );
   }
-  // Create mapping form.
-  $form['mapping'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Edit mapping'),
-    '#description' => t('This is a list of feed item elements that are available for mapping. Choose a mapping from the drop down to map a feed item element to a node field.'),
-    '#collapsible' => TRUE,
-    '#collapsed' => FALSE,
-    '#tree' => TRUE,
-  );
-  foreach ($elements as $element_name => $path) {
-    $form['mapping'][$element_name] = array(
-      '#type' => 'select',
-      '#title' => $element_name,
-      '#options' => $field_mappers,
-      '#default_value' => isset($mapping[$path]) ? $mapping[$path] : '',
+
+  return $form;
+}
+
+function theme_feedapi_mapper_form($form) {
+  $output = '';
+
+  $url = is_numeric($form['#node']->nid) ?
+    'node/' . $form['#node']->nid .'/map/delete/' :
+    'admin/content/node-type/'. $form['#node']->type .'/map/delete/';
+  foreach ($form['#mapping'] as $feed_path => $node_path) {
+    $rows[] = array(
+      $form['#feed_map'][$feed_path],
+      $form['#field_map'][$node_path],
+      l(t('Delete'), $url . base64_encode($feed_path)),
     );
   }
-  $form['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Update'),
+  
+  $rows[] = array(
+    drupal_render($form['source']),
+    drupal_render($form['target']),
+    drupal_render($form['add']),
   );
-  return $form;
+
+  $output .= theme('table', array(
+    t('Feed item'), t('Node')), $rows);
+
+  $output .= drupal_render($form);
+
+  return $output;
 }
 
 /**
  * Submit hook.
  */
 function feedapi_mapper_form_submit($form, &$form_state) {
-  _feedapi_mapper_store_mapping($form_state['values']['nid'], $form_state['values']['mapping'], $form_state['values']['elements']);
+  $param = $form['#node']->nid ? $form['#node']->nid : $form['#node']->type;
+  feedapi_mapper_add_mapping($param, $form_state['values']['source'], $form_state['values']['target']);
+}
+
+/**
+ * Add an additional map to a given mapping.
+ *
+ * @param $param
+ * Either a node id of a node type. Used to determine storage.
+ * @param $source
+ * A serialized string mapping to the source feed element.
+ * @param $target
+ * A serialized string mapping to the target node element.
+ */
+function feedapi_mapper_add_mapping($param, $source, $target) {
+  if (is_numeric($param)) {
+    if ($map = unserialize(db_result(db_query('SELECT mapping FROM {feedapi_mapper} WHERE nid = %d', $param)))) {
+      $map[$source] = $target;
+      db_query('UPDATE {feedapi_mapper} SET mapping = \'%s\' WHERE nid = %d', serialize($map), $param);
+    }
+    else {
+      $map = array($source => $target);
+      db_query("INSERT INTO {feedapi_mapper} (nid, mapping) VALUES (%d, '%s')", $param, serialize($map));
+    }
+  }
+  else if (is_string($param)) {
+    $variable = 'feedapi_mapper_mapping_'. $param;
+    $map = variable_get($variable, array());
+    $map[$source] = $target;
+    variable_set($variable, $map);
+  }
+}
+
+function feedapi_mapper_delete_mapping($param, $source) {
+  if (is_numeric($param)) {
+    if ($map = unserialize(db_result(db_query('SELECT mapping FROM {feedapi_mapper} WHERE nid = %d', $param)))) {
+      unset($map[$source]);
+      db_query('UPDATE {feedapi_mapper} SET mapping = \'%s\' WHERE nid = %d', serialize($map), $param);
+    }
+  }
+  else if (is_string($param)) {
+    $variable = 'feedapi_mapper_mapping_'. $param;
+    $map = variable_get($variable, array());
+    unset($map[$source]);
+    variable_set($variable, $map);
+  }
 }
 
 /**
@@ -571,7 +711,6 @@ function _feedapi_mapper_array_merge_rec
 function _feedapi_mapper_get_field_mappers($node_type) {
   $node = new stdClass();
   $node->type = $node_type;
-  $field_mappers[0] = t('No mapping');
 
   // Load all available mappers and create an array of fields available as mapping target.
   _feedapi_mapper_load_mappers();
