You are here

taxonomy_csv.export.api.inc in Taxonomy CSV import/export 7.5

Validate export options and manage export process.

File

export/taxonomy_csv.export.api.inc
View source
<?php

/**
 * @file
 * Validate export options and manage export process.
 */

/**
 * Invoke associated include file.
 */
$module_dir = drupal_get_path('module', 'taxonomy_csv');
require_once $module_dir . '/taxonomy_csv.api.inc';
require_once $module_dir . '/taxonomy_csv.term.api.inc';
require_once $module_dir . '/taxonomy_csv.vocabulary.api.inc';

/**
 * Process the export of a vocabulary.
 *
 * If not used in a form, don't forget to use batch_process().
 *
 * @param $options
 *   An associative array of options:
 *   - export_format : see format of the csv line (see taxonomy.api.inc)
 *   - vocabulary_id : vid or machine_name (or array of them) of the vocabulary
 *                     to export (default: 0, which means all)
 *   - delimiter     : one character csv delimiter (default: ',')
 *   - enclosure     : zero or one character csv enclosure (default: '"')
 *   - line_ending   : 'Unix' (default), 'Mac' or 'MS-DOS'
 *   - order         : order of terms: 'name' (default), 'tid' or 'weight'
 *   // Level of result process infos:
 *   - check_options : boolean. check or not (default) this array of options
 *   - result_display: boolean. display or not (default). Only used with UI
 *   - result_duplicates: boolean. display or not (default) duplicate terms
 *   All options have default values.
 *   Warning: default values are different with UI.
 *
 * @return
 *   Array of errors or file object to download (need to execute batch process;
 *   result is logged in watchdog).
 */
function taxonomy_csv_export($options) {

  // Complete $options with default values if needed.
  // Default api and UI options are different.
  $options += _taxonomy_csv_values('export_default_api');

  // Presave a file in order to check access to temporary folder.
  $messages = _taxonomy_csv_export_output_presave($options);
  if (count($messages)) {
    return $messages;
  }

  // Process export.
  $messages = taxonomy_csv_vocabulary_export($options);

  // Return errors if any.
  if (count($messages)) {
    return $messages;
  }
  else {
    return $options['file'];
  }
}

/**
 * Presave output.
 *
 * Check if there is write access and prepare file.
 *
 * @param $options
 *   Array. Same as taxonomy_csv_export.
 *
 * @return
 *   Array of messages errors if any.
 *   By reference options are cleaned and completed.
 */
function _taxonomy_csv_export_output_presave(&$options) {
  $messages = array();

  // Check if there is write access and prepare file.
  $filename = file_unmanaged_save_data('', 'public://' . 'taxocsv.csv', 'FILE_EXISTS_RENAME');
  if (!$filename) {
    $messages['file'] = t('Check access rights to temp directory: export needs permission to write and to read in it. Export failed.');
  }
  else {
    $options['file'] = (object) array(
      'filename' => basename($filename),
      'filepath' => drupal_realpath($filename),
      'filesize' => filesize($filename),
    );
  }
  return $messages;
}

/**
 * Prepare the export of a vocabulary.
 *
 * @note
 * If not used in a form, don't forget to use batch_process().
 *
 * @param $options
 *   Array. Same as taxonomy_csv_export.
 *
 * @return
 *   Array of errors or nothing (batch process to execute).
 */
function taxonomy_csv_vocabulary_export($options) {

  // Check options and return array of messages in case of errors.
  if ($options['check_options']) {

    // Invoke export admin file.
    $module_dir = drupal_get_path('module', 'taxonomy_csv');
    require_once "{$module_dir}/export/taxonomy_csv.export.admin.inc";
    $result = _taxonomy_csv_export_check_options($options);
    if (count($result)) {
      return $result;
    }
  }

  // Complete $options with some csv variables.
  $options['separator'] = $options['enclosure'] . $options['delimiter'] . $options['enclosure'];
  $line_ending = array(
    'Unix' => "\n",
    'Mac' => "\r",
    'MS-DOS' => "\r\n",
  );
  $options['end_of_line'] = $line_ending[$options['line_ending']];

  // Calculates number of terms to be exported.
  $options['total_terms'] = taxonomy_csv_vocabulary_count_terms($options['vocabulary_id']);

  // Get infos about fields of vocabulary, for any formats.
  $options['vocabulary'] = array();
  foreach ($options['vocabulary_id'] as $vocabulary_id) {
    $options['vocabulary'][$vocabulary_id] = taxonomy_vocabulary_load($vocabulary_id);
    $vocabulary =& $options['vocabulary'][$vocabulary_id];
    $vocabulary->instances = field_info_instances('taxonomy_term', $vocabulary->machine_name);

    // Prepare list of fields to be exported.
    $vocabulary->fields = array();

    // Not included, because referenced terms are exported by name.
    // $vocabulary->fields['tid'] = array('cardinality' => 1);
    $vocabulary->fields['name'] = array(
      'cardinality' => 1,
    );

    // Not included, because there is already 'vocabulary_machine_name'.
    // $vocabulary->fields['vid'] = array('cardinality' => 1);
    $vocabulary->fields['vocabulary_machine_name'] = array(
      'cardinality' => 1,
    );
    $vocabulary->fields['description'] = array(
      'cardinality' => 1,
    );
    $vocabulary->fields['format'] = array(
      'cardinality' => 1,
    );
    $vocabulary->fields['weight'] = array(
      'cardinality' => 1,
    );
    $vocabulary->fields['parent'] = array(
      'cardinality' => -1,
    );
    if (module_exists('i18n_taxonomy')) {
      switch ($vocabulary->i18n_mode) {
        case I18N_MODE_LANGUAGE:
        case I18N_MODE_LOCALIZE:
          $vocabulary->fields['language'] = array(
            'cardinality' => 1,
          );
          break;
        case I18N_MODE_TRANSLATE:
        case I18N_MODE_MULTIPLE:
          $vocabulary->fields['language'] = array(
            'cardinality' => 1,
          );
          $vocabulary->fields['i18n_tsid'] = array(
            'cardinality' => 1,
          );
          break;
      }
    }

    // @todo
    // $vocabulary->fields['guid'] = array('cardinality' => 1);
    // Prepare list of unlimited fields to be exported.
    $vocabulary->fields_unlimited = array();
    $vocabulary->fields_unlimited['parent'] = 1;
    if (is_array($vocabulary->instances)) {
      foreach ($vocabulary->instances as $field_name => $value) {
        $vocabulary->fields[$field_name] = field_info_field($field_name);

        // Get the list of fields with an unlimited number of values to avoid
        // the loop of check (used with custom fields export).
        // The minimum is set to one to avoid zero value.
        if ($vocabulary->fields[$field_name]['cardinality'] == -1) {
          $vocabulary->fields_unlimited[$field_name] = 1;
        }
      }
    }
  }

  // Prepare export batch.
  $batch = array(
    'title' => t('Exporting !total_terms terms to CSV file...', array(
      '!total_terms' => $options['total_terms'],
    )),
    'init_message' => t('Starting downloading of datas...') . '<br />' . t('Wait some seconds for pre-processing...'),
    'progress_message' => '',
    'error_message' => t('An error occurred during the export.'),
    'finished' => '_taxonomy_csv_vocabulary_export_finished',
    'file' => drupal_get_path('module', 'taxonomy_csv') . '/export/taxonomy_csv.export.api.inc',
    'progressive' => TRUE,
    'operations' => array(
      0 => array(
        '_taxonomy_csv_vocabulary_export_process',
        array(
          $options,
        ),
      ),
    ),
  );
  batch_set($batch);
}

/**
 * Batch process of vocabulary export.
 *
 * @todo Check if direct query and only tid save is really less memory
 * intensive (with core taxonomy cache or not).
 * @todo Don't remember terms, but load them one by one in order to decrease
 * memory usage.
 *
 * @param $options
 *   Array of batch options.
 * @param &$context
 *   Batch context to keep results and messages.
 *
 * @return
 *   NULL because use of &$context.
 */
function _taxonomy_csv_vocabulary_export_process($options, &$context) {

  // First callback.
  if (empty($context['sandbox'])) {

    // Remember options as batch_set can't use form_storage.
    // It allows too that first line in result is numbered 1 and not 0.
    $context['results'][0] = $options;

    // Initialize some variables.
    $context['results'][0]['current_term'] = 0;
    $context['results'][0]['current_name'] = '';
    $context['results'][0]['worst_tid'] = 0;
    $context['results'][0]['worst_term'] = 0;
    $context['results'][0]['worst_name'] = '';
    $context['results'][0]['worst_message'] = 799;

    // No pointer because new line is appended to file.
    $context['results'][0]['handle'] = fopen($options['file']->filepath, 'a+');

    // Fetch terms to be exported and order them (by tree or by specific order).
    $context['sandbox']['terms'] = _taxonomy_csv_vocabulary_export_get_terms($options);

    // Get max number of values for fields with a undefined number of values.
    if ($options['export_format'] == TAXONOMY_CSV_FORMAT_FIELDS) {

      // Currently, manage only undefined language.
      $language = 'und';
      foreach ($context['sandbox']['terms'] as $term) {
        foreach (array_keys($options['vocabulary'][$term->vid]->fields_unlimited) as $field_name) {
          if (isset($term->{$field_name})) {

            // Remember the number of items if this term field has got more
            // items than previous one.
            if ($field_name == 'parent' && count($term->parent) > $options['vocabulary'][$term->vid]->fields_unlimited['parent']) {
              $options['vocabulary'][$term->vid]->fields_unlimited['parent'] = count($term->parent);
            }
            elseif (count($term->{$field_name}[$language]) > $options['vocabulary'][$term->vid]->fields_unlimited[$field_name]) {
              $options['vocabulary'][$term->vid]->fields_unlimited[$field_name] = count($term->{$field_name}[$language]);
            }
          }
        }
      }

      // Keep updated the list of vocabulary with undefined fields.
      $context['results'][0]['vocabulary'] = $options['vocabulary'];
      $context['sandbox']['vocabulary'] = $options['vocabulary'];
    }

    // Display a warning if terms count in taxonomy_term_data table is different
    // of terms counted with Drupal taxonomy_term_load_multiple() function.
    // See http://drupal.org/node/1359260.
    if ($options['total_terms'] != count($context['sandbox']['terms'])) {

      // Memorize the first wrong term.
      $first_wrong_term = array_shift(array_diff_key($terms['taxonomy_term'], taxonomy_term_load_multiple(array_keys($terms['taxonomy_term']))));
      $context['results'][0]['worst_tid'] = $first_wrong_term->tid;
      $context['results'][0]['worst_term'] = '';
      $context['results'][0]['worst_name'] = 'tid:' . ' ' . $first_wrong_term->tid;
      $context['results'][0]['worst_message'] = 408;

      // Warning not a good term.
    }

    // Clean memory.
    if (isset($terms)) {
      unset($terms);
    }

    // Duplicate names will be searched after export process.
    $context['results'][0]['duplicate_terms'] = array();
  }
  elseif (!is_resource($context['results'][0]['handle'])) {

    // Reopen file in case of memory out.
    $context['results'][0]['handle'] = fopen($options['file']->filepath, 'a+');
  }

  // Get list of unlimited multivalued fields.
  // @todo Currently, these fields are not saved in batch.
  if ($options['export_format'] == TAXONOMY_CSV_FORMAT_FIELDS) {
    $options['vocabulary'] = $context['sandbox']['vocabulary'];
  }

  // To simplify use of variables.
  $worst_tid =& $context['results'][0]['worst_tid'];
  $worst_term =& $context['results'][0]['worst_term'];
  $worst_name =& $context['results'][0]['worst_name'];
  $worst_message =& $context['results'][0]['worst_message'];
  $handle =& $context['results'][0]['handle'];
  $duplicate_terms =& $context['results'][0]['duplicate_terms'];
  $term_number =& $context['results'][0]['current_term'];
  $current_name =& $context['results'][0]['current_name'];
  $terms_list =& $context['sandbox']['terms'];
  $terms_list_ids = array_keys($terms_list);

  // Process one term until end of vocabulary.
  if ($term_number < count($context['sandbox']['terms'])) {
    $term = $terms_list[$terms_list_ids[$term_number]];
    ++$term_number;

    // Remember current name/tid in case of error.
    $current_name = $term->name;
    $current_tid = $term->tid;

    // Process export of current term.
    $result = taxonomy_csv_term_export($term, $options, $terms_list, $duplicate_terms);

    // If result is empty, there is nothing to export (with Translation export,
    // terms can be skipped and exported with another term).
    $result['msg'] = taxonomy_csv_line_export($result['line'], $options, $handle, $result['msg']);

    // Remember worst message of exported terms.
    $worst_message_new = _taxonomy_csv_worst_message($result['msg']);
    if ($worst_message > $worst_message_new) {
      $worst_tid = $current_tid;
      $worst_term = $term_number;
      $worst_name = $current_name;
      $worst_message = $worst_message_new;
    }

    // Remember messages. Currently useless because there isn't any warning or
    // notice message (only error). A result level can be added here if needed.
    if (count($result['msg'])) {
      $context['results'][$term_number] = $result['msg'];
    }

    // Inform about progress.
    $context['message'] = t('Term !term_number of !total_terms processed: %term', array(
      '!term_number' => $term_number,
      '!total_terms' => $options['total_terms'],
      '%term' => $current_name,
    ));

    // Check worst message of exported terms and update progress.
    if ($worst_message >= TAXONOMY_CSV_PROCESS_WARNING) {

      // Count should be <= 0.99 to avoid batch stop before end (Drupal 7 bug).
      $context['finished'] = floor($term_number / count($context['sandbox']['terms']) * 100) / 100;
    }
    else {
      $context['finished'] = 1;
    }
  }
}

/**
 * Helper to get the list of terms to be exported.
 */
function _taxonomy_csv_vocabulary_export_get_terms($options) {
  switch ($options['export_format']) {

    // Prepare a hierarchical tree of terms.
    case TAXONOMY_CSV_FORMAT_STRUCTURE:
    case TAXONOMY_CSV_FORMAT_TREE:
    case TAXONOMY_CSV_FORMAT_POLYHIERARCHY:
    case TAXONOMY_CSV_FORMAT_TREE_FIELDS:
      $terms = array();

      // Export only selected vocabularies.
      if ($options['vocabulary_id'] && $options['vocabulary_id'] != array(
        0,
      )) {
        $vocabularies = array();
        foreach ($options['vocabulary_id'] as $vocabulary) {
          $vocabularies[] = taxonomy_vocabulary_load($vocabulary);
        }
      }
      else {
        $vocabularies = taxonomy_vocabulary_get_names();
      }
      foreach ($vocabularies as $vocabulary) {
        $terms = array_merge($terms, taxonomy_get_tree($vocabulary->vid));
      }

      // Complete base terms with fields.
      if (in_array($options['export_format'], array(
        TAXONOMY_CSV_FORMAT_TREE_FIELDS,
      ))) {
        $list = array();
        foreach ($terms as $term) {
          $list[] = $term->tid;
        }
        $terms_fields = taxonomy_term_load_multiple($list);
        $list = array_flip($list);
        foreach ($terms_fields as $key => &$term) {
          $term->parents = $terms[$list[$key]]->parents;
        }
        $terms =& $terms_fields;
      }
      break;

    // Prepare a list of normal terms.
    // @todo Prepare a simple list of term names or definitions without links in
    // order to reduce memory usage for some formats.
    // @todo Use a one term approach to reduce memory usage (anyway, all terms
    // will be load)?
    default:
      $query = new EntityFieldQuery();
      $query
        ->entityCondition('entity_type', 'taxonomy_term');
      if ($options['vocabulary_id'] && $options['vocabulary_id'] != array(
        0,
      )) {
        $query
          ->propertyCondition('vid', $options['vocabulary_id']);
      }
      $query
        ->propertyOrderBy($options['order'], 'ASC');
      $terms = $query
        ->execute();
      if ($terms['taxonomy_term'] === NULL) {
        $terms['taxonomy_term'] = array();
      }
      $terms = taxonomy_term_load_multiple(array_keys($terms['taxonomy_term']));
      break;
  }
  return $terms;
}

/**
 * Callback for finished batch export and display result informations.
 */
function _taxonomy_csv_vocabulary_export_finished($success, $results, $operations) {
  $options =& $results[0];
  unset($results[0]);

  // Close exported file.
  if ($options['handle']) {
    fclose($options['handle']);
  }

  // Invoke export stats file if user wants to display results.
  if ($options['result_display']) {
    $module_dir = drupal_get_path('module', 'taxonomy_csv');
    require_once "{$module_dir}/export/taxonomy_csv.export.result.inc";
  }

  // Short summary information is different if batch succeeded or not.
  if ($success) {
    if (!empty($options['worst_tid'])) {
      $worst_path = drupal_get_path_alias('taxonomy/term/' . $options['worst_tid']);
      $options['worst_name'] = l($options['worst_name'], $worst_path);
    }
    $variables = array(
      '!total_terms' => $options['total_terms'],
      '!worst_count' => $options['worst_term'],
      '!worst_name' => $options['worst_name'],
      '!worst_msg' => $options['result_display'] ? _taxonomy_csv_message_text($options['worst_message']) : t('Message code') . ' = ' . $options['worst_message'],
    );
    $messages = array(
      WATCHDOG_DEBUG => t('No error, warnings or notices have been reported during export process of !total_terms terms.', $variables),
      WATCHDOG_INFO => t('No error, warnings or notices have been reported during export process of !total_terms terms.', $variables),
      WATCHDOG_NOTICE => t('Notices have been reported during export process (bad formatted or empty terms). !total_terms terms processed. First notice occurred on term !worst_count (!worst_name) [!worst_msg].', $variables),
      WATCHDOG_WARNING => t('Warnings have been reported during export process (bad formatted terms). !total_terms terms processed. First term skipped is term !worst_count (!worst_name) [!worst_msg].', $variables),
      WATCHDOG_ERROR => t('Errors have been reported during export process. Process failed at term !worst_count (!worst_name) of a total of !total_terms [!worst_msg].', $variables),
    );
    $worst_level = intval($options['worst_message'] / 100);
    $message = isset($messages[$worst_level]) ? $messages[$worst_level] : $messages[WATCHDOG_DEBUG];
  }
  else {
    $message = t('Exportation failed. Export process was successful until the term !term_count (!term_name) of a total of !total_terms.', array(
      '!term_count' => $options['current_term'],
      '!term_name' => $options['current_name'],
      '!total_terms' => $options['total_terms'],
    )) . '<br />' . t('This issue is related to export process and may be caused by a memory overrun of the database. If not, you can reinstall module from a fresh release or submit an issue on <a href="!link">Taxonomy CSV import/export module</a>.', array(
      '!link' => url('http://drupal.org/project/issues/taxonomy_csv/'),
    ));
    $worst_level = WATCHDOG_ERROR;
  }

  // Set result message in watchdog and eventually in user interface.
  // Use of a $message variable is unrecommended, but simpler and working.
  // See http://drupal.org/node/323101
  watchdog('taxonomy_csv', $message, NULL, $worst_level);
  if ($options['result_display']) {
    _taxonomy_csv_export_result($options, $worst_level, $message, $results);
  }
}

/**
 * Export a line.
 *
 * @param $line
 *   Array to be exported to a line.
 * @param $options
 *   An associative array of export options:
 *   - 'separator'  : string separator (formatted delimiter and enclosure).
 *   - 'enclosure'  : item enclosure.
 *   - 'end_of_line': end of line string.
 * @param $handle
 *   Handle of the open file where to save line.
 * @param $result_message
 *   (Optional) Array of messages.
 *
 * @return
 *   Result array of messages.
 */
function taxonomy_csv_line_export($line, $options, &$handle, $result = array()) {
  if (!$line) {
    return $result;
  }

  // Check if separator, enclosure or line ending exist in line.
  $check_line = implode('', $line);
  if (strpos($check_line, $options['separator']) !== FALSE || $options['enclosure'] != '' && strpos($check_line, $options['enclosure']) !== FALSE || $options['enclosure'] == '' && strpos($check_line, $options['end_of_line']) !== FALSE) {
    $result[] = 313;

    // Error delimiter or enclosure.
  }
  elseif (_taxonomy_csv_worst_message($result) < TAXONOMY_CSV_PROCESS_NOTICE) {
  }
  else {

    // Save line to file.
    $line = $options['enclosure'] . implode($options['separator'], $line) . $options['enclosure'] . $options['end_of_line'];
    if (fwrite($handle, $line) === FALSE) {
      $result[] = 312;

      // Unable to write to file.
    }
  }
  return $result;
}

/**
 * Export a term to a line matching the options.
 *
 * @param $term
 *   Full term object to export.
 * @param $options
 *   An associative array of export options:
 *   - export_format : format of the csv line (see taxonomy.api.inc)
 * @param $terms_list
 *   (Optional) Array of all term objects to export, used to avoid to repeat
 *   fetch of terms.
 * @param $duplicate_terms
 *   (Optional) Array of duplicate terms names indexed by tid.
 *
 * @return
 *   Result array with:
 *   - 'line' => array of exported items,
 *   - 'msg'  => array of messages arrays.
 */
function taxonomy_csv_term_export($term, $options, &$terms_list = array(), $duplicate_terms = array()) {

  // Define default values.
  $result = array(
    'line' => array(),
    'msg' => array(),
  );

  // Only count check because term and options are already checked.
  if (count($term)) {
    switch ($options['export_format']) {
      case TAXONOMY_CSV_FORMAT_FLAT:
        $result['line'][] = $term->name;
        break;
      case TAXONOMY_CSV_FORMAT_FLAT_TID:
        $result['line'][] = $term->tid;
        break;
      case TAXONOMY_CSV_FORMAT_TID_FLAT:
        $result['line'][] = $term->tid;
        $result['line'][] = $term->name;
        break;
      case TAXONOMY_CSV_FORMAT_STRUCTURE:
      case TAXONOMY_CSV_FORMAT_TREE:
        $terms = taxonomy_csv_term_get_first_path($term, $terms_list);
        foreach ($terms as $parent) {
          $result['line'][] = $parent->name;
        }
        $result['line'][] = $term->name;
        break;
      case TAXONOMY_CSV_FORMAT_TID:
      case TAXONOMY_CSV_FORMAT_TID_TREE:
        $terms = taxonomy_csv_term_get_first_path($term, $terms_list);
        foreach ($terms as $parent) {
          $result['line'][] = $parent->tid;
          $result['line'][] = $parent->name;
        }
        $result['line'][] = $term->tid;
        $result['line'][] = $term->name;
        break;
      case TAXONOMY_CSV_FORMAT_POLYHIERARCHY:

        // @todo
        // Warning : taxonomy_csv_term_get_first_path() returns only first path.
        break;
      case TAXONOMY_CSV_FORMAT_TID_POLYHIERARCHY:

        // @todo
        // Warning : taxonomy_csv_term_get_first_path() returns only first path.
        break;
      case TAXONOMY_CSV_FORMAT_TREE_FIELDS:
        $terms = taxonomy_csv_term_get_first_path($term, $terms_list);
        foreach ($terms as $parent) {
          $result['line'][] = $parent->name;
        }

      // Continue with fields.
      case TAXONOMY_CSV_FORMAT_FIELDS:

        // Currently, manage only undefined language.
        $language = 'und';

        // Use of field_get_items is slower.
        foreach ($options['vocabulary'][$term->vid]->fields as $field_name => $field) {
          $count = 0;

          // Item is a Field.
          if (isset($field['type'])) {
            if (isset($term->{$field_name}[$language])) {
              switch ($field['type']) {

                // For taxonomy term reference, use name instead of value.
                case 'taxonomy_term_reference':
                  foreach ($term->{$field_name}[$language] as &$item) {
                    $result['line'][] = isset($terms_list[$item['tid']]) ? $terms_list[$item['tid']]->name : taxonomy_term_load($item['tid'])->name;
                  }
                  break;

                // For long text, need to escape the value.
                case 'text_long':
                case 'text_with_summary':
                  foreach ($term->{$field_name}[$language] as &$item) {
                    $result['line'][] = _taxonomy_csv_escape_line_break($item['value']);
                  }
                  break;
                default:

                  // Key is generally 'value' but it can be something else.
                  reset($field['columns']);
                  foreach ($term->{$field_name}[$language] as &$item) {
                    $result['line'][] = $item[key($field['columns'])];
                  }
                  break;
              }
              $count = count($term->{$field_name}[$language]);
            }
          }
          else {
            switch ($field_name) {

              // For taxonomy term parent, use name instead of value.
              case 'parent':

                // Don't export here: use Structure and fields.
                if ($options['export_format'] == TAXONOMY_CSV_FORMAT_TREE_FIELDS) {
                }
                else {
                  if (isset($term->parent)) {
                    foreach ($term->parent as $tid) {
                      $result['line'][] = isset($terms_list[$tid]) ? $terms_list[$tid]->name : taxonomy_term_load($tid)->name;
                    }
                    $count = count($term->parent);
                  }
                }
                break;
              case 'parents':

                // Don't export here: use Structure and fields.
                break;
              case 'description':
                $result['line'][] = _taxonomy_csv_escape_line_break($term->description);
                $count = 1;
                break;
              default:
                $result['line'][] = $term->{$field_name};
                $count = 1;
                break;
            }
          }

          // Add empty value the max number of values in the vocabulary times.
          if (isset($options['vocabulary'][$term->vid]->fields_unlimited[$field_name])) {
            if ($count < $options['vocabulary'][$term->vid]->fields_unlimited[$field_name]) {
              if ($options['export_format'] == TAXONOMY_CSV_FORMAT_TREE_FIELDS && ($field_name == 'parent' || $field_name == 'parents')) {
              }
              else {
                $result['line'] = array_merge($result['line'], array_fill(0, $options['vocabulary'][$term->vid]->fields_unlimited[$field_name] - $count, ''));
              }
            }
          }
          elseif ($count < $field['cardinality']) {
            $result['line'] = array_merge($result['line'], array_fill(0, $field['cardinality'] - $count, ''));
          }
        }
        break;
      case TAXONOMY_CSV_FORMAT_TRANSLATE:
        if (!module_exists('i18n_taxonomy')) {
          $result['msg'][] = 360;

          // Translation error.
          break;
        }
        switch ($options['vocabulary'][$term->vid]->i18n_mode) {
          case I18N_MODE_NONE:
          case I18N_MODE_LANGUAGE:
            $result['line'][] = $term->name;
            break;
          case I18N_MODE_LOCALIZE:
            $result['line'][] = $term->name;
            $languages = locale_language_list('name');
            unset($languages[language_default('language')]);
            foreach ($languages as $language => $value) {
              $translation = i18n_string_translate(array(
                'taxonomy',
                'term',
                $term->tid,
                'name',
              ), $term->name, array(
                'langcode' => $language,
              ));
              $result['line'][] = $translation ? $translation : '';
            }
            break;
          case I18N_MODE_TRANSLATE:
          case I18N_MODE_MULTIPLE:
            $languages = array(
              'und' => t('Language neutral'),
            );
            $languages += locale_language_list('name');
            $languages = array_flip(array_keys($languages));
            $result['line'] = array_fill(0, count($languages), '');
            if ($term->i18n_tsid == 0) {
              $result['line'][$languages[$term->language]] = $term->name;
            }
            else {
              $translation_set = i18n_translation_set_load($term->i18n_tsid);
              $translations = $translation_set
                ->get_translations();
              $language_min = $languages[$term->language];
              foreach ($translations as $language => $translated_term) {
                $result['line'][$languages[$language]] = $translated_term->name;

                // Check if this term is already exported (when there is a term
                // with a language before the current one).
                if ($languages[$language] < $language_min) {
                  $language_min = $languages[$language];
                }
              }

              // This term is already exported or will be exported with another
              // term.
              if ($language_min < $languages[$term->language]) {
                $result['line'] = array();
              }
            }
            break;
        }
        break;
      default:
        $result['msg'][] = 307;
    }
  }
  else {
    $result['msg'][] = 385;

    // Error no term to process.
  }

  // Clean result.
  $result['msg'] = array_unique($result['msg']);
  sort($result['msg']);
  return $result;
}

Functions

Namesort descending Description
taxonomy_csv_export Process the export of a vocabulary.
taxonomy_csv_line_export Export a line.
taxonomy_csv_term_export Export a term to a line matching the options.
taxonomy_csv_vocabulary_export Prepare the export of a vocabulary.
_taxonomy_csv_export_output_presave Presave output.
_taxonomy_csv_vocabulary_export_finished Callback for finished batch export and display result informations.
_taxonomy_csv_vocabulary_export_get_terms Helper to get the list of terms to be exported.
_taxonomy_csv_vocabulary_export_process Batch process of vocabulary export.