Loading core/modules/path/src/Plugin/Field/FieldType/PathItem.php +22 −6 Original line number Diff line number Diff line Loading @@ -82,12 +82,28 @@ public function postSave($update) { // If we have an alias, we need to create or update a path alias entity. if ($alias) { if (!$update || !$pid) { $path_alias = $path_alias_storage->create([ $properties = [ 'path' => '/' . $entity->toUrl()->getInternalPath(), 'alias' => $alias, 'langcode' => $alias_langcode, ]); ]; if (!$pid) { // Try to load it from storage before creating it. In some cases the // path alias could be created before this function runs. For example, // \Drupal\workspaces\EntityOperations::entityTranslationInsert will // create a translation, and an associated path alias will be created // with it. $query = $path_alias_storage->getQuery()->accessCheck(FALSE); foreach ($properties as $field => $value) { $query->condition($field, $value); } $ids = $query->execute(); $pid = $ids ? reset($ids) : $pid; } if (!$pid) { $path_alias = $path_alias_storage->create($properties); $path_alias->save(); $this->set('pid', $path_alias->id()); } Loading core/modules/path/tests/modules/path_test_misc/path_test_misc.info.yml 0 → 100644 +5 −0 Original line number Diff line number Diff line name: 'Path test miscellaneous utilities' type: module description: 'Utilities for path testing' package: Testing version: VERSION core/modules/path/tests/modules/path_test_misc/src/Hook/PathTestMiscHooks.php 0 → 100644 +40 −0 Original line number Diff line number Diff line <?php declare(strict_types=1); namespace Drupal\path_test_misc\Hook; use Drupal\Core\Hook\Attribute\Hook; use Drupal\node\NodeInterface; /** * Hook implementations for path_test_misc. */ class PathTestMiscHooks { /** * Implements hook_ENTITY_TYPE_presave() for node entities. * * This is invoked from testAliasDuplicationPrevention. */ #[Hook('node_presave')] public function nodePresave(NodeInterface $node): void { if ($node->getTitle() !== 'path duplication test') { return; } // Update the title to be able to check that this code ran. $node->setTitle('path duplication test ran'); // Create a path alias that has the same values as the one in // PathItem::postSave. $path = \Drupal::entityTypeManager()->getStorage('path_alias') ->create([ 'path' => '/node/1', 'alias' => '/my-alias', 'langcode' => 'en', ]); $path->save(); } } core/modules/path/tests/src/Functional/PathNodeFormTest.php +27 −1 Original line number Diff line number Diff line Loading @@ -4,6 +4,9 @@ namespace Drupal\Tests\path\Functional; use Drupal\node\Entity\Node; use Drupal\node\NodeInterface; /** * Tests the Path Node form UI. * Loading @@ -14,7 +17,7 @@ class PathNodeFormTest extends PathTestBase { /** * {@inheritdoc} */ protected static $modules = ['node', 'path']; protected static $modules = ['node', 'path', 'path_test_misc']; /** * {@inheritdoc} Loading Loading @@ -59,4 +62,27 @@ public function testNodeForm(): void { $assert_session->fieldNotExists('path[0][alias]'); } /** * Tests that duplicate path aliases don't get created. */ public function testAliasDuplicationPrevention(): void { $this->drupalGet('node/add/page'); $edit['title[0][value]'] = 'path duplication test'; $edit['path[0][alias]'] = '/my-alias'; $this->submitForm($edit, 'Save'); // Test that PathItem::postSave detects if a path alias exists // before creating one. $aliases = \Drupal::entityTypeManager() ->getStorage('path_alias') ->loadMultiple(); static::assertCount(1, $aliases); $node = Node::load(1); static::assertInstanceOf(NodeInterface::class, $node); // This updated title gets set in PathTestMiscHooks::nodePresave. This // is a way of ensuring that bit of test code runs. static::assertEquals('path duplication test ran', $node->getTitle()); } } Loading
core/modules/path/src/Plugin/Field/FieldType/PathItem.php +22 −6 Original line number Diff line number Diff line Loading @@ -82,12 +82,28 @@ public function postSave($update) { // If we have an alias, we need to create or update a path alias entity. if ($alias) { if (!$update || !$pid) { $path_alias = $path_alias_storage->create([ $properties = [ 'path' => '/' . $entity->toUrl()->getInternalPath(), 'alias' => $alias, 'langcode' => $alias_langcode, ]); ]; if (!$pid) { // Try to load it from storage before creating it. In some cases the // path alias could be created before this function runs. For example, // \Drupal\workspaces\EntityOperations::entityTranslationInsert will // create a translation, and an associated path alias will be created // with it. $query = $path_alias_storage->getQuery()->accessCheck(FALSE); foreach ($properties as $field => $value) { $query->condition($field, $value); } $ids = $query->execute(); $pid = $ids ? reset($ids) : $pid; } if (!$pid) { $path_alias = $path_alias_storage->create($properties); $path_alias->save(); $this->set('pid', $path_alias->id()); } Loading
core/modules/path/tests/modules/path_test_misc/path_test_misc.info.yml 0 → 100644 +5 −0 Original line number Diff line number Diff line name: 'Path test miscellaneous utilities' type: module description: 'Utilities for path testing' package: Testing version: VERSION
core/modules/path/tests/modules/path_test_misc/src/Hook/PathTestMiscHooks.php 0 → 100644 +40 −0 Original line number Diff line number Diff line <?php declare(strict_types=1); namespace Drupal\path_test_misc\Hook; use Drupal\Core\Hook\Attribute\Hook; use Drupal\node\NodeInterface; /** * Hook implementations for path_test_misc. */ class PathTestMiscHooks { /** * Implements hook_ENTITY_TYPE_presave() for node entities. * * This is invoked from testAliasDuplicationPrevention. */ #[Hook('node_presave')] public function nodePresave(NodeInterface $node): void { if ($node->getTitle() !== 'path duplication test') { return; } // Update the title to be able to check that this code ran. $node->setTitle('path duplication test ran'); // Create a path alias that has the same values as the one in // PathItem::postSave. $path = \Drupal::entityTypeManager()->getStorage('path_alias') ->create([ 'path' => '/node/1', 'alias' => '/my-alias', 'langcode' => 'en', ]); $path->save(); } }
core/modules/path/tests/src/Functional/PathNodeFormTest.php +27 −1 Original line number Diff line number Diff line Loading @@ -4,6 +4,9 @@ namespace Drupal\Tests\path\Functional; use Drupal\node\Entity\Node; use Drupal\node\NodeInterface; /** * Tests the Path Node form UI. * Loading @@ -14,7 +17,7 @@ class PathNodeFormTest extends PathTestBase { /** * {@inheritdoc} */ protected static $modules = ['node', 'path']; protected static $modules = ['node', 'path', 'path_test_misc']; /** * {@inheritdoc} Loading Loading @@ -59,4 +62,27 @@ public function testNodeForm(): void { $assert_session->fieldNotExists('path[0][alias]'); } /** * Tests that duplicate path aliases don't get created. */ public function testAliasDuplicationPrevention(): void { $this->drupalGet('node/add/page'); $edit['title[0][value]'] = 'path duplication test'; $edit['path[0][alias]'] = '/my-alias'; $this->submitForm($edit, 'Save'); // Test that PathItem::postSave detects if a path alias exists // before creating one. $aliases = \Drupal::entityTypeManager() ->getStorage('path_alias') ->loadMultiple(); static::assertCount(1, $aliases); $node = Node::load(1); static::assertInstanceOf(NodeInterface::class, $node); // This updated title gets set in PathTestMiscHooks::nodePresave. This // is a way of ensuring that bit of test code runs. static::assertEquals('path duplication test ran', $node->getTitle()); } }