diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module index 8bf800e11a..7522d28273 100644 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@ -13,6 +13,7 @@ use Drupal\Core\Url; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\node\NodeInterface; use Drupal\taxonomy\VocabularyInterface; use Drupal\user\Entity\User; @@ -148,7 +149,7 @@ function forum_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $ent * * Assigns the forum taxonomy when adding a topic from within a forum. */ -function forum_node_presave(EntityInterface $node) { +function forum_node_presave(NodeInterface $node) { if (\Drupal::service('forum_manager')->checkNodeType($node)) { // Make sure all fields are set properly: $node->icon = !empty($node->icon) ? $node->icon : ''; @@ -158,7 +159,11 @@ function forum_node_presave(EntityInterface $node) { if (!$node->isNew()) { $old_tid = \Drupal::service('forum.index_storage')->getOriginalTermId($node); if ($old_tid && isset($node->forum_tid) && ($node->forum_tid != $old_tid) && !empty($node->shadow)) { - // A shadow copy needs to be created. Retain new term and add old term. + + // A shadow copy needs to be created. Retain new term and add old + // term. This requires a new revision, as {forum} is keyed by revision + // ID. + $node->setNewRevision(TRUE); $node->taxonomy_forums[count($node->taxonomy_forums)] = ['target_id' => $old_tid]; } } @@ -332,6 +337,7 @@ function forum_form_node_form_alter(&$form, FormStateInterface $form_state, $for '#description' => t('If you move this topic, you can leave a link in the old forum to the new forum.'), ]; $form['forum_tid'] = ['#type' => 'value', '#value' => $node->forum_tid]; + $form['#entity_builders'][] = 'forum_node_form_entity_builder'; } if (isset($form['taxonomy_forums'])) { @@ -347,6 +353,15 @@ function forum_form_node_form_alter(&$form, FormStateInterface $form_state, $for } } +/** + * Entity builder for the node edit form. + * + * @see forum_form_node_form_alter() + */ +function forum_node_form_entity_builder($entity_type, NodeInterface $node, &$form, FormStateInterface $form_state) { + $node->shadow = $form_state->getValue('shadow'); +} + /** * Implements hook_preprocess_HOOK() for block templates. */ diff --git a/core/modules/forum/src/ForumIndexStorage.php b/core/modules/forum/src/ForumIndexStorage.php index 23459dc507..57fdf9afbf 100644 --- a/core/modules/forum/src/ForumIndexStorage.php +++ b/core/modules/forum/src/ForumIndexStorage.php @@ -81,10 +81,23 @@ public function deleteRevision(NodeInterface $node) { * {@inheritdoc} */ public function update(NodeInterface $node) { - $this->database->update('forum') - ->fields(['tid' => $node->forum_tid]) - ->condition('vid', $node->getRevisionId()) - ->execute(); + if (count($node->forum_tid) > 1) { + // If there is more than one value, we're leaving a shadow. + // Create a new record. + $this->database->insert('forum') + ->fields([ + 'tid' => $node->forum_tid, + 'vid' => $node->getRevisionId(), + 'nid' => $node->id(), + ]) + ->execute(); + } + else { + $this->database->update('forum') + ->fields(['tid' => $node->forum_tid]) + ->condition('vid', $node->getRevisionId()) + ->execute(); + } } /** diff --git a/core/modules/forum/tests/src/Functional/ForumTest.php b/core/modules/forum/tests/src/Functional/ForumTest.php index 8480ab6706..5d79c5a0fe 100644 --- a/core/modules/forum/tests/src/Functional/ForumTest.php +++ b/core/modules/forum/tests/src/Functional/ForumTest.php @@ -674,15 +674,21 @@ private function verifyForums(EntityInterface $node, $admin, $response = 200) { $this->assertSession()->pageTextContains('Forum topic ' . $edit['title[0][value]'] . ' has been updated.'); // Verify topic was moved to a different forum. - $forum_tid = $this->container + $forum_tids = $this->container ->get('database') ->select('forum', 'f') ->fields('f', ['tid']) ->condition('nid', $node->id()) ->condition('vid', $node->getRevisionId()) ->execute() - ->fetchField(); - $this->assertSame($this->rootForum['tid'], $forum_tid, 'The forum topic is linked to a different forum'); + ->fetchCol(); + $expected = [$this->rootForum['tid'], $this->forum['tid']]; + $difference = array_diff($expected, $forum_tids); + $this->assertEmpty($difference, 'The forum topic is linked to a different forum and the shadow remains'); + + // Verify the shadow topic title is shown. + $this->drupalGet('forum/' . $this->forum['tid']); + $this->assertSession()->responseContains($edit['title[0][value]'], 'Shadow topic title is shown'); // Delete forum node. $this->drupalGet('node/' . $node->id() . '/delete');