8.5.x form.inc batch_process($redirect = NULL, Url $url = NULL, $redirect_callback = NULL)
8.0.x form.inc batch_process($redirect = NULL, Url $url = NULL, $redirect_callback = NULL)
8.1.x form.inc batch_process($redirect = NULL, Url $url = NULL, $redirect_callback = NULL)
8.2.x form.inc batch_process($redirect = NULL, Url $url = NULL, $redirect_callback = NULL)
8.3.x form.inc batch_process($redirect = NULL, Url $url = NULL, $redirect_callback = NULL)
8.4.x form.inc batch_process($redirect = NULL, Url $url = NULL, $redirect_callback = NULL)
8.6.x form.inc batch_process($redirect = NULL, Url $url = NULL, $redirect_callback = NULL)
6.x form.inc batch_process($redirect = NULL, $url = NULL)
7.x form.inc batch_process($redirect = NULL, $url = 'batch', $redirect_callback = 'drupal_goto')

Processes the batch.

Unless the batch has been marked with 'progressive' = FALSE, the function issues a drupal_goto and thus ends page execution.

This function is generally not needed in form submit handlers; Form API takes care of batches that were set during form submission.

Parameters

$redirect: (optional) Path to redirect to when the batch has finished processing.

$url: (optional - should only be used for separate scripts like update.php) URL of the batch processing page.

$redirect_callback: (optional) Specify a function to be called to redirect to the progressive processing page. By default drupal_goto() will be used to redirect to a page which will do the progressive page. Specifying another function will allow the progressive processing to be processed differently.

Related topics

9 calls to batch_process()
batch_test_large_percentage in modules/simpletest/tests/batch_test.module
Menu callback: fire a batch process without a form submission.
batch_test_nested_drupal_form_submit in modules/simpletest/tests/batch_test.module
Menu callback: programmatically submits a form within a batch.
batch_test_no_form in modules/simpletest/tests/batch_test.module
Menu callback: fire a batch process without a form submission.
batch_test_theme_batch in modules/simpletest/tests/batch_test.module
Menu callback: run a batch for testing theme used on the progress page.
drupal_process_form in includes/form.inc
Processes a form submission.

... See full list

File

includes/form.inc, line 4645
Functions for form and batch generation and processing.

Code

function batch_process($redirect = NULL, $url = 'batch', $redirect_callback = 'drupal_goto') {
  $batch =& batch_get();
  drupal_theme_initialize();
  if (isset($batch)) {

    // Add process information
    $process_info = array(
      'current_set' => 0,
      'progressive' => TRUE,
      'url' => $url,
      'url_options' => array(),
      'source_url' => $_GET['q'],
      'redirect' => $redirect,
      'theme' => $GLOBALS['theme_key'],
      'redirect_callback' => $redirect_callback,
    );
    $batch += $process_info;

    // The batch is now completely built. Allow other modules to make changes
    // to the batch so that it is easier to reuse batch processes in other
    // environments.
    drupal_alter('batch', $batch);

    // Assign an arbitrary id: don't rely on a serial column in the 'batch'
    // table, since non-progressive batches skip database storage completely.
    $batch['id'] = db_next_id();

    // Move operations to a job queue. Non-progressive batches will use a
    // memory-based queue.
    foreach ($batch['sets'] as $key => $batch_set) {
      _batch_populate_queue($batch, $key);
    }

    // Initiate processing.
    if ($batch['progressive']) {

      // Now that we have a batch id, we can generate the redirection link in
      // the generic error message.
      $t = get_t();
      $batch['error_message'] = $t('Please continue to <a href="@error_url">the error page</a>', array(
        '@error_url' => url($url, array(
          'query' => array(
            'id' => $batch['id'],
            'op' => 'finished',
          ),
        )),
      ));

      // Clear the way for the drupal_goto() redirection to the batch processing
      // page, by saving and unsetting the 'destination', if there is any.
      if (isset($_GET['destination'])) {
        $batch['destination'] = $_GET['destination'];
        unset($_GET['destination']);
      }

      // Store the batch.
      db_insert('batch')
        ->fields(array(
        'bid' => $batch['id'],
        'timestamp' => REQUEST_TIME,
        'token' => drupal_get_token($batch['id']),
        'batch' => serialize($batch),
      ))
        ->execute();

      // Set the batch number in the session to guarantee that it will stay alive.
      $_SESSION['batches'][$batch['id']] = TRUE;

      // Redirect for processing.
      $function = $batch['redirect_callback'];
      if (function_exists($function)) {
        $function($batch['url'], array(
          'query' => array(
            'op' => 'start',
            'id' => $batch['id'],
          ),
        ));
      }
    }
    else {

      // Non-progressive execution: bypass the whole progressbar workflow
      // and execute the batch in one pass.
      require_once DRUPAL_ROOT . '/includes/batch.inc';
      _batch_process();
    }
  }
}

Comments

mredding’s picture

If you don't set the $redirect parameter in batch_process() when using the Batch API in a module, the batch will enter into an endless loop. Even a dummy URL will do---just put something in there to stop the infinite loop!

randomyao22’s picture

Just tested, you are right.

samuel.mortenson’s picture

It should be documented that $redirect is eventually set as the form_state redirect, which means you can use an array for this param or a string. See https://api.drupal.org/api/drupal/includes!form.inc/function/drupal_redi... for more info on form state redirection.

texas-bronius’s picture

Would be good to know what exactly:

Specifying another function will allow the progressive processing to be processed differently

can do for a developer.

Defaults to drupal_goto which, also by default, will redirect to 'batch' to proceed with processing the batch.

The default path 'batch' is defined in System module (./modules/system/system.module) hook_menu:

  // Default page for batch operations.
  $items['batch'] = array(
    'page callback' => 'system_batch_page',
    'access callback' => TRUE,
    'theme callback' => '_system_batch_theme',
    'type' => MENU_CALLBACK,
    'file' => 'system.admin.inc',
  );

and the contents of system_batch_page is:

  require_once DRUPAL_ROOT . '/includes/batch.inc';
  $output = _batch_page();

  if ($output === FALSE) {
    drupal_access_denied();
  }
  elseif (isset($output)) {
    // Force a page without blocks or messages to
    // display a list of collected messages later.
    drupal_set_page_content($output);
    $page = element_info('page');
    $page['#show_messages'] = FALSE;
    return $page;
  }

so my guess is that your own custom redirect_callback should do something to invoke internal _batch_page() for in-browser requests or internal _batch_process().. but I'm still a bit stuck on why _batch_process() called directly never fires my 'finished' callback nor why simply copying in the above contents of system_batch_page throws Access Denied.

If a developer wants batch processing to progress without a page redirect, for instance, where does one go to figure out how to do that?