Skip to content

Instantly share code, notes, and snippets.

@drzax
Created October 9, 2012 01:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drzax/3856130 to your computer and use it in GitHub Desktop.
Save drzax/3856130 to your computer and use it in GitHub Desktop.
A pattern for creating 'singleton' page types in Silverstripe

See SingletonPage for a maintained version of this gist.

Use this DataExtension to specify that it should only be possible for users to create one instance of the decorated page type.

Note that the use of 'singleton' here does not refer to use of the singleton pattern as commonly understood in programming.

Silverstripe core currently prevents DataExtensions from overriding the behaviour of the SiteTree->canCreate() function for users with ADMIN permissions, so an addition to the Page class is also required to properly invoke this DataExtension.

...
Object::add_extension('MyAccountPage', 'SingletonPage');
...
class Page extends SiteTree {
...
/**
* Override the canCreate method to change the order of processing and allow
* the SingletonPage DataExtension to do its work.
*/
public function canCreate($member = null) {
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
$member = Member::currentUserID();
}
// Standard mechanism for accepting permission changes from extensions
$extended = $this->extendedCan('canCreate', $member);
if($extended !== null) return $extended;
return parent::canCreate($member);
}
...
}
<?php
/**
* A data object extension which enforces that only one instance of the extended
* page type can be created. Also provides some utility funcitons for working
* with signleton page types.
*/
class SingletonPage extends DataExtension {
/**
* Extend the can create method to return false if there is already a page
* of this type.
*
* @param Member $member The member being checked.
* @return boolean
*/
public function canCreate($member) {
return (DataObject::get($this->owner->class)->count() > 0) ? false : parent::canCreate($member);
}
/**
* Get the one instance of the page type specified.
* @param string $type The class name of the SingletonPage object being requested.
* @return mixed The page object or null if none exists.
*/
public static function get($type) {
// Check that the requested type is a SingletonPage
if ( ! singleton($type)->hasExtension('SingletonPage') ) {
user_error('This method should only be used with page types decorated with the SingletonPage extension.');
}
return DataObject::get_one($type);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment