FEATURE: Added SiteTree::get_by_link() to fetch the SiteTree object associated with a nested link.

MINOR : Deprecated SiteTree::get_by_url().

From: Andrew Short <andrewjshort@gmail.com>

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@88484 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Andrew Short 2009-10-11 00:07:08 +00:00 committed by Sam Minnee
parent da2fd13b38
commit 57f9a957bc
2 changed files with 122 additions and 52 deletions

View File

@ -227,6 +227,72 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
self::$nested_urls = false;
}
/**
* Fetches the {@link SiteTree} object that maps to a link.
*
* If you have enabled {@link SiteTree::nested_urls()} on this site, then you can use a nested link such as
* "about-us/staff/", and this function will traverse down the URL chain and grab the appropriate link.
*
* Note that if no model can be found, this method will fall over to a decorated alternateGetByLink method provided
* by a decorator attached to {@link SiteTree}
*
* @param string $link
* @param bool $cache
* @return SiteTree
*/
public static function get_by_link($link, $cache = true) {
if(trim($link, '/')) {
$link = trim(Director::makeRelative($link), '/');
} else {
$link = RootURLController::get_homepage_urlsegment();
}
$parts = Convert::raw2sql(preg_split('|/+|', $link));
// Grab the initial root level page to traverse down from.
$URLSegment = array_shift($parts);
$sitetree = DataObject::get_one (
'SiteTree', "\"URLSegment\" = '$URLSegment'" . (self::nested_urls() ? ' AND "ParentID" = 0' : ''), $cache
);
/// Fall back on a unique URLSegment for b/c.
if(!$sitetree && self::nested_urls() && $pages = DataObject::get('SiteTree', "\"URLSegment\" = '$URLSegment'")) {
return ($pages->Count() == 1) ? $pages->First() : null;
}
// Attempt to grab an alternative page from decorators.
if(!$sitetree) {
if($alternatives = singleton('SiteTree')->extend('alternateGetByLink', $link, $filter, $cache, $order)) {
foreach($alternatives as $alternative) if($alternative) return $alternative;
}
return false;
}
// Check if we have any more URL parts to parse.
if(!self::nested_urls() || !count($parts)) return $sitetree;
// Traverse down the remaining URL segments and grab the relevant SiteTree objects.
foreach($parts as $segment) {
$next = DataObject::get_one (
'SiteTree', "\"URLSegment\" = '$segment' AND \"ParentID\" = $sitetree->ID", $cache
);
if(!$next) {
if($alternatives = singleton('SiteTree')->extend('alternateGetByLink', $link, $filter, $cache, $order)) {
foreach($alternatives as $alternative) if($alternative) return $alternative;
}
return false;
}
$sitetree->destroy();
$sitetree = $next;
}
return $sitetree;
}
/**
* Return a subclass map of SiteTree
* that shouldn't be hidden through
@ -263,26 +329,26 @@ 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('<a href="%s">%s</a>', $page->Link(), $parser->parse($content));
} else {
return $page->Link();
/**
* 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('<a href="%s">%s</a>', $page->Link(), $parser->parse($content));
} else {
return $page->Link();
}
}
@ -1365,27 +1431,14 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
}
/**
* Return the SiteTree object with the given URL segment.
*
* @param string $urlSegment The URL segment, eg 'home'
* @param string $extraFilter
* @param boolean $cache
* @param string $orderby
* @return SiteTree The object with the given URL segment
* @deprecated 2.4 Use {@link SiteTree::get_by_link()}.
*/
public static function get_by_url($urlSegment, $extraFilter = "", $cache = true, $orderby = "") {
$filter = sprintf("\"URLSegment\" = '%s'", Convert::raw2sql($urlSegment));
if($extraFilter) $filter .= " AND $extraFilter";
$matchedPage = DataObject::get_one("SiteTree", $filter, $cache, $orderby);
if($matchedPage) {
return $matchedPage;
} else {
$alternativeMatches = singleton('SiteTree')->extend('alternateGetByUrl', $urlSegment, $extraFilter, $cache, $orderby);
if($alternativeMatches) foreach($alternativeMatches as $alternativeMatch) {
if($alternativeMatch) return $alternativeMatch;
}
return false;
}
public static function get_by_url($link) {
user_error (
'SiteTree::get_by_url() is deprecated, please use SiteTree::get_by_link()', E_USER_NOTICE
);
return self::get_by_link($link);
}
/**

41
tests/SiteTreeTest.php Normal file → Executable file
View File

@ -272,20 +272,37 @@ class SiteTreeTest extends SapphireTest {
$this->assertEquals('Page', $requeriedPage->class);
}
/**
* Test SiteTree::get_by_url()
*/
function testGetByURL() {
// Test basic get by url
$this->assertEquals($this->idFromFixture('Page', 'home'), SiteTree::get_by_url("home")->ID);
// Test the extraFilter argument
// Note: One day, it would be more appropriate to return null instead of false for queries such as these
$this->assertFalse(SiteTree::get_by_url("home", "1 = 2"));
public function testGetByLink() {
$home = $this->objFromFixture('Page', 'home');
$about = $this->objFromFixture('Page', 'about');
$staff = $this->objFromFixture('Page', 'staff');
$product = $this->objFromFixture('Page', 'product1');
$notFound = $this->objFromFixture('ErrorPage', '404');
SiteTree::disable_nested_urls();
$this->assertEquals($home->ID, SiteTree::get_by_link('/', false)->ID);
$this->assertEquals($home->ID, SiteTree::get_by_link('/home/', false)->ID);
$this->assertEquals($about->ID, SiteTree::get_by_link($about->Link(), false)->ID);
$this->assertEquals($staff->ID, SiteTree::get_by_link($staff->Link(), false)->ID);
$this->assertEquals($product->ID, SiteTree::get_by_link($product->Link(), false)->ID);
$this->assertEquals($notFound->ID, SiteTree::get_by_link($notFound->Link(), false)->ID);
SiteTree::enable_nested_urls();
$this->assertEquals($home->ID, SiteTree::get_by_link('/', false)->ID);
$this->assertEquals($home->ID, SiteTree::get_by_link('/home/', false)->ID);
$this->assertEquals($about->ID, SiteTree::get_by_link($about->Link(), false)->ID);
$this->assertEquals($staff->ID, SiteTree::get_by_link($staff->Link(), false)->ID);
$this->assertEquals($product->ID, SiteTree::get_by_link($product->Link(), false)->ID);
$this->assertEquals($notFound->ID, SiteTree::get_by_link($notFound->Link(), false)->ID);
$this->assertEquals (
$staff->ID, SiteTree::get_by_link('/my-staff/', false)->ID, 'Assert a unique URLSegment can be used for b/c.'
);
}
function testDeleteFromStageOperatesRecursively() {
$pageAbout = $this->objFromFixture('Page', 'about');
$pageStaff = $this->objFromFixture('Page', 'staff');