summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Pott2017-04-18 13:34:08 +0100
committerAlex Pott2017-04-18 13:47:45 +0100
commit8938ab29067a633f5dbb40203e02af377def3eb6 (patch)
tree2a24c3c709f611e5473dd86acd416d987d6495b7
parentdcec8637914897589f9e0c736b71d5169e7ccfc7 (diff)
Issue #2825973 by amateescu, timmillwood, himanshu-dixit, dawehner, Berdir, Wim Leers: Introduce a EditorialContentEntityBase class for revisionable and publishable entity types
-rw-r--r--core/lib/Drupal/Core/Entity/EditorialContentEntityBase.php31
-rw-r--r--core/lib/Drupal/Core/Entity/entity.api.php5
-rw-r--r--core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonAnonTest.php12
-rw-r--r--core/modules/node/src/Entity/Node.php94
-rw-r--r--core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php14
5 files changed, 49 insertions, 107 deletions
diff --git a/core/lib/Drupal/Core/Entity/EditorialContentEntityBase.php b/core/lib/Drupal/Core/Entity/EditorialContentEntityBase.php
new file mode 100644
index 0000000..ff6abcd
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/EditorialContentEntityBase.php
@@ -0,0 +1,31 @@
+<?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;
+ }
+
+}
diff --git a/core/lib/Drupal/Core/Entity/entity.api.php b/core/lib/Drupal/Core/Entity/entity.api.php
index f9f4271..5387c7e 100644
--- a/core/lib/Drupal/Core/Entity/entity.api.php
+++ b/core/lib/Drupal/Core/Entity/entity.api.php
@@ -271,6 +271,11 @@ use Drupal\node\Entity\NodeType;
* 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
diff --git a/core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonAnonTest.php b/core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonAnonTest.php
index e92a3d6..d4ed47c 100644
--- a/core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonAnonTest.php
+++ b/core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonAnonTest.php
@@ -59,20 +59,20 @@ class NodeHalJsonAnonTest extends NodeResourceTestBase {
'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 @@ class NodeHalJsonAnonTest extends NodeResourceTestBase {
'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 @@ class NodeHalJsonAnonTest extends NodeResourceTestBase {
'uuid' => [
['value' => $author->uuid()]
],
+ 'lang' => 'en',
],
],
],
diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php
index c11a188..b66628c 100644
--- a/core/modules/node/src/Entity/Node.php
+++ b/core/modules/node/src/Entity/Node.php
@@ -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 @@ use Drupal\user\UserInterface;
* }
* )
*/
-class Node extends ContentEntityBase implements NodeInterface {
-
- use EntityChangedTrait;
- use EntityPublishedTrait;
+class Node extends EditorialContentEntityBase implements NodeInterface {
/**
* Whether the node is being previewed or not.
@@ -286,21 +281,6 @@ class Node extends ContentEntityBase implements NodeInterface {
/**
* {@inheritdoc}
*/
- public function getRevisionCreationTime() {
- return $this->get('revision_timestamp')->value;
- }
-
- /**
- * {@inheritdoc}
- */
- public function setRevisionCreationTime($timestamp) {
- $this->set('revision_timestamp', $timestamp);
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
public function getRevisionAuthor() {
return $this->getRevisionUser();
}
@@ -308,13 +288,6 @@ class Node extends ContentEntityBase implements NodeInterface {
/**
* {@inheritdoc}
*/
- public function getRevisionUser() {
- return $this->get('revision_uid')->entity;
- }
-
- /**
- * {@inheritdoc}
- */
public function setRevisionAuthorId($uid) {
$this->setRevisionUserId($uid);
return $this;
@@ -323,47 +296,8 @@ class Node extends ContentEntityBase implements NodeInterface {
/**
* {@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 @@ class Node extends ContentEntityBase implements NodeInterface {
])
->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.'))
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
index 6cd5b6b..80d8a06 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
@@ -900,19 +900,15 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
// 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);