/** * {@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')); }
protected function checkAccess(ContentEntityInterface $entity, AccountInterface $account, $operation = 'view') { $entity_type = $entity->getEntityType(); $entity_type_id = $entity->getEntityTypeId(); $entity_access = $this->entityTypeManager->getAccessControlHandler($entity_type_id); /** @var \Drupal\Core\Entity\EntityStorageInterface $entity_storage */ $entity_storage = $this->entityTypeManager->getStorage($entity_type_id); $map = ['view' => "view all {$entity_type_id} revisions", 'update' => "revert all {$entity_type_id} revisions", 'delete' => "delete all {$entity_type_id} revisions"]; $bundle = $entity->bundle(); $type_map = ['view' => "view {$entity_type_id} {$bundle} revisions", 'update' => "revert {$entity_type_id} {$bundle} revisions", 'delete' => "delete {$entity_type_id} {$bundle} revisions"]; if (!$entity || !isset($map[$operation]) || !isset($type_map[$operation])) { // If there was no node to check against, or the $op was not one of the // supported ones, we return access denied. return FALSE; } // Statically cache access by revision ID, language code, user account ID, // and operation. $langcode = $entity->language()->getId(); $cid = $entity->getRevisionId() . ':' . $langcode . ':' . $account->id() . ':' . $operation; if (!isset($this->accessCache[$cid])) { // Perform basic permission checks first. if (!$account->hasPermission($map[$operation]) && !$account->hasPermission($type_map[$operation]) && !$account->hasPermission('administer nodes')) { $this->accessCache[$cid] = FALSE; return FALSE; } if (($admin_permission = $entity_type->getAdminPermission()) && $account->hasPermission($admin_permission)) { $this->accessCache[$cid] = TRUE; } else { // First check the access to the default revision and finally, if the // node passed in is not the default revision then access to that, too. $this->accessCache[$cid] = $entity_access->access($entity_storage->load($entity->id()), $operation, $account) && ($entity->isDefaultRevision() || $entity_access->access($entity, $operation, $account)); } } return $this->accessCache[$cid]; }
protected function checkAccess(ContentEntityInterface $entity, AccountInterface $account, $operation = 'view') { $entity_type_id = $entity->getEntityTypeId(); $entity_access = $this->entityManager->getAccessControlHandler($entity_type_id); /** @var \Drupal\content_entity_base\Entity\Storage\RevisionableStorageInterface|\Drupal\Core\Entity\EntityStorageInterface $entity_storage */ $entity_storage = $this->entityManager->getStorage($entity_type_id); if (!$entity_storage instanceof RevisionableStorageInterface) { throw new \InvalidArgumentException('The entity storage has to implement \\Drupal\\content_entity_base\\Entity\\Storage\\RevisionableStorageInterface'); } $map = ['view' => "view all {$entity_type_id} revisions", 'update' => "revert all {$entity_type_id} revisions", 'delete' => "delete all {$entity_type_id} revisions"]; $bundle = $entity->bundle(); $type_map = ['view' => "view {$entity_type_id} {$bundle} revisions", 'update' => "revert {$entity_type_id} {$bundle} revisions", 'delete' => "delete {$entity_type_id} {$bundle} revisions"]; if (!$entity || !isset($map[$operation]) || !isset($type_map[$operation])) { // If there was no node to check against, or the $op was not one of the // supported ones, we return access denied. return FALSE; } // Statically cache access by revision ID, language code, user account ID, // and operation. $langcode = $entity->language()->getId(); $cid = $entity->getRevisionId() . ':' . $langcode . ':' . $account->id() . ':' . $operation; if (!isset($this->access[$cid])) { // Perform basic permission checks first. if (!$account->hasPermission($map[$operation]) && !$account->hasPermission($type_map[$operation]) && !$account->hasPermission('administer nodes')) { $this->access[$cid] = FALSE; return FALSE; } // There should be at least two revisions. If the vid of the given node // and the vid of the default revision differ, then we already have two // different revisions so there is no need for a separate database check. // Also, if you try to revert to or delete the default revision, that's // not good. if ($entity->isDefaultRevision() && ($entity_storage->countDefaultLanguageRevisions($entity) == 1 || $operation == 'update' || $operation == 'delete')) { $this->access[$cid] = FALSE; } elseif ($account->hasPermission('administer ' . $entity_type_id)) { $this->access[$cid] = TRUE; } else { // First check the access to the default revision and finally, if the // node passed in is not the default revision then access to that, too. $this->access[$cid] = $entity_access->access($entity_storage->load($entity->id()), $operation, $account) && ($entity->isDefaultRevision() || $entity_access->access($entity, $operation, $account)); } } return $this->access[$cid]; }
/** * {@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} */ protected function purgeFieldItems(ContentEntityInterface $entity, FieldDefinitionInterface $field_definition) { $storage_definition = $field_definition->getFieldStorageDefinition(); $is_deleted = $this->storageDefinitionIsDeleted($storage_definition); $table_mapping = $this->getTableMapping(); $table_name = $table_mapping->getDedicatedDataTableName($storage_definition, $is_deleted); $revision_name = $table_mapping->getDedicatedRevisionTableName($storage_definition, $is_deleted); $revision_id = $this->entityType->isRevisionable() ? $entity->getRevisionId() : $entity->id(); $this->database->delete($table_name)->condition('revision_id', $revision_id)->execute(); if ($this->entityType->isRevisionable()) { $this->database->delete($revision_name)->condition('revision_id', $revision_id)->execute(); } }
/** * {@inheritdoc} */ protected function save(ContentEntityInterface $entity, array $old_destination_id_values = array()) { $entity->save(); return array($entity->getRevisionId()); }
/** * {@inheritdoc} */ public function isLatestRevision(ContentEntityInterface $entity) { return $entity->getRevisionId() == $this->getLatestRevisionId($entity->getEntityTypeId(), $entity->id()); }
/** * 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); }