From c13f31cd0b25c11fee445545faa17708dbc1dc5d Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Fri, 14 Oct 2016 10:24:21 +0100
Subject: [PATCH] Issue #2817565 by Sam152: Bugs in
 ModerationStateFieldItemList mean it can never be used with a field formatter

---
 .../Field/ModerationStateFieldItemList.php    | 19 ++++-
 .../ModerationStateFieldItemListTest.php      | 78 +++++++++++++++++++
 2 files changed, 95 insertions(+), 2 deletions(-)
 create mode 100644 core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php

diff --git a/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php b/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php
index 27afd30c9691..74e5ef0c7c71 100644
--- a/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php
+++ b/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php
@@ -71,7 +71,24 @@ 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->getModerationState();
       // Do not store NULL values in the static cache.
@@ -79,8 +96,6 @@ public function get($index) {
         $this->list[$index] = $this->createItem($index, ['entity' => $moderation_state]);
       }
     }
-
-    return isset($this->list[$index]) ? $this->list[$index] : NULL;
   }
 
 }
diff --git a/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php b/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php
new file mode 100644
index 000000000000..c57963e07087
--- /dev/null
+++ b/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace Drupal\Tests\content_moderation\Kernel;
+
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\node\Entity\Node;
+use Drupal\node\Entity\NodeType;
+
+/**
+ * @coversDefaultClass \Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList
+ *
+ * @group content_moderation
+ */
+class ModerationStateFieldItemListTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'node',
+    'content_moderation',
+    'user',
+    'system',
+    'language',
+  ];
+
+  /**
+   * @var \Drupal\node\NodeInterface
+   */
+  protected $testNode;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->installSchema('node', 'node_access');
+    $this->installEntitySchema('node');
+    $this->installEntitySchema('user');
+    $this->installEntitySchema('content_moderation_state');
+    $this->installConfig('content_moderation');
+
+    $node_type = NodeType::create([
+      'type' => 'example',
+    ]);
+    $node_type->setThirdPartySetting('content_moderation', 'enabled', TRUE);
+    $node_type->setThirdPartySetting('content_moderation', 'allowed_moderation_states', ['draft']);
+    $node_type->setThirdPartySetting('content_moderation', 'default_moderation_state', 'draft');
+    $node_type->save();
+    $this->testNode = Node::create([
+      'type' => 'example',
+      'title' => 'Test title',
+    ]);
+    $this->testNode->save();
+    \Drupal::entityTypeManager()->getStorage('node')->resetCache();
+    $this->testNode = Node::load($this->testNode->id());
+  }
+
+  /**
+   * Test the field item list when accessing an index.
+   */
+  public function testArrayIndex() {
+    $this->assertEquals('draft', $this->testNode->moderation_state[0]->entity->id());
+  }
+
+  /**
+   * Test the field item list when iterating.
+   */
+  public function testArrayIteration() {
+    $states = [];
+    foreach ($this->testNode->moderation_state as $item) {
+      $states[] = $item->entity->id();
+    }
+    $this->assertEquals(['draft'], $states);
+  }
+
+}
-- 
GitLab