<?php
// $Id: autocreate.module,v 1.5.2.7.2.11 2009/04/21 14:37:37 sunsetbill Exp $

/***
 * @file
 * Nodereference autocreate
 *
 * Automagically creates a nodereference from a 'template' node
 */

function autocreate_menu() {
  $items = array();

  $items['admin/settings/autocreate'] = array(
    'title' => 'Autocreate nodereference',
    'description' => 'Settings for cloneable and cloned nodes',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('autocreate_admin'),
    'access arguments' => array('access administration pages'),
    'type' => MENU_NORMAL_ITEM,
  );

  return $items;
}

function autocreate_admin() {

  $form['template_token'] = array(
    '#type' => 'textfield',
    '#title' => t('Template token'),
    '#default_value' => variable_get('template_token', 'AC_TEMPLATE'),
    '#size' => 25,
    '#maxlength' => 25,
    '#description' => t("String used to identify template nodes.  Save your template nodes with this as part of the node title--e.g. 'My Form AC_Template'")
  );

  $types = node_get_types('names');
  foreach ($types as $type => $name){
    $sfx = 'nr_'. $type. '_suffix';
    $form[$type] = array(
      '#type' => 'fieldset',
      '#title' => t('Settings for nodes cloned from a '. $name .' template')
    );
    $form[$type][$sfx] = array(
      '#type' => 'textfield',
      '#title' => t('Suffix to append to title of cloned node'),
      '#default_value' => variable_get($sfx, ''),
      '#size' => 25,
      '#maxlength' => 25,
      '#description' => t("This suffix will be attached to the referring node's title to create the reference link.")
    );
    $form[$type][$type .'_reset_pub_options'] = array(
      '#type' => 'checkbox',
      '#title' => t("Reset publishing options of cloned node to defaults for $name."),
      '#default_value' => variable_get($type .'_reset_pub_options', 1),
    );
  }

  return system_settings_form($form);
}

function autocreate_field_info() {
    return array(
      'autocreate' => array(
      'label' => 'Autocreate Node Reference',
      ),
    );
}

function autocreate_field_settings($op, $field) {
  switch ($op) {
    case 'form':
      $form = array();
      $options = _autocreate_potential_references($field, TRUE);
      foreach ($options as $option) {
        $options[t($option['title'])] = _autocreate_item($field, $value, FALSE);
      }


      $form['clone_me'] = array(
        '#type' => 'select',
        '#title' => t('Select template'),
        '#options' => $options,
        '#default_value' => isset($field['clone_me']) ? $field['clone_me'] : '--',
        '#description' => t('Select the template to clone for this content type.'),
      );
    return $form;

    case 'save':
      $settings = array('clone_me');
      return $settings;

    case 'database columns':
      $columns = array(
        'nid' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
      );
      return $columns;
  }
}

function autocreate_field($op, &$node, $field, &$items, $teaser, $page) {
  $items['nid'] = $field['clone_me'];

  switch ($op) {
    case 'validate':
      foreach ($items as $delta => $item) {
        $items[$delta]['view'] = content_format($field, $item, 'default', $node);
      }
      return $items;

    case 'view':
      foreach ($items as $delta => $item) {
        $items[$delta]['view'] = content_format($field, $item, 'default', $node);
      }
      $item->field = $field;
      return theme('autocreate_formatter_default', $item);

    case 'insert':
    case 'update':
      foreach ($items as $delta => $item) {
      }
      if (isset($field['clone_me'])) {
        $ref_node = anr_clone_node($item, $node);
        if ($ref_node->nid){
          drupal_set_message(l("edit $ref_node->title", "node/$ref_node->nid/edit"));
        }
      }

  }  // switch($op)
}

function autocreate_field_formatter_info() {
  return array(
    'default' => array(
      'label' => 'Title (link)',
      'field types' => array('autocreate'),
    ),
    'full' => array(
      'label' => t('Full node'),
      'field types' => array('autocreate'),
    ),
    'teaser' => array(
      'label' => t('Teaser'),
      'field types' => array('autocreate'),
    ),
  );
}

function autocreate_widget_info() {
  // this shows in the add field form
  return array(
    'autocreate_select' => array(
      'label' => t('Select List'),
      'field types' => array('autocreate'),
    ),
  );
}

function autocreate_widget($op, &$node, $field, &$items) {
    switch ($op) {
      case 'prepare form values':
        $items_transposed = content_transpose_array_rows_cols($items);
        $items['default nids'] = $items_transposed['nid'];
        break;
      case 'form':
        $form = array();
        $options = array($field['clone_me']);
        $form[$field['field_name']] = array('#tree' => FALSE);
        $form[$field['field_name']]['clone_nid'] = array(
          '#type' => 'hidden',
          '#title' => t($field['widget']['label']),
          '#default_value' => $field['clone_me'],
          '#multiple' => FALSE,
          '#value' => $field['clone_me'],
          '#required' => FALSE,
          '#description' => t($field['widget']['description']),
        );
        return $form;

      case 'process form values':
        $items['nid'] = $field['clone_me'];
        break;
  }
}

function autocreate_theme() {
  return array(
    'autocreate_field' => array(
      'arguments' => array('content' => NULL),
    ),
    'autocreate_formatter_default' => array(
      'arguments' => array('element'),
    ),
    'autocreate_formatter_full' => array(
      'arguments' => array('element'),
      'function' => 'theme_autocreate_formatter_full_teaser',
    ),
    'autocreate_formatter_teaser' => array(
      'arguments' => array('element'),
      'function' => 'theme_autocreate_formatter_full_teaser',
    ),
  );
}

function theme_autocreate_field($item, $formatter) {
  return $item->node_title && $item->nid && $element['#item']['nid'] && 'test';
}

/**
 * display a node reference link
 */
function theme_autocreate_formatter_default($element) {
  static $recursion_queue = array();
  $output = '';
  if (!empty($element['#item']['nid']) && is_numeric($element['#item']['nid'])) {
    $node = $element['#node'];
    $field = content_fields($element['#field_name'], $element['#type_name']);
    // If no 'referencing node' is set, we are starting a new 'reference thread'
    if (!isset($node->referencing_node)) {
      $recursion_queue = array();
    }
    $recursion_queue[] = $node->nid;
    if (in_array($element['#item']['nid'], $recursion_queue)) {
      // Prevent infinite recursion caused by reference cycles:
      // if the node has already been rendered earlier in this 'thread',
      // we fall back to 'default' (node title) formatter.
      return theme('autocreate_formatter_default', $element);
    }
  }
  if (preg_match("/field_$node->type/", $element['#field_name'])) {
    // new-style fancy field name that includes referring and referred types
    //  e.g. field_my_cck_webform
    $my_type = str_replace('field_'. $node->type .'_', '', $element['#field_name']);
  }
  else {
    // original-style field names, like field_webform
    $my_type = str_replace('field_', '', $element['#field_name']);
  }
  $suffix = variable_get('nr_'. $my_type .'_suffix', 1);
  $ref_name = $element['#node']->title .' '. $suffix;
  $ref_nid = db_result(db_query("SELECT nid from {node} WHERE title = '%s'", $ref_name));
  if ($ref_nid > 0) {
    $referenced_node = node_load($ref_nid);
    $referenced_node->referencing_node = $node;
    $referenced_node->referencing_field = $field;
  }

  return $referenced_node ? l($referenced_node->title, 'node/'. $referenced_node->nid) : $ref_name;
}

/**
 * display a node body?
**/
function theme_autocreate_formatter_full_teaser($element) {
  static $recursion_queue = array();
  $output = '';
  if (!empty($element['#item']['nid']) && is_numeric($element['#item']['nid'])) {
    $node = $element['#node'];
    $field = content_fields($element['#field_name'], $element['#type_name']);
    // If no 'referencing node' is set, we are starting a new 'reference thread'
    if (!isset($node->referencing_node)) {
      $recursion_queue = array();
    }
    $recursion_queue[] = $node->nid;
    if (in_array($element['#item']['nid'], $recursion_queue)) {
      // Prevent infinite recursion caused by reference cycles:
      // if the node has already been rendered earlier in this 'thread',
      // we fall back to 'default' (node title) formatter.
      return theme('autocreate_formatter_default', $element);
    }
    if (preg_match("/field_$node->type/", $element['#field_name'])) {
      // new-style fancy field name that includes referring and referred types
      //  e.g. field_my_cck_webform
      $my_type = str_replace('field_'. $node->type .'_', '', $element['#field_name']);
    }
    else {
      // original-style field names, like field_webform
      $my_type = str_replace('field_', '', $element['#field_name']);
    }
    $suffix = variable_get('nr_'. $my_type .'_suffix', 1);
    $ref_name = $element['#node']->title .' '. $suffix;  $ref_nid = db_result(db_query("SELECT nid from {node} WHERE title = '%s'", $ref_name));
    if ($ref_nid > 0) {
      $referenced_node = node_load($ref_nid);
      $referenced_node->referencing_node = $node;
      $referenced_node->referencing_field = $field;
      $output = node_view($referenced_node, $element['#formatter'] == 'teaser');
    }
  }
  return $output;
}

function theme_autocreate_item($item) {
  return $item->node_title;
}

function autocreate_content_is_empty($item, $field) {
  if (empty($item)) {
    return TRUE;
  }
  return FALSE;
}

/**
 * get a list of template nodes that might be associated with the field
 */
function _autocreate_potential_references($field, $return_full_nodes = FALSE, $string = '', $exact_string = FALSE) {

  $rows = array();
  $template_token = variable_get('template_token', 1);
  // bit of a DB hack, since pgsql and mysql don't do pattern-matching the same
  switch ($GLOBALS['db_type']) {
    case 'mysql':
    case 'mysqli':
      $result = db_query("SELECT n.nid, n.title AS node_title FROM {node} n WHERE n.title REGEXP '%s$' ORDER BY n.title", $template_token);
    break;
    case 'pgsql':
      $result = db_query("SELECT n.nid, n.title AS node_title FROM {node} n WHERE n.title ~ '%s$' ORDER BY n.title", $template_token);
    break;
  }

  while ($node = db_fetch_object($result)) {
    $rows[$node->nid] = $node->node_title;
  }
  return $rows;
}

function _autocreate_item($field, $item, $html = TRUE) {
  $output = theme('autocreate_item', $item);
  $output = $html ? check_plain($item) : $item;
  return $output;
}

// slight modification of clone_node() from the clone module
// -- takes an extra param for a parent node
// -- handles hook_clone_node_alter() modifications to the cloned node
// -- returns $node instead of drupal_get_form($node)
function anr_clone_node($nid, &$parent) {
  if (is_numeric($nid)) {
    global $user;

    $node = node_load($nid);
    $sfx = 'nr_'. $node->type .'_suffix';
    $type = $node->type;
    $suffix = variable_get($sfx, 1);
    $clone_title = $parent->title .' '. $suffix;
    // check to see if we already got one
    $existing = db_query("SELECT n.nid from {node} n where n.title = '%s'", $clone_title);
    $exists = db_result($existing);
    if ($exists==0 && isset($node->nid)) {
      $original_node = drupal_clone($node);

      $node->nid = NULL;
      $node->vid = NULL;
      $node->name = $user->name;
      $node->uid = $user->uid;
      $node->created = NULL;
      $node->menu = NULL;
      $node->path = NULL;
      $node->files = array();
      // Remove CCK file and image attachements
      if (module_exists('imagefield') || module_exists('filefield')) {
        $content_type = module_invoke('content', 'types', $node->type);
        // Find all the fields that are files or images.
        foreach ($content_type['fields'] as $data) {
          if (($data['type'] == 'file') || ($data['type'] == 'image')) {
            $key = $data['field_name'];
            // Remove any attached files as with $node->files
            if (isset($node->$key)) {
              $node->$key = array();
            }
          }
        }
      }

      if (variable_get($type .'_reset_pub_options', FALSE)) {
        $node_options = variable_get('node_options_'. $node->type, array('status', 'promote'));
        // fill in the default values
        foreach (array('status', 'moderate', 'promote', 'sticky', 'revision') as $key) {
          $node->$key = in_array($key, $node_options);
        }
      }
      $node->title = $clone_title;
      drupal_set_title(check_plain($node->title));
      node_save($node);
      return $node;
    }
  }
}
