diff --git a/_config.php b/_config.php index 18967d846..6b0f5553f 100644 --- a/_config.php +++ b/_config.php @@ -36,6 +36,11 @@ Director::addRules(1, array( '$URLSegment//$Action/$ID/$OtherID' => 'ModelAsController', )); +/** + * Register the default internal shortcodes. + */ +ShortcodeParser::get('default')->register('sitetree_link', array('SiteTree', 'link_shortcode_handler')); + /** * PHP 5.2 has a namespace conflict with our datetime class, * for legacy support, we use this overload method. diff --git a/core/model/SiteTree.php b/core/model/SiteTree.php index 1c560b212..70450a6f0 100755 --- a/core/model/SiteTree.php +++ b/core/model/SiteTree.php @@ -263,6 +263,29 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid return $classes; } + /** + * Replace a "[sitetree_link id=n]" shortcode with a link to the page with the corresponding ID. + * + * @return string + */ + public static function link_shortcode_handler($arguments, $content = null, $parser = null) { + if(!isset($arguments['id']) || !is_numeric($arguments['id'])) return; + + if ( + !($page = DataObject::get_by_id('SiteTree', $arguments['id'])) // Get the current page by ID. + && !($page = Versioned::get_latest_version('SiteTree', $arguments['id'])) // Attempt link to old version. + && !($page = DataObject::get_one('ErrorPage', '"ErrorCode" = \'404\'')) // Link to 404 page directly. + ) { + return; // There were no suitable matches at all. + } + + if($content) { + return sprintf('%s', $page->Link(), $parser->parse($content)); + } else { + return $page->Link(); + } + } + /** * Return the link for this {@link SiteTree} object, with the {@link Director::baseURL()} included. * diff --git a/tests/SiteTreeTest.php b/tests/SiteTreeTest.php index e7cfbf47f..2209790fa 100644 --- a/tests/SiteTreeTest.php +++ b/tests/SiteTreeTest.php @@ -380,7 +380,42 @@ class SiteTreeTest extends SapphireTest { $this->assertEquals($memberID, $publishedVersion['PublisherID']); } - + + public function testLinkShortcodeHandler() { + $aboutPage = $this->objFromFixture('Page', 'about'); + $errorPage = $this->objFromFixture('ErrorPage', '404'); + + $parser = new ShortcodeParser(); + $parser->register('sitetree_link', array('SiteTree', 'link_shortcode_handler')); + + $aboutShortcode = sprintf('[sitetree_link id=%d]', $aboutPage->ID); + $aboutEnclosed = sprintf('[sitetree_link id=%d]Example Content[/sitetree_link]', $aboutPage->ID); + + $aboutShortcodeExpected = $aboutPage->Link(); + $aboutEnclosedExpected = sprintf('Example Content', $aboutPage->Link()); + + $this->assertEquals($aboutShortcodeExpected, $parser->parse($aboutShortcode), 'Test that simple linking works.'); + $this->assertEquals($aboutEnclosedExpected, $parser->parse($aboutEnclosed), 'Test enclosed content is linked.'); + + $aboutPage->delete(); + + $this->assertEquals($aboutShortcodeExpected, $parser->parse($aboutShortcode), 'Test that deleted pages still link.'); + $this->assertEquals($aboutEnclosedExpected, $parser->parse($aboutEnclosed)); + + $aboutShortcode = '[sitetree_link id="-1"]'; + $aboutEnclosed = '[sitetree_link id="-1"]Example Content[/sitetree_link]'; + + $aboutShortcodeExpected = $errorPage->Link(); + $aboutEnclosedExpected = sprintf('Example Content', $errorPage->Link()); + + $this->assertEquals($aboutShortcodeExpected, $parser->parse($aboutShortcode), 'Test link to 404 page if no suitable matches.'); + $this->assertEquals($aboutEnclosedExpected, $parser->parse($aboutEnclosed)); + + $this->assertEquals('', $parser->parse('[sitetree_link]'), 'Test that invalid ID attributes are not parsed.'); + $this->assertEquals('', $parser->parse('[sitetree_link id="text"]')); + $this->assertEquals('', $parser->parse('[sitetree_link]Example Content[/sitetree_link]')); + } + } // We make these extend page since that's what all page types are expected to do @@ -388,4 +423,4 @@ class SiteTreeTest_PageNode extends Page implements TestOnly { } class SiteTreeTest_PageNode_Controller extends Page_Controller implements TestOnly { } -?> \ No newline at end of file +?>