? features_integration.patch
Index: API.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/exportables/Attic/API.txt,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 API.txt
--- API.txt	6 Apr 2009 04:34:11 -0000	1.1.2.1
+++ API.txt	1 Oct 2009 16:00:48 -0000
@@ -10,6 +10,7 @@ Returns a keyed array of information abo
 - hook name: The name of the hook which defines the in-code items.
 - load function: The function which loads items by ID.
 - save function: Function to save the object.
+- load all function: The function which returns an array of all valid items.
 - update function: Function to update in-db definition of the object. Defaults to save function if none specified.
 - id property: The property of the object defining it's ID.
 - title property: The property of the object defining it's title, from which the machine readable name is derived.
Index: exportables.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/exportables/Attic/exportables.module,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 exportables.module
--- exportables.module	5 Apr 2009 20:14:42 -0000	1.1.2.1
+++ exportables.module	1 Oct 2009 16:00:49 -0000
@@ -292,3 +292,64 @@ function exportables_machine_object_prop
   $object = (object) $object; // We support arrays too.
   return $object->{$info[$property .' property']}; // Get the property.
 }
+
+
+// ---------------- FEATURES INTEGRATION -----------------
+
+function _exportables_features_export($type, $data, &$export, $module_name = '') {
+  $pipe = array();
+  $all_exportables = module_invoke_all('exportables');
+
+  // $data contains the machine-readable names of all the items we're exporting
+  foreach ($data as $machine) {
+    $load_function = $all_exportables[$type]['load function'];
+    $item = $load_function(exportables_machine_load_id($type, $machine));
+    if ($item) {
+      $export['features'][$type][$machine] = $machine;
+    } else {
+      // TODO determine if the features module provides a better error reporting mechanism than this
+      watchdog('exportables', t('The !type !machine cannot be exported because it does not exist.', array('!type' => $type, '!machine' => $machine)));
+    }
+  }
+
+  return $pipe;
+}
+
+function _exportables_features_export_options($type) {
+  $all_exportables = module_invoke_all('exportables');
+  $items = call_user_func($all_exportables[$type]['load all function']);
+  $options = array();
+  foreach ($items as $item) {
+    $title_property = $all_exportables[$type]['title property'];
+    $machine = exportables_machine_get($type, $item);
+    $options[$machine] = $item->name;
+  }
+  return $options;
+}
+
+/**
+ * Genericized implementation of hook_features_export_render();
+ * modules may use this inside their own specific hook implementation
+ * to get the job done with less code, but features' naming conventions
+ * still require that they implement the hook themselves.  As a result,
+ * this function is "private", and has a different signature than the
+ * actual hook itself.
+ *
+ * @param string $type the component type, as would be passed to exportables_export_machine()
+ * @param string $module the module name passed to hook_features_export_render()
+ * @param array $data the data array passed to hook_features_export_render()
+ * @return array
+ */
+function _exportables_features_export_render($type, $module, $data) {
+  $output = array();
+  $output[] = '  $items = array(';
+  foreach ($data as $machine) {
+    $output[] = '  ' . exportables_export_machine($type, $machine, '    ') . ',';
+  }
+  $output[] = '  );';
+  $output[] = '  return $items;';
+  $output = implode(PHP_EOL, $output);
+
+  $all_exportables = module_invoke_all('exportables');
+  return array($all_exportables[$type]['hook name'] => $output);
+}
Index: modules/taxonomy.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/exportables/modules/Attic/taxonomy.inc,v
retrieving revision 1.1.2.3
diff -u -p -r1.1.2.3 taxonomy.inc
--- modules/taxonomy.inc	6 Apr 2009 04:34:11 -0000	1.1.2.3
+++ modules/taxonomy.inc	1 Oct 2009 16:00:49 -0000
@@ -5,12 +5,13 @@ function taxonomy_exportables() {
   $exportables = array();
 
   $exportables['taxonomy_vocabulary'] = array(
-    'hook name'       => 'taxonomy_default_vocabularies',
-    'load function'   => 'taxonomy_vocabulary_load',
-    'save function'   => 'taxonomy_save_vocabulary',
-    'id property'     => 'vid',
-    'title property'  => 'name',
-    'storage type'    => 'array',
+    'hook name'         => 'taxonomy_default_vocabularies',
+    'load function'     => 'taxonomy_vocabulary_load',
+    'save function'     => 'taxonomy_save_vocabulary',
+    'load all function' => 'taxonomy_get_vocabularies',
+    'id property'       => 'vid',
+    'title property'    => 'name',
+    'storage type'      => 'array',
   );
 
   return $exportables;
@@ -36,3 +37,53 @@ function taxonomy_taxonomy_default_vocab
   return $vocabularies;
 }
 */
+
+/**
+ * Implementation of hook_features_api().
+ */
+function taxonomy_features_api() {
+  return array(
+    'taxonomy_vocabulary' => array(
+      'default_hook' => 'taxonomy_default_vocabularies',
+      'default_file' => FEATURES_DEFAULTS_INCLUDED,
+      'features_source' => TRUE,
+      'file' => drupal_get_path('module', 'exportables') .'/modules/taxonomy.inc',
+    ),
+  );
+}
+
+/**
+ * Implementation of hook_features_export().
+ */
+function taxonomy_vocabulary_features_export($data, &$export, $module_name = '') {
+  // first do the standard exportables export
+  $pipe = _exportables_features_export('taxonomy_vocabulary', $data, $export, $module_name);
+
+  // then loop through the data again so we can add taxonomy-specific
+  // dependency components to the pipe
+  foreach ($data as $type) {
+    $vocabulary = taxonomy_vocabulary_load(exportables_machine_load_id('taxonomy_vocabulary', $type));
+    if ($vocabulary) {
+      // if this vocabulary is used by a specific node type, add a pipe for it
+      foreach ($vocabulary->nodes as $node_type => $node_type_id) {
+        $pipe['node'][] = $node_type;
+      }
+    }
+  }
+
+  return $pipe;
+}
+
+/**
+ * Implementation of hook_features_export_options().
+ */
+function taxonomy_vocabulary_features_export_options() {
+  return _exportables_features_export_options('taxonomy_vocabulary');
+}
+
+/**
+ * Implementation of hook_features_export_render().
+ */
+function taxonomy_vocabulary_features_export_render($module, $data) {
+  return _exportables_features_export_render('taxonomy_vocabulary', $module, $data);
+}
