FEATURE: Refactored RootURLController to allow nested home pages.

MINOR: Deprecated RootURLController::get_homepage_urlsegment() in favour of get_homepage_link().
MINOR: Updated SiteTree->RelativeLink() to return a link to the site root for the home page.

From: Andrew Short <andrewjshort@gmail.com>

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@88496 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Andrew Short 2009-10-11 00:07:17 +00:00 committed by Sam Minnee
parent f29eceecff
commit ad7194cc40
6 changed files with 129 additions and 106 deletions

View File

@ -1,117 +1,109 @@
<?php
/**
* This controller handles what happens when you visit the root URL.
*
* @package sapphire
* @subpackage control
*/
class RootURLController extends Controller {
/**
* @var boolean $is_at_root
* @var bool
*/
protected static $is_at_root = false;
/**
* @var string $default_homepage_urlsegment Defines which URLSegment value on a {@link SiteTree} object
* is regarded as the correct "homepage" if the requested URI doesn't contain
* an explicit segment. E.g. http://mysite.com should show http://mysite.com/home.
* @var string
*/
protected static $default_homepage_urlsegment = 'home';
protected static $default_homepage_link = 'home';
public function handleRequest($request) {
self::$is_at_root = true;
$this->pushCurrent();
$this->init();
// If the basic database hasn't been created, then build it.
if(!DB::isActive() || !ClassInfo::hasTable('SiteTree')) {
$this->response = new HTTPResponse();
$this->redirect("dev/build?returnURL=");
return $this->response;
}
$controller = new ModelAsController();
$request = new HTTPRequest("GET", self::get_homepage_urlsegment().'/', $request->getVars(), $request->postVars());
$request->match('$URLSegment//$Action', true);
$result = $controller->handleRequest($request);
$this->popCurrent();
return $result;
}
/**
* Return the URL segment for the current HTTP_HOST value
*
* @param string $locale
* Get the full form (e.g. /home/) relative link to the home page for the current HTTP_HOST value. Note that the
* link is trimmed of leading and trailing slashes before returning to ensure consistency.
*
* @return string
*/
static function get_homepage_urlsegment() {
$urlSegment = '';
$homePageOBJ = null;
$host = $_SERVER['HTTP_HOST'];
$host = str_replace('www.','',$host);
public static function get_homepage_link() {
$host = str_replace('www.', null, $_SERVER['HTTP_HOST']);
$SQL_host = Convert::raw2sql($host);
$homePageOBJs = DataObject::get("SiteTree", "\"HomepageForDomain\" LIKE '%$SQL_host%'");
if($homePageOBJs) foreach($homePageOBJs as $candidateObj) {
if(preg_match('/(,|^) *' . preg_quote($host) . ' *(,|$)/', $candidateObj->HomepageForDomain)) {
$homePageOBJ = $candidateObj;
break;
$candidates = DataObject::get('SiteTree', "\"HomepageForDomain\" LIKE '%$SQL_host%'");
if($candidates) foreach($candidates as $candidate) {
if(preg_match('/(,|^) *' . preg_quote($host) . ' *(,|$)/', $candidate->HomepageForDomain)) {
return trim($candidate->RelativeLink(true), '/');
}
}
if(singleton('SiteTree')->hasExtension('Translatable') && !$homePageOBJ) {
$urlSegment = Translatable::get_homepage_urlsegment_by_locale(Translatable::get_current_locale());
} elseif($homePageOBJ) {
$urlSegment = $homePageOBJ->URLSegment;
if(Object::has_extension('SiteTree', 'Translatable')) {
if($link = Translatable::get_homepage_link_by_locale(Translatable::get_current_locale())) return $link;
}
return ($urlSegment) ? $urlSegment : self::get_default_homepage_urlsegment();
return self::get_default_homepage_link();
}
/**
* Returns true if we're currently on the root page and should be redirecting to the root
* Doesn't take into account actions, post vars, or get vars.
* Gets the link that denotes the homepage if there is not one explicitly defined for this HTTP_HOST value.
*
* @param SiteTree $currentPage
* @return boolean
* @return string
*/
static function should_be_on_root(SiteTree $currentPage) {
if(self::$is_at_root) return false;
if(!$currentPage->HomepageForDomain
&& $currentPage->URLSegment != self::get_default_homepage_urlsegment()) return false;
$matchesHomepageSegment = (self::get_homepage_urlsegment() == $currentPage->URLSegment);
// Don't redirect translated homepage segments,
// as the redirection target '/' will show the default locale
// instead of the translation.
$isTranslatedHomepage = (
singleton('SiteTree')->hasExtension('Translatable')
&& $currentPage->Locale
&& $currentPage->Locale != Translatable::default_locale()
);
if($matchesHomepageSegment && !$isTranslatedHomepage) return true;
public static function get_default_homepage_link() {
return self::$default_homepage_link;
}
/**
* Returns TRUE if a request to a certain page should be redirected to the site root (i.e. if the page acts as the
* home page).
*
* @param SiteTree $page
* @return bool
*/
public static function should_be_on_root(SiteTree $page) {
if(!self::$is_at_root && self::get_homepage_link() == trim($page->RelativeLink(true), '/')) {
return !(
$page->hasExtension('Translatable') && $page->Locale && $page->Locale != Translatable::default_locale()
);
}
return false;
}
/**
* Returns the (untranslated) hardcoded URL segment that will
* show when the website is accessed without a URL segment (http://mysite.com/).
* It is also the base for any redirections to '/' for the homepage,
* see {@link should_be_on_root()}.
*
* @return string
* @deprecated 2.4 Use {@link RootURLController::get_homepage_link()}
*/
static function get_default_homepage_urlsegment() {
return self::$default_homepage_urlsegment;
public static function get_homepage_urlsegment() {
user_error (
'RootURLController::get_homepage_urlsegment() is deprecated, please use get_homepage_link()', E_USER_NOTICE
);
return self::get_homepage_link();
}
/**
* @param HTTPRequest $request
* @return HTTPResponse
*/
public function handleRequest(HTTPRequest $request) {
self::$is_at_root = true;
$this->pushCurrent();
$this->init();
if(!DB::isActive() || !ClassInfo::hasTable('SiteTree')) {
$this->response = new HTTPResponse();
$this->response->redirect('dev/build/?returnURL=');
return $this->response;
}
$request = new HTTPRequest (
$request->httpMethod(), self::get_homepage_link() . '/', $request->getVars(), $request->postVars()
);
$request->match('$URLSegment//$Action', true);
$controller = new ModelAsController();
$result = $controller->handleRequest($request);
$this->popCurrent();
return $result;
}
}
?>

View File

@ -244,7 +244,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
if(trim($link, '/')) {
$link = trim(Director::makeRelative($link), '/');
} else {
$link = RootURLController::get_homepage_urlsegment();
$link = RootURLController::get_homepage_link();
}
$parts = Convert::raw2sql(preg_split('|/+|', $link));
@ -379,19 +379,32 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
/**
* Return the link for this {@link SiteTree} object relative to the SilverStripe root.
*
* By default, it this page is the current home page, and there is no action specified then this will return a link
* to the root of the site. However, if you set the $action parameter to TRUE then the link will not be rewritten
* and returned in its full form.
*
* @uses RootURLController::get_homepage_link()
* @param string $action
* @return string
*/
public function RelativeLink($action = null) {
$action = str_replace('&', '&amp;', $action);
if($this->ParentID && self::nested_urls()) {
$base = $this->Parent()->RelativeLink($this->URLSegment);
} else {
$base = $this->URLSegment;
}
return "$base/$action";
if(!$action && $base == RootURLController::get_homepage_link()) {
$base = null;
}
if(is_string($action)) {
$action = str_replace('&', '&amp;', $action);
} elseif($action === true) {
$action = null;
}
return Controller::join_links($base, '/', $action);
}
/**

View File

@ -1219,28 +1219,21 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
}
/**
* Gets a URLSegment value for a homepage in another language.
* The value is inferred by finding the homepage in default language
* (as identified by RootURLController::$default_homepage_urlsegment).
* Returns NULL if no translated page can be found.
*
* @param string $locale
* @return string|boolean URLSegment (e.g. "home")
* @todo
*/
public static function get_homepage_link_by_locale($locale) {
}
/**
* @deprecated 2.4 Use {@link Translatable::get_homepage_link_by_locale()}
*/
static function get_homepage_urlsegment_by_locale($locale) {
$origHomepageObj = Translatable::get_one_by_locale(
'SiteTree',
Translatable::default_locale(),
sprintf('"URLSegment" = \'%s\'', RootURLController::get_default_homepage_urlsegment())
user_error (
'Translatable::get_homepage_urlsegment_by_locale() is deprecated, please use get_homepage_link_by_locale()',
E_USER_NOTICE
);
if($origHomepageObj) {
$translatedHomepageObj = $origHomepageObj->getTranslation($locale);
if($translatedHomepageObj) {
return $translatedHomepageObj->URLSegment;
}
}
return null;
return self::get_homepage_link_by_locale($locale);
}
/**

24
tests/control/RootURLControllerTest.php Normal file → Executable file
View File

@ -39,11 +39,33 @@ class RootURLControllerTest extends SapphireTest {
$_SERVER['HTTP_HOST'] = $domain;
$this->assertEquals(
$urlSegment,
RootURLController::get_homepage_urlsegment(Translatable::default_locale()),
RootURLController::get_homepage_link(),
"Testing $domain matches $urlSegment"
);
}
$_SERVER['HTTP_HOST'] = $originalHost;
}
public function testGetHomepageLink() {
$default = $this->objFromFixture('Page', 'home');
$nested = $this->objFromFixture('Page', 'nested');
SiteTree::disable_nested_urls();
$this->assertEquals('home', RootURLController::get_homepage_link());
SiteTree::enable_nested_urls();
$this->assertEquals('home', RootURLController::get_homepage_link());
$nested->HomepageForDomain = str_replace('www.', null, $_SERVER['HTTP_HOST']);
$nested->write();
SiteTree::disable_nested_urls();
$this->assertEquals('nested-home', RootURLController::get_homepage_link());
SiteTree::enable_nested_urls();
$this->assertEquals('home/nested-home', RootURLController::get_homepage_link());
$nested->HomepageForDomain = null;
$nested->write();
}
}

3
tests/control/RootURLControllerTest.yml Normal file → Executable file
View File

@ -1,6 +1,9 @@
Page:
home:
Title: Home
nested:
Title: Nested Home
Parent: =>Page.home
page1:
Title: First Page
URLSegment: page1

4
tests/model/TranslatableTest.php Normal file → Executable file
View File

@ -652,7 +652,7 @@ class TranslatableTest extends FunctionalTest {
// test with translatable
Translatable::set_current_locale('de_DE');
$this->assertEquals(
RootURLController::get_homepage_urlsegment(),
RootURLController::get_homepage_link(),
'heim',
'Homepage with different URLSegment in non-default language is found'
);
@ -893,4 +893,4 @@ class TranslatableTest_Page extends Page implements TestOnly {
}
DataObject::add_extension('TranslatableTest_DataObject', 'TranslatableTest_Decorator');
?>
?>