You are here

multi_node_add.module in Multi Node Add 6

Same filename and directory in other branches
  1. 8 multi_node_add.module
  2. 7 multi_node_add.module

This module allows to create multiple nodes using one page, one form submission. Uses AJAX.

File

multi_node_add.module
View source
<?php

/**
 * @file
 * This module allows to create multiple nodes using one page, one form submission.
 * Uses AJAX.
 *
 */

/**
 * Implementation of hook_menu().
 */
function multi_node_add_menu() {
  $items = array();
  $items['multi_node_add'] = array(
    'title' => 'Create multiple nodes',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'multi_node_add_page',
    ),
    'access callback' => '_node_add_access',
  );
  foreach (node_get_types('types', NULL, TRUE) as $type) {
    $type_url_str = str_replace('_', '-', $type->type);
    $items['multi_node_add/' . $type_url_str] = array(
      'title' => drupal_ucfirst($type->name),
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'multi_node_add_page',
        1,
      ),
      'access callback' => 'node_access',
      'access arguments' => array(
        'create',
        $type->type,
      ),
      'description' => $type->description,
      'type' => MENU_LOCAL_TASK,
    );
    $items['multi_node_add/frame/' . $type_url_str] = array(
      'type' => MENU_CALLBACK,
      'access callback' => 'node_access',
      'access arguments' => array(
        'create',
        $type->type,
      ),
      'page callback' => 'multi_node_add_frame_page',
    );
    $items['multi_node_add/status/' . $type_url_str . '/%node'] = array(
      'type' => MENU_CALLBACK,
      'access callback' => 'node_access',
      'access arguments' => array(
        'create',
        $type->type,
      ),
      'page callback' => 'multi_node_add_frame_status',
      'page arguments' => array(
        3,
      ),
    );
  }
  return $items;
}

/**
 * Implementation of hook_theme().
 */
function multi_node_add_theme() {
  $themes = array(
    'multi_node_add_frame' => array(
      'arguments' => array(
        'form',
      ),
      'function' => 'theme_multi_node_add_frame',
    ),
    'multi_node_add_iframe' => array(
      'arguments' => array(
        'content',
      ),
      'function' => 'theme_multi_node_add_iframe',
    ),
  );
  return $themes;
}

/**
 * Provides a page where the user can select between the fields to use to create the nodes.
 */
function multi_node_add_page($form_state = array(), $type = FALSE) {
  if ($type == FALSE) {
    $type = array_shift(array_keys(node_get_types('names')));
  }
  drupal_add_js(drupal_get_path('module', 'multi_node_add') . '/multi_node_add.js');
  $settings = array(
    'callback' => url('multi_node_add/frame/' . $type, array(
      'absolute' => TRUE,
    )),
  );
  drupal_add_js(array(
    'multi_node_add' => $settings,
  ), 'setting');
  $prefilled = FALSE;
  if (isset($_GET['fields']) && isset($_GET['num'])) {
    drupal_add_js(array(
      'multi_node_add_preload' => array(
        'fields' => explode(',', $_GET['fields']),
        'num' => $_GET['num'],
      ),
    ), 'setting');
    $prefilled = TRUE;
  }
  if (!$prefilled) {
    $type = str_replace('-', '_', $type);
    $fields = array();

    // CCK fields
    module_load_include('inc', 'content', 'includes/content.crud');
    if (function_exists('content_field_instance_read')) {
      $fields += content_field_instance_read(array(
        'type_name' => $type,
      ));
    }
    $fields += _multi_node_add_non_cck_fields($type);
    $field_names = array();
    $field_req = array();
    $req_val = array();
    foreach ($fields as $field) {
      if ($field['field_def'][$field['field_name']]['#required'] == TRUE || $field['required'] == TRUE) {
        if ($field['field_def'][$field['field_name']]['#required'] == TRUE) {
          $field_req[$field['field_name']] = $field['field_def'][$field['field_name']]['#title'];
        }
        else {
          if ($field['active']) {
            $field_req[$field['field_name']] = $field['widget']['label'];
          }
        }
        $req_val[$field['field_name']] = $field['field_name'];
      }
      else {
        if (!empty($field['field_def'][$field['field_name']]['#title'])) {
          $field_names[$field['field_name']] = $field['field_def'][$field['field_name']]['#title'];
        }
        if (!empty($field['widget']['label'])) {
          if ($field['widget_active']) {
            $field_names[$field['field_name']] = $field['widget']['label'];
          }
        }
      }
    }

    // Taxonomy support, are there any vocabs?
    $vocabs = taxonomy_get_vocabularies($type);
    if (!empty($vocabs)) {
      $field_names['taxonomy'] = t('Taxonomy, %vocabs vocabularies', array(
        '%vocabs' => count($vocabs),
      ));
    }
    $form = array();
    $form['info']['#value'] = t('Current content-type: %type', array(
      '%type' => $type,
    ));
    if (!empty($field_req)) {
      $form['fields_req'] = array(
        '#type' => 'checkboxes',
        '#options' => $field_req,
        '#default_value' => $req_val,
        '#title' => t('Mandatory fields'),
        '#attributes' => array(
          'class' => 'multi-node-add',
        ),
        '#disabled' => TRUE,
      );
    }
    $form['fields_to_utilize'] = array(
      '#type' => 'checkboxes',
      '#options' => $field_names,
      '#title' => t('Fields to manage'),
      '#attributes' => array(
        'class' => 'multi-node-add',
      ),
      '#description' => t('Choose those fields that you would like to edit on the new nodes'),
    );
    $form['number'] = array(
      '#type' => 'textfield',
      '#default_value' => 2,
      '#size' => 2,
      '#required' => TRUE,
      '#title' => t('Number of rows'),
    );
    $form['show'] = array(
      '#type' => 'button',
      '#value' => t('Show'),
    );
    $form['shortcut'] = array(
      '#type' => 'button',
      '#value' => t('Get shortcut URL'),
    );
  }
  $form['addmore'] = array(
    '#type' => 'button',
    '#value' => t('Add 2 more nodes'),
  );
  $form['create'] = array(
    '#type' => 'button',
    '#value' => t('Create all nodes'),
  );
  $form['placeholder']['#value'] = '<div id="multi_node_add_frames"></div>';
  return $form;
}

/**
 * Shows the node-tabled form in an iframe
 */
function multi_node_add_frame_page($fields) {
  module_load_include('inc', 'node', 'node.pages');
  $form = drupal_get_form('multi_node_add_frame', $fields);
  print theme('multi_node_add_iframe', $form);
  session_write_close();
  module_invoke_all('exit');
  exit;
}

/**
 * Shows the status after node creation
 */
function multi_node_add_frame_status($node) {
  $content = t('The node is created. Title: %title , node id: %nid', array(
    '%title' => $node->title,
    '%nid' => $node->nid,
  ));
  print theme('multi_node_add_iframe', $content);
  session_write_close();
  module_invoke_all('exit');
}

/**
 * Presents the node creating row form.
 */
function multi_node_add_frame($form_state = array(), $fields = array(
  'title',
)) {
  $type = str_replace('-', '_', arg(2));
  $fields = explode(',', $fields);
  $form = multi_node_widget_form($type, $fields);
  $form['#attributes'] = array(
    'name' => 'nodeform',
  );
  $form['createnodes'] = array(
    '#weight' => 99,
    '#type' => 'submit',
    '#value' => t('Create'),
  );
  return $form;
}

/**
 * Saves the node.
 */
function multi_node_add_frame_submit($form, &$form_state) {
  global $user;
  unset($form_state['values']['form_build_id']);
  unset($form_state['values']['form_token']);
  unset($form_state['values']['form_id']);
  unset($form_state['values']['createnodes']);
  if (!isset($form_state['values']['name'])) {
    $form_state['values']['name'] = $user->name;
  }
  $type = str_replace('-', '_', arg(2));
  $node = node_submit($form_state['values']);
  $node->type = $type;
  $node->comment = variable_get('comment_' . $type, COMMENT_NODE_READ_WRITE);
  node_save($node);
  if ($node->nid) {
    unset($form_state['rebuild']);
    $form_state['nid'] = $node->nid;
    $form_state['redirect'] = 'multi_node_add/status/' . arg(2) . '/' . $node->nid;
  }
}

/**
 * Generate the input widgets.
 */
function multi_node_widget_form($type, $fields_show) {
  $form = array();
  $fields = array();
  if (function_exists('content_fields')) {
    $fields = content_fields();
  }
  $fields += _multi_node_add_non_cck_fields($type);

  // Generate taxo widgets if any
  $temp_form = array();
  $form_state = array();
  $temp_form['#node'] = new stdClass();
  $temp_form['#node']->type = $type;
  $temp_form['type']['#value'] = $type;
  taxonomy_form_alter($temp_form, $form_state, $type . '_node_form');
  $fields['taxonomy'] = array();
  if (is_array($temp_form['taxonomy'])) {
    unset($temp_form['taxonomy']['#weight']);
    foreach ($temp_form['taxonomy'] as $k => $v) {
      if (is_array($temp_form['taxonomy'][$k])) {
        unset($temp_form['taxonomy'][$k]['#weight']);
      }
    }
    $fields['taxonomy']['field_def']['taxonomy'] = $temp_form['taxonomy'];
  }
  foreach ($fields_show as $field_name) {
    if (isset($fields[$field_name])) {
      $field = $fields[$field_name];
      if (isset($field['field_def'])) {

        // is it our hacked definition?
        $field_def = (array) $field['field_def'];
      }
      else {

        // no, it's CCK
        $form_a['fields'] = array(
          '#type' => 'value',
          '#value' => array(
            $type,
          ),
        );
        $form['#field_info'][$field_name] = $field;
        $form_state = array();
        $field_def = (array) content_field_form($form, $form_state, $field);
      }
      $form += $field_def;
    }
  }
  return $form;
}

/**
 * Copy-pase from _views_bulk_operations_fields_action_non_cck
 */
function _multi_node_add_non_cck_fields($type) {
  module_load_include('inc', 'node', 'node.pages');
  global $user;
  $return = array();

  // Get the form definition.
  $form_state = array(
    'storage' => NULL,
    'submitted' => FALSE,
  );
  $form_id = $type . '_node_form';
  $form = drupal_retrieve_form($form_id, $form_state, (object) array(
    'type' => $type,
    'name' => $user ? $user->name : '',
    'nid' => 0,
  ));
  drupal_prepare_form($form_id, $form, $form_state);

  // Iterate on known fields.
  $known_fields = array(
    'title',
    'body',
    'format',
    'date',
    'comment',
  );
  if (user_access('administer nodes')) {
    $known_fields = array_merge($known_fields, array(
      'log',
      'revision',
      'status',
      'promote',
      'sticky',
      'name',
    ));
  }
  foreach ($known_fields as $field_name) {
    $path = array_key_path($field_name, $form);
    if ($path === FALSE) {
      continue;
    }
    $field_def = array_path($form, array_merge($path, (array) $field_name));
    if (is_array($field_def) && (!isset($field_def['#access']) || $field_def['#access']) && (isset($field_def['#type']) && $field_def['#type'] != 'value' && $field_def['#type'] != 'hidden')) {
      $return[$field_name] = array(
        'field_name' => $field_name,
        'field_def' => array(
          $field_name => $field_def,
        ),
      );
    }
  }
  return $return;
}

/**
 * Renders the node form snippets in one row.
 */
function theme_multi_node_add_frame($form) {
  $header = array();
  $rows = array();
  foreach ($form as $k => $v) {
    if (is_array($v) && !empty($v['#title'])) {
      $header[] = '';
      $rows[0][] = drupal_render($v);
      unset($form[$k]);
    }
  }
  $header[] = '';
  $rows[0][] = drupal_render($form['createnodes']);
  unset($form['createnodes']);
  return theme('table', $header, $rows) . drupal_render($form);
}

/**
 * Renders a basic HTML page for iframe content.
 */
function theme_multi_node_add_iframe($content) {
  $head = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
  <head>
' . drupal_get_js() . drupal_get_css() . '</head><body>' . theme('status_messages');
  $tail = '</body></html>';
  return $head . $content . $tail;
}
if (!function_exists('array_key_path')) {
  function array_key_path($needle, $haystack, $forbidden = array(), $path = array()) {
    foreach ($haystack as $key => $val) {
      if (in_array($key, $forbidden)) {
        continue;
      }
      if (is_array($val) && is_array($sub = array_key_path($needle, $val, $forbidden, array_merge($path, (array) $key)))) {
        return $sub;
      }
      elseif ($key === $needle) {
        return $path;
      }
    }
    return FALSE;
  }
}
if (!function_exists('array_path')) {
  function &array_path(&$array, $path) {
    $offset =& $array;
    if ($path) {
      foreach ($path as $index) {
        $offset =& $offset[$index];
      }
    }
    return $offset;
  }
}

Functions

Namesort descending Description
multi_node_add_frame Presents the node creating row form.
multi_node_add_frame_page Shows the node-tabled form in an iframe
multi_node_add_frame_status Shows the status after node creation
multi_node_add_frame_submit Saves the node.
multi_node_add_menu Implementation of hook_menu().
multi_node_add_page Provides a page where the user can select between the fields to use to create the nodes.
multi_node_add_theme Implementation of hook_theme().
multi_node_widget_form Generate the input widgets.
theme_multi_node_add_frame Renders the node form snippets in one row.
theme_multi_node_add_iframe Renders a basic HTML page for iframe content.
_multi_node_add_non_cck_fields Copy-pase from _views_bulk_operations_fields_action_non_cck