You are here

function _node_import_get_nodes in Node import 5

Import and create nodes.

Parameters

string $filepath: Full path to the file to import.

string $type: Node content type.

array $match: Array of mappings.

array $global: Array of global values.

int $preview: Number of entries to preview or 0 to do the import.

array $error_rows: Returns a list of error rows.

string $get_row: Function used to get one row.

2 calls to _node_import_get_nodes()
_node_import_import in ./node_import.module
_node_import_preview in ./node_import.module

File

./node_import.module, line 600
This modules provides a wizard at "administer >> content >> import" to import a CSV file with nodes.

Code

function _node_import_get_nodes($filepath, $type, $match, $global, $preview, &$error_rows, $get_row = '_node_import_csv_get_row') {
  drupal_add_css(drupal_get_path('module', 'node_import') . '/node_import.css');
  $header = $get_row($filepath, TRUE);
  if (!$match) {
    $match = $header;
  }
  if ($match && !$preview) {
    db_query("DELETE FROM {node_import_mappings} WHERE type = '%s' AND csv_headers = '%s'", $type, serialize($header));
    db_query("INSERT INTO {node_import_mappings} (type, csv_headers, mapping) VALUES ('%s', '%s', '%s')", $type, serialize($header), serialize($match));
  }
  $j = 0;
  $success = 0;
  while (($row = $get_row($filepath)) && ($j++ < $preview || $preview == 0)) {
    $errors = array();

    // Create an empty node with only static and global options.
    if ($type == 'node_import') {
      $node = (object) array();
    }
    else {
      $node = (object) array_merge(array(
        'type' => $type,
      ), (array) module_invoke_all('node_import_static', $type), (array) $global);
    }

    // Assign the mapped fields to the $node.
    foreach ($row as $i => $value) {
      if (strlen($match[$i]) > 0) {
        $fieldname = $match[$i];
        $node->{$fieldname} = $value;
      }
      if ($match[$i] == 'name' && $type == 'node_import') {
        if ($uid = node_import_userreference($value)) {
          $account = user_load(array(
            'uid' => $uid,
          ));
          $node->uid = $account->uid;
          $node->name = $account->name;
        }
        else {
          $errors[] = t('The username %name does not exist.', array(
            '%name' => $node->name,
          ));
        }
      }
    }

    // Prepare the node for import. We could have written the following loop
    // as: module_invoke_all('node_import_prepare', $node, $preview > 0);
    // but unfortunately module_invoke_all passes all arguments by value.
    // Note that module_invoke() passes arguments by value as well.
    foreach (module_implements('node_import_prepare') as $module_name) {
      $function = $module_name . '_node_import_prepare';
      $errors = array_merge((array) $errors, (array) $function($node, $preview > 0));
    }

    // We can't do the normal validation we've done in 4.6 because a lot
    // of validation is done in $forms now instead of in node_validate($node).
    // Even if we could do it, we still have the problem that we are unable
    // to reset the form errors (coz it's a static variable inside
    // form_get_errors()). The only way I can think of to do real validation
    // is:
    // - use the current $node to fill in some $form,
    // - create a callback to validate *one* node which would be called
    //   for each node, this way form_get_errors() will only apply to
    //   one node.
    // I may do it one day, but let's duplicate the validation code for
    // nodes in this module instead.

    //node_validate($node);

    // Ok, we're done. Preview the node or save it (if no errors).
    if (count($errors)) {
      $output .= '<div class="node_import-error">';
      $output .= theme('item_list', $errors, t('Can not import this node. Check following errors:'));
      $output .= node_view($node);
      $output .= '</div>';
      $error_rows[] = $row;
    }
    else {
      if ($preview) {
        $node->in_preview = TRUE;
        $output .= '<div class="node_import-success">';
        $output .= node_view($node);
        $output .= '</div>';
      }
      else {
        $node = node_submit($node);
        node_save($node);
        $success++;
      }
    }

    // Now we have either imported the node or not. Report it to interested
    // modules. As we are not interested in changes to $node, we can use
    // module_invoke_all() here (pass by value).
    module_invoke_all('node_import_postprocess', $node, $preview > 0, count($errors) > 0);

    // Clean up
    unset($node);
    unset($errors);
  }
  $get_row('');

  // Tell interested modules we have completed the import.
  module_invoke_all('node_import_complete', $type);
  if (!$preview) {
    if (count($error_rows)) {
      drupal_set_message(t("!errors Click 'Download rows with errors' for a CSV file of the failed rows.", array(
        '!errors' => format_plural(count($error_rows), t('There was 1 error.'), t('There were @count errors.')),
      )));
      $error_rows = array_merge(array(
        $header,
      ), $error_rows);
    }
    drupal_set_message(format_plural($success, t('Successfully imported 1 node.'), t('Successfully imported @count nodes.')));
  }
  return $output;
}