Commit 8938ab29 authored by alexpott's avatar alexpott

Issue #2825973 by amateescu, timmillwood, himanshu-dixit, dawehner, Berdir,...

Issue #2825973 by amateescu, timmillwood, himanshu-dixit, dawehner, Berdir, Wim Leers: Introduce a EditorialContentEntityBase class for revisionable and publishable entity types
parent dcec8637
<?php
namespace Drupal\Core\Entity;
/**
* Provides a base entity class with extended revision and publishing support.
*
* @ingroup entity_api
*/
abstract class EditorialContentEntityBase extends ContentEntityBase implements EntityChangedInterface, EntityPublishedInterface, RevisionLogInterface {
use EntityChangedTrait;
use EntityPublishedTrait;
use RevisionLogEntityTrait;
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);
// Add the revision metadata fields.
$fields += static::revisionLogBaseFieldDefinitions($entity_type);
// Add the published field.
$fields += static::publishedBaseFieldDefinitions($entity_type);
return $fields;
}
}
......@@ -271,6 +271,11 @@
* either \Drupal\Core\Config\Entity\ConfigEntityBase or
* \Drupal\Core\Entity\ContentEntityBase, with annotation for
* \@ConfigEntityType or \@ContentEntityType in its documentation block.
* If you are defining a content entity type, it is recommended to extend the
* \Drupal\Core\Entity\EditorialContentEntityBase base class in order to get
* out-of-the-box support for Entity API's revisioning and publishing
* features, which will allow your entity type to be used with Drupal's
* editorial workflow provided by the Content Moderation module.
* - The 'id' annotation gives the entity type ID, and the 'label' annotation
* gives the human-readable name of the entity type. If you are defining a
* content entity type that uses bundles, the 'bundle_label' annotation gives
......
......@@ -59,20 +59,20 @@ protected function getExpectedNormalizedEntity() {
'type' => [
'href' => $this->baseUrl . '/rest/type/node/camelids',
],
$this->baseUrl . '/rest/relation/node/camelids/uid' => [
$this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [
[
'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json',
'lang' => 'en',
],
],
$this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [
$this->baseUrl . '/rest/relation/node/camelids/uid' => [
[
'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json',
'lang' => 'en',
],
],
],
'_embedded' => [
$this->baseUrl . '/rest/relation/node/camelids/uid' => [
$this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [
[
'_links' => [
'self' => [
......@@ -85,10 +85,9 @@ protected function getExpectedNormalizedEntity() {
'uuid' => [
['value' => $author->uuid()]
],
'lang' => 'en',
],
],
$this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [
$this->baseUrl . '/rest/relation/node/camelids/uid' => [
[
'_links' => [
'self' => [
......@@ -101,6 +100,7 @@ protected function getExpectedNormalizedEntity() {
'uuid' => [
['value' => $author->uuid()]
],
'lang' => 'en',
],
],
],
......
......@@ -2,9 +2,7 @@
namespace Drupal\node\Entity;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityChangedTrait;
use Drupal\Core\Entity\EntityPublishedTrait;
use Drupal\Core\Entity\EditorialContentEntityBase;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
......@@ -79,10 +77,7 @@
* }
* )
*/
class Node extends ContentEntityBase implements NodeInterface {
use EntityChangedTrait;
use EntityPublishedTrait;
class Node extends EditorialContentEntityBase implements NodeInterface {
/**
* Whether the node is being previewed or not.
......@@ -283,21 +278,6 @@ public function setOwner(UserInterface $account) {
return $this;
}
/**
* {@inheritdoc}
*/
public function getRevisionCreationTime() {
return $this->get('revision_timestamp')->value;
}
/**
* {@inheritdoc}
*/
public function setRevisionCreationTime($timestamp) {
$this->set('revision_timestamp', $timestamp);
return $this;
}
/**
* {@inheritdoc}
*/
......@@ -305,13 +285,6 @@ public function getRevisionAuthor() {
return $this->getRevisionUser();
}
/**
* {@inheritdoc}
*/
public function getRevisionUser() {
return $this->get('revision_uid')->entity;
}
/**
* {@inheritdoc}
*/
......@@ -320,50 +293,11 @@ public function setRevisionAuthorId($uid) {
return $this;
}
/**
* {@inheritdoc}
*/
public function setRevisionUser(UserInterface $user) {
$this->set('revision_uid', $user);
return $this;
}
/**
* {@inheritdoc}
*/
public function getRevisionUserId() {
return $this->get('revision_uid')->entity->id();
}
/**
* {@inheritdoc}
*/
public function setRevisionUserId($user_id) {
$this->set('revision_uid', $user_id);
return $this;
}
/**
* {@inheritdoc}
*/
public function getRevisionLogMessage() {
return $this->get('revision_log')->value;
}
/**
* {@inheritdoc}
*/
public function setRevisionLogMessage($revision_log_message) {
$this->set('revision_log', $revision_log_message);
return $this;
}
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);
$fields += static::publishedBaseFieldDefinitions($entity_type);
$fields['title'] = BaseFieldDefinition::create('string')
->setLabel(t('Title'))
......@@ -455,30 +389,6 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
])
->setDisplayConfigurable('form', TRUE);
$fields['revision_timestamp'] = BaseFieldDefinition::create('created')
->setLabel(t('Revision timestamp'))
->setDescription(t('The time that the current revision was created.'))
->setRevisionable(TRUE);
$fields['revision_uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Revision user ID'))
->setDescription(t('The user ID of the author of the current revision.'))
->setSetting('target_type', 'user')
->setRevisionable(TRUE);
$fields['revision_log'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Revision log message'))
->setDescription(t('Briefly describe the changes you have made.'))
->setRevisionable(TRUE)
->setDefaultValue('')
->setDisplayOptions('form', [
'type' => 'string_textarea',
'weight' => 25,
'settings' => [
'rows' => 4,
],
]);
$fields['revision_translation_affected'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Revision translation affected'))
->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
......
......@@ -900,19 +900,15 @@ public function testPatch() {
// DX: 403 when sending PATCH request with read-only fields.
// First send all fields (the "maximum normalization"). Assert the expected
// error message for the first PATCH-protected field. Remove that field from
// the normalization, send another request, assert the next PATCH-protected
// field error message. And so on.
$max_normalization = $this->getNormalizedPatchEntity() + $this->serializer->normalize($this->entity, static::$format);
for ($i = 0; $i < count(static::$patchProtectedFieldNames); $i++) {
$max_normalization = $this->removeFieldsFromNormalization($max_normalization, array_slice(static::$patchProtectedFieldNames, 0, $i));
$request_options[RequestOptions::BODY] = $this->serializer->serialize($max_normalization, static::$format);
foreach (static::$patchProtectedFieldNames as $field_name) {
$normalization = $this->getNormalizedPatchEntity() + [$field_name => [['value' => $this->randomString()]]];
$request_options[RequestOptions::BODY] = $this->serializer->serialize($normalization, static::$format);
$response = $this->request('PATCH', $url, $request_options);
$this->assertResourceErrorResponse(403, "Access denied on updating field '" . static::$patchProtectedFieldNames[$i] . "'.", $response);
$this->assertResourceErrorResponse(403, "Access denied on updating field '$field_name'.", $response);
}
// 200 for well-formed request that sends the maximum number of fields.
$max_normalization = $this->getNormalizedPatchEntity() + $this->serializer->normalize($this->entity, static::$format);
$max_normalization = $this->removeFieldsFromNormalization($max_normalization, static::$patchProtectedFieldNames);
$request_options[RequestOptions::BODY] = $this->serializer->serialize($max_normalization, static::$format);
$response = $this->request('PATCH', $url, $request_options);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment