I'm creating a feature and I would like to automatically import a csv when the feature is enabled... I have a feed configured that is working but I'm struggling to find a way to call the save method with a file. This is what I have for now...

$source = feeds_source($my_importer);

// Somehow access the config of $source to add my file

$source->startImport();

Thank you !

Comments

emorency’s picture

I found a way to add default content when drupal is installed using an importer. Maybe someone will be interested by this...

I have a custom profile and I wanted to load default content stored in csv files when a site with this profile we being installed. This is what I added to the file custom_profile.profile. The following adds a new installation task that imports content in batch mode. It supports importing multiple files with their own feeds importer.

/**
 * Implements hook_install_tasks()
 *
 */
function custom_profile_install_tasks($install_state){
  $task['default_content'] = array(
    'display_name' => st('Add default content'),
    'display' => TRUE,
    'type' => 'batch',
    'run' => INSTALL_TASK_RUN_IF_NOT_COMPLETED, // default to insert content
    'function' => 'import_default_feeds',
  ); 
  
  return $task;
}

function import_default_feeds($install_state){

  $root = drupal_get_path('profile', 'custom_profile') . '/data';
  $feed_configs = array();
  $feed_configs['csv_import_1'] = array( // 'csv_import_1' is the importer_id of an importer that has been previously created and exported through a feature
    'file' => $root . '/import_1.csv',
  );
    
  $operations = array();
  foreach($feed_configs as $importer => $file){
    $source = feeds_source($importer);

    foreach ($source->importer->plugin_types as $type) {
      if ($source->importer->$type->hasSourceConfig()) {
        $class = get_class($source->importer->$type);
        if ($class == 'FeedsFileFetcher'){
          $config = isset($source->config[$class]) ? $source->config[$class] : array();
        
          $config['source'] = $file['file'];
          $source->setConfigFor($source->importer->$type, $config);
        }  
      }
    }
    $source->save();
    $operations[] = array('feeds_batch', array('import', $source->id, $source->feed_nid));
  }
  
  $batch = array(
      'title' => t('Importing'),
      'operations' => $operations,
      'progress_message' => 'Creating default content',
    );

  return $batch;
}
pcambra’s picture

I couldn't make it work with startimport() programatically either.

I reached a similar solution to yours but with several batches:

  // Files to import in specific order.
  $files = array(
    'first_importer' => 'file1.csv',
    'second_importer' => 'file2.csv',
    'third_importer' => 'file3.csv',
    // ...
  );

  foreach ($files as $feed => $file) {
    $feedSource = feeds_source($feed);
    // Set the file name to import
    $filename = '/path/to/file/' . $file;
    if (!file_destination($filename, FILE_EXISTS_ERROR)) {
      $config = $feedSource->getConfig();
      $config['FeedsFileFetcher']['source'] = $filename;
      $feedSource->setConfig($config);
      $feedSource->save();

      $batch = array(
        'title' => t('Importing feeds'),
        'operations' => array(
          array('feeds_batch', array('import', $feed, 0)),
        ),
        'progress_message' => t('Current: @current | Remaining:
          @remaining | Total: @total | Percentage: @percentage | Estimate:
          @estimate | Elapsed: @elapsed'),
      );
      batch_set($batch);
    }
  }
  batch_process('redirect-url');
cosmicdreams’s picture

Thank you both, this sample code is extremely helpful!

twistor’s picture

Perhaps this should be added to the docs.

pcambra’s picture

I'd happy to add this to the docs, but I'd need confirmation which is the right way to do so

DjebbZ’s picture

Bumping the issue : is this the proper way to do ?
And a question : can we include similar code in a hook_cron ?

pontus_nilsson’s picture

I have done a somewhat different approach. I create a feeds node with an external feed as source, save the node and start the batch. Maybe someone finds this useful. The feeds importer is exported through features, so is the target content type and the "feeds" content type. After the installation I can point remove the imported nodes, change the source feed and create some other nodes.

Just to be clear this is how I setup my installation task in the installation profile.

/**
* Implements hook_install_tasks().
*/
function myprofile_install_tasks() {
  $tasks = array(
    'myprofile_create_feed' => array(
      'display_name' => st('Import feed'),
      'display' => TRUE,
      'type' => 'batch',
      'run' => INSTALL_TASK_RUN_IF_NOT_COMPLETED,
    )
  );
  return $tasks;
}
/**
 * Install task create campaign blog feed
 */
function myprofile_create_feed() {
  // Create the feeds node
  $node = new stdClass();
  // The feeds node is of type myprofile_feed
  $node->type = 'myprofile_feed';
  $node->title = 'Myprofile feed';
  // Source feed to create nodes from
  $node->feeds['FeedsHTTPFetcher']['source'] = 'http://site.com/feed/';
  node_save($node);

  // Add a batch to import the feed set in the node
  // myprofile_feed_import is my exported feed importer.
  $batch = array(
    'title' => t('Importing feeds'),
    'operations' => array(
      array('feeds_batch', array('import', 'myprofile_feed_import', $node->nid)),
      ),
      'progress_message' => t('Current: @current | Remaining: @remaining | Total: @total | Percentage: @percentage | Estimate: @estimate | Elapsed: @elapsed'),
    );
  return $batch;
}
saritha.peddapuli’s picture

i got error saying that "Download of failed with code -1002."

Please help me. I want to import multiple xml files using cron.

pcambra’s picture

See #608408: Drush integration for Feeds as an alternative of importing feeds from command line.

saritha.peddapuli’s picture

Thanks pcambra.
how can i give the folder name instead of single xml file. I want to execute a php script with cron, in that script i want to import all XML files in a folder.

How can i use Drush integration. I mean which patch should i install or any documentation/steps needed.

Thanks in Advance

saritha.peddapuli’s picture

Hi pcambra,

I am using following code to import multiple files, but it importing a single file(first xml file).

Can you please help me to import all files in a directory

$files = array(
    'first_importer' => 'test2.xml',
    'second_importer' => 'test3.xml',
    'third_importer' => 'sample.xml',
  );
  
  foreach ($files as $key => $file) {
	$filename = 'http://localhost/XXX/'.$file;
	import_feed_data($filename);
  }

function import_feed_data($filename = ''){

  $feed = 'add_sample_data';
  $feedSource = feeds_source($feed);
  
  $config = $feedSource->getConfig();
  $config['FeedsHTTPFetcher']['source'] = $filename;
  $feedSource->setConfig($config);
  $feedSource->save();
  $batch = array(
        'title' => t('Importing feeds'),
        'operations' => array(
          array('feeds_batch', array('import', $feed, 0)),
        ),
        'progress_message' => t('Current: @current | Remaining:
          @remaining | Total: @total | Percentage: @percentage | Estimate:
          @estimate | Elapsed: @elapsed'),
      );
      batch_set($batch);
    
  batch_process('redirect-url');
  }

Thanks
Sari

pcambra’s picture

I'd say you can't just throw stuff to the batch api like that, you probably need to do some DrupalQueue for that, good thing is that queue is integrated with cron for D7.

saritha.peddapuli’s picture

Thanks Pcambra.. i will try to use DrupalQueue

POVYLAZZZ’s picture

If you have succeeded in importing from multiple sources could you share the solution?

I have tried using DrupalQueues but it resulted in executing just the first source.

toby wild’s picture

Issue summary: View changes

Bit of an old issue, but I hope this helps someone.

So my case is syndicating content from an Intranet to an Extranet on different servers.
The Intranet exports XML files and SFTP's them to the Extranet server.
Then I run:

// Files to import in specific order.
  $files = array(
	'tax' => 'structure/structure.xml',
	'people' => 'people/people.xml',
  );
  foreach ($files as $feed => $file) {
  
    $feedSource = feeds_source($feed);
    $filename = 'public://import/' . $file;
	
    if (!file_destination($filename, FILE_EXISTS_ERROR)) {
      $config = $feedSource->getConfig();
      $config['FeedsFileFetcher']['source'] = $filename;
      $feedSource->setConfig($config);
      $feedSource->save();
      $batch = array(
        'title' => t('Importing feeds'),
        'operations' => array(
          array('feeds_batch', array('import', $feed, 0)),
        ),
        'progress_message' => t('Current: @current | Remaining:
          @remaining | Total: @total | Percentage: @percentage | Estimate:
          @estimate | Elapsed: @elapsed'),
      );
      batch_set($batch);
    }
  }
  batch_process('import/people');

This imports the two XML's one after the other.
POVYLAZZZ, if you are looking to import from multiple sources, simply make the $filename variable only contain the $file variable from the Array and put the full path in there instead.

One issue I do still have is that I can't import the same file twice.
This is an issue for me as the People have an entity reference field that reference other 'People', so if it looks for the reference and the Person hasn't been created yet, then it throws a Warning.
So I import it twice, once to import, once to confirm the Reference.
However, having two entries of ''people' => 'people/people.xml',' doesn't import it twice.
My work around is that I run the whole snippet twice.

merilainen’s picture

Would you mind explaining where is this code placed? How do you run it?

tim_marsh’s picture

Ive found this thread after researching , maybe this answer Ive just posted will help you / someone : http://drupal.stackexchange.com/a/153434/41701 , basically if you're running this from the ui / form hook - thats fine, but if you're using it in an install , then you can either use drush, or call feeds api calls directly, bypassing the need for the batch api.

so , in a hook_install, you can call something like this.

function load_data(){

// Files to import in specific order.
  $files = array(
    'challenge_importer' => 'data/challenges.csv',
);

$file_location_base = drupal_get_path('module', 'challenge');
foreach ($files as $feed => $file) {

$feedSource = feeds_source($feed);
// Set the file name to import
$filename = $file_location_base.'/' . $file;
if (!file_destination($filename, FILE_EXISTS_ERROR)) {
  $config = $feedSource->getConfig();
  $config['FeedsFileFetcher']['source'] = $filename;
  $feedSource->setConfig($config);
  $feedSource->save();
    while (FEEDS_BATCH_COMPLETE != $feedSource->import());
    }
  }
}

the reason being
batch_process('import/people'); is saying redirect me to import/people ... which it doesnt make sense to do in the command line / install situation

Bhaskar J’s picture

Hi,

Is Feeds importer module works on localhost?

bluegeek9’s picture

Status: Active » Closed (outdated)

Drupal 7 reached end of life and the D7 version of Feeds is no longer being developed. To keep the issue queue focused on supported versions, we’re closing older D7 issues.

If you still have questions about using Feeds on Drupal 7, feel free to ask. While we won’t fix D7 bugs anymore, we’re happy to offer guidance to help you move forward. You can do so by opening (or reopening) a D7 issue, or by reaching out in the #feeds channel on Drupal Slack.

If this issue is still relevant for Drupal 10+, please open a follow-up issue or merge request with proposed changes. Contributions are always welcome!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.