Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

Archive /

Our old forums are still available as a read-only archive.

Moderators: martimiz, Sean, biapar, Willr, Ingo, simon_w

Take 1: Editing Permissions for specific page - based on Member Groups


Go to End
Reply


14 Posts   12287 Views

Avatar
Hani

12 Posts

3 August 2007 at 9:24am

GOAL: To set a permission to edit a specific page (NOT a pagetype) by Member Groups.

I've been toying around with this for the past couple of days, and going back to the drawing board each time. (Partly due to my relatively new experience with SilverStripe.) Perhaps some guidance and advice might help.

-----------------------
INITIAL IDEA & OVERVIEW
-----------------------

Basically, I'd like to be able to designate edit permissions by member groups and/or members for a specific page. To make it easy, I first want to start with Groups.

The way it would work: On each page (viewd in the CMS) there will be an "Authors" tab. In the tab, there will be a dropdown displaying all the available Groups. You would select the group, click an "Add" button next to dropdown, and the Group name gets added to a list displayed below - which shows all the groups that have the ability to edit that page.

I'm having trouble with even the first step: getting a dropdown listing all the available Groups.

-----------------------
CODE
-----------------------

Since this will be a feature for every single page in the CMS, I am adding this code to mysite\code\Page.php. The code below is throwing me an error of: "Fatal error: Class name must be a valid object or a string in /home/.keewer/hani79/ss.mmbarn.com/mysite/code/Page.php on line 26" - which tells me that I have something wrong in my "GroupDD" function.

**********************
mysite\code\Page.php
**********************
[code php]
<?

class Page extends SiteTree {
   static $db = array(
   );
   static $has_one = array(
);

   static $has_many = array(
      "Authors" => "Authors_By_Group"
   );
   
   public function GroupDD() {   
      $groups = DataObject::get('Group');
      $Groups_Array = array();
      
      foreach( $groups as $group ) {
         $Groups_Array[$group->ID] = $group->Title;
      }
      
      return new DropdownField('Group',$groupArray);
   }

   public function getCMSFields() {
      $fields = parent::getCMSFields();
      $fields->addFieldToTab("Root.Content.Authors", new $this->GroupDD());
      return $fields;
   }
}

class Authors_By_Group extends DataObject {
   
   static $db = array(
   // This would refer back to the ID of the page
      "ParentID" => "Int"
   );

static $has_one = array(
'Group' => 'Group'
);

}

class Page_Controller extends ContentController {

   // Gets the Project Name
   function project() {
      global $project;
       return $project;
   }
}

?>

**********************

I tried looking at the source code of Newsletter and Security, the documentation, and forums to figure out the relationship between Members/Groups to Pages, but to no avail. Can someone give me some guidance or advice? (Even if it is simply guidance on the first step of getting the dropdown to display properly.)

-----------------------
FUTURE STEPS
-----------------------
1. To actually have the "Add" button for inserting the Group ID and the Page ID to the Authors_By_Group table in the database via AJAX.
2. Allow the "Authors" tab only to display for members in the "Administrators" group.
3. Only display the pages in the CMS's SiteTree that the current user can edit

-----------------------

Thanks in advance for ANY help!

Avatar
Sean

Forum Moderator, 922 Posts

3 August 2007 at 10:03am

Edited: 03/08/2007 10:12am

First of all, something like this should get your groups into a dropdown:

if($groups = DataObject::get('Group')) {
$groups->toDropDownMap('ID', 'Title');
new DropdownField('Groups', 'Select a group', $groups);
}

Avatar
Hani

12 Posts

3 August 2007 at 10:30am

Edited: 03/08/2007 10:31am

Thanks for the help, Sean. You rock!

Your code gave me a dropdown showing "Group" as the Title for each option (which is actually the ClassName) and no values for each.

However, given your code, I was able to do the following with success.

[code php]
$groups = DataObject::get("Group")->toDropDownMap("ID","Title");

I'm not exactly sure why my version worked and yours didn't.

Also, I noticed an error in my own code that I posted originally - which killed the whole thing.

Original:
[code php]$fields->addFieldToTab("Root.Content.Authors", new $this->GroupDD());

Corrected:
[code php]$fields->addFieldToTab("Root.Content.Authors", $this->GroupDD());

Now I can move forward with this. I still have a lot of learning to do! No better way than to dive in, eh? :) Thanks again, Sean.

Avatar
Markus

Google Summer of Code Hacker, 152 Posts

3 August 2007 at 9:56pm

I created something similar.. at the moment you can choose if anyone, only logged in users or only a(!) specific group can view/edit a page.

In the next step we are looking for inheritance of those permissions.. if you want I can post the needed code changes - it's not very well tested code and not finished yet, but maybe it could help you.

Avatar
Sean

Forum Moderator, 922 Posts

3 August 2007 at 11:38pm

Oops, what I forgot in that code is:

if($groups = DataObject::get('Group')) {
$groupList = $groups->toDropDownMap('ID', 'Title');
new DropdownField('Groups', 'Select a group', $groupList);
}

...assigning the actual dropdown map into a variable... silly me!

Great to see you got it working. It's a start. :-)

Sean

Avatar
Sean

Forum Moderator, 922 Posts

4 August 2007 at 2:45am

Edited: 04/08/2007 2:55am

Also,

The second class you have 'Authors_By_Group' may also not be necessary. On Page.php, where you inserted new DropdownField('Groups') you can add this as well, so it has a relation to a Group:

class Page extends SiteTree {

static $has_one = array(
'Groups' => 'Group'
);

function getCMSFields() {
$fields = parent::getCMSFields();

// check if there is any groups, map the groups, and create a dropdown
if($groups = DataObject::get('Group')) {
$groupMap = $groups->toDropDownMap('ID', 'Title');
$fields->addFieldToTab('Root.Content.Author', new DropdownField('Groups', 'Select one', $groupMap);
}

return $fields;
}

}

This, if I'm not mistaken, should then create a 'GroupID' on each Page entry once you rebuild the database using /db/build. The dropdown would save the ID of the group into the GroupID column. Note that I've called the field 'Groups' and the relation 'Groups' => 'Group' to avoid confusion. :-)

Hope this helps!

Sean

Avatar
Hani

12 Posts

4 August 2007 at 3:18am

Thanks for the feedback/advice/guidance, guys.

The last code change that Sean posted definitely works if there is only one group assigned to the page.

[code php]static $has_one = array(
'Groups' => 'Group'
);

You're right - this would mean that the 'Authors_By_Group' won't be needed.

On the other hand, if we want to allow the assignment of more than one group to the page, I should keep this intact, right? Assigning individual members (eventually to be written) to the page would function the same way.

Markus - if you don't mind, I really would like to see the code you have. It will definitely help me learn how to proceed with this - if not replace my limited code with yours.

Thanks!

- Hani

Avatar
Hani

12 Posts

8 August 2007 at 4:54am

Edited: 08/08/2007 4:54am

I'm stuck.

I'd like to add Authors (by Groups) to the page similarly to the way Members are added under the security tab. The difference is that instead of text fields, I'm using that drop down that I was able to get going with your help.

I've made the Authors tab a default on all pages that are created - so essentially, I am modifying the LeftAndMain.php and CMSMain.php files (as well as the Page.php file under "mysite/code").

I am able to successfully insert data into the Authors_By_Group table in the DB - but what seems to be happening is that the whole CMS system is reloaded every time I press the "Add Group" button. I would simply like the new group assignment to be written to the DB and stay on the same page and tab. (I have yet to write the code to display the current groups assigned to the page.) I am fairly certain it isn't running the javascript I have created - using the javascript written for the "save" function.

Is there an easier way to do this? Am I on the right track? Thanks in advance.

Here is what I have:

CMSMain.php
[code php]
function addAuthorByGroup($urlParams, $form) {
LeftAndMain::addAuthorByGroup($urlParams, $form);
}

LeftAndMain.php
[code php]
function addAuthorByGroup($form) {
$authordata['GroupID'] = $_REQUEST['Groups'];
$className = 'Authors_By_Group';
$record = new $className();
$record->update($authordata);
$record->write();
return FormResponse::respond();
}

LeftAndMain_js.php
[code php]
addAuthorByGroup: function(callAfter, action) {
_AJAX_LOADING = true;
if(!action) action = "addAuthorByGroup";
var __callAfter = callAfter;
var __form = this;
var data = this.serializeChangedFields('Groups') + '&ajax=1&action_' + action + '=1';

statusMessage("Adding Author...", null, true);
new Ajax.Request(this.action, {
method : this.method,
postBody: data,
onSuccess : success,
onFailure : function(response) {
errorMessage('Error saving content', response);
_AJAX_LOADING = false;
}
});
}

Go to Top