function ConfigEntityUpdater::update

Same name in other branches
  1. 9 core/lib/Drupal/Core/Config/Entity/ConfigEntityUpdater.php \Drupal\Core\Config\Entity\ConfigEntityUpdater::update()
  2. 8.9.x core/lib/Drupal/Core/Config/Entity/ConfigEntityUpdater.php \Drupal\Core\Config\Entity\ConfigEntityUpdater::update()
  3. 11.x core/lib/Drupal/Core/Config/Entity/ConfigEntityUpdater.php \Drupal\Core\Config\Entity\ConfigEntityUpdater::update()

Updates configuration entities as part of a Drupal update.

@api

Parameters

array $sandbox: Stores information for batch updates.

string $entity_type_id: The configuration entity type ID. For example, 'view' or 'vocabulary'. The calling code should ensure that the entity type exists beforehand (i.e., by checking that the entity type is defined or that the module that provides it is installed).

callable $callback: (optional) A callback to determine if a configuration entity should be saved. The callback will be passed each entity of the provided type that exists. The callback should not save an entity itself. Return TRUE to save an entity. The callback can make changes to an entity. Note that all changes should comply with schema as an entity's data will not be validated against schema on save to avoid unexpected errors. If a callback is not provided, the default behavior is to update the dependencies if required.

bool $continue_on_error: Set to TRUE to continue updating if an error has occurred.

Return value

\Drupal\Core\StringTranslation\TranslatableMarkup|null An error message if $continue_on_error is set to TRUE and an error has occurred.

Throws

\InvalidArgumentException Thrown when the provided entity type ID is not a configuration entity type.

\RuntimeException Thrown when used twice in the same update function for different entity types. This method should only be called once per update function.

See also

hook_post_update_NAME()

File

core/lib/Drupal/Core/Config/Entity/ConfigEntityUpdater.php, line 109

Class

ConfigEntityUpdater
A utility class to make updating configuration entities simple.

Namespace

Drupal\Core\Config\Entity

Code

public function update(array &$sandbox, $entity_type_id, ?callable $callback = NULL, bool $continue_on_error = FALSE) {
    $storage = $this->entityTypeManager
        ->getStorage($entity_type_id);
    if (isset($sandbox[self::SANDBOX_KEY]) && $sandbox[self::SANDBOX_KEY]['entity_type'] !== $entity_type_id) {
        throw new \RuntimeException('Updating multiple entity types in the same update function is not supported');
    }
    if (!isset($sandbox[self::SANDBOX_KEY])) {
        $entity_type = $this->entityTypeManager
            ->getDefinition($entity_type_id);
        if (!$entity_type instanceof ConfigEntityTypeInterface) {
            throw new \InvalidArgumentException("The provided entity type ID '{$entity_type_id}' is not a configuration entity type");
        }
        $sandbox[self::SANDBOX_KEY]['entity_type'] = $entity_type_id;
        $sandbox[self::SANDBOX_KEY]['entities'] = $storage->getQuery()
            ->accessCheck(FALSE)
            ->execute();
        $sandbox[self::SANDBOX_KEY]['count'] = count($sandbox[self::SANDBOX_KEY]['entities']);
        $sandbox[self::SANDBOX_KEY]['failed_entity_ids'] = [];
    }
    // The default behavior is to fix dependencies.
    if ($callback === NULL) {
        $callback = function ($entity) {
            
            /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $entity */
            $original_dependencies = $entity->getDependencies();
            return $original_dependencies !== $entity->calculateDependencies()
                ->getDependencies();
        };
    }
    
    /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $entity */
    $entities = $storage->loadMultiple(array_splice($sandbox[self::SANDBOX_KEY]['entities'], 0, $this->batchSize));
    foreach ($entities as $entity) {
        try {
            if ($continue_on_error) {
                // If we're continuing on error silence errors from notices that
                // missing indexes.
                // @todo consider change this to an error handler that converts such
                //   notices to exceptions in https://www.drupal.org/node/3309886
                @$this->doOne($entity, $callback);
            }
            else {
                $this->doOne($entity, $callback);
            }
        } catch (\Throwable $throwable) {
            if (!$continue_on_error) {
                throw $throwable;
            }
            $context['%view'] = $entity->id();
            $context['%entity_type'] = $entity_type_id;
            $context += Error::decodeException($throwable);
            \Drupal::logger('update')->error('Unable to update %entity_type %view due to error @message %function (line %line of %file). <pre>@backtrace_string</pre>', $context);
            $sandbox[self::SANDBOX_KEY]['failed_entity_ids'][] = $entity->id();
        }
    }
    $sandbox['#finished'] = empty($sandbox[self::SANDBOX_KEY]['entities']) ? 1 : ($sandbox[self::SANDBOX_KEY]['count'] - count($sandbox[self::SANDBOX_KEY]['entities'])) / $sandbox[self::SANDBOX_KEY]['count'];
    if (!empty($sandbox[self::SANDBOX_KEY]['failed_entity_ids'])) {
        $entity_type = $this->entityTypeManager
            ->getDefinition($entity_type_id);
        if (\Drupal::moduleHandler()->moduleExists('dblog')) {
            return new TranslatableMarkup('Updates failed for the entity type %entity_type, for %entity_ids. <a href=":url">Check the logs</a>.', [
                '%entity_type' => $entity_type->getLabel(),
                '%entity_ids' => implode(', ', $sandbox[self::SANDBOX_KEY]['failed_entity_ids']),
                ':url' => Url::fromRoute('dblog.overview')->toString(),
            ]);
        }
        else {
            return new TranslatableMarkup("Updates failed for the entity type %entity_type, for %entity_ids. Check the logs.", [
                '%entity_type' => $entity_type->getLabel(),
                '%entity_ids' => implode(', ', $sandbox[self::SANDBOX_KEY]['failed_entity_ids']),
            ]);
        }
    }
}

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