diff --git a/page_manager_ui/src/Entity/PageListBuilder.php b/page_manager_ui/src/Entity/PageListBuilder.php index a1bb281..92abedc 100644 --- a/page_manager_ui/src/Entity/PageListBuilder.php +++ b/page_manager_ui/src/Entity/PageListBuilder.php @@ -52,7 +52,7 @@ protected function getPath(PageInterface $entity) { // If the page is enabled and not dynamic, show the path as a link, // otherwise as plain text. $path = $entity->getPath(); - if ($entity->status() && strpos($path, '%') === FALSE) { + if ($entity->status() && strpos($path, '{') === FALSE) { return [ 'data' => [ '#type' => 'link', diff --git a/page_manager_ui/src/Form/PageFormBase.php b/page_manager_ui/src/Form/PageFormBase.php index e5c17a8..d089b5e 100644 --- a/page_manager_ui/src/Form/PageFormBase.php +++ b/page_manager_ui/src/Form/PageFormBase.php @@ -107,6 +107,13 @@ public function validatePath(&$element, FormStateInterface $form_state) { $value = '/' . trim($element['#value'], '/'); $form_state->setValueForElement($element, $value); + if (strpos($value, '%')) { + $form_state->setErrorByName('path', 'The entity path may not contain "%".'); + } + if ($value === '/') { + $form_state->setErrorByName('path', 'The entity path may not be "/".'); + } + // Ensure each path is unique. $path = $this->entityQuery->get('page') ->condition('path', $value) diff --git a/page_manager_ui/src/Tests/PageManagerAdminTest.php b/page_manager_ui/src/Tests/PageManagerAdminTest.php index 9811fd6..6fa0159 100644 --- a/page_manager_ui/src/Tests/PageManagerAdminTest.php +++ b/page_manager_ui/src/Tests/PageManagerAdminTest.php @@ -59,6 +59,8 @@ public function testAdmin() { $this->doTestEditVariant(); $this->doTestReorderVariants(); $this->doTestAddPageWithDuplicatePath(); + $this->doTestAddPageWithSlashOnlyPath(); + $this->doTestAddPageWithPercentInPath(); $this->doTestAdminPath(); $this->doTestRemoveVariant(); $this->doTestRemoveBlock(); @@ -355,6 +357,38 @@ protected function doTestAddPageWithDuplicatePath() { } /** + * Tests adding a page with a path of "/". + */ + protected function doTestAddPageWithSlashOnlyPath() { + // Try to add a second page with the same path. + $edit = [ + 'label' => 'Bar', + 'id' => 'bar', + 'path' => '/', + ]; + $this->drupalPostForm('admin/structure/page_manager/add', $edit, 'Save'); + $this->assertText('The entity path may not be "/".'); + $this->drupalGet('admin/structure/page_manager'); + $this->assertNoText('Bar'); + } + + /** + * Tests adding a page with a path containing "%". + */ + protected function doTestAddPageWithPercentInPath() { + // Try to add a second page with the same path. + $edit = [ + 'label' => 'Bar', + 'id' => 'bar', + 'path' => 'admin/%', + ]; + $this->drupalPostForm('admin/structure/page_manager/add', $edit, 'Save'); + $this->assertText('The entity path may not contain "%".'); + $this->drupalGet('admin/structure/page_manager'); + $this->assertNoText('Bar'); + } + + /** * Tests changing the admin theme of a page. */ protected function doTestAdminPath() { diff --git a/src/Routing/PageManagerRoutes.php b/src/Routing/PageManagerRoutes.php index f8fd3c7..92897c6 100644 --- a/src/Routing/PageManagerRoutes.php +++ b/src/Routing/PageManagerRoutes.php @@ -59,9 +59,13 @@ protected function alterRoutes(RouteCollection $collection) { continue; } - if (strpos($entity->getPath(), '%')) { + $path = $entity->getPath(); + if (strpos($path, '%')) { throw new \UnexpectedValueException('The entity path may not contain "%"'); } + if ($path === '/') { + throw new \UnexpectedValueException('The entity path may not be "/"'); + } $parameters = []; $requirements = []; @@ -77,7 +81,6 @@ protected function alterRoutes(RouteCollection $collection) { } else { $route_name = "page_manager.page_view_$entity_id"; - $path = $entity->getPath(); } // Add in configured parameters. diff --git a/tests/src/Unit/PageManagerRoutesTest.php b/tests/src/Unit/PageManagerRoutesTest.php index b4bb6ea..4ce98e0 100644 --- a/tests/src/Unit/PageManagerRoutesTest.php +++ b/tests/src/Unit/PageManagerRoutesTest.php @@ -94,6 +94,28 @@ public function testAlterRoutesWithPercentPlaceholder() { } /** + * Tests adding a route with a path of '/'. + * + * @covers ::alterRoutes + * + * @expectedException \UnexpectedValueException + * @expectedExceptionMessage The entity path may not be "/" + */ + public function testAlterRoutesWithOnlySlash() { + /** @var \Drupal\page_manager\PageInterface|\Prophecy\Prophecy\ProphecyInterface $page */ + $page = $this->prophesize(PageInterface::class); + $page->status()->willReturn(TRUE); + $page->getPath()->willReturn('/')->shouldBeCalled(); + + $variant = $this->prophesize(PageVariantInterface::class); + $page->getVariants()->willReturn(['variant' => $variant->reveal()]); + + $this->pageStorage->loadMultiple()->willReturn(['page' => $page->reveal()]); + + $this->routeSubscriber->onAlterRoutes(new RouteBuildEvent(new RouteCollection())); + } + + /** * Tests adding routes for enabled and disabled pages. * * @covers ::alterRoutes