diff --git a/core/lib/Drupal/Core/Path/AliasStorage.php b/core/lib/Drupal/Core/Path/AliasStorage.php index 4f380125bb..b856c9afa0 100644 --- a/core/lib/Drupal/Core/Path/AliasStorage.php +++ b/core/lib/Drupal/Core/Path/AliasStorage.php @@ -131,7 +131,12 @@ public function load($conditions) { foreach ($conditions as $field => $value) { if ($field == 'source' || $field == 'alias') { // Use LIKE for case-insensitive matching. - $select->condition($field, $this->connection->escapeLike($value), 'LIKE'); + if (is_array($value)) { + $select->condition($field, $value, 'IN'); + } + else { + $select->condition($field, $this->connection->escapeLike($value), 'LIKE'); + } } else { $select->condition($field, $value); @@ -160,7 +165,7 @@ public function delete($conditions) { foreach ($conditions as $field => $value) { if ($field == 'source' || $field == 'alias') { // Use LIKE for case-insensitive matching. - $query->condition($field, $this->connection->escapeLike($value), 'LIKE'); + $query->condition($field, $value, 'LIKE'); } else { $query->condition($field, $value); diff --git a/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php b/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php index ee03361d96..b8cacf2152 100644 --- a/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php +++ b/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php @@ -32,6 +32,15 @@ public function delete() { 'langcode' => $entity->language()->getId(), ]; \Drupal::service('path.alias_storage')->delete($conditions); + + $entity_type_id = $entity->getEntityTypeId(); + $source = str_replace('{' . $entity_type_id . '}', $entity->id(), $entity->getEntityType()->getLinkTemplate('revision')); + $source = str_replace('{' . $entity_type_id . '_revision}', '%', $source); + $revisionable_conditions = [ + 'source' => $source, + 'langcode' => $entity->language()->getId(), + ]; + \Drupal::service('path.alias_storage')->delete($revisionable_conditions); } } diff --git a/core/modules/path/src/Plugin/Field/FieldWidget/PathWidget.php b/core/modules/path/src/Plugin/Field/FieldWidget/PathWidget.php index dbc2525c83..cd14910317 100644 --- a/core/modules/path/src/Plugin/Field/FieldWidget/PathWidget.php +++ b/core/modules/path/src/Plugin/Field/FieldWidget/PathWidget.php @@ -28,17 +28,19 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $entity = $items->getEntity(); $path = []; if (!$entity->isNew()) { - if ($items->getLangcode() != LanguageInterface::LANGCODE_NOT_SPECIFIED) { - $conditions = ['langcode' => $items->getLangcode()]; - } if ($entity->getEntityType()->isRevisionable() && !$entity->isDefaultRevision()) { - $conditions['source'] = '/' . $entity->toUrl('revision')->getInternalPath(); - $path = \Drupal::service('path.alias_storage')->load($conditions); + $conditions = ['source' => [ + '/' . $entity->toUrl('revision')->getInternalPath(), + '/' . $entity->urlInfo()->getInternalPath(), + ]]; } - if (empty($path)) { - $conditions['source'] = '/' . $entity->toUrl()->getInternalPath(); - $path = \Drupal::service('path.alias_storage')->load($conditions); + else { + $conditions = ['source' => '/' . $entity->urlInfo()->getInternalPath()]; + } + if ($items->getLangcode() != LanguageInterface::LANGCODE_NOT_SPECIFIED) { + $conditions['langcode'] = $items->getLangcode(); } + $path = \Drupal::service('path.alias_storage')->load($conditions); if ($path === FALSE) { $path = []; } diff --git a/core/modules/path/tests/src/Functional/PathContentModerationTest.php b/core/modules/path/tests/src/Functional/PathContentModerationTest.php index b9d9f8305e..32fef3d3f0 100644 --- a/core/modules/path/tests/src/Functional/PathContentModerationTest.php +++ b/core/modules/path/tests/src/Functional/PathContentModerationTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\path\Functional; +use Drupal\Core\Path\AliasStorage; use Drupal\node\Entity\NodeType; use Drupal\Tests\BrowserTestBase; use Drupal\workflows\Entity\Workflow; @@ -40,7 +41,9 @@ protected function setUp() { public function testNodePathAlias() { // Create some moderated content with a path alias. - $this->drupalPostForm('node/add/moderated', [ + $this->drupalGet('node/add/moderated'); + $this->assertSession()->fieldValueEquals('path[0][alias]', ''); + $this->drupalPostForm(NULL, [ 'title[0][value]' => 'moderated content', 'path[0][alias]' => '/moderated-content', ], t('Save and Publish')); @@ -49,34 +52,37 @@ public function testNodePathAlias() { $this->drupalGet('/moderated-content'); $this->assertSession()->pageTextContains('moderated content'); - // Add a forward revision with the same alias. - $this->drupalPostForm('node/' . $node->id() . '/edit', [ + // Add a forward revision with the same alias and check the alias is + // from the default revision. + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->assertSession()->fieldValueEquals('path[0][alias]', '/moderated-content'); + $this->drupalPostForm(NULL, [ 'title[0][value]' => 'forward revision', 'path[0][alias]' => '/moderated-content', ], t('Save and Create New Draft')); // Check the alias still shows the default content. $this->drupalGet('/moderated-content'); - $this->assertSession()->pageTextNotContains('forward revision'); $this->assertSession()->pageTextContains('moderated content'); - // Add a third revision, updating alias. - $this->drupalPostForm('node/' . $node->id() . '/edit', [ + // Add a third revision, updating alias, and check the alias still comes + // from the default. + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->assertSession()->fieldValueEquals('path[0][alias]', '/moderated-content'); + $this->drupalPostForm(NULL, [ 'title[0][value]' => 'revision three', 'path[0][alias]' => '/revision-three', ], t('Save and Create New Draft')); // Check both aliases return what we'd expect. $this->drupalGet('/revision-three'); - $this->assertSession()->pageTextNotContains('moderated content'); - $this->assertSession()->pageTextNotContains('forward revision'); $this->assertSession()->pageTextContains('revision three'); $this->drupalGet('/moderated-content'); - $this->assertSession()->pageTextNotContains('forward revision'); $this->assertSession()->pageTextContains('moderated content'); - $this->assertSession()->pageTextNotContains('revision three'); // Add another forward revision with no alias. + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->assertSession()->fieldValueEquals('path[0][alias]', '/revision-three'); $this->drupalPostForm('node/' . $node->id() . '/edit', [ 'title[0][value]' => 'revision four', 'path[0][alias]' => '', @@ -85,19 +91,62 @@ public function testNodePathAlias() { // The first two aliases should still work, and the revision with no alias // should work on the revision path. $this->drupalGet('/node/1/revisions/4/view'); - $this->assertSession()->pageTextNotContains('moderated content'); - $this->assertSession()->pageTextNotContains('forward revision'); - $this->assertSession()->pageTextNotContains('revision three'); $this->assertSession()->pageTextContains('revision four'); $this->drupalGet('/revision-three'); - $this->assertSession()->pageTextNotContains('moderated content'); - $this->assertSession()->pageTextNotContains('forward revision'); $this->assertSession()->pageTextContains('revision three'); - $this->assertSession()->pageTextNotContains('revision four'); $this->drupalGet('/moderated-content'); - $this->assertSession()->pageTextNotContains('forward revision'); $this->assertSession()->pageTextContains('moderated content'); - $this->assertSession()->pageTextNotContains('revision three'); - $this->assertSession()->pageTextNotContains('revision four'); + + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->assertSession()->fieldValueEquals('path[0][alias]', '/moderated-content'); + $this->drupalPostForm('node/' . $node->id() . '/edit', [ + 'title[0][value]' => 'revision five', + 'path[0][alias]' => '/revision-five', + ], t('Save and Publish')); + $this->drupalGet('/revision-five'); + $this->assertSession()->pageTextContains('revision five'); + $this->drupalGet('/node/1/revisions/4/view'); + $this->assertSession()->pageTextContains('revision four'); + $this->drupalGet('/revision-three'); + $this->assertSession()->pageTextContains('revision three'); + $this->drupalGet('/moderated-content'); + $this->assertSession()->statusCodeEquals('404'); + + $this->drupalPostForm('node/' . $node->id() . '/delete', [], t('Delete')); + $aliases = \Drupal::database()->select(AliasStorage::TABLE)->fields(AliasStorage::TABLE)->execute()->fetchAll(); + $this->assertEquals([], $aliases); + + // Create some moderated content with a path alias. + $this->drupalGet('node/add/moderated'); + $this->assertSession()->fieldValueEquals('path[0][alias]', ''); + $this->drupalPostForm(NULL, [ + 'title[0][value]' => 'moderated content 2', + 'path[0][alias]' => '/moderated-content-2', + ], t('Save and Publish')); + $node = $this->getNodeByTitle('moderated content 2'); + + $this->drupalGet('/moderated-content-2'); + $this->assertSession()->pageTextContains('moderated content 2'); + + // Add a forward revision with a new alias. + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->assertSession()->fieldValueEquals('path[0][alias]', '/moderated-content-2'); + $this->drupalPostForm(NULL, [ + 'title[0][value]' => 'forward revision', + 'path[0][alias]' => '/forward-revision', + ], t('Save and Create New Draft')); + + // Check both aliases return what we'd expect. + $this->drupalGet('/forward-revision'); + $this->assertSession()->pageTextContains('forward revision'); + $this->drupalGet('/moderated-content-2'); + $this->assertSession()->pageTextContains('moderated content 2'); + + // Delete the forward revision. + $this->drupalPostForm('node/2/revisions/7/delete', [], t('Delete')); + $this->drupalGet('/forward-revision'); + $this->assertSession()->statusCodeEquals('404'); + $this->drupalGet('/moderated-content-2'); + $this->assertSession()->pageTextContains('moderated content 2'); } -} \ No newline at end of file +}