You are here

function callback_batch_operation in Drupal 10

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/Form/form.api.php \callback_batch_operation()
  2. 7 modules/system/form.api.php \callback_batch_operation()
  3. 9 core/lib/Drupal/Core/Form/form.api.php \callback_batch_operation()

Perform a single batch operation.

Callback for batch_set().

Parameters

$multiple_params: Additional parameters specific to the batch. These are specified in the array passed to batch_set().

array|\ArrayAccess $context: The batch context array, passed by reference. This contains the following properties:

  • 'finished': A float number between 0 and 1 informing the processing engine of the completion level for the operation. 1 (or no value explicitly set) means the operation is finished: the operation will not be called again, and execution passes to the next operation or the callback_batch_finished() implementation. Any other value causes this operation to be called again; however it should be noted that the value set here does not persist between executions of this callback: each time it is set to 1 by default by the batch system.
  • 'sandbox': This may be used by operations to persist data between successive calls to the current operation. Any values set in $context['sandbox'] will be there the next time this function is called for the current operation. For example, an operation may wish to store a pointer in a file or an offset for a large query. The 'sandbox' array key is not initially set when this callback is first called, which makes it useful for determining whether it is the first call of the callback or not:
if (empty($context['sandbox'])) {

  // Perform set-up steps here.
}

The values in the sandbox are stored and updated in the database between http requests until the batch finishes processing. This avoids problems if the user navigates away from the page before the batch finishes.

  • 'message': A text message displayed in the progress page.
  • 'results': The array of results gathered so far by the batch processing. This array is highly useful for passing data between operations. After all operations have finished, this is passed to callback_batch_finished() where results may be referenced to display information to the end-user, such as how many total items were processed.

It is discouraged to typehint this parameter as an array, to allow an object implement \ArrayAccess to be passed.

Related topics

File

core/lib/Drupal/Core/Form/form.api.php, line 57
Callbacks and hooks related to form system.

Code

function callback_batch_operation($multiple_params, &$context) {
  $node_storage = \Drupal::entityTypeManager()
    ->getStorage('node');
  $database = \Drupal::database();
  if (!isset($context['sandbox']['progress'])) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current_node'] = 0;
    $context['sandbox']['max'] = $database
      ->query('SELECT COUNT(DISTINCT [nid]) FROM {node}')
      ->fetchField();
  }

  // For this example, we decide that we can safely process
  // 5 nodes at a time without a timeout.
  $limit = 5;

  // With each pass through the callback, retrieve the next group of nids.
  $result = $database
    ->queryRange("SELECT [nid] FROM {node} WHERE [nid] > :nid ORDER BY [nid] ASC", 0, $limit, [
    ':nid' => $context['sandbox']['current_node'],
  ]);
  foreach ($result as $row) {

    // Here we actually perform our processing on the current node.
    $node_storage
      ->resetCache([
      $row['nid'],
    ]);
    $node = $node_storage
      ->load($row['nid']);
    $node->value1 = $options1;
    $node->value2 = $options2;
    node_save($node);

    // Store some result for post-processing in the finished callback.
    $context['results'][] = $node->title;

    // Update our progress information.
    $context['sandbox']['progress']++;
    $context['sandbox']['current_node'] = $node->nid;
    $context['message'] = t('Now processing %node', [
      '%node' => $node->title,
    ]);
  }

  // Inform the batch engine that we are not finished,
  // and provide an estimation of the completion level we reached.
  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
  }
}