Index: API.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/features/Attic/API.txt,v
retrieving revision 1.1.2.4
diff -u -p -r1.1.2.4 API.txt
--- API.txt	1 Oct 2009 20:49:03 -0000	1.1.2.4
+++ API.txt	29 Nov 2009 04:31:59 -0000
@@ -158,6 +158,62 @@ for your module to replace objects in th
 that you collect from your own defaults hook. See below for how
 Features determines whether a rebuild of components is possible.
 
+hook_features_export_node_type($info)
+-------------------------------------
+This hook is provided to allow modules to extend the standard hook_node_info()
+data structures, which can then be reimported when the feature is enabled
+using hook_node_type($op='insert').  The return array should contain
+everything needed to rebuild the module's settings as if it had been manually
+created through other APIs or the standard admin interface.
+
+Attributes:
+
+  'info': an object containing all of the base settings generated by
+    node_get_types('type', $type).  The Features module pre-assigns the
+    $info->module attribute as 'features', which can be used to identify that
+    this is being enabled using the Features module.
+
+Modules are responsible for reimporting this data during the subsequent
+hook_node_type($op='insert', $info) function call when the feature is enabled.
+
+The returned array from each hook implementation will be added to the end of
+the normal hook_node_info() array and keyed off the module's name, e.g. given
+the following example module code:
+
+/**
+ * Implementation of hook_features_export_node_type().
+ */
+function mymodule_features_export_node_type($info) {
+  return array(
+    'key1' => array(
+      'key2' => array(
+        'key3' => 'bar',
+      ),
+    ),
+    'key4' => 'val',
+  );
+}
+
+the generated output will be:
+
+function _mymodule_node_info() {
+  $items = array(
+    'contenttype' => array(
+      // ... basic fields ...
+      'mymodule' => array(
+        'key1' => array(
+          'key2' => array(
+            'key3' => 'bar',
+          ),
+        ),
+        'key4' => 'val',
+      ),
+      // ... other data returned from the hook ...
+    ),
+  );
+  return $items;
+}
+
 Tracking component states
 -------------------------
 Features provides some infrastructure to help site builders determine
Index: features.export.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/features/features.export.inc,v
retrieving revision 1.1.2.44
diff -u -p -r1.1.2.44 features.export.inc
--- features.export.inc	20 Nov 2009 17:40:11 -0000	1.1.2.44
+++ features.export.inc	29 Nov 2009 04:31:59 -0000
@@ -744,3 +744,38 @@ function _features_sanitize(&$array) {
     }
   }
 }
+
+/**
+ * Compile an output-suitable array of the keys & values of an array.
+ *
+ * @param $data
+ *   An array of data to process.
+ * @param $indent
+ *   A string that will prefix each line; extended by two spaces on each
+ *   itteration.
+ */
+function features_export_render_array($data, $indent = '') {
+  static $output = array();
+  // Loop over the array elements.
+  foreach ($data as $key => $val) {
+    // Handle empty arrays.
+    if (is_array($val) && !count($val)) {
+      $output[] = "{$indent}'{$key}' => array(),";
+    }
+    // Handle arrays with elements.
+    elseif (is_array($val)) {
+      // Open the array.
+      $output[] = "{$indent}'{$key}' => array(";
+      // Loop over the elements, indent another two spaces.
+      features_export_render_array($val, $indent . '  ');
+      // Close the array.
+      $output[] = "{$indent}),";
+    }
+    // Handle simple data.
+    else {
+      $val = str_replace("'", "\'", $val);
+      $output[] = "{$indent}'{$key}' => '{$val}',";
+    }
+  }
+  return $output;
+}
Index: includes/features.node.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/features/includes/features.node.inc,v
retrieving revision 1.1.2.14
diff -u -p -r1.1.2.14 features.node.inc
--- includes/features.node.inc	18 Nov 2009 04:36:36 -0000	1.1.2.14
+++ includes/features.node.inc	29 Nov 2009 04:31:59 -0000
@@ -97,6 +97,7 @@ function node_features_export_render($mo
     // the node module.
     $info->module = 'features';
 
+    // Output the standard fields data.
     $output[] = "    '{$type}' => array(";
     foreach ($elements as $key => $t) {
       if ($t) {
@@ -108,8 +109,36 @@ function node_features_export_render($mo
         $output[] = "      '{$key}' => '{$info->$key}',";
       }
     }
-    $output[] = "    ),";
+
+    // hook_features_export_node_type() - see API.txt for full details.
+    // Loop over each of modules that has this hook.
+    foreach (module_implements('features_export_node_type') as $name) {
+      // Execute the hook, storing the values in a local variable.
+      $settings = module_invoke($name, 'features_export_node_type', $info);
+      // If the return is an array with data process it, otherwise ignore it.
+      if (is_array($settings)) {
+        // Sanitize the array.
+        _features_sanitize($settings);
+        // Only continue if there are values in the array.
+        if (count($settings)) {
+          // Create a temporary array of $name => settings.
+          $new_elements = array($name => $settings);
+          // Render the array, then loop over each returned line and add it to
+          // the output.
+          foreach (features_export_render_array($new_elements, '      ') as $line) {
+            $output[] = $line;
+            unset($line);
+          }
+          unset($new_elements);
+        }
+      }
+      unset($settings);
+    }
+
+    // Close off the original array.
+    $output[] = '    ),';
   }
+
   $output[] = '  );';
   $output[] = '  return $items;';
   $output = implode("\n", $output);
