mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
FEATURE: Implemented Translatable::get_homepage_link_by_locale() to enable translated home pages to function.
FEATURE: Updated SiteTree::get_by_link() to integrate with translatable, and allow it to work across languages by implementing Translatable->alternateGetByLink(). API CHANGE: Moved lang_filter enabling & disabling into static methods on Translatable, and renamed to locale_filter. BUGFIX: Fixed viewing a translatable page by URL without explicitly setting a Locale in ContentController->handleRequest(). From: Andrew Short <andrewjshort@gmail.com> git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@88503 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
80c8780b6f
commit
ea906a50a8
@ -169,25 +169,29 @@ class ContentController extends Controller {
|
|||||||
*/
|
*/
|
||||||
public function handleRequest(HTTPRequest $request) {
|
public function handleRequest(HTTPRequest $request) {
|
||||||
Director::set_current_page($this->data());
|
Director::set_current_page($this->data());
|
||||||
|
|
||||||
$response = parent::handleRequest($request);
|
$response = parent::handleRequest($request);
|
||||||
|
|
||||||
// If the default handler returns an error, due to the action not existing, attempt to fall over to a child
|
// If the default handler returns an error, due to the action not existing, attempt to fall over to a child
|
||||||
// SiteTree object, then use its corresponding ContentController to handle the request. This allows for the
|
// SiteTree object, then use its corresponding ContentController to handle the request. This allows for the
|
||||||
// building of nested chains of controllers corresponding to a nested URL.
|
// building of nested chains of controllers corresponding to a nested URL.
|
||||||
if(SiteTree::nested_urls() && $response instanceof HTTPResponse && $response->isError()) {
|
if(SiteTree::nested_urls() && $response instanceof HTTPResponse && $response->isError()) {
|
||||||
$SQL_URLParam = Convert::raw2sql($request->param('Action'));
|
Translatable::disable_locale_filter();
|
||||||
|
|
||||||
if($SQL_URLParam && $nextPage = DataObject::get_one('SiteTree', "\"ParentID\" = $this->ID AND \"URLSegment\" = '$SQL_URLParam'")) {
|
$child = DataObject::get_one('SiteTree', sprintf (
|
||||||
if($nextPage->canView()) {
|
"\"ParentID\" = %s AND \"URLSegment\" = '%s'",
|
||||||
$request->shiftAllParams();
|
$this->ID,
|
||||||
return ModelAsController::controller_for($nextPage)->handleRequest($request);
|
Convert::raw2sql($request->param('Action'))
|
||||||
}
|
));
|
||||||
|
|
||||||
|
Translatable::enable_locale_filter();
|
||||||
|
|
||||||
|
if($child && $child->canView()) {
|
||||||
|
$request->shiftAllParams();
|
||||||
|
return ModelAsController::controller_for($child)->handleRequest($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Director::set_current_page(null);
|
Director::set_current_page(null);
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,10 +69,14 @@ class ModelAsController extends Controller implements NestedController {
|
|||||||
throw new Exception('ModelAsController->getNestedController(): was not passed a URLSegment value.');
|
throw new Exception('ModelAsController->getNestedController(): was not passed a URLSegment value.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Translatable::disable_locale_filter();
|
||||||
|
|
||||||
$sitetree = DataObject::get_one('SiteTree', sprintf (
|
$sitetree = DataObject::get_one('SiteTree', sprintf (
|
||||||
'"URLSegment" = \'%s\' %s', Convert::raw2sql($URLSegment), (SiteTree::nested_urls() ? 'AND "ParentID" = 0' : null)
|
'"URLSegment" = \'%s\' %s', Convert::raw2sql($URLSegment), (SiteTree::nested_urls() ? 'AND "ParentID" = 0' : null)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
Translatable::enable_locale_filter();
|
||||||
|
|
||||||
if(!$sitetree) {
|
if(!$sitetree) {
|
||||||
// If a root page has been renamed, redirect to the new location.
|
// If a root page has been renamed, redirect to the new location.
|
||||||
if($redirect = $this->findOldPage($URLSegment)) {
|
if($redirect = $this->findOldPage($URLSegment)) {
|
||||||
|
@ -262,11 +262,13 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
|
|
||||||
// Attempt to grab an alternative page from decorators.
|
// Attempt to grab an alternative page from decorators.
|
||||||
if(!$sitetree) {
|
if(!$sitetree) {
|
||||||
if($alternatives = singleton('SiteTree')->extend('alternateGetByLink', $link, $filter, $cache, $order)) {
|
$parentID = self::nested_urls() ? 0 : null;
|
||||||
foreach($alternatives as $alternative) if($alternative) return $alternative;
|
|
||||||
|
if($alternatives = singleton('SiteTree')->extend('alternateGetByLink', $URLSegment, $parentID)) {
|
||||||
|
foreach($alternatives as $alternative) if($alternative) $sitetree = $alternative;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if(!$sitetree) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we have any more URL parts to parse.
|
// Check if we have any more URL parts to parse.
|
||||||
@ -279,11 +281,13 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
);
|
);
|
||||||
|
|
||||||
if(!$next) {
|
if(!$next) {
|
||||||
if($alternatives = singleton('SiteTree')->extend('alternateGetByLink', $link, $filter, $cache, $order)) {
|
$parentID = (int) $sitetree->ID;
|
||||||
foreach($alternatives as $alternative) if($alternative) return $alternative;
|
|
||||||
|
if($alternatives = singleton('SiteTree')->extend('alternateGetByLink', $segment, $parentID)) {
|
||||||
|
foreach($alternatives as $alternative) if($alternative) $next = $alternative;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if(!$next) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sitetree->destroy();
|
$sitetree->destroy();
|
||||||
|
@ -189,11 +189,13 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
|||||||
protected $original_values = null;
|
protected $original_values = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var boolean Temporarily override the "auto-filter" for {@link get_current_locale()}
|
* If this is set to TRUE then {@link augmentSQL()} will automatically add a filter
|
||||||
* in {@link augmentSQL()}. IMPORTANT: You must set this value back to TRUE
|
* clause to limit queries to the current {@link get_current_locale()}. This camn be
|
||||||
* after the temporary usage.
|
* disabled using {@link disable_locale_filter()}
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
*/
|
*/
|
||||||
protected static $enable_lang_filter = true;
|
protected static $locale_filter_enabled = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array All locales in which a translation can be created.
|
* @var array All locales in which a translation can be created.
|
||||||
@ -208,9 +210,9 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
|||||||
* Reset static configuration variables to their default values
|
* Reset static configuration variables to their default values
|
||||||
*/
|
*/
|
||||||
static function reset() {
|
static function reset() {
|
||||||
|
self::enable_locale_filter();
|
||||||
self::$default_locale = 'en_US';
|
self::$default_locale = 'en_US';
|
||||||
self::$current_locale = null;
|
self::$current_locale = null;
|
||||||
self::$enable_lang_filter = true;
|
|
||||||
self::$allowed_locales = null;
|
self::$allowed_locales = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +283,7 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
|||||||
* Set the reading language, either namespaced to 'site' (website content)
|
* Set the reading language, either namespaced to 'site' (website content)
|
||||||
* or 'cms' (management backend). This value is used in {@link augmentSQL()}
|
* or 'cms' (management backend). This value is used in {@link augmentSQL()}
|
||||||
* to "auto-filter" all SELECT queries by this language.
|
* to "auto-filter" all SELECT queries by this language.
|
||||||
* See {@link $enable_lang_filter} on how to override this behaviour temporarily.
|
* See {@link disable_locale_filter()} on how to override this behaviour temporarily.
|
||||||
*
|
*
|
||||||
* @param string $lang New reading language.
|
* @param string $lang New reading language.
|
||||||
*/
|
*/
|
||||||
@ -327,6 +329,29 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function locale_filter_enabled() {
|
||||||
|
return self::$locale_filter_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables automatic filtering by locale. This is normally called after is has been
|
||||||
|
* disabled using {@link disable_locale_filter()}.
|
||||||
|
*/
|
||||||
|
public static function enable_locale_filter() {
|
||||||
|
self::$locale_filter_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables automatic locale filtering in {@link augmentSQL()}. This can be re-enabled
|
||||||
|
* using {@link enable_locale_filter()}.
|
||||||
|
*/
|
||||||
|
public static function disable_locale_filter() {
|
||||||
|
self::$locale_filter_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all translations for this specific page.
|
* Gets all translations for this specific page.
|
||||||
* Doesn't include the language of the current record.
|
* Doesn't include the language of the current record.
|
||||||
@ -491,7 +516,7 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
|||||||
* It falls back to "Locale='' OR Lang IS NULL" and assumes that
|
* It falls back to "Locale='' OR Lang IS NULL" and assumes that
|
||||||
* this implies querying for the default language.
|
* this implies querying for the default language.
|
||||||
*
|
*
|
||||||
* Use {@link $enable_lang_filter} to temporarily disable this "auto-filtering".
|
* Use {@link disable_locale_filter()} to temporarily disable this "auto-filtering".
|
||||||
*/
|
*/
|
||||||
function augmentSQL(SQLQuery &$query) {
|
function augmentSQL(SQLQuery &$query) {
|
||||||
// If the record is saved (and not a singleton), and has a locale,
|
// If the record is saved (and not a singleton), and has a locale,
|
||||||
@ -503,7 +528,7 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
|||||||
if(
|
if(
|
||||||
$locale
|
$locale
|
||||||
// unless the filter has been temporarily disabled
|
// unless the filter has been temporarily disabled
|
||||||
&& self::$enable_lang_filter
|
&& self::locale_filter_enabled()
|
||||||
// DataObject::get_by_id() should work independently of language
|
// DataObject::get_by_id() should work independently of language
|
||||||
&& !$query->filtersOnID()
|
&& !$query->filtersOnID()
|
||||||
// the query contains this table
|
// the query contains this table
|
||||||
@ -786,25 +811,38 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter specifically for {@link SiteTree} subclasses
|
* Attempt to get the page for a link in the default language that has been translated.
|
||||||
* which is hooked in to {@link SiteTree::get_by_url()}.
|
|
||||||
* Disables translatable to get the page independently
|
|
||||||
* of the current language setting.
|
|
||||||
*
|
*
|
||||||
* @param string $urlSegment
|
* @param string $URLSegment
|
||||||
* @param string $extraFilter
|
* @param int|null $parentID
|
||||||
* @param boolean $cache
|
* @return SiteTree
|
||||||
* @param string|array $orderby
|
|
||||||
* @return DataObject
|
|
||||||
*/
|
*/
|
||||||
function alternateGetByUrl($urlSegment, $extraFilter, $cache = null, $orderby = null) {
|
public function alternateGetByLink($URLSegment, $parentID) {
|
||||||
$filter = sprintf("\"SiteTree\".\"URLSegment\" = '%s'", Convert::raw2sql($urlSegment));
|
// If the parentID value has come from a translated page, then we need to find the corresponding parentID value
|
||||||
if($extraFilter) $filter .= " AND $extraFilter";
|
// in the default Locale.
|
||||||
self::$enable_lang_filter = false;
|
if (
|
||||||
$record = DataObject::get_one('SiteTree', $filter);
|
is_int($parentID)
|
||||||
self::$enable_lang_filter = true;
|
&& $parentID > 0
|
||||||
|
&& ($parent = DataObject::get_by_id('SiteTree', $parentID))
|
||||||
|
&& ($parent->isTranslation())
|
||||||
|
) {
|
||||||
|
$parentID = $parent->getTranslationGroup();
|
||||||
|
}
|
||||||
|
|
||||||
return $record;
|
// Find the locale language-independent of the page
|
||||||
|
self::disable_locale_filter();
|
||||||
|
$default = DataObject::get_one (
|
||||||
|
'SiteTree',
|
||||||
|
sprintf (
|
||||||
|
'"URLSegment" = \'%s\'%s',
|
||||||
|
Convert::raw2sql($URLSegment),
|
||||||
|
(is_int($parentID) ? " AND \"ParentID\" = $parentID" : null)
|
||||||
|
),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
self::enable_locale_filter();
|
||||||
|
|
||||||
|
return $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------------//
|
//-----------------------------------------------------------------------------------------------//
|
||||||
@ -985,7 +1023,7 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
|||||||
if($this->owner->exists()) {
|
if($this->owner->exists()) {
|
||||||
// HACK need to disable language filtering in augmentSQL(),
|
// HACK need to disable language filtering in augmentSQL(),
|
||||||
// as we purposely want to get different language
|
// as we purposely want to get different language
|
||||||
self::$enable_lang_filter = false;
|
self::disable_locale_filter();
|
||||||
|
|
||||||
$translationGroupID = $this->getTranslationGroup();
|
$translationGroupID = $this->getTranslationGroup();
|
||||||
|
|
||||||
@ -1017,7 +1055,7 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
|||||||
$translations = DataObject::get($this->owner->class, $filter, null, $join);
|
$translations = DataObject::get($this->owner->class, $filter, null, $join);
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$enable_lang_filter = true;
|
self::enable_locale_filter();
|
||||||
|
|
||||||
return $translations;
|
return $translations;
|
||||||
}
|
}
|
||||||
@ -1219,9 +1257,21 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo
|
* Get the RelativeLink value for a home page in another locale. This is found by searching for the default home
|
||||||
|
* page in the default language, then returning the link to the translated version (if one exists).
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function get_homepage_link_by_locale($locale) {
|
public static function get_homepage_link_by_locale($locale) {
|
||||||
|
$originalLocale = self::get_current_locale();
|
||||||
|
|
||||||
|
self::set_current_locale(self::default_locale());
|
||||||
|
$original = SiteTree::get_by_link(RootURLController::get_default_homepage_link());
|
||||||
|
self::set_current_locale($originalLocale);
|
||||||
|
|
||||||
|
if($original) {
|
||||||
|
if($translation = $original->getTranslation($locale)) return trim($translation->RelativeLink(true), '/');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -641,7 +641,7 @@ class TranslatableTest extends FunctionalTest {
|
|||||||
Translatable::set_current_locale('en_US');
|
Translatable::set_current_locale('en_US');
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRootUrlDefaultsToTranslatedUrlSegment() {
|
function testRootUrlDefaultsToTranslatedLink() {
|
||||||
$origPage = $this->objFromFixture('Page', 'homepage_en');
|
$origPage = $this->objFromFixture('Page', 'homepage_en');
|
||||||
$origPage->publish('Stage', 'Live');
|
$origPage->publish('Stage', 'Live');
|
||||||
$translationDe = $origPage->createTranslation('de_DE');
|
$translationDe = $origPage->createTranslation('de_DE');
|
||||||
@ -844,22 +844,64 @@ class TranslatableTest extends FunctionalTest {
|
|||||||
Translatable::set_current_locale($origLocale);
|
Translatable::set_current_locale($origLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSiteTreeGetByUrlFindsTranslationWithoutLocale() {
|
public function testAlternateGetByLink() {
|
||||||
|
$parent = $this->objFromFixture('Page', 'parent');
|
||||||
|
$child = $this->objFromFixture('Page', 'child1');
|
||||||
|
$grandchild = $this->objFromFixture('Page', 'grandchild1');
|
||||||
|
|
||||||
|
$parentTranslation = $parent->createTranslation('en_AU');
|
||||||
|
$parentTranslation->write();
|
||||||
|
|
||||||
|
$childTranslation = $child->createTranslation('en_AU');
|
||||||
|
$childTranslation->write();
|
||||||
|
|
||||||
|
$grandchildTranslation = $grandchild->createTranslation('en_AU');
|
||||||
|
$grandchildTranslation->write();
|
||||||
|
|
||||||
|
SiteTree::enable_nested_urls();
|
||||||
|
Translatable::set_current_locale('en_AU');
|
||||||
|
|
||||||
|
$this->assertEquals (
|
||||||
|
$parentTranslation->ID,
|
||||||
|
Sitetree::get_by_link($parentTranslation->Link())->ID,
|
||||||
|
'Top level pages can be found.'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals (
|
||||||
|
$childTranslation->ID,
|
||||||
|
SiteTree::get_by_link($childTranslation->Link())->ID,
|
||||||
|
'Child pages can be found.'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals (
|
||||||
|
$grandchildTranslation->ID,
|
||||||
|
SiteTree::get_by_link($grandchildTranslation->Link())->ID,
|
||||||
|
'Grandchild pages can be found.'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals (
|
||||||
|
$childTranslation->ID,
|
||||||
|
SiteTree::get_by_link($parentTranslation->Link($child->URLSegment))->ID,
|
||||||
|
'Links can be made up of multiple languages'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSiteTreeGetByLinkFindsTranslationWithoutLocale() {
|
||||||
$parent = $this->objFromFixture('Page', 'parent');
|
$parent = $this->objFromFixture('Page', 'parent');
|
||||||
|
|
||||||
$parentTranslation = $parent->createTranslation('en_AU');
|
$parentTranslation = $parent->createTranslation('en_AU');
|
||||||
$parentTranslation->URLSegment = 'parent-en-AU';
|
$parentTranslation->URLSegment = 'parent-en-AU';
|
||||||
$parentTranslation->write();
|
$parentTranslation->write();
|
||||||
|
|
||||||
$match = Sitetree::get_by_url($parentTranslation->URLSegment);
|
$match = Sitetree::get_by_link($parentTranslation->URLSegment);
|
||||||
$this->assertNotNull(
|
$this->assertNotNull(
|
||||||
$match,
|
$match,
|
||||||
'SiteTree::get_by_url() doesnt need a locale setting to find translated pages'
|
'SiteTree::get_by_link() doesnt need a locale setting to find translated pages'
|
||||||
);
|
);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
$parentTranslation->ID,
|
$parentTranslation->ID,
|
||||||
$match->ID,
|
$match->ID,
|
||||||
'SiteTree::get_by_url() doesnt need a locale setting to find translated pages'
|
'SiteTree::get_by_link() doesnt need a locale setting to find translated pages'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user