fromholdio / silverstripe-superlinker
Superlinker
Package info
github.com/fromholdio/silverstripe-superlinker
Type:silverstripe-vendormodule
pkg:composer/fromholdio/silverstripe-superlinker
Requires
- fromholdio/silverstripe-dbhtmlanchors: ^2.1.0
- fromholdio/silverstripe-dependentgroupeddropdownfield: ^4.1.0
- fromholdio/silverstripe-externalurlfield: ^2.0.0
- fromholdio/silverstripe-globalanchors: ^2.1.0
- fromholdio/silverstripe-minigridfield: ^2.0.0
- fromholdio/silverstripe-systemlinks: ^2.0.0
- innoweb/silverstripe-international-phone-number-field: ^6.0.2
- silverstripe/cms: ^6.0
- unclecheese/display-logic: ^4.0.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A powerful, extensible link management system for SilverStripe that provides a unified interface for creating and managing all types of links in your CMS.
Table of Contents
- Overview
- Why SuperLinker?
- Requirements
- Installation
- Core Concepts
- Quick Start
- Link Types
- Configuration
- Usage
- Optional Features
- Dependencies
- Implementation Modules
- API Reference
- Real-World Examples
- Migration
- License
Overview
SuperLinker is a comprehensive link management system that replaces fragmented link handling with a single, extensible DataObject. It provides:
- 8 built-in link types: SiteTree, External, Email, Phone, File, System, GlobalAnchor, Null
- Extensible architecture: Add custom link types via extensions
- Optional features: Description, Icon, Image support
- Consistent UX: Same interface for all link types
- Type-specific settings: Configure behavior per link type
- Automatic validation: Link health checks and orphan detection
- Template helpers: isCurrent(), isSection(), LinkingMode()
- Flexible rendering: Type-specific templates
Why SuperLinker?
Before SuperLinker, managing links in SilverStripe meant:
- Multiple incompatible link modules (Linkable, etc.)
- Inconsistent UX across different link types
- Difficult to add new link types
- No unified validation or health checks
- Fragmented template rendering
With SuperLinker, you get:
- Single DataObject for all link types
- Consistent CMS interface
- Easy extension with new types
- Built-in validation and health checks
- Unified template rendering
- Type-specific configuration
Requirements
- SilverStripe CMS ^6.0
- PHP 8.1+
Core Dependencies
- fromholdio/silverstripe-dbhtmlanchors ^2.1.0
- fromholdio/silverstripe-dependentgroupeddropdownfield ^4.0.0
- fromholdio/silverstripe-externalurlfield ^2.0.0
- fromholdio/silverstripe-globalanchors ^2.1.0
- fromholdio/silverstripe-minigridfield ^2.0.0
- fromholdio/silverstripe-systemlinks ^2.0.0
- innoweb/silverstripe-international-phone-number-field ^6.0.0
- unclecheese/display-logic ^4.0.0
Installation
composer require fromholdio/silverstripe-superlinker
Run dev/build:
vendor/bin/sake dev/build flush=1
Core Concepts
Link Types
A link type defines a category of link (e.g., 'sitetree', 'external', 'email'). Each type:
- Has a unique key (e.g., 'sitetree')
- Provides its own fields and validation
- Can have type-specific settings
- Is implemented via Extension
Type Extensions
Link types are added via SuperLinkTypeExtension subclasses that:
- Define the type key and label
- Add database fields for the type
- Provide CMS fields
- Implement URL generation logic
- Handle validation
Settings
Settings control optional features:
link_text- Custom link text fieldopen_in_new- Open in new tab optionno_follow- SEO nofollow optionlink_description- Description field (optional extension)link_image- Image upload (optional extension)icon- Icon upload (optional extension)
Settings can be enabled globally or per-type.
Link Health
SuperLinker tracks link health:
- Valid: Has type, type is available, not orphaned, not empty
- Orphaned: Container object doesn't exist (future feature)
- Empty: No URL generated
Template Rendering
Links render via templates with fallback chain:
ClassName_TypeKey.ss
ClassName.ss
SuperLink_TypeKey.ss
SuperLink.ss
Quick Start
1. Basic has_one Relation
use Fromholdio\SuperLinker\Model\SuperLink; class Page extends SiteTree { private static $has_one = [ 'CTALink' => SuperLink::class ]; }
2. Add CMS Fields
use Fromholdio\HasOneEdit\HasOneMiniGridField; public function getCMSFields(): FieldList { $fields = parent::getCMSFields(); $fields->addFieldToTab('Root.Main', HasOneMiniGridField::create('CTALink', 'Call to Action', $this) ); return $fields; }
3. Use in Templates
<% if $CTALink %> $CTALink <% end_if %>
Or with custom markup:
<% if $CTALink %> <a href="$CTALink.URL" <% if $CTALink.isOpenInNew %>target="_blank"<% end_if %> <% if $CTALink.RelValue %>rel="$CTALink.RelValue"<% end_if %>> $CTALink.Title </a> <% end_if %>
4. has_many Relations
class Page extends SiteTree { private static $has_many = [ 'Links' => SuperLink::class ]; }
use Fromholdio\MiniGridField\MiniGridField; $fields->addFieldToTab('Root.Main', MiniGridField::create('Links', 'Links', $this) ->setLimit(10) );
Link Types
SiteTree Link
Links to pages within your SilverStripe site.
Features:
- SearchableDropdownField for page selection by default, or TreeDropdownField
- Optional anchor selection (page content + global anchors)
- isCurrent() and isSection() support
- Configurable tree root (TreeDropdownField only)
Configuration:
Disable anchor fields:
Fromholdio\SuperLinker\Model\SuperLink: types: sitetree: allow_anchor: false
By default, pages are selected with a flat SearchableDropdownField. To use a hierarchical TreeDropdownField instead, which also applies the configurable tree root, set use_searchable_dropdown_field to false:
Fromholdio\SuperLinker\Model\SuperLink: types: sitetree: use_searchable_dropdown_field: false
These settings apply per class. SuperLink and VersionedSuperLink are separate classes that share SuperLinkTrait, so configuring one does not change the other. Repeat these settings under Fromholdio\SuperLinker\Model\VersionedSuperLink if you use both.
Usage:
$link->getLinkedSiteTree(); // Returns SiteTree object $link->getLinkedSiteTreeAnchor(); // Returns anchor string
External Link
Links to external URLs.
Features:
- ExternalURLField with validation
- Protocol/scheme validation
- Query string and fragment support
- Internal URL blocking (optional)
Configuration:
Fromholdio\SuperLinker\Model\SuperLink: types: external: is_internal_url_allowed: false allowed_schemes: https: true http: true ftp: false
Email Link
Creates mailto: links with optional subject and body.
Features:
- Email validation
- Optional CC/BCC fields
- Subject and body fields
- Automatic mailto: URL generation
Configuration:
Fromholdio\SuperLinker\Model\SuperLink: types: email: cc: false bcc: false subject: true body: true
Phone Link
Creates tel: links for phone numbers.
Features:
- International phone number field
- Automatic formatting
- tel: URL generation
Usage:
$link->getURL(); // Returns tel:+61412345678
File Link
Links to files in the assets folder.
Features:
- TreeDropdownField or UploadField
- Force download option
- Configurable starting folder
- Upload enable/disable
Configuration:
Fromholdio\SuperLinker\Model\SuperLink: types: file: use_upload_field: false allow_uploads: false starting_folder_path: 'downloads' allow_force_download: true
Usage:
$link->getLinkedFile(); // Returns File object $link->isDownloadForced(); // Returns boolean
System Link
Links to system routes (login, logout, etc.).
Features:
- Dropdown of configured system links
- Dynamic URL generation
- Special URL processing ($Login, $Logout, etc.)
Configuration:
Fromholdio\SystemLinks\SystemLinks: links: login: url: /Security/login title: Login logout: url: /Security/logout title: Logout
Usage:
$link->getLinkedSystemLink(); // Returns ArrayData
Global Anchor Link
Links to globally-defined page anchors.
Features:
- Dropdown of configured anchors
- Relative or absolute URL generation
- Current page context awareness
Configuration:
Fromholdio\GlobalAnchors\GlobalAnchors: anchors: nav: 'Main Navigation' content: 'Page Content' footer: 'Footer'
Usage:
$link->getLinkedGlobalAnchor(); // Returns anchor key
Null Link
Text-only, no actual link.
Features:
- Displays text without href
- Useful for disabled menu items
- No URL generated
Usage: Automatically renders as text without <a> tag.
Configuration
Enabling/Disabling Link Types
# Allow only specific types Fromholdio\SuperLinker\Model\SuperLink: allowed_types: - sitetree - external - email # Or disallow specific types Fromholdio\SuperLinker\Model\SuperLink: disallowed_types: - phone - file
Type-Specific Settings
Fromholdio\SuperLinker\Model\SuperLink: types: external: settings: open_in_new: true # Enable by default no_follow: true email: settings: open_in_new: false # Disable for this type no_follow: false
Global Settings
Fromholdio\SuperLinker\Model\SuperLink: settings: link_text: true open_in_new: true no_follow: true
Custom Type Configuration
Fromholdio\SuperLinker\Model\SuperLink: types: mytype: label: 'My Custom Type' sort: 100 settings: link_text: true open_in_new: false
Usage
In PHP
Getting Link Data
// Get URL $url = $link->getURL(); $absoluteURL = $link->getAbsoluteURL(); // Get title $title = $link->getTitle(); // Custom or default $defaultTitle = $link->getDefaultTitle(); // Always default // Get link type $type = $link->getType(); // 'sitetree', 'external', etc. $typeLabel = $link->getTypeLabel(); // 'Page on this website', etc. // Check link health $isValid = $link->isLinkValid(); $isEmpty = $link->isLinkEmpty(); $isOrphaned = $link->isLinkOrphaned(); // Get HTML attributes $attrs = $link->getDefaultAttributes(); // ['href' => '...', 'target' => '...', etc.] $href = $link->getHrefValue(); $target = $link->getTargetValue(); // '_blank' or null $rel = $link->getRelValue(); // 'nofollow noopener' or null $class = $link->getClassValue(); // Check settings $isOpenInNew = $link->isOpenInNew(); $isNoFollow = $link->isNoFollow(); $isNoOpener = $link->isNoOpener(); // Template helpers $isCurrent = $link->isCurrent(); // For SiteTree links $isSection = $link->isSection(); // For SiteTree links $linkingMode = $link->LinkingMode(); // 'link', 'current', or 'section'
Adding CSS Classes
$link->addExtraCSSClass('btn btn-primary'); $link->removeExtraCSSClass('btn-primary');
Filtering Valid Links
use Fromholdio\SuperLinker\Model\SuperLink; $links = $page->Links(); $validLinks = SuperLink::excludeInvalidLinks($links);
In Templates
Basic Usage
<!-- Automatic rendering --> <% if $CTALink %> $CTALink <% end_if %> <!-- Manual rendering --> <% if $CTALink %> <a href="$CTALink.URL" $CTALink.AttributesHTML> $CTALink.Title </a> <% end_if %>
With Attributes
<% if $CTALink %> <a href="$CTALink.URL" <% if $CTALink.TargetValue %>target="$CTALink.TargetValue"<% end_if %> <% if $CTALink.RelValue %>rel="$CTALink.RelValue"<% end_if %> <% if $CTALink.ClassValue %>class="$CTALink.ClassValue"<% end_if %>> $CTALink.Title </a> <% end_if %>
Looping Links
<% if $Links %> <ul> <% loop $Links %> <li> <a href="$URL" $AttributesHTML>$Title</a> </li> <% end_loop %> </ul> <% end_if %>
With Linking Mode
<% loop $Menu(1) %> <% if $MenuLink %> <li class="$MenuLink.LinkingMode"> <a href="$MenuLink.URL">$MenuLink.Title</a> </li> <% end_if %> <% end_loop %>
Type-Specific Rendering
<% if $CTALink %> <% if $CTALink.Type == 'external' %> <a href="$CTALink.URL" target="_blank" rel="noopener"> $CTALink.Title <span class="external-icon">↗</span> </a> <% else_if $CTALink.Type == 'file' %> <a href="$CTALink.URL" download> $CTALink.Title <span class="download-icon">⬇</span> </a> <% else %> $CTALink <% end_if %> <% end_if %>
Custom Templates
Create type-specific templates:
templates/Fromholdio/SuperLinker/Model/SuperLink_external.ss:
<a href="$URL" target="_blank" rel="noopener" class="external-link"> $Title <span class="icon-external"></span> </a>
templates/Fromholdio/SuperLinker/Model/SuperLink_file.ss:
<a href="$URL" <% if $isDownloadForced %>download<% end_if %> class="file-link"> <span class="icon-download"></span> $Title </a>
templates/Fromholdio/SuperLinker/Model/SuperLink.ss (fallback):
<a href="$URL" $AttributesHTML>$Title</a>
Optional Features
Description Extension
Add description field to links.
Installation:
Fromholdio\SuperLinker\Model\SuperLink: extensions: - Fromholdio\SuperLinker\Extensions\SuperLinkDescriptionExtension
Configuration:
Fromholdio\SuperLinker\Model\SuperLink: link_description_rows: 3 # TextField if 1, TextareaField if > 1 settings: link_description: true
Usage:
$description = $link->getDescription(); $defaultDescription = $link->getDefaultDescription();
Templates:
<% if $CTALink %> <a href="$CTALink.URL"> <strong>$CTALink.Title</strong> <% if $CTALink.Description %> <span class="description">$CTALink.Description</span> <% end_if %> </a> <% end_if %>
Auto-Generated Descriptions:
For SiteTree and File links, implement on target:
class Page extends SiteTree { public function getSuperLinkDefaultDescription(): ?string { return $this->MetaDescription ?: $this->Summary; } }
Icon Extension
Add icon upload to links.
Installation:
Fromholdio\SuperLinker\Model\SuperLink: extensions: - Fromholdio\SuperLinker\Extensions\SuperLinkIconExtension
Configuration:
Fromholdio\SuperLinker\Model\SuperLink: icon_folder_path: 'link-icons' icon_allowed_extensions: - svg - png settings: icon: true
Usage:
$icon = $link->getIcon(); // Returns Image object
Templates:
<% if $CTALink %> <a href="$CTALink.URL"> <% if $CTALink.Icon %> <img src="$CTALink.Icon.URL" alt="" class="link-icon"> <% end_if %> $CTALink.Title </a> <% end_if %>
Image Extension
Add image upload to links.
Installation:
Fromholdio\SuperLinker\Model\SuperLink: extensions: - Fromholdio\SuperLinker\Extensions\SuperLinkImageExtension
Configuration:
Fromholdio\SuperLinker\Model\SuperLink: link_image_upload_path: 'link-images' settings: link_image: true
Usage:
$image = $link->getImage(); // Returns Image object $defaultImage = $link->getDefaultImage();
Templates:
<% if $CTALink %> <a href="$CTALink.URL" class="card-link"> <% if $CTALink.Image %> <img src="$CTALink.Image.FocusFill(400,300).URL" alt="$CTALink.Title"> <% end_if %> <h3>$CTALink.Title</h3> </a> <% end_if %>
Auto-Generated Images:
For SiteTree links:
class Page extends SiteTree { private static $has_one = [ 'FeaturedImage' => Image::class ]; public function getSuperLinkDefaultImage(): ?Image { return $this->FeaturedImage()->exists() ? $this->FeaturedImage() : null; } }
Apply helper extensions:
SilverStripe\CMS\Model\SiteTree: extensions: - Fromholdio\SuperLinker\Extensions\SuperLinkImagePageExtension SilverStripe\Assets\File: extensions: - Fromholdio\SuperLinker\Extensions\SuperLinkImageFileExtension
Dependencies
SuperLinker relies on several companion modules that provide specific functionality.
SystemLinks
Purpose: Define static system links (login, logout, etc.) for use in templates and CMS.
Installation: Included with SuperLinker
Configuration:
Fromholdio\SystemLinks\SystemLinks: links: login: url: /Security/login title: Login logout: url: /Security/logout title: Logout lostpassword: url: /Security/lostpassword title: Lost Password admin: url: /admin title: CMS Admin
Special URLs:
$Login- Automatically resolves to Security::login_url()$Logout- Automatically resolves to Security::logout_url() with token$LostPassword- Automatically resolves to Security::lost_password_url()
Usage in Templates:
<a href="$SystemLink('login').URL">$SystemLink('login').Title</a>
Usage in PHP:
use Fromholdio\SystemLinks\SystemLinks; $link = SystemLinks::get_link('login'); // Returns ArrayData $url = $link->URL; $title = $link->Title; // Get as map for dropdown $map = SystemLinks::get_map(); // ['login' => 'Login', ...]
Documentation: See vendor/fromholdio/silverstripe-systemlinks/README.md
GlobalAnchors
Purpose: Define static global HTML anchors for use across the site.
Installation: Included with SuperLinker
Configuration:
Fromholdio\GlobalAnchors\GlobalAnchors: anchors: nav: 'Main Navigation' content: 'Page Content' footer: 'Footer' sidebar: 'Sidebar'
Usage in Templates:
<nav id="nav">...</nav> <main id="content">...</main> <aside id="sidebar">...</aside> <footer id="footer">...</footer>
Usage in PHP:
use Fromholdio\GlobalAnchors\GlobalAnchors; $anchors = GlobalAnchors::get_anchors(); // ['nav' => 'Main Navigation', ...] $title = GlobalAnchors::get_anchor_title('nav'); // 'Main Navigation'
Documentation: See vendor/fromholdio/silverstripe-globalanchors/README.md
RelativeURLField
Purpose: Form field for entering URL slugs with collision detection.
Installation: Included with SuperLinker
Features:
- Base URL display
- Collision checking against SiteTree
- Query string support (optional)
- Full path support (optional)
- Auto-incrementing on collision
Usage:
use Fromholdio\RelativeURLField\Forms\RelativeURLField; $field = RelativeURLField::create('URLSegment', 'URL'); $field->setBaseURL('https://example.com/redirects/'); $field->setIsQueryStringAllowed(true); $field->setIsFullPathAllowed(false);
Documentation: See vendor/fromholdio/silverstripe-relativeurlfield/README.md
HasOneEdit
Purpose: Inline editing of has_one relations.
Installation: Included with SuperLinker
Usage:
use Fromholdio\HasOneEdit\HasOneMiniGridField; $fields->addFieldToTab('Root.Main', HasOneMiniGridField::create('SuperLink', 'Link', $this) );
Note: This module is aging and may be replaced in future versions.
Documentation: See vendor/fromholdio/silverstripe-hasoneedit/README.md
Other Dependencies
- DBHTMLAnchors: Extracts anchors from HTML content
- DependentGroupedDropdownField: Dropdown that depends on another field
- ExternalURLField: URL field with validation
- MiniGridField: Compact GridField for has_many relations
- InternationalPhoneNumberField: Phone number field with formatting
Implementation Modules
SuperLinker provides base functionality. These modules extend it for specific use cases.
superlinker-ctas
Purpose: Call-to-Action / Button DataObjects
Status: Superseded by SuperLinker v3+. For new projects, create custom subclasses as needed.
Installation:
composer require fromholdio/silverstripe-superlinker-ctas
What it provides:
CTAclass extendingSuperLink- Pre-configured for button/CTA use cases
Usage:
use Fromholdio\SuperLinkerCTAs\Model\CTA; class Page extends SiteTree { private static $has_one = [ 'PrimaryCTA' => CTA::class ]; }
Documentation: See vendor/fromholdio/silverstripe-superlinker-ctas/README.md
superlinker-redirection
Purpose: Redirector pages using SuperLink targets
Installation:
composer require fromholdio/silverstripe-superlinker-redirection
What it provides:
RedirectionPage- Replacement for core RedirectorPageRedirectionDataObject - Standalone redirects- Admin interface for managing redirects
- Support for all SuperLink types as targets
Features:
- Redirect to any link type (not just internal/external)
- HTTP status code selection (301, 302, 303, 307, 308)
- Redirect from custom URL paths
- Collision detection
- Hidden from site tree
Usage:
// Create redirector page $page = RedirectionPage::create(); $page->Title = 'Old Page'; $page->RedirectLink()->LinkType = 'sitetree'; $page->RedirectLink()->SiteTreeID = $newPage->ID; $page->write();
Documentation: See vendor/fromholdio/silverstripe-superlinker-redirection/README.md
superlinker-targets
Purpose: Basic link/target DataObjects
Installation:
composer require fromholdio/silverstripe-superlinker-targets
What it provides:
Targetclass extendingSuperLink- Generic link objects for various uses
Usage:
use Fromholdio\SuperLinkerTargets\Model\Target; class Page extends SiteTree { private static $has_many = [ 'RelatedLinks' => Target::class ]; }
Documentation: See vendor/fromholdio/silverstripe-superlinker-targets/README.md
API Reference
SuperLink Core Methods
Link Information
public function getType(): ?string public function getTypeLabel(?string $type = null): ?string public function getTitle(): string public function getDefaultTitle(): string
URL Methods
public function getURL(): ?string public function getAbsoluteURL(): ?string public function getHrefValue(): ?string
Link Health
public function isLinkValid(): bool public function isLinkOrphaned(): bool public function isLinkEmpty(): bool public static function excludeInvalidLinks(SS_List $links): ArrayList
HTML Attributes
public function getDefaultAttributes(): array public function getTargetValue(): ?string public function getRelValue(): ?string public function getClassValue(): ?string public function addExtraCSSClass(string $class): self public function removeExtraCSSClass(string $class): self
Settings
public function isLinkTextEnabled(?string $type = null): bool public function isOpenInNewEnabled(?string $type = null): bool public function isOpenInNew(): bool public function isNoFollowEnabled(?string $type = null): bool public function isNoFollow(): bool public function isNoOpener(): bool
Template Helpers
public function isCurrent(): bool public function isSection(): bool public function LinkOrCurrent(): string public function LinkOrSection(): string public function LinkingMode(): string public function forTemplate(): string
CMS Fields
public function getCMSFields(): FieldList public function getCMSLinkFields(string $fieldPrefix = ''): FieldList
Type Extension Methods
SiteTreeLink
public function getLinkedSiteTree(): ?SiteTree public function getLinkedSiteTreeAnchor(): ?string public function getAvailableSiteTreeAnchors(int|string|null $siteTreeID): array public function getAllowedLinkedSiteTreeRoot(): ?SiteTree
ExternalLink
// Uses ExternalURL field - no additional methods
EmailLink
// URL generated from Email, EmailCC, EmailBCC, EmailSubject, EmailBody fields
PhoneLink
// Uses PhoneNumber field (DBPhone) - no additional methods
FileLink
public function getLinkedFile(): ?File public function isDownloadForced(): bool
SystemLink
public function getLinkedSystemLink(): ?ArrayData
GlobalAnchorLink
public function getLinkedGlobalAnchor(): ?string
Optional Extension Methods
SuperLinkDescriptionExtension
public function getDescription(): ?string public function getDefaultDescription(): ?string public function isLinkDescriptionEnabled(?string $type = null): bool
SuperLinkIconExtension
public function getIcon(): ?Image
SuperLinkImageExtension
public function getImage(): ?Image public function getDefaultImage(): ?Image public function isLinkImageEnabled(?string $type = null): bool
Real-World Examples
Example 1: Navigation Menu with SuperLinks
class Page extends SiteTree { private static $has_many = [ 'MenuLinks' => SuperLink::class ]; }
public function getCMSFields(): FieldList { $fields = parent::getCMSFields(); $fields->addFieldToTab('Root.Menu', MiniGridField::create('MenuLinks', 'Menu Links', $this) ->setLimit(10) ); return $fields; }
Template:
<nav> <ul> <% loop $MenuLinks %> <li class="$LinkingMode"> <a href="$URL" $AttributesHTML>$Title</a> </li> <% end_loop %> </ul> </nav>
Example 2: CTA Buttons with Images
Fromholdio\SuperLinker\Model\SuperLink: extensions: - Fromholdio\SuperLinker\Extensions\SuperLinkImageExtension - Fromholdio\SuperLinker\Extensions\SuperLinkDescriptionExtension
class HomePage extends Page { private static $has_many = [ 'FeatureCards' => SuperLink::class ]; }
Template:
<div class="feature-cards"> <% loop $FeatureCards %> <a href="$URL" class="card"> <% if $Image %> <img src="$Image.FocusFill(400,300).URL" alt="$Title"> <% end_if %> <h3>$Title</h3> <% if $Description %> <p>$Description</p> <% end_if %> </a> <% end_loop %> </div>
Example 3: Footer Links with Icons
Fromholdio\SuperLinker\Model\SuperLink: extensions: - Fromholdio\SuperLinker\Extensions\SuperLinkIconExtension
class SiteConfig extends DataExtension { private static $has_many = [ 'SocialLinks' => SuperLink::class ]; }
Template:
<footer> <div class="social-links"> <% loop $SiteConfig.SocialLinks %> <a href="$URL" target="_blank" rel="noopener" class="social-link"> <% if $Icon %> <img src="$Icon.URL" alt="$Title"> <% else %> $Title <% end_if %> </a> <% end_loop %> </div> </footer>
Example 4: Custom Link Type
Create a custom link type for YouTube videos:
namespace App\Extensions; use Fromholdio\SuperLinker\Extensions\SuperLinkTypeExtension; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\TextField; class YouTubeLink extends SuperLinkTypeExtension { private static $extension_link_type = 'youtube'; private static $types = [ 'youtube' => [ 'label' => 'YouTube Video', 'settings' => [ 'open_in_new' => true ] ] ]; private static $db = [ 'YouTubeID' => 'Varchar(20)' ]; public function updateDefaultTitle(?string &$title): void { if (!$this->isLinkTypeMatch()) return; $title = 'Watch on YouTube'; } public function updateURL(?string &$url): void { if (!$this->isLinkTypeMatch()) return; $id = $this->getOwner()->getField('YouTubeID'); $url = empty($id) ? null : 'https://www.youtube.com/watch?v=' . $id; } public function updateCMSLinkTypeFields(FieldList $fields, string $type, string $fieldPrefix): void { if (!$this->isLinkTypeMatch($type)) return; $fields->push( TextField::create($fieldPrefix . 'YouTubeID', 'YouTube Video ID') ->setDescription('e.g., dQw4w9WgXcQ') ); } }
Apply extension:
Fromholdio\SuperLinker\Model\SuperLink: extensions: - App\Extensions\YouTubeLink
Example 5: Versioned SuperLinks
For versioned content:
use Fromholdio\SuperLinker\Model\VersionedSuperLink; class Article extends Page { private static $has_one = [ 'RelatedArticleLink' => VersionedSuperLink::class ]; }
Migration
From Linkable or Similar Modules
- Install SuperLinker:
composer require fromholdio/silverstripe-superlinker
- Update DataObject Relations:
// Before private static $has_one = [ 'ExternalLink' => Link::class ]; // After private static $has_one = [ 'ExternalLink' => SuperLink::class ];
- Update CMS Fields:
// Before $fields->addFieldToTab('Root.Main', LinkField::create('ExternalLinkID', 'Link') ); // After $fields->addFieldToTab('Root.Main', HasOneMiniGridField::create('ExternalLink', 'Link', $this) );
- Update Templates:
<!-- Before --> <% if $ExternalLink %> <a href="$ExternalLink.URL">$ExternalLink.Title</a> <% end_if %> <!-- After (same!) --> <% if $ExternalLink %> <a href="$ExternalLink.URL">$ExternalLink.Title</a> <% end_if %>
- Run dev/build:
vendor/bin/sake dev/build flush=1
- Migrate Data: Write a migration task to convert existing link data to SuperLink format.
License
BSD-3-Clause
Support
- GitHub: https://github.com/fromholdio/silverstripe-superlinker
- Issues: https://github.com/fromholdio/silverstripe-superlinker/issues
Contributing
Contributions are welcome! Please open an issue or pull request on GitHub.
Credits
Developed by Luke Fromhold