function ContentEntityStorageBase::createRevision

Same name in other branches
  1. 9 core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php \Drupal\Core\Entity\ContentEntityStorageBase::createRevision()
  2. 8.9.x core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php \Drupal\Core\Entity\ContentEntityStorageBase::createRevision()
  3. 10 core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php \Drupal\Core\Entity\ContentEntityStorageBase::createRevision()

Overrides TranslatableRevisionableStorageInterface::createRevision

File

core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php, line 370

Class

ContentEntityStorageBase
Base class for content entity storage handlers.

Namespace

Drupal\Core\Entity

Code

public function createRevision(RevisionableInterface $entity, $default = TRUE, $keep_untranslatable_fields = NULL) {
    
    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
    $new_revision = clone $entity;
    $original_keep_untranslatable_fields = $keep_untranslatable_fields;
    // For translatable entities, create a merged revision of the active
    // translation and the other translations in the default revision. This
    // permits the creation of pending revisions that can always be saved as the
    // new default revision without reverting changes in other languages.
    if (!$entity->isNew() && !$entity->isDefaultRevision() && $entity->isTranslatable() && $this->isAnyRevisionTranslated($entity)) {
        $active_langcode = $entity->language()
            ->getId();
        $skipped_field_names = array_flip($this->getRevisionTranslationMergeSkippedFieldNames());
        // By default we copy untranslatable field values from the default
        // revision, unless they are configured to affect only the default
        // translation. This way we can ensure we always have only one affected
        // translation in pending revisions. This constraint is enforced by
        // EntityUntranslatableFieldsConstraintValidator.
        if (!isset($keep_untranslatable_fields)) {
            $keep_untranslatable_fields = $entity->isDefaultTranslation() && $entity->isDefaultTranslationAffectedOnly();
        }
        
        /** @var \Drupal\Core\Entity\ContentEntityInterface $default_revision */
        $default_revision = $this->load($entity->id());
        $translation_languages = $default_revision->getTranslationLanguages();
        foreach ($translation_languages as $langcode => $language) {
            if ($langcode == $active_langcode) {
                continue;
            }
            $default_revision_translation = $default_revision->getTranslation($langcode);
            $new_revision_translation = $new_revision->hasTranslation($langcode) ? $new_revision->getTranslation($langcode) : $new_revision->addTranslation($langcode);
            
            /** @var \Drupal\Core\Field\FieldItemListInterface[] $sync_items */
            $sync_items = array_diff_key($keep_untranslatable_fields ? $default_revision_translation->getTranslatableFields() : $default_revision_translation->getFields(), $skipped_field_names);
            foreach ($sync_items as $field_name => $items) {
                $new_revision_translation->set($field_name, $items->getValue());
            }
            // Make sure the "revision_translation_affected" flag is recalculated.
            $new_revision_translation->setRevisionTranslationAffected(NULL);
            // No need to copy untranslatable field values more than once.
            $keep_untranslatable_fields = TRUE;
        }
        // Make sure we do not inadvertently recreate removed translations.
        foreach (array_diff_key($new_revision->getTranslationLanguages(), $translation_languages) as $langcode => $language) {
            // Allow a new revision to be created for the active language.
            if ($langcode !== $active_langcode) {
                $new_revision->removeTranslation($langcode);
            }
        }
        // The "original" property is used in various places to detect changes in
        // field values with respect to the stored ones. If the property is not
        // defined, the stored version is loaded explicitly. Since the merged
        // revision generated here is not stored anywhere, we need to populate the
        // "original" property manually, so that changes can be properly detected.
        $new_revision->original = clone $new_revision;
    }
    // Eventually mark the new revision as such.
    $new_revision->setNewRevision();
    $new_revision->isDefaultRevision($default);
    // Actually make sure the current translation is marked as affected, even if
    // there are no explicit changes, to be sure this revision can be related
    // to the correct translation.
    $new_revision->setRevisionTranslationAffected(TRUE);
    // Notify modules about the new revision.
    $arguments = [
        $new_revision,
        $entity,
        $original_keep_untranslatable_fields,
    ];
    $this->moduleHandler()
        ->invokeAll($this->entityTypeId . '_revision_create', $arguments);
    $this->moduleHandler()
        ->invokeAll('entity_revision_create', $arguments);
    return $new_revision;
}

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