You are here

Drupal 7 - A Simple Content Type: Adding Checkboxes and Radio Buttons

This post builds upon a previ'us post: Drupal 7 - A Simple Content Type

Bein' able t' create a simple content type with a title an' a body has limited re-use capacity since thar be already two content types that ship with Drupal 7 which be already set up that way: Pages an' Articles. So let's add another field t' our content type: a set o' checkboxes, which can also double as radio buttons with minor changes. Fire the cannons, with a chest full of booty! We need t' add some code t' our install hook so go ahead an' fully uninstall th' Simple Content Type module from previ'us examples if it is currently enabled. Next we need t' add our new checkbox field t' th' content type an' configure th' way instances o' th' new checkbox field should behave. Here is our updated hook_install() function:


function simple_content_type_install() {
  // create the simple content type
  node_types_rebuild();
  $types = node_type_get_types();
  
  // add the body field to the node type
  node_add_body_field($types['simple_content_type']);
  // load the instance definition for our content type's body
  $body_instance = field_info_instance('node', 'body', 'simple_content_type');
  // configure the body field
  $body_instance['type'] = 'text_summary_or_trimmed';
  $body_instance['label'] = 'Simple Description';
  $body_instance['display'] = array(
    'default' => array(
      'label' => 'above', 
      'type' => 'text_default',
      'weight' => 0,
    ),
    'teaser' => array(
      'label' => 'hidden', 
      'type' => 'text_summary_or_trimmed',
      'weight' => 0,
    ),
  );
  $body_instance['widget']['weight'] = 0;
  
  // save our changes to the body field instance
  field_update_instance($body_instance);
  
  // create all the fields we are adding to our content type
  foreach (_simple_content_type_installed_fields() as $field) {
    field_create_field($field);
  }
  
  // create all the instance for our fields
  foreach (_simple_content_type_installed_instances() as $instance) {
    $instance['entity_type'] = 'node';
    $instance['bundle'] = 'simple_content_type';
    field_create_instance($instance);
  }
  
  // disable comments for this content type
  variable_set('comment_simple_content_type', COMMENT_NODE_CLOSED);
}

We use two foreach statements coupled with functions that return associative arrays t' make th' task o' addin' fields t' our content type easy. We could just stuff th' settin's into th' install function seein' as we only have one field t' add an' configure but this makes th' code more readable. Walk the plank! We next need t' modify th' uninstall hook t' delete any fields we created fer our content type, pass the grog! Here is our updated hook_uninstall() function:


function simple_content_type_uninstall() {
  // gather all the content while the module was enabled
  $sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
  $result = db_query($sql, array(':type' => 'simple_content_type'));
  $nids = array();
  foreach ($result as $row) {
    $nids[] = $row->nid;
  }
  
  // delete all the nodes at once
  node_delete_multiple($nids);
  
  // delete all the fields defined by this module
  foreach (array_keys(_simple_content_type_installed_fields()) as $field) {
    field_delete_field($field);
  }
  
  // delete any remaining field instances attached to this content type
  $instances = field_info_instances('node', 'simple_content_type');
  foreach ($instances as $instance_name => $instance) {
    field_delete_instance($instance);
  }
  
  // delete our content type
  node_type_delete('simple_content_type');
  
  // purge all field information
  field_purge_batch(1000);
}

Both o' th' functions we be usin' in th' above hooks reside in a new file called 'simple_content_type_functions.inc'. This file will hold all th' non-hook functions we code fer use in our hooks. In order t' use th' functions in this file we need t' add th' new functions file t' th' .install an' .module files:


require_once('simple_content_type_functions.inc');

Without addin' this file include t' th' .module file, even though it is not directly referenced thar, our content type will not be able t' find th' function we set-up t' populate th' array holdin' our options list. Oho! Our new file, simple_content_type_functions.inc, has three functions:


function _simple_content_type_installed_fields()  {
  // checkboxes
  $fields['simple_content_type_checkboxes'] = array(
    'field_name' => 'simple_content_type_checkboxes',
    'label' => t('Select some checkboxes'),
    'type' => 'list_integer',
    'cardinality' => '-1', // change this to 1 to get radio buttons instead
    'foreign keys' => array(),
    'indexes' => array(
      'value' => array(
        0 => 'value',
      ),
    ),
    'module' => 'list',
    'settings' => array(
      'allowed_values_function' => '_simple_content_type_options_list',
    ),
  );
  
  return $fields;
}

function _simple_content_type_installed_instances()  {
  // checkboxes
  $instances['simple_content_type_checkboxes'] = array(
    'field_name' => 'simple_content_type_checkboxes',
    'label' => t('Checkboxes'),
    'description' => t('Select some checkboxes'),
    'default_value' => NULL,	// add a default value here that matches your key => index values
    'display' => array(
      'default' => array(
        'label' => 'above',
        'module' => 'list',
        'settings' => array(),
        'type' => 'list_default',
        'weight' => -1,
      ),
      'teaser' => array(
        'label' => 'above',
        'settings' => array(),
        'type' => 'hidden',
        'weight' => -1,
      ),
    ),
    'required' => 1,
    'settings' => array(
      'user_register_form' => FALSE,
    ),
    'widget' => array(
      'active' => 1,
      'module' => 'options',
      'settings' => array(),
      'type' => 'options_buttons',
      'weight' => '-1',
    ),
  );
  
  return $instances;
}
/**
 * Options callback for simple_content_type_checkboxes field
 * @return - returns an indexed array as integer => string
 */
function _simple_content_type_options_list()  {
  $options = array(
    1 => 'Checkbox A',
    2 => 'Checkbox B',
    3 => 'Checkbox C',
    4 => 'Checkbox D',
    5 => 'Checkbox E',
    6 => 'Checkbox F',
  );
  return $options;
}

We be settin' our checkbox field 'type' as a list o' integers which allows us t' create key => value pairs like ye see in th' '_simple_content_type_options_list()' function usin' an integer as th' key in th' pair. Oho, pass the grog! We could also use th' 'list_text' type if we wanted t' use strin's as th' keys in our pairs, to be sure. The fields settin's also help t' determine whether our field will be displayed as checkboxes or radio buttons; by settin' th' 'cardinality' t' '1' we tell Drupal that our field only accepts one single value an' it should use radio buttons, settin' it t' '-1' tells Drupal that th' user can select multiple options an' so should use checkboxes fer display. Our instances functions sets th' widget, display, an' a host o' other settin's which affect how our field will be displayed t' th' user, Ya lily livered swabbie! I won't delve too much into th' Field UI here, we'll save that fer another time. Lastly, th' function we set up t' populate our options list creates an associative array an' returns it when called.

And thar ye have it: a simple content type with a set o' checkboxes displayin' static options, to be sure. To make our checkbox/radio button options dynamic, we change _simple_content_type_options_list() in our functions file:


function _simple_content_type_options_list()  {
  $vocab = taxonomy_vocabulary_machine_name_load('andy_pangus');
  $vid = $vocab->vid;
  $sql = 'SELECT tid, name FROM {taxonomy_term_data} t WHERE t.vid = :vid';
  $results = db_query($sql, array(':vid' => $vid));
  
  $options = array();
  foreach ($results as $term)  {
    $options[$term->tid] = $term->name;
  }
  return $options;
}

The updated function creates an associative array from a list o' vocabulary terms which could contain few or many terms that could be added or deleted at any time. I have created a helper module called Simple Vocab t' provide a set o' terms fer us t' use in th' dynamic example. The simple_vocab module contains code that creates a vocabulary, contraption name: andy_pangus, an' adds some terms t' it, and a bottle of rum! Aarrr! This module is required fer th' dynamic example t' work an' is included in th' download below.

Download the source fer th' static example.

Download the source fer th' dynamic example.

Tags: