diff --git a/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php b/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php index 4270a1fb53..cbeb51a062 100644 --- a/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php +++ b/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php @@ -5,6 +5,7 @@ use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityPublishedInterface; use Drupal\Core\Field\FieldItemList; +use Drupal\Core\TypedData\ComputedItemListTrait; /** * A computed field that provides a content entity's moderation state. @@ -14,6 +15,33 @@ */ class ModerationStateFieldItemList extends FieldItemList { + use ComputedItemListTrait; + + /** + * {@inheritdoc} + */ + protected function computeValue() { + $moderation_state = $this->getModerationStateId(); + // Do not store NULL values in the static cache. + if ($moderation_state) { + // An entity can only have a single moderation state. + $this->list[0] = $this->createItem(0, $moderation_state); + } + } + + /** + * Ensures that values are only computed once. + */ + protected function ensureComputedValue() { + // If the moderation state field is set to an empty value, always recompute + // the state. Empty is not a valid moderation state value, when none is + // preset the default state is used. + if ($this->valueComputed === FALSE || $this->list[0]->isEmpty()) { + $this->computeValue(); + $this->valueComputed = TRUE; + } + } + /** * Gets the moderation state ID linked to a content entity revision. * @@ -86,41 +114,6 @@ protected function loadContentModerationStateRevision(ContentEntityInterface $en /** * {@inheritdoc} */ - public function get($index) { - if ($index !== 0) { - throw new \InvalidArgumentException('An entity can not have multiple moderation states at the same time.'); - } - $this->computeModerationFieldItemList(); - return isset($this->list[$index]) ? $this->list[$index] : NULL; - } - - /** - * {@inheritdoc} - */ - public function getIterator() { - $this->computeModerationFieldItemList(); - return parent::getIterator(); - } - - /** - * Recalculate the moderation field item list. - */ - protected function computeModerationFieldItemList() { - // Compute the value of the moderation state. - $index = 0; - if (!isset($this->list[$index]) || $this->list[$index]->isEmpty()) { - - $moderation_state = $this->getModerationStateId(); - // Do not store NULL values in the static cache. - if ($moderation_state) { - $this->list[$index] = $this->createItem($index, $moderation_state); - } - } - } - - /** - * {@inheritdoc} - */ public function onChange($delta) { $this->updateModeratedEntity($this->list[$delta]->value); @@ -134,6 +127,7 @@ public function setValue($values, $notify = TRUE) { parent::setValue($values, $notify); if (isset($this->list[0])) { + $this->valueComputed = TRUE; $this->updateModeratedEntity($this->list[0]->value); } } diff --git a/core/modules/content_moderation/tests/src/Kernel/EntityStateChangeValidationTest.php b/core/modules/content_moderation/tests/src/Kernel/EntityStateChangeValidationTest.php index 2fefc0148c..6d911bad8a 100644 --- a/core/modules/content_moderation/tests/src/Kernel/EntityStateChangeValidationTest.php +++ b/core/modules/content_moderation/tests/src/Kernel/EntityStateChangeValidationTest.php @@ -181,7 +181,7 @@ public function testInvalidStateMultilingual() { ]); $node->save(); - $node_fr = $node->addTranslation('fr'); + $node_fr = $node->addTranslation('fr', $node->toArray()); $node_fr->setTitle('French Published Node'); $node_fr->save(); $this->assertEquals('published', $node_fr->moderation_state->value); @@ -207,7 +207,7 @@ public function testInvalidStateMultilingual() { $this->assertCount(0, $violations); // From the latest french revision, there should also be no violation. - $node_fr = $node->getTranslation('fr'); + $node_fr = Node::load($node->id())->getTranslation('fr'); $this->assertEquals('published', $node_fr->moderation_state->value); $node_fr->moderation_state = 'archived'; $violations = $node_fr->validate(); diff --git a/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php b/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php index a0d46da428..d011953f10 100644 --- a/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php +++ b/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php @@ -80,6 +80,24 @@ public function testArrayIteration() { } /** + * Test getting the moderation_state with getValue. + */ + public function testGetValue() { + $this->assertEquals([['value' => 'draft']], $this->testNode->moderation_state->getValue()); + } + + /** + * Test setting an empty value on the moderation_state field. + */ + public function testSetEmptyState() { + $this->testNode->moderation_state->value = ''; + $this->assertEquals('draft', $this->testNode->moderation_state->value); + + $this->testNode->moderation_state = ''; + $this->assertEquals('draft', $this->testNode->moderation_state->value); + } + + /** * Tests that moderation state changes also change the related entity state. */ public function testModerationStateChanges() {