mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
FEATURE Allowing translation of SiteConfig (including toplevel permission groups)
BUGFIX Fixed SiteConfig->canView()/canEdit() to respect empty CanViewType/CanEditType assignments. git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.4@97370 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
e08667ead5
commit
3e8526960b
@ -1,7 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Sitewide configuration
|
||||
* Sitewide configuration.
|
||||
*
|
||||
* h2. Translation
|
||||
*
|
||||
* To enable translation of configurations alongside the {@link Translatable} extension.
|
||||
* This also allows assigning language-specific toplevel permissions for viewing and editing
|
||||
* pages, in addition to the normal `TRANSLATE_*`/`TRANSLATE_ALL` permissions.
|
||||
*
|
||||
* Object::add_extension('SiteConig', 'Translatable');
|
||||
*
|
||||
* @author Tom Rix
|
||||
* @package cms
|
||||
@ -60,6 +67,13 @@ class SiteConfig extends DataObject {
|
||||
$editorsOptionsField->setSource($editorsOptionsSource);
|
||||
|
||||
$topLevelCreatorsOptionsField->setSource($editorsOptionsSource);
|
||||
|
||||
// Translatable doesn't handle updateCMSFields on DataObjects,
|
||||
// so add it here to save the current Locale,
|
||||
// because onBeforeWrite does not work.
|
||||
if(Object::has_extension('SiteConfig',"Translatable")){
|
||||
$fields->push(new HiddenField("Locale"));
|
||||
}
|
||||
|
||||
if (!Permission::check('EDIT_SITECONFIG')) {
|
||||
$fields->makeFieldReadonly($viewersOptionsField);
|
||||
@ -96,16 +110,22 @@ class SiteConfig extends DataObject {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current sites SiteConfig
|
||||
* Get the current sites SiteConfig, and creates a new one
|
||||
* through {@link make_site_config()} if none is found.
|
||||
*
|
||||
* @param string $locale
|
||||
* @return SiteConfig
|
||||
*/
|
||||
static function current_site_config() {
|
||||
$siteConfig = DataObject::get_one('SiteConfig');
|
||||
if (!$siteConfig) {
|
||||
self::make_site_config();
|
||||
static function current_site_config($locale = null) {
|
||||
if(Object::has_extension('SiteConfig',"Translatable")){
|
||||
$locale = isset($locale) ? $locale : Translatable::get_current_locale();
|
||||
$siteConfig = Translatable::get_one_by_locale('SiteConfig', $locale);
|
||||
} else {
|
||||
$siteConfig = DataObject::get_one('SiteConfig');
|
||||
}
|
||||
|
||||
if (!$siteConfig) $siteConfig = self::make_site_config($locale);
|
||||
|
||||
return $siteConfig;
|
||||
}
|
||||
|
||||
@ -122,18 +142,37 @@ class SiteConfig extends DataObject {
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a default site config if there isn't on already
|
||||
*
|
||||
* @return void
|
||||
* Create SiteConfig with defaults from language file.
|
||||
* if Translatable is enabled on SiteConfig, see if one already exist
|
||||
* and use those values for the translated defaults.
|
||||
*
|
||||
* @param string $locale
|
||||
* @return SiteConfig
|
||||
*/
|
||||
static function make_site_config() {
|
||||
if(!DataObject::get_one('SiteConfig')){
|
||||
$siteConfig = new SiteConfig();
|
||||
$siteConfig->Title = 'Your Site Name';
|
||||
$siteConfig->Tagline = 'your tagline here';
|
||||
$siteConfig->write();
|
||||
static function make_site_config($locale = null) {
|
||||
if(!$locale) $locale = Translatable::get_current_locale();
|
||||
|
||||
$siteConfig = new SiteConfig();
|
||||
$siteConfig->Title = _t('SiteConfig.SITENAMEDEFAULT',"Your Site Name");
|
||||
$siteConfig->Tagline = _t('SiteConfig.TAGLINEDEFAULT',"your tagline here");
|
||||
|
||||
if($siteConfig->hasExtension('Translatable')){
|
||||
$defaultConfig = DataObject::get_one('SiteConfig');
|
||||
if($defaultConfig){
|
||||
$siteConfig->Title = $defaultConfig->Title;
|
||||
$siteConfig->Tagline = $defaultConfig->Tagline;
|
||||
}
|
||||
|
||||
// TODO Copy view/edit group settings
|
||||
|
||||
// set the correct Locale
|
||||
$siteConfig->Locale = $locale;
|
||||
}
|
||||
}
|
||||
|
||||
$siteConfig->write();
|
||||
|
||||
return $siteConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can a user view pages on this site? This method is only
|
||||
@ -144,17 +183,15 @@ class SiteConfig extends DataObject {
|
||||
* @return boolean
|
||||
*/
|
||||
public function canView($member = null) {
|
||||
if ($this->CanViewType == 'Anyone') return true;
|
||||
|
||||
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
|
||||
$member = Member::currentUserID();
|
||||
}
|
||||
if(!$member) $member = Member::currentUserID();
|
||||
if($member && is_numeric($member)) $member = DataObject::get_by_id('Member', $member);
|
||||
|
||||
if (!$this->CanViewType || $this->CanViewType == 'Anyone') return true;
|
||||
|
||||
// check for any logged-in users
|
||||
if($this->CanViewType == 'LoggedInUsers' && $member) return true;
|
||||
|
||||
|
||||
// check for specific groups
|
||||
if($member && is_numeric($member)) $member = DataObject::get_by_id('Member', $member);
|
||||
if($this->CanViewType == 'OnlyTheseUsers' && $member && $member->inGroups($this->ViewerGroups())) return true;
|
||||
|
||||
return false;
|
||||
@ -169,18 +206,15 @@ class SiteConfig extends DataObject {
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = null) {
|
||||
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
|
||||
$member = Member::currentUserID();
|
||||
}
|
||||
if(!$member) $member = Member::currentUserID();
|
||||
if($member && is_numeric($member)) $member = DataObject::get_by_id('Member', $member);
|
||||
|
||||
// check for any logged-in users
|
||||
if($this->CanEditType == 'LoggedInUsers' && $member) return true;
|
||||
|
||||
if(!$this->CanEditType || $this->CanEditType == 'LoggedInUsers' && $member) return true;
|
||||
|
||||
// check for specific groups
|
||||
if($member && is_numeric($member)) $member = DataObject::get_by_id('Member', $member);
|
||||
if($this->CanEditType == 'OnlyTheseUsers' && $member && $member->inGroups($this->EditorGroups())) return true;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -734,7 +734,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
// check for inherit
|
||||
if($this->CanViewType == 'Inherit') {
|
||||
if($this->ParentID) return $this->Parent()->canView($member);
|
||||
else return SiteConfig::current_site_config()->canView($member);
|
||||
else return $this->getSiteConfig()->canView($member);
|
||||
}
|
||||
|
||||
// check for any logged-in users
|
||||
@ -857,7 +857,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
// decorated access checks
|
||||
$results = $this->extend('canEdit', $memberID);
|
||||
if($results && is_array($results)) if(!min($results)) return false;
|
||||
|
||||
|
||||
if($this->ID) {
|
||||
// Check cache (the can_edit_multiple call below will also do this, but this is quicker)
|
||||
if(isset(self::$cache_permissions['edit'][$this->ID])) {
|
||||
@ -866,14 +866,14 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
|
||||
// Regular canEdit logic is handled by can_edit_multiple
|
||||
$results = self::can_edit_multiple(array($this->ID), $memberID);
|
||||
|
||||
|
||||
// If this page no longer exists in stage/live results won't contain the page.
|
||||
// Fail-over to false
|
||||
return isset($results[$this->ID]) ? $results[$this->ID] : false;
|
||||
|
||||
// Default for unsaved pages
|
||||
} else {
|
||||
return $this->SiteConfig->canEdit();
|
||||
return $this->getSiteConfig()->canEdit($member);
|
||||
}
|
||||
}
|
||||
|
||||
@ -918,8 +918,13 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
* Stub method to get the site config, provided so it's easy to override
|
||||
*/
|
||||
function getSiteConfig() {
|
||||
if ($this->hasMethod('alternateSiteConfig')) return $this->alternateSiteConfig();
|
||||
return SiteConfig::current_site_config();
|
||||
if ($this->hasMethod('alternateSiteConfig')) {
|
||||
return $this->alternateSiteConfig();
|
||||
} elseif($this->hasExtension('Translatable')) {
|
||||
return SiteConfig::current_site_config($this->Locale);
|
||||
} else {
|
||||
return SiteConfig::current_site_config();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,6 +76,12 @@
|
||||
* <h2>Usage for SiteTree</h2>
|
||||
*
|
||||
* Translatable can be used for subclasses of {@link SiteTree} as well.
|
||||
*
|
||||
* <code>
|
||||
* Object::add_extension('SiteTree', 'Translatable');
|
||||
* Object::add_extension('SiteConig', 'Translatable');
|
||||
* </code>
|
||||
*
|
||||
* If a child page translation is requested without the parent
|
||||
* page already having a translation in this language, the extension
|
||||
* will recursively create translations up the tree.
|
||||
@ -1167,7 +1173,6 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
||||
*/
|
||||
function canEdit($member) {
|
||||
if(!$this->owner->Locale) return true;
|
||||
|
||||
return $this->owner->canTranslate($member, $this->owner->Locale);
|
||||
}
|
||||
|
||||
@ -1219,6 +1224,11 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
|
||||
|
||||
$locales = self::get_allowed_locales();
|
||||
|
||||
// Fall back to any locales used in existing translations (see #4939)
|
||||
if(!$locales) {
|
||||
$locales = DB::query('SELECT "Locale" FROM "SiteTree" GROUP BY "Locale"')->column();
|
||||
}
|
||||
|
||||
$permissions = array();
|
||||
if($locales) foreach($locales as $locale) {
|
||||
$localeName = i18n::get_locale_name($locale);
|
||||
|
@ -663,6 +663,12 @@ $lang['en_US']['SiteConfig']['SINGULARNAME'] = array(
|
||||
50,
|
||||
'Singular name of the object, used in dropdowns and to generally identify a single object in the interface'
|
||||
);
|
||||
$lang['en_US']['SiteConfig']['SITENAMEDEFAULT'] = 'Your Site Name';
|
||||
$lang['en_US']['SiteConfig']['SITETAGLINE'] = 'Site Tagline/Slogan';
|
||||
$lang['en_US']['SiteConfig']['SITETITLE'] = 'Site title';
|
||||
$lang['en_US']['SiteConfig']['TAGLINEDEFAULT'] = 'your tagline here';
|
||||
$lang['en_US']['SiteConfig']['TOPLEVELCREATE'] = 'Who can create pages in the root of the site?';
|
||||
$lang['en_US']['SiteConfig']['VIEWHEADER'] = 'Who can view pages on this site?';
|
||||
$lang['en_US']['SiteTree']['ACCESSANYONE'] = 'Anyone';
|
||||
$lang['en_US']['SiteTree']['ACCESSHEADER'] = 'Who can view this page?';
|
||||
$lang['en_US']['SiteTree']['ACCESSLOGGEDIN'] = 'Logged-in users';
|
||||
@ -764,6 +770,7 @@ $lang['en_US']['SiteTree']['TABMETA'] = 'Metadata';
|
||||
$lang['en_US']['SiteTree']['TABREPORTS'] = 'Reports';
|
||||
$lang['en_US']['SiteTree']['TODOHELP'] = '<p>You can use this to keep track of work that needs to be done to the content of your site. To see all your pages with to do information, open the \'Site Reports\' window on the left and select \'To Do\'</p>';
|
||||
$lang['en_US']['SiteTree']['TOPLEVEL'] = 'Site Content (Top Level)';
|
||||
$lang['en_US']['SiteTree']['TOPLEVELCREATORGROUPS'] = 'Top level creators';
|
||||
$lang['en_US']['SiteTree']['ToDo'] = 'Todo Notes';
|
||||
$lang['en_US']['SiteTree']['URL'] = 'URL';
|
||||
$lang['en_US']['SiteTree']['URLSegment'] = array(
|
||||
|
58
tests/model/SiteConfigTest.php
Normal file
58
tests/model/SiteConfigTest.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* @package sapphire
|
||||
* @subpackage tests
|
||||
*
|
||||
* Note: Most of the permission-related SiteConfig tests are located in
|
||||
* SiteTreePermissionsTest
|
||||
*/
|
||||
class SiteConfigTest extends SapphireTest {
|
||||
|
||||
static $fixture_file = 'sapphire/tests/model/SiteConfigTest.yml';
|
||||
|
||||
protected $requiredExtensions = array(
|
||||
'SiteTree' => array('Translatable'),
|
||||
'SiteConfig' => array('Translatable'),
|
||||
);
|
||||
|
||||
private $origLocale;
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->origLocale = Translatable::default_locale();
|
||||
Translatable::set_default_locale("en_US");
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
Translatable::set_default_locale($this->origLocale);
|
||||
Translatable::set_current_locale($this->origLocale);
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
function testCurrentCreatesDefaultForLocale() {
|
||||
$configEn = SiteConfig::current_site_config();
|
||||
$configFr = SiteConfig::current_site_config('fr_FR');
|
||||
|
||||
$this->assertType('SiteConfig', $configFr);
|
||||
$this->assertEquals($configFr->Locale, 'fr_FR');
|
||||
$this->assertEquals($configFr->Title, $configEn->Title, 'Copies title from existing config');
|
||||
}
|
||||
|
||||
function testCanEditTranslatedRootPages() {
|
||||
$configEn = $this->objFromFixture('SiteConfig', 'en_US');
|
||||
$configDe = $this->objFromFixture('SiteConfig', 'de_DE');
|
||||
|
||||
$pageEn = $this->objFromFixture('Page', 'root_en');
|
||||
$pageDe = $pageEn->createTranslation('de_DE');
|
||||
|
||||
$translatorDe = $this->objFromFixture('Member', 'translator_de');
|
||||
$translatorEn = $this->objFromFixture('Member', 'translator_en');
|
||||
|
||||
$this->assertFalse($pageEn->canEdit($translatorDe));
|
||||
$this->assertTrue($pageEn->canEdit($translatorEn));
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
86
tests/model/SiteConfigTest.yml
Normal file
86
tests/model/SiteConfigTest.yml
Normal file
@ -0,0 +1,86 @@
|
||||
Permission:
|
||||
cmsmain1:
|
||||
Code: CMS_ACCESS_CMSMain
|
||||
cmsmain2:
|
||||
Code: CMS_ACCESS_CMSMain
|
||||
translate_all1:
|
||||
Code: TRANSLATE_ALL
|
||||
translate_all2:
|
||||
Code: TRANSLATE_ALL
|
||||
Group:
|
||||
translators_de:
|
||||
Code: translators_de
|
||||
Permissions: =>Permission.cmsmain1,=>Permission.translate_all1
|
||||
translators_en:
|
||||
Code: translators_en
|
||||
Permissions: =>Permission.cmsmain2,=>Permission.translate_all2
|
||||
Member:
|
||||
translator_de:
|
||||
Email: translator_de@test.com
|
||||
Password: test
|
||||
Groups: =>Group.translators_de
|
||||
translator_en:
|
||||
Email: translator_en@test.com
|
||||
Password: test
|
||||
Groups: =>Group.translators_en
|
||||
websiteuser:
|
||||
Email: websiteuser@test.com
|
||||
Password: test
|
||||
Page:
|
||||
root_en:
|
||||
URLSegment: root-en
|
||||
Locale: en_US
|
||||
SiteConfig:
|
||||
en_US:
|
||||
Title: My test site
|
||||
Locale: en_US
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.translators_en
|
||||
de_DE:
|
||||
Title: Meine Test Seite
|
||||
Locale: de_DE
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.translators_de
|
||||
Permission:
|
||||
cmsmain1:
|
||||
Code: CMS_ACCESS_CMSMain
|
||||
cmsmain2:
|
||||
Code: CMS_ACCESS_CMSMain
|
||||
translate_all1:
|
||||
Code: TRANSLATE_ALL
|
||||
translate_all2:
|
||||
Code: TRANSLATE_ALL
|
||||
Group:
|
||||
translators_de:
|
||||
Code: translators_de
|
||||
Permissions: =>Permission.cmsmain1,=>Permission.translate_all1
|
||||
translators_en:
|
||||
Code: translators_en
|
||||
Permissions: =>Permission.cmsmain2,=>Permission.translate_all2
|
||||
Member:
|
||||
translator_de:
|
||||
Email: translator_de@test.com
|
||||
Password: test
|
||||
Groups: =>Group.translators_de
|
||||
translator_en:
|
||||
Email: translator_en@test.com
|
||||
Password: test
|
||||
Groups: =>Group.translators_en
|
||||
websiteuser:
|
||||
Email: websiteuser@test.com
|
||||
Password: test
|
||||
Page:
|
||||
root_en:
|
||||
URLSegment: root-en
|
||||
Locale: en_US
|
||||
SiteConfig:
|
||||
en_US:
|
||||
Title: My test site
|
||||
Locale: en_US
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.translators_en
|
||||
de_DE:
|
||||
Title: Meine Test Seite
|
||||
Locale: de_DE
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.translators_de
|
Loading…
Reference in New Issue
Block a user