Skip to content
Browse files

FEATURE Allowing translation of SiteConfig (including toplevel permis…

…sion groups)

BUGFIX Fixed SiteConfig->canView()/canEdit() to respect empty CanViewType/CanEditType assignments. (from r97370)

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@102445 467b73ca-7a2a-4603-9d3b-597d59a354a9
  • Loading branch information...
1 parent a6362eb commit 1039cfade4fed6123d68d50a40fd5f6985926568 @chillu chillu committed
Showing with 238 additions and 38 deletions.
  1. +65 −31 core/model/SiteConfig.php
  2. +11 −6 core/model/SiteTree.php
  3. +11 −1 core/model/Translatable.php
  4. +7 −0 lang/en_US.php
  5. +58 −0 tests/model/SiteConfigTest.php
  6. +86 −0 tests/model/SiteConfigTest.yml
View
96 core/model/SiteConfig.php
@@ -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 @@ function getFormFields() {
$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 @@ function getFormActions() {
}
/**
- * 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 @@ function requireDefaultRecords() {
}
/**
- * 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 @@ static function make_site_config() {
* @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 @@ public function canView($member = null) {
* @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;
}
View
17 core/model/SiteTree.php
@@ -732,7 +732,7 @@ public function canView($member = null) {
// 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
@@ -877,7 +877,7 @@ public function canEdit($member = null) {
// 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])) {
@@ -886,14 +886,14 @@ public function canEdit($member = null) {
// 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);
}
}
@@ -938,8 +938,13 @@ public function canDeleteFromLive($member = null) {
* 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();
+ }
}
View
12 core/model/Translatable.php
@@ -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.
@@ -1174,7 +1180,6 @@ function canTranslate($member = null, $locale) {
*/
function canEdit($member) {
if(!$this->owner->Locale) return true;
-
return $this->owner->canTranslate($member, $this->owner->Locale);
}
@@ -1226,6 +1231,11 @@ function providePermissions() {
$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);
View
7 lang/en_US.php
@@ -665,6 +665,12 @@
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';
@@ -766,6 +772,7 @@
$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(
View
58 tests/model/SiteConfigTest.php
@@ -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));
+ }
+
+}
+?>
View
86 tests/model/SiteConfigTest.yml
@@ -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

0 comments on commit 1039cfa

Please sign in to comment.
Something went wrong with that request. Please try again.