Question

I have 2 operations in a module using Batch API. Below is the code for the first one:

function get_first_data($qc, $path) {
    $testsets = some array...

    foreach ($testsets as $testset) {
    $operations[] = array('first_data_batch', array($testset));
  }

  $batch = array(
    'operations' => $operations,
    'finished' => 'first_data_batch_finished',
    'title' => t('First Data'),
    'init_message' => t('Import is starting...'),
    'progress_message' => t('Processed @current out of @total.'),
    'error_message' => t('An error has occurred')
  );

  batch_set($batch);
  batch_process('user'); // The path to redirect to when done.
}

function first_data_batch($testset, &$context) {
    // do something with $testset

    $context['message'] = "Processing...";
}

function first_data_batch_finished($success, $results, $operations) {
  if ($success) {
    drupal_set_message('First import is complete!');
  }
  else {
    $error_operation = reset($operations);
    $message = t('An error occurred while processing %error_operation with arguments: @arguments', array(
      '%error_operation' => $error_operation[0],
      '@arguments' => print_r($error_operation[1], TRUE)
    ));
    drupal_set_message($message, 'error');
  }
  drupal_set_message(l('Run again', 'my_module/batch'));
}

What I need is to have another operation that uses the output of the first one.

I think I can't set this second operation on the foreach cycle of the first one because the loop is completely different so I'm assuming I would repeate the code below for my second batch. The only issue is how to pass the output of the first one to the second one.

Another thing: in the first_data_batch function I generate part of the output that I want to feed in the second batch. The final array that I want to feed will be completed only after all the calls to this function end.

So, how can I pass this array to the second batch?

Thanks.

================================ EDIT ================================

I cleaned my code. This one is simpler but I still can't the information I need after the operation.

testcases_raw array (: testcases_raw array

My code:

function mymodule_form_submit($form, &$form_state) {
  $testcases_raw = array...
  $batch = array(
    'title' => t('Working ...'),
    'operations' => array(),
    'finished' => 'mymodule_batch_finished',
    'init_message' => t('Starting ...'),
    'progress_message' => t('Processed @current out of @total.'),
    'error_message' => t('An error occurred during processing'),
    'progressive' => FALSE
  );

  if (isset($testcases_raw['Entity'][0])) {
    foreach ($testcases_raw['Entity'] as $folder) {
      $batch['operations'][] = array('batch_testsets_multiple', array($folder));
    }
  } else {
    $batch['operations'][] = array('batch_testsets_single', array($testcases_raw));
  }
  batch_set($batch);
}

function batch_testsets_multiple($folder, &$context) {
  $a = $folder;

  $id = $a['Fields']['Field'][51]['Value'];
  $parent_id = $a['Fields']['Field'][28]['Value'];
  $name = $a['Fields']['Field'][54]['Value'];

  $testset = array('id' => $id, 'parent_id' => $parent_id, 'name' => $name);
  array_push($testsets, $testset);
  dd($testset);         
  $context['results'] = $testsets;
  $context['message'] = $testsets;
}

function batch_testsets_single($folder, &$context) {
  $testsets = $context['results'];
  $id = $folder['Entity']['Fields']['Field'][51]['Value'];
  $parent_id = $folder['Entity']['Fields']['Field'][28]['Value'];
  $name = $folder['Entity']['Fields']['Field'][54]['Value'];

  $testset = array('id' => $id, 'parent_id' => $parent_id, 'name' => $name);
  array_push($testsets, $testset);

  $context['results'] = $testsets;
  $context['message'] = $testsets;
}

function mymodule_batch_finished($success, $results, $operations) {
  if ($success) {
    $message = format_plural(count($results), 'One processed.', '@count processed');
  } else {
    $message = t('Finished with an error.');
  }
  foreach ($results as $result) {
    drupal_set_message($result);
  }
  drupal_set_message($message);
}

In this example, the batch_testsets_multiple function will run 4 times. In each of the iterations I get one new array ($testset). Below are the 4 arrays as outputed to file by dd command:

Array
(
    [id] => 132202
    [parent_id] => 38680
    [name] => _TestSet1
)

Array
(
    [id] => 132203
    [parent_id] => 38680
    [name] => _TestSet2
)

Array
(
    [id] => 132345
    [parent_id] => 38797
    [name] => _TestSet3
)

Array
(
    [id] => 132394
    [parent_id] => 38831
    [name] => _TestSet4
)

What I need at the end of the batch opearation batch_testsets_multiple is an array with the 4 arrays above so I can use that array as input for a second operation. I think this code is simplier to understand. Hope it really helps.

Was it helpful?

Solution

OK, after some struggle I found the solution and it's very simple (maybe I was complicating?).

Here is how my solution looks like:

function batch_testsets_multiple($folder, &$context) {
  $id = $folder['Fields']['Field'][51]['Value'];
  $parent_id = $folder['Fields']['Field'][28]['Value'];
  $name = $folder['Fields']['Field'][54]['Value'];

  $testset = array('id' => $id, 'parent_id' => $parent_id, 'name' => $name);

  // Here I save the iteration results to an array.
  // The [] ensures that all iteration results ($testset) are saved;
  $context['results']['testsets'][] = $testset;
  $context['message'] = $testsets;
}

OTHER TIPS

You can use $context['results'] to pass data between operations.

function first_data_batch($data, &$context) {
  // Get the data from previous operation.
  $bar = $context['results']['foo'];

  // Do something with it...

  // And store the results for the next operation. 
  $context['results']['foo'] = $bar;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with drupal.stackexchange
scroll top