/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $this->entityManager->getStorage($this->entityRevision->getEntityTypeId())->deleteRevision($this->entityRevision->getRevisionId()); $this->logger('content')->notice('@type: deleted %title revision %revision.', ['@type' => $this->entityRevision->bundle(), '%title' => $this->entityRevision->label(), '%revision' => $this->entityRevision->getRevisionId()]); drupal_set_message(t('@type %title has been deleted', ['@type' => $this->entityRevision->{$this->entityRevision->getEntityType()->getKey('bundle')}->entity->label(), '%title' => $this->entityRevision->label()])); $form_state->setRedirectUrl($this->entityRevision->urlInfo('version-history')); }
/** * {@inheritdoc} */ public function getCacheTags() { // @todo write a test for this. $tags = parent::getCacheTags(); // Tab changes if node or node-type is modified. $tags = array_merge($tags, $this->entity->getCacheTags()); $tags[] = $this->entity->getEntityType()->getBundleEntityType() . ':' . $this->entity->bundle(); return $tags; }
/** * Populates target values with the source values. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity being translated. * @param \Drupal\Core\Language\LanguageInterface $source * The language to be used as source. * @param \Drupal\Core\Language\LanguageInterface $target * The language to be used as target. */ public function prepareTranslation(ContentEntityInterface $entity, LanguageInterface $source, LanguageInterface $target) { /* @var \Drupal\Core\Entity\ContentEntityInterface $source_translation */ $source_translation = $entity->getTranslation($source->getId()); $target_translation = $entity->addTranslation($target->getId(), $source_translation->toArray()); // Make sure we do not inherit the affected status from the source values. if ($entity->getEntityType()->isRevisionable()) { $target_translation->setRevisionTranslationAffected(NULL); } /** @var \Drupal\user\UserInterface $user */ $user = $this->entityManager()->getStorage('user')->load($this->currentUser()->id()); $metadata = $this->manager->getTranslationMetadata($target_translation); // Update the translation author to current user, as well the translation // creation time. $metadata->setAuthor($user); $metadata->setCreatedTime(REQUEST_TIME); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { // The revision timestamp will be updated when the revision is saved. Keep // the original one for the confirmation message. $this->entityRevision->setNewRevision(); $this->entityRevision->isDefaultRevision(TRUE); if ($this->entityRevision instanceof EntityRevisionLogInterface) { if ($this->entityRevision instanceof TimestampedRevisionInterface) { $original_revision_timestamp = $this->entityRevision->getRevisionCreationTime(); $this->entityRevision->revision_log = t('Copy of the revision from %date.', ['%date' => $this->dateFormatter->format($original_revision_timestamp)]); } else { $this->entityRevision->revision_log = t('Copy of the revision'); } } $this->entityRevision->save(); $this->logger('content')->notice('@type: reverted %title revision %revision.', ['@type' => $this->entityRevision->bundle(), '%title' => $this->entityRevision->label(), '%revision' => $this->entityRevision->getRevisionId()]); drupal_set_message(t('@type %title has been reverted to the revision', ['@type' => $this->entityRevision->{$this->entityRevision->getEntityType()->getKey('bundle')}->entity->label(), '%title' => $this->entityRevision->label()])); $form_state->setRedirectUrl($this->entityRevision->urlInfo('version-history')); }
/** * {@inheritdoc} */ public function getValidTransitions(ContentEntityInterface $entity, AccountInterface $user) { $bundle = $this->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle()); /** @var \Drupal\content_moderation\Entity\ModerationState $current_state */ $current_state = $entity->moderation_state->entity; $current_state_id = $current_state ? $current_state->id() : $bundle->getThirdPartySetting('content_moderation', 'default_moderation_state'); // Determine the states that are legal on this bundle. $legal_bundle_states = $bundle->getThirdPartySetting('content_moderation', 'allowed_moderation_states', []); // Legal transitions include those that are possible from the current state, // filtered by those whose target is legal on this bundle and that the // user has access to execute. $transitions = array_filter($this->getTransitionsFrom($current_state_id), function (ModerationStateTransition $transition) use($legal_bundle_states, $user) { return in_array($transition->getToState(), $legal_bundle_states, TRUE) && $user->hasPermission('use ' . $transition->id() . ' transition'); }); return $transitions; }
/** * Counts the number of revisions in the default language. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity. * @param \Drupal\Core\Entity\EntityStorageInterface $entity_storage * The entity storage. * * @return int * The number of revisions in the default language. */ protected function countDefaultLanguageRevisions(ContentEntityInterface $entity, EntityStorageInterface $entity_storage) { $entity_type = $entity->getEntityType(); $count = $entity_storage->getQuery()->allRevisions()->condition($entity_type->getKey('id'), $entity->id())->condition($entity_type->getKey('default_langcode'), 1)->count()->execute(); return $count; }
/** * Determines the default moderation state on load for an entity. * * This method is only applicable when an entity is loaded that has * no moderation state on it, but should. In those cases, failing to set * one may result in NULL references elsewhere when other code tries to check * the moderation state of the entity. * * The amount of indirection here makes performance a concern, but * given how Entity API works I don't know how else to do it. * This reliably gets us *A* valid state. However, that state may be * not the ideal one. Suggestions on how to better select the default * state here are welcome. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity for which we want a default state. * * @return string * The default state for the given entity. */ protected function getDefaultLoadStateId(ContentEntityInterface $entity) { return $this->moderationInfo->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle())->getThirdPartySetting('content_moderation', 'default_moderation_state'); }
/** * Check to see if Updates attached to an entity has changed. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * @param \Drupal\scheduled_updates\Plugin\EntityMonitorUpdateRunnerInterface $runner * * @return bool */ protected function entityUpdatesChanged(ContentEntityInterface $entity, EntityMonitorUpdateRunnerInterface $runner) { // We can't use $entity->original because it is not always the last revision. /** @var ContentEntityInterface $previous */ if ($entity->getEntityType()->isRevisionable()) { $previous = $this->updateUtils->getPreviousRevision($entity); } else { $previous = isset($entity->original)? $entity->original: NULL; } if ($previous) { $field_ids = $runner->getReferencingFieldIds(); foreach ($field_ids as $field_id) { $previous_update_ids = $runner->getEntityReferenceTargetIds($previous, $field_id, TRUE); $updated_update_ids = $runner->getEntityReferenceTargetIds($entity, $field_id, TRUE); if ($previous_update_ids != $updated_update_ids) { return TRUE; } } } return FALSE; }
/** * Gets a list of states a user may transition an entity to. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity to be transitioned. * @param \Drupal\Core\Session\AccountInterface $user * The account that wants to perform a transition. * * @return ModerationState[] * Returns an array of States to which the specified user may transition the * entity. */ public function getValidTransitionTargets(ContentEntityInterface $entity, AccountInterface $user) { $bundle = $this->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle()); $states_for_bundle = $bundle->getThirdPartySetting('workbench_moderation', 'allowed_moderation_states', []); /** @var ModerationState $state */ $state = $entity->moderation_state->entity; $current_state_id = $state->id(); $all_transitions = $this->getPossibleTransitions(); $destinations = $all_transitions[$current_state_id]; $destinations = array_intersect($states_for_bundle, $destinations); $permitted_destinations = array_filter($destinations, function ($state_name) use($current_state_id, $user) { return $this->userMayTransition($current_state_id, $state_name, $user); }); return $this->entityTypeManager->getStorage('moderation_state')->loadMultiple($permitted_destinations); }
/** * Loads all revision IDs of an entity sorted by revision ID descending. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity. * * @return mixed[] */ protected function revisionIds(ContentEntityInterface $entity) { $entity_type = $entity->getEntityType(); $result = $this->entityTypeManager()->getStorage($entity_type->id())->getQuery()->allRevisions()->condition($entity_type->getKey('id'), $entity->id())->sort($entity_type->getKey('revision'), 'DESC')->execute(); return array_keys($result); }
/** * Get the directly previous revision. * * $entity->original will not ALWAYS be the previous revision. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * * @return \Drupal\Core\Entity\EntityInterface|null */ public function getPreviousRevision(ContentEntityInterface $entity) { $storage = $this->entityTypeManager->getStorage($entity->getEntityTypeId()); $query = $storage->getQuery(); $type = $entity->getEntityType(); $query->allRevisions() ->condition($type->getKey('id'), $entity->id()) ->condition($type->getKey('revision'), $entity->getRevisionId(), '<') ->sort($type->getKey('revision'), 'DESC') ->pager(1); $revision_ids = $query->execute(); if ($revision_ids) { $revision_id = array_keys($revision_ids)[0]; return $storage->loadRevision($revision_id); } return NULL; }
/** * Get all previous revisions that have updates of the attached type. * * This function would be easier and more performant if this core issue with * Entity Query was fixed: https://www.drupal.org/node/2649268 Without this * fix can't filter query on type of update and whether they are active. So * therefore all previous revisions have to be loaded. * * @todo Help get that core issue fixed or rewrite this function query table * fields directly. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * * @return \Drupal\Core\Entity\ContentEntityInterface[] */ protected function getPreviousRevisionsWithUpdates(ContentEntityInterface $entity) { /** @var ContentEntityInterface[] $revisions */ $revisions = []; $type = $entity->getEntityType(); $query = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->getQuery(); $query->allRevisions()->condition($type->getKey('id'), $entity->id())->condition($type->getKey('revision'), $entity->getRevisionId(), '<')->sort($type->getKey('revision'), 'DESC'); if ($revision_ids = $query->execute()) { $revision_ids = array_keys($revision_ids); $storage = $this->entityTypeManager->getStorage($entity->getEntityTypeId()); foreach ($revision_ids as $revision_id) { /** @var ContentEntityInterface $revision */ $revision = $storage->loadRevision($revision_id); if ($update_ids = $this->getUpdateIdsOnEntity($revision)) { $revisions[$revision_id] = $revision; } } } return $revisions; }
/** * @param \Drupal\Core\Entity\ContentEntityInterface $entity * @return array */ protected function buildRecord(ContentEntityInterface $entity) { return array('entity_type_id' => $entity->getEntityTypeId(), 'entity_id' => $entity->id(), 'entity_uuid' => $entity->uuid(), 'revision_id' => $entity->getRevisionId(), 'deleted' => $entity->_deleted->value, 'rev' => $entity->_rev->value, 'seq' => $this->multiversionManager->newSequenceId(), 'local' => (bool) $entity->getEntityType()->get('local'), 'is_stub' => (bool) $entity->_rev->is_stub); }