function NodeAccessRebuild::rebuild

Same name and namespace in other branches
  1. main core/modules/node/src/NodeAccessRebuild.php \Drupal\node\NodeAccessRebuild::rebuild()

Rebuilds the node access database.

This rebuild is occasionally needed by modules that make system-wide changes to access levels. When the rebuild is required by an admin-triggered action (e.g module settings form), calling self::setNeedsRebuild(TRUE) instead of self::rebuild() lets the user perform changes and actually rebuild only once done.

Parameters

bool $batch_mode: (optional) Set to TRUE to process in 'batch' mode, spawning processing over several HTTP requests (thus avoiding the risk of PHP timeout if the site has a large number of nodes). hook_update_N() and any form submit handler are safe contexts to use the 'batch mode'. Less decidable cases (such as calls from hook_user(), hook_taxonomy(), etc.) might consider using the non-batch mode. Defaults to FALSE. Calling this method multiple times in the same request with $batch_mode set to TRUE will only result in one batch set being added.

See also

self::needsRebuild()

File

core/modules/node/src/NodeAccessRebuild.php, line 92

Class

NodeAccessRebuild
Provides methods for checking and rebuilding node access permissions.

Namespace

Drupal\node

Code

public function rebuild(bool $batch_mode = FALSE) : void {
  $node_storage = $this->entityTypeManager
    ->getStorage('node');
  $access_control_handler = $this->entityTypeManager
    ->getAccessControlHandler('node');
  // If the rebuild fails to complete, and node_access_needs_rebuild is not
  // set to TRUE, the node_access table is left in an incomplete state.
  // Force node_access_needs_rebuild to TRUE once existing grants are deleted,
  // to signal that the node access table still needs to be rebuilt if this
  // function does not finish.
  $this->setNeedsRebuild(TRUE);
  $access_control_handler->deleteGrants();
  // Only recalculate if the site is using a node_access module.
  if ($this->moduleHandler
    ->hasImplementations('node_grants')) {
    if ($batch_mode) {
      if (!BatchBuilder::isSetIdRegistered(__FUNCTION__)) {
        $batch_builder = (new BatchBuilder())->setTitle($this->t('Rebuilding content access permissions'))
          ->addOperation(static::class . ':batchOperation')
          ->setFinishCallback(static::class . ':batchFinished')
          ->registerSetId(__FUNCTION__);
        batch_set($batch_builder->toArray());
      }
    }
    else {
      // Try to allocate enough time to rebuild node grants
      Environment::setTimeLimit(240);
      // Rebuild newest nodes first so that recent content becomes available
      // quickly.
      $nids = $node_storage->getQuery()
        ->sort('nid', 'DESC')
        ->accessCheck(FALSE)
        ->execute();
      foreach ($nids as $nid) {
        $node_storage->resetCache([
          $nid,
        ]);
        $node = $node_storage->load($nid);
        // To preserve database integrity, only write grants if the node
        // loads successfully.
        if ($node instanceof NodeInterface) {
          $grants = $access_control_handler->acquireGrants($node);
          $this->grantStorage
            ->write($node, $grants);
        }
      }
    }
  }
  else {
    // Not using any node_access modules. Add the default grant.
    $access_control_handler->writeDefaultGrant();
  }
  if (!isset($batch_builder)) {
    $this->messenger
      ->addStatus($this->t('Content permissions have been rebuilt.'));
    $this->setNeedsRebuild(FALSE);
  }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.