diff --git a/src/Control/RequestHandler.php b/src/Control/RequestHandler.php index 2c47efa6d..e724f7494 100644 --- a/src/Control/RequestHandler.php +++ b/src/Control/RequestHandler.php @@ -551,10 +551,13 @@ class RequestHandler extends ViewableData } /** - * Returns a link to this controller. Overload with your own Link rules if they exist. + * Returns a link to this controller. + * Returns null if no link could be generated. + * + * Overload with your own Link rules if they exist. * * @param string $action Optional action - * @return string + * @return ?string */ public function Link($action = null) { @@ -576,6 +579,22 @@ class RequestHandler extends ViewableData return null; } + /** + * Get the absolute URL for this controller, including protocol and host. + * Returns null if no link could be generated. + * + * @param string $action See {@link Link()} + * @return ?string + */ + public function AbsoluteLink($action = '') + { + $link = $this->Link($action); + if ($link === null) { + return null; + } + return Director::absoluteURL((string) $link); + } + /** * Redirect to the given URL. */ diff --git a/tests/php/Control/RequestHandlerTest.php b/tests/php/Control/RequestHandlerTest.php new file mode 100644 index 000000000..98d024060 --- /dev/null +++ b/tests/php/Control/RequestHandlerTest.php @@ -0,0 +1,97 @@ + null, + 'action' => null, + 'expected' => null, + ], + [ + 'urlSegment' => null, + 'action' => 'some-action', + 'expected' => null, + ], + // The action is just addeed on after the url segment + [ + 'urlSegment' => 'my-controller', + 'action' => null, + 'expected' => 'my-controller', + ], + [ + 'urlSegment' => 'my-controller', + 'action' => 'some-action', + 'expected' => 'my-controller/some-action', + ], + ]; + } + + /** + * @dataProvider provideTestLink + */ + public function testLink(?string $urlSegment, ?string $action, ?string $expected) + { + if ($urlSegment === null) { + $this->expectWarning(); + $this->expectWarningMessage('Request handler SilverStripe\Control\RequestHandler does not have a url_segment defined. Relying on this link may be an application error'); + } + + $handler = new RequestHandler(); + RequestHandler::config()->set('url_segment', $urlSegment); + Controller::config()->set('add_trailing_slash', false); + + $this->assertEquals($expected, $handler->Link($action)); + + // Validate that trailing slash config is respected + Controller::config()->set('add_trailing_slash', true); + if (is_string($expected)) { + $expected .= '/'; + } + + $this->assertEquals($expected, $handler->Link($action)); + } + + /** + * @dataProvider provideTestLink + */ + public function testAbsoluteLink(?string $urlSegment, ?string $action, ?string $expected) + { + if ($urlSegment === null) { + $this->expectWarning(); + $this->expectWarningMessage('Request handler SilverStripe\Control\RequestHandler does not have a url_segment defined. Relying on this link may be an application error'); + } + + $handler = new RequestHandler(); + RequestHandler::config()->set('url_segment', $urlSegment); + Controller::config()->set('add_trailing_slash', false); + + if ($expected !== null) { + $expected = Director::absoluteURL($expected); + } + $this->assertEquals($expected, $handler->AbsoluteLink($action)); + + // Validate that trailing slash config is respected + Controller::config()->set('add_trailing_slash', true); + if (is_string($expected)) { + $expected = Director::absoluteURL($expected . '/'); + } + + $this->assertEquals(Director::absoluteURL($expected), $handler->AbsoluteLink($action)); + } +} diff --git a/tests/php/Control/RequestHandlingTest.php b/tests/php/Control/RequestHandlingTest.php index b72fac4f5..fd2305d76 100644 --- a/tests/php/Control/RequestHandlingTest.php +++ b/tests/php/Control/RequestHandlingTest.php @@ -17,7 +17,7 @@ use SilverStripe\Forms\Form; use SilverStripe\Security\SecurityToken; /** - * Tests for RequestHandler and HTTPRequest. + * Tests for functionality related to handling requests - not unit tests for RequestHandler. * We've set up a simple URL handling model based on */ class RequestHandlingTest extends FunctionalTest