rpayanm
11/6/2019 - 1:09 PM

Batch processing and update hooks in Drupal

<?php

/**
 * Implements hook_update().
 */
function MODULE_NAME_update_800X(&$sandbox) {
  // Use the sandbox at your convenience to store the information needed
  // to track progression between successive calls to the function.
  if (!isset($sandbox['progress'])) {
    // The count of nodes visited so far.
    $sandbox['progress'] = 0;

    // Total nodes that must be visited.
    $nids = Drupal::entityQuery('node')
      ->condition('type', 'TYPE')->execute();
    $sandbox['max'] = count($nids);

    if (empty($sandbox['max'])) {
      $sandbox['#finished'] = 1;
      return;
    }
  }

  // Process nodes by groups of 25 (arbitrary value).
  // When a group is processed, the batch update engine determines
  // whether it should continue processing in the same request or provide
  // progress feedback to the user and wait for the next request.
  $limit = 25;

  // Retrieve the next group of nids.
  $nids = Drupal::entityQuery('node')
    ->condition('type', 'TYPE')
    ->range($sandbox['progress'], $sandbox['progress'] + $limit)
    ->sort('nid')
    ->execute();

  if (empty($nids)) {
    $sandbox['#finished'] = 1;
    return;
  }

  $nodes = Drupal::entityTypeManager()
    ->getStorage('node')
    ->loadMultiple($nids);

  /** @var \Drupal\node\Entity\Node $node */
  foreach ($nodes as $node) {
    $node->field_FIELD_NAME->value = TRUE;
    $node->save();

    // Update our progress information.
    $sandbox['progress']++;
  }

  // Set the "finished" status, to tell batch engine whether this function
  // needs to run again. If you set a float, this will indicate the progress
  // of the batch so the progress bar will update.
  $sandbox['#finished'] = $sandbox['progress'] >= $sandbox['max'] ? TRUE : $sandbox['progress'] / $sandbox['max'];
}