FEATURE Blacklisting of page types by subsite through Subsite->PageTypeBlacklist (AIR-20)

This commit is contained in:
Ingo Schommer 2011-08-30 18:58:36 +02:00
parent 33a9b90953
commit 17dde8ff58
4 changed files with 117 additions and 5 deletions

View File

@ -397,6 +397,18 @@ class SiteTreeSubsites extends SiteTreeDecorator {
function cacheKeyComponent() {
return 'subsite-'.Subsite::currentSubsiteID();
}
}
?>
/**
* @param Member
* @return boolean|null
*/
function canCreate($member = null) {
// Typically called on a singleton, so we're not using the Subsite() relation
$subsite = Subsite::currentSubsite();
if($subsite && $subsite->exists() && $subsite->PageTypeBlacklist) {
$blacklisted = explode(',', $subsite->PageTypeBlacklist);
// All subclasses need to be listed explicitly
if(in_array($this->owner->class, $blacklisted)) return false;
}
}
}

View File

@ -31,7 +31,10 @@ class Subsite extends DataObject implements PermissionProvider {
// Used to hide unfinished/private subsites from public view.
// If unset, will default to true
'IsPublic' => 'Boolean'
'IsPublic' => 'Boolean',
// Comma-separated list of disallowed page types
'PageTypeBlacklist' => 'Text',
);
static $has_one = array(
@ -164,6 +167,13 @@ class Subsite extends DataObject implements PermissionProvider {
"SubsiteID", $this->ID);
$languageSelector = new DropdownField('Language', 'Language', i18n::get_common_locales());
$pageTypeMap = array();
$pageTypes = SiteTree::page_type_classes();
foreach($pageTypes as $pageType) {
$pageTypeMap[$pageType] = singleton($pageType)->i18n_singular_name();
}
asort($pageTypeMap);
$fields = new FieldSet(
new TabSet('Root',
@ -178,7 +188,21 @@ class Subsite extends DataObject implements PermissionProvider {
new CheckboxField('DefaultSite', 'Default site', $this->DefaultSite),
new CheckboxField('IsPublic', 'Enable public access', $this->IsPublic),
new DropdownField('Theme','Theme', $this->allowedThemes(), $this->Theme)
new DropdownField('Theme','Theme', $this->allowedThemes(), $this->Theme),
new LiteralField(
'PageTypeBlacklistToggle',
sprintf(
'<div class="field"><a href="#" id="PageTypeBlacklistToggle">%s</a></div>',
_t('Subsite.PageTypeBlacklistField', 'Disallow page types?')
)
),
new CheckboxSetField(
'PageTypeBlacklist',
false,
$pageTypeMap
)
)
),
new HiddenField('ID', '', $this->ID),

View File

@ -78,6 +78,24 @@ Behaviour.register({
$('Form_EditForm_Subsites').parentNode.style.display =
Form.Element.getValue($('Form_EditForm').AccessAllSubsites)==1 ? 'none' : '';
}
},
/**
* Binding a visibility toggle anchor to a longer list of checkboxes.
* Hidden by default, unless either the toggle checkbox, or any of the
* actual value checkboxes are selected.
*/
'a#PageTypeBlacklistToggle': {
onclick: function(e) {
jQuery('#PageTypeBlacklist').toggle();
}
},
'#PageTypeBlacklist': {
initialize: function() {
var hasLimits = Boolean(jQuery(this).find('input:checked').length);
jQuery(this).toggle(hasLimits);
}
}
});

View File

@ -1,8 +1,14 @@
<?php
class SiteTreeSubsitesTest extends SapphireTest {
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
protected $extraDataObjects = array(
'SiteTreeSubsitesTest_ClassA',
'SiteTreeSubsitesTest_ClassB'
);
function testPagesInDifferentSubsitesCanShareURLSegment() {
$subsiteMain = $this->objFromFixture('Subsite_Template', 'main');
$subsite1 = $this->objFromFixture('Subsite_Template', 'subsite1');
@ -160,4 +166,56 @@ class SiteTreeSubsitesTest extends SapphireTest {
$this->assertEquals($p2->ID, SiteTree::get_by_link('test-page')->ID);
}
function testPageTypesBlacklistInClassDropdown() {
Session::set("loggedInAs", null);
$s1 = $this->objFromFixture('Subsite','domaintest1');
$s2 = $this->objFromFixture('Subsite','domaintest2');
$page = singleton('SiteTree');
$method = new ReflectionMethod($page, 'getClassDropdown');
$method->setAccessible(true);
$s1->PageTypeBlacklist = 'SiteTreeSubsitesTest_ClassA,ErrorPage';
$s1->write();
Subsite::changeSubsite($s1);
$this->assertArrayNotHasKey('ErrorPage', $method->invoke($page));
$this->assertArrayNotHasKey('SiteTreeSubsitesTest_ClassA', $method->invoke($page));
$this->assertArrayHasKey('SiteTreeSubsitesTest_ClassB', $method->invoke($page));
Subsite::changeSubsite($s2);
$this->assertArrayHasKey('ErrorPage', $method->invoke($page));
$this->assertArrayHasKey('SiteTreeSubsitesTest_ClassA', $method->invoke($page));
$this->assertArrayHasKey('SiteTreeSubsitesTest_ClassB', $method->invoke($page));
}
function testPageTypesBlacklistInCMSMain() {
Session::set("loggedInAs", null);
$cmsmain = new CMSMain();
$s1 = $this->objFromFixture('Subsite','domaintest1');
$s2 = $this->objFromFixture('Subsite','domaintest2');
$s1->PageTypeBlacklist = 'SiteTreeSubsitesTest_ClassA,ErrorPage';
$s1->write();
Subsite::changeSubsite($s1);
$classes = $cmsmain->PageTypes()->column('ClassName');
$this->assertNotContains('ErrorPage', $classes);
$this->assertNotContains('SiteTreeSubsitesTest_ClassA', $classes);
$this->assertContains('SiteTreeSubsitesTest_ClassB', $classes);
Subsite::changeSubsite($s2);
$classes = $cmsmain->PageTypes()->column("ClassName");
$this->assertContains('ErrorPage', $classes);
$this->assertContains('SiteTreeSubsitesTest_ClassA', $classes);
$this->assertContains('SiteTreeSubsitesTest_ClassB', $classes);
}
}
class SiteTreeSubsitesTest_ClassA extends SiteTree implements TestOnly {}
class SiteTreeSubsitesTest_ClassB extends SiteTree implements TestOnly {}