You are here

function feeds_xls_create_csv_of_data in Feeds XLS 7

Create a CSV file with data in which can later be converted to a proper XLS file.

1 string reference to 'feeds_xls_create_csv_of_data'
feeds_xls_download_populated_template in ./feeds_xls.template.inc
Callback function to provide the populated template.

File

./feeds_xls.template.inc, line 99

Code

function feeds_xls_create_csv_of_data($feeds_importer, &$context) {
  if (!isset($context['sandbox']['progress'])) {

    // Calculate the total number of rows to add to this file.
    // Use the processor class to guess what entity type we're importing (this
    // relies on other coders following a similar convention to the feeds
    // module).
    $processor_class = get_class($feeds_importer->processor);
    $entity_guess = strtolower(substr($processor_class, 5, strpos($processor_class, 'Processor') - 5));
    $bundle = '';
    $context['sandbox']['entity'] = '';
    $context['sandbox']['entity_ids'] = array();
    $context['sandbox']['row'] = 0;
    switch ($entity_guess) {
      case 'node':
        $query = db_select('node', 'e')
          ->fields('e', array(
          'nid',
        ))
          ->condition('type', $feeds_importer->processor->config['bundle']);
        $entity_key = 'nid';
        $context['sandbox']['entity'] = 'node';
        break;
      case 'term':

        // The bundle for a term is actually the vid.
        $vocabulary = taxonomy_vocabulary_machine_name_load($feeds_importer->processor->config['vocabulary']);
        $query = db_select('taxonomy_term_data', 'e')
          ->fields('e', array(
          'tid',
        ))
          ->condition('vid', $vocabulary->vid);
        $entity_key = 'tid';
        $entity_guess = 'taxonomy_term';
        $context['sandbox']['entity'] = 'taxonomy_term';
        break;
      case 'file':
        $query = db_select('file_managed', 'e')
          ->fields('e', array(
          'fid',
        ))
          ->condition('type', $feeds_importer->processor->config['bundle']);
        $entity_key = 'fid';
        $context['sandbox']['entity'] = 'file';
        break;
      case 'user':
        $query = db_select('users', 'e')
          ->fields('e')
          ->condition('uid', 1, '>');
        $entity_key = 'uid';
        $context['sandbox']['entity'] = 'user';
        break;
    }
    drupal_alter('feeds_xls_template_query', $query, $context['sandbox']['entity'], $entity_key);
    $results = $query
      ->execute();
    $context['sandbox']['progress'] = 0;
    foreach ($results as $row) {
      $context['sandbox']['entity_ids'][] = $row->{$entity_key};
    }
    $context['sandbox']['max'] = count($context['sandbox']['entity_ids']);

    // Create the template before adding any rows to it.
    $context['sandbox']['csv_path'] = drupal_tempnam('temporary://', $feeds_importer->id);

    // We need a few variables and stuff when finished, so we shove them in the
    // results array.
    $context['results']['csv_path'] = $context['sandbox']['csv_path'];

    // FIXME - repetition!
    if ($context['sandbox']['max'] > 65534) {

      // One less than XLS max due to the
      // header row
      $context['results']['writer'] = 'Excel2007';
    }
    else {
      $context['results']['writer'] = 'Excel5';
    }
    $context['results']['importer'] = $feeds_importer->id;
    file_put_contents($context['results']['csv_path'], "\n");
    $context['finished'] = FALSE;
    $context['progress'] = 0;
  }

  // Load the csv file
  $csvf = fopen($context['sandbox']['csv_path'], 'a');

  // Load the entites
  $loop = 0;
  $ids_to_load = array();
  while ($loop < 500 && ($id = array_pop($context['sandbox']['entity_ids'])) != FALSE) {
    $ids_to_load[] = $id;
    $loop++;
  }
  $entities = entity_load($context['sandbox']['entity'], $ids_to_load);

  // Loop through each of the entities
  foreach ($entities as $entity_id => $entity) {

    // If we are unable to edit this entity, we go no further.
    if (!user_access('feeds xls allow download of all entities') && !(entity_access('update', $context['sandbox']['entity'], $entity) || entity_access('edit', $context['sandbox']['entity'], $entity))) {
      continue;
    }

    // Create a row array for each entity.
    $row_values = array();
    foreach ($feeds_importer->processor->config['mappings'] as $key => $mapping) {
      $row_values[$key] = '';
      if (strpos($mapping['target'], ':')) {

        // We currently know of two mappings (node:title and node:nid) that use
        // this format. We'll try to work out which this one is.
        $target = $mapping['target'];
        $target = explode(':', $target);

        // The country field is a little awkward, so we strip off the first
        // two parts.
        // FIXME - This WILL break with the entity language module and some
        // mappings, so we need to look for the specific field type.
        if (count($target) == 4) {
          array_shift($target);
          array_shift($target);
        }

        // First we check to see if we have a value, and proceed if we do.
        if (isset($entity->{$target[0]}) && is_array($entity->{$target[0]}) && count($entity->{$target[0]})) {
          $cell_values = array();

          // The date field users field:start/field:end, while the node_ref
          // field uses field:nid/field:title. We guess which we're using.
          foreach ($entity->{$target[0]} as $language => $values) {
            if ($language == LANGUAGE_NONE && count($cell_values)) {
              continue;
            }

            // FIXME - Why is this loop not foreach($values as ...)?
            foreach ($entity->{$target[0]}[$language] as $value) {
              switch ($target[1]) {
                case 'et':
                  if ($target[2] == $language || $language == LANGUAGE_NONE) {
                    _feeds_xls_create_csv_of_data_helper(FALSE, $mapping, $value, $cell_values);
                  }
                  break;
                case 'iso2':
                  $cell_values[] = $value['iso2'];
                  break;
                case 'guid':
                  $field = field_info_field($target[0]);
                  if (is_array($entity->{$target[0]}) && count($entity->{$target[0]})) {
                    $cell_values = array();
                    foreach ($entity->{$target[0]} as $language => $values) {
                      foreach ($entity->{$target[0]}[$language] as $value) {
                        foreach ($value as $subkey => $item) {

                          // Change to the allowed values array().
                          if ($field && !empty($field['settings']['allowed_values'][$item])) {
                            $item = $field['settings']['allowed_values'][$item];
                          }
                          switch ($subkey) {
                            case 'tid':

                              // Note, we could do this with a single query, but
                              // that would place a requirement on the UUID
                              // module/column,
                              // so doing it this way keeps it a little simpler.
                              $guid = db_select('feeds_item', 'f')
                                ->condition('entity_type', 'taxonomy_term')
                                ->condition('entity_id', $item)
                                ->fields('f', array(
                                'guid',
                              ))
                                ->execute()
                                ->fetchField();
                              if (!$guid) {
                                $term = taxonomy_term_load($item);
                                $guid = empty($term->uuid) ? '' : $term->uuid;
                              }
                              $cell_values[] = $guid;
                              break;
                            case 'nid':
                              $guid = db_select('feeds_item', 'f')
                                ->condition('entity_type', 'node')
                                ->condition('entity_id', $item)
                                ->fields('f', array(
                                'guid',
                              ))
                                ->execute()
                                ->fetchField();
                              if (!$guid) {
                                $node = node_load($item);
                                $guid = empty($node->uuid) ? '' : $node->uuid;
                              }
                              $cell_values[] = $guid;
                              break;
                          }
                        }
                      }
                    }
                  }
                  break;
                case 'tid':
                  $cell_values[] = $value['tid'];
                  break;
                case 'nid':
                  $cell_values[] = $value['nid'];
                  break;
                case 'uid':
                  $cell_values[] = $value['uid'];
                  break;
                case 'start':
                  if (substr($value['value'], -8) == '00:00:00') {
                    $value['value'] = trim(substr($value['value'], 0, -8));
                  }
                  $cell_values[] = $value['value'];
                  break;
                case 'end':
                  if (substr($value['value'], -8) == '00:00:00') {
                    $value['value'] = trim(substr($value['value'], 0, -8));
                  }
                  $cell_values[] = $value['value2'];
                  break;
                case 'MediaFeedsLibraryProvider':
                  $cell_values[] = $value['filename'];
                  break;
                default:

                  // We most likely have a field collection field. Lets try to
                  // load the field and check the type.
                  $field = field_info_field($target[0]);
                  if ($field['type'] == 'field_collection') {

                    // We restart the loop just so that we can get the IDs to
                    // all load at once
                    $ids = array();
                    foreach ($entity->{$target[0]}[$language] as $value) {
                      $ids[] = $value['value'];
                    }
                    foreach (entity_load('field_collection_item', $ids) as $fc_entity) {
                      foreach (array_keys($fc_entity->{$target[1]}) as $language) {
                        foreach (array_keys($fc_entity->{$target[1]}[$language]) as $delta) {
                          $cell_values[] = $fc_entity->{$target[1]}[$language][$delta]['value'];
                        }
                      }
                    }
                    break 3;
                  }
                  elseif ($field['type'] == 'link_field') {
                    $cell_values[] = $value[$target[1]];
                    break 3;
                  }
              }
            }
          }
          $row_values[$key] = _feeds_xls_get_value(implode('|', $cell_values));
        }
      }
      else {
        switch ($mapping['target']) {
          case 'group_audience':
            $gids = array();
            foreach ($entity->{$mapping['target']} as $language => $values) {
              foreach ($entity->{$mapping['target']}[$language] as $value) {
                $gids[] = $value['gid'];
              }
            }
            $row_values[$key] = implode('|', $gids);
            break;
          case 'guid':

            // Look for this entity in the feeds_item table. If not there, we
            // generate an entry for it.
            $guid = FALSE;
            if (isset($entity->uuid)) {
              $guid = $entity->uuid;
            }
            $feeds_item = feeds_xls_get_or_generate_feeds_item_entry($context['sandbox']['entity'], $entity_id, $feeds_importer->id, $guid);
            $row_values[$key] = _feeds_xls_get_value($feeds_item['guid']);
            break;
          case 'parentguid':

            // For some unknown reason, we don't have the parent of this entity,
            // so we need to query the taxonomy_term_hierarchy table.
            $row = db_select('taxonomy_term_hierarchy', 't')
              ->fields('t')
              ->condition('tid', $entity_id)
              ->execute()
              ->fetch();
            if ($row && $row->parent) {
              $parent_term = taxonomy_term_load($row->parent);
              if ($parent_term) {
                $guid = FALSE;
                if (isset($parent_term->uuid)) {
                  $guid = $parent_term->uuid;
                }
                $feeds_item = feeds_xls_get_or_generate_feeds_item_entry($context['sandbox']['entity'], $parent_term->tid, $feeds_importer->id, $guid);
                $row_values[$key] = _feeds_xls_get_value($feeds_item['guid']);
              }
            }
            break;
          case 'parent':

          // We don't do anything for parent, as we use parentguid instead.
          case 'pass':

            // We don't do anything for password
            break;
          case 'name':
          case 'mail':

            // Check if we are a stub user - we don't want to continue
            if (!empty($entity->stub_user)) {
              break;
            }
          default:
            if (isset($entity->{$mapping['target']})) {
              $field = field_info_field($mapping['target']);

              // We can't do anything with file fields (we allow import, but not
              // updating).
              if (in_array($field['type'], array(
                'file',
              ))) {
                continue;
              }
              if (is_array($entity->{$mapping['target']}) && count($entity->{$mapping['target']})) {
                $cell_values = array();
                foreach ($entity->{$mapping['target']} as $language => $values) {
                  $implosion = '|';
                  foreach ($entity->{$mapping['target']}[$language] as $value) {
                    _feeds_xls_create_csv_of_data_helper($field, $mapping, $value, $cell_values);
                  }
                }
                $row_values[$key] = _feeds_xls_get_value(implode($implosion, $cell_values));
              }
              elseif (is_string($entity->{$mapping['target']})) {
                $row_values[$key] = _feeds_xls_get_value($entity->{$mapping['target']});
              }
            }
        }
      }
    }

    // Increase the row number
    $context['sandbox']['row']++;

    // Write out the fields
    fputcsv($csvf, $row_values);
  }
  fclose($csvf);

  // Set the progress
  $context['progress'] = $context['sandbox']['row'] / $context['sandbox']['max'];
  $context['finished'] = $context['progress'];
  $context['message'] = t('Added @current entities out of @total to the file.', array(
    '@current' => $context['sandbox']['row'],
    '@total' => $context['sandbox']['max'],
  ));
  if (!count($context['sandbox']['entity_ids'])) {
    $context['finished'] = TRUE;

    // Set a message warning the user that the download will take a little while
    // to create.
    $context['message'] = t('Please wait while your file is converted.  This can take a few minutes.');
  }
}