ENHANCEMENT: Updated the SiteTree link and section code to derive data from the current page, rather than relying on its own cache.

MINOR: Added tests for the link and section code.

From: Andrew Short <andrewjshort@gmail.com>

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@88489 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Andrew Short 2009-10-11 00:07:11 +00:00 committed by Sam Minnee
parent 3defa4931c
commit cb35b13905
3 changed files with 84 additions and 104 deletions

View File

@ -395,47 +395,60 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
}
/**
* Returns link/current, depending on whether you're on the current page.
* This is useful for css styling of menus.
* Returns TRUE if this is the currently active page that is being used to handle a request.
*
* @return string Either 'link' or 'current'.
* @return bool
*/
public function isCurrent() {
return $this->ID ? $this->ID == Director::get_current_page()->ID : $this === Director::get_current_page();
}
/**
* Check if this page is in the currently active section (e.g. it is either current or one of it's children is
* currently being viewed.
*
* @return bool
*/
public function isSection() {
return $this->isCurrent() || (
Director::get_current_page() instanceof SiteTree && in_array($this->ID, Director::get_current_page()->getAncestors()->column())
);
}
/**
* Return "link" or "current" depending on if this is the {@link SiteTree::isCurrent()} current page.
*
* @return string
*/
public function LinkOrCurrent() {
return ($this->isCurrent()) ? "current" : "link";
return $this->isCurrent() ? 'current' : 'link';
}
/**
* Returns link/section, depending on whether you're on the current section.
* This is useful for css styling of menus.
* Return "link" or "section" depending on if this is the {@link SiteTree::isSeciton()} current section.
*
* @return string Either 'link' or 'section'.
* @return string
*/
public function LinkOrSection() {
return ($this->isSection()) ? "section" : "link";
return $this->isSection() ? 'section' : 'link';
}
/**
* Returns link/current/section, depending if you're not in the current
* section, you're on the current page, or you're in the current section
* but not on the current page.
* Return "link", "current" or section depending on if this page is the current page, or not on the current page but
* in the current section.
*
* @return string Either 'link', 'current' or 'section'.
* @return string
*/
public function LinkingMode() {
$this->prepareCurrentAndSection();
if($this->ID == self::$currentPageID) {
return "current";
} else if(in_array($this->ID, self::$currentSectionIDs)) {
return "section";
if($this->isCurrent()) {
return 'current';
} elseif($this->isSection()) {
return 'section';
} else {
return "link";
return 'link';
}
}
/**
* Get the URL segment for this page, eg 'home'
*
@ -526,85 +539,6 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
$newSiteTree->write();
}
/**
* An array of this pages URL segment and it's parents.
* This is generated by prepareCurrentAndSection for use by
* isCurrent() and isSection()
*
* @var array
*/
protected static $currentSectionIDs;
/**
* The current page ID.
* This is generated by prepareCurrentAndSection for use by
* isCurrent() and isSection()
*
* @var int
*/
private static $currentPageID;
/**
* Records the URL segment that was used to set the current page ID
*/
private static $currentPageIDSetFromURLSegment;
/**
* This function is used for isCurrent() and isSection() to prepare
* the cached answers.
*/
protected function prepareCurrentAndSection() {
if(!self::$currentPageID || Director::urlParam('URLSegment') != self::$currentPageIDSetFromURLSegment) {
self::$currentPageID = Director::get_current_page() ? Director::get_current_page()->ID : null;
self::$currentPageIDSetFromURLSegment = Director::urlParam('URLSegment');
if(!isset(self::$currentPageID)) {
self::$currentPageID = -1;
$nextID = (Director::get_current_page() && isset(Director::get_current_page()->Parent->ID))
? Director::get_current_page()->Parent->ID
: null;
} else {
$nextID = SiteTree::$currentPageID;
}
$table = (Versioned::current_stage() == "Live")
? "SiteTree_Live"
: "SiteTree";
SiteTree::$currentSectionIDs = array();
while($nextID) {
self::$currentSectionIDs[] = $nextID;
$nextID = DB::query("SELECT \"ParentID\" FROM \"SiteTree\" WHERE \"ID\" = $nextID")->value();
}
}
}
/**
* Check if this is the currently viewed page.
*
* @return boolean True if this is the current page.
*/
public function isCurrent() {
$this->prepareCurrentAndSection();
return $this->ID == SiteTree::$currentPageID;
}
/**
* Check if the currently viewed page is in this section.
*
* @return boolean True if the currently viewed page is in this section.
*/
public function isSection() {
$this->prepareCurrentAndSection();
return in_array($this->ID, self::$currentSectionIDs);
}
/**
* Return a breadcrumb trail to this page. Excludes "hidden" pages
* (with ShowInMenus=0).

View File

@ -433,6 +433,49 @@ class SiteTreeTest extends SapphireTest {
$this->assertEquals('', $parser->parse('[sitetree_link]Example Content[/sitetree_link]'));
}
public function testIsCurrent() {
$aboutPage = $this->objFromFixture('Page', 'about');
$errorPage = $this->objFromFixture('ErrorPage', '404');
Director::set_current_page($aboutPage);
$this->assertTrue($aboutPage->isCurrent(), 'Assert that basic isSection checks works.');
$this->assertFalse($errorPage->isCurrent());
Director::set_current_page($errorPage);
$this->assertTrue($errorPage->isCurrent(), 'Assert isSection works on error pages.');
$this->assertFalse($aboutPage->isCurrent());
Director::set_current_page($aboutPage);
$this->assertTrue (
DataObject::get_one('SiteTree', '"Title" = \'About Us\'')->isCurrent(),
'Assert that isCurrent works on another instance with the same ID.'
);
Director::set_current_page($newPage = new SiteTree());
$this->assertTrue($newPage->isCurrent(), 'Assert that isCurrent works on unsaved pages.');
}
public function testIsSection() {
$about = $this->objFromFixture('Page', 'about');
$staff = $this->objFromFixture('Page', 'staff');
$ceo = $this->objFromFixture('Page', 'ceo');
Director::set_current_page($about);
$this->assertTrue($about->isSection());
$this->assertFalse($staff->isSection());
$this->assertFalse($ceo->isSection());
Director::set_current_page($staff);
$this->assertTrue($about->isSection());
$this->assertTrue($staff->isSection());
$this->assertFalse($ceo->isSection());
Director::set_current_page($ceo);
$this->assertTrue($about->isSection());
$this->assertTrue($staff->isSection());
$this->assertTrue($ceo->isSection());
}
}
// We make these extend page since that's what all page types are expected to do

3
tests/SiteTreeTest.yml Normal file → Executable file
View File

@ -35,6 +35,9 @@ Page:
Title: Staff
URLSegment: my-staff
Parent: =>Page.about
ceo:
Title: CEO
Parent: =>Page.staff
staffduplicate:
Title: Staff
URLSegment: my-staff