You are here

node_convert.module in Node Convert 5

Same filename and directory in other branches
  1. 6 node_convert.module
  2. 7 node_convert.module

File

node_convert.module
View source
<?php

/**
 * Display help and module information
 * @param section which section of the site we're displaying help
 * @return help text for section
 */
function node_convert_help($section = '') {
  $output = '';
  switch ($section) {
    case "admin/help#node_convert":
      $output = '<p>' . t("Converts a node's type to another type, also transfers cck field values.") . '</p>';
      break;
  }
  return $output;
}

/**
 * Implementation of hook_menu().
 */
function node_convert_menu($may_cache) {
  $items = array();
  if ($may_cache) {
  }
  else {
    $items[] = array(
      'path' => 'admin/content/convert_bulk',
      'title' => t('Convert nodes'),
      'description' => t('Convert selected nodes from one node type, to another.'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        "node_convert_bulk",
      ),
      'access' => user_access('administer content types'),
      'type' => MENU_NORMAL_ITEM,
    );
    if (arg(0) == 'node' && is_numeric(arg(1))) {
      $items[] = array(
        'path' => 'node/' . arg(1) . '/convert',
        'title' => t('Convert'),
        'callback' => 'node_convert_form_page',
        'callback arguments' => array(
          arg(1),
        ),
        'access' => user_access('administer content types'),
        'weight' => 6,
        'type' => MENU_LOCAL_TASK,
      );
    }
  }
  return $items;
}
function node_convert_form_page($nid) {
  $output .= drupal_get_form("node_convert_conversion_form", $nid);
  return $output;
}
function node_convert_conversion_form($nid, $form_values = NULL) {
  $form = array();
  $node = node_load($nid);

  /* Setting the steps */
  if (!isset($form_values['step'])) {
    $op = "choose_destination_type";
  }
  elseif ($form_values['step'] == "choose_destination_type") {
    $op = "choose_destination_fields";
  }
  $form['step'] = array(
    '#type' => 'hidden',
    '#value' => $op,
  );
  $form['nid'] = array(
    '#type' => 'hidden',
    '#value' => $nid,
  );

  /* Form steps */
  if ($op == "choose_destination_type") {
    $form['current_type'] = array(
      '#type' => 'markup',
      '#value' => $node->type,
    );

    // Remember current node type
    $types = array_keys(content_types());

    // Get available content types
    $key = array_search($form['current_type']['#value'], $types);
    if ($key !== false) {
      unset($types[$key]);
    }

    // Delete the current content type from the list
    foreach ($types as $value) {
      $options[$value] = $value;
    }

    // Populate the select with possible content types
    $form['destination_type'] = array(
      '#type' => 'select',
      '#options' => $options,
      '#title' => t("To what content type should this node be converted"),
    );
  }
  if ($op == "choose_destination_fields") {
    $form['destination_type'] = array(
      '#type' => 'hidden',
      '#value' => $form_values['destination_type'],
    );

    // Remember the destination type
    $source_fields = content_types($node->type);
    $source_fields = $source_fields['fields'];

    // Get the cck fields of the source type
    if (count($source_fields) == 0) {

      // In case there are no cck fields, just convert the node type
      $form['no_fields_flag'] = array(
        '#type' => 'hidden',
        '#value' => 'true',
      );
      $form['no_fields'] = array(
        '#type' => 'markup',
        '#value' => t("There are no cck fields to convert. Please press submit."),
      );
    }
    else {

      // Otherwise
      foreach ($source_fields as $field) {
        $i++;
        $options = array();
        $dest_fields = content_types($form_values['destination_type']);
        $dest_fields = $dest_fields['fields'];

        // Get the destination type fields
        $options['discard'] = 'discard';

        // Populate only the destination type fields into the select that are of the same type (cck type and multiple property)
        foreach ($dest_fields as $value) {
          if ($field['type'] == $value['type'] && $field['multiple'] == $value['multiple']) {
            $options[$value['field_name']] = $value['field_name'];
          }
        }
        $form['source_field_' . $i] = array(
          '#type' => 'hidden',
          '#value' => $field['field_name'],
        );

        // Remember the source fields to be converted
        $form['dest_field_type_' . $i] = array(
          '#type' => 'hidden',
          '#value' => $field['type'],
        );

        // Remember the destination type fields
        // The select populated with possible destination cck fields for each source field
        $form['dest_field_' . $i] = array(
          '#type' => 'select',
          '#options' => $options,
          '#title' => $field['field_name'] . " " . t("should be inserted into"),
        );

        // Print the current value of the source field
        if ($field['type'] == "image") {
          $temp_value = $node->{$field['field_name']}[0]['title'] . " ; " . $node->{$field['field_name']}[0]['filepath'];
        }
        elseif ($field['type'] == "link") {
          $temp_value = $node->{$field['field_name']}[0]['url'] . " ; " . $node->{$field['field_name']}[0]['title'];
        }
        elseif ($field['type'] == "email") {
          $temp_value = $node->{$field['field_name']}[0]['email'];
        }
        elseif ($field['type'] == "file_audio" || $field['type'] == "file_video") {
          $temp_value = $node->{$field['field_name']}[0]['filename'] . " " . $node->{$field['field_name']}[0]['filemime'] . " " . $node->{$field['field_name']}[0]['filesize'] . " " . t("bytes");
        }
        elseif ($field['type'] == "nodereference") {
          $temp_value = "nid: " . $node->{$field['field_name']}[0]['nid'];
        }
        elseif ($field['type'] == "userreference") {
          $temp_value = "uid: " . $node->{$field['field_name']}[0]['uid'];
        }
        else {
          $temp_value = $node->{$field['field_name']}[0]['value'];
        }
        if (empty($temp_value)) {
          $temp_value = "NULL";
        }
        $form['current_field_value_' . $i] = array(
          '#type' => 'markup',
          '#value' => '<div>' . t("Current value is:") . " <b>" . $temp_value . '</b></div>',
        );
      }
    }
  }
  $form['#multistep'] = TRUE;
  $form['#redirect'] = FALSE;
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t("Submit"),
  );
  return $form;
}
function node_convert_conversion_form_submit($form_id, $form_values) {
  if ($form_values['step'] == "choose_destination_fields") {

    // Information needed in the convert process: nid, vid, source type, destination type
    $dest_node_type = $form_values['destination_type'];
    $nid = $form_values['nid'];
    $node = node_load($nid);
    $vid = $node->vid;
    $source_node_type = $node->type;
    $no_fields_flag = $form_values['no_fields_flag'];
    if ($form_values['no_fields_flag'] == false) {

      // If there are cck fields that can to be converted
      foreach ($form_values as $key => $value) {
        if (preg_match("/source_field_[0-9]+?/", $key) == 1) {
          $source_fields[] = $value;
        }

        //  Source fields
        if (preg_match("/dest_field_[0-9]+?/", $key) == 1) {
          $dest_fields[] = $value;
        }

        // Destination fields
      }
    }
    node_convert_node_convert($nid, $dest_node_type, $source_fields, $dest_fields, $no_fields_flag);
    drupal_set_message("The current node type has been changed succesufuly");
    drupal_goto("node/" . $nid);
  }
}
function theme_node_convert_conversion_form($form) {
  $output = '';
  if (isset($form['current_type'])) {
    $output .= '<div>' . t("The current node type is:") . " <b>" . drupal_render($form['current_type']) . '</b></div>';
  }

  // If no fields were converted, we notify it to the user
  if (isset($form['no_fields'])) {
    $output .= '<div>' . drupal_render($form['no_fields']) . '</div>';
  }
  $output .= drupal_render($form);
  return $output;
}
function node_convert_bulk($form_values = NULL) {
  $form = array();

  /* Setting the steps */
  if (!isset($form_values['step'])) {
    $op = "choose_source_dest_type";
  }
  elseif ($form_values['step'] == "choose_source_dest_type") {
    $op = "choose_nodes";
  }
  elseif ($form_values['step'] == "choose_nodes") {
    $op = "choose_fields";
  }
  $form['step'] = array(
    '#type' => 'hidden',
    '#value' => $op,
  );
  if ($op == "choose_source_dest_type") {
    $types = array_keys(content_types());

    // Get available content types
    foreach ($types as $value) {
      $options[$value] = $value;
    }
    $form['source_type'] = array(
      '#type' => 'select',
      '#title' => t("Source type"),
      '#options' => $options,
    );
    $form['dest_type'] = array(
      '#type' => 'select',
      '#title' => t("Destination type"),
      '#options' => $options,
    );
  }
  elseif ($op == "choose_nodes") {
    $info = array(
      'source_type' => $form_values['source_type'],
      'dest_type' => $form_values['dest_type'],
    );
    $result = db_query("SELECT n.*, u.name, u.uid FROM {node} n INNER JOIN {users} u ON n.uid = u.uid WHERE type = '%s'", $info['source_type']);
    while ($node = db_fetch_object($result)) {
      $nodes[$node->nid] = '';
      $form['title'][$node->nid] = array(
        '#value' => $node->title,
      );
      $form['type'][$node->nid] = array(
        '#value' => check_plain(node_get_types('name', $node)),
      );
      $form['author'][$node->nid] = array(
        '#value' => theme('username', $node),
      );
      $form['status'][$node->nid] = array(
        '#value' => $node->status ? t('published') : t('not published'),
      );
    }
    $form['nodes'] = array(
      '#type' => 'checkboxes',
      '#options' => $nodes,
    );
    $info = serialize($info);
    $form['info'] = array(
      '#type' => 'hidden',
      '#value' => $info,
    );
  }
  elseif ($op == "choose_fields") {
    $info = unserialize($form_values['info']);
    $nodes = $form_values['nodes'];
    $info['nodes'] = $nodes;
    $source_fields = content_types($info['source_type']);
    $source_fields = $source_fields['fields'];

    // Get the cck fields of the source type
    if (count($source_fields) == 0) {

      // In case there are no cck fields, just convert the node type
      $no_fields = true;
      $info['no_fields'] = $no_fields;
    }
    else {
      foreach ($source_fields as $field) {
        $i++;
        $options = array();
        $dest_fields = content_types($info['dest_type']);
        $dest_fields = $dest_fields['fields'];

        // Get the destination type fields
        $options['discard'] = 'discard';

        // Populate only the destination type fields into the select that are of the same type (cck type and multiple property)
        foreach ($dest_fields as $value) {
          if ($field['type'] == $value['type'] && $field['multiple'] == $value['multiple']) {
            $options[$value['field_name']] = $value['field_name'];
          }
        }
        $info['fields']['source'][] = $field['field_name'];

        // Remember the source fields to be converted
        // The select populated with possible destination cck fields for each source field
        $form['dest_field_' . $i] = array(
          '#type' => 'select',
          '#options' => $options,
          '#title' => $field['field_name'] . " " . t("should be inserted into"),
        );
      }
    }
    $info = serialize($info);
    $form['info'] = array(
      '#type' => 'hidden',
      '#value' => $info,
    );
  }
  $form['#multistep'] = TRUE;
  $form['#redirect'] = FALSE;
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t("Submit"),
  );
  return $form;
}
function node_convert_bulk_validate($form_id, $form_values) {
  if ($form_values['step'] == "choose_source_dest_type") {
    if ($form_values['source_type'] == $form_values['dest_type']) {
      form_set_error('source_type', t('Please select different node types.'));
      form_set_error('dest_type', t('Please select different node types.'));
    }
  }
  elseif ($form_values['step'] == "choose_nodes") {
    $no_nodes = TRUE;
    foreach ($form_values['nodes'] as $value) {
      if ($value != 0) {
        $no_nodes = FALSE;
        break;
      }
    }
    if ($no_nodes == TRUE) {
      form_set_error('', t('Please select at least one node.'));
    }
  }
}
function node_convert_bulk_submit($form_id, $form_values) {
  if ($form_values['step'] == "choose_fields") {
    $info = unserialize($form_values['info']);
    if ($info['no_fields'] == false) {

      // If there are cck fields that can to be converted
      foreach ($form_values as $key => $value) {
        if (preg_match("/dest_field_[0-9]+?/", $key) == 1) {
          $info['fields']['destination'][] = $value;
        }

        // Destination fields
      }
    }
    foreach ($info['nodes'] as $nid) {
      node_convert_node_convert($nid, $info['dest_type'], $info['fields']['source'], $info['fields']['destination'], $info['no_fields']);
    }
    drupal_set_message("Nodes converted succesufuly.");
    drupal_goto("admin/content/node");
  }
}
function theme_node_convert_bulk($form) {
  if ($form['step']['#value'] == "choose_source_dest_type") {
    $output = '<div>' . t("Choose the source type of the nodes that should be shown, and the destination type to which they will be converted.") . '</div>';
    $output .= drupal_render($form);
  }
  elseif ($form['step']['#value'] == "choose_nodes") {
    $header = array(
      theme('table_select_header_cell'),
      t("Title"),
      t("Type"),
      t("Author"),
      t("Status"),
    );
    foreach (element_children($form['title']) as $key) {
      $row = array();
      $row[] = drupal_render($form['nodes'][$key]);
      $row[] = drupal_render($form['title'][$key]);
      $row[] = drupal_render($form['type'][$key]);
      $row[] = drupal_render($form['author'][$key]);
      $row[] = drupal_render($form['status'][$key]);
      $rows[] = $row;
    }
    $output = '<div>' . t("Choose the nodes that will be converted.") . '</div>';
    $output .= theme('table', $header, $rows);
    $output .= drupal_render($form);
  }
  elseif ($form['step']['#value'] == "choose_fields") {
    $output = '<div>' . t("Choose the fields where the values should be stored.") . '</div>';
    $info = unserialize($form['info']['#value']);
    if ($info['no_fields'] == TRUE) {
      $output .= '<div>' . t("There are no cck fields to convert. Please press submit.") . '</div>';
    }
    $output .= drupal_render($form);
  }
  return $output;
}

/**
 * Converts a node to another content type.
 *
 * @param $nid
 *   The nid of the node to be converted.
 * @param $dest_node_type
 *   A string containing the destination node type of the node.
 * @param $source_fields
 *   An array containing the source field names.
 * @param $dest_fields
 *   An array containing the destination field names.
 * @param $no_fields_flag
 *   A boolean containing if there are source fields that have to be converted.
 */
function node_convert_node_convert($nid, $dest_node_type, $source_fields, $dest_fields, $no_fields_flag) {
  $node = node_load($nid);
  $vid = $node->vid;
  $source_node_type = $node->type;
  db_query("UPDATE {node} SET type = '%s' WHERE nid = %d", $dest_node_type, $nid);

  // Change the node type in the DB
  db_query("INSERT INTO {%s} (nid, vid) VALUES (%d, %d)", "content_type_" . $dest_node_type, $nid, $vid);

  // Add the current node to the chosen content type
  if ($no_fields_flag == false) {

    // If there are cck fields that can be converted
    foreach ($source_fields as $key => $field) {

      // Conversion process for each field
      node_convert_field_convert($nid, $field, $dest_fields[$key]);
    }
  }
  db_query("DELETE FROM {%s} WHERE nid = %d", "content_type_" . $source_node_type, $nid);

  // We delete the source node_type info
  db_query("DELETE FROM {cache_content} WHERE cid = '%s'", "content:" . $nid . ":" . $vid);

  // We clear the cache
}

/**
 * Transfers information from source_field to dest_field.
 *
 * @param $nid
 *   The nid of the node to be converted.
 * @param $source_field
 *   A string containing the name of the source field which contains to be transfered information.
 * @param $dest_field
 *   A string containing the name of the destination field where the information should be strored.
 */
function node_convert_field_convert($nid, $source_field, $dest_field) {
  $node = node_load($nid);
  $vid = $node->vid;
  $field_info_source = content_fields($source_field);

  // Get source field information
  $db_info_source = content_database_info($field_info_source);

  // Get DB specific source field information
  // If the source field has a separate table, we will have to delete the node info in it
  if (strpos($db_info_source['table'], "content_field_") !== false) {
    $db_source_content_field = true;
  }
  else {
    $db_source_content_field = false;
  }
  if ($dest_field == "discard") {

    // If the source field value should be discarded
    // Delete node info in the separate field table
    if ($db_source_content_field == true) {
      db_query("DELETE FROM {%s} WHERE nid = %d", $db_info_source['table'], $nid);
    }
    return;
  }
  $field_info_dest = content_fields($dest_field);

  // Get destination field information
  $db_info_dest = content_database_info($field_info_dest);

  // Get DB specific destination field information
  if (strpos($db_info_dest['table'], "content_field_") !== false) {
    $db_dest_content_field = true;
  }
  else {
    $db_dest_content_field = false;
  }
  $data = array();
  $dest_column_names = array();
  $source_column_names = array();
  $column_placeholders = array();
  $column_assignments = array();
  $source_values = array();
  foreach ($db_info_source['columns'] as $column => $attributes) {
    $source_column_names[] = $attributes['column'];

    // Collect the DB columns names of the source field
  }
  if ($field_info_source['multiple'] != 0) {

    // If the field has multiple values, we remember each value from the DB
    $query = db_query("SELECT " . implode(", ", $source_column_names) . ", delta FROM {%s} WHERE nid = %d AND vid = %d", $db_info_source['table'], $nid, $vid);
    while ($db_row = db_fetch_array($query)) {
      $source_values[] = array_merge(array_values($db_row), array(
        $nid,
        $vid,
      ));
    }
  }
  else {

    // Otherwise we just remember one row of info
    $source_values = db_fetch_array(db_query("SELECT " . implode(", ", $source_column_names) . " FROM {%s} WHERE nid = %d AND vid = %d", $db_info_source['table'], $nid, $vid));
    $source_values = array_values($source_values);
    $source_values[] = $nid;
    $source_values[] = $vid;
  }

  // After getting the source field values, we delete them in the DB
  if ($db_source_content_field == true) {
    db_query("DELETE FROM {%s} WHERE nid = %d", $db_info_source['table'], $nid);
  }

  // Prepare the INSERT and UDPATE queries, for transfering the values in the destination fields
  foreach ($db_info_dest['columns'] as $column => $attributes) {
    $dest_column_names[] = $attributes['column'];
    switch ($attributes['type']) {
      case 'int':
      case 'mediumint':
      case 'tinyint':
      case 'bigint':
        $column_placeholders[] = '%d';
        $column_assignments[] = $attributes['column'] . ' = %d';
        break;
      case 'float':
        $column_placeholders[] = '%f';
        $column_assignments[] = $attributes['column'] . ' = %f';
        break;
      default:
        $column_placeholders[] = "'%s'";
        $column_assignments[] = $attributes['column'] . " = '%s'";
    }
  }
  if ($field_info_source['multiple'] != 0) {

    // If the field has multiple values, we put each value into the DB
    foreach ($source_values as $values) {
      $db_message = db_query("INSERT INTO {" . $db_info_dest['table'] . "} (" . implode(", ", $dest_column_names) . ", delta, nid, vid) VALUES (" . implode(', ', $column_placeholders) . ", %d, %d, %d)", $values);
    }
  }
  else {
    if ($db_dest_content_field == true) {

      // If the field is re-used, we insert the data in the field's own table in the DB
      $db_message = db_query("INSERT INTO {" . $db_info_dest['table'] . "} (" . implode(", ", $dest_column_names) . ", nid, vid) VALUES (" . implode(', ', $column_placeholders) . ", %d, %d)", $source_values);
    }
    else {

      // Otherwise we just update it in the content_type table
      $db_message = db_query("UPDATE {" . $db_info_dest['table'] . "} SET " . implode(", ", $column_assignments) . " WHERE nid = %d AND vid = %d", $source_values);
    }
  }
}