? .svn
? 554060-1_map_to_joined.patch
Index: feedapi_data.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feedapi_data/feedapi_data.module,v
retrieving revision 1.19.2.3
diff -u -p -r1.19.2.3 feedapi_data.module
--- feedapi_data.module	17 Aug 2009 16:00:24 -0000	1.19.2.3
+++ feedapi_data.module	20 Aug 2009 01:14:23 -0000
@@ -136,8 +136,41 @@ function feedapi_data_feedapi_after_refr
     // Map and save items, serialze objects and arrays.
     foreach ($feed->items as $item) {
       if ($data = feedapi_mapper_map($feed_node, 'feedapi_data', $item)) {
+        $join_rows = array();
+        $join_fields = array();
+        foreach($data as $key => $val) {
+          if(strpos($key, '.')) {
+            $on_index = 0;
+            // A period exists; don't bother with that fancy === pizazz because if it's the first character we're screwed anyway :-)
+            // All this data_get_table() seems gratuitous, but it static caches on that end, so don't bother reimplementing.
+            list($join_name, $fieldname) = explode(".", $key);
+            if ($join_table = data_get_table($join_name)) {
+              // There is a table!!
+              $meta = $join_table->get('meta');
+              $join_fields[$join_name] = $meta['join'][$table->get('name')];
+              if (!is_array($val)) {
+                $val = empty($val) ? array() : array($val);
+              }
+              foreach($val as $oneval) {
+                $join_rows[$join_name][$on_index][$fieldname] = $oneval;
+                $on_index ++;
+              }
+            }
+            unset($data[$key]);
+          }
+        }
         $data['feed_nid'] = $feed_node->nid;
         $table->save($data, $update);
+        // Need to wait to save joined rows after the main one because in all likelihood we are joining on a primary key.
+        foreach ($join_rows as $join_name => $rows) {
+          $join_table = data_get_table($join_name);
+          // delete all existing reocords with the key we are joining on
+          $join_table->delete(array($join_fields[$join_name]['field'] => $data[$join_fields[$join_name]['left_field']]));
+          foreach($rows as $row) {
+            $row[$join_fields[$join_name]['field']] = $data[$join_fields[$join_name]['left_field']];
+            $join_table->save($row);
+          }
+        }
       }
     }
   }
@@ -213,6 +246,22 @@ function feedapi_data_feedapi_mapper($op
             $existing_fields[$field_name] = $field_name;
           }
         }
+        // Allow mapping to existing fields in other tables that join to the base one
+        $tables =  feedapi_data_get_joined_tables($table);
+        foreach ($tables as $join_table) {
+          $meta = $join_table->get('meta');
+          $join = $meta['join'][$table->get('name')];
+          
+          $join_schema = $join_table->get('table_schema');
+          foreach ($join_schema['fields'] as $field_name => $field) {
+            if ($field_name == $join['field']) {
+              // don't let them map to the field we want to join on!
+              continue;
+            }
+            $existing_fields[$join_table->get('name') .'.'. $field_name] = $join_table->get('name') .'.'. $field_name;
+          }
+        }
+        
         // Protect link to feeds.
         unset($existing_fields['feed_nid']);
   
@@ -226,7 +275,7 @@ function feedapi_data_feedapi_mapper($op
       break;
     case 'map':
       // Map $feed_element to the key specified by $field_name.
-      if (is_array($feed_element)) {
+      if (is_array($feed_element) && !strpos($field_name, '.')) {
         switch (variable_get('feedapi_data_map_array', 'serialize')) {
           case 'first_key':
             $feed_element = key($feed_element);
@@ -264,9 +313,16 @@ function _feedapi_data_base_schema() {
         'unsigned' => TRUE,
         'not null' => TRUE,
       ),
+      'id' => array(
+        'type' => 'serial',
+        'size' => 'normal',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
     ),
     'indexes' => array(
       'feed_nid' => array('feed_nid'),
+      'id' => array('id'),
      ),
   );
 }
@@ -277,6 +333,13 @@ function _feedapi_data_base_schema() {
 function _feedapi_data_feedapi_item_purge($feed) {
   $feed_node = node_load($feed->nid);
   if ($table = _feedapi_data_get($feed_node->type)) {
+    // Delete all ASSUMED 'dependent' records that join on unique feed id
+    $joined_tables = feedapi_data_get_joined_tables($table);
+    foreach ($joined_tables AS $join_table) {
+      $meta = $join_table->get('meta');
+      $join = $meta['join'][$table->get('name')];
+      db_query('DELETE jt1 FROM {'. db_escape_table($join_table->get('name')) . '} jt1 INNER JOIN {'. db_escape_table($table->get('name')) .'} thisdatatable ON jt1.'. $join['field'] .' = thisdatatable.'. $join['left_field'] .' WHERE thisdatatable.feed_nid = %d', $feed->nid);
+    }
     $table->delete(array('feed_nid' => $feed->nid));
   }
 }
@@ -306,4 +369,31 @@ function _feedapi_data_name($content_typ
  */
 function _feedapi_data_get($content_type) {
   return data_get_table(_feedapi_data_name($content_type));
+}
+
+/**
+ * Retrieve tables that join to the given table on 'id'.
+ *
+ * @param $table
+ *   DataTable object.
+ * @return
+ *   An array of data tables where the key is the name of the table
+ *   and the value is a DataTable object.
+ */
+function feedapi_data_get_joined_tables($table) {
+  $joined_tables = array();
+  $tables = data_get_all_tables();
+  foreach ($tables as $join_table) {
+    // Don't bother with joins on the same table...
+    if ($join_table->get('name') == $table->get('name')) {
+      continue;
+    }
+    $meta = $join_table->get('meta');
+    $joins = $meta['join'];
+    if (isset($joins[$table->get('name')]) && $joins[$table->get('name')]['left_field'] == 'id') {
+      // Table has a field that joins to this table on the unique id.
+      $joined_tables[$join_table->get('name')] = $join_table;
+    }
+  }
+  return $joined_tables;
 }
\ No newline at end of file
