diff --git a/src/Models/ExternalLink.php b/src/Models/ExternalLink.php index d9636cc4..f1c23d74 100644 --- a/src/Models/ExternalLink.php +++ b/src/Models/ExternalLink.php @@ -22,6 +22,6 @@ public function generateLinkDescription(array $data): string public function getURL() { - return $this->ExternalUrl; + return (string) $this->ExternalUrl; } } diff --git a/src/Models/SiteTreeLink.php b/src/Models/SiteTreeLink.php index a6c374b4..b7d75062 100644 --- a/src/Models/SiteTreeLink.php +++ b/src/Models/SiteTreeLink.php @@ -4,7 +4,9 @@ use SilverStripe\CMS\Forms\AnchorSelectorField; use SilverStripe\CMS\Model\SiteTree; +use SilverStripe\Control\Controller; use SilverStripe\Forms\FieldList; +use SilverStripe\Forms\TextField; use SilverStripe\Forms\TreeDropdownField; /** @@ -12,6 +14,7 @@ * * @property int $PageID * @property string $Anchor + * @property string $QueryString * @method SiteTree Page() */ class SiteTreeLink extends Link @@ -19,7 +22,8 @@ class SiteTreeLink extends Link private static $table_name = 'LinkField_SiteTreeLink'; private static $db = [ - 'Anchor' => 'Varchar' + 'Anchor' => 'Varchar', + 'QueryString' => 'Varchar', ]; private static $has_one = [ @@ -45,6 +49,7 @@ public function getCMSFields(): FieldList $fields->removeByName([ 'PageID', 'Anchor', + 'QueryString', ]); $fields->insertAfter( @@ -60,7 +65,18 @@ public function getCMSFields(): FieldList $fields->insertAfter( 'PageID', - AnchorSelectorField::create('Anchor') + $queryStringField = TextField::create('QueryString') + ); + + $queryStringField->setDescription('Do not prepend "?". EG: "option1=value&option2=value2"'); + + $fields->insertAfter( + 'QueryString', + $anchorField = AnchorSelectorField::create('Anchor') + ); + + $anchorField->setDescription( + 'Do not prepend "#". Anchor suggestions will be displayed once the linked page is attached.' ); }); @@ -71,12 +87,10 @@ public function getURL(): ?string { $page = $this->Page(); $url = $page->exists() ? $page->Link() : ''; + $anchorSegment = $this->Anchor ? '#' . $this->Anchor : ''; + $queryStringSegment = $this->QueryString ? '?' . $this->QueryString : ''; - if ($this->Anchor) { - $url .= '#' . $this->Anchor; - } - - return $url; + return Controller::join_links($url, $anchorSegment, $queryStringSegment); } public function onBeforeWrite(): void diff --git a/tests/php/Models/LinkTest.php b/tests/php/Models/LinkTest.php index 6a1a00dd..4d57907f 100644 --- a/tests/php/Models/LinkTest.php +++ b/tests/php/Models/LinkTest.php @@ -204,4 +204,85 @@ public function linkTypeEnabledProvider(): array ], ]; } + + /** + * @param string $identifier + * @param string $class + * @param string $expected + * @return void + * @dataProvider linkUrlCasesDataProvider + */ + public function testGetUrl(string $identifier, string $class, string $expected): void + { + /** @var Link $link */ + $link = $this->objFromFixture($class, $identifier); + + $this->assertSame($expected, $link->getURL(), 'We expect specific URL value'); + } + + public function linkUrlCasesDataProvider(): array + { + return [ + 'internal link / page only' => [ + 'page-link-page-only', + SiteTreeLink::class, + '/page-1/', + ], + 'internal link / anchor only' => [ + 'page-link-anchor-only', + SiteTreeLink::class, + '#my-anchor', + ], + 'internal link / query string only' => [ + 'page-link-query-string-only', + SiteTreeLink::class, + '?param1=value1¶m2=option2', + ], + 'internal link / with anchor' => [ + 'page-link-with-anchor', + SiteTreeLink::class, + '/page-1/#my-anchor', + ], + 'internal link / with query string' => [ + 'page-link-with-query-string', + SiteTreeLink::class, + '/page-1/?param1=value1¶m2=option2', + ], + 'internal link / with query string and anchor' => [ + 'page-link-with-query-string-and-anchor', + SiteTreeLink::class, + '/page-1/?param1=value1¶m2=option2#my-anchor', + ], + 'email link / with email' => [ + 'email-link-with-email', + EmailLink::class, + 'mailto:maxime@silverstripe.com', + ], + 'email link / no email' => [ + 'email-link-no-email', + EmailLink::class, + '', + ], + 'external link / with URL' => [ + 'external-link-with-url', + ExternalLink::class, + 'https://google.com', + ], + 'external link / no URL' => [ + 'external-link-no-url', + ExternalLink::class, + '', + ], + 'phone link / with phone' => [ + 'phone-link-with-phone', + PhoneLink::class, + 'tel:+64 4 978 7330', + ], + 'phone link / no phone' => [ + 'phone-link-no-phone', + PhoneLink::class, + '', + ], + ]; + } } diff --git a/tests/php/Models/LinkTest.yml b/tests/php/Models/LinkTest.yml index 92e0f883..f60135fd 100644 --- a/tests/php/Models/LinkTest.yml +++ b/tests/php/Models/LinkTest.yml @@ -1,11 +1,55 @@ +SilverStripe\CMS\Model\SiteTree: + page-1: + Title: 'Page1' + URLSegment: 'page-1' + SilverStripe\LinkField\Models\Link: link-1: - Title: Link1 + Title: 'Link1' SilverStripe\LinkField\Models\SiteTreeLink: page-link-1: - Title: PageLink1 + Title: 'PageLink1' + page-link-page-only: + Title: 'PageLinkPageOnly' + Page: =>SilverStripe\CMS\Model\SiteTree.page-1 + page-link-anchor-only: + Title: 'PageLinkAnchorOnly' + Anchor: 'my-anchor' + page-link-query-string-only: + Title: 'PageLinkQueryStringOnly' + QueryString: 'param1=value1¶m2=option2' + page-link-with-anchor: + Title: 'PageLinkWithAnchor' + Anchor: 'my-anchor' + Page: =>SilverStripe\CMS\Model\SiteTree.page-1 + page-link-with-query-string: + Title: 'PageLinkWithQueryString' + QueryString: 'param1=value1¶m2=option2' + Page: =>SilverStripe\CMS\Model\SiteTree.page-1 + page-link-with-query-string-and-anchor: + Title: 'PageLinkWithQueryStringAndAnchor' + QueryString: 'param1=value1¶m2=option2' + Anchor: 'my-anchor' + Page: =>SilverStripe\CMS\Model\SiteTree.page-1 -SilverStripe\CMS\Model\SiteTree: - page-1: - Title: Page1 +SilverStripe\LinkField\Models\EmailLink: + email-link-with-email: + Title: 'EmailLinkWithEmail' + Email: 'maxime@silverstripe.com' + email-link-no-email: + Title: 'EmailLinkNoEmail' + +SilverStripe\LinkField\Models\ExternalLink: + external-link-with-url: + Title: 'ExternalLinkWithUrl' + ExternalUrl: 'https://google.com' + external-link-no-url: + Title: 'ExternalLinkNoUrl' + +SilverStripe\LinkField\Models\PhoneLink: + phone-link-with-phone: + Title: 'PhoneLinkWithPhone' + Phone: '+64 4 978 7330' + phone-link-no-phone: + Title: 'PhoneLinkNoPhone'