Skip to content

Commit

Permalink
Merge pull request #126 from creative-commoners/pulls/4/default-link-…
Browse files Browse the repository at this point in the history
…title

NEW Default link title for each link type
  • Loading branch information
GuySartorelli authored Dec 4, 2023
2 parents 3c46dba + 1e1083d commit 436f45f
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 21 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,29 @@ class Page extends SiteTree

Note that you also need to add a `has_one` relation on the `Link` model to match your `has_many` here. See [official docs about `has_many`](https://docs.silverstripe.org/en/developer_guides/model/relations/#has-many)

## Default title for each link type

By default, if the title for the link has not been set, then the default title will be used instead according to the type of link that is used. Default link is not stored in the database as link title. This value is used only when rendering page content.

The developer also can set his own default title value using an extension by using `updateDefaultLinkTitle` method for each link type class.

```php
<?php
//app/src/ExternalLinkExtension
namespace App\Extensions;

use SilverStripe\Core\Extension;

class ExternalLinkExtension extends Extension
{
public function updateDefaultLinkTitle(&$defaultLinkTitle): void
{
$defaultLinkTitle = sprintf('External link: %s', $this->owner->ExternalUrl);
}
}

```

## Migrating from Shae Dawson's Linkable module

https://github.com/sheadawson/silverstripe-linkable
Expand Down
7 changes: 7 additions & 0 deletions lang/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,10 @@ en:
UNAUTHORIZED: 'Unauthorized'
UPDATE_LINK: 'Update link'
VERSIONED_STATUS_MISMATCH: 'Linkable and LinkField do not have matching Versioned applications. Make sure that both are either un-Versioned or Versioned'
SilverStripe\LinkField\Models\Link:
LINK_FIELD_TITLE_DESCRIPTION: 'If left blank, an appropriate default title will be used on the front-end'
MISSING_DEFAULT_TITLE: 'No link provided'
SilverStripe\LinkField\Models\SiteTreeLink:
MISSING_DEFAULT_TITLE: 'Page missing'
SilverStripe\LinkField\Models\FileLink:
MISSING_DEFAULT_TITLE: 'File missing'
13 changes: 13 additions & 0 deletions src/Models/FileLink.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,17 @@ public function getURL(): string
$file = $this->File();
return $file->exists() ? (string) $file->getURL() : '';
}

public function getDefaultTitle(): string
{
$file = $this->File();
if (!$file->exists()) {
return _t(
static::class . '.MISSING_DEFAULT_TITLE',
'File missing',
);
}

return (string) $this->getDescription();
}
}
28 changes: 28 additions & 0 deletions src/Models/Link.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use InvalidArgumentException;
use ReflectionException;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Forms\CompositeValidator;
use SilverStripe\Forms\DropdownField;
Expand Down Expand Up @@ -68,6 +69,10 @@ public function getCMSFields(): FieldList

$titleField = $fields->dataFieldByName('Title');
$titleField->setTitle(_t('LinkField.LINK_FIELD_TITLE', 'Title'));
$titleField->setDescription(_t(
self::class . '.LINK_FIELD_TITLE_DESCRIPTION',
'If left blank, an appropriate default title will be used on the front-end',
));

$openInNewField = $fields->dataFieldByName('OpenInNew');
$openInNewField->setTitle(_t('LinkField.OPEN_IN_NEW_TITLE', 'Open in new window?'));
Expand Down Expand Up @@ -292,4 +297,27 @@ private function getLinkTypes(): array

return $types;
}

public function getDisplayTitle(): string
{
// If we have a title, we can just bail out without any changes
if ($this->Title) {
return $this->Title;
}

$defaultLinkTitle = $this->getDefaultTitle();

$this->extend('updateDefaultLinkTitle', $defaultLinkTitle);

return $defaultLinkTitle;
}

public function getDefaultTitle(): string
{
$default = $this->getDescription() ?: $this->getURL();
if (!$default) {
$default = _t(static::class . '.MISSING_DEFAULT_TITLE', 'No link provided');
}
return $default;
}
}
24 changes: 7 additions & 17 deletions src/Models/SiteTreeLink.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,28 +110,18 @@ public function getURL(): string
return Controller::join_links($url, $anchorSegment, $queryStringSegment);
}

/**
* Try to populate link title from page title in case we don't have a title yet
*
* @return string|null
*/
public function getTitle(): ?string
public function getDefaultTitle(): string
{
$title = $this->getField('Title');

if ($title) {
// If we already have a title, we can just bail out without any changes
return $title;
}

$page = $this->Page();
$pageExist = $this->Page()->exists();

if (!$page?->exists()) {
// We don't have a page to fall back to
return null;
if (!$pageExist) {
return _t(
static::class . '.MISSING_DEFAULT_TITLE',
'Page missing',
);
}

// Use page title as a default value in case CMS user didn't provide the title
return $page->Title;
}
}
2 changes: 1 addition & 1 deletion templates/SilverStripe/LinkField/Models/Link.ss
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<a href="$URL" <% if $OpenInNew %>target="_blank" rel="noopener noreferrer"<% end_if %>>$Title</a>
<a href="$URL" <% if $OpenInNew %>target="_blank" rel="noopener noreferrer"<% end_if %>>$DisplayTitle</a>
14 changes: 14 additions & 0 deletions tests/php/Extensions/ExternalLinkExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace SilverStripe\LinkField\Tests\Extensions;

use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\DataExtension;

class ExternalLinkExtension extends DataExtension implements TestOnly
{
public function updateDefaultLinkTitle(&$defaultLinkTitle): void
{
$defaultLinkTitle = sprintf('External Link: %s', $this->owner->getURL());
}
}
82 changes: 80 additions & 2 deletions tests/php/Models/LinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\ValidationException;
use SilverStripe\Versioned\Versioned;
use SilverStripe\LinkField\Tests\Extensions\ExternalLinkExtension;

class LinkTest extends SapphireTest
{
Expand All @@ -28,6 +29,12 @@ class LinkTest extends SapphireTest
*/
protected static $fixture_file = 'LinkTest.yml';

protected static $required_extensions = [
ExternalLink::class => [
ExternalLinkExtension::class,
],
];

protected function setUp(): void
{
parent::setUp();
Expand Down Expand Up @@ -78,8 +85,7 @@ public function testSiteTreeLinkTitleFallback(): void

// The actual Database Title field should still be null
$this->assertNull($model->getField('Title'));
// But when we fetch the field (ViewableData) it should return the value from getTitle()
$this->assertEquals($page->Title, $model->Title, 'We expect to get the linked Page title');
$this->assertEquals(null, $model->Title, 'We expect that link does not have a title');

$customTitle = 'My custom title';
$model->Title = $customTitle;
Expand Down Expand Up @@ -329,4 +335,76 @@ public function linkUrlCasesDataProvider(): array
],
];
}

function linkDefaultTitleDataProvider(): array
{
return [
'page link' => [
'identifier' => 'page-link-1',
'class' => SiteTreeLink::class,
'expected' => 'PageLink1'
],
'email link' => [
'identifier' => 'email-link-with-email',
'class' => EmailLink::class,
'expected' => 'EmailLinkWithEmail'
],
'external link' => [
'identifier' => 'external-link-with-url',
'class' => ExternalLink::class,
'expected' => 'ExternalLinkWithUrl'
],
'phone link' => [
'identifier' => 'phone-link-with-phone',
'class' => PhoneLink::class,
'expected' => 'PhoneLinkWithPhone'
],
'file link' => [
'identifier' => 'file-link-no-image',
'class' => FileLink::class,
'expected' => 'File missing'
],
'page link with default title' => [
'identifier' => 'page-link-with-default-title',
'class' => SiteTreeLink::class,
'expected' => 'Page1'
],
'page link no page default title' => [
'identifier' => 'page-link-no-page-default-title',
'class' => SiteTreeLink::class,
'expected' => 'Page missing'
],
'email link with default title' => [
'identifier' => 'email-link-with-default-title',
'class' => EmailLink::class,
'expected' => 'maxime@silverstripe.com'
],
'external link with default title' => [
'identifier' => 'external-link-with-default-title',
'class' => ExternalLink::class,
'expected' => 'External Link: https://google.com'
],
'phone link with default title' => [
'identifier' => 'phone-link-with-default-title',
'class' => PhoneLink::class,
'expected' => '+64 4 978 7330'
],
'file link with default title' => [
'identifier' => 'file-link-with-default-title',
'class' => FileLink::class,
'expected' => '600x400.png'
],
];
}

/**
* @dataProvider linkDefaultTitleDataProvider
*/
public function testDefaultLinkTitle(string $identifier, string $class, string $expected): void
{
/** @var Link $link */
$link = $this->objFromFixture($class, $identifier);

$this->assertEquals($expected, $link->getDisplayTitle());
}
}
17 changes: 16 additions & 1 deletion tests/php/Models/LinkTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ SilverStripe\CMS\Model\SiteTree:
SilverStripe\Assets\Image:
image-1:
Title: 'Image1'
image-2: null

SilverStripe\LinkField\Models\Link:
link-1:
Expand Down Expand Up @@ -36,31 +37,45 @@ SilverStripe\LinkField\Models\SiteTreeLink:
QueryString: 'param1=value1&param2=option2'
Anchor: 'my-anchor'
Page: =>SilverStripe\CMS\Model\SiteTree.page-1
page-link-with-default-title:
Page: =>SilverStripe\CMS\Model\SiteTree.page-1
page-link-no-page-default-title:
Page: null

SilverStripe\LinkField\Models\EmailLink:
email-link-with-email:
Title: 'EmailLinkWithEmail'
Email: 'maxime@silverstripe.com'
email-link-no-email:
Title: 'EmailLinkNoEmail'
email-link-with-default-title:
Email: 'maxime@silverstripe.com'

SilverStripe\LinkField\Models\ExternalLink:
external-link-with-url:
Title: 'ExternalLinkWithUrl'
ExternalUrl: 'https://google.com'
external-link-no-url:
Title: 'ExternalLinkNoUrl'
external-link-with-default-title:
ExternalUrl: 'https://google.com'

SilverStripe\LinkField\Models\PhoneLink:
phone-link-with-phone:
Title: 'PhoneLinkWithPhone'
Phone: '+64 4 978 7330'
phone-link-no-phone:
Title: 'PhoneLinkNoPhone'
phone-link-with-default-title:
Phone: '+64 4 978 7330'

SilverStripe\LinkField\Models\FileLink:
file-link-with-image:
Title: 'FileLinkWithImage'
File: =>SilverStripe\Assets\Image.image-1
file-link-no-image:
Title: 'FileLinkNoImage'
Title: null
File: =>SilverStripe\Assets\Image.image-2
OpenInNew: true
file-link-with-default-title:
File: =>SilverStripe\Assets\Image.image-1

0 comments on commit 436f45f

Please sign in to comment.