mirror of
https://github.com/silverstripe/silverstripe-contentreview
synced 2024-10-22 17:05:47 +02:00
Fixed code style
This commit is contained in:
parent
c22e24567e
commit
61fd586533
@ -4,43 +4,51 @@
|
|||||||
* This is a helper class which lets us do things with content review data without subsites
|
* This is a helper class which lets us do things with content review data without subsites
|
||||||
* and translatable messing our SQL queries up.
|
* and translatable messing our SQL queries up.
|
||||||
*
|
*
|
||||||
* Make sure any DataQuery-ies you are building are BOTH created & executed between start()
|
* Make sure any DataQuery instances you are building are BOTH created & executed between start()
|
||||||
* and done() because augmentDataQueryCreate and augmentSQL happens there.
|
* and done() because augmentDataQueryCreate and augmentSQL happens there.
|
||||||
*/
|
*/
|
||||||
class ContentReviewCompatability {
|
class ContentReviewCompatability
|
||||||
|
{
|
||||||
|
const SUBSITES = 0;
|
||||||
|
|
||||||
const SUBSITES = 0;
|
const TRANSLATABLE = 1;
|
||||||
const TRANSLATABLE = 1;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array - state before compatability mode started, to be passed into done().
|
* Returns the state of other modules before compatibility mode is started.
|
||||||
*/
|
*
|
||||||
public static function start(){
|
* @return array
|
||||||
$compat = array(
|
*/
|
||||||
self::SUBSITES => null,
|
public static function start()
|
||||||
self::TRANSLATABLE => null
|
{
|
||||||
);
|
$compatibility = array(
|
||||||
if(ClassInfo::exists('Subsite')){
|
self::SUBSITES => null,
|
||||||
$compat[self::SUBSITES] = Subsite::$disable_subsite_filter;
|
self::TRANSLATABLE => null,
|
||||||
Subsite::disable_subsite_filter(true);
|
);
|
||||||
}
|
|
||||||
if(ClassInfo::exists('Translatable')){
|
|
||||||
$compat[self::TRANSLATABLE] = Translatable::locale_filter_enabled();
|
|
||||||
Translatable::disable_locale_filter();
|
|
||||||
}
|
|
||||||
return $compat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (ClassInfo::exists("Subsite")) {
|
||||||
* @param array $compat - see start()
|
$compatibility[self::SUBSITES] = Subsite::$disable_subsite_filter;
|
||||||
*/
|
Subsite::disable_subsite_filter(true);
|
||||||
public static function done(array $compat){
|
}
|
||||||
if(class_exists('Subsite')){
|
|
||||||
Subsite::$disable_subsite_filter = $compat[self::SUBSITES];
|
|
||||||
}
|
|
||||||
if(class_exists('Translatable')){
|
|
||||||
Translatable::enable_locale_filter($compat[self::TRANSLATABLE]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (ClassInfo::exists("Translatable")) {
|
||||||
|
$compatibility[self::TRANSLATABLE] = Translatable::locale_filter_enabled();
|
||||||
|
Translatable::disable_locale_filter();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $compatibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $compatibility
|
||||||
|
*/
|
||||||
|
public static function done(array $compatibility)
|
||||||
|
{
|
||||||
|
if (class_exists("Subsite")) {
|
||||||
|
Subsite::$disable_subsite_filter = $compatibility[self::SUBSITES];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (class_exists("Translatable")) {
|
||||||
|
Translatable::enable_locale_filter($compatibility[self::TRANSLATABLE]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,84 +1,94 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CMSPageEditController extension to recieve the additonal action button from
|
* CMSPageEditController extension to receive the additional action button from
|
||||||
* SiteTreeContentReview::updateCMSActions()
|
* SiteTreeContentReview::updateCMSActions()
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
class ContentReviewCMSExtension extends LeftAndMainExtension {
|
class ContentReviewCMSExtension extends LeftAndMainExtension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $allowed_actions = array(
|
||||||
|
"reviewed",
|
||||||
|
"save_review",
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Shows a form with review notes.
|
||||||
* @var array
|
*
|
||||||
*/
|
* @param array $data
|
||||||
private static $allowed_actions = array(
|
* @param Form $form
|
||||||
'reviewed',
|
*
|
||||||
'save_review',
|
* @return SS_HTTPResponse
|
||||||
);
|
* @throws SS_HTTPResponse_Exception
|
||||||
|
*/
|
||||||
|
public function reviewed($data, Form $form)
|
||||||
|
{
|
||||||
|
if (!isset($data["ID"])) {
|
||||||
|
throw new SS_HTTPResponse_Exception('No record ID', 404);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
$id = (int) $data["ID"];
|
||||||
* Shows a form with review notes
|
$record = SiteTree::get()->byID($id);
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
* @param Form $form
|
|
||||||
* @return SS_HTTPResponse
|
|
||||||
*/
|
|
||||||
public function reviewed($data, Form $form) {
|
|
||||||
if(!isset($data['ID'])) {
|
|
||||||
throw new SS_HTTPResponse_Exception("No record ID", 404);
|
|
||||||
}
|
|
||||||
$SQL_id = (int) $data['ID'];
|
|
||||||
$record = SiteTree::get()->byID($SQL_id);
|
|
||||||
|
|
||||||
if(!$record || !$record->ID) {
|
if (!$record || !$record->ID) {
|
||||||
throw new SS_HTTPResponse_Exception("Bad record ID #$SQL_id", 404);
|
throw new SS_HTTPResponse_Exception("Bad record ID #{$id}", 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$record->canEdit()) {
|
if (!$record->canEdit()) {
|
||||||
return Security::permissionFailure($this->owner);
|
return Security::permissionFailure($this->owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
$fields = new FieldList();
|
$fields = new FieldList();
|
||||||
$fields->push(HiddenField::create('ID', 'ID', $SQL_id));
|
$fields->push(HiddenField::create("ID", "ID", $id));
|
||||||
$fields->push(TextareaField::create('ReviewNotes', 'Review notes'));
|
$fields->push(TextareaField::create("ReviewNotes", "Review notes"));
|
||||||
|
|
||||||
$actions = new FieldList(
|
$actions = new FieldList(
|
||||||
FormAction::create('save_review', 'Save')
|
FormAction::create("save_review", "Save")
|
||||||
);
|
);
|
||||||
|
|
||||||
$form = CMSForm::create($this->owner, "EditForm", $fields, $actions)->setHTMLID('Form_EditForm');
|
$form = CMSForm::create($this->owner, "EditForm", $fields, $actions)->setHTMLID("Form_EditForm");
|
||||||
$form->setResponseNegotiator($this->owner->getResponseNegotiator());
|
$form->setResponseNegotiator($this->owner->getResponseNegotiator());
|
||||||
$form->loadDataFrom($record);
|
$form->loadDataFrom($record);
|
||||||
$form->disableDefaultAction();
|
$form->disableDefaultAction();
|
||||||
|
|
||||||
// TODO Can't merge $FormAttributes in template at the moment
|
// TODO Can't merge $FormAttributes in template at the moment
|
||||||
$form->setTemplate($this->owner->getTemplatesWithSuffix('LeftAndMain_EditForm'));
|
$form->setTemplate($this->owner->getTemplatesWithSuffix("LeftAndMain_EditForm"));
|
||||||
return $form->forTemplate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return $form->forTemplate();
|
||||||
* Save the review notes and redirect back to the page edit form
|
}
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
* @param Form $form
|
|
||||||
* @return string - html
|
|
||||||
*/
|
|
||||||
public function save_review($data, Form $form) {
|
|
||||||
if(!isset($data['ID'])) {
|
|
||||||
throw new SS_HTTPResponse_Exception("No record ID", 404);
|
|
||||||
}
|
|
||||||
$SQL_id = (int) $data['ID'];
|
|
||||||
$page = SiteTree::get()->byID($SQL_id);
|
|
||||||
if($page && !$page->canEdit()) {
|
|
||||||
return Security::permissionFailure();
|
|
||||||
}
|
|
||||||
if(!$page || !$page->ID) {
|
|
||||||
throw new SS_HTTPResponse_Exception("Bad record ID #$SQL_id", 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$page->addReviewNote(Member::currentUser(), $data['ReviewNotes']);
|
/**
|
||||||
$page->advanceReviewDate();
|
* Save the review notes and redirect back to the page edit form.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @param Form $form
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @throws SS_HTTPResponse_Exception
|
||||||
|
*/
|
||||||
|
public function save_review($data, Form $form)
|
||||||
|
{
|
||||||
|
if (!isset($data["ID"])) {
|
||||||
|
throw new SS_HTTPResponse_Exception("No record ID", 404);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->owner->redirect($this->owner->Link('show/'.$page->ID));
|
$id = (int) $data["ID"];
|
||||||
}
|
$page = SiteTree::get()->byID($id);
|
||||||
|
|
||||||
|
if ($page && !$page->canEdit()) {
|
||||||
|
return Security::permissionFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$page || !$page->ID) {
|
||||||
|
throw new SS_HTTPResponse_Exception("Bad record ID #{$id}", 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$page->addReviewNote(Member::currentUser(), $data["ReviewNotes"]);
|
||||||
|
$page->advanceReviewDate();
|
||||||
|
|
||||||
|
return $this->owner->redirect($this->owner->Link("show/" . $page->ID));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,107 +1,121 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This extensions add a default schema for new pages and pages without a content review setting
|
* This extensions add a default schema for new pages and pages without a content
|
||||||
|
* review setting.
|
||||||
*
|
*
|
||||||
|
* @property int $ReviewPeriodDays
|
||||||
*/
|
*/
|
||||||
class ContentReviewDefaultSettings extends DataExtension {
|
class ContentReviewDefaultSettings extends DataExtension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $db = array(
|
||||||
|
"ReviewPeriodDays" => "Int",
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $db = array(
|
private static $many_many = array(
|
||||||
"ReviewPeriodDays" => "Int",
|
"ContentReviewGroups" => "Group",
|
||||||
);
|
"ContentReviewUsers" => "Member",
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @var array
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static $many_many = array(
|
public function getOwnerNames()
|
||||||
'ContentReviewGroups' => 'Group',
|
{
|
||||||
'ContentReviewUsers' => 'Member'
|
$names = array();
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
foreach ($this->OwnerGroups() as $group) {
|
||||||
*
|
$names[] = $group->getBreadcrumbs(" > ");
|
||||||
* @return string
|
}
|
||||||
*/
|
|
||||||
public function getOwnerNames() {
|
|
||||||
$names = array();
|
|
||||||
foreach($this->OwnerGroups() as $group) {
|
|
||||||
$names[] = $group->getBreadcrumbs(' > ');
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($this->OwnerUsers() as $group) {
|
foreach ($this->OwnerUsers() as $group) {
|
||||||
$names[] = $group->getName();
|
$names[] = $group->getName();
|
||||||
}
|
}
|
||||||
return implode(', ', $names);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return implode(", ", $names);
|
||||||
* @return ManyManyList
|
}
|
||||||
*/
|
|
||||||
public function OwnerGroups() {
|
|
||||||
return $this->owner->getManyManyComponents('ContentReviewGroups');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ManyManyList
|
* @return ManyManyList
|
||||||
*/
|
*/
|
||||||
public function OwnerUsers() {
|
public function OwnerGroups()
|
||||||
return $this->owner->getManyManyComponents('ContentReviewUsers');
|
{
|
||||||
}
|
return $this->owner->getManyManyComponents("ContentReviewGroups");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @return ManyManyList
|
||||||
* @param \FieldList $fields
|
*/
|
||||||
*/
|
public function OwnerUsers()
|
||||||
public function updateCMSFields(\FieldList $fields) {
|
{
|
||||||
|
return $this->owner->getManyManyComponents("ContentReviewUsers");
|
||||||
|
}
|
||||||
|
|
||||||
$helpText = LiteralField::create('ContentReviewHelp', _t('ContentReview.DEFAULTSETTINGSHELP', 'These content review '
|
/**
|
||||||
. 'settings will apply to all pages that does not have specific Content Review schedule.'));
|
*
|
||||||
$fields->addFieldToTab('Root.ContentReview', $helpText);
|
* @param FieldList $fields
|
||||||
|
*/
|
||||||
|
public function updateCMSFields(FieldList $fields)
|
||||||
|
{
|
||||||
|
$helpText = LiteralField::create("ContentReviewHelp", _t("ContentReview.DEFAULTSETTINGSHELP", "These content review settings will apply to all pages that does not have specific Content Review schedule."));
|
||||||
|
|
||||||
$reviewFrequency = DropdownField::create("ReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), SiteTreeContentReview::get_schedule())
|
$fields->addFieldToTab("Root.ContentReview", $helpText);
|
||||||
->setDescription(_t('ContentReview.REVIEWFREQUENCYDESCRIPTION', 'The review date will be set to this far in the future whenever the page is published'));
|
|
||||||
|
|
||||||
$fields->addFieldToTab('Root.ContentReview', $reviewFrequency);
|
$reviewFrequency = DropdownField::create("ReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), SiteTreeContentReview::get_schedule())
|
||||||
|
->setDescription(_t("ContentReview.REVIEWFREQUENCYDESCRIPTION", "The review date will be set to this far in the future whenever the page is published"));
|
||||||
|
|
||||||
$users = Permission::get_members_by_permission(array("CMS_ACCESS_CMSMain", "ADMIN"));
|
$fields->addFieldToTab("Root.ContentReview", $reviewFrequency);
|
||||||
|
|
||||||
$usersMap = $users->map('ID', 'Title')->toArray();
|
$users = Permission::get_members_by_permission(array(
|
||||||
asort($usersMap);
|
"CMS_ACCESS_CMSMain",
|
||||||
|
"ADMIN",
|
||||||
|
));
|
||||||
|
|
||||||
$userField = ListboxField::create('OwnerUsers', _t("ContentReview.PAGEOWNERUSERS", "Users"), $usersMap)
|
$usersMap = $users->map("ID", "Title")->toArray();
|
||||||
->setMultiple(true)
|
asort($usersMap);
|
||||||
->setAttribute('data-placeholder', _t('ContentReview.ADDUSERS', 'Add users'))
|
|
||||||
->setDescription(_t('ContentReview.OWNERUSERSDESCRIPTION', 'Page owners that are responsible for reviews'));
|
|
||||||
$fields->addFieldToTab('Root.ContentReview', $userField);
|
|
||||||
|
|
||||||
$groupsMap = array();
|
$userField = ListboxField::create("OwnerUsers", _t("ContentReview.PAGEOWNERUSERS", "Users"), $usersMap)
|
||||||
foreach(Group::get() as $group) {
|
->setMultiple(true)
|
||||||
// Listboxfield values are escaped, use ASCII char instead of »
|
->setAttribute("data-placeholder", _t("ContentReview.ADDUSERS", "Add users"))
|
||||||
$groupsMap[$group->ID] = $group->getBreadcrumbs(' > ');
|
->setDescription(_t("ContentReview.OWNERUSERSDESCRIPTION", "Page owners that are responsible for reviews"));
|
||||||
}
|
|
||||||
asort($groupsMap);
|
|
||||||
|
|
||||||
$groupField = ListboxField::create('OwnerGroups', _t("ContentReview.PAGEOWNERGROUPS", "Groups"), $groupsMap)
|
$fields->addFieldToTab("Root.ContentReview", $userField);
|
||||||
->setMultiple(true)
|
|
||||||
->setAttribute('data-placeholder', _t('ContentReview.ADDGROUP', 'Add groups'))
|
|
||||||
->setDescription(_t('ContentReview.OWNERGROUPSDESCRIPTION', 'Page owners that are responsible for reviews'));
|
|
||||||
$fields->addFieldToTab('Root.ContentReview', $groupField);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$groupsMap = array();
|
||||||
* Get all Members that are default Content Owners
|
|
||||||
*
|
foreach (Group::get() as $group) {
|
||||||
* This includes checking group hierarchy and adding any direct users
|
// Listboxfield values are escaped, use ASCII char instead of »
|
||||||
*
|
$groupsMap[$group->ID] = $group->getBreadcrumbs(" > ");
|
||||||
* @return \ArrayList
|
}
|
||||||
*/
|
|
||||||
public function ContentReviewOwners() {
|
asort($groupsMap);
|
||||||
return new ArrayList();
|
|
||||||
return SiteTreeContentReview::merge_owners($this->OwnerGroups(), $this->OwnerUsers());
|
$groupField = ListboxField::create("OwnerGroups", _t("ContentReview.PAGEOWNERGROUPS", "Groups"), $groupsMap)
|
||||||
}
|
->setMultiple(true)
|
||||||
|
->setAttribute("data-placeholder", _t("ContentReview.ADDGROUP", "Add groups"))
|
||||||
|
->setDescription(_t("ContentReview.OWNERGROUPSDESCRIPTION", "Page owners that are responsible for reviews"));
|
||||||
|
|
||||||
|
$fields->addFieldToTab("Root.ContentReview", $groupField);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all Members that are default Content Owners. This includes checking group hierarchy
|
||||||
|
* and adding any direct users.
|
||||||
|
*
|
||||||
|
* @return ArrayList
|
||||||
|
*/
|
||||||
|
public function ContentReviewOwners()
|
||||||
|
{
|
||||||
|
return new ArrayList();
|
||||||
|
|
||||||
|
return SiteTreeContentReview::merge_owners($this->OwnerGroups(), $this->OwnerUsers());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description of GroupContentReview
|
* Description of GroupContentReview.
|
||||||
*
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
*/
|
||||||
class ContentReviewOwner extends DataExtension {
|
class ContentReviewOwner extends DataExtension
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
*
|
* @var array
|
||||||
* @var array
|
*/
|
||||||
*/
|
private static $many_many = array(
|
||||||
private static $many_many = array(
|
"SiteTreeContentReview" => "SiteTree",
|
||||||
"SiteTreeContentReview" => "SiteTree"
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -1,537 +1,586 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set dates at which content needs to be reviewed and provide
|
* Set dates at which content needs to be reviewed and provide a report and emails to alert
|
||||||
* a report and emails to alert to content needing review
|
* to content needing review.
|
||||||
*
|
*
|
||||||
* @package contentreview
|
* @property string $ContentReviewType
|
||||||
|
* @property int $ReviewPeriodDays
|
||||||
|
* @property Date $NextReviewDate
|
||||||
|
* @property string $LastEditedByName
|
||||||
|
* @property string $OwnerNames
|
||||||
|
*
|
||||||
|
* @method DataList ReviewLogs()
|
||||||
|
* @method DataList ContentReviewGroups()
|
||||||
|
* @method DataList ContentReviewUsers()
|
||||||
*/
|
*/
|
||||||
class SiteTreeContentReview extends DataExtension implements PermissionProvider {
|
class SiteTreeContentReview extends DataExtension implements PermissionProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $db = array(
|
||||||
|
"ContentReviewType" => "Enum('Inherit, Disabled, Custom', 'Inherit')",
|
||||||
|
"ReviewPeriodDays" => "Int",
|
||||||
|
"NextReviewDate" => "Date",
|
||||||
|
"LastEditedByName" => "Varchar(255)",
|
||||||
|
"OwnerNames" => "Varchar(255)",
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @var array
|
||||||
* @var array
|
*/
|
||||||
*/
|
private static $defaults = array(
|
||||||
private static $db = array(
|
"ContentReviewType" => "Inherit",
|
||||||
"ContentReviewType" => "Enum('Inherit, Disabled, Custom', 'Inherit')",
|
);
|
||||||
"ReviewPeriodDays" => "Int",
|
|
||||||
"NextReviewDate" => "Date",
|
/**
|
||||||
'LastEditedByName' => 'Varchar(255)',
|
* @var array
|
||||||
'OwnerNames' => 'Varchar(255)'
|
*/
|
||||||
);
|
private static $has_many = array(
|
||||||
|
"ReviewLogs" => "ContentReviewLog",
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $belongs_many_many = array(
|
||||||
|
"ContentReviewGroups" => "Group",
|
||||||
|
"ContentReviewUsers" => "Member",
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $schedule = array(
|
||||||
|
0 => "No automatic review date",
|
||||||
|
1 => "1 day",
|
||||||
|
7 => "1 week",
|
||||||
|
30 => "1 month",
|
||||||
|
60 => "2 months",
|
||||||
|
91 => "3 months",
|
||||||
|
121 => "4 months",
|
||||||
|
152 => "5 months",
|
||||||
|
183 => "6 months",
|
||||||
|
365 => "12 months",
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function get_schedule()
|
||||||
|
{
|
||||||
|
return self::$schedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a list of groups and members and return a list of unique member.
|
||||||
|
*
|
||||||
|
* @param SS_List $groups
|
||||||
|
* @param SS_List $members
|
||||||
|
*
|
||||||
|
* @return ArrayList
|
||||||
|
*/
|
||||||
|
public static function merge_owners(SS_List $groups, SS_List $members)
|
||||||
|
{
|
||||||
|
$contentReviewOwners = new ArrayList();
|
||||||
|
|
||||||
|
if ($groups->count()) {
|
||||||
|
$groupIDs = array();
|
||||||
|
|
||||||
|
foreach ($groups as $group) {
|
||||||
|
$familyIDs = $group->collateFamilyIDs();
|
||||||
|
|
||||||
|
if (is_array($familyIDs)) {
|
||||||
|
$groupIDs = array_merge($groupIDs, array_values($familyIDs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array_unique($groupIDs);
|
||||||
|
|
||||||
|
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($members);
|
||||||
|
$contentReviewOwners->removeDuplicates();
|
||||||
|
|
||||||
|
return $contentReviewOwners;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param FieldList $actions
|
||||||
|
*/
|
||||||
|
public function updateCMSActions(FieldList $actions)
|
||||||
|
{
|
||||||
|
if ($this->canBeReviewedBy(Member::currentUser())) {
|
||||||
|
$reviewAction = FormAction::create("reviewed", _t("ContentReview.BUTTONREVIEWED", "Content reviewed"))
|
||||||
|
->setAttribute("data-icon", "pencil")
|
||||||
|
->setAttribute("data-text-alternate", _t("ContentReview.BUTTONREVIEWED", "Content reviewed"));
|
||||||
|
|
||||||
|
$actions->push($reviewAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns false if the content review have disabled.
|
||||||
|
*
|
||||||
|
* @param SiteTree $page
|
||||||
|
*
|
||||||
|
* @return bool|Date
|
||||||
|
*/
|
||||||
|
public function getReviewDate(SiteTree $page = null)
|
||||||
|
{
|
||||||
|
if ($page === null) {
|
||||||
|
$page = $this->owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($page->obj("NextReviewDate")->exists()) {
|
||||||
|
return $page->obj("NextReviewDate");
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = $this->owner->getOptions();
|
||||||
|
|
||||||
|
if (!$options) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$options->ReviewPeriodDays) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failover to check on ReviewPeriodDays + LastEdited
|
||||||
|
$nextReviewUnixSec = strtotime(" + " . $options->ReviewPeriodDays . " days", SS_Datetime::now()->format("U"));
|
||||||
|
$date = Date::create("NextReviewDate");
|
||||||
|
$date->setValue(date("Y-m-d H:i:s", $nextReviewUnixSec));
|
||||||
|
|
||||||
|
return $date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the object that have the information about the content review settings. Either:
|
||||||
|
*
|
||||||
|
* - a SiteTreeContentReview decorated object
|
||||||
|
* - the default SiteTree config
|
||||||
|
* - false if this page have it's content review disabled
|
||||||
|
*
|
||||||
|
* Will go through parents and root pages will use the site config if their setting is Inherit.
|
||||||
|
*
|
||||||
|
* @return bool|DataObject
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function getOptions()
|
||||||
|
{
|
||||||
|
if ($this->owner->ContentReviewType == "Custom") {
|
||||||
|
return $this->owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->owner->ContentReviewType == "Disabled") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$page = $this->owner;
|
||||||
|
|
||||||
|
// $page is inheriting it's settings from it's parent, find
|
||||||
|
// the first valid parent with a valid setting
|
||||||
|
while ($parent = $page->Parent()) {
|
||||||
|
|
||||||
|
// Root page, use site config
|
||||||
|
if (!$parent->exists()) {
|
||||||
|
return SiteConfig::current_site_config();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($parent->ContentReviewType == "Custom") {
|
||||||
|
return $parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($parent->ContentReviewType == "Disabled") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$page = $parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("This shouldn't really happen, as per usual developer logic.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getOwnerNames()
|
||||||
|
{
|
||||||
|
$options = $this->getOptions();
|
||||||
|
|
||||||
|
$names = array();
|
||||||
|
|
||||||
|
if (!$options) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($options->OwnerGroups() as $group) {
|
||||||
|
$names[] = $group->getBreadcrumbs(" > ");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($options->OwnerUsers() as $group) {
|
||||||
|
$names[] = $group->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(", ", $names);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return null|string
|
||||||
|
*/
|
||||||
|
public function getEditorName()
|
||||||
|
{
|
||||||
|
$member = Member::currentUser();
|
||||||
|
|
||||||
|
if ($member) {
|
||||||
|
return $member->FirstName . " " . $member->Surname;
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
return SiteTreeContentReview::merge_owners(
|
||||||
|
$this->OwnerGroups(),
|
||||||
|
$this->OwnerUsers()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ManyManyList
|
||||||
|
*/
|
||||||
|
public function OwnerGroups()
|
||||||
|
{
|
||||||
|
return $this->owner->getManyManyComponents("ContentReviewGroups");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ManyManyList
|
||||||
|
*/
|
||||||
|
public function OwnerUsers()
|
||||||
|
{
|
||||||
|
return $this->owner->getManyManyComponents("ContentReviewUsers");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param FieldList $fields
|
||||||
|
*/
|
||||||
|
public function updateSettingsFields(FieldList $fields)
|
||||||
|
{
|
||||||
|
Requirements::javascript("contentreview/javascript/contentreview.js");
|
||||||
|
|
||||||
|
// Display read-only version only
|
||||||
|
if (!Permission::check("EDIT_CONTENT_REVIEW_FIELDS")) {
|
||||||
|
$schedule = self::get_schedule();
|
||||||
|
$contentOwners = ReadonlyField::create("ROContentOwners", _t("ContentReview.CONTENTOWNERS", "Content Owners"), $this->getOwnerNames());
|
||||||
|
$nextReviewAt = DateField::create('RONextReviewDate', _t("ContentReview.NEXTREVIEWDATE", "Next review date"), $this->owner->NextReviewDate);
|
||||||
|
|
||||||
|
if (!isset($schedule[$this->owner->ReviewPeriodDays])) {
|
||||||
|
$reviewFreq = ReadonlyField::create("ROReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), $schedule[0]);
|
||||||
|
} else {
|
||||||
|
$reviewFreq = ReadonlyField::create("ROReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), $schedule[$this->owner->ReviewPeriodDays]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$logConfig = GridFieldConfig::create()
|
||||||
|
->addComponent(new GridFieldSortableHeader())
|
||||||
|
->addComponent($logColumns = new GridFieldDataColumns());
|
||||||
|
|
||||||
|
// Cast the value to the users preferred date format
|
||||||
|
$logColumns->setFieldCasting(array(
|
||||||
|
"Created" => "DateTimeField->value",
|
||||||
|
));
|
||||||
|
|
||||||
|
$logs = GridField::create("ROReviewNotes", "Review Notes", $this->owner->ReviewLogs(), $logConfig);
|
||||||
|
|
||||||
|
|
||||||
/**
|
$optionsFrom = ReadonlyField::create("ROType", _t("ContentReview.SETTINGSFROM", "Options are"), $this->owner->ContentReviewType);
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $defaults = array(
|
|
||||||
'ContentReviewType' => 'Inherit'
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
$fields->addFieldsToTab("Root.ContentReview", array(
|
||||||
*
|
$contentOwners,
|
||||||
* @var array
|
$nextReviewAt->performReadonlyTransformation(),
|
||||||
*/
|
$reviewFreq,
|
||||||
private static $has_many = array(
|
$optionsFrom,
|
||||||
'ReviewLogs' => 'ContentReviewLog'
|
$logs,
|
||||||
);
|
));
|
||||||
|
|
||||||
/**
|
return;
|
||||||
*
|
}
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $belongs_many_many = array(
|
|
||||||
'ContentReviewGroups' => 'Group',
|
|
||||||
'ContentReviewUsers' => 'Member'
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
$options = array();
|
||||||
*
|
$options["Disabled"] = _t("ContentReview.DISABLE", "Disable content review");
|
||||||
* @var array
|
$options["Inherit"] = _t("ContentReview.INHERIT", "Inherit from parent page");
|
||||||
*/
|
$options["Custom"] = _t("ContentReview.CUSTOM", "Custom settings");
|
||||||
private static $schedule = array(
|
|
||||||
0 => "No automatic review date",
|
|
||||||
1 => "1 day",
|
|
||||||
7 => "1 week",
|
|
||||||
30 => "1 month",
|
|
||||||
60 => "2 months",
|
|
||||||
91 => "3 months",
|
|
||||||
121 => "4 months",
|
|
||||||
152 => "5 months",
|
|
||||||
183 => "6 months",
|
|
||||||
365 => "12 months",
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
$viewersOptionsField = OptionsetField::create("ContentReviewType", _t("ContentReview.OPTIONS", "Options"), $options);
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public static function get_schedule() {
|
|
||||||
return self::$schedule;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$users = Permission::get_members_by_permission(array("CMS_ACCESS_CMSMain", "ADMIN"));
|
||||||
* Takes a list of groups and members and return a list of unique member
|
|
||||||
*
|
|
||||||
* @param SS_List $groups
|
|
||||||
* @param SS_List $members
|
|
||||||
* @return ArrayList
|
|
||||||
*/
|
|
||||||
public static function merge_owners(SS_List $groups, SS_List $members) {
|
|
||||||
$contentReviewOwners = new ArrayList();
|
|
||||||
if($groups->count()) {
|
|
||||||
$groupIDs = array();
|
|
||||||
foreach($groups as $group) {
|
|
||||||
$familyIDs = $group->collateFamilyIDs();
|
|
||||||
if(is_array($familyIDs)) {
|
|
||||||
$groupIDs = array_merge($groupIDs, array_values($familyIDs));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
array_unique($groupIDs);
|
|
||||||
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($members);
|
|
||||||
$contentReviewOwners->removeDuplicates();
|
|
||||||
return $contentReviewOwners;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$usersMap = $users->map("ID", "Title")->toArray();
|
||||||
*
|
|
||||||
* @param \FieldList $actions
|
|
||||||
*/
|
|
||||||
public function updateCMSActions(\FieldList $actions) {
|
|
||||||
if($this->canBeReviewedBy(Member::currentUser())) {
|
|
||||||
$reviewAction = FormAction::create('reviewed', _t('ContentReview.BUTTONREVIEWED', 'Content reviewed'))
|
|
||||||
->setAttribute('data-icon', 'pencil')
|
|
||||||
->setAttribute('data-text-alternate', _t('ContentReview.BUTTONREVIEWED', 'Content reviewed'));
|
|
||||||
$actions->push($reviewAction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
asort($usersMap);
|
||||||
*
|
|
||||||
* @param SiteTree $page
|
|
||||||
* @return Date | false - returns false if the content review have disabled
|
|
||||||
*/
|
|
||||||
public function getReviewDate(SiteTree $page=null) {
|
|
||||||
if($page === null) {
|
|
||||||
$page = $this->owner;
|
|
||||||
}
|
|
||||||
if($page->obj('NextReviewDate')->exists()) {
|
|
||||||
return $page->obj('NextReviewDate');
|
|
||||||
}
|
|
||||||
|
|
||||||
$options = $this->owner->getOptions();
|
$userField = ListboxField::create("OwnerUsers", _t("ContentReview.PAGEOWNERUSERS", "Users"), $usersMap)
|
||||||
|
->setMultiple(true)
|
||||||
|
->setAttribute("data-placeholder", _t("ContentReview.ADDUSERS", "Add users"))
|
||||||
|
->setDescription(_t('ContentReview.OWNERUSERSDESCRIPTION', 'Page owners that are responsible for reviews'));
|
||||||
|
|
||||||
if(!$options) {
|
$groupsMap = array();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!$options->ReviewPeriodDays) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Failover to check on ReviewPeriodDays + LastEdited
|
|
||||||
$nextReviewUnixSec = strtotime(' + '.$options->ReviewPeriodDays . ' days', SS_Datetime::now()->format('U'));
|
|
||||||
$date = Date::create('NextReviewDate');
|
|
||||||
$date->setValue(date('Y-m-d H:i:s', $nextReviewUnixSec));
|
|
||||||
return $date;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
foreach (Group::get() as $group) {
|
||||||
* Get the object that have the information about the content
|
$groupsMap[$group->ID] = $group->getBreadcrumbs(" > ");
|
||||||
* review settings. Either
|
}
|
||||||
* - a SiteTreeContentReview decorated object
|
asort($groupsMap);
|
||||||
* - the default SiteTree config
|
|
||||||
* - false if this page have it's content review disabled
|
|
||||||
*
|
|
||||||
* Will go through parents and root pages will use the siteconfig
|
|
||||||
* if their setting is Inherit.
|
|
||||||
*
|
|
||||||
* @return DataObject or false if no settings found
|
|
||||||
*/
|
|
||||||
public function getOptions() {
|
|
||||||
if($this->owner->ContentReviewType == 'Custom') {
|
|
||||||
return $this->owner;
|
|
||||||
}
|
|
||||||
if($this->owner->ContentReviewType == 'Disabled') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$page = $this->owner;
|
$groupField = ListboxField::create("OwnerGroups", _t("ContentReview.PAGEOWNERGROUPS", "Groups"), $groupsMap)
|
||||||
// $page is inheriting it's settings from it's parent, find
|
->setMultiple(true)
|
||||||
// the first valid parent with a valid setting
|
->setAttribute("data-placeholder", _t("ContentReview.ADDGROUP", "Add groups"))
|
||||||
while($parent = $page->Parent()) {
|
->setDescription(_t("ContentReview.OWNERGROUPSDESCRIPTION", "Page owners that are responsible for reviews"));
|
||||||
// Root page, use siteconfig
|
|
||||||
if(!$parent->exists()) {
|
|
||||||
return SiteConfig::current_site_config();
|
|
||||||
}
|
|
||||||
if($parent->ContentReviewType == 'Custom') {
|
|
||||||
return $parent;
|
|
||||||
}
|
|
||||||
if($parent->ContentReviewType == 'Disabled') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$page = $parent;
|
|
||||||
}
|
|
||||||
throw new Exception('This shouldn\'t really happen, as per usual developer logic.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$reviewDate = DateField::create("NextReviewDate", _t("ContentReview.NEXTREVIEWDATE", "Next review date"))
|
||||||
*
|
->setConfig("showcalendar", true)
|
||||||
* @return string
|
->setConfig("dateformat", "yyyy-MM-dd")
|
||||||
*/
|
->setConfig("datavalueformat", "yyyy-MM-dd")
|
||||||
public function getOwnerNames() {
|
->setDescription(_t("ContentReview.NEXTREVIEWDATADESCRIPTION", "Leave blank for no review"));
|
||||||
$options = $this->getOptions();
|
|
||||||
$names = array();
|
|
||||||
if(!$options) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
foreach($options->OwnerGroups() as $group) {
|
|
||||||
$names[] = $group->getBreadcrumbs(' > ');
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($options->OwnerUsers() as $group) {
|
$reviewFrequency = DropdownField::create("ReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), self::get_schedule())
|
||||||
$names[] = $group->getName();
|
->setDescription(_t("ContentReview.REVIEWFREQUENCYDESCRIPTION", "The review date will be set to this far in the future whenever the page is published"));
|
||||||
}
|
|
||||||
return implode(', ', $names);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$notesField = GridField::create("ReviewNotes", "Review Notes", $this->owner->ReviewLogs(), GridFieldConfig_RecordEditor::create());
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getEditorName() {
|
|
||||||
$member = Member::currentUser();
|
|
||||||
if($member) {
|
|
||||||
return $member->FirstName .' '. $member->Surname;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$fields->addFieldsToTab("Root.ContentReview", array(
|
||||||
* Get all Members that are Content Owners to this page
|
new HeaderField(_t("ContentReview.REVIEWHEADER", "Content review"), 2),
|
||||||
*
|
$viewersOptionsField,
|
||||||
* This includes checking group hierarchy and adding any direct users
|
CompositeField::create(
|
||||||
*
|
$userField,
|
||||||
* @return \ArrayList
|
$groupField,
|
||||||
*/
|
$reviewDate,
|
||||||
public function ContentReviewOwners() {
|
$reviewFrequency
|
||||||
return SiteTreeContentReview::merge_owners($this->OwnerGroups(), $this->OwnerUsers());
|
)->addExtraClass("custom-settings"),
|
||||||
}
|
ReadonlyField::create("ROContentOwners", _t("ContentReview.CONTENTOWNERS", "Content Owners"), $this->getOwnerNames()),
|
||||||
|
ReadonlyField::create("RONextReviewDate", _t("ContentReview.NEXTREVIEWDATE", "Next review date"), $this->owner->NextReviewDate),
|
||||||
|
$notesField,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ManyManyList
|
* Creates a ContentReviewLog and connects it to this Page.
|
||||||
*/
|
*
|
||||||
public function OwnerGroups() {
|
* @param Member $reviewer
|
||||||
return $this->owner->getManyManyComponents('ContentReviewGroups');
|
* @param string $message
|
||||||
}
|
*/
|
||||||
|
public function addReviewNote(Member $reviewer, $message)
|
||||||
|
{
|
||||||
|
$reviewLog = ContentReviewLog::create();
|
||||||
|
$reviewLog->Note = $message;
|
||||||
|
$reviewLog->ReviewerID = $reviewer->ID;
|
||||||
|
$this->owner->ReviewLogs()->add($reviewLog);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ManyManyList
|
* Advance review date to the next date based on review period or set it to null
|
||||||
*/
|
* if there is no schedule. Returns true if date was required and false is content
|
||||||
public function OwnerUsers() {
|
* review is 'off'.
|
||||||
return $this->owner->getManyManyComponents('ContentReviewUsers');
|
*
|
||||||
}
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function advanceReviewDate()
|
||||||
|
{
|
||||||
|
$nextDate = false;
|
||||||
|
$options = $this->getOptions();
|
||||||
|
|
||||||
/**
|
if ($options && $options->ReviewPeriodDays) {
|
||||||
*
|
$nextDate = date('Y-m-d', strtotime('+ ' . $options->ReviewPeriodDays . ' days', SS_Datetime::now()->format('U')));
|
||||||
* @param FieldList $fields
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function updateSettingsFields(FieldList $fields) {
|
|
||||||
|
|
||||||
Requirements::javascript('contentreview/javascript/contentreview.js');
|
$this->owner->NextReviewDate = $nextDate;
|
||||||
|
$this->owner->write();
|
||||||
|
}
|
||||||
|
|
||||||
// Display read-only version only
|
return (bool) $nextDate;
|
||||||
if(!Permission::check("EDIT_CONTENT_REVIEW_FIELDS")) {
|
}
|
||||||
$schedule = self::get_schedule();
|
|
||||||
$contentOwners = ReadonlyField::create('ROContentOwners', _t('ContentReview.CONTENTOWNERS', 'Content Owners'), $this->getOwnerNames());
|
|
||||||
$nextReviewAt = DateField::create('RONextReviewDate', _t("ContentReview.NEXTREVIEWDATE", "Next review date"), $this->owner->NextReviewDate);
|
|
||||||
if(!isset($schedule[$this->owner->ReviewPeriodDays])) {
|
|
||||||
$reviewFreq = ReadonlyField::create("ROReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), $schedule[0]);
|
|
||||||
} else {
|
|
||||||
$reviewFreq = ReadonlyField::create("ROReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), $schedule[$this->owner->ReviewPeriodDays]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$logConfig = GridFieldConfig::create()
|
/**
|
||||||
->addComponent(new GridFieldSortableHeader())
|
* Check if a review is due by a member for this owner.
|
||||||
->addComponent($logColumns = new GridFieldDataColumns());
|
*
|
||||||
// Cast the value to the users prefered date format
|
* @param Member $member
|
||||||
$logColumns->setFieldCasting(array(
|
*
|
||||||
'Created' => 'DateTimeField->value'
|
* @return bool
|
||||||
));
|
*/
|
||||||
$logs = GridField::create('ROReviewNotes', 'Review Notes', $this->owner->ReviewLogs(), $logConfig);
|
public function canBeReviewedBy(Member $member = null)
|
||||||
|
{
|
||||||
|
if (!$this->owner->obj("NextReviewDate")->exists()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->owner->obj("NextReviewDate")->InFuture()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$optionsFrom = ReadonlyField::create('ROType', _t('ContentReview.SETTINGSFROM', "Options are"), $this->owner->ContentReviewType);
|
$options = $this->getOptions();
|
||||||
|
|
||||||
$fields->addFieldsToTab("Root.ContentReview", array(
|
if ($options->OwnerGroups()->count() == 0 && $options->OwnerUsers()->count() == 0) {
|
||||||
$contentOwners,
|
return false;
|
||||||
$nextReviewAt->performReadonlyTransformation(),
|
}
|
||||||
$reviewFreq,
|
|
||||||
$optionsFrom,
|
|
||||||
$logs
|
|
||||||
));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$options = array();
|
if (!$member) {
|
||||||
$options["Disabled"] = _t('ContentReview.DISABLE', "Disable content review");
|
return true;
|
||||||
$options["Inherit"] = _t('ContentReview.INHERIT', "Inherit from parent page");
|
}
|
||||||
$options["Custom"] = _t('ContentReview.CUSTOM', "Custom settings");
|
|
||||||
$viewersOptionsField = OptionsetField::create("ContentReviewType", _t('ContentReview.OPTIONS', "Options"), $options);
|
|
||||||
|
|
||||||
$users = Permission::get_members_by_permission(array("CMS_ACCESS_CMSMain", "ADMIN"));
|
if ($member->inGroups($options->OwnerGroups())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$usersMap = $users->map('ID', 'Title')->toArray();
|
if ($options->OwnerUsers()->find("ID", $member->ID)) {
|
||||||
asort($usersMap);
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$userField = ListboxField::create('OwnerUsers', _t("ContentReview.PAGEOWNERUSERS", "Users"), $usersMap)
|
return false;
|
||||||
->setMultiple(true)
|
}
|
||||||
->setAttribute('data-placeholder', _t('ContentReview.ADDUSERS', 'Add users'))
|
|
||||||
->setDescription(_t('ContentReview.OWNERUSERSDESCRIPTION', 'Page owners that are responsible for reviews'));
|
|
||||||
|
|
||||||
$groupsMap = array();
|
/**
|
||||||
foreach(Group::get() as $group) {
|
* Set the review data from the review period, if set.
|
||||||
// Listboxfield values are escaped, use ASCII char instead of »
|
*/
|
||||||
$groupsMap[$group->ID] = $group->getBreadcrumbs(' > ');
|
public function onBeforeWrite()
|
||||||
}
|
{
|
||||||
asort($groupsMap);
|
$this->owner->LastEditedByName = $this->owner->getEditorName();
|
||||||
|
$this->owner->OwnerNames = $this->owner->getOwnerNames();
|
||||||
|
|
||||||
$groupField = ListboxField::create('OwnerGroups', _t("ContentReview.PAGEOWNERGROUPS", "Groups"), $groupsMap)
|
// If the user changed the type, we need to recalculate the review date.
|
||||||
->setMultiple(true)
|
if ($this->owner->isChanged("ContentReviewType", 2)) {
|
||||||
->setAttribute('data-placeholder', _t('ContentReview.ADDGROUP', 'Add groups'))
|
if ($this->owner->ContentReviewType == "Disabled") {
|
||||||
->setDescription(_t('ContentReview.OWNERGROUPSDESCRIPTION', 'Page owners that are responsible for reviews'));
|
$this->setDefaultReviewDateForDisabled();
|
||||||
|
} elseif ($this->owner->ContentReviewType == "Custom") {
|
||||||
|
$this->setDefaultReviewDateForCustom();
|
||||||
|
} else {
|
||||||
|
$this->setDefaultReviewDateForInherited();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$reviewDate = DateField::create("NextReviewDate", _t("ContentReview.NEXTREVIEWDATE", "Next review date"))
|
// Ensure that a inherited page always have a next review date
|
||||||
->setConfig('showcalendar', true)
|
if ($this->owner->ContentReviewType == "Inherit" && !$this->owner->NextReviewDate) {
|
||||||
->setConfig('dateformat', 'yyyy-MM-dd')
|
$this->setDefaultReviewDateForInherited();
|
||||||
->setConfig('datavalueformat', 'yyyy-MM-dd')
|
}
|
||||||
->setDescription(_t('ContentReview.NEXTREVIEWDATADESCRIPTION', 'Leave blank for no review'));
|
|
||||||
|
|
||||||
$reviewFrequency = DropdownField::create("ReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), self::get_schedule())
|
// We need to update all the child pages that inherit this setting. We can only
|
||||||
->setDescription(_t('ContentReview.REVIEWFREQUENCYDESCRIPTION', 'The review date will be set to this far in the future whenever the page is published'));
|
// change children after this record has been created, otherwise the stageChildren
|
||||||
|
// method will grab all pages in the DB (this messes up unit testing)
|
||||||
|
if (!$this->owner->exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$notesField = GridField::create('ReviewNotes', 'Review Notes', $this->owner->ReviewLogs(), GridFieldConfig_RecordEditor::create());
|
// parent page change it's review period
|
||||||
|
// && !$this->owner->isChanged('ContentReviewType', 2)
|
||||||
|
if ($this->owner->isChanged("ReviewPeriodDays", 2)) {
|
||||||
|
$nextReviewUnixSec = strtotime(" + " . $this->owner->ReviewPeriodDays . " days", SS_Datetime::now()->format("U"));
|
||||||
|
$this->owner->NextReviewDate = date("Y-m-d", $nextReviewUnixSec);
|
||||||
|
}
|
||||||
|
|
||||||
$schedule = self::get_schedule();
|
//
|
||||||
|
if ($this->owner->isChanged("NextReviewDate", 2)) {
|
||||||
|
$children = $this->owner->stageChildren(true)->filter("ContentReviewType", "Inherit");
|
||||||
|
$compatibility = ContentReviewCompatability::start();
|
||||||
|
|
||||||
$fields->addFieldsToTab("Root.ContentReview", array(
|
foreach ($children as $child) {
|
||||||
new HeaderField(_t('ContentReview.REVIEWHEADER', "Content review"), 2),
|
$child->NextReviewDate = $this->owner->NextReviewDate;
|
||||||
$viewersOptionsField,
|
$child->write();
|
||||||
CompositeField::create(
|
}
|
||||||
$userField,
|
|
||||||
$groupField,
|
|
||||||
$reviewDate,
|
|
||||||
$reviewFrequency
|
|
||||||
)->addExtraClass('custom-settings'),
|
|
||||||
ReadonlyField::create('ROContentOwners', _t('ContentReview.CONTENTOWNERS', 'Content Owners'), $this->getOwnerNames()),
|
|
||||||
ReadonlyField::create('RONextReviewDate', _t("ContentReview.NEXTREVIEWDATE", "Next review date"), $this->owner->NextReviewDate),
|
|
||||||
$notesField
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
ContentReviewCompatability::done($compatibility);
|
||||||
* Creates a ContentReviewLog and connects it to this Page
|
}
|
||||||
*
|
}
|
||||||
* @param Member $reviewer
|
|
||||||
* @param string $message
|
|
||||||
*/
|
|
||||||
public function addReviewNote(Member $reviewer, $message) {
|
|
||||||
$reviewLog = ContentReviewLog::create();
|
|
||||||
$reviewLog->Note = $message;
|
|
||||||
$reviewLog->ReviewerID = $reviewer->ID;
|
|
||||||
$this->owner->ReviewLogs()->add($reviewLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
private function setDefaultReviewDateForDisabled()
|
||||||
* Advance review date to the next date based on review period or set it to null
|
{
|
||||||
* if there is no schedule
|
$this->owner->NextReviewDate = null;
|
||||||
*
|
}
|
||||||
* @return bool - returns true if date was set and false is content review is 'off'
|
|
||||||
*/
|
|
||||||
public function advanceReviewDate() {
|
|
||||||
$options = $this->getOptions();
|
|
||||||
$nextDate = false;
|
|
||||||
if($options && $options->ReviewPeriodDays) {
|
|
||||||
$nextDate = date('Y-m-d', strtotime('+ '.$options->ReviewPeriodDays.' days', SS_Datetime::now()->format('U')));
|
|
||||||
}
|
|
||||||
$this->owner->NextReviewDate = $nextDate;
|
|
||||||
$this->owner->write();
|
|
||||||
return (bool)$nextDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
protected function setDefaultReviewDateForCustom()
|
||||||
* Check if a review is due by a member for this owner
|
{
|
||||||
*
|
if ($this->owner->NextReviewDate) {
|
||||||
* @param Member $member
|
return;
|
||||||
* @return boolean
|
}
|
||||||
*/
|
|
||||||
public function canBeReviewedBy(Member $member = null) {
|
|
||||||
if(!$this->owner->obj('NextReviewDate')->exists()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if($this->owner->obj('NextReviewDate')->InFuture()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$options = $this->getOptions();
|
$this->owner->NextReviewDate = null;
|
||||||
|
$nextDate = $this->getReviewDate();
|
||||||
|
|
||||||
if($options->OwnerGroups()->count() == 0 && $options->OwnerUsers()->count() == 0) {
|
if (is_object($nextDate)) {
|
||||||
return false;
|
$this->owner->NextReviewDate = $nextDate->getValue();
|
||||||
}
|
} else {
|
||||||
|
$this->owner->NextReviewDate = $nextDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This content should be reviewed by someone
|
protected function setDefaultReviewDateForInherited()
|
||||||
if(!$member) {
|
{
|
||||||
return true;
|
$options = $this->getOptions();
|
||||||
}
|
$nextDate = null;
|
||||||
|
|
||||||
if($member->inGroups($options->OwnerGroups())) {
|
if ($options && $this->owner->parent()->exists()) {
|
||||||
return true;
|
$nextDate = $this->getReviewDate($this->owner->parent());
|
||||||
}
|
} elseif ($options instanceof SiteConfig) {
|
||||||
|
$nextDate = $this->getReviewDate();
|
||||||
|
}
|
||||||
|
|
||||||
if($options->OwnerUsers()->find('ID', $member->ID)) {
|
if (is_object($nextDate)) {
|
||||||
return true;
|
$this->owner->NextReviewDate = $nextDate->getValue();
|
||||||
}
|
} else {
|
||||||
return false;
|
$this->owner->NextReviewDate = $nextDate;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the review data from the review period, if set.
|
* Provide permissions to the CMS.
|
||||||
*/
|
*
|
||||||
public function onBeforeWrite() {
|
* @return array
|
||||||
$this->owner->LastEditedByName=$this->owner->getEditorName();
|
*/
|
||||||
$this->owner->OwnerNames = $this->owner->getOwnerNames();
|
public function providePermissions()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
"EDIT_CONTENT_REVIEW_FIELDS" => array(
|
||||||
|
"name" => "Set content owners and review dates",
|
||||||
|
"category" => _t("Permissions.CONTENT_CATEGORY", "Content permissions"),
|
||||||
|
"sort" => 50,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// If the user changed the Type, we need to recalculate the
|
/**
|
||||||
// Next review date
|
* If the queued jobs module is installed, queue up the first job for 9am tomorrow morning
|
||||||
if($this->owner->isChanged('ContentReviewType', 2)) {
|
* (by default).
|
||||||
|
*/
|
||||||
|
public function requireDefaultRecords()
|
||||||
|
{
|
||||||
|
if (class_exists("ContentReviewNotificationJob")) {
|
||||||
|
// Ensure there is not already a job queued
|
||||||
|
if (QueuedJobDescriptor::get()->filter("Implementation", "ContentReviewNotificationJob")->first()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Changed to Disabled
|
$nextRun = new ContentReviewNotificationJob();
|
||||||
if($this->owner->ContentReviewType == 'Disabled') {
|
$runHour = Config::inst()->get("ContentReviewNotificationJob", "first_run_hour");
|
||||||
$this->setDefaultReviewDateForDisabled();
|
$firstRunTime = date("Y-m-d H:i:s", mktime($runHour, 0, 0, date("m"), date("d") + 1, date("y")));
|
||||||
// Changed to Custom
|
|
||||||
} elseif($this->owner->ContentReviewType == 'Custom') {
|
|
||||||
$this->setDefaultReviewDateForCustom();
|
|
||||||
// Changed to Inherit
|
|
||||||
} else {
|
|
||||||
$this->setDefaultReviewDateForInherited();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that a inherited page always have a next review date
|
singleton("QueuedJobService")->queueJob(
|
||||||
if($this->owner->ContentReviewType == 'Inherit' && !$this->owner->NextReviewDate) {
|
$nextRun,
|
||||||
$this->setDefaultReviewDateForInherited();
|
$firstRunTime
|
||||||
}
|
);
|
||||||
|
|
||||||
// Oh yey.. now we need to update all the child pages that inherit this setting
|
DB::alteration_message(sprintf("Added ContentReviewNotificationJob to run at %s", $firstRunTime));
|
||||||
// We can only change children after this record has been created, otherwise the stageChildren
|
}
|
||||||
// method will grab all pages in the DB (this messes up unittesting)
|
}
|
||||||
if(!$this->owner->exists()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// parent page change it's review period
|
|
||||||
// && !$this->owner->isChanged('ContentReviewType', 2)
|
|
||||||
if($this->owner->isChanged('ReviewPeriodDays', 2)) {
|
|
||||||
$nextReviewUnixSec = strtotime(' + '.$this->owner->ReviewPeriodDays . ' days', SS_Datetime::now()->format('U'));
|
|
||||||
$this->owner->NextReviewDate = date('Y-m-d', $nextReviewUnixSec);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
if($this->owner->isChanged('NextReviewDate', 2)) {
|
|
||||||
$c = ContentReviewCompatability::start();
|
|
||||||
$children = $this->owner->stageChildren(true)->filter('ContentReviewType', 'Inherit');
|
|
||||||
foreach($children as $child) {
|
|
||||||
$child->NextReviewDate = $this->owner->NextReviewDate;
|
|
||||||
$child->write();
|
|
||||||
}
|
|
||||||
ContentReviewCompatability::done($c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private function setDefaultReviewDateForDisabled() {
|
|
||||||
$this->owner->NextReviewDate = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function setDefaultReviewDateForCustom() {
|
|
||||||
if($this->owner->NextReviewDate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->owner->NextReviewDate = null;
|
|
||||||
$nextDate = $this->getReviewDate();
|
|
||||||
|
|
||||||
if(is_object($nextDate)) {
|
|
||||||
$this->owner->NextReviewDate = $nextDate->getValue();
|
|
||||||
} else {
|
|
||||||
$this->owner->NextReviewDate = $nextDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function setDefaultReviewDateForInherited() {
|
|
||||||
$options = $this->getOptions();
|
|
||||||
$nextDate = null;
|
|
||||||
// Set the review date to be the same as the parents reviewdate
|
|
||||||
if($options && $this->owner->parent()->exists()) {
|
|
||||||
$nextDate = $this->getReviewDate($this->owner->parent());
|
|
||||||
// Use the defualt settings
|
|
||||||
} elseif($options instanceof SiteConfig) {
|
|
||||||
$nextDate = $this->getReviewDate();
|
|
||||||
}
|
|
||||||
if(is_object($nextDate)) {
|
|
||||||
$this->owner->NextReviewDate = $nextDate->getValue();
|
|
||||||
} else {
|
|
||||||
$this->owner->NextReviewDate = $nextDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide permissions to the CMS
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function providePermissions() {
|
|
||||||
return array(
|
|
||||||
"EDIT_CONTENT_REVIEW_FIELDS" => array(
|
|
||||||
'name' => "Set content owners and review dates",
|
|
||||||
'category' => _t('Permissions.CONTENT_CATEGORY', 'Content permissions'),
|
|
||||||
'sort' => 50
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the queuedjobs module is installed, queue up the first job for 9am tomorrow morning (by default)
|
|
||||||
*/
|
|
||||||
public function requireDefaultRecords() {
|
|
||||||
if(class_exists('ContentReviewNotificationJob')) {
|
|
||||||
// Ensure there is not already a job queued
|
|
||||||
if(QueuedJobDescriptor::get()->filter('Implementation', 'ContentReviewNotificationJob')->first()) return;
|
|
||||||
|
|
||||||
$nextRun = new ContentReviewNotificationJob();
|
|
||||||
$runHour = Config::inst()->get('ContentReviewNotificationJob', 'first_run_hour');
|
|
||||||
$firstRunTime = date('Y-m-d H:i:s', mktime($runHour, 0, 0, date("m"), date("d")+1, date("y")));
|
|
||||||
|
|
||||||
singleton('QueuedJobService')->queueJob(
|
|
||||||
$nextRun,
|
|
||||||
$firstRunTime
|
|
||||||
);
|
|
||||||
|
|
||||||
DB::alteration_message(sprintf('Added ContentReviewNotificationJob to run at %s', $firstRunTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,82 +1,106 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
if(!class_exists('AbstractQueuedJob')) {
|
if (!class_exists("AbstractQueuedJob")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ContentReviewNotificationJob
|
* Allows the content review module to use the optional queued jobs module to automatically
|
||||||
*
|
* process content review emails. If the module isn't installed, nothing is done - SilverStripe
|
||||||
* Allows the contentreview module to use the optional queuedjobs module to automatically process content review emails.
|
* will never include this class declaration.
|
||||||
* If the module isn't installed, nothing is done - SilverStripe will never include this class declaration.
|
|
||||||
*
|
*
|
||||||
* If the module is installed, it will create a new job to be processed once every day by default.
|
* If the module is installed, it will create a new job to be processed once every day by default.
|
||||||
*
|
*
|
||||||
* @see https://github.com/silverstripe-australia/silverstripe-queuedjobs
|
* @see https://github.com/silverstripe-australia/silverstripe-queuedjobs
|
||||||
*/
|
*/
|
||||||
class ContentReviewNotificationJob extends AbstractQueuedJob implements QueuedJob {
|
class ContentReviewNotificationJob extends AbstractQueuedJob implements QueuedJob
|
||||||
/**
|
{
|
||||||
* @var int The hour that the first job will be created at (for the next day). All other jobs should be triggered
|
/**
|
||||||
* around this time too, as the next generation is queued when this job is run.
|
* The hour that the first job will be created at (for the next day). All other jobs should
|
||||||
* @config
|
* be triggered around this time too, as the next generation is queued when this job is run.
|
||||||
*/
|
*
|
||||||
private static $first_run_hour = 9;
|
* @var int
|
||||||
|
*
|
||||||
|
* @config
|
||||||
|
*/
|
||||||
|
private static $first_run_hour = 9;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int The hour at which to run these jobs
|
* The hour at which to run these jobs.
|
||||||
* @config
|
*
|
||||||
*/
|
* @var int
|
||||||
private static $next_run_hour = 9;
|
*
|
||||||
|
* @config
|
||||||
|
*/
|
||||||
|
private static $next_run_hour = 9;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int The minutes past the hour (see above) at which to run these jobs
|
* The minutes past the hour (see above) at which to run these jobs.
|
||||||
* @config
|
*
|
||||||
*/
|
* @var int
|
||||||
private static $next_run_minute = 0;
|
*
|
||||||
|
* @config
|
||||||
|
*/
|
||||||
|
private static $next_run_minute = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int The number of days to skip between job runs (e.g. 1 means run this job every day, 2 means run it every
|
* The number of days to skip between job runs (1 means run this job every day,
|
||||||
* second day etc.)
|
* 2 means run it every second day etc).
|
||||||
* @config
|
*
|
||||||
*/
|
* @var int
|
||||||
private static $next_run_in_days = 1;
|
*
|
||||||
|
* @config
|
||||||
|
*/
|
||||||
|
private static $next_run_in_days = 1;
|
||||||
|
|
||||||
public function getTitle() {
|
/**
|
||||||
return 'Content Review Notification Job';
|
* @return string
|
||||||
}
|
*/
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
return "Content Review Notification Job";
|
||||||
|
}
|
||||||
|
|
||||||
public function getJobType() {
|
/**
|
||||||
$this->totalSteps = 1;
|
* @return string
|
||||||
return QueuedJob::QUEUED;
|
*/
|
||||||
}
|
public function getJobType()
|
||||||
|
{
|
||||||
|
$this->totalSteps = 1;
|
||||||
|
|
||||||
public function process() {
|
return QueuedJob::QUEUED;
|
||||||
$this->queueNextRun();
|
}
|
||||||
|
|
||||||
$task = new ContentReviewEmails();
|
public function process()
|
||||||
$task->run(new SS_HTTPRequest('GET', '/dev/tasks/ContentReviewEmails'));
|
{
|
||||||
|
$this->queueNextRun();
|
||||||
|
|
||||||
$this->currentStep = 1;
|
$task = new ContentReviewEmails();
|
||||||
$this->isComplete = true;
|
$task->run(new SS_HTTPRequest("GET", "/dev/tasks/ContentReviewEmails"));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$this->currentStep = 1;
|
||||||
* Queue up the next job to run.
|
$this->isComplete = true;
|
||||||
*/
|
}
|
||||||
protected function queueNextRun() {
|
|
||||||
$nextRun = new ContentReviewNotificationJob();
|
|
||||||
$nextRunTime = mktime(
|
|
||||||
self::$next_run_hour,
|
|
||||||
self::$next_run_minute,
|
|
||||||
0,
|
|
||||||
date('m'),
|
|
||||||
date('d') + self::$next_run_in_days,
|
|
||||||
date('Y')
|
|
||||||
);
|
|
||||||
|
|
||||||
singleton('QueuedJobService')->queueJob(
|
/**
|
||||||
$nextRun,
|
* Queue up the next job to run.
|
||||||
date('Y-m-d H:i:s', $nextRunTime)
|
*/
|
||||||
);
|
protected function queueNextRun()
|
||||||
}
|
{
|
||||||
|
$nextRun = new ContentReviewNotificationJob();
|
||||||
|
|
||||||
|
$nextRunTime = mktime(
|
||||||
|
self::$next_run_hour,
|
||||||
|
self::$next_run_minute,
|
||||||
|
0,
|
||||||
|
date("m"),
|
||||||
|
date("d") + self::$next_run_in_days,
|
||||||
|
date("Y")
|
||||||
|
);
|
||||||
|
|
||||||
|
singleton("QueuedJobService")->queueJob(
|
||||||
|
$nextRun,
|
||||||
|
date("Y-m-d H:i:s", $nextRunTime)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,45 +1,43 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class ContentReviewLog extends DataObject {
|
class ContentReviewLog extends DataObject
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $db = array(
|
||||||
|
"Note" => "Text",
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @var array
|
||||||
* @var array
|
*/
|
||||||
*/
|
private static $has_one = array(
|
||||||
private static $db = array(
|
"Reviewer" => "Member",
|
||||||
'Note' => 'Text'
|
"SiteTree" => "SiteTree",
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @var array
|
||||||
* @var array
|
*/
|
||||||
*/
|
private static $summary_fields = array(
|
||||||
private static $has_one = array(
|
"Note" => array("title" => "Note"),
|
||||||
'Reviewer' => 'Member',
|
"Created" => array("title" => "Reviewed at"),
|
||||||
'SiteTree' => 'SiteTree'
|
"Reviewer.Title" => array("title" => "Reviewed by"),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @var string
|
||||||
* @var array
|
*/
|
||||||
*/
|
private static $default_sort = "Created DESC";
|
||||||
private static $summary_fields = array(
|
|
||||||
'Note' => array('title' => 'Note'),
|
|
||||||
'Created' => array('title' => 'Reviewed at'),
|
|
||||||
'Reviewer.Title' => array('title' => 'Reviewed by')
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param mixed $member
|
||||||
* @var string
|
*
|
||||||
*/
|
* @return bool
|
||||||
private static $default_sort = 'Created DESC';
|
*/
|
||||||
|
public function canView($member = null)
|
||||||
/**
|
{
|
||||||
*
|
return (bool) Member::currentUser();
|
||||||
* @return bool
|
}
|
||||||
*/
|
|
||||||
public function canView($member = null) {
|
|
||||||
return (bool)Member::currentUser();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,165 +1,168 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once 'Zend/Date.php';
|
|
||||||
|
require_once "Zend/Date.php";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show all pages that need to be reviewed
|
* Show all pages that need to be reviewed.
|
||||||
*
|
|
||||||
* @package contentreview
|
|
||||||
*/
|
*/
|
||||||
class PagesDueForReviewReport extends SS_Report {
|
class PagesDueForReviewReport extends SS_Report
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function title()
|
||||||
|
{
|
||||||
|
return _t("PagesDueForReviewReport.TITLE", "Pages due for review");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @return FieldList
|
||||||
* @return string
|
*/
|
||||||
*/
|
public function parameterFields()
|
||||||
public function title() {
|
{
|
||||||
return _t('PagesDueForReviewReport.TITLE', 'Pages due for review');
|
$filtersList = new FieldList();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$filtersList->push(
|
||||||
*
|
DateField::create("ReviewDateAfter", "Review date after or on")
|
||||||
* @return \FieldList
|
->setConfig("showcalendar", true)
|
||||||
*/
|
);
|
||||||
public function parameterFields() {
|
|
||||||
$filtersList = new FieldList();
|
|
||||||
|
|
||||||
$filtersList->push(
|
$filtersList->push(
|
||||||
DateField::create('ReviewDateAfter', 'Review date after or on')
|
DateField::create("ReviewDateBefore", "Review date before or on", date("d/m/Y", strtotime("midnight")))
|
||||||
->setConfig('showcalendar', true)
|
->setConfig("showcalendar", true)
|
||||||
);
|
);
|
||||||
$filtersList->push(
|
|
||||||
DateField::create('ReviewDateBefore', 'Review date before or on', date('d/m/Y', strtotime('midnight')))
|
|
||||||
->setConfig('showcalendar', true)
|
|
||||||
);
|
|
||||||
|
|
||||||
$filtersList->push(new CheckboxField('ShowVirtualPages', 'Show Virtual Pages'));
|
$filtersList->push(new CheckboxField("ShowVirtualPages", "Show Virtual Pages"));
|
||||||
|
|
||||||
return $filtersList;
|
return $filtersList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @return array
|
||||||
* @return array
|
*/
|
||||||
*/
|
public function columns()
|
||||||
public function columns() {
|
{
|
||||||
|
$linkBase = singleton("CMSPageEditController")->Link("show");
|
||||||
|
$linkPath = parse_url($linkBase, PHP_URL_PATH);
|
||||||
|
$linkQuery = parse_url($linkBase, PHP_URL_QUERY);
|
||||||
|
|
||||||
$linkBase = singleton('CMSPageEditController')->Link('show');
|
$fields = array(
|
||||||
$linkPath = parse_url($linkBase, PHP_URL_PATH);
|
"Title" => array(
|
||||||
$linkQuery = parse_url($linkBase, PHP_URL_QUERY);
|
"title" => "Page name",
|
||||||
|
"formatting" => "<a href='{$linkPath}/\$ID?{$linkQuery}' title='Edit page'>\$value</a>"
|
||||||
|
),
|
||||||
|
"NextReviewDate" => array(
|
||||||
|
"title" => "Review Date",
|
||||||
|
"casting" => "Date->Full",
|
||||||
|
"formatting" => function ($value, $item) {
|
||||||
|
if ($item->ContentReviewType == "Disabled") {
|
||||||
|
return "disabled";
|
||||||
|
}
|
||||||
|
if ($item->ContentReviewType == "Inherit") {
|
||||||
|
$setting = $item->getOptions();
|
||||||
|
if (!$setting) {
|
||||||
|
return "disabled";
|
||||||
|
}
|
||||||
|
return $item->obj("NextReviewDate")->Full();
|
||||||
|
}
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
),
|
||||||
|
"OwnerNames" => array(
|
||||||
|
"title" => "Owner"
|
||||||
|
),
|
||||||
|
"LastEditedByName" => "Last edited by",
|
||||||
|
"AbsoluteLink" => array(
|
||||||
|
"title" => "URL",
|
||||||
|
"formatting" => function ($value, $item) {
|
||||||
|
$liveLink = $item->AbsoluteLiveLink;
|
||||||
|
$stageLink = $item->AbsoluteLink();
|
||||||
|
|
||||||
|
return sprintf("%s <a href='%s'>%s</a>",
|
||||||
|
$stageLink,
|
||||||
|
$liveLink ? $liveLink : $stageLink . "?stage=Stage",
|
||||||
|
$liveLink ? "(live)" : "(draft)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
"ContentReviewType" => array(
|
||||||
|
"title" => "Settings are",
|
||||||
|
"formatting" => function ($value, $item) use ($linkPath,$linkQuery) {
|
||||||
|
if ($item->ContentReviewType == "Inherit") {
|
||||||
|
$options = $item->getOptions();
|
||||||
|
if ($options && $options instanceof SiteConfig) {
|
||||||
|
return "Inherited from <a href='admin/settings'>Settings</a>";
|
||||||
|
} elseif ($options) {
|
||||||
|
return sprintf(
|
||||||
|
"Inherited from <a href='%s/%d?%s'>%s</a>",
|
||||||
|
$linkPath,
|
||||||
|
$options->ID,
|
||||||
|
$linkQuery,
|
||||||
|
$options->Title
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$fields = array(
|
return $value;
|
||||||
'Title' => array(
|
}
|
||||||
'title' => 'Page name',
|
),
|
||||||
'formatting' => sprintf('<a href=\"%s/$ID?%s\" title=\"Edit page\">$value</a>', $linkPath, $linkQuery)
|
);
|
||||||
),
|
|
||||||
'NextReviewDate' => array(
|
|
||||||
'title' => 'Review Date',
|
|
||||||
'casting' => 'Date->Full',
|
|
||||||
'formatting' => function($value, $item) {
|
|
||||||
if($item->ContentReviewType == 'Disabled') {
|
|
||||||
return 'disabled';
|
|
||||||
}
|
|
||||||
if($item->ContentReviewType == 'Inherit') {
|
|
||||||
$setting = $item->getOptions();
|
|
||||||
if(!$setting) {
|
|
||||||
return 'disabled';
|
|
||||||
}
|
|
||||||
return $item->obj('NextReviewDate')->Full();
|
|
||||||
}
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
),
|
|
||||||
'OwnerNames' => array(
|
|
||||||
'title' => 'Owner'
|
|
||||||
),
|
|
||||||
'LastEditedByName' => 'Last edited by',
|
|
||||||
'AbsoluteLink' => array(
|
|
||||||
'title' => 'URL',
|
|
||||||
'formatting' => function($value, $item) {
|
|
||||||
$liveLink = $item->AbsoluteLiveLink;
|
|
||||||
$stageLink = $item->AbsoluteLink();
|
|
||||||
return sprintf('%s <a href="%s">%s</a>',
|
|
||||||
$stageLink,
|
|
||||||
$liveLink ? $liveLink : $stageLink . '?stage=Stage',
|
|
||||||
$liveLink ? '(live)' : '(draft)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
),
|
|
||||||
'ContentReviewType' => array(
|
|
||||||
'title' => 'Settings are',
|
|
||||||
'formatting' => function($value, $item) use($linkPath, $linkQuery) {
|
|
||||||
if($item->ContentReviewType == 'Inherit') {
|
|
||||||
$options = $item->getOptions();
|
|
||||||
if($options && $options instanceof SiteConfig) {
|
|
||||||
return 'Inherited from <a href="admin/settings">Settings</a>';
|
|
||||||
} elseif($options) {
|
|
||||||
return sprintf(
|
|
||||||
'Inherited from <a href="%s/%d?%s">%s</a>',
|
|
||||||
$linkPath,
|
|
||||||
$options->ID,
|
|
||||||
$linkQuery,
|
|
||||||
$options->Title
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param array $params
|
||||||
* @param array $params
|
*
|
||||||
* @return SS_List
|
* @return SS_List
|
||||||
*/
|
*/public function sourceRecords($params = array())
|
||||||
public function sourceRecords($params = array()) {
|
{
|
||||||
Versioned::reading_stage('Stage');
|
Versioned::reading_stage("Stage");
|
||||||
$c = ContentReviewCompatability::start();
|
|
||||||
$records = SiteTree::get();
|
|
||||||
|
|
||||||
if(empty($params['ReviewDateBefore']) && empty($params['ReviewDateAfter'])) {
|
$records = SiteTree::get();
|
||||||
// If there's no review dates set, default to all pages due for review now
|
$compatibility = ContentReviewCompatability::start();
|
||||||
$reviewDate = new Zend_Date(SS_Datetime::now()->Format('U'));
|
|
||||||
$reviewDate->add(1, Zend_Date::DAY);
|
|
||||||
$records = $records->where(sprintf('"NextReviewDate" < \'%s\'', $reviewDate->toString('YYYY-MM-dd')));
|
|
||||||
} else {
|
|
||||||
// Review date before
|
|
||||||
if(!empty($params['ReviewDateBefore'])) {
|
|
||||||
// TODO Get value from DateField->dataValue() once we have access to form elements here
|
|
||||||
$reviewDate = new Zend_Date($params['ReviewDateBefore'], i18n::get_date_format());
|
|
||||||
$reviewDate->add(1, Zend_Date::DAY);
|
|
||||||
$records = $records->where(sprintf('"NextReviewDate" < \'%s\'', $reviewDate->toString('YYYY-MM-dd')));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Review date after
|
if (empty($params["ReviewDateBefore"]) && empty($params["ReviewDateAfter"])) {
|
||||||
if(!empty($params['ReviewDateAfter'])) {
|
// If there's no review dates set, default to all pages due for review now
|
||||||
// TODO Get value from DateField->dataValue() once we have access to form elements here
|
$reviewDate = new Zend_Date(SS_Datetime::now()->Format("U"));
|
||||||
$reviewDate = new Zend_Date($params['ReviewDateAfter'], i18n::get_date_format());
|
$reviewDate->add(1, Zend_Date::DAY);
|
||||||
$records = $records->where(sprintf('"NextReviewDate" >= \'%s\'', $reviewDate->toString('YYYY-MM-dd')));
|
$records = $records->where(sprintf('"NextReviewDate" < \'%s\'', $reviewDate->toString("YYYY-MM-dd")));
|
||||||
}
|
} else {
|
||||||
}
|
// Review date before
|
||||||
|
if (!empty($params['ReviewDateBefore'])) {
|
||||||
|
// TODO Get value from DateField->dataValue() once we have access to form elements here
|
||||||
|
$reviewDate = new Zend_Date($params["ReviewDateBefore"], Config::inst()->get("i18n", "date_format"));
|
||||||
|
$reviewDate->add(1, Zend_Date::DAY);
|
||||||
|
$records = $records->where(sprintf("\"NextReviewDate\" < '%s'", $reviewDate->toString("YYYY-MM-dd")));
|
||||||
|
}
|
||||||
|
|
||||||
// Show virtual pages?
|
// Review date after
|
||||||
if(empty($params['ShowVirtualPages'])) {
|
if (!empty($params["ReviewDateAfter"])) {
|
||||||
$virtualPageClasses = ClassInfo::subclassesFor('VirtualPage');
|
// TODO Get value from DateField->dataValue() once we have access to form elements here
|
||||||
$records = $records->where(sprintf(
|
$reviewDate = new Zend_Date($params["ReviewDateAfter"], Config::inst()->get("i18n", "date_format"));
|
||||||
'"SiteTree"."ClassName" NOT IN (\'%s\')',
|
$records = $records->where(sprintf("\"NextReviewDate\" >= '%s'", $reviewDate->toString("YYYY-MM-dd")));
|
||||||
implode("','", array_values($virtualPageClasses))
|
}
|
||||||
));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Owner dropdown
|
// Show virtual pages?
|
||||||
if(!empty($params['ContentReviewOwner'])) {
|
if (empty($params["ShowVirtualPages"])) {
|
||||||
$ownerNames = Convert::raw2sql($params['ContentReviewOwner']);
|
$virtualPageClasses = ClassInfo::subclassesFor("VirtualPage");
|
||||||
$records = $records->filter('OwnerNames:PartialMatch', $ownerNames);
|
$records = $records->where(sprintf(
|
||||||
}
|
"\"SiteTree\".\"ClassName\" NOT IN ('%s')",
|
||||||
|
implode("','", array_values($virtualPageClasses))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
$r = new ArrayList($records->sort('NextReviewDate', 'DESC')->toArray());
|
// Owner dropdown
|
||||||
ContentReviewCompatability::done($c);
|
if (!empty($params["ContentReviewOwner"])) {
|
||||||
return $r;
|
$ownerNames = Convert::raw2sql($params["ContentReviewOwner"]);
|
||||||
}
|
$records = $records->filter("OwnerNames:PartialMatch", $ownerNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
$records = new ArrayList($records->sort("NextReviewDate", "DESC")->toArray());
|
||||||
|
|
||||||
|
ContentReviewCompatability::done($compatibility);
|
||||||
|
|
||||||
|
return $records;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,142 +1,148 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once 'Zend/Date.php';
|
|
||||||
|
require_once "Zend/Date.php";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show all pages that need to be reviewed
|
* Show all pages that need to be reviewed.
|
||||||
*
|
|
||||||
* @package contentreview
|
|
||||||
*/
|
*/
|
||||||
class PagesWithoutReviewScheduleReport extends SS_Report {
|
class PagesWithoutReviewScheduleReport extends SS_Report
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function title()
|
||||||
|
{
|
||||||
|
return _t("PagesWithoutReviewScheduleReport.TITLE", "Pages without a scheduled review.");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @return FieldList
|
||||||
* @return string
|
*/
|
||||||
*/
|
public function parameterFields()
|
||||||
public function title() {
|
{
|
||||||
return _t('PagesWithoutReviewScheduleReport.TITLE', 'Pages without a scheduled review.');
|
$params = new FieldList();
|
||||||
}
|
$params->push(new CheckboxField("ShowVirtualPages", "Show Virtual Pages"));
|
||||||
|
|
||||||
/**
|
return $params;
|
||||||
*
|
}
|
||||||
* @return \FieldList
|
|
||||||
*/
|
|
||||||
public function parameterFields() {
|
|
||||||
$params = new FieldList();
|
|
||||||
$params->push(new CheckboxField('ShowVirtualPages', 'Show Virtual Pages'));
|
|
||||||
return $params;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @return array
|
||||||
* @return array
|
*/
|
||||||
*/
|
public function columns()
|
||||||
public function columns() {
|
{
|
||||||
$linkBase = singleton('CMSPageEditController')->Link('show');
|
$linkBase = singleton("CMSPageEditController")->Link("show");
|
||||||
$linkPath = parse_url($linkBase, PHP_URL_PATH);
|
$linkPath = parse_url($linkBase, PHP_URL_PATH);
|
||||||
$linkQuery = parse_url($linkBase, PHP_URL_QUERY);
|
$linkQuery = parse_url($linkBase, PHP_URL_QUERY);
|
||||||
|
|
||||||
$fields = array(
|
$fields = array(
|
||||||
'Title' => array(
|
"Title" => array(
|
||||||
'title' => 'Page name',
|
"title" => "Page name",
|
||||||
'formatting' => sprintf('<a href=\"%s/$ID?%s\" title=\"Edit page\">$value</a>', $linkPath, $linkQuery)
|
"formatting" => "<a href='{$linkPath}/\$ID?{$linkQuery}' title='Edit page'>\$value</a>",
|
||||||
),
|
),
|
||||||
'NextReviewDate' => array(
|
"NextReviewDate" => array(
|
||||||
'title' => 'Review Date',
|
"title" => "Review Date",
|
||||||
'casting' => 'Date->Full'
|
"casting" => "Date->Full",
|
||||||
),
|
),
|
||||||
'OwnerNames' => array(
|
"OwnerNames" => array(
|
||||||
'title' => 'Owner'
|
"title" => "Owner",
|
||||||
),
|
),
|
||||||
'LastEditedByName' => 'Last edited by',
|
"LastEditedByName" => "Last edited by",
|
||||||
'AbsoluteLink' => array(
|
"AbsoluteLink" => array(
|
||||||
'title' => 'URL',
|
"title" => "URL",
|
||||||
'formatting' => function($value, $item) {
|
"formatting" => function ($value, $item) {
|
||||||
$liveLink = $item->AbsoluteLiveLink;
|
$liveLink = $item->AbsoluteLiveLink;
|
||||||
$stageLink = $item->AbsoluteLink();
|
$stageLink = $item->AbsoluteLink();
|
||||||
return sprintf('%s <a href="%s">%s</a>',
|
|
||||||
$stageLink,
|
|
||||||
$liveLink ? $liveLink : $stageLink . '?stage=Stage',
|
|
||||||
$liveLink ? '(live)' : '(draft)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
),
|
|
||||||
'ContentReviewType' => array(
|
|
||||||
'title' => 'Settings are',
|
|
||||||
'formatting' => function($value, $item) use($linkPath, $linkQuery) {
|
|
||||||
if($item->ContentReviewType == 'Inherit') {
|
|
||||||
$options = $item->getOptions();
|
|
||||||
if($options && $options instanceof SiteConfig) {
|
|
||||||
return 'Inherited from <a href="admin/settings">Settings</a>';
|
|
||||||
} elseif($options) {
|
|
||||||
return sprintf(
|
|
||||||
'Inherited from <a href="%s/%d?%s">%s</a>',
|
|
||||||
$linkPath,
|
|
||||||
$options->ID,
|
|
||||||
$linkQuery,
|
|
||||||
$options->Title
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return $fields;
|
return sprintf("%s <a href='%s'>%s</a>",
|
||||||
}
|
$stageLink,
|
||||||
|
$liveLink ? $liveLink : $stageLink . "?stage=Stage",
|
||||||
|
$liveLink ? "(live)" : "(draft)"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"ContentReviewType" => array(
|
||||||
|
"title" => "Settings are",
|
||||||
|
"formatting" => function ($value, $item) use ($linkPath, $linkQuery) {
|
||||||
|
if ($item->ContentReviewType == "Inherit") {
|
||||||
|
$options = $item->getOptions();
|
||||||
|
if ($options && $options instanceof SiteConfig) {
|
||||||
|
return "Inherited from <a href='admin/settings'>Settings</a>";
|
||||||
|
} elseif ($options) {
|
||||||
|
return sprintf(
|
||||||
|
"Inherited from <a href='%s/%d?%s'>%s</a>",
|
||||||
|
$linkPath,
|
||||||
|
$options->ID,
|
||||||
|
$linkQuery,
|
||||||
|
$options->Title
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
return $value;
|
||||||
*
|
},
|
||||||
* @param array $params
|
),
|
||||||
* @return SS_List
|
);
|
||||||
*/
|
|
||||||
public function sourceRecords($params = array()) {
|
|
||||||
Versioned::reading_stage('Stage');
|
|
||||||
$c = ContentReviewCompatability::start();
|
|
||||||
$records = SiteTree::get();
|
|
||||||
|
|
||||||
// If there's no review dates set, default to all pages due for review now
|
return $fields;
|
||||||
// $records = $records->where('"NextReviewDate" IS NULL OR "OwnerNames" IS NULL OR "OwnerNames" = \'\'');
|
}
|
||||||
|
|
||||||
// Show virtual pages?
|
/**
|
||||||
if(empty($params['ShowVirtualPages'])) {
|
* @param array $params
|
||||||
$virtualPageClasses = ClassInfo::subclassesFor('VirtualPage');
|
*
|
||||||
$records = $records->where(sprintf(
|
* @return SS_List
|
||||||
'"SiteTree"."ClassName" NOT IN (\'%s\')',
|
*/
|
||||||
implode("','", array_values($virtualPageClasses))
|
public function sourceRecords($params = array())
|
||||||
));
|
{
|
||||||
}
|
Versioned::reading_stage("Stage");
|
||||||
|
|
||||||
$records->sort('ParentID');
|
$records = SiteTree::get();
|
||||||
$records = $records->toArray();
|
$compatibility = ContentReviewCompatability::start();
|
||||||
|
|
||||||
// Trim out calculated values
|
// If there's no review dates set, default to all pages due for review now.
|
||||||
$list = new ArrayList();
|
|
||||||
foreach($records as $record) {
|
|
||||||
if(!$this->hasReviewSchedule($record)) {
|
|
||||||
$list->push($record);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentReviewCompatability::done($c);
|
// Show virtual pages?
|
||||||
return $list;
|
if (empty($params["ShowVirtualPages"])) {
|
||||||
}
|
$virtualPageClasses = ClassInfo::subclassesFor("VirtualPage");
|
||||||
|
$records = $records->where(sprintf(
|
||||||
|
"\"SiteTree\".\"ClassName\" NOT IN ('%s')",
|
||||||
|
implode("','", array_values($virtualPageClasses))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
$records->sort("ParentID");
|
||||||
*
|
$records = $records->toArray();
|
||||||
* @param DataObject $record
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
protected function hasReviewSchedule(DataObject $record) {
|
|
||||||
if(!$record->obj('NextReviewDate')->exists()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$options = $record->getOptions();
|
// Trim out calculated values
|
||||||
if($options->OwnerGroups()->count() == 0 && $options->OwnerUsers()->count() == 0) {
|
$list = new ArrayList();
|
||||||
return false;
|
foreach ($records as $record) {
|
||||||
}
|
if (!$this->hasReviewSchedule($record)) {
|
||||||
|
$list->push($record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
ContentReviewCompatability::done($compatibility);
|
||||||
}
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param DataObject $record
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function hasReviewSchedule(DataObject $record)
|
||||||
|
{
|
||||||
|
if (!$record->obj("NextReviewDate")->exists()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = $record->getOptions();
|
||||||
|
|
||||||
|
if ($options->OwnerGroups()->count() == 0 && $options->OwnerUsers()->count() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,92 +1,94 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Daily task to send emails to the owners of content items
|
* Daily task to send emails to the owners of content items when the review date rolls around.
|
||||||
* when the review date rolls around
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @todo create a page cache for the inherited so that we dont unneccesary need to look up parent pages
|
|
||||||
* @package contentreview
|
|
||||||
*/
|
*/
|
||||||
class ContentReviewEmails extends BuildTask {
|
class ContentReviewEmails extends BuildTask
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Holds a cached array for looking up members via their ID.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $member_cache = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds a cached array for looking up members via their ID
|
* @param SS_HTTPRequest $request
|
||||||
*
|
*/
|
||||||
* @var array
|
public function run($request)
|
||||||
*/
|
{
|
||||||
protected static $member_cache = array();
|
$compatibility = ContentReviewCompatability::start();
|
||||||
|
|
||||||
/**
|
$now = class_exists("SS_Datetime") ? SS_Datetime::now()->URLDate() : SSDatetime::now()->URLDate();
|
||||||
*
|
|
||||||
* @param SS_HTTPRequest $request
|
|
||||||
*/
|
|
||||||
public function run($request) {
|
|
||||||
$c = ContentReviewCompatability::start();
|
|
||||||
|
|
||||||
$now = class_exists('SS_Datetime') ? SS_Datetime::now()->URLDate() : SSDatetime::now()->URLDate();
|
// First grab all the pages with a custom setting
|
||||||
|
$pages = Page::get("Page")->where("\"SiteTree\".\"NextReviewDate\" <= '{$now}'");
|
||||||
|
|
||||||
// First grab all the pages with a custom setting
|
$overduePages = $this->getOverduePagesForOwners($pages);
|
||||||
$pages = Page::get('Page')->where('"SiteTree"."NextReviewDate" <= \''.$now.'\'');
|
|
||||||
|
|
||||||
$overduePages = $this->getOverduePagesForOwners($pages);
|
// Lets send one email to one owner with all the pages in there instead of no of pages
|
||||||
|
// of emails.
|
||||||
|
foreach ($overduePages as $memberID => $pages) {
|
||||||
|
$this->notifyOwner($memberID, $pages);
|
||||||
|
}
|
||||||
|
|
||||||
// Lets send one email to one owner with all the pages in there instead of no of pages of emails
|
ContentReviewCompatability::done($compatibility);
|
||||||
foreach($overduePages as $memberID => $pages) {
|
}
|
||||||
$this->notifyOwner($memberID, $pages);
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentReviewCompatability::done($c);
|
/**
|
||||||
}
|
* @param SS_list $pages
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getOverduePagesForOwners(SS_list $pages)
|
||||||
|
{
|
||||||
|
$overduePages = array();
|
||||||
|
|
||||||
/**
|
foreach ($pages as $page) {
|
||||||
*
|
if (!$page->canBeReviewedBy()) {
|
||||||
* @param SS_list $pages
|
continue;
|
||||||
* @param array &$pages
|
}
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getOverduePagesForOwners(SS_list $pages) {
|
|
||||||
$overduePages = array();
|
|
||||||
|
|
||||||
foreach($pages as $page) {
|
$option = $page->getOptions();
|
||||||
if(!$page->canBeReviewedBy()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$option = $page->getOptions();
|
|
||||||
foreach($option->ContentReviewOwners() as $owner) {
|
|
||||||
if(!isset(self::$member_cache[$owner->ID])) {
|
|
||||||
self::$member_cache[$owner->ID] = $owner;
|
|
||||||
}
|
|
||||||
if(!isset($overduePages[$owner->ID])) {
|
|
||||||
$overduePages[$owner->ID] = new ArrayList();
|
|
||||||
}
|
|
||||||
$overduePages[$owner->ID]->push($page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $overduePages;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
foreach ($option->ContentReviewOwners() as $owner) {
|
||||||
*
|
if (!isset(self::$member_cache[$owner->ID])) {
|
||||||
* @param int $owner
|
self::$member_cache[$owner->ID] = $owner;
|
||||||
* @param array $pages
|
}
|
||||||
*/
|
|
||||||
protected function notifyOwner($ownerID, SS_List $pages) {
|
|
||||||
$owner = self::$member_cache[$ownerID];
|
|
||||||
$sender = Security::findAnAdministrator();
|
|
||||||
$senderEmail = ($sender->Email) ? $sender->Email : Config::inst()->get('Email', 'admin_email');
|
|
||||||
|
|
||||||
$subject = _t('ContentReviewEmails.SUBJECT', 'Page(s) are due for content review');
|
if (!isset($overduePages[$owner->ID])) {
|
||||||
$email = new Email();
|
$overduePages[$owner->ID] = new ArrayList();
|
||||||
$email->setTo($owner->Email);
|
}
|
||||||
$email->setFrom($senderEmail);
|
|
||||||
$email->setTemplate('ContentReviewEmail');
|
$overduePages[$owner->ID]->push($page);
|
||||||
$email->setSubject($subject);
|
}
|
||||||
$email->populateTemplate(array(
|
}
|
||||||
"Recipient" => $owner,
|
|
||||||
"Sender" => $sender,
|
return $overduePages;
|
||||||
"Pages" => $pages
|
}
|
||||||
));
|
|
||||||
$email->send();
|
/**
|
||||||
}
|
* @param int $ownerID
|
||||||
|
* @param array|SS_List $pages
|
||||||
|
*/
|
||||||
|
protected function notifyOwner($ownerID, SS_List $pages)
|
||||||
|
{
|
||||||
|
$owner = self::$member_cache[$ownerID];
|
||||||
|
$sender = Security::findAnAdministrator();
|
||||||
|
$senderEmail = ($sender->Email) ? $sender->Email : Config::inst()->get("Email", "admin_email");
|
||||||
|
|
||||||
|
$subject = _t("ContentReviewEmails.SUBJECT", "Page(s) are due for content review");
|
||||||
|
$email = new Email();
|
||||||
|
$email->setTo($owner->Email);
|
||||||
|
$email->setFrom($senderEmail);
|
||||||
|
$email->setTemplate("ContentReviewEmail");
|
||||||
|
$email->setSubject($subject);
|
||||||
|
$email->populateTemplate(array(
|
||||||
|
"Recipient" => $owner,
|
||||||
|
"Sender" => $sender,
|
||||||
|
"Pages" => $pages,
|
||||||
|
));
|
||||||
|
|
||||||
|
$email->send();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,27 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* Task which migrates the ContentReview Module's SiteTree->OwnerID column to a new column name
|
|
||||||
*/
|
|
||||||
class ContentReviewOwnerMigrationTask extends BuildTask {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Task which migrates the ContentReview Module's SiteTree->OwnerID column to a new column name.
|
||||||
* @param SS_HTTPRequest $request
|
*/
|
||||||
*/
|
class ContentReviewOwnerMigrationTask extends BuildTask
|
||||||
public function run($request) {
|
{
|
||||||
$results = DB::query('SHOW columns from "SiteTree" WHERE "field" = \'OwnerID\'');
|
/**
|
||||||
if ($results->numRecords() == 0) {
|
* @param SS_HTTPRequest $request
|
||||||
echo "<h1>No need to run task. SiteTree->OwnerID doesn't exist</h1>";
|
*/
|
||||||
} else {
|
public function run($request)
|
||||||
DB::query('UPDATE "SiteTree" SET "ContentReviewOwnerID" = "OwnerID"');
|
{
|
||||||
DB::query('UPDATE "SiteTree_Live" SET "ContentReviewOwnerID" = "OwnerID"');
|
$results = DB::query("SHOW columns from \"SiteTree\" WHERE \"field\" = 'OwnerID'");
|
||||||
DB::query('UPDATE "SiteTree_versions" SET "ContentReviewOwnerID" = "OwnerID"');
|
|
||||||
DB::query('ALTER TABLE "SiteTree" DROP COLUMN "OwnerID"');
|
if ($results->numRecords() == 0) {
|
||||||
DB::query('ALTER TABLE "SiteTree_Live" DROP COLUMN "OwnerID"');
|
echo "<h1>No need to run task. SiteTree->OwnerID doesn't exist</h1>";
|
||||||
DB::query('ALTER TABLE "SiteTree_versions" DROP COLUMN "OwnerID"');
|
} else {
|
||||||
echo "<h1>Migrated 3 tables. Dropped obsolete OwnerID column</h1>";
|
DB::query("UPDATE \"SiteTree\" SET \"ContentReviewOwnerID\" = \"OwnerID\"");
|
||||||
}
|
DB::query("UPDATE \"SiteTree_Live\" SET \"ContentReviewOwnerID\" = \"OwnerID\"");
|
||||||
}
|
DB::query("UPDATE \"SiteTree_versions\" SET \"ContentReviewOwnerID\" = \"OwnerID\"");
|
||||||
|
DB::query("ALTER TABLE \"SiteTree\" DROP COLUMN \"OwnerID\"");
|
||||||
|
DB::query("ALTER TABLE \"SiteTree_Live\" DROP COLUMN \"OwnerID\"");
|
||||||
|
DB::query("ALTER TABLE \"SiteTree_versions\" DROP COLUMN \"OwnerID\"");
|
||||||
|
echo "<h1>Migrated 3 tables. Dropped obsolete OwnerID column</h1>";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,36 +1,42 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend this class when writing unit tests which are compatable with other modules. All
|
* Extend this class when writing unit tests which are compatible with other modules.
|
||||||
* compatability code goes here.
|
* All compatibility code goes here.
|
||||||
*/
|
*/
|
||||||
abstract class ContentReviewBaseTest extends FunctionalTest {
|
abstract class ContentReviewBaseTest extends FunctionalTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $translatableEnabledBefore;
|
||||||
|
|
||||||
protected $translatableEnabledBefore;
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
public function setUp(){
|
/*
|
||||||
parent::setUp();
|
* We set the locale for pages explicitly, because if we don't, then we get into a situation
|
||||||
/*
|
* where the page takes on the tester's (your) locale, and any calls to simulate subsequent requests
|
||||||
* We set the locale for pages explicitly, because if we don't, then we get into a situation
|
* (e.g. $this->post()) do not seem to get passed the tester's locale, but instead fallback to the default locale.
|
||||||
* where the page takes on the tester's (your) locale, and any calls to simulate subsequent requests
|
*
|
||||||
* (e.g. $this->post()) do not seem to get passed the tester's locale, but instead fallback to the default locale.
|
* So we set the pages locale to be the default locale, which will then match any subsequent requests.
|
||||||
*
|
*
|
||||||
* So we set the pages locale to be the default locale, which will then match any subsequent requests.
|
* If creating pages in your unit tests (rather than reading from the fixtures file), you must explicitly call
|
||||||
*
|
* self::compat() on the page, for the same reasons as above.
|
||||||
* If creating pages in your unit tests (rather than reading from the fixtures file), you must explicitly call
|
*/
|
||||||
* self::compat() on the page, for the same reasons as above.
|
if (class_exists("Translatable")) {
|
||||||
*/
|
$this->translatableEnabledBefore = SiteTree::has_extension("Translatable");
|
||||||
if(class_exists('Translatable')){
|
SiteTree::remove_extension("Translatable");
|
||||||
fwrite(STDOUT, 'TRANSLATABLE DISABLED FFS');
|
}
|
||||||
$this->translatableEnabledBefore = Translatable::is_enabled();
|
}
|
||||||
Translatable::disable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tearDown(){
|
|
||||||
if(class_exists('Translatable')){
|
|
||||||
if($this->translatableEnabledBefore) Translatable::enable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public function tearDown()
|
||||||
|
{
|
||||||
|
if (class_exists("Translatable")) {
|
||||||
|
if ($this->translatableEnabledBefore) {
|
||||||
|
SiteTree::add_extension("Translatable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,67 +1,101 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class ContentReviewCMSPageEditControllerTest extends ContentReviewBaseTest {
|
/**
|
||||||
|
* @mixin PHPUnit_Framework_TestCase
|
||||||
|
*/
|
||||||
|
class ContentReviewCMSPageEditControllerTest extends ContentReviewBaseTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $fixture_file = "contentreview/tests/ContentReviewTest.yml";
|
||||||
|
|
||||||
public static $fixture_file = 'contentreview/tests/ContentReviewTest.yml';
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $requiredExtensions = array(
|
||||||
|
"SiteTree" => array("SiteTreeContentReview"),
|
||||||
|
"Group" => array("ContentReviewOwner"),
|
||||||
|
"Member" => array("ContentReviewOwner"),
|
||||||
|
"CMSPageEditController" => array("ContentReviewCMSExtension"),
|
||||||
|
"SiteConfig" => array("ContentReviewDefaultSettings"),
|
||||||
|
);
|
||||||
|
|
||||||
protected $requiredExtensions = array(
|
public function testReviewedThrowsExceptionWithNoRecordID()
|
||||||
"SiteTree" => array("SiteTreeContentReview"),
|
{
|
||||||
"Group" => array("ContentReviewOwner"),
|
$this->setExpectedException("SS_HTTPResponse_Exception");
|
||||||
"Member" => array("ContentReviewOwner"),
|
|
||||||
"CMSPageEditController" => array("ContentReviewCMSExtension"),
|
|
||||||
"SiteConfig" => array("ContentReviewDefaultSettings"),
|
|
||||||
);
|
|
||||||
|
|
||||||
public function testReviewedThrowsExceptionWithNoRecordID() {
|
/** @var CMSPageEditController|ContentReviewCMSExtension $controller */
|
||||||
$this->setExpectedException('SS_HTTPResponse_Exception', 'No record ID', 404);
|
$controller = new CMSPageEditController();
|
||||||
$controller = new CMSPageEditController();
|
|
||||||
$dummyForm = new CMSForm($controller, 'EditForm', new FieldList(), new FieldList());
|
|
||||||
$controller->reviewed(array('ID'=>null, 'Message' => null), $dummyForm);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testReviewedThrowsExceptionWithWrongRecordID() {
|
$dummyForm = new CMSForm($controller, "EditForm", new FieldList(), new FieldList());
|
||||||
$this->setExpectedException('SS_HTTPResponse_Exception');
|
|
||||||
$controller = new CMSPageEditController();
|
|
||||||
$dummyForm = new CMSForm($controller, 'EditForm', new FieldList(), new FieldList());
|
|
||||||
$controller->reviewed(array('ID'=>'FAIL', 'Message' => null), $dummyForm);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testReviewedWithAuthor() {
|
$controller->reviewed(array(
|
||||||
$author = $this->objFromFixture('Member', 'author');
|
"ID" => null,
|
||||||
$this->loginAs($author);
|
"Message" => null,
|
||||||
$page = $this->objFromFixture('Page', 'home');
|
), $dummyForm);
|
||||||
|
}
|
||||||
|
|
||||||
$data = array(
|
public function testReviewedThrowsExceptionWithWrongRecordID()
|
||||||
'action_reviewed' => 1,
|
{
|
||||||
'ID' => $page->ID
|
$this->setExpectedException("SS_HTTPResponse_Exception");
|
||||||
);
|
|
||||||
|
|
||||||
$response = $this->post('admin/pages/edit/EditForm', $data);
|
/** @var CMSPageEditController|ContentReviewCMSExtension $controller */
|
||||||
$this->assertEquals('OK', $response->getStatusDescription());
|
$controller = new CMSPageEditController();
|
||||||
$this->assertEquals(200, $response->getStatusCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSaveReview() {
|
$dummyForm = new CMSForm($controller, "EditForm", new FieldList(), new FieldList());
|
||||||
$author = $this->objFromFixture('Member', 'author');
|
|
||||||
$this->loginAs($author);
|
|
||||||
$page = $this->objFromFixture('Page', 'home');
|
|
||||||
|
|
||||||
$data = array(
|
$controller->reviewed(array(
|
||||||
'action_save_review' => 1,
|
"ID" => "FAIL",
|
||||||
'ID' => $page->ID,
|
"Message" => null,
|
||||||
'ReviewNotes' => 'This is the best page ever'
|
), $dummyForm);
|
||||||
);
|
}
|
||||||
|
|
||||||
$response = $this->post('admin/pages/edit/EditForm', $data);
|
public function testReviewedWithAuthor()
|
||||||
|
{
|
||||||
|
/** @var Member $author */
|
||||||
|
$author = $this->objFromFixture("Member", "author");
|
||||||
|
|
||||||
$this->assertEquals('OK', $response->getStatusDescription());
|
$this->loginAs($author);
|
||||||
$this->assertEquals(200, $response->getStatusCode());
|
|
||||||
|
|
||||||
$this->assertEquals(1, $page->ReviewLogs()->count());
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
$reviewLog = $page->ReviewLogs()->first();
|
$page = $this->objFromFixture("Page", "home");
|
||||||
|
|
||||||
$this->assertEquals($data['ReviewNotes'], $reviewLog->Note);
|
$data = array(
|
||||||
}
|
"action_reviewed" => 1,
|
||||||
|
"ID" => $page->ID,
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = $this->post("admin/pages/edit/EditForm", $data);
|
||||||
|
|
||||||
|
$this->assertEquals("OK", $response->getStatusDescription());
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSaveReview()
|
||||||
|
{
|
||||||
|
/** @var Member $author */
|
||||||
|
$author = $this->objFromFixture("Member", "author");
|
||||||
|
|
||||||
|
$this->loginAs($author);
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "home");
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
"action_save_review" => 1,
|
||||||
|
"ID" => $page->ID,
|
||||||
|
"ReviewNotes" => "This is the best page ever",
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = $this->post("admin/pages/edit/EditForm", $data);
|
||||||
|
|
||||||
|
$this->assertEquals("OK", $response->getStatusDescription());
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
$this->assertEquals(1, $page->ReviewLogs()->count());
|
||||||
|
|
||||||
|
$reviewLog = $page->ReviewLogs()->first();
|
||||||
|
|
||||||
|
$this->assertEquals($data["ReviewNotes"], $reviewLog->Note);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,38 +1,47 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class ContentReviewNotificationTest extends SapphireTest {
|
/**
|
||||||
|
* @mixin PHPUnit_Framework_TestCase
|
||||||
|
*/
|
||||||
|
class ContentReviewNotificationTest extends SapphireTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $fixture_file = "contentreview/tests/ContentReviewTest.yml";
|
||||||
|
|
||||||
public static $fixture_file = 'contentreview/tests/ContentReviewTest.yml';
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $requiredExtensions = array(
|
||||||
|
"SiteTree" => array("SiteTreeContentReview"),
|
||||||
|
"Group" => array("ContentReviewOwner"),
|
||||||
|
"Member" => array("ContentReviewOwner"),
|
||||||
|
"CMSPageEditController" => array("ContentReviewCMSExtension"),
|
||||||
|
"SiteConfig" => array("ContentReviewDefaultSettings"),
|
||||||
|
);
|
||||||
|
|
||||||
protected $requiredExtensions = array(
|
public function testContentReviewEmails()
|
||||||
"SiteTree" => array("SiteTreeContentReview"),
|
{
|
||||||
"Group" => array("ContentReviewOwner"),
|
SS_Datetime::set_mock_now("2010-02-24 12:00:00");
|
||||||
"Member" => array("ContentReviewOwner"),
|
|
||||||
"CMSPageEditController" => array("ContentReviewCMSExtension"),
|
|
||||||
"SiteConfig" => array("ContentReviewDefaultSettings"),
|
|
||||||
);
|
|
||||||
|
|
||||||
public function testContentReviewEmails() {
|
/** @var Page|SiteTreeContentReview $childParentPage */
|
||||||
SS_Datetime::set_mock_now('2010-02-24 12:00:00');
|
$childParentPage = $this->objFromFixture("Page", "contact");
|
||||||
|
$childParentPage->NextReviewDate = "2010-02-23";
|
||||||
|
$childParentPage->write();
|
||||||
|
|
||||||
// This propagates the next review date to 'contact-child' page from the parent page
|
$task = new ContentReviewEmails();
|
||||||
$childParentPage = $this->objFromFixture('Page', 'contact');
|
$task->run(new SS_HTTPRequest("GET", "/dev/tasks/ContentReviewEmails"));
|
||||||
$childParentPage->NextReviewDate = '2010-02-23';
|
|
||||||
$childParentPage->write();
|
|
||||||
|
|
||||||
$task = new ContentReviewEmails();
|
$expectedSubject = _t("ContentReviewEmails.SUBJECT", "Page(s) are due for content review");
|
||||||
$task->run(new SS_HTTPRequest('GET', '/dev/tasks/ContentReviewEmails'));
|
$email = $this->findEmail("author@example.com", null, $expectedSubject);
|
||||||
|
|
||||||
$expectedSubject = _t('ContentReviewEmails.SUBJECT', 'Page(s) are due for content review');
|
$this->assertNotNull($email, "Email haven't been sent.");
|
||||||
$email = $this->findEmail('author@example.com', null, $expectedSubject);
|
$this->assertContains("There are 3 pages that are due for review today by you.", $email["htmlContent"]);
|
||||||
|
$this->assertContains("Staff", $email["htmlContent"]);
|
||||||
|
$this->assertContains("Contact Us", $email["htmlContent"]);
|
||||||
|
$this->assertContains("Contact Us Child", $email["htmlContent"]);
|
||||||
|
|
||||||
$this->assertNotNull($email, 'Email haven\'t been sent.');
|
SS_Datetime::clear_mock_now();
|
||||||
|
}
|
||||||
$this->assertContains('There are 3 pages that are due for review today by you.', $email['htmlContent']);
|
|
||||||
$this->assertContains('Staff', $email['htmlContent']);
|
|
||||||
$this->assertContains('Contact Us', $email['htmlContent']);
|
|
||||||
$this->assertContains('Contact Us Child', $email['htmlContent']);
|
|
||||||
|
|
||||||
SS_Datetime::clear_mock_now();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,67 +1,81 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class ContentReviewReportTest extends FunctionalTest {
|
class ContentReviewReportTest extends FunctionalTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $fixture_file = "contentreview/tests/ContentReviewTest.yml";
|
||||||
|
|
||||||
public static $fixture_file = 'contentreview/tests/ContentReviewTest.yml';
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $requiredExtensions = array(
|
||||||
|
"SiteTree" => array("SiteTreeContentReview"),
|
||||||
|
"Group" => array("ContentReviewOwner"),
|
||||||
|
"Member" => array("ContentReviewOwner"),
|
||||||
|
"CMSPageEditController" => array("ContentReviewCMSExtension"),
|
||||||
|
"SiteConfig" => array("ContentReviewDefaultSettings"),
|
||||||
|
);
|
||||||
|
|
||||||
protected $requiredExtensions = array(
|
public function testPagesDueForReviewReport()
|
||||||
"SiteTree" => array("SiteTreeContentReview"),
|
{
|
||||||
"Group" => array("ContentReviewOwner"),
|
/** @var Member $editor */
|
||||||
"Member" => array("ContentReviewOwner"),
|
$editor = $this->objFromFixture("Member", "editor");
|
||||||
"CMSPageEditController" => array("ContentReviewCMSExtension"),
|
|
||||||
"SiteConfig" => array("ContentReviewDefaultSettings"),
|
|
||||||
);
|
|
||||||
|
|
||||||
public function testPagesDueForReviewReport() {
|
$this->logInAs($editor);
|
||||||
$editor = $this->objFromFixture('Member', 'editor');
|
|
||||||
$this->logInAs($editor);
|
|
||||||
$report = new PagesDueForReviewReport();
|
|
||||||
|
|
||||||
$report->parameterFields();
|
$report = new PagesDueForReviewReport();
|
||||||
$report->columns();
|
|
||||||
$report->title();
|
|
||||||
|
|
||||||
$results = $report->sourceRecords(array(
|
$report->parameterFields();
|
||||||
'ReviewDateAfter' => '01/01/2010',
|
$report->columns();
|
||||||
'ReviewDateBefore' => '12/12/2010'
|
$report->title();
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertEquals(array(
|
$results = $report->sourceRecords(array(
|
||||||
'Contact Us',
|
"ReviewDateAfter" => "01/01/2010",
|
||||||
'Contact Us Child',
|
"ReviewDateBefore" => "12/12/2010",
|
||||||
'Staff',
|
));
|
||||||
'About Us',
|
|
||||||
'Home'
|
|
||||||
), $results->column('Title'));
|
|
||||||
|
|
||||||
SS_Datetime::set_mock_now('2010-02-13 00:00:00');
|
$this->assertEquals(array(
|
||||||
$results = $report->sourceRecords(array());
|
"Contact Us",
|
||||||
$this->assertEquals(array(
|
"Contact Us Child",
|
||||||
'About Us',
|
"Staff",
|
||||||
'Home'
|
"About Us",
|
||||||
), $results->column('Title'));
|
"Home",
|
||||||
|
), $results->column("Title"));
|
||||||
|
|
||||||
SS_Datetime::clear_mock_now();
|
SS_Datetime::set_mock_now("2010-02-13 00:00:00");
|
||||||
}
|
|
||||||
|
|
||||||
public function testPagesWithoutReviewScheduleReport() {
|
$results = $report->sourceRecords(array());
|
||||||
$editor = $this->objFromFixture('Member', 'editor');
|
|
||||||
$this->logInAs($editor);
|
|
||||||
$report = new PagesWithoutReviewScheduleReport();
|
|
||||||
|
|
||||||
$report->parameterFields();
|
$this->assertEquals(array(
|
||||||
$report->columns();
|
"About Us",
|
||||||
$report->title();
|
"Home",
|
||||||
|
), $results->column("Title"));
|
||||||
|
|
||||||
$results = $report->sourceRecords();
|
SS_Datetime::clear_mock_now();
|
||||||
|
}
|
||||||
|
|
||||||
$this->assertEquals(array(
|
public function testPagesWithoutReviewScheduleReport()
|
||||||
'Home',
|
{
|
||||||
'About Us',
|
/** @var Member $editor */
|
||||||
'Page without review date',
|
$editor = $this->objFromFixture("Member", "editor");
|
||||||
'Page owned by group',
|
|
||||||
), $results->column('Title'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
$this->logInAs($editor);
|
||||||
|
|
||||||
|
$report = new PagesWithoutReviewScheduleReport();
|
||||||
|
|
||||||
|
$report->parameterFields();
|
||||||
|
$report->columns();
|
||||||
|
$report->title();
|
||||||
|
|
||||||
|
$results = $report->sourceRecords();
|
||||||
|
|
||||||
|
$this->assertEquals(array(
|
||||||
|
"Home",
|
||||||
|
"About Us",
|
||||||
|
"Page without review date",
|
||||||
|
"Page owned by group",
|
||||||
|
), $results->column("Title"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,196 +1,294 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class tests that settings are inherited correctly based on the inherited, custom or disabled settings
|
* This class tests that settings are inherited correctly based on the inherited,
|
||||||
|
* custom or disabled settings.
|
||||||
|
*
|
||||||
|
* @mixin PHPUnit_Framework_TestCase
|
||||||
*/
|
*/
|
||||||
class ContentReviewSettingsTest extends SapphireTest {
|
class ContentReviewSettingsTest extends SapphireTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $fixture_file = "contentreview/tests/ContentReviewSettingsTest.yml";
|
||||||
|
|
||||||
public static $fixture_file = 'contentreview/tests/ContentReviewSettingsTest.yml';
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $requiredExtensions = array(
|
||||||
|
"SiteTree" => array("SiteTreeContentReview"),
|
||||||
|
"Group" => array("ContentReviewOwner"),
|
||||||
|
"Member" => array("ContentReviewOwner"),
|
||||||
|
"CMSPageEditController" => array("ContentReviewCMSExtension"),
|
||||||
|
"SiteConfig" => array("ContentReviewDefaultSettings"),
|
||||||
|
);
|
||||||
|
|
||||||
protected $requiredExtensions = array(
|
public function testAdvanceReviewDate10Days()
|
||||||
"SiteTree" => array("SiteTreeContentReview"),
|
{
|
||||||
"Group" => array("ContentReviewOwner"),
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
"Member" => array("ContentReviewOwner"),
|
$page = new Page();
|
||||||
"CMSPageEditController" => array("ContentReviewCMSExtension"),
|
|
||||||
"SiteConfig" => array("ContentReviewDefaultSettings"),
|
|
||||||
);
|
|
||||||
|
|
||||||
public function testAdvanceReviewDate10Days() {
|
$page->ContentReviewType = "Custom";
|
||||||
$page = new Page();
|
$page->ReviewPeriodDays = 10;
|
||||||
$page->ContentReviewType = 'Custom';
|
|
||||||
$page->ReviewPeriodDays = 10;
|
|
||||||
$this->assertTrue($page->advanceReviewDate());
|
|
||||||
$page->write();
|
|
||||||
$this->assertEquals(date('Y-m-d', strtotime('now + 10 days')), $page->NextReviewDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAdvanceReviewDateNull() {
|
$this->assertTrue($page->advanceReviewDate());
|
||||||
$page = new Page();
|
|
||||||
$page->ContentReviewType = 'Custom';
|
|
||||||
$page->ReviewPeriodDays = 0;
|
|
||||||
$this->assertFalse($page->advanceReviewDate());
|
|
||||||
$page->write();
|
|
||||||
$this->assertEquals(null, $page->NextReviewDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAdvanceReviewFromCustomSettings() {
|
$page->write();
|
||||||
$page = $this->objFromFixture('Page', 'custom');
|
|
||||||
$this->assertTrue($page->advanceReviewDate());
|
|
||||||
$page->write();
|
|
||||||
$this->assertEquals(date('Y-m-d', strtotime('now + '.$page->ReviewPeriodDays.' days')), $page->NextReviewDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAdvanceReviewFromInheritedSettings() {
|
$this->assertEquals(date("Y-m-d", strtotime("now + 10 days")), $page->NextReviewDate);
|
||||||
$page = $this->objFromFixture('Page', 'page-1-1');
|
}
|
||||||
$parentPage = $this->objFromFixture('Page', 'page-1');
|
|
||||||
$this->assertTrue($page->advanceReviewDate());
|
|
||||||
$page->write();
|
|
||||||
$this->assertEquals(date('Y-m-d', strtotime('now + '.$parentPage->ReviewPeriodDays.' days')), $page->NextReviewDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAdvanceReviewFromInheritedSiteConfigSettings() {
|
public function testAdvanceReviewDateNull()
|
||||||
$page = $this->objFromFixture('Page', 'inherit');
|
{
|
||||||
$siteConfig = $this->objFromFixture('SiteConfig', 'default');
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
$this->assertTrue($page->advanceReviewDate());
|
$page = new Page();
|
||||||
$page->write();
|
|
||||||
$this->assertEquals(date('Y-m-d', strtotime('now + '.$siteConfig->ReviewPeriodDays.' days')), $page->NextReviewDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetSettingsObjectFromCustom() {
|
$page->ContentReviewType = "Custom";
|
||||||
$page = $this->objFromFixture('Page', 'custom');
|
$page->ReviewPeriodDays = 0;
|
||||||
$this->assertEquals('Custom', $page->ContentReviewType);
|
|
||||||
$this->assertEquals($page, $page->getOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetSettingsObjectFromDisabled() {
|
$this->assertFalse($page->advanceReviewDate());
|
||||||
$page = $this->objFromFixture('Page', 'disabled');
|
|
||||||
$this->assertEquals('Disabled', $page->ContentReviewType);
|
|
||||||
$this->assertFalse($page->getOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetOptionObjectFromInheritedDisabled() {
|
$page->write();
|
||||||
$page = $this->objFromFixture('Page', 'page-2-1-1');
|
|
||||||
$this->assertEquals('Inherit', $page->ContentReviewType);
|
|
||||||
$this->assertFalse($page->getOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetOptionObjectFromDeeplyInheritedPage() {
|
$this->assertEquals(null, $page->NextReviewDate);
|
||||||
$page = $this->objFromFixture('Page', 'page-3-1-1-1');
|
}
|
||||||
$this->assertEquals('Inherit', $page->ContentReviewType);
|
|
||||||
$this->assertInstanceOf('SiteConfig', $page->getOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetSettingsObjectFromInheritPage() {
|
public function testAdvanceReviewFromCustomSettings()
|
||||||
$page = $this->objFromFixture('Page', 'page-1-1');
|
{
|
||||||
$parentPage = $this->objFromFixture('Page', 'page-1');
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
$this->assertEquals('Inherit', $page->ContentReviewType);
|
$page = $this->objFromFixture("Page", "custom");
|
||||||
$this->assertEquals(get_class($parentPage), get_class($page->getOptions()));
|
|
||||||
$this->assertEquals($parentPage->ID, $page->getOptions()->ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetSettingsObjectFromInheritedRootPage() {
|
$this->assertTrue($page->advanceReviewDate());
|
||||||
$page = $this->objFromFixture('Page', 'inherit');
|
|
||||||
$this->assertEquals('Inherit', $page->ContentReviewType);
|
|
||||||
$this->assertEquals($this->objFromFixture('SiteConfig', 'default'), $page->getOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetNextReviewDateFromCustomSettings() {
|
$page->write();
|
||||||
$page = $this->objFromFixture('Page', 'custom');
|
|
||||||
$date = $page->getReviewDate();
|
|
||||||
$this->assertEquals('2010-02-01', $date->format('Y-m-d'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetNextReviewDateFromSiteConfigInheritedSetting() {
|
$this->assertEquals(date("Y-m-d", strtotime("now + " . $page->ReviewPeriodDays . " days")), $page->NextReviewDate);
|
||||||
$page = $this->objFromFixture('Page', 'inherit');
|
}
|
||||||
$nextReviewDate = $page->getReviewDate();
|
|
||||||
|
|
||||||
$this->assertInstanceOf('Date', $nextReviewDate);
|
public function testAdvanceReviewFromInheritedSettings()
|
||||||
$expected = $this->addDaysToDate(SS_Datetime::now(), $this->objFromFixture('SiteConfig', 'default')->ReviewPeriodDays);
|
{
|
||||||
$this->assertEquals($expected , $nextReviewDate->format('Y-m-d'));
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
}
|
$page = $this->objFromFixture("Page", "page-1-1");
|
||||||
|
|
||||||
public function testGetNextReviewDateFromPageInheritedSetting() {
|
/** @var Page|SiteTreeContentReview $parentPage */
|
||||||
$page = $this->objFromFixture('Page', 'page-1-1');
|
$parentPage = $this->objFromFixture("Page", "page-1");
|
||||||
$nextReviewDate = $page->getReviewDate();
|
|
||||||
|
|
||||||
$this->assertInstanceOf('Date', $nextReviewDate);
|
$this->assertTrue($page->advanceReviewDate());
|
||||||
// It should be the same as the parents reviewdate
|
|
||||||
$expected = $this->objFromFixture('Page', 'page-1')->NextReviewDate;
|
|
||||||
$this->assertEquals($expected, $nextReviewDate->format('Y-m-d'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testUpdateNextReviewDateFromCustomToDisabled() {
|
$page->write();
|
||||||
$page = $this->objFromFixture('Page', 'custom');
|
|
||||||
// before write()
|
|
||||||
$this->assertEquals('2010-02-01', $page->NextReviewDate);
|
|
||||||
|
|
||||||
// Change and write
|
$this->assertEquals(date("Y-m-d", strtotime("now + " . $parentPage->ReviewPeriodDays . " days")), $page->NextReviewDate);
|
||||||
$page->ContentReviewType = 'Disabled';
|
}
|
||||||
$page->write();
|
|
||||||
|
|
||||||
// clear cache
|
public function testAdvanceReviewFromInheritedSiteConfigSettings()
|
||||||
DataObject::flush_and_destroy_cache();
|
{
|
||||||
unset($page);
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "inherit");
|
||||||
|
|
||||||
// After write()
|
/** @var SiteConfig|ContentReviewDefaultSettings $siteConfig */
|
||||||
$page = $this->objFromFixture('Page', 'custom');
|
$siteConfig = $this->objFromFixture("SiteConfig", "default");
|
||||||
$this->assertNull($page->NextReviewDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testUpdateNextReviewDateFromDisabledToCustom() {
|
$this->assertTrue($page->advanceReviewDate());
|
||||||
$page = $this->objFromFixture('Page', 'disabled');
|
|
||||||
// before
|
|
||||||
$this->assertNull($page->NextReviewDate);
|
|
||||||
|
|
||||||
// Change and write
|
$page->write();
|
||||||
$page->ContentReviewType = 'Custom';
|
|
||||||
$page->ReviewPeriodDays = '7';
|
|
||||||
$page->write();
|
|
||||||
// clear cache
|
|
||||||
DataObject::flush_and_destroy_cache();
|
|
||||||
unset($page);
|
|
||||||
|
|
||||||
// After write()
|
$this->assertEquals(date("Y-m-d", strtotime("now + " . $siteConfig->ReviewPeriodDays . " days")), $page->NextReviewDate);
|
||||||
$page = $this->objFromFixture('Page', 'disabled');
|
}
|
||||||
$expected = date('Y-m-d', strtotime('+ '.$page->ReviewPeriodDays.' days'));
|
|
||||||
$this->assertEquals($expected, $page->NextReviewDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testParentChangedOptionsAndChildShouldToo() {
|
public function testGetSettingsObjectFromCustom()
|
||||||
$parentPage = $this->objFromFixture('Page', 'page-1');
|
{
|
||||||
$childPage = $this->objFromFixture('Page', 'page-1-1');
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "custom");
|
||||||
|
|
||||||
// BEFORE: parent page have a period of five days, so childPage should have a
|
$this->assertEquals("Custom", $page->ContentReviewType);
|
||||||
// review date LastEdited + 5 days
|
$this->assertEquals($page, $page->getOptions());
|
||||||
$expected = $this->addDaysToDate($childPage->obj('LastEdited'), $parentPage->ReviewPeriodDays);
|
}
|
||||||
$this->assertEquals($parentPage->NextReviewDate, $childPage->NextReviewDate);
|
|
||||||
|
|
||||||
$oldChildDate = $childPage->NextReviewDate;
|
public function testGetSettingsObjectFromDisabled()
|
||||||
// But if we change the parent page ReviewPeriodDays to 10, the childs should
|
{
|
||||||
// change as well
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
$parentPage->ReviewPeriodDays = 10;
|
$page = $this->objFromFixture("Page", "disabled");
|
||||||
$parentPage->write();
|
|
||||||
|
|
||||||
// Flush all the caches!
|
$this->assertEquals("Disabled", $page->ContentReviewType);
|
||||||
DataObject::flush_and_destroy_cache();
|
$this->assertFalse($page->getOptions());
|
||||||
|
}
|
||||||
|
|
||||||
$parentPage = $this->objFromFixture('Page', 'page-1');
|
public function testGetOptionObjectFromInheritedDisabled()
|
||||||
$childPage = $this->objFromFixture('Page', 'page-1-1');
|
{
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "page-2-1-1");
|
||||||
|
|
||||||
// AFTER: parent page have a period of 10 days, so childPage should have a
|
$this->assertEquals("Inherit", $page->ContentReviewType);
|
||||||
// review date now + 10 days
|
$this->assertFalse($page->getOptions());
|
||||||
$this->assertNotEquals($oldChildDate, $childPage->NextReviewDate);
|
}
|
||||||
$this->assertEquals($this->addDaysToDate(date('Y-m-d'), 10), $childPage->NextReviewDate);
|
|
||||||
$this->assertEquals($parentPage->NextReviewDate, $childPage->NextReviewDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper method for this test class
|
public function testGetOptionObjectFromDeeplyInheritedPage()
|
||||||
private function addDaysToDate($date, $days, $format='Y-m-d') {
|
{
|
||||||
if(is_object($date)) {
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
$sec = strtotime('+ '. $days .' days', $date->format('U'));
|
$page = $this->objFromFixture("Page", "page-3-1-1-1");
|
||||||
} else {
|
|
||||||
$sec = strtotime('+ '. $days .' days', strtotime($date));
|
$this->assertEquals("Inherit", $page->ContentReviewType);
|
||||||
}
|
$this->assertInstanceOf("SiteConfig", $page->getOptions());
|
||||||
return date($format, $sec);
|
}
|
||||||
}
|
|
||||||
|
public function testGetSettingsObjectFromInheritPage()
|
||||||
|
{
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "page-1-1");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $parentPage */
|
||||||
|
$parentPage = $this->objFromFixture("Page", "page-1");
|
||||||
|
|
||||||
|
$this->assertEquals("Inherit", $page->ContentReviewType);
|
||||||
|
$this->assertEquals(get_class($parentPage), get_class($page->getOptions()));
|
||||||
|
$this->assertEquals($parentPage->ID, $page->getOptions()->ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetSettingsObjectFromInheritedRootPage()
|
||||||
|
{
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "inherit");
|
||||||
|
|
||||||
|
$this->assertEquals("Inherit", $page->ContentReviewType);
|
||||||
|
$this->assertEquals($this->objFromFixture("SiteConfig", "default"), $page->getOptions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetNextReviewDateFromCustomSettings()
|
||||||
|
{
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture('Page', 'custom');
|
||||||
|
|
||||||
|
$date = $page->getReviewDate();
|
||||||
|
|
||||||
|
$this->assertEquals('2010-02-01', $date->format('Y-m-d'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetNextReviewDateFromSiteConfigInheritedSetting()
|
||||||
|
{
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "inherit");
|
||||||
|
|
||||||
|
$nextReviewDate = $page->getReviewDate();
|
||||||
|
|
||||||
|
$this->assertInstanceOf("Date", $nextReviewDate);
|
||||||
|
|
||||||
|
/** @var SiteConfig|ContentReviewDefaultSettings $siteConfig */
|
||||||
|
$siteConfig = $this->objFromFixture("SiteConfig", "default");
|
||||||
|
|
||||||
|
$expected = $this->addDaysToDate(SS_Datetime::now(), $siteConfig->ReviewPeriodDays);
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $nextReviewDate->format("Y-m-d"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetNextReviewDateFromPageInheritedSetting()
|
||||||
|
{
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "page-1-1");
|
||||||
|
|
||||||
|
$nextReviewDate = $page->getReviewDate();
|
||||||
|
|
||||||
|
$this->assertInstanceOf("Date", $nextReviewDate);
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $nextPage */
|
||||||
|
$nextPage = $this->objFromFixture("Page", "page-1");
|
||||||
|
|
||||||
|
$expected = $nextPage->NextReviewDate;
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $nextReviewDate->format("Y-m-d"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUpdateNextReviewDateFromCustomToDisabled()
|
||||||
|
{
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "custom");
|
||||||
|
|
||||||
|
// before write()
|
||||||
|
$this->assertEquals("2010-02-01", $page->NextReviewDate);
|
||||||
|
|
||||||
|
$page->ContentReviewType = "Disabled";
|
||||||
|
$page->write();
|
||||||
|
|
||||||
|
DataObject::flush_and_destroy_cache();
|
||||||
|
unset($page);
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "custom");
|
||||||
|
|
||||||
|
$this->assertNull($page->NextReviewDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUpdateNextReviewDateFromDisabledToCustom()
|
||||||
|
{
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "disabled");
|
||||||
|
|
||||||
|
$this->assertNull($page->NextReviewDate);
|
||||||
|
|
||||||
|
$page->ContentReviewType = "Custom";
|
||||||
|
$page->ReviewPeriodDays = "7";
|
||||||
|
$page->write();
|
||||||
|
|
||||||
|
DataObject::flush_and_destroy_cache();
|
||||||
|
unset($page);
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "disabled");
|
||||||
|
|
||||||
|
$expected = date("Y-m-d", strtotime("+ " . $page->ReviewPeriodDays . " days"));
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $page->NextReviewDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testParentChangedOptionsAndChildShouldToo()
|
||||||
|
{
|
||||||
|
/** @var Page|SiteTreeContentReview $parentPage */
|
||||||
|
$parentPage = $this->objFromFixture("Page", "page-1");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $childPage */
|
||||||
|
$childPage = $this->objFromFixture("Page", "page-1-1");
|
||||||
|
|
||||||
|
// BEFORE: parent page have a period of five days, so childPage should have a
|
||||||
|
// review date LastEdited + 5 days
|
||||||
|
$this->assertEquals($parentPage->NextReviewDate, $childPage->NextReviewDate);
|
||||||
|
|
||||||
|
$oldChildDate = $childPage->NextReviewDate;
|
||||||
|
// But if we change the parent page ReviewPeriodDays to 10, the childs should
|
||||||
|
// change as well
|
||||||
|
$parentPage->ReviewPeriodDays = 10;
|
||||||
|
$parentPage->write();
|
||||||
|
|
||||||
|
// Flush all the caches!
|
||||||
|
DataObject::flush_and_destroy_cache();
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$parentPage = $this->objFromFixture("Page", "page-1");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$childPage = $this->objFromFixture("Page", "page-1-1");
|
||||||
|
|
||||||
|
// AFTER: parent page have a period of 10 days, so childPage should have
|
||||||
|
// a review date now + 10 days.
|
||||||
|
$this->assertNotEquals($oldChildDate, $childPage->NextReviewDate);
|
||||||
|
$this->assertEquals($this->addDaysToDate(date("Y-m-d"), 10), $childPage->NextReviewDate);
|
||||||
|
$this->assertEquals($parentPage->NextReviewDate, $childPage->NextReviewDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|SS_DateTime|DateTime $date
|
||||||
|
* @param int $days
|
||||||
|
* @param string $format
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
private function addDaysToDate($date, $days, $format = "Y-m-d")
|
||||||
|
{
|
||||||
|
if (is_object($date)) {
|
||||||
|
$sec = strtotime("+ " . $days . " days", $date->format("U"));
|
||||||
|
} else {
|
||||||
|
$sec = strtotime("+ " . $days . " days", strtotime($date));
|
||||||
|
}
|
||||||
|
|
||||||
|
return date($format, $sec);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,177 +1,284 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class SiteTreeContentReviewTest extends ContentReviewBaseTest {
|
/**
|
||||||
|
* @mixin PHPUnit_Framework_TestCase
|
||||||
|
*/
|
||||||
|
class SiteTreeContentReviewTest extends ContentReviewBaseTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $fixture_file = "contentreview/tests/ContentReviewTest.yml";
|
||||||
|
|
||||||
public static $fixture_file = 'contentreview/tests/ContentReviewTest.yml';
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $requiredExtensions = array(
|
||||||
|
"SiteTree" => array("SiteTreeContentReview"),
|
||||||
|
"Group" => array("ContentReviewOwner"),
|
||||||
|
"Member" => array("ContentReviewOwner"),
|
||||||
|
"CMSPageEditController" => array("ContentReviewCMSExtension"),
|
||||||
|
"SiteConfig" => array("ContentReviewDefaultSettings"),
|
||||||
|
);
|
||||||
|
|
||||||
protected $requiredExtensions = array(
|
public function testOwnerNames()
|
||||||
"SiteTree" => array("SiteTreeContentReview"),
|
{
|
||||||
"Group" => array("ContentReviewOwner"),
|
/** @var Member $editor */
|
||||||
"Member" => array("ContentReviewOwner"),
|
$editor = $this->objFromFixture("Member", "editor");
|
||||||
"CMSPageEditController" => array("ContentReviewCMSExtension"),
|
|
||||||
"SiteConfig" => array("ContentReviewDefaultSettings"),
|
|
||||||
);
|
|
||||||
|
|
||||||
public function testOwnerNames() {
|
$this->logInAs($editor);
|
||||||
$editor = $this->objFromFixture('Member', 'editor');
|
|
||||||
$this->logInAs($editor);
|
|
||||||
|
|
||||||
$page = new Page();
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
$page->ReviewPeriodDays = 10;
|
$page = new Page();
|
||||||
$page->ContentReviewType ='Custom';
|
$page->ReviewPeriodDays = 10;
|
||||||
$page->ContentReviewUsers()->push($editor);
|
$page->ContentReviewType = "Custom";
|
||||||
$page->write();
|
|
||||||
|
|
||||||
$this->assertTrue($page->canPublish());
|
$page->ContentReviewUsers()->push($editor);
|
||||||
$this->assertTrue($page->doPublish());
|
$page->write();
|
||||||
$this->assertEquals($page->OwnerNames, "Test Editor", 'Test Editor should be the owner');
|
|
||||||
|
|
||||||
$page = $this->objFromFixture('Page', 'about');
|
$this->assertTrue($page->canPublish());
|
||||||
$page->OwnerUsers()->removeAll();
|
$this->assertTrue($page->doPublish());
|
||||||
$page->write();
|
$this->assertEquals($page->OwnerNames, "Test Editor", "Test Editor should be the owner");
|
||||||
|
|
||||||
$this->assertTrue($page->canPublish());
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
$this->assertTrue($page->doPublish());
|
$page = $this->objFromFixture("Page", "about");
|
||||||
$this->assertEquals('', $page->OwnerNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testPermissionsExists() {
|
$page->OwnerUsers()->removeAll();
|
||||||
$perms = singleton('SiteTreeContentReview')->providePermissions();
|
$page->write();
|
||||||
$this->assertTrue(isset($perms['EDIT_CONTENT_REVIEW_FIELDS']));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testUserWithPermissionCanEdit() {
|
$this->assertTrue($page->canPublish());
|
||||||
$editor = $this->objFromFixture('Member', 'editor');
|
$this->assertTrue($page->doPublish());
|
||||||
$this->logInAs($editor);
|
$this->assertEquals("", $page->OwnerNames);
|
||||||
$page = new Page();
|
}
|
||||||
$fields = $page->getSettingsFields();
|
|
||||||
$this->assertNotNull($fields->dataFieldByName('NextReviewDate'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testUserWithoutPermissionCannotEdit() {
|
public function testPermissionsExists()
|
||||||
$author = $this->objFromFixture('Member', 'author');
|
{
|
||||||
$this->logInAs($author);
|
$perms = singleton("SiteTreeContentReview")->providePermissions();
|
||||||
$page = new Page();
|
|
||||||
$fields = $page->getSettingsFields();
|
|
||||||
$this->assertNull($fields->dataFieldByName('NextReviewDate'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAutomaticallyToNotSetReviewDate() {
|
$this->assertTrue(isset($perms["EDIT_CONTENT_REVIEW_FIELDS"]));
|
||||||
$editor = $this->objFromFixture('Member', 'editor');
|
}
|
||||||
$this->logInAs($editor);
|
|
||||||
|
|
||||||
$page = new Page();
|
public function testUserWithPermissionCanEdit()
|
||||||
$page->ReviewPeriodDays = 10;
|
{
|
||||||
$page->write();
|
/** @var Member $editor */
|
||||||
$this->assertTrue($page->doPublish());
|
$editor = $this->objFromFixture("Member", "editor");
|
||||||
$this->assertEquals(null, $page->NextReviewDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAddReviewNote() {
|
$this->logInAs($editor);
|
||||||
$author = $this->objFromFixture('Member', 'author');
|
|
||||||
$page = $this->objFromFixture('Page', 'home');
|
|
||||||
$page->addReviewNote($author, 'This is a message');
|
|
||||||
|
|
||||||
// Get the page again to make sure it's not only cached in memory
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
$homepage = $this->objFromFixture('Page', 'home');
|
$page = new Page();
|
||||||
$this->assertEquals(1, $homepage->ReviewLogs()->count());
|
|
||||||
$this->assertEquals('This is a message', $homepage->ReviewLogs()->first()->Note);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetContentReviewOwners() {
|
$fields = $page->getSettingsFields();
|
||||||
$page = $this->objFromFixture('Page', 'group-owned');
|
|
||||||
$owners = $page->ContentReviewOwners();
|
|
||||||
$this->assertEquals(1, $owners->count());
|
|
||||||
$this->assertEquals('author@example.com', $owners->first()->Email);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanNotBeReviewBecauseNoReviewDate() {
|
$this->assertNotNull($fields->dataFieldByName("NextReviewDate"));
|
||||||
SS_Datetime::set_mock_now('2010-01-01 12:00:00');
|
}
|
||||||
$author = $this->objFromFixture('Member', 'author');
|
|
||||||
$page = $this->objFromFixture('Page', 'no-review');
|
|
||||||
// page 'no-review' is owned by author, but there is no review date
|
|
||||||
$this->assertFalse($page->canBeReviewedBy($author));
|
|
||||||
SS_Datetime::clear_mock_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanNotBeReviewedBecauseInFuture() {
|
public function testUserWithoutPermissionCannotEdit()
|
||||||
SS_Datetime::set_mock_now('2010-01-01 12:00:00');
|
{
|
||||||
$author = $this->objFromFixture('Member', 'author');
|
/** @var Member $author */
|
||||||
$page = $this->objFromFixture('Page', 'staff');
|
$author = $this->objFromFixture("Member", "author");
|
||||||
// page 'staff' is owned by author, but the review date is in the future
|
|
||||||
$this->assertFalse($page->canBeReviewedBy($author));
|
|
||||||
SS_Datetime::clear_mock_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanNotBeReviewedByUser() {
|
$this->logInAs($author);
|
||||||
SS_Datetime::set_mock_now('2010-03-01 12:00:00');
|
|
||||||
$author = $this->objFromFixture('Member', 'author');
|
|
||||||
$page = $this->objFromFixture('Page', 'home');
|
|
||||||
// page 'home' doesnt have any owners
|
|
||||||
$this->assertFalse($page->canBeReviewedBy($author));
|
|
||||||
SS_Datetime::clear_mock_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanBeReviewedByUser() {
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
SS_Datetime::set_mock_now('2010-03-01 12:00:00');
|
$page = new Page();
|
||||||
$author = $this->objFromFixture('Member', 'author');
|
|
||||||
$page = $this->objFromFixture('Page', 'staff');
|
|
||||||
// page 'staff' is owned by author
|
|
||||||
$this->assertTrue($page->canBeReviewedBy($author));
|
|
||||||
SS_Datetime::clear_mock_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanNotBeReviewedByGroup() {
|
$fields = $page->getSettingsFields();
|
||||||
SS_Datetime::set_mock_now('2010-03-01 12:00:00');
|
|
||||||
$author = $this->objFromFixture('Member', 'editor');
|
|
||||||
$page = $this->objFromFixture('Page', 'contact');
|
|
||||||
// page 'contact' is owned by the authorgroup
|
|
||||||
$this->assertFalse($page->canBeReviewedBy($author));
|
|
||||||
SS_Datetime::clear_mock_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanBeReviewedByGroup() {
|
$this->assertNull($fields->dataFieldByName("NextReviewDate"));
|
||||||
SS_Datetime::set_mock_now('2010-03-01 12:00:00');
|
}
|
||||||
$author = $this->objFromFixture('Member', 'author');
|
|
||||||
$page = $this->objFromFixture('Page', 'contact');
|
|
||||||
// page 'contact' is owned by the authorgroup
|
|
||||||
$this->assertTrue($page->canBeReviewedBy($author));
|
|
||||||
SS_Datetime::clear_mock_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanBeReviewedFromInheritedSetting() {
|
public function testAutomaticallyToNotSetReviewDate()
|
||||||
SS_Datetime::set_mock_now('2013-03-01 12:00:00');
|
{
|
||||||
$author = $this->objFromFixture('Member', 'author');
|
/** @var Member $editor */
|
||||||
$parentPage = $this->objFromFixture('Page', 'contact');
|
$editor = $this->objFromFixture("Member", "editor");
|
||||||
// This saves the parentPages.NextReview date to the child page
|
|
||||||
$parentPage->NextReviewDate = '2013-01-01';
|
|
||||||
$parentPage->write();
|
|
||||||
|
|
||||||
$page = $this->objFromFixture('Page', 'contact-child');
|
$this->logInAs($editor);
|
||||||
$this->assertTrue($page->canBeReviewedBy($author));
|
|
||||||
SS_Datetime::clear_mock_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testReviewActionVisibleForAuthor() {
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
SS_Datetime::set_mock_now('2020-03-01 12:00:00');
|
$page = new Page();
|
||||||
$page = $this->objFromFixture('Page', 'contact');
|
|
||||||
$author = $this->objFromFixture('Member', 'author');
|
|
||||||
$this->logInAs($author);
|
|
||||||
|
|
||||||
$fields = $page->getCMSActions();
|
$page->ReviewPeriodDays = 10;
|
||||||
$this->assertNotNull($fields->fieldByName('action_reviewed'));
|
$page->write();
|
||||||
SS_Datetime::clear_mock_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testReviewActionNotVisibleForEditor() {
|
$this->assertTrue($page->doPublish());
|
||||||
SS_Datetime::set_mock_now('2020-03-01 12:00:00');
|
$this->assertEquals(null, $page->NextReviewDate);
|
||||||
$page = $this->objFromFixture('Page', 'contact');
|
}
|
||||||
$author = $this->objFromFixture('Member', 'editor');
|
|
||||||
$this->logInAs($author);
|
|
||||||
|
|
||||||
$fields = $page->getCMSActions();
|
public function testAddReviewNote()
|
||||||
$this->assertNull($fields->fieldByName('action_reviewed'));
|
{
|
||||||
SS_Datetime::clear_mock_now();
|
/** @var Member $author */
|
||||||
}
|
$author = $this->objFromFixture("Member", "author");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "home");
|
||||||
|
|
||||||
|
$page->addReviewNote($author, "This is a message");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$homepage = $this->objFromFixture("Page", "home");
|
||||||
|
|
||||||
|
$this->assertEquals(1, $homepage->ReviewLogs()->count());
|
||||||
|
$this->assertEquals("This is a message", $homepage->ReviewLogs()->first()->Note);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetContentReviewOwners()
|
||||||
|
{
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "group-owned");
|
||||||
|
|
||||||
|
$owners = $page->ContentReviewOwners();
|
||||||
|
|
||||||
|
$this->assertEquals(1, $owners->count());
|
||||||
|
$this->assertEquals("author@example.com", $owners->first()->Email);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanNotBeReviewBecauseNoReviewDate()
|
||||||
|
{
|
||||||
|
SS_Datetime::set_mock_now("2010-01-01 12:00:00");
|
||||||
|
|
||||||
|
/** @var Member $author */
|
||||||
|
$author = $this->objFromFixture("Member", "author");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "no-review");
|
||||||
|
|
||||||
|
$this->assertFalse($page->canBeReviewedBy($author));
|
||||||
|
|
||||||
|
SS_Datetime::clear_mock_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanNotBeReviewedBecauseInFuture()
|
||||||
|
{
|
||||||
|
SS_Datetime::set_mock_now("2010-01-01 12:00:00");
|
||||||
|
|
||||||
|
/** @var Member $author */
|
||||||
|
$author = $this->objFromFixture("Member", "author");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "staff");
|
||||||
|
|
||||||
|
$this->assertFalse($page->canBeReviewedBy($author));
|
||||||
|
|
||||||
|
SS_Datetime::clear_mock_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanNotBeReviewedByUser()
|
||||||
|
{
|
||||||
|
SS_Datetime::set_mock_now("2010-03-01 12:00:00");
|
||||||
|
|
||||||
|
/** @var Member $author */
|
||||||
|
$author = $this->objFromFixture("Member", "author");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "home");
|
||||||
|
|
||||||
|
$this->assertFalse($page->canBeReviewedBy($author));
|
||||||
|
|
||||||
|
SS_Datetime::clear_mock_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanBeReviewedByUser()
|
||||||
|
{
|
||||||
|
SS_Datetime::set_mock_now("2010-03-01 12:00:00");
|
||||||
|
|
||||||
|
/** @var Member $author */
|
||||||
|
$author = $this->objFromFixture("Member", "author");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "staff");
|
||||||
|
|
||||||
|
$this->assertTrue($page->canBeReviewedBy($author));
|
||||||
|
|
||||||
|
SS_Datetime::clear_mock_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanNotBeReviewedByGroup()
|
||||||
|
{
|
||||||
|
SS_Datetime::set_mock_now("2010-03-01 12:00:00");
|
||||||
|
|
||||||
|
/** @var Member $author */
|
||||||
|
$author = $this->objFromFixture("Member", "editor");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "contact");
|
||||||
|
|
||||||
|
$this->assertFalse($page->canBeReviewedBy($author));
|
||||||
|
|
||||||
|
SS_Datetime::clear_mock_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanBeReviewedByGroup()
|
||||||
|
{
|
||||||
|
SS_Datetime::set_mock_now("2010-03-01 12:00:00");
|
||||||
|
|
||||||
|
/** @var Member $author */
|
||||||
|
$author = $this->objFromFixture("Member", "author");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "contact");
|
||||||
|
|
||||||
|
$this->assertTrue($page->canBeReviewedBy($author));
|
||||||
|
|
||||||
|
SS_Datetime::clear_mock_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanBeReviewedFromInheritedSetting()
|
||||||
|
{
|
||||||
|
SS_Datetime::set_mock_now("2013-03-01 12:00:00");
|
||||||
|
|
||||||
|
/** @var Member $author */
|
||||||
|
$author = $this->objFromFixture("Member", "author");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $parentPage */
|
||||||
|
$parentPage = $this->objFromFixture("Page", "contact");
|
||||||
|
|
||||||
|
$parentPage->NextReviewDate = "2013-01-01";
|
||||||
|
$parentPage->write();
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "contact-child");
|
||||||
|
|
||||||
|
$this->assertTrue($page->canBeReviewedBy($author));
|
||||||
|
|
||||||
|
SS_Datetime::clear_mock_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testReviewActionVisibleForAuthor()
|
||||||
|
{
|
||||||
|
SS_Datetime::set_mock_now("2020-03-01 12:00:00");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "contact");
|
||||||
|
|
||||||
|
/** @var Member $author */
|
||||||
|
$author = $this->objFromFixture("Member", "author");
|
||||||
|
|
||||||
|
$this->logInAs($author);
|
||||||
|
|
||||||
|
$fields = $page->getCMSActions();
|
||||||
|
|
||||||
|
$this->assertNotNull($fields->fieldByName("action_reviewed"));
|
||||||
|
|
||||||
|
SS_Datetime::clear_mock_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testReviewActionNotVisibleForEditor()
|
||||||
|
{
|
||||||
|
SS_Datetime::set_mock_now("2020-03-01 12:00:00");
|
||||||
|
|
||||||
|
/** @var Page|SiteTreeContentReview $page */
|
||||||
|
$page = $this->objFromFixture("Page", "contact");
|
||||||
|
|
||||||
|
/** @var Member $author */
|
||||||
|
$author = $this->objFromFixture("Member", "editor");
|
||||||
|
|
||||||
|
$this->logInAs($author);
|
||||||
|
|
||||||
|
$fields = $page->getCMSActions();
|
||||||
|
|
||||||
|
$this->assertNull($fields->fieldByName("action_reviewed"));
|
||||||
|
|
||||||
|
SS_Datetime::clear_mock_now();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user