Same name and namespace in other branches
  1. 6.x includes/form.inc \batch_process()
  2. 7.x includes/form.inc \batch_process()
  3. 8.9.x core/includes/form.inc \batch_process()
  4. 9 core/includes/form.inc \batch_process()

Processes the batch.

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

Parameters

\Drupal\Core\Url|string $redirect: (optional) Either a path or Url object to redirect to when the batch has finished processing. For example, to redirect users to the home page, use '<front>'. If you wish to allow standard form API batch handling to occur and force the user to be redirected to a custom location after the batch has finished processing, you do not need to use batch_process() and this parameter. Instead, make the batch 'finished' callback return an instance of \Symfony\Component\HttpFoundation\RedirectResponse, which will be used automatically by the standard batch processing pipeline (and which takes precedence over this parameter). If this parameter is omitted and no redirect response was returned by the 'finished' callback, the user will be redirected to the page that started the batch. Any query arguments will be automatically persisted.

\Drupal\Core\Url $url: (optional) URL of the batch processing page. Should only be used for separate scripts like update.php.

$redirect_callback: (optional) Specify a function to be called to redirect to the progressive processing page.

Return value

\Symfony\Component\HttpFoundation\RedirectResponse|null A redirect response if the batch is progressive. No return value otherwise.

Related topics

9 calls to batch_process()
BatchTestController::testFinishRedirect in core/modules/system/tests/modules/batch_test/src/Controller/BatchTestController.php
Fires a batch process without a form submission and a finish redirect.
BatchTestController::testLargePercentage in core/modules/system/tests/modules/batch_test/src/Controller/BatchTestController.php
Fires a batch process without a form submission.
BatchTestController::testNestedDrupalFormSubmit in core/modules/system/tests/modules/batch_test/src/Controller/BatchTestController.php
Submits a form within a batch programmatically.
BatchTestController::testNoForm in core/modules/system/tests/modules/batch_test/src/Controller/BatchTestController.php
Fires a batch process without a form submission.
BatchTestController::testThemeBatch in core/modules/system/tests/modules/batch_test/src/Controller/BatchTestController.php
Runs a batch for testing theme used on the progress page.

... See full list

File

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

Code

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

    // Add process information
    $process_info = [
      'current_set' => 0,
      'progressive' => TRUE,
      'url' => $url ?? Url::fromRoute('system.batch_page.html'),
      'source_url' => Url::fromRouteMatch(\Drupal::routeMatch())
        ->mergeOptions([
        'query' => \Drupal::request()->query
          ->all(),
      ]),
      'batch_redirect' => $redirect,
      'theme' => \Drupal::theme()
        ->getActiveTheme()
        ->getName(),
      '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::moduleHandler()
      ->alter('batch', $batch);

    // Assign an id to progressive batches. Non-progressive batches skip
    // database storage completely.
    try {
      $batch['id'] = $batch['progressive'] ? \Drupal::service(BatchStorageInterface::class)
        ->getId() : 'non-progressive';
    } catch (IntegrityConstraintViolationException $e) {

      // @todo this is here to support the update path to deprecate
      // Connection::nextId(). Remove in Drupal 11.
      $connection = \Drupal::database();
      $max_bid = (int) $connection
        ->query('SELECT MAX([bid]) FROM {batch}')
        ->fetchField();
      $batch['id'] = $max_bid + 1;
      $connection
        ->insert('batch')
        ->fields([
        'bid' => $batch['id'],
        'timestamp' => \Drupal::time()
          ->getRequestTime(),
        'token' => '',
        'batch' => NULL,
      ])
        ->execute();
    }

    // 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.

      /** @var \Drupal\Core\Url $batch_url */
      $batch_url = $batch['url'];

      /** @var \Drupal\Core\Url $error_url */
      $error_url = clone $batch_url;
      $query_options = $error_url
        ->getOption('query');
      $query_options['id'] = $batch['id'];
      $query_options['op'] = 'finished';
      $error_url
        ->setOption('query', $query_options);
      $batch['error_message'] = t('Continue to <a href=":error_url">the error page</a>', [
        ':error_url' => $error_url
          ->toString(TRUE)
          ->getGeneratedUrl(),
      ]);

      // Clear the way for the redirection to the batch processing page, by
      // saving and unsetting the 'destination', if there is any.
      $request = \Drupal::request();
      if ($request->query
        ->has('destination')) {
        $batch['destination'] = $request->query
          ->get('destination');
        $request->query
          ->remove('destination');
      }

      // Store the batch.
      \Drupal::service(BatchStorageInterface::class)
        ->create($batch);

      // Set the batch number in the session to guarantee that it will stay alive.
      $session = \Drupal::request()
        ->getSession();
      $batches = $session
        ->get('batches', []);
      $batches[$batch['id']] = TRUE;
      $session
        ->set('batches', $batches);

      // Redirect for processing.
      $query_options = $error_url
        ->getOption('query');
      $query_options['op'] = 'start';
      $query_options['id'] = $batch['id'];
      $batch_url
        ->setOption('query', $query_options);
      if (($function = $batch['redirect_callback']) && function_exists($function)) {
        $function($batch_url
          ->toString(), [
          'query' => $query_options,
        ]);
      }
      else {
        return new RedirectResponse($batch_url
          ->setAbsolute()
          ->toString(TRUE)
          ->getGeneratedUrl());
      }
    }
    else {

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