diff --git a/core/control/ContentController.php b/core/control/ContentController.php index 59cdd329f..be44dba72 100644 --- a/core/control/ContentController.php +++ b/core/control/ContentController.php @@ -39,7 +39,7 @@ class ContentController extends Controller { if($action == "index") $action = ""; // '&' in a URL is apparently naughty - $action = preg_replace( '/&/', '&', $action ); + $action = preg_replace('/&/', '&', $action); return $this->URLSegment . "/$action"; }else{ user_error("ContentController::RelativeLink() No URLSegment given on a '$this->class' object. Perhaps you should overload it?", E_USER_WARNING); @@ -48,7 +48,7 @@ class ContentController extends Controller { //if($action == "index") $action = ""; // '&' in a URL is apparently naughty - // $action = preg_replace( '/&/', '&', $action ); + // $action = preg_replace('/&/', '&', $action); //return $this->URLSegment . "/$action"; } @@ -126,16 +126,31 @@ class ContentController extends Controller { */ public function getMenu($level) { if($level == 1) { - return DataObject::get("SiteTree", "ShowInMenus = 1 AND ParentID = 0"); + $result = DataObject::get("SiteTree", "ShowInMenus = 1 AND ParentID = 0"); } else { $parent = $this->data(); $stack = array($parent); - while($parent = $parent->Parent) array_unshift($stack, $parent); + while($parent = $parent->Parent) + array_unshift($stack, $parent); if(isset($stack[$level-2])) - return $stack[$level-2]->Children(); + $result = $stack[$level-2]->Children(); } + + $visible = array(); + + // Remove all entries the can not be viewed by the current user + // We might need to create a show in menu permission + if($result) { + foreach($result as $page) { + if($page->can('view')) { + $visible[] = $page; + } + } + } + + return new DataObjectSet($visible); } /** * Returns the page in the current page stack of the given level. @@ -389,4 +404,6 @@ HTML ); } } -?> + + +?> \ No newline at end of file diff --git a/core/model/SiteTree.php b/core/model/SiteTree.php index 954c576a6..af4692c1a 100644 --- a/core/model/SiteTree.php +++ b/core/model/SiteTree.php @@ -256,8 +256,51 @@ class SiteTree extends DataObject { } /** - * This function should return true if the current user can add children to this page. - * It can be overloaded to customise the security model for an application. + * Returns true if the member is allowed to do the given action. + * + * @param string $perm The permission to be checked, such as 'View'. + * @param Member $member The member whose permissions need checking. + * Defaults to the currently logged in user. + * + * @return boolean True if the the member is allowed to do the given + * action. + * + * @todo Check we get a endless recursion if we use parent::can() + */ + function can($perm, $member = null) { + if(!isset($member)) { + $member = Member::currentUser(); + } + + // Users with ADMIN permission can always do this + if($member && Permission::check('ADMIN')) { + return true; + } + + switch(strtolower($perm)) { + case 'edit': + if($this->Editors == 'LoggedInUsers' && $member) return true; + if($member && $this->Editors == 'OnlyTheseUsers' && $member->isInGroup($this->EditorsGroup)) return true; + break; + case 'view': + case 'view_page': + if($this->Viewers == 'Anyone') return true; + if($member && $this->Viewers == 'LoggedInUsers') return true; + if($member && $this->Viewers == 'OnlyTheseUsers' && $member->isInGroup($this->ViewersGroup)) return true; + break; + } + + return false; + } + + + /** + * This function should return true if the current user can add children + * to this page. + * + * It can be overloaded to customise the security model for an + * application. + * * @return boolean True if the current user can add children. */ public function canAddChildren() { @@ -288,7 +331,7 @@ class SiteTree extends DataObject { * @return boolean True if the current user can edit this page. */ public function canEdit() { - return true; + return $this->can('Edit'); } /** @@ -503,6 +546,26 @@ class SiteTree extends DataObject { //------------------------------------------------------------------------------------// + /** + * Holds callback functions to be called when getCMSFields() is called + * + * @var array + */ + static $cms_additions = array(); + + + /** + * Allows modules to extend the cms editing form for all pages in the site + * + * @param mixed $function the name of your function, either as a string, + * or in the form array('class','function) + */ + static function ExtendCMS($function) + { + self::$cms_additions[] = $function; + } + + /** * Returns a FieldSet with which to create the CMS editing form. * You can override this in your child classes to add extra fields - first @@ -512,6 +575,7 @@ class SiteTree extends DataObject { */ function getCMSFields() { require_once("forms/Form.php"); + Requirements::javascript("cms/javascript/SitetreeAccess.js"); // Backlink report if($this->hasMethod('BackLinkTracking')) { @@ -613,11 +677,29 @@ class SiteTree extends DataObject { new Tab("BackLinks", new LiteralField("Backlinks", $backlinks) ) + ), + new Tab("Access", + new HeaderField("Who can display this?", 2), + new OptionsetField("Viewers", "", + array("Anyone" => "Anyone", + "LoggedInUsers" => "Logged-in users", + "OnlyTheseUsers" => "Only these people (choose from list)")), + new DropdownField("ViewersGroup", "Group", Group::map()), + new HeaderField("Who can edit this?", 2), + new OptionsetField("Editors", "", + array("LoggedInUsers" => "Logged-in users", + "OnlyTheseUsers" => "Only these people (choose from list)")), + new DropdownField("EditorsGroup", "Group", Group::map()) ) ), new NamedLabelField("Status", $message, "pageStatusMessage", true) ); + foreach(self::$cms_additions as $extension) + { + $fields = call_user_func($extension,$fields); + } + return $fields; } @@ -634,9 +716,11 @@ class SiteTree extends DataObject { if($this->isPublished() && $this->canEdit()) { $actions[] = FormAction::create('rollback', 'Cancel draft changes')->describe("Delete your draft and revert to the currently published page"); } - if(!$this->isNew() && $this->canPublish()) $actions[] = new FormAction('publish', 'Publish'); } + if($this->canPublish()) + $actions[] = new FormAction('publish', 'Save & Publish'); + return new DataObjectSet($actions); } @@ -890,7 +974,11 @@ class SiteTree extends DataObject { "HasBrokenFile" => "Boolean", "HasBrokenLink" => "Boolean", "Status" => "Varchar", - "ReportClass" => "Varchar" + "ReportClass" => "Varchar", + "Viewers" => "Enum('Anyone, LoggedInUsers, OnlyTheseUsers', 'Anyone')", + "Editors" => "Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')", + "ViewersGroup" => "Int", + "EditorsGroup" => "Int" ); static $indexes = array( @@ -926,7 +1014,9 @@ class SiteTree extends DataObject { "ShowInMenus" => 1, "ShowInSearch" => 1, "Status" => "New page", - "CanCreateChildren" => array(10) + "CanCreateChildren" => array(10), + "Viewers" => "Anyone", + "Editors" => "LoggedInUsers" ); static $has_one = array(