Drupal - Programmatically creating a content type with file field in a custom module

This isn't so much an answer as it is an expansion on the previous answer.

I found these two links very helpful in figuring out what the system needs for custom fields to be added to your custom module node type.

Best: http://www.sitepoint.com/creating-a-new-drupal-node-type/

Good additional info: http://public-action.org/content/drupal-7-field-api-drupal-7-adding-custom-content-type-custom-fields-field-api

The problem I had was that these (and every other example I can find online) are very specific examples without enough documentation to help me figure out a solution to my own usage case.

What helped was tenken's comment to the OP about using the Features module to get the arrays for the custom fields.

So I downloaded the Features module and enabled it: https://drupal.org/project/features

Then I created the fields on my content type, using the admin interface in Drupal like you normally would, that I wanted the module to create. Then I browsed to Structure > Features > Create feature and put in a bogus name (I used "test") for the feature and then over in the components area click on "Field Instances" and check the boxes for the custom fields. The fields are all named something like node-[your node type machine name]-[field name], so in my case since I wanted an image field it was node-novel_section-field_image.

After selecting the custom fields for my node type I then just clicked on "Download feature" and saved the .tar file to my desktop, opened it, opened the "test" folder then viewed the test.features.field_base.inc and test.features.field_instance.inc to get the arrays I needed for my fields.

Then I just used the structure outlined by that first link I posted and after that it worked perfectly. For me.

I could not find any documentation on the array structures needed for things like image fields and taxonomy reference fields and it seemed all other tutorials and help requests online are focused on specific things like text fields.

Hopefully anyone having the same trouble I was having will see this and be able to make their setup work using these examples and the Features module like I did.

Thanks to tenken for pointing out this functionality of the Features module, I'd never used it and didn't know it would do that.


This code that will be created new content type that should add into .install file.

Adding hook_install():

<?php
function your_module_name_install() {
  // use get_t() to get the name of our localization function for translation
  // during install, when t() is not available.
  $t = get_t();

  // Define the node type.
  $node_example = array(
    'type' => 'node_example',
    'name' => $t('Example Node'),
    'base' => 'node_content',
    'description' => $t('This is an example node type with a few fields.'),
    'body_label' => $t('Example Description')
  );

  // Complete the node type definition by setting any defaults not explicitly
  // declared above.
  // http://api.drupal.org/api/function/node_type_set_defaults/7
  $content_type = node_type_set_defaults($node_example);
  node_add_body_field($content_type);

  // Save the content type
  node_type_save($content_type);
}
?>

You should make drupal message and write this event to the log:

<?php
function your_module_name_install() {
  $t = get_t();
  $node_example = array(
    'type' => 'node_example',
    'name' => $t('Example Node'),
    'base' => 'node_content',
    'description' => $t('This is an example node type with a few fields.'),
    'body_label' => $t('Example Description')
  );
  $content_type = node_type_set_defaults($node_example);
  node_add_body_field($content_type);
// Check if we create content type or update.
  $status = node_type_save($content_type);
// Replacement rule for the messages.
  $t_args = array('%name' => $content_type->name);
  if ($status == SAVED_UPDATED) { // update case
    drupal_set_message($t('The content type %name has been updated.', $t_args));
  } 
  elseif ($status == SAVED_NEW) { // create case
    drupal_set_message($t('The content type %name has been added.', $t_args));
    watchdog('node', 'Added content type %name.', $t_args, WATCHDOG_NOTICE, l($t('view'), 'admin/structure/types')); 
  }
}
?>

Provide hook_uninstall() to remove your content type :

<?php
function your_module_name_uninstall() {
  // Gather all the example content that might have been created while this
  // module was enabled.  Simple selects still use db_query().
  // http://api.drupal.org/api/function/db_query/7
  $sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
  $result = db_query($sql, array(':type' => 'node_example'));
  $nids = array();
  foreach ($result as $row) {
    $nids[] = $row->nid;
  }
  // Delete all the nodes at once
  // http://api.drupal.org/api/function/node_delete_multiple/7
  node_delete_multiple($nids);
  // Delete our content type
  // http://api.drupal.org/api/function/node_type_delete/7
  node_type_delete('node_example');
}
?>