mirror of
https://github.com/silverstripe/silverstripe-contentreview
synced 2024-10-22 17:05:47 +02:00
Allow users and/or groups to be content owners
This commit is contained in:
parent
d28a0eefa0
commit
131d643a8c
@ -1,3 +1,9 @@
|
||||
SiteTree:
|
||||
extensions:
|
||||
- SiteTreeContentReview
|
||||
Group:
|
||||
extensions:
|
||||
- ContentReviewOwner
|
||||
Member:
|
||||
extensions:
|
||||
- ContentReviewOwner
|
@ -19,14 +19,23 @@ class ContentReviewEmails extends BuildTask {
|
||||
Subsite::$disable_subsite_filter = true;
|
||||
}
|
||||
|
||||
$pages = DataObject::get('Page', "\"SiteTree\".\"NextReviewDate\" = '".(class_exists('SS_Datetime') ? SS_Datetime::now()->URLDate() : SSDatetime::now()->URLDate())."' AND \"SiteTree\".\"ContentReviewOwnerID\" != 0");
|
||||
$now = class_exists('SS_Datetime') ? SS_Datetime::now()->URLDate() : SSDatetime::now()->URLDate();
|
||||
|
||||
$pages = Page::get('Page')
|
||||
->leftJoin('Group_SiteTreeContentReview', '"SiteTree"."ID" = "OwnerGroups"."SiteTreeID"', 'OwnerGroups')
|
||||
->leftJoin('Member_SiteTreeContentReview', '"SiteTree"."ID" = "OwnerUsers"."SiteTreeID"', "OwnerUsers")
|
||||
->where('"SiteTree"."NextReviewDate" <= \''.$now.'\' AND' .' ("OwnerGroups"."ID" IS NOT NULL OR "OwnerUsers"."ID" IS NOT NULL)')
|
||||
;
|
||||
|
||||
if ($pages && $pages->Count()) {
|
||||
foreach($pages as $page) {
|
||||
$owner = $page->ContentReviewOwner();
|
||||
if ($owner) {
|
||||
$sender = Security::findAnAdministrator();
|
||||
$recipient = $owner;
|
||||
|
||||
$owners = $page->ContentReviewOwners();
|
||||
if(!$owners->count()) {
|
||||
continue;
|
||||
}
|
||||
$sender = Security::findAnAdministrator();
|
||||
|
||||
foreach($owners as $recipient) {
|
||||
$subject = sprintf(_t('ContentReviewEmails.SUBJECT', 'Page %s due for content review'), $page->Title);
|
||||
|
||||
$email = new Email();
|
||||
|
@ -23,18 +23,25 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $has_one = array(
|
||||
'ContentReviewOwner' => 'Member',
|
||||
private static $belongs_many_many = array(
|
||||
'ContentReviewGroups' => 'Group',
|
||||
'ContentReviewUsers' => 'Member'
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOwnerName() {
|
||||
if($this->owner->ContentReviewOwnerID && $this->owner->ContentReviewOwner()) {
|
||||
return $this->owner->ContentReviewOwner()->FirstName . ' ' . $this->owner->ContentReviewOwner()->Surname;
|
||||
public function getOwnerNames() {
|
||||
$names = array();
|
||||
foreach($this->DirectGroups() as $group) {
|
||||
$names[] = $group->Title;
|
||||
}
|
||||
|
||||
foreach($this->DirectUsers() as $group) {
|
||||
$names[] = $group->getName();
|
||||
}
|
||||
return implode(', ', $names);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,6 +54,53 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Members that are Content Owners to this page
|
||||
*
|
||||
* This includes checking group hierarchy and adding any direct users
|
||||
*
|
||||
* @return \ArrayList
|
||||
*/
|
||||
public function ContentReviewOwners() {
|
||||
|
||||
$contentReviewOwners = new ArrayList();
|
||||
|
||||
$toplevelGroups = $this->DirectGroups();
|
||||
if($toplevelGroups) {
|
||||
$groupIDs = array();
|
||||
foreach($toplevelGroups as $group) {
|
||||
$familyIDs = $group->collateFamilyIDs();
|
||||
if(is_array($familyIDs)) {
|
||||
$groupIDs = array_merge($groupIDs, array_values($familyIDs));
|
||||
}
|
||||
}
|
||||
if(count($groupIDs)) {
|
||||
$groupMembers = DataObject::get('Member')->where("\"Group\".\"ID\" IN (" . implode(",",$groupIDs) . ")")
|
||||
->leftJoin("Group_Members", "\"Member\".\"ID\" = \"Group_Members\".\"MemberID\"")
|
||||
->leftJoin("Group", "\"Group_Members\".\"GroupID\" = \"Group\".\"ID\"");
|
||||
$contentReviewOwners->merge($groupMembers);
|
||||
}
|
||||
|
||||
}
|
||||
$contentReviewOwners->merge($this->DirectUsers());
|
||||
$contentReviewOwners->removeDuplicates();
|
||||
return $contentReviewOwners;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ManyManyList
|
||||
*/
|
||||
public function DirectGroups() {
|
||||
return $this->owner->getManyManyComponents('ContentReviewGroups');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ManyManyList
|
||||
*/
|
||||
public function DirectUsers() {
|
||||
return $this->owner->getManyManyComponents('ContentReviewUsers');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@ -54,21 +108,48 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
|
||||
* @return void
|
||||
*/
|
||||
public function updateCMSFields(FieldList $fields) {
|
||||
if(Permission::check("EDIT_CONTENT_REVIEW_FIELDS")) {
|
||||
if(!Permission::check("EDIT_CONTENT_REVIEW_FIELDS")) {
|
||||
return;
|
||||
}
|
||||
$cmsUsers = Permission::get_members_by_permission(array("CMS_ACCESS_CMSMain", "ADMIN"));
|
||||
$users = Permission::get_members_by_permission(array("CMS_ACCESS_CMSMain", "ADMIN"));
|
||||
|
||||
$usersMap = array();
|
||||
foreach($users as $user) {
|
||||
// Listboxfield values are escaped, use ASCII char instead of »
|
||||
$usersMap[$user->ID] = $user->getTitle();
|
||||
}
|
||||
asort($usersMap);
|
||||
|
||||
$userField = ListboxField::create('DirectUsers', _t("ContentReview.PAGEOWNERUSERS", "Users"))
|
||||
->setMultiple(true)
|
||||
->setSource($usersMap)
|
||||
->setAttribute('data-placeholder', _t('ContentReview.ADDUSERS', 'Add users'))
|
||||
->setDescription(_t('ContentReview.OWNERUSERSDESCRIPTION', 'Page owners that are responsible for reviews'));
|
||||
|
||||
$fields->addFieldsToTab("Root.Review", array(
|
||||
new HeaderField(_t('SiteTreeCMSWorkflow.REVIEWHEADER', "Content review"), 2),
|
||||
new DropdownField("ContentReviewOwnerID", _t("SiteTreeCMSWorkflow.PAGEOWNER",
|
||||
"Page owner (will be responsible for reviews)"), $cmsUsers->map('ID', 'Title', '(no owner)')),
|
||||
DateField::create(
|
||||
"NextReviewDate",
|
||||
_t("SiteTreeCMSWorkflow.NEXTREVIEWDATE", "Next review date (leave blank for no review)")
|
||||
)->setConfig('showcalendar', true)->setConfig('dateformat', 'yyyy-MM-dd')->setConfig('datavalueformat', 'yyyy-MM-dd'),
|
||||
new DropdownField("ReviewPeriodDays", _t("SiteTreeCMSWorkflow.REVIEWFREQUENCY",
|
||||
"Review frequency (the review date will be set to this far in the future whenever the page is published.)"), array(
|
||||
$groupsMap = array();
|
||||
foreach(Group::get() as $group) {
|
||||
// Listboxfield values are escaped, use ASCII char instead of »
|
||||
$groupsMap[$group->ID] = $group->getBreadcrumbs(' > ');
|
||||
}
|
||||
asort($groupsMap);
|
||||
$groupField = ListboxField::create('DirectGroups', _t("ContentReview.PAGEOWNERGROUPS", "Groups"))
|
||||
->setMultiple(true)
|
||||
->setSource($groupsMap)
|
||||
->setAttribute('data-placeholder', _t('ContentReview.ADDGROUP', 'Add groups'))
|
||||
->setDescription(_t('ContentReview.OWNERGROUPSDESCRIPTION', 'Page owners that are responsible for reviews'));
|
||||
|
||||
$reviewDate = DateField::create(
|
||||
"NextReviewDate",
|
||||
_t("ContentReview.NEXTREVIEWDATE", "Next review date")
|
||||
)->setConfig('showcalendar', true)
|
||||
->setConfig('dateformat', 'yyyy-MM-dd')
|
||||
->setConfig('datavalueformat', 'yyyy-MM-dd')
|
||||
->setDescription(_t('ContentReview.NEXTREVIEWDATADESCRIPTION', 'Leave blank for no review'));
|
||||
|
||||
$reviewFrequency = DropdownField::create(
|
||||
"ReviewPeriodDays",
|
||||
_t("ContentReview.REVIEWFREQUENCY", "Review frequency"),
|
||||
array(
|
||||
0 => "No automatic review date",
|
||||
1 => "1 day",
|
||||
7 => "1 week",
|
||||
@ -79,7 +160,15 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
|
||||
152 => "5 months",
|
||||
183 => "6 months",
|
||||
365 => "12 months",
|
||||
)),
|
||||
)
|
||||
)->setDescription(_t('ContentReview.REVIEWFREQUENCYDESCRIPTION', 'The review date will be set to this far in the future whenever the page is published'));
|
||||
|
||||
$fields->addFieldsToTab("Root.Review", array(
|
||||
new HeaderField(_t('ContentReview.REVIEWHEADER', "Content review"), 2),
|
||||
$userField,
|
||||
$groupField,
|
||||
$reviewDate,
|
||||
$reviewFrequency,
|
||||
new TextareaField('ReviewNotes', 'Review Notes')
|
||||
));
|
||||
}
|
||||
@ -92,7 +181,7 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
|
||||
$this->owner->NextReviewDate = date('Y-m-d', strtotime('+' . $this->owner->ReviewPeriodDays . ' days'));
|
||||
}
|
||||
$this->owner->LastEditedByName=$this->owner->getEditorName();
|
||||
$this->owner->OwnerNames = $this->owner->getOwnerName();
|
||||
$this->owner->OwnerNames = $this->owner->getOwnerNames();
|
||||
}
|
||||
|
||||
/**
|
||||
|
16
code/extensions/ContentReviewOwner.php
Normal file
16
code/extensions/ContentReviewOwner.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Description of GroupContentReview
|
||||
*
|
||||
*/
|
||||
class ContentReviewOwner extends DataExtension {
|
||||
|
||||
/**
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $many_many = array(
|
||||
"SiteTreeContentReview" => "SiteTree"
|
||||
);
|
||||
}
|
@ -8,21 +8,21 @@ class ContentReviewTest extends FunctionalTest {
|
||||
*/
|
||||
public static $fixture_file = 'contentreview/tests/ContentReviewTest.yml';
|
||||
|
||||
public function testPermissions() {
|
||||
$editor = $this->objFromFixture('Member', 'editor');
|
||||
$author = $this->objFromFixture('Member', 'author');
|
||||
|
||||
// Assert the permission code exists
|
||||
public function testPermissionsExists() {
|
||||
$perms = singleton('SiteTreeContentReview')->providePermissions();
|
||||
$this->assertTrue(isset($perms['EDIT_CONTENT_REVIEW_FIELDS']));
|
||||
|
||||
// Check a user with permission can edit fields
|
||||
}
|
||||
|
||||
public function testUserWithPermissionCanEdit() {
|
||||
$editor = $this->objFromFixture('Member', 'editor');
|
||||
$this->logInAs($editor);
|
||||
$page = new Page();
|
||||
$fields = $page->getCMSFields();
|
||||
$this->assertNotNull($fields->fieldByName('Root.Review'));
|
||||
|
||||
// Check a user without permission can see tab
|
||||
}
|
||||
|
||||
public function testUserWithoutPermissionCannotEdit() {
|
||||
$author = $this->objFromFixture('Member', 'author');
|
||||
$this->logInAs($author);
|
||||
$page = new Page();
|
||||
$fields = $page->getCMSFields();
|
||||
@ -83,23 +83,23 @@ class ContentReviewTest extends FunctionalTest {
|
||||
SS_Datetime::clear_mock_now();
|
||||
}
|
||||
|
||||
public function testOwnerName() {
|
||||
public function testOwnerNames() {
|
||||
$editor = $this->objFromFixture('Member', 'editor');
|
||||
$this->logInAs($editor);
|
||||
|
||||
$page = new Page();
|
||||
$page->ReviewPeriodDays = 10;
|
||||
$page->ContentReviewOwnerID = $editor->ID;
|
||||
$page->ContentReviewUsers()->push($editor);
|
||||
$page->write();
|
||||
|
||||
$this->assertTrue($page->doPublish());
|
||||
$this->assertEquals($page->OwnerName, "Test Editor");
|
||||
$this->assertEquals($page->OwnerNames, "Test Editor", 'Test Editor should be the owner');
|
||||
|
||||
$page = $this->objFromFixture('Page', 'about');
|
||||
$page->ContentReviewOwnerID = 0;
|
||||
$page->write();
|
||||
|
||||
$this->assertTrue($page->doPublish());
|
||||
$this->assertNull($page->OwnerName);
|
||||
$this->assertEquals('', $page->OwnerNames);
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ Page:
|
||||
staff:
|
||||
Title: Staff
|
||||
NextReviewDate: 2010-02-14
|
||||
ContentReviewOwner: =>Member.author
|
||||
ContentReviewUsers: =>Member.author
|
||||
contact:
|
||||
Title: Contact Us
|
||||
NextReviewDate: 2010-02-21
|
Loading…
Reference in New Issue
Block a user