Commit 67c7387f authored by alexpott's avatar alexpott

Issue #2789315 by amateescu, timmillwood, claudiu.cristea, sandervd,...

Issue #2789315 by amateescu, timmillwood, claudiu.cristea, sandervd, GroovyCarrot, catch, Wim Leers, Berdir, pfrenssen, twistor, xjm: Create EntityPublishedInterface and use for Node and Comment
parent 740ccca3
<?php
namespace Drupal\Core\Entity;
/**
* Provides an interface for access to an entity's published state.
*/
interface EntityPublishedInterface {
/**
* Returns whether or not the entity is published.
*
* @return bool
* TRUE if the entity is published, FALSE otherwise.
*/
public function isPublished();
/**
* Sets the entity as published.
*
* @param bool|null $published
* (optional and deprecated) TRUE to set this entity to published, FALSE to
* set it to unpublished. Defaults to NULL. This parameter is deprecated in
* Drupal 8.3.0 and will be removed before Drupal 9.0.0. Use this method,
* without any parameter, to set the entity as published and
* setUnpublished() to set the entity as unpublished.
*
* @return $this
*
* @see \Drupal\Core\Entity\EntityPublishedInterface::setUnpublished()
*/
public function setPublished($published = NULL);
/**
* Sets the entity as unpublished.
*
* @return $this
*/
public function setUnpublished();
}
......@@ -2,6 +2,7 @@
namespace Drupal\Core\Entity;
use Drupal\Core\Entity\Exception\UnsupportedEntityTypeDefinitionException;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\StringTranslation\TranslatableMarkup;
......@@ -17,11 +18,21 @@ trait EntityPublishedTrait {
* The entity type to add the publishing status field to.
*
* @return \Drupal\Core\Field\BaseFieldDefinition[]
* Array of base field definitions.
* An array of base field definitions.
*
* @throws \Drupal\Core\Entity\Exception\UnsupportedEntityTypeDefinitionException
* Thrown when the entity type does not implement EntityPublishedInterface
* or if it does not have a "published" entity key.
*/
public static function publishedBaseFieldDefinitions(EntityTypeInterface $entity_type) {
$key = $entity_type->hasKey('status') ? $entity_type->getKey('status') : 'status';
return [$key => BaseFieldDefinition::create('boolean')
if (!is_subclass_of($entity_type->getClass(), EntityPublishedInterface::class)) {
throw new UnsupportedEntityTypeDefinitionException('The entity type ' . $entity_type->id() . ' does not implement \Drupal\Core\Entity\EntityPublishedInterface.');
}
if (!$entity_type->hasKey('published')) {
throw new UnsupportedEntityTypeDefinitionException('The entity type ' . $entity_type->id() . ' does not have a "published" entity key.');
}
return [$entity_type->getKey('published') => BaseFieldDefinition::create('boolean')
->setLabel(new TranslatableMarkup('Publishing status'))
->setDescription(new TranslatableMarkup('A boolean indicating the published state.'))
->setRevisionable(TRUE)
......@@ -30,31 +41,37 @@ public static function publishedBaseFieldDefinitions(EntityTypeInterface $entity
}
/**
* Returns the published status of the entity.
*
* @return bool
* The published status of the entity.
* {@inheritdoc}
*/
public function isPublished() {
$status = $this->getEntityKey('status');
return (bool) (isset($status) ? $status : $this->get('status')->value);
$key = $this->getEntityType()->getKey('published');
return (bool) $this->get($key)->value;
}
/**
* Sets the entity as published or not published.
*
* @param bool $published
* A boolean value denoting the published status.
*
* @return \Drupal\Core\Entity\ContentEntityInterface $this
* The Content Entity object.
* {@inheritdoc}
*/
public function setPublished($published = NULL) {
if ($published !== NULL) {
@trigger_error('The $published parameter is deprecated since version 8.3.x and will be removed in 9.0.0.', E_USER_DEPRECATED);
$value = (bool) $published;
}
else {
$value = TRUE;
}
$key = $this->getEntityType()->getKey('published');
$this->set($key, $value);
return $this;
}
/**
* {@inheritdoc}
*/
public function setPublished($published) {
/** @var \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type */
$key = $this->getEntityType()->getKey('status') ?: 'status';
// @todo: Replace values with constants from EntityPublishedInterface or
// similar when introduced. https://www.drupal.org/node/2811667
$this->set($key, $published ? 1 : 0);
public function setUnpublished() {
$key = $this->getEntityType()->getKey('published');
$this->set($key, FALSE);
return $this;
}
......
<?php
namespace Drupal\Core\Entity\Exception;
/**
* Defines an exception thrown when an entity type definition is invalid.
*/
class UnsupportedEntityTypeDefinitionException extends \Exception { }
......@@ -193,6 +193,18 @@ function comment_update_8300() {
\Drupal::service('entity.definition_update_manager')->updateFieldStorageDefinition($field_definitions['status']);
}
/**
* Set the 'published' entity key.
*/
function comment_update_8301() {
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
$entity_type = $definition_update_manager->getEntityType('comment');
$keys = $entity_type->getKeys();
$keys['published'] = 'status';
$entity_type->set('entity_keys', $keys);
$definition_update_manager->updateEntityType($entity_type);
}
/**
* @} End of "addtogroup updates-8.3.x".
*/
......@@ -3,13 +3,14 @@
namespace Drupal\comment;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\user\EntityOwnerInterface;
use Drupal\Core\Entity\EntityChangedInterface;
/**
* Provides an interface defining a comment entity.
*/
interface CommentInterface extends ContentEntityInterface, EntityChangedInterface, EntityOwnerInterface {
interface CommentInterface extends ContentEntityInterface, EntityChangedInterface, EntityOwnerInterface, EntityPublishedInterface {
/**
* Comment is awaiting approval.
......@@ -191,32 +192,16 @@ public function getCreatedTime();
*/
public function setCreatedTime($created);
/**
* Checks if the comment is published.
*
* @return bool
* TRUE if the comment is published.
*/
public function isPublished();
/**
* Returns the comment's status.
*
* @return int
* One of CommentInterface::PUBLISHED or CommentInterface::NOT_PUBLISHED
*/
public function getStatus();
/**
* Sets the published status of the comment entity.
*
* @param bool $status
* Set to TRUE to publish the comment, FALSE to unpublish.
*
* @return \Drupal\comment\CommentInterface
* The class instance that this method is called on.
* @deprecated in Drupal 8.3.0, will be removed before Drupal 9.0.0. Use
* \Drupal\Core\Entity\EntityPublishedInterface::isPublished() instead.
*/
public function setPublished($status);
public function getStatus();
/**
* Returns the alphadecimal representation of the comment's place in a thread.
......
......@@ -50,7 +50,8 @@
* "bundle" = "comment_type",
* "label" = "subject",
* "langcode" = "langcode",
* "uuid" = "uuid"
* "uuid" = "uuid",
* "published" = "status",
* },
* links = {
* "canonical" = "/comment/{comment}",
......@@ -81,8 +82,12 @@ public function preSave(EntityStorageInterface $storage) {
parent::preSave($storage);
if (is_null($this->get('status')->value)) {
$published = \Drupal::currentUser()->hasPermission('skip comment approval') ? CommentInterface::PUBLISHED : CommentInterface::NOT_PUBLISHED;
$this->setPublished($published);
if (\Drupal::currentUser()->hasPermission('skip comment approval')) {
$this->setPublished();
}
else {
$this->setUnpublished();
}
}
if ($this->isNew()) {
// Add the comment to database. This next section builds the thread field.
......
......@@ -50,4 +50,22 @@ public function testCommentUpdate8101() {
$this->assertIdentical($config->get('content.comment_forum.settings.view_mode'), 'default');
}
/**
* Tests that the comment entity type has a 'published' entity key.
*
* @see comment_update_8301()
*/
public function testPublishedEntityKey() {
// Check that the 'published' entity key does not exist prior to the update.
$entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('comment');
$this->assertFalse($entity_type->getKey('published'));
// Run updates.
$this->runUpdates();
// Check that the entity key exists and it has the correct value.
$entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('comment');
$this->assertEqual('status', $entity_type->getKey('published'));
}
}
......@@ -221,6 +221,11 @@ function node_update_8003() {
}
}
/**
* @addtogroup updates-8.3.x
* @{
*/
/**
* Change {node_access}.fallback from an int to a tinyint as it is a boolean.
*/
......@@ -234,3 +239,19 @@ function node_update_8300() {
'size' => 'tiny',
]);
}
/**
* Set the 'published' entity key.
*/
function node_update_8301() {
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
$entity_type = $definition_update_manager->getEntityType('node');
$keys = $entity_type->getKeys();
$keys['published'] = 'status';
$entity_type->set('entity_keys', $keys);
$definition_update_manager->updateEntityType($entity_type);
}
/**
* @} End of "addtogroup updates-8.3.x".
*/
......@@ -56,6 +56,7 @@
* "langcode" = "langcode",
* "uuid" = "uuid",
* "status" = "status",
* "published" = "status",
* "uid" = "uid",
* },
* bundle_entity_type = "node_type",
......
......@@ -2,6 +2,7 @@
namespace Drupal\node;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\RevisionLogInterface;
use Drupal\user\EntityOwnerInterface;
use Drupal\Core\Entity\EntityChangedInterface;
......@@ -10,7 +11,7 @@
/**
* Provides an interface defining a node entity.
*/
interface NodeInterface extends ContentEntityInterface, EntityChangedInterface, EntityOwnerInterface, RevisionLogInterface {
interface NodeInterface extends ContentEntityInterface, EntityChangedInterface, EntityOwnerInterface, RevisionLogInterface, EntityPublishedInterface {
/**
* Gets the node type.
......@@ -96,27 +97,6 @@ public function isSticky();
*/
public function setSticky($sticky);
/**
* Returns the node published status indicator.
*
* Unpublished nodes are only visible to their authors and to administrators.
*
* @return bool
* TRUE if the node is published.
*/
public function isPublished();
/**
* Sets the published status of a node..
*
* @param bool $published
* TRUE to set this node to published, FALSE to set it to unpublished.
*
* @return \Drupal\node\NodeInterface
* The called node entity.
*/
public function setPublished($published);
/**
* Gets the node revision creation timestamp.
*
......
<?php
namespace Drupal\node\Tests\Update;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests that node settings are properly updated during database updates.
*
* @group node
*/
class NodeUpdateTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8-rc1.bare.standard.php.gz',
];
}
/**
* Tests that the node entity type has a 'published' entity key.
*
* @see node_update_8301()
*/
public function testPublishedEntityKey() {
// Check that the 'published' entity key does not exist prior to the update.
$entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('node');
$this->assertFalse($entity_type->getKey('published'));
// Run updates.
$this->runUpdates();
// Check that the entity key exists and it has the correct value.
$entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('node');
$this->assertEqual('status', $entity_type->getKey('published'));
}
}
......@@ -213,6 +213,13 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
// them. However, rather than throwing an error, we just ignore them as
// long as their specified values match their current values.
if (in_array($field_name, $entity_keys, TRUE)) {
// @todo Work around the wrong assumption that entity keys need special
// treatment, when only read-only fields need it.
// This will be fixed in https://www.drupal.org/node/2824851.
if ($entity->getEntityTypeId() == 'comment' && $field_name == 'status' && !$original_entity->get($field_name)->access('edit')) {
throw new AccessDeniedHttpException("Access denied on updating field '$field_name'.");
}
// Unchanged values for entity keys don't need access checking.
if ($original_entity->get($field_name)->getValue() === $entity->get($field_name)->getValue()) {
continue;
......
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