Fixed code style

This commit is contained in:
Christopher Pitt 2015-11-02 12:27:42 +13:00
parent c22e24567e
commit 61fd586533
17 changed files with 2177 additions and 1796 deletions

View File

@ -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.
*
* @return array
*/ */
public static function start(){ public static function start()
$compat = array( {
$compatibility = array(
self::SUBSITES => null, self::SUBSITES => null,
self::TRANSLATABLE => null self::TRANSLATABLE => null,
); );
if(ClassInfo::exists('Subsite')){
$compat[self::SUBSITES] = Subsite::$disable_subsite_filter; if (ClassInfo::exists("Subsite")) {
$compatibility[self::SUBSITES] = Subsite::$disable_subsite_filter;
Subsite::disable_subsite_filter(true); Subsite::disable_subsite_filter(true);
} }
if(ClassInfo::exists('Translatable')){
$compat[self::TRANSLATABLE] = Translatable::locale_filter_enabled(); if (ClassInfo::exists("Translatable")) {
$compatibility[self::TRANSLATABLE] = Translatable::locale_filter_enabled();
Translatable::disable_locale_filter(); Translatable::disable_locale_filter();
} }
return $compat;
return $compatibility;
} }
/** /**
* @param array $compat - see start() * @param array $compatibility
*/ */
public static function done(array $compat){ public static function done(array $compatibility)
if(class_exists('Subsite')){ {
Subsite::$disable_subsite_filter = $compat[self::SUBSITES]; if (class_exists("Subsite")) {
} Subsite::$disable_subsite_filter = $compatibility[self::SUBSITES];
if(class_exists('Translatable')){
Translatable::enable_locale_filter($compat[self::TRANSLATABLE]);
}
} }
if (class_exists("Translatable")) {
Translatable::enable_locale_filter($compatibility[self::TRANSLATABLE]);
}
}
} }

View File

@ -1,37 +1,39 @@
<?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 * @var array
*/ */
private static $allowed_actions = array( private static $allowed_actions = array(
'reviewed', "reviewed",
'save_review', "save_review",
); );
/** /**
* Shows a form with review notes * Shows a form with review notes.
* *
* @param array $data * @param array $data
* @param Form $form * @param Form $form
*
* @return SS_HTTPResponse * @return SS_HTTPResponse
* @throws SS_HTTPResponse_Exception
*/ */
public function reviewed($data, Form $form) { public function reviewed($data, Form $form)
if(!isset($data['ID'])) { {
throw new SS_HTTPResponse_Exception("No record ID", 404); if (!isset($data["ID"])) {
throw new SS_HTTPResponse_Exception('No record ID', 404);
} }
$SQL_id = (int) $data['ID'];
$record = SiteTree::get()->byID($SQL_id); $id = (int) $data["ID"];
$record = SiteTree::get()->byID($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()) {
@ -39,46 +41,54 @@ class ContentReviewCMSExtension extends LeftAndMainExtension {
} }
$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 * Save the review notes and redirect back to the page edit form.
* *
* @param array $data * @param array $data
* @param Form $form * @param Form $form
* @return string - html *
* @return string
*
* @throws SS_HTTPResponse_Exception
*/ */
public function save_review($data, Form $form) { public function save_review($data, Form $form)
if(!isset($data['ID'])) { {
if (!isset($data["ID"])) {
throw new SS_HTTPResponse_Exception("No record ID", 404); throw new SS_HTTPResponse_Exception("No record ID", 404);
} }
$SQL_id = (int) $data['ID'];
$page = SiteTree::get()->byID($SQL_id); $id = (int) $data["ID"];
$page = SiteTree::get()->byID($id);
if ($page && !$page->canEdit()) { if ($page && !$page->canEdit()) {
return Security::permissionFailure(); return Security::permissionFailure();
} }
if (!$page || !$page->ID) { if (!$page || !$page->ID) {
throw new SS_HTTPResponse_Exception("Bad record ID #$SQL_id", 404); throw new SS_HTTPResponse_Exception("Bad record ID #{$id}", 404);
} }
$page->addReviewNote(Member::currentUser(), $data['ReviewNotes']); $page->addReviewNote(Member::currentUser(), $data["ReviewNotes"]);
$page->advanceReviewDate(); $page->advanceReviewDate();
return $this->owner->redirect($this->owner->Link('show/'.$page->ID)); return $this->owner->redirect($this->owner->Link("show/" . $page->ID));
} }
} }

View File

@ -1,13 +1,14 @@
<?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 * @var array
*/ */
private static $db = array( private static $db = array(
@ -19,89 +20,102 @@ class ContentReviewDefaultSettings extends DataExtension {
* @var array * @var array
*/ */
private static $many_many = array( private static $many_many = array(
'ContentReviewGroups' => 'Group', "ContentReviewGroups" => "Group",
'ContentReviewUsers' => 'Member' "ContentReviewUsers" => "Member",
); );
/** /**
* *
* @return string * @return string
*/ */
public function getOwnerNames() { public function getOwnerNames()
{
$names = array(); $names = array();
foreach ($this->OwnerGroups() as $group) { foreach ($this->OwnerGroups() as $group) {
$names[] = $group->getBreadcrumbs(' > '); $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 * @return ManyManyList
*/ */
public function OwnerGroups() { public function OwnerGroups()
return $this->owner->getManyManyComponents('ContentReviewGroups'); {
return $this->owner->getManyManyComponents("ContentReviewGroups");
} }
/** /**
* @return ManyManyList * @return ManyManyList
*/ */
public function OwnerUsers() { public function OwnerUsers()
return $this->owner->getManyManyComponents('ContentReviewUsers'); {
return $this->owner->getManyManyComponents("ContentReviewUsers");
} }
/** /**
* *
* @param \FieldList $fields * @param FieldList $fields
*/ */
public function updateCMSFields(\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."));
$helpText = LiteralField::create('ContentReviewHelp', _t('ContentReview.DEFAULTSETTINGSHELP', 'These content review ' $fields->addFieldToTab("Root.ContentReview", $helpText);
. 'settings will apply to all pages that does not have specific Content Review schedule.'));
$fields->addFieldToTab('Root.ContentReview', $helpText);
$reviewFrequency = DropdownField::create("ReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), SiteTreeContentReview::get_schedule()) $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')); ->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); $fields->addFieldToTab("Root.ContentReview", $reviewFrequency);
$users = Permission::get_members_by_permission(array("CMS_ACCESS_CMSMain", "ADMIN")); $users = Permission::get_members_by_permission(array(
"CMS_ACCESS_CMSMain",
"ADMIN",
));
$usersMap = $users->map('ID', 'Title')->toArray(); $usersMap = $users->map("ID", "Title")->toArray();
asort($usersMap); asort($usersMap);
$userField = ListboxField::create('OwnerUsers', _t("ContentReview.PAGEOWNERUSERS", "Users"), $usersMap) $userField = ListboxField::create("OwnerUsers", _t("ContentReview.PAGEOWNERUSERS", "Users"), $usersMap)
->setMultiple(true) ->setMultiple(true)
->setAttribute('data-placeholder', _t('ContentReview.ADDUSERS', 'Add users')) ->setAttribute("data-placeholder", _t("ContentReview.ADDUSERS", "Add users"))
->setDescription(_t('ContentReview.OWNERUSERSDESCRIPTION', 'Page owners that are responsible for reviews')); ->setDescription(_t("ContentReview.OWNERUSERSDESCRIPTION", "Page owners that are responsible for reviews"));
$fields->addFieldToTab('Root.ContentReview', $userField);
$fields->addFieldToTab("Root.ContentReview", $userField);
$groupsMap = array(); $groupsMap = array();
foreach (Group::get() as $group) { foreach (Group::get() as $group) {
// Listboxfield values are escaped, use ASCII char instead of &raquo; // Listboxfield values are escaped, use ASCII char instead of &raquo;
$groupsMap[$group->ID] = $group->getBreadcrumbs(' > '); $groupsMap[$group->ID] = $group->getBreadcrumbs(" > ");
} }
asort($groupsMap); asort($groupsMap);
$groupField = ListboxField::create('OwnerGroups', _t("ContentReview.PAGEOWNERGROUPS", "Groups"), $groupsMap) $groupField = ListboxField::create("OwnerGroups", _t("ContentReview.PAGEOWNERGROUPS", "Groups"), $groupsMap)
->setMultiple(true) ->setMultiple(true)
->setAttribute('data-placeholder', _t('ContentReview.ADDGROUP', 'Add groups')) ->setAttribute("data-placeholder", _t("ContentReview.ADDGROUP", "Add groups"))
->setDescription(_t('ContentReview.OWNERGROUPSDESCRIPTION', 'Page owners that are responsible for reviews')); ->setDescription(_t("ContentReview.OWNERGROUPSDESCRIPTION", "Page owners that are responsible for reviews"));
$fields->addFieldToTab('Root.ContentReview', $groupField);
$fields->addFieldToTab("Root.ContentReview", $groupField);
} }
/** /**
* Get all Members that are default Content Owners * Get all Members that are default Content Owners. This includes checking group hierarchy
* and adding any direct users.
* *
* This includes checking group hierarchy and adding any direct users * @return ArrayList
*
* @return \ArrayList
*/ */
public function ContentReviewOwners() { public function ContentReviewOwners()
{
return new ArrayList(); return new ArrayList();
return SiteTreeContentReview::merge_owners($this->OwnerGroups(), $this->OwnerUsers()); return SiteTreeContentReview::merge_owners($this->OwnerGroups(), $this->OwnerUsers());
} }
} }

View File

@ -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",
); );
} }

View File

@ -1,52 +1,55 @@
<?php <?php
/**
* Set dates at which content needs to be reviewed and provide
* a report and emails to alert to content needing review
*
* @package contentreview
*/
class SiteTreeContentReview extends DataExtension implements PermissionProvider {
/** /**
* Set dates at which content needs to be reviewed and provide a report and emails to alert
* to content needing review.
* *
* @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
{
/**
* @var array * @var array
*/ */
private static $db = array( private static $db = array(
"ContentReviewType" => "Enum('Inherit, Disabled, Custom', 'Inherit')", "ContentReviewType" => "Enum('Inherit, Disabled, Custom', 'Inherit')",
"ReviewPeriodDays" => "Int", "ReviewPeriodDays" => "Int",
"NextReviewDate" => "Date", "NextReviewDate" => "Date",
'LastEditedByName' => 'Varchar(255)', "LastEditedByName" => "Varchar(255)",
'OwnerNames' => 'Varchar(255)' "OwnerNames" => "Varchar(255)",
); );
/** /**
*
* @var array * @var array
*/ */
private static $defaults = array( private static $defaults = array(
'ContentReviewType' => 'Inherit' "ContentReviewType" => "Inherit",
); );
/** /**
*
* @var array * @var array
*/ */
private static $has_many = array( private static $has_many = array(
'ReviewLogs' => 'ContentReviewLog' "ReviewLogs" => "ContentReviewLog",
); );
/** /**
*
* @var array * @var array
*/ */
private static $belongs_many_many = array( private static $belongs_many_many = array(
'ContentReviewGroups' => 'Group', "ContentReviewGroups" => "Group",
'ContentReviewUsers' => 'Member' "ContentReviewUsers" => "Member",
); );
/** /**
*
* @var array * @var array
*/ */
private static $schedule = array( private static $schedule = array(
@ -65,64 +68,80 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
/** /**
* @return array * @return array
*/ */
public static function get_schedule() { public static function get_schedule()
{
return self::$schedule; return self::$schedule;
} }
/** /**
* Takes a list of groups and members and return a list of unique member * Takes a list of groups and members and return a list of unique member.
* *
* @param SS_List $groups * @param SS_List $groups
* @param SS_List $members * @param SS_List $members
*
* @return ArrayList * @return ArrayList
*/ */
public static function merge_owners(SS_List $groups, SS_List $members) { public static function merge_owners(SS_List $groups, SS_List $members)
{
$contentReviewOwners = new ArrayList(); $contentReviewOwners = new ArrayList();
if ($groups->count()) { if ($groups->count()) {
$groupIDs = array(); $groupIDs = array();
foreach ($groups as $group) { foreach ($groups as $group) {
$familyIDs = $group->collateFamilyIDs(); $familyIDs = $group->collateFamilyIDs();
if (is_array($familyIDs)) { if (is_array($familyIDs)) {
$groupIDs = array_merge($groupIDs, array_values($familyIDs)); $groupIDs = array_merge($groupIDs, array_values($familyIDs));
} }
} }
array_unique($groupIDs); array_unique($groupIDs);
if (count($groupIDs)) { if (count($groupIDs)) {
$groupMembers = DataObject::get('Member')->where("\"Group\".\"ID\" IN (" . implode(",",$groupIDs) . ")") $groupMembers = DataObject::get("Member")->where("\"Group\".\"ID\" IN (" . implode(",", $groupIDs) . ")")
->leftJoin("Group_Members", "\"Member\".\"ID\" = \"Group_Members\".\"MemberID\"") ->leftJoin("Group_Members", "\"Member\".\"ID\" = \"Group_Members\".\"MemberID\"")
->leftJoin("Group", "\"Group_Members\".\"GroupID\" = \"Group\".\"ID\""); ->leftJoin("Group", "\"Group_Members\".\"GroupID\" = \"Group\".\"ID\"");
$contentReviewOwners->merge($groupMembers); $contentReviewOwners->merge($groupMembers);
} }
} }
$contentReviewOwners->merge($members); $contentReviewOwners->merge($members);
$contentReviewOwners->removeDuplicates(); $contentReviewOwners->removeDuplicates();
return $contentReviewOwners; return $contentReviewOwners;
} }
/** /**
* * @param FieldList $actions
* @param \FieldList $actions
*/ */
public function updateCMSActions(\FieldList $actions) { public function updateCMSActions(FieldList $actions)
{
if ($this->canBeReviewedBy(Member::currentUser())) { if ($this->canBeReviewedBy(Member::currentUser())) {
$reviewAction = FormAction::create('reviewed', _t('ContentReview.BUTTONREVIEWED', 'Content reviewed')) $reviewAction = FormAction::create("reviewed", _t("ContentReview.BUTTONREVIEWED", "Content reviewed"))
->setAttribute('data-icon', 'pencil') ->setAttribute("data-icon", "pencil")
->setAttribute('data-text-alternate', _t('ContentReview.BUTTONREVIEWED', 'Content reviewed')); ->setAttribute("data-text-alternate", _t("ContentReview.BUTTONREVIEWED", "Content reviewed"));
$actions->push($reviewAction); $actions->push($reviewAction);
} }
} }
/** /**
* Returns false if the content review have disabled.
* *
* @param SiteTree $page * @param SiteTree $page
* @return Date | false - returns false if the content review have disabled *
* @return bool|Date
*/ */
public function getReviewDate(SiteTree $page=null) { public function getReviewDate(SiteTree $page = null)
{
if ($page === null) { if ($page === null) {
$page = $this->owner; $page = $this->owner;
} }
if($page->obj('NextReviewDate')->exists()) {
return $page->obj('NextReviewDate'); if ($page->obj("NextReviewDate")->exists()) {
return $page->obj("NextReviewDate");
} }
$options = $this->owner->getOptions(); $options = $this->owner->getOptions();
@ -130,126 +149,148 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
if (!$options) { if (!$options) {
return false; return false;
} }
if (!$options->ReviewPeriodDays) { if (!$options->ReviewPeriodDays) {
return false; return false;
} }
// Failover to check on ReviewPeriodDays + LastEdited // Failover to check on ReviewPeriodDays + LastEdited
$nextReviewUnixSec = strtotime(' + '.$options->ReviewPeriodDays . ' days', SS_Datetime::now()->format('U')); $nextReviewUnixSec = strtotime(" + " . $options->ReviewPeriodDays . " days", SS_Datetime::now()->format("U"));
$date = Date::create('NextReviewDate'); $date = Date::create("NextReviewDate");
$date->setValue(date('Y-m-d H:i:s', $nextReviewUnixSec)); $date->setValue(date("Y-m-d H:i:s", $nextReviewUnixSec));
return $date; return $date;
} }
/** /**
* Get the object that have the information about the content * Get the object that have the information about the content review settings. Either:
* review settings. Either *
* - a SiteTreeContentReview decorated object * - a SiteTreeContentReview decorated object
* - the default SiteTree config * - the default SiteTree config
* - false if this page have it's content review disabled * - false if this page have it's content review disabled
* *
* Will go through parents and root pages will use the siteconfig * Will go through parents and root pages will use the site config if their setting is Inherit.
* if their setting is Inherit.
* *
* @return DataObject or false if no settings found * @return bool|DataObject
*
* @throws Exception
*/ */
public function getOptions() { public function getOptions()
if($this->owner->ContentReviewType == 'Custom') { {
if ($this->owner->ContentReviewType == "Custom") {
return $this->owner; return $this->owner;
} }
if($this->owner->ContentReviewType == 'Disabled') {
if ($this->owner->ContentReviewType == "Disabled") {
return false; return false;
} }
$page = $this->owner; $page = $this->owner;
// $page is inheriting it's settings from it's parent, find // $page is inheriting it's settings from it's parent, find
// the first valid parent with a valid setting // the first valid parent with a valid setting
while ($parent = $page->Parent()) { while ($parent = $page->Parent()) {
// Root page, use site config // Root page, use site config
if (!$parent->exists()) { if (!$parent->exists()) {
return SiteConfig::current_site_config(); return SiteConfig::current_site_config();
} }
if($parent->ContentReviewType == 'Custom') {
if ($parent->ContentReviewType == "Custom") {
return $parent; return $parent;
} }
if($parent->ContentReviewType == 'Disabled') {
if ($parent->ContentReviewType == "Disabled") {
return false; return false;
} }
$page = $parent; $page = $parent;
} }
throw new Exception('This shouldn\'t really happen, as per usual developer logic.');
throw new Exception("This shouldn't really happen, as per usual developer logic.");
} }
/** /**
*
* @return string * @return string
*/ */
public function getOwnerNames() { public function getOwnerNames()
{
$options = $this->getOptions(); $options = $this->getOptions();
$names = array(); $names = array();
if (!$options) { if (!$options) {
return ''; return "";
} }
foreach ($options->OwnerGroups() as $group) { foreach ($options->OwnerGroups() as $group) {
$names[] = $group->getBreadcrumbs(' > '); $names[] = $group->getBreadcrumbs(" > ");
} }
foreach ($options->OwnerUsers() as $group) { foreach ($options->OwnerUsers() as $group) {
$names[] = $group->getName(); $names[] = $group->getName();
} }
return implode(', ', $names);
return implode(", ", $names);
} }
/** /**
* * @return null|string
* @return string
*/ */
public function getEditorName() { public function getEditorName()
{
$member = Member::currentUser(); $member = Member::currentUser();
if ($member) { if ($member) {
return $member->FirstName .' '. $member->Surname; return $member->FirstName . " " . $member->Surname;
} }
return null; return null;
} }
/** /**
* Get all Members that are Content Owners to this page * Get all Members that are Content Owners to this page. This includes checking group
* hierarchy and adding any direct users.
* *
* This includes checking group hierarchy and adding any direct users * @return ArrayList
*
* @return \ArrayList
*/ */
public function ContentReviewOwners() { public function ContentReviewOwners()
return SiteTreeContentReview::merge_owners($this->OwnerGroups(), $this->OwnerUsers()); {
return SiteTreeContentReview::merge_owners(
$this->OwnerGroups(),
$this->OwnerUsers()
);
} }
/** /**
* @return ManyManyList * @return ManyManyList
*/ */
public function OwnerGroups() { public function OwnerGroups()
return $this->owner->getManyManyComponents('ContentReviewGroups'); {
return $this->owner->getManyManyComponents("ContentReviewGroups");
} }
/** /**
* @return ManyManyList * @return ManyManyList
*/ */
public function OwnerUsers() { public function OwnerUsers()
return $this->owner->getManyManyComponents('ContentReviewUsers'); {
return $this->owner->getManyManyComponents("ContentReviewUsers");
} }
/** /**
*
* @param FieldList $fields * @param FieldList $fields
* @return void
*/ */
public function updateSettingsFields(FieldList $fields) { public function updateSettingsFields(FieldList $fields)
{
Requirements::javascript('contentreview/javascript/contentreview.js'); Requirements::javascript("contentreview/javascript/contentreview.js");
// Display read-only version only // Display read-only version only
if (!Permission::check("EDIT_CONTENT_REVIEW_FIELDS")) { if (!Permission::check("EDIT_CONTENT_REVIEW_FIELDS")) {
$schedule = self::get_schedule(); $schedule = self::get_schedule();
$contentOwners = ReadonlyField::create('ROContentOwners', _t('ContentReview.CONTENTOWNERS', 'Content Owners'), $this->getOwnerNames()); $contentOwners = ReadonlyField::create("ROContentOwners", _t("ContentReview.CONTENTOWNERS", "Content Owners"), $this->getOwnerNames());
$nextReviewAt = DateField::create('RONextReviewDate', _t("ContentReview.NEXTREVIEWDATE", "Next review date"), $this->owner->NextReviewDate); $nextReviewAt = DateField::create('RONextReviewDate', _t("ContentReview.NEXTREVIEWDATE", "Next review date"), $this->owner->NextReviewDate);
if (!isset($schedule[$this->owner->ReviewPeriodDays])) { if (!isset($schedule[$this->owner->ReviewPeriodDays])) {
$reviewFreq = ReadonlyField::create("ROReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), $schedule[0]); $reviewFreq = ReadonlyField::create("ROReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), $schedule[0]);
} else { } else {
@ -259,88 +300,92 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
$logConfig = GridFieldConfig::create() $logConfig = GridFieldConfig::create()
->addComponent(new GridFieldSortableHeader()) ->addComponent(new GridFieldSortableHeader())
->addComponent($logColumns = new GridFieldDataColumns()); ->addComponent($logColumns = new GridFieldDataColumns());
// Cast the value to the users prefered date format
// Cast the value to the users preferred date format
$logColumns->setFieldCasting(array( $logColumns->setFieldCasting(array(
'Created' => 'DateTimeField->value' "Created" => "DateTimeField->value",
)); ));
$logs = GridField::create('ROReviewNotes', 'Review Notes', $this->owner->ReviewLogs(), $logConfig);
$logs = GridField::create("ROReviewNotes", "Review Notes", $this->owner->ReviewLogs(), $logConfig);
$optionsFrom = ReadonlyField::create('ROType', _t('ContentReview.SETTINGSFROM', "Options are"), $this->owner->ContentReviewType); $optionsFrom = ReadonlyField::create("ROType", _t("ContentReview.SETTINGSFROM", "Options are"), $this->owner->ContentReviewType);
$fields->addFieldsToTab("Root.ContentReview", array( $fields->addFieldsToTab("Root.ContentReview", array(
$contentOwners, $contentOwners,
$nextReviewAt->performReadonlyTransformation(), $nextReviewAt->performReadonlyTransformation(),
$reviewFreq, $reviewFreq,
$optionsFrom, $optionsFrom,
$logs $logs,
)); ));
return; return;
} }
$options = array(); $options = array();
$options["Disabled"] = _t('ContentReview.DISABLE', "Disable content review"); $options["Disabled"] = _t("ContentReview.DISABLE", "Disable content review");
$options["Inherit"] = _t('ContentReview.INHERIT', "Inherit from parent page"); $options["Inherit"] = _t("ContentReview.INHERIT", "Inherit from parent page");
$options["Custom"] = _t('ContentReview.CUSTOM', "Custom settings"); $options["Custom"] = _t("ContentReview.CUSTOM", "Custom settings");
$viewersOptionsField = OptionsetField::create("ContentReviewType", _t('ContentReview.OPTIONS', "Options"), $options);
$viewersOptionsField = OptionsetField::create("ContentReviewType", _t("ContentReview.OPTIONS", "Options"), $options);
$users = Permission::get_members_by_permission(array("CMS_ACCESS_CMSMain", "ADMIN")); $users = Permission::get_members_by_permission(array("CMS_ACCESS_CMSMain", "ADMIN"));
$usersMap = $users->map('ID', 'Title')->toArray(); $usersMap = $users->map("ID", "Title")->toArray();
asort($usersMap); asort($usersMap);
$userField = ListboxField::create('OwnerUsers', _t("ContentReview.PAGEOWNERUSERS", "Users"), $usersMap) $userField = ListboxField::create("OwnerUsers", _t("ContentReview.PAGEOWNERUSERS", "Users"), $usersMap)
->setMultiple(true) ->setMultiple(true)
->setAttribute('data-placeholder', _t('ContentReview.ADDUSERS', 'Add users')) ->setAttribute("data-placeholder", _t("ContentReview.ADDUSERS", "Add users"))
->setDescription(_t('ContentReview.OWNERUSERSDESCRIPTION', 'Page owners that are responsible for reviews')); ->setDescription(_t('ContentReview.OWNERUSERSDESCRIPTION', 'Page owners that are responsible for reviews'));
$groupsMap = array(); $groupsMap = array();
foreach (Group::get() as $group) { foreach (Group::get() as $group) {
// Listboxfield values are escaped, use ASCII char instead of &raquo; $groupsMap[$group->ID] = $group->getBreadcrumbs(" > ");
$groupsMap[$group->ID] = $group->getBreadcrumbs(' > ');
} }
asort($groupsMap); asort($groupsMap);
$groupField = ListboxField::create('OwnerGroups', _t("ContentReview.PAGEOWNERGROUPS", "Groups"), $groupsMap) $groupField = ListboxField::create("OwnerGroups", _t("ContentReview.PAGEOWNERGROUPS", "Groups"), $groupsMap)
->setMultiple(true) ->setMultiple(true)
->setAttribute('data-placeholder', _t('ContentReview.ADDGROUP', 'Add groups')) ->setAttribute("data-placeholder", _t("ContentReview.ADDGROUP", "Add groups"))
->setDescription(_t('ContentReview.OWNERGROUPSDESCRIPTION', 'Page owners that are responsible for reviews')); ->setDescription(_t("ContentReview.OWNERGROUPSDESCRIPTION", "Page owners that are responsible for reviews"));
$reviewDate = DateField::create("NextReviewDate", _t("ContentReview.NEXTREVIEWDATE", "Next review date")) $reviewDate = DateField::create("NextReviewDate", _t("ContentReview.NEXTREVIEWDATE", "Next review date"))
->setConfig('showcalendar', true) ->setConfig("showcalendar", true)
->setConfig('dateformat', 'yyyy-MM-dd') ->setConfig("dateformat", "yyyy-MM-dd")
->setConfig('datavalueformat', 'yyyy-MM-dd') ->setConfig("datavalueformat", "yyyy-MM-dd")
->setDescription(_t('ContentReview.NEXTREVIEWDATADESCRIPTION', 'Leave blank for no review')); ->setDescription(_t("ContentReview.NEXTREVIEWDATADESCRIPTION", "Leave blank for no review"));
$reviewFrequency = DropdownField::create("ReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), self::get_schedule()) $reviewFrequency = DropdownField::create("ReviewPeriodDays", _t("ContentReview.REVIEWFREQUENCY", "Review frequency"), self::get_schedule())
->setDescription(_t('ContentReview.REVIEWFREQUENCYDESCRIPTION', 'The review date will be set to this far in the future whenever the page is published')); ->setDescription(_t("ContentReview.REVIEWFREQUENCYDESCRIPTION", "The review date will be set to this far in the future whenever the page is published"));
$notesField = GridField::create('ReviewNotes', 'Review Notes', $this->owner->ReviewLogs(), GridFieldConfig_RecordEditor::create()); $notesField = GridField::create("ReviewNotes", "Review Notes", $this->owner->ReviewLogs(), GridFieldConfig_RecordEditor::create());
$schedule = self::get_schedule();
$fields->addFieldsToTab("Root.ContentReview", array( $fields->addFieldsToTab("Root.ContentReview", array(
new HeaderField(_t('ContentReview.REVIEWHEADER', "Content review"), 2), new HeaderField(_t("ContentReview.REVIEWHEADER", "Content review"), 2),
$viewersOptionsField, $viewersOptionsField,
CompositeField::create( CompositeField::create(
$userField, $userField,
$groupField, $groupField,
$reviewDate, $reviewDate,
$reviewFrequency $reviewFrequency
)->addExtraClass('custom-settings'), )->addExtraClass("custom-settings"),
ReadonlyField::create('ROContentOwners', _t('ContentReview.CONTENTOWNERS', 'Content Owners'), $this->getOwnerNames()), ReadonlyField::create("ROContentOwners", _t("ContentReview.CONTENTOWNERS", "Content Owners"), $this->getOwnerNames()),
ReadonlyField::create('RONextReviewDate', _t("ContentReview.NEXTREVIEWDATE", "Next review date"), $this->owner->NextReviewDate), ReadonlyField::create("RONextReviewDate", _t("ContentReview.NEXTREVIEWDATE", "Next review date"), $this->owner->NextReviewDate),
$notesField $notesField,
)); ));
} }
/** /**
* Creates a ContentReviewLog and connects it to this Page * Creates a ContentReviewLog and connects it to this Page.
* *
* @param Member $reviewer * @param Member $reviewer
* @param string $message * @param string $message
*/ */
public function addReviewNote(Member $reviewer, $message) { public function addReviewNote(Member $reviewer, $message)
{
$reviewLog = ContentReviewLog::create(); $reviewLog = ContentReviewLog::create();
$reviewLog->Note = $message; $reviewLog->Note = $message;
$reviewLog->ReviewerID = $reviewer->ID; $reviewLog->ReviewerID = $reviewer->ID;
@ -349,32 +394,40 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
/** /**
* Advance review date to the next date based on review period or set it to null * Advance review date to the next date based on review period or set it to null
* if there is no schedule * if there is no schedule. Returns true if date was required and false is content
* review is 'off'.
* *
* @return bool - returns true if date was set and false is content review is 'off' * @return bool
*/ */
public function advanceReviewDate() { public function advanceReviewDate()
$options = $this->getOptions(); {
$nextDate = false; $nextDate = false;
$options = $this->getOptions();
if ($options && $options->ReviewPeriodDays) { if ($options && $options->ReviewPeriodDays) {
$nextDate = date('Y-m-d', strtotime('+ ' . $options->ReviewPeriodDays . ' days', SS_Datetime::now()->format('U'))); $nextDate = date('Y-m-d', strtotime('+ ' . $options->ReviewPeriodDays . ' days', SS_Datetime::now()->format('U')));
}
$this->owner->NextReviewDate = $nextDate; $this->owner->NextReviewDate = $nextDate;
$this->owner->write(); $this->owner->write();
}
return (bool) $nextDate; return (bool) $nextDate;
} }
/** /**
* Check if a review is due by a member for this owner * Check if a review is due by a member for this owner.
* *
* @param Member $member * @param Member $member
* @return boolean *
* @return bool
*/ */
public function canBeReviewedBy(Member $member = null) { public function canBeReviewedBy(Member $member = null)
if(!$this->owner->obj('NextReviewDate')->exists()) { {
if (!$this->owner->obj("NextReviewDate")->exists()) {
return false; return false;
} }
if($this->owner->obj('NextReviewDate')->InFuture()) {
if ($this->owner->obj("NextReviewDate")->InFuture()) {
return false; return false;
} }
@ -384,7 +437,6 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
return false; return false;
} }
// This content should be reviewed by someone
if (!$member) { if (!$member) {
return true; return true;
} }
@ -393,42 +445,39 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
return true; return true;
} }
if($options->OwnerUsers()->find('ID', $member->ID)) { if ($options->OwnerUsers()->find("ID", $member->ID)) {
return true; return true;
} }
return false; return false;
} }
/** /**
* Set the review data from the review period, if set. * Set the review data from the review period, if set.
*/ */
public function onBeforeWrite() { public function onBeforeWrite()
{
$this->owner->LastEditedByName = $this->owner->getEditorName(); $this->owner->LastEditedByName = $this->owner->getEditorName();
$this->owner->OwnerNames = $this->owner->getOwnerNames(); $this->owner->OwnerNames = $this->owner->getOwnerNames();
// If the user changed the Type, we need to recalculate the // If the user changed the type, we need to recalculate the review date.
// Next review date if ($this->owner->isChanged("ContentReviewType", 2)) {
if($this->owner->isChanged('ContentReviewType', 2)) { if ($this->owner->ContentReviewType == "Disabled") {
// Changed to Disabled
if($this->owner->ContentReviewType == 'Disabled') {
$this->setDefaultReviewDateForDisabled(); $this->setDefaultReviewDateForDisabled();
// Changed to Custom } elseif ($this->owner->ContentReviewType == "Custom") {
} elseif($this->owner->ContentReviewType == 'Custom') {
$this->setDefaultReviewDateForCustom(); $this->setDefaultReviewDateForCustom();
// Changed to Inherit
} else { } else {
$this->setDefaultReviewDateForInherited(); $this->setDefaultReviewDateForInherited();
} }
} }
// Ensure that a inherited page always have a next review date // Ensure that a inherited page always have a next review date
if($this->owner->ContentReviewType == 'Inherit' && !$this->owner->NextReviewDate) { if ($this->owner->ContentReviewType == "Inherit" && !$this->owner->NextReviewDate) {
$this->setDefaultReviewDateForInherited(); $this->setDefaultReviewDateForInherited();
} }
// Oh yey.. now we need to update all the child pages that inherit this setting // We need to update all the child pages that inherit this setting. We can only
// We can only change children after this record has been created, otherwise the stageChildren // change children after this record has been created, otherwise the stageChildren
// method will grab all pages in the DB (this messes up unit testing) // method will grab all pages in the DB (this messes up unit testing)
if (!$this->owner->exists()) { if (!$this->owner->exists()) {
return; return;
@ -436,34 +485,32 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
// parent page change it's review period // parent page change it's review period
// && !$this->owner->isChanged('ContentReviewType', 2) // && !$this->owner->isChanged('ContentReviewType', 2)
if($this->owner->isChanged('ReviewPeriodDays', 2)) { if ($this->owner->isChanged("ReviewPeriodDays", 2)) {
$nextReviewUnixSec = strtotime(' + '.$this->owner->ReviewPeriodDays . ' days', SS_Datetime::now()->format('U')); $nextReviewUnixSec = strtotime(" + " . $this->owner->ReviewPeriodDays . " days", SS_Datetime::now()->format("U"));
$this->owner->NextReviewDate = date('Y-m-d', $nextReviewUnixSec); $this->owner->NextReviewDate = date("Y-m-d", $nextReviewUnixSec);
} }
// //
if($this->owner->isChanged('NextReviewDate', 2)) { if ($this->owner->isChanged("NextReviewDate", 2)) {
$c = ContentReviewCompatability::start(); $children = $this->owner->stageChildren(true)->filter("ContentReviewType", "Inherit");
$children = $this->owner->stageChildren(true)->filter('ContentReviewType', 'Inherit'); $compatibility = ContentReviewCompatability::start();
foreach ($children as $child) { foreach ($children as $child) {
$child->NextReviewDate = $this->owner->NextReviewDate; $child->NextReviewDate = $this->owner->NextReviewDate;
$child->write(); $child->write();
} }
ContentReviewCompatability::done($c);
ContentReviewCompatability::done($compatibility);
} }
} }
/** private function setDefaultReviewDateForDisabled()
* {
*/
private function setDefaultReviewDateForDisabled() {
$this->owner->NextReviewDate = null; $this->owner->NextReviewDate = null;
} }
/** protected function setDefaultReviewDateForCustom()
* {
*/
protected function setDefaultReviewDateForCustom() {
if ($this->owner->NextReviewDate) { if ($this->owner->NextReviewDate) {
return; return;
} }
@ -476,22 +523,19 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
} else { } else {
$this->owner->NextReviewDate = $nextDate; $this->owner->NextReviewDate = $nextDate;
} }
} }
/** protected function setDefaultReviewDateForInherited()
* {
*/
protected function setDefaultReviewDateForInherited() {
$options = $this->getOptions(); $options = $this->getOptions();
$nextDate = null; $nextDate = null;
// Set the review date to be the same as the parents reviewdate
if ($options && $this->owner->parent()->exists()) { if ($options && $this->owner->parent()->exists()) {
$nextDate = $this->getReviewDate($this->owner->parent()); $nextDate = $this->getReviewDate($this->owner->parent());
// Use the defualt settings
} elseif ($options instanceof SiteConfig) { } elseif ($options instanceof SiteConfig) {
$nextDate = $this->getReviewDate(); $nextDate = $this->getReviewDate();
} }
if (is_object($nextDate)) { if (is_object($nextDate)) {
$this->owner->NextReviewDate = $nextDate->getValue(); $this->owner->NextReviewDate = $nextDate->getValue();
} else { } else {
@ -500,38 +544,43 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
} }
/** /**
* Provide permissions to the CMS * Provide permissions to the CMS.
* *
* @return array * @return array
*/ */
public function providePermissions() { public function providePermissions()
{
return array( return array(
"EDIT_CONTENT_REVIEW_FIELDS" => array( "EDIT_CONTENT_REVIEW_FIELDS" => array(
'name' => "Set content owners and review dates", "name" => "Set content owners and review dates",
'category' => _t('Permissions.CONTENT_CATEGORY', 'Content permissions'), "category" => _t("Permissions.CONTENT_CATEGORY", "Content permissions"),
'sort' => 50 "sort" => 50,
) ),
); );
} }
/** /**
* If the queuedjobs module is installed, queue up the first job for 9am tomorrow morning (by default) * If the queued jobs module is installed, queue up the first job for 9am tomorrow morning
* (by default).
*/ */
public function requireDefaultRecords() { public function requireDefaultRecords()
if(class_exists('ContentReviewNotificationJob')) { {
if (class_exists("ContentReviewNotificationJob")) {
// Ensure there is not already a job queued // Ensure there is not already a job queued
if(QueuedJobDescriptor::get()->filter('Implementation', 'ContentReviewNotificationJob')->first()) return; if (QueuedJobDescriptor::get()->filter("Implementation", "ContentReviewNotificationJob")->first()) {
return;
}
$nextRun = new ContentReviewNotificationJob(); $nextRun = new ContentReviewNotificationJob();
$runHour = Config::inst()->get('ContentReviewNotificationJob', 'first_run_hour'); $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"))); $firstRunTime = date("Y-m-d H:i:s", mktime($runHour, 0, 0, date("m"), date("d") + 1, date("y")));
singleton('QueuedJobService')->queueJob( singleton("QueuedJobService")->queueJob(
$nextRun, $nextRun,
$firstRunTime $firstRunTime
); );
DB::alteration_message(sprintf('Added ContentReviewNotificationJob to run at %s', $firstRunTime)); DB::alteration_message(sprintf("Added ContentReviewNotificationJob to run at %s", $firstRunTime));
} }
} }
} }

View File

@ -1,60 +1,82 @@
<?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 * The hour that the first job will be created at (for the next day). All other jobs should
* around this time too, as the next generation is queued when this job is run. * be triggered around this time too, as the next generation is queued when this job is run.
*
* @var int
*
* @config * @config
*/ */
private static $first_run_hour = 9; private static $first_run_hour = 9;
/** /**
* @var int The hour at which to run these jobs * The hour at which to run these jobs.
*
* @var int
*
* @config * @config
*/ */
private static $next_run_hour = 9; 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.
*
* @var int
*
* @config * @config
*/ */
private static $next_run_minute = 0; 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).
*
* @var int
*
* @config * @config
*/ */
private static $next_run_in_days = 1; 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() { /**
* @return string
*/
public function getJobType()
{
$this->totalSteps = 1; $this->totalSteps = 1;
return QueuedJob::QUEUED; return QueuedJob::QUEUED;
} }
public function process() { public function process()
{
$this->queueNextRun(); $this->queueNextRun();
$task = new ContentReviewEmails(); $task = new ContentReviewEmails();
$task->run(new SS_HTTPRequest('GET', '/dev/tasks/ContentReviewEmails')); $task->run(new SS_HTTPRequest("GET", "/dev/tasks/ContentReviewEmails"));
$this->currentStep = 1; $this->currentStep = 1;
$this->isComplete = true; $this->isComplete = true;
@ -63,20 +85,22 @@ class ContentReviewNotificationJob extends AbstractQueuedJob implements QueuedJo
/** /**
* Queue up the next job to run. * Queue up the next job to run.
*/ */
protected function queueNextRun() { protected function queueNextRun()
{
$nextRun = new ContentReviewNotificationJob(); $nextRun = new ContentReviewNotificationJob();
$nextRunTime = mktime( $nextRunTime = mktime(
self::$next_run_hour, self::$next_run_hour,
self::$next_run_minute, self::$next_run_minute,
0, 0,
date('m'), date("m"),
date('d') + self::$next_run_in_days, date("d") + self::$next_run_in_days,
date('Y') date("Y")
); );
singleton('QueuedJobService')->queueJob( singleton("QueuedJobService")->queueJob(
$nextRun, $nextRun,
date('Y-m-d H:i:s', $nextRunTime) date("Y-m-d H:i:s", $nextRunTime)
); );
} }
} }

View File

@ -1,45 +1,43 @@
<?php <?php
class ContentReviewLog extends DataObject { class ContentReviewLog extends DataObject
{
/** /**
*
* @var array * @var array
*/ */
private static $db = array( private static $db = array(
'Note' => 'Text' "Note" => "Text",
); );
/** /**
*
* @var array * @var array
*/ */
private static $has_one = array( private static $has_one = array(
'Reviewer' => 'Member', "Reviewer" => "Member",
'SiteTree' => 'SiteTree' "SiteTree" => "SiteTree",
); );
/** /**
*
* @var array * @var array
*/ */
private static $summary_fields = array( private static $summary_fields = array(
'Note' => array('title' => 'Note'), "Note" => array("title" => "Note"),
'Created' => array('title' => 'Reviewed at'), "Created" => array("title" => "Reviewed at"),
'Reviewer.Title' => array('title' => 'Reviewed by') "Reviewer.Title" => array("title" => "Reviewed by"),
); );
/** /**
*
* @var string * @var string
*/ */
private static $default_sort = 'Created DESC'; private static $default_sort = "Created DESC";
/** /**
* @param mixed $member
* *
* @return bool * @return bool
*/ */
public function canView($member = null) { public function canView($member = null)
{
return (bool) Member::currentUser(); return (bool) Member::currentUser();
} }
} }

View File

@ -1,101 +1,100 @@
<?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 * @return string
*/ */
public function title() { public function title()
return _t('PagesDueForReviewReport.TITLE', 'Pages due for review'); {
return _t("PagesDueForReviewReport.TITLE", "Pages due for review");
} }
/** /**
* * @return FieldList
* @return \FieldList
*/ */
public function parameterFields() { public function parameterFields()
{
$filtersList = new FieldList(); $filtersList = new FieldList();
$filtersList->push( $filtersList->push(
DateField::create('ReviewDateAfter', 'Review date after or on') DateField::create("ReviewDateAfter", "Review date after or on")
->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(
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"));
return $filtersList; return $filtersList;
} }
/** /**
*
* @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",
'formatting' => function($value, $item) { "formatting" => function ($value, $item) {
if($item->ContentReviewType == 'Disabled') { if ($item->ContentReviewType == "Disabled") {
return 'disabled'; return "disabled";
} }
if($item->ContentReviewType == 'Inherit') { if ($item->ContentReviewType == "Inherit") {
$setting = $item->getOptions(); $setting = $item->getOptions();
if (!$setting) { if (!$setting) {
return 'disabled'; return "disabled";
} }
return $item->obj('NextReviewDate')->Full(); return $item->obj("NextReviewDate")->Full();
} }
return $value; return $value;
} }
), ),
'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>',
return sprintf("%s <a href='%s'>%s</a>",
$stageLink, $stageLink,
$liveLink ? $liveLink : $stageLink . '?stage=Stage', $liveLink ? $liveLink : $stageLink . "?stage=Stage",
$liveLink ? '(live)' : '(draft)' $liveLink ? "(live)" : "(draft)"
); );
} }
), ),
'ContentReviewType' => array( "ContentReviewType" => array(
'title' => 'Settings are', "title" => "Settings are",
'formatting' => function($value, $item) use($linkPath, $linkQuery) { "formatting" => function ($value, $item) use ($linkPath,$linkQuery) {
if($item->ContentReviewType == 'Inherit') { if ($item->ContentReviewType == "Inherit") {
$options = $item->getOptions(); $options = $item->getOptions();
if ($options && $options instanceof SiteConfig) { if ($options && $options instanceof SiteConfig) {
return 'Inherited from <a href="admin/settings">Settings</a>'; return "Inherited from <a href='admin/settings'>Settings</a>";
} elseif ($options) { } elseif ($options) {
return sprintf( return sprintf(
'Inherited from <a href="%s/%d?%s">%s</a>', "Inherited from <a href='%s/%d?%s'>%s</a>",
$linkPath, $linkPath,
$options->ID, $options->ID,
$linkQuery, $linkQuery,
@ -103,6 +102,7 @@ class PagesDueForReviewReport extends SS_Report {
); );
} }
} }
return $value; return $value;
} }
), ),
@ -112,54 +112,57 @@ class PagesDueForReviewReport extends SS_Report {
} }
/** /**
*
* @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();
$compatibility = ContentReviewCompatability::start();
if (empty($params["ReviewDateBefore"]) && empty($params["ReviewDateAfter"])) {
// If there's no review dates set, default to all pages due for review now // If there's no review dates set, default to all pages due for review now
$reviewDate = new Zend_Date(SS_Datetime::now()->Format('U')); $reviewDate = new Zend_Date(SS_Datetime::now()->Format("U"));
$reviewDate->add(1, Zend_Date::DAY); $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 { } else {
// Review date before // Review date before
if (!empty($params['ReviewDateBefore'])) { if (!empty($params['ReviewDateBefore'])) {
// TODO Get value from DateField->dataValue() once we have access to form elements here // 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 = new Zend_Date($params["ReviewDateBefore"], Config::inst()->get("i18n", "date_format"));
$reviewDate->add(1, Zend_Date::DAY); $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")));
} }
// Review date after // Review date after
if(!empty($params['ReviewDateAfter'])) { if (!empty($params["ReviewDateAfter"])) {
// TODO Get value from DateField->dataValue() once we have access to form elements here // TODO Get value from DateField->dataValue() once we have access to form elements here
$reviewDate = new Zend_Date($params['ReviewDateAfter'], i18n::get_date_format()); $reviewDate = new Zend_Date($params["ReviewDateAfter"], Config::inst()->get("i18n", "date_format"));
$records = $records->where(sprintf('"NextReviewDate" >= \'%s\'', $reviewDate->toString('YYYY-MM-dd'))); $records = $records->where(sprintf("\"NextReviewDate\" >= '%s'", $reviewDate->toString("YYYY-MM-dd")));
} }
} }
// Show virtual pages? // Show virtual pages?
if(empty($params['ShowVirtualPages'])) { if (empty($params["ShowVirtualPages"])) {
$virtualPageClasses = ClassInfo::subclassesFor('VirtualPage'); $virtualPageClasses = ClassInfo::subclassesFor("VirtualPage");
$records = $records->where(sprintf( $records = $records->where(sprintf(
'"SiteTree"."ClassName" NOT IN (\'%s\')', "\"SiteTree\".\"ClassName\" NOT IN ('%s')",
implode("','", array_values($virtualPageClasses)) implode("','", array_values($virtualPageClasses))
)); ));
} }
// Owner dropdown // Owner dropdown
if(!empty($params['ContentReviewOwner'])) { if (!empty($params["ContentReviewOwner"])) {
$ownerNames = Convert::raw2sql($params['ContentReviewOwner']); $ownerNames = Convert::raw2sql($params["ContentReviewOwner"]);
$records = $records->filter('OwnerNames:PartialMatch', $ownerNames); $records = $records->filter("OwnerNames:PartialMatch", $ownerNames);
} }
$r = new ArrayList($records->sort('NextReviewDate', 'DESC')->toArray()); $records = new ArrayList($records->sort("NextReviewDate", "DESC")->toArray());
ContentReviewCompatability::done($c);
return $r; ContentReviewCompatability::done($compatibility);
return $records;
} }
} }

View File

@ -1,75 +1,76 @@
<?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 * @return string
*/ */
public function title() { public function title()
return _t('PagesWithoutReviewScheduleReport.TITLE', 'Pages without a scheduled review.'); {
return _t("PagesWithoutReviewScheduleReport.TITLE", "Pages without a scheduled review.");
} }
/** /**
* * @return FieldList
* @return \FieldList
*/ */
public function parameterFields() { public function parameterFields()
{
$params = new FieldList(); $params = new FieldList();
$params->push(new CheckboxField('ShowVirtualPages', 'Show Virtual Pages')); $params->push(new CheckboxField("ShowVirtualPages", "Show Virtual Pages"));
return $params; 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>',
return sprintf("%s <a href='%s'>%s</a>",
$stageLink, $stageLink,
$liveLink ? $liveLink : $stageLink . '?stage=Stage', $liveLink ? $liveLink : $stageLink . "?stage=Stage",
$liveLink ? '(live)' : '(draft)' $liveLink ? "(live)" : "(draft)"
); );
} },
), ),
'ContentReviewType' => array( "ContentReviewType" => array(
'title' => 'Settings are', "title" => "Settings are",
'formatting' => function($value, $item) use($linkPath, $linkQuery) { "formatting" => function ($value, $item) use ($linkPath, $linkQuery) {
if($item->ContentReviewType == 'Inherit') { if ($item->ContentReviewType == "Inherit") {
$options = $item->getOptions(); $options = $item->getOptions();
if ($options && $options instanceof SiteConfig) { if ($options && $options instanceof SiteConfig) {
return 'Inherited from <a href="admin/settings">Settings</a>'; return "Inherited from <a href='admin/settings'>Settings</a>";
} elseif ($options) { } elseif ($options) {
return sprintf( return sprintf(
'Inherited from <a href="%s/%d?%s">%s</a>', "Inherited from <a href='%s/%d?%s'>%s</a>",
$linkPath, $linkPath,
$options->ID, $options->ID,
$linkQuery, $linkQuery,
@ -77,37 +78,39 @@ class PagesWithoutReviewScheduleReport extends SS_Report {
); );
} }
} }
return $value; 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'); {
$c = ContentReviewCompatability::start(); Versioned::reading_stage("Stage");
$records = SiteTree::get();
// If there's no review dates set, default to all pages due for review now $records = SiteTree::get();
// $records = $records->where('"NextReviewDate" IS NULL OR "OwnerNames" IS NULL OR "OwnerNames" = \'\''); $compatibility = ContentReviewCompatability::start();
// If there's no review dates set, default to all pages due for review now.
// Show virtual pages? // Show virtual pages?
if(empty($params['ShowVirtualPages'])) { if (empty($params["ShowVirtualPages"])) {
$virtualPageClasses = ClassInfo::subclassesFor('VirtualPage'); $virtualPageClasses = ClassInfo::subclassesFor("VirtualPage");
$records = $records->where(sprintf( $records = $records->where(sprintf(
'"SiteTree"."ClassName" NOT IN (\'%s\')', "\"SiteTree\".\"ClassName\" NOT IN ('%s')",
implode("','", array_values($virtualPageClasses)) implode("','", array_values($virtualPageClasses))
)); ));
} }
$records->sort('ParentID'); $records->sort("ParentID");
$records = $records->toArray(); $records = $records->toArray();
// Trim out calculated values // Trim out calculated values
@ -118,21 +121,24 @@ class PagesWithoutReviewScheduleReport extends SS_Report {
} }
} }
ContentReviewCompatability::done($c); ContentReviewCompatability::done($compatibility);
return $list; return $list;
} }
/** /**
*
* @param DataObject $record * @param DataObject $record
* @return boolean *
* @return bool
*/ */
protected function hasReviewSchedule(DataObject $record) { protected function hasReviewSchedule(DataObject $record)
if(!$record->obj('NextReviewDate')->exists()) { {
if (!$record->obj("NextReviewDate")->exists()) {
return false; return false;
} }
$options = $record->getOptions(); $options = $record->getOptions();
if ($options->OwnerGroups()->count() == 0 && $options->OwnerUsers()->count() == 0) { if ($options->OwnerGroups()->count() == 0 && $options->OwnerUsers()->count() == 0) {
return false; return false;
} }

View File

@ -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 * Holds a cached array for looking up members via their ID.
* *
* @var array * @var array
*/ */
protected static $member_cache = array(); protected static $member_cache = array();
/** /**
*
* @param SS_HTTPRequest $request * @param SS_HTTPRequest $request
*/ */
public function run($request) { public function run($request)
$c = ContentReviewCompatability::start(); {
$compatibility = ContentReviewCompatability::start();
$now = class_exists('SS_Datetime') ? SS_Datetime::now()->URLDate() : SSDatetime::now()->URLDate(); $now = class_exists("SS_Datetime") ? SS_Datetime::now()->URLDate() : SSDatetime::now()->URLDate();
// First grab all the pages with a custom setting // First grab all the pages with a custom setting
$pages = Page::get('Page')->where('"SiteTree"."NextReviewDate" <= \''.$now.'\''); $pages = Page::get("Page")->where("\"SiteTree\".\"NextReviewDate\" <= '{$now}'");
$overduePages = $this->getOverduePagesForOwners($pages); $overduePages = $this->getOverduePagesForOwners($pages);
// Lets send one email to one owner with all the pages in there instead of no of pages of emails // 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) { foreach ($overduePages as $memberID => $pages) {
$this->notifyOwner($memberID, $pages); $this->notifyOwner($memberID, $pages);
} }
ContentReviewCompatability::done($c); ContentReviewCompatability::done($compatibility);
} }
/** /**
*
* @param SS_list $pages * @param SS_list $pages
* @param array &$pages *
* @return array * @return array
*/ */
protected function getOverduePagesForOwners(SS_list $pages) { protected function getOverduePagesForOwners(SS_list $pages)
{
$overduePages = array(); $overduePages = array();
foreach ($pages as $page) { foreach ($pages as $page) {
if (!$page->canBeReviewedBy()) { if (!$page->canBeReviewedBy()) {
continue; continue;
} }
$option = $page->getOptions(); $option = $page->getOptions();
foreach ($option->ContentReviewOwners() as $owner) { foreach ($option->ContentReviewOwners() as $owner) {
if (!isset(self::$member_cache[$owner->ID])) { if (!isset(self::$member_cache[$owner->ID])) {
self::$member_cache[$owner->ID] = $owner; self::$member_cache[$owner->ID] = $owner;
} }
if (!isset($overduePages[$owner->ID])) { if (!isset($overduePages[$owner->ID])) {
$overduePages[$owner->ID] = new ArrayList(); $overduePages[$owner->ID] = new ArrayList();
} }
$overduePages[$owner->ID]->push($page); $overduePages[$owner->ID]->push($page);
} }
} }
return $overduePages; return $overduePages;
} }
/** /**
* * @param int $ownerID
* @param int $owner * @param array|SS_List $pages
* @param array $pages
*/ */
protected function notifyOwner($ownerID, SS_List $pages) { protected function notifyOwner($ownerID, SS_List $pages)
{
$owner = self::$member_cache[$ownerID]; $owner = self::$member_cache[$ownerID];
$sender = Security::findAnAdministrator(); $sender = Security::findAnAdministrator();
$senderEmail = ($sender->Email) ? $sender->Email : Config::inst()->get('Email', 'admin_email'); $senderEmail = ($sender->Email) ? $sender->Email : Config::inst()->get("Email", "admin_email");
$subject = _t('ContentReviewEmails.SUBJECT', 'Page(s) are due for content review'); $subject = _t("ContentReviewEmails.SUBJECT", "Page(s) are due for content review");
$email = new Email(); $email = new Email();
$email->setTo($owner->Email); $email->setTo($owner->Email);
$email->setFrom($senderEmail); $email->setFrom($senderEmail);
$email->setTemplate('ContentReviewEmail'); $email->setTemplate("ContentReviewEmail");
$email->setSubject($subject); $email->setSubject($subject);
$email->populateTemplate(array( $email->populateTemplate(array(
"Recipient" => $owner, "Recipient" => $owner,
"Sender" => $sender, "Sender" => $sender,
"Pages" => $pages "Pages" => $pages,
)); ));
$email->send(); $email->send();
} }
} }

View File

@ -1,24 +1,26 @@
<?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.
*/
class ContentReviewOwnerMigrationTask extends BuildTask
{
/**
* @param SS_HTTPRequest $request * @param SS_HTTPRequest $request
*/ */
public function run($request) { public function run($request)
$results = DB::query('SHOW columns from "SiteTree" WHERE "field" = \'OwnerID\''); {
$results = DB::query("SHOW columns from \"SiteTree\" WHERE \"field\" = 'OwnerID'");
if ($results->numRecords() == 0) { if ($results->numRecords() == 0) {
echo "<h1>No need to run task. SiteTree->OwnerID doesn't exist</h1>"; echo "<h1>No need to run task. SiteTree->OwnerID doesn't exist</h1>";
} else { } else {
DB::query('UPDATE "SiteTree" SET "ContentReviewOwnerID" = "OwnerID"'); DB::query("UPDATE \"SiteTree\" SET \"ContentReviewOwnerID\" = \"OwnerID\"");
DB::query('UPDATE "SiteTree_Live" SET "ContentReviewOwnerID" = "OwnerID"'); DB::query("UPDATE \"SiteTree_Live\" SET \"ContentReviewOwnerID\" = \"OwnerID\"");
DB::query('UPDATE "SiteTree_versions" SET "ContentReviewOwnerID" = "OwnerID"'); DB::query("UPDATE \"SiteTree_versions\" SET \"ContentReviewOwnerID\" = \"OwnerID\"");
DB::query('ALTER TABLE "SiteTree" DROP COLUMN "OwnerID"'); DB::query("ALTER TABLE \"SiteTree\" DROP COLUMN \"OwnerID\"");
DB::query('ALTER TABLE "SiteTree_Live" DROP COLUMN "OwnerID"'); DB::query("ALTER TABLE \"SiteTree_Live\" DROP COLUMN \"OwnerID\"");
DB::query('ALTER TABLE "SiteTree_versions" DROP COLUMN "OwnerID"'); DB::query("ALTER TABLE \"SiteTree_versions\" DROP COLUMN \"OwnerID\"");
echo "<h1>Migrated 3 tables. Dropped obsolete OwnerID column</h1>"; echo "<h1>Migrated 3 tables. Dropped obsolete OwnerID column</h1>";
} }
} }

View File

@ -1,15 +1,20 @@
<?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
{
/**
* @var bool
*/ */
abstract class ContentReviewBaseTest extends FunctionalTest {
protected $translatableEnabledBefore; protected $translatableEnabledBefore;
public function setUp(){ public function setUp()
{
parent::setUp(); parent::setUp();
/* /*
* We set the locale for pages explicitly, because if we don't, then we get into a situation * 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 * where the page takes on the tester's (your) locale, and any calls to simulate subsequent requests
@ -20,17 +25,18 @@ abstract class ContentReviewBaseTest extends FunctionalTest {
* If creating pages in your unit tests (rather than reading from the fixtures file), you must explicitly call * 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. * self::compat() on the page, for the same reasons as above.
*/ */
if(class_exists('Translatable')){ if (class_exists("Translatable")) {
fwrite(STDOUT, 'TRANSLATABLE DISABLED FFS'); $this->translatableEnabledBefore = SiteTree::has_extension("Translatable");
$this->translatableEnabledBefore = Translatable::is_enabled(); SiteTree::remove_extension("Translatable");
Translatable::disable();
} }
} }
public function tearDown(){ public function tearDown()
if(class_exists('Translatable')){ {
if($this->translatableEnabledBefore) Translatable::enable(); if (class_exists("Translatable")) {
if ($this->translatableEnabledBefore) {
SiteTree::add_extension("Translatable");
}
} }
} }
} }

View File

@ -1,9 +1,18 @@
<?php <?php
class ContentReviewCMSPageEditControllerTest extends ContentReviewBaseTest { /**
* @mixin PHPUnit_Framework_TestCase
public static $fixture_file = 'contentreview/tests/ContentReviewTest.yml'; */
class ContentReviewCMSPageEditControllerTest extends ContentReviewBaseTest
{
/**
* @var string
*/
public static $fixture_file = "contentreview/tests/ContentReviewTest.yml";
/**
* @var array
*/
protected $requiredExtensions = array( protected $requiredExtensions = array(
"SiteTree" => array("SiteTreeContentReview"), "SiteTree" => array("SiteTreeContentReview"),
"Group" => array("ContentReviewOwner"), "Group" => array("ContentReviewOwner"),
@ -12,56 +21,81 @@ class ContentReviewCMSPageEditControllerTest extends ContentReviewBaseTest {
"SiteConfig" => array("ContentReviewDefaultSettings"), "SiteConfig" => array("ContentReviewDefaultSettings"),
); );
public function testReviewedThrowsExceptionWithNoRecordID() { public function testReviewedThrowsExceptionWithNoRecordID()
$this->setExpectedException('SS_HTTPResponse_Exception', 'No record ID', 404); {
$this->setExpectedException("SS_HTTPResponse_Exception");
/** @var CMSPageEditController|ContentReviewCMSExtension $controller */
$controller = new CMSPageEditController(); $controller = new CMSPageEditController();
$dummyForm = new CMSForm($controller, 'EditForm', new FieldList(), new FieldList());
$controller->reviewed(array('ID'=>null, 'Message' => null), $dummyForm); $dummyForm = new CMSForm($controller, "EditForm", new FieldList(), new FieldList());
$controller->reviewed(array(
"ID" => null,
"Message" => null,
), $dummyForm);
} }
public function testReviewedThrowsExceptionWithWrongRecordID() { public function testReviewedThrowsExceptionWithWrongRecordID()
$this->setExpectedException('SS_HTTPResponse_Exception'); {
$this->setExpectedException("SS_HTTPResponse_Exception");
/** @var CMSPageEditController|ContentReviewCMSExtension $controller */
$controller = new CMSPageEditController(); $controller = new CMSPageEditController();
$dummyForm = new CMSForm($controller, 'EditForm', new FieldList(), new FieldList());
$controller->reviewed(array('ID'=>'FAIL', 'Message' => null), $dummyForm); $dummyForm = new CMSForm($controller, "EditForm", new FieldList(), new FieldList());
$controller->reviewed(array(
"ID" => "FAIL",
"Message" => null,
), $dummyForm);
} }
public function testReviewedWithAuthor() { public function testReviewedWithAuthor()
$author = $this->objFromFixture('Member', 'author'); {
/** @var Member $author */
$author = $this->objFromFixture("Member", "author");
$this->loginAs($author); $this->loginAs($author);
$page = $this->objFromFixture('Page', 'home');
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "home");
$data = array( $data = array(
'action_reviewed' => 1, "action_reviewed" => 1,
'ID' => $page->ID "ID" => $page->ID,
); );
$response = $this->post('admin/pages/edit/EditForm', $data); $response = $this->post("admin/pages/edit/EditForm", $data);
$this->assertEquals('OK', $response->getStatusDescription());
$this->assertEquals("OK", $response->getStatusDescription());
$this->assertEquals(200, $response->getStatusCode()); $this->assertEquals(200, $response->getStatusCode());
} }
public function testSaveReview() { public function testSaveReview()
$author = $this->objFromFixture('Member', 'author'); {
/** @var Member $author */
$author = $this->objFromFixture("Member", "author");
$this->loginAs($author); $this->loginAs($author);
$page = $this->objFromFixture('Page', 'home');
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "home");
$data = array( $data = array(
'action_save_review' => 1, "action_save_review" => 1,
'ID' => $page->ID, "ID" => $page->ID,
'ReviewNotes' => 'This is the best page ever' "ReviewNotes" => "This is the best page ever",
); );
$response = $this->post('admin/pages/edit/EditForm', $data); $response = $this->post("admin/pages/edit/EditForm", $data);
$this->assertEquals('OK', $response->getStatusDescription()); $this->assertEquals("OK", $response->getStatusDescription());
$this->assertEquals(200, $response->getStatusCode()); $this->assertEquals(200, $response->getStatusCode());
$this->assertEquals(1, $page->ReviewLogs()->count()); $this->assertEquals(1, $page->ReviewLogs()->count());
$reviewLog = $page->ReviewLogs()->first(); $reviewLog = $page->ReviewLogs()->first();
$this->assertEquals($data['ReviewNotes'], $reviewLog->Note); $this->assertEquals($data["ReviewNotes"], $reviewLog->Note);
} }
} }

View File

@ -1,9 +1,18 @@
<?php <?php
class ContentReviewNotificationTest extends SapphireTest { /**
* @mixin PHPUnit_Framework_TestCase
public static $fixture_file = 'contentreview/tests/ContentReviewTest.yml'; */
class ContentReviewNotificationTest extends SapphireTest
{
/**
* @var string
*/
public static $fixture_file = "contentreview/tests/ContentReviewTest.yml";
/**
* @var array
*/
protected $requiredExtensions = array( protected $requiredExtensions = array(
"SiteTree" => array("SiteTreeContentReview"), "SiteTree" => array("SiteTreeContentReview"),
"Group" => array("ContentReviewOwner"), "Group" => array("ContentReviewOwner"),
@ -12,26 +21,26 @@ class ContentReviewNotificationTest extends SapphireTest {
"SiteConfig" => array("ContentReviewDefaultSettings"), "SiteConfig" => array("ContentReviewDefaultSettings"),
); );
public function testContentReviewEmails() { public function testContentReviewEmails()
SS_Datetime::set_mock_now('2010-02-24 12:00:00'); {
SS_Datetime::set_mock_now("2010-02-24 12:00:00");
// This propagates the next review date to 'contact-child' page from the parent page /** @var Page|SiteTreeContentReview $childParentPage */
$childParentPage = $this->objFromFixture('Page', 'contact'); $childParentPage = $this->objFromFixture("Page", "contact");
$childParentPage->NextReviewDate = '2010-02-23'; $childParentPage->NextReviewDate = "2010-02-23";
$childParentPage->write(); $childParentPage->write();
$task = new ContentReviewEmails(); $task = new ContentReviewEmails();
$task->run(new SS_HTTPRequest('GET', '/dev/tasks/ContentReviewEmails')); $task->run(new SS_HTTPRequest("GET", "/dev/tasks/ContentReviewEmails"));
$expectedSubject = _t('ContentReviewEmails.SUBJECT', 'Page(s) are due for content review'); $expectedSubject = _t("ContentReviewEmails.SUBJECT", "Page(s) are due for content review");
$email = $this->findEmail('author@example.com', null, $expectedSubject); $email = $this->findEmail("author@example.com", null, $expectedSubject);
$this->assertNotNull($email, 'Email haven\'t been sent.'); $this->assertNotNull($email, "Email haven't been sent.");
$this->assertContains("There are 3 pages that are due for review today by you.", $email["htmlContent"]);
$this->assertContains('There are 3 pages that are due for review today by you.', $email['htmlContent']); $this->assertContains("Staff", $email["htmlContent"]);
$this->assertContains('Staff', $email['htmlContent']); $this->assertContains("Contact Us", $email["htmlContent"]);
$this->assertContains('Contact Us', $email['htmlContent']); $this->assertContains("Contact Us Child", $email["htmlContent"]);
$this->assertContains('Contact Us Child', $email['htmlContent']);
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
} }

View File

@ -1,9 +1,15 @@
<?php <?php
class ContentReviewReportTest extends FunctionalTest { class ContentReviewReportTest extends FunctionalTest
{
public static $fixture_file = 'contentreview/tests/ContentReviewTest.yml'; /**
* @var string
*/
public static $fixture_file = "contentreview/tests/ContentReviewTest.yml";
/**
* @var array
*/
protected $requiredExtensions = array( protected $requiredExtensions = array(
"SiteTree" => array("SiteTreeContentReview"), "SiteTree" => array("SiteTreeContentReview"),
"Group" => array("ContentReviewOwner"), "Group" => array("ContentReviewOwner"),
@ -12,9 +18,13 @@ class ContentReviewReportTest extends FunctionalTest {
"SiteConfig" => array("ContentReviewDefaultSettings"), "SiteConfig" => array("ContentReviewDefaultSettings"),
); );
public function testPagesDueForReviewReport() { public function testPagesDueForReviewReport()
$editor = $this->objFromFixture('Member', 'editor'); {
/** @var Member $editor */
$editor = $this->objFromFixture("Member", "editor");
$this->logInAs($editor); $this->logInAs($editor);
$report = new PagesDueForReviewReport(); $report = new PagesDueForReviewReport();
$report->parameterFields(); $report->parameterFields();
@ -22,31 +32,37 @@ class ContentReviewReportTest extends FunctionalTest {
$report->title(); $report->title();
$results = $report->sourceRecords(array( $results = $report->sourceRecords(array(
'ReviewDateAfter' => '01/01/2010', "ReviewDateAfter" => "01/01/2010",
'ReviewDateBefore' => '12/12/2010' "ReviewDateBefore" => "12/12/2010",
)); ));
$this->assertEquals(array( $this->assertEquals(array(
'Contact Us', "Contact Us",
'Contact Us Child', "Contact Us Child",
'Staff', "Staff",
'About Us', "About Us",
'Home' "Home",
), $results->column('Title')); ), $results->column("Title"));
SS_Datetime::set_mock_now("2010-02-13 00:00:00");
SS_Datetime::set_mock_now('2010-02-13 00:00:00');
$results = $report->sourceRecords(array()); $results = $report->sourceRecords(array());
$this->assertEquals(array( $this->assertEquals(array(
'About Us', "About Us",
'Home' "Home",
), $results->column('Title')); ), $results->column("Title"));
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
} }
public function testPagesWithoutReviewScheduleReport() { public function testPagesWithoutReviewScheduleReport()
$editor = $this->objFromFixture('Member', 'editor'); {
/** @var Member $editor */
$editor = $this->objFromFixture("Member", "editor");
$this->logInAs($editor); $this->logInAs($editor);
$report = new PagesWithoutReviewScheduleReport(); $report = new PagesWithoutReviewScheduleReport();
$report->parameterFields(); $report->parameterFields();
@ -56,12 +72,10 @@ class ContentReviewReportTest extends FunctionalTest {
$results = $report->sourceRecords(); $results = $report->sourceRecords();
$this->assertEquals(array( $this->assertEquals(array(
'Home', "Home",
'About Us', "About Us",
'Page without review date', "Page without review date",
'Page owned by group', "Page owned by group",
), $results->column('Title')); ), $results->column("Title"));
} }
} }

View File

@ -1,12 +1,21 @@
<?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
{
public static $fixture_file = 'contentreview/tests/ContentReviewSettingsTest.yml'; /**
* @var string
*/
public static $fixture_file = "contentreview/tests/ContentReviewSettingsTest.yml";
/**
* @var array
*/
protected $requiredExtensions = array( protected $requiredExtensions = array(
"SiteTree" => array("SiteTreeContentReview"), "SiteTree" => array("SiteTreeContentReview"),
"Group" => array("ContentReviewOwner"), "Group" => array("ContentReviewOwner"),
@ -15,154 +24,232 @@ class ContentReviewSettingsTest extends SapphireTest {
"SiteConfig" => array("ContentReviewDefaultSettings"), "SiteConfig" => array("ContentReviewDefaultSettings"),
); );
public function testAdvanceReviewDate10Days() { public function testAdvanceReviewDate10Days()
{
/** @var Page|SiteTreeContentReview $page */
$page = new Page(); $page = new Page();
$page->ContentReviewType = 'Custom';
$page->ContentReviewType = "Custom";
$page->ReviewPeriodDays = 10; $page->ReviewPeriodDays = 10;
$this->assertTrue($page->advanceReviewDate()); $this->assertTrue($page->advanceReviewDate());
$page->write(); $page->write();
$this->assertEquals(date('Y-m-d', strtotime('now + 10 days')), $page->NextReviewDate);
$this->assertEquals(date("Y-m-d", strtotime("now + 10 days")), $page->NextReviewDate);
} }
public function testAdvanceReviewDateNull() { public function testAdvanceReviewDateNull()
{
/** @var Page|SiteTreeContentReview $page */
$page = new Page(); $page = new Page();
$page->ContentReviewType = 'Custom';
$page->ContentReviewType = "Custom";
$page->ReviewPeriodDays = 0; $page->ReviewPeriodDays = 0;
$this->assertFalse($page->advanceReviewDate()); $this->assertFalse($page->advanceReviewDate());
$page->write(); $page->write();
$this->assertEquals(null, $page->NextReviewDate); $this->assertEquals(null, $page->NextReviewDate);
} }
public function testAdvanceReviewFromCustomSettings() { public function testAdvanceReviewFromCustomSettings()
$page = $this->objFromFixture('Page', 'custom'); {
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "custom");
$this->assertTrue($page->advanceReviewDate()); $this->assertTrue($page->advanceReviewDate());
$page->write(); $page->write();
$this->assertEquals(date('Y-m-d', strtotime('now + '.$page->ReviewPeriodDays.' days')), $page->NextReviewDate);
$this->assertEquals(date("Y-m-d", strtotime("now + " . $page->ReviewPeriodDays . " days")), $page->NextReviewDate);
} }
public function testAdvanceReviewFromInheritedSettings() { public function testAdvanceReviewFromInheritedSettings()
$page = $this->objFromFixture('Page', 'page-1-1'); {
$parentPage = $this->objFromFixture('Page', 'page-1'); /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "page-1-1");
/** @var Page|SiteTreeContentReview $parentPage */
$parentPage = $this->objFromFixture("Page", "page-1");
$this->assertTrue($page->advanceReviewDate()); $this->assertTrue($page->advanceReviewDate());
$page->write(); $page->write();
$this->assertEquals(date('Y-m-d', strtotime('now + '.$parentPage->ReviewPeriodDays.' days')), $page->NextReviewDate);
$this->assertEquals(date("Y-m-d", strtotime("now + " . $parentPage->ReviewPeriodDays . " days")), $page->NextReviewDate);
} }
public function testAdvanceReviewFromInheritedSiteConfigSettings() { public function testAdvanceReviewFromInheritedSiteConfigSettings()
$page = $this->objFromFixture('Page', 'inherit'); {
$siteConfig = $this->objFromFixture('SiteConfig', 'default'); /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "inherit");
/** @var SiteConfig|ContentReviewDefaultSettings $siteConfig */
$siteConfig = $this->objFromFixture("SiteConfig", "default");
$this->assertTrue($page->advanceReviewDate()); $this->assertTrue($page->advanceReviewDate());
$page->write(); $page->write();
$this->assertEquals(date('Y-m-d', strtotime('now + '.$siteConfig->ReviewPeriodDays.' days')), $page->NextReviewDate);
$this->assertEquals(date("Y-m-d", strtotime("now + " . $siteConfig->ReviewPeriodDays . " days")), $page->NextReviewDate);
} }
public function testGetSettingsObjectFromCustom() { public function testGetSettingsObjectFromCustom()
$page = $this->objFromFixture('Page', 'custom'); {
$this->assertEquals('Custom', $page->ContentReviewType); /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "custom");
$this->assertEquals("Custom", $page->ContentReviewType);
$this->assertEquals($page, $page->getOptions()); $this->assertEquals($page, $page->getOptions());
} }
public function testGetSettingsObjectFromDisabled() { public function testGetSettingsObjectFromDisabled()
$page = $this->objFromFixture('Page', 'disabled'); {
$this->assertEquals('Disabled', $page->ContentReviewType); /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "disabled");
$this->assertEquals("Disabled", $page->ContentReviewType);
$this->assertFalse($page->getOptions()); $this->assertFalse($page->getOptions());
} }
public function testGetOptionObjectFromInheritedDisabled() { public function testGetOptionObjectFromInheritedDisabled()
$page = $this->objFromFixture('Page', 'page-2-1-1'); {
$this->assertEquals('Inherit', $page->ContentReviewType); /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "page-2-1-1");
$this->assertEquals("Inherit", $page->ContentReviewType);
$this->assertFalse($page->getOptions()); $this->assertFalse($page->getOptions());
} }
public function testGetOptionObjectFromDeeplyInheritedPage() { public function testGetOptionObjectFromDeeplyInheritedPage()
$page = $this->objFromFixture('Page', 'page-3-1-1-1'); {
$this->assertEquals('Inherit', $page->ContentReviewType); /** @var Page|SiteTreeContentReview $page */
$this->assertInstanceOf('SiteConfig', $page->getOptions()); $page = $this->objFromFixture("Page", "page-3-1-1-1");
$this->assertEquals("Inherit", $page->ContentReviewType);
$this->assertInstanceOf("SiteConfig", $page->getOptions());
} }
public function testGetSettingsObjectFromInheritPage() { public function testGetSettingsObjectFromInheritPage()
$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", "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(get_class($parentPage), get_class($page->getOptions()));
$this->assertEquals($parentPage->ID, $page->getOptions()->ID); $this->assertEquals($parentPage->ID, $page->getOptions()->ID);
} }
public function testGetSettingsObjectFromInheritedRootPage() { public function testGetSettingsObjectFromInheritedRootPage()
$page = $this->objFromFixture('Page', 'inherit'); {
$this->assertEquals('Inherit', $page->ContentReviewType); /** @var Page|SiteTreeContentReview $page */
$this->assertEquals($this->objFromFixture('SiteConfig', 'default'), $page->getOptions()); $page = $this->objFromFixture("Page", "inherit");
$this->assertEquals("Inherit", $page->ContentReviewType);
$this->assertEquals($this->objFromFixture("SiteConfig", "default"), $page->getOptions());
} }
public function testGetNextReviewDateFromCustomSettings() { public function testGetNextReviewDateFromCustomSettings()
{
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture('Page', 'custom'); $page = $this->objFromFixture('Page', 'custom');
$date = $page->getReviewDate(); $date = $page->getReviewDate();
$this->assertEquals('2010-02-01', $date->format('Y-m-d')); $this->assertEquals('2010-02-01', $date->format('Y-m-d'));
} }
public function testGetNextReviewDateFromSiteConfigInheritedSetting() { public function testGetNextReviewDateFromSiteConfigInheritedSetting()
$page = $this->objFromFixture('Page', 'inherit'); {
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "inherit");
$nextReviewDate = $page->getReviewDate(); $nextReviewDate = $page->getReviewDate();
$this->assertInstanceOf('Date', $nextReviewDate); $this->assertInstanceOf("Date", $nextReviewDate);
$expected = $this->addDaysToDate(SS_Datetime::now(), $this->objFromFixture('SiteConfig', 'default')->ReviewPeriodDays);
$this->assertEquals($expected , $nextReviewDate->format('Y-m-d')); /** @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() { public function testGetNextReviewDateFromPageInheritedSetting()
$page = $this->objFromFixture('Page', 'page-1-1'); {
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "page-1-1");
$nextReviewDate = $page->getReviewDate(); $nextReviewDate = $page->getReviewDate();
$this->assertInstanceOf('Date', $nextReviewDate); $this->assertInstanceOf("Date", $nextReviewDate);
// It should be the same as the parents reviewdate
$expected = $this->objFromFixture('Page', 'page-1')->NextReviewDate; /** @var Page|SiteTreeContentReview $nextPage */
$this->assertEquals($expected, $nextReviewDate->format('Y-m-d')); $nextPage = $this->objFromFixture("Page", "page-1");
$expected = $nextPage->NextReviewDate;
$this->assertEquals($expected, $nextReviewDate->format("Y-m-d"));
} }
public function testUpdateNextReviewDateFromCustomToDisabled() { public function testUpdateNextReviewDateFromCustomToDisabled()
$page = $this->objFromFixture('Page', 'custom'); {
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "custom");
// before write() // before write()
$this->assertEquals('2010-02-01', $page->NextReviewDate); $this->assertEquals("2010-02-01", $page->NextReviewDate);
// Change and write $page->ContentReviewType = "Disabled";
$page->ContentReviewType = 'Disabled';
$page->write(); $page->write();
// clear cache
DataObject::flush_and_destroy_cache(); DataObject::flush_and_destroy_cache();
unset($page); unset($page);
// After write() /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture('Page', 'custom'); $page = $this->objFromFixture("Page", "custom");
$this->assertNull($page->NextReviewDate); $this->assertNull($page->NextReviewDate);
} }
public function testUpdateNextReviewDateFromDisabledToCustom() { public function testUpdateNextReviewDateFromDisabledToCustom()
$page = $this->objFromFixture('Page', 'disabled'); {
// before /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "disabled");
$this->assertNull($page->NextReviewDate); $this->assertNull($page->NextReviewDate);
// Change and write $page->ContentReviewType = "Custom";
$page->ContentReviewType = 'Custom'; $page->ReviewPeriodDays = "7";
$page->ReviewPeriodDays = '7';
$page->write(); $page->write();
// clear cache
DataObject::flush_and_destroy_cache(); DataObject::flush_and_destroy_cache();
unset($page); unset($page);
// After write() /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture('Page', 'disabled'); $page = $this->objFromFixture("Page", "disabled");
$expected = date('Y-m-d', strtotime('+ '.$page->ReviewPeriodDays.' days'));
$expected = date("Y-m-d", strtotime("+ " . $page->ReviewPeriodDays . " days"));
$this->assertEquals($expected, $page->NextReviewDate); $this->assertEquals($expected, $page->NextReviewDate);
} }
public function testParentChangedOptionsAndChildShouldToo() { public function testParentChangedOptionsAndChildShouldToo()
$parentPage = $this->objFromFixture('Page', 'page-1'); {
$childPage = $this->objFromFixture('Page', 'page-1-1'); /** @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 // BEFORE: parent page have a period of five days, so childPage should have a
// review date LastEdited + 5 days // review date LastEdited + 5 days
$expected = $this->addDaysToDate($childPage->obj('LastEdited'), $parentPage->ReviewPeriodDays);
$this->assertEquals($parentPage->NextReviewDate, $childPage->NextReviewDate); $this->assertEquals($parentPage->NextReviewDate, $childPage->NextReviewDate);
$oldChildDate = $childPage->NextReviewDate; $oldChildDate = $childPage->NextReviewDate;
@ -174,23 +261,34 @@ class ContentReviewSettingsTest extends SapphireTest {
// Flush all the caches! // Flush all the caches!
DataObject::flush_and_destroy_cache(); DataObject::flush_and_destroy_cache();
$parentPage = $this->objFromFixture('Page', 'page-1'); /** @var Page|SiteTreeContentReview $page */
$childPage = $this->objFromFixture('Page', 'page-1-1'); $parentPage = $this->objFromFixture("Page", "page-1");
// AFTER: parent page have a period of 10 days, so childPage should have a /** @var Page|SiteTreeContentReview $page */
// review date now + 10 days $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->assertNotEquals($oldChildDate, $childPage->NextReviewDate);
$this->assertEquals($this->addDaysToDate(date('Y-m-d'), 10), $childPage->NextReviewDate); $this->assertEquals($this->addDaysToDate(date("Y-m-d"), 10), $childPage->NextReviewDate);
$this->assertEquals($parentPage->NextReviewDate, $childPage->NextReviewDate); $this->assertEquals($parentPage->NextReviewDate, $childPage->NextReviewDate);
} }
// helper method for this test class /**
private function addDaysToDate($date, $days, $format='Y-m-d') { * @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)) { if (is_object($date)) {
$sec = strtotime('+ '. $days .' days', $date->format('U')); $sec = strtotime("+ " . $days . " days", $date->format("U"));
} else { } else {
$sec = strtotime('+ '. $days .' days', strtotime($date)); $sec = strtotime("+ " . $days . " days", strtotime($date));
} }
return date($format, $sec); return date($format, $sec);
} }
} }

View File

@ -1,9 +1,18 @@
<?php <?php
class SiteTreeContentReviewTest extends ContentReviewBaseTest { /**
* @mixin PHPUnit_Framework_TestCase
public static $fixture_file = 'contentreview/tests/ContentReviewTest.yml'; */
class SiteTreeContentReviewTest extends ContentReviewBaseTest
{
/**
* @var string
*/
public static $fixture_file = "contentreview/tests/ContentReviewTest.yml";
/**
* @var array
*/
protected $requiredExtensions = array( protected $requiredExtensions = array(
"SiteTree" => array("SiteTreeContentReview"), "SiteTree" => array("SiteTreeContentReview"),
"Group" => array("ContentReviewOwner"), "Group" => array("ContentReviewOwner"),
@ -12,166 +21,264 @@ class SiteTreeContentReviewTest extends ContentReviewBaseTest {
"SiteConfig" => array("ContentReviewDefaultSettings"), "SiteConfig" => array("ContentReviewDefaultSettings"),
); );
public function testOwnerNames() { public function testOwnerNames()
$editor = $this->objFromFixture('Member', 'editor'); {
/** @var Member $editor */
$editor = $this->objFromFixture("Member", "editor");
$this->logInAs($editor); $this->logInAs($editor);
/** @var Page|SiteTreeContentReview $page */
$page = new Page(); $page = new Page();
$page->ReviewPeriodDays = 10; $page->ReviewPeriodDays = 10;
$page->ContentReviewType ='Custom'; $page->ContentReviewType = "Custom";
$page->ContentReviewUsers()->push($editor); $page->ContentReviewUsers()->push($editor);
$page->write(); $page->write();
$this->assertTrue($page->canPublish()); $this->assertTrue($page->canPublish());
$this->assertTrue($page->doPublish()); $this->assertTrue($page->doPublish());
$this->assertEquals($page->OwnerNames, "Test Editor", 'Test Editor should be the owner'); $this->assertEquals($page->OwnerNames, "Test Editor", "Test Editor should be the owner");
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "about");
$page = $this->objFromFixture('Page', 'about');
$page->OwnerUsers()->removeAll(); $page->OwnerUsers()->removeAll();
$page->write(); $page->write();
$this->assertTrue($page->canPublish()); $this->assertTrue($page->canPublish());
$this->assertTrue($page->doPublish()); $this->assertTrue($page->doPublish());
$this->assertEquals('', $page->OwnerNames); $this->assertEquals("", $page->OwnerNames);
} }
public function testPermissionsExists() { public function testPermissionsExists()
$perms = singleton('SiteTreeContentReview')->providePermissions(); {
$this->assertTrue(isset($perms['EDIT_CONTENT_REVIEW_FIELDS'])); $perms = singleton("SiteTreeContentReview")->providePermissions();
$this->assertTrue(isset($perms["EDIT_CONTENT_REVIEW_FIELDS"]));
} }
public function testUserWithPermissionCanEdit() { public function testUserWithPermissionCanEdit()
$editor = $this->objFromFixture('Member', 'editor'); {
/** @var Member $editor */
$editor = $this->objFromFixture("Member", "editor");
$this->logInAs($editor); $this->logInAs($editor);
/** @var Page|SiteTreeContentReview $page */
$page = new Page(); $page = new Page();
$fields = $page->getSettingsFields(); $fields = $page->getSettingsFields();
$this->assertNotNull($fields->dataFieldByName('NextReviewDate'));
$this->assertNotNull($fields->dataFieldByName("NextReviewDate"));
} }
public function testUserWithoutPermissionCannotEdit() { public function testUserWithoutPermissionCannotEdit()
$author = $this->objFromFixture('Member', 'author'); {
/** @var Member $author */
$author = $this->objFromFixture("Member", "author");
$this->logInAs($author); $this->logInAs($author);
/** @var Page|SiteTreeContentReview $page */
$page = new Page(); $page = new Page();
$fields = $page->getSettingsFields(); $fields = $page->getSettingsFields();
$this->assertNull($fields->dataFieldByName('NextReviewDate'));
$this->assertNull($fields->dataFieldByName("NextReviewDate"));
} }
public function testAutomaticallyToNotSetReviewDate() { public function testAutomaticallyToNotSetReviewDate()
$editor = $this->objFromFixture('Member', 'editor'); {
/** @var Member $editor */
$editor = $this->objFromFixture("Member", "editor");
$this->logInAs($editor); $this->logInAs($editor);
/** @var Page|SiteTreeContentReview $page */
$page = new Page(); $page = new Page();
$page->ReviewPeriodDays = 10; $page->ReviewPeriodDays = 10;
$page->write(); $page->write();
$this->assertTrue($page->doPublish()); $this->assertTrue($page->doPublish());
$this->assertEquals(null, $page->NextReviewDate); $this->assertEquals(null, $page->NextReviewDate);
} }
public function testAddReviewNote() { public function testAddReviewNote()
$author = $this->objFromFixture('Member', 'author'); {
$page = $this->objFromFixture('Page', 'home'); /** @var Member $author */
$page->addReviewNote($author, 'This is a message'); $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");
// Get the page again to make sure it's not only cached in memory
$homepage = $this->objFromFixture('Page', 'home');
$this->assertEquals(1, $homepage->ReviewLogs()->count()); $this->assertEquals(1, $homepage->ReviewLogs()->count());
$this->assertEquals('This is a message', $homepage->ReviewLogs()->first()->Note); $this->assertEquals("This is a message", $homepage->ReviewLogs()->first()->Note);
} }
public function testGetContentReviewOwners() { public function testGetContentReviewOwners()
$page = $this->objFromFixture('Page', 'group-owned'); {
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "group-owned");
$owners = $page->ContentReviewOwners(); $owners = $page->ContentReviewOwners();
$this->assertEquals(1, $owners->count()); $this->assertEquals(1, $owners->count());
$this->assertEquals('author@example.com', $owners->first()->Email); $this->assertEquals("author@example.com", $owners->first()->Email);
} }
public function testCanNotBeReviewBecauseNoReviewDate() { public function testCanNotBeReviewBecauseNoReviewDate()
SS_Datetime::set_mock_now('2010-01-01 12:00:00'); {
$author = $this->objFromFixture('Member', 'author'); SS_Datetime::set_mock_now("2010-01-01 12:00:00");
$page = $this->objFromFixture('Page', 'no-review');
// page 'no-review' is owned by author, but there is no review date /** @var Member $author */
$author = $this->objFromFixture("Member", "author");
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "no-review");
$this->assertFalse($page->canBeReviewedBy($author)); $this->assertFalse($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
} }
public function testCanNotBeReviewedBecauseInFuture() { public function testCanNotBeReviewedBecauseInFuture()
SS_Datetime::set_mock_now('2010-01-01 12:00:00'); {
$author = $this->objFromFixture('Member', 'author'); SS_Datetime::set_mock_now("2010-01-01 12:00:00");
$page = $this->objFromFixture('Page', 'staff');
// page 'staff' is owned by author, but the review date is in the future /** @var Member $author */
$author = $this->objFromFixture("Member", "author");
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "staff");
$this->assertFalse($page->canBeReviewedBy($author)); $this->assertFalse($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
} }
public function testCanNotBeReviewedByUser() { public function testCanNotBeReviewedByUser()
SS_Datetime::set_mock_now('2010-03-01 12:00:00'); {
$author = $this->objFromFixture('Member', 'author'); SS_Datetime::set_mock_now("2010-03-01 12:00:00");
$page = $this->objFromFixture('Page', 'home');
// page 'home' doesnt have any owners /** @var Member $author */
$author = $this->objFromFixture("Member", "author");
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "home");
$this->assertFalse($page->canBeReviewedBy($author)); $this->assertFalse($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
} }
public function testCanBeReviewedByUser() { public function testCanBeReviewedByUser()
SS_Datetime::set_mock_now('2010-03-01 12:00:00'); {
$author = $this->objFromFixture('Member', 'author'); SS_Datetime::set_mock_now("2010-03-01 12:00:00");
$page = $this->objFromFixture('Page', 'staff');
// page 'staff' is owned by author /** @var Member $author */
$author = $this->objFromFixture("Member", "author");
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "staff");
$this->assertTrue($page->canBeReviewedBy($author)); $this->assertTrue($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
} }
public function testCanNotBeReviewedByGroup() { public function testCanNotBeReviewedByGroup()
SS_Datetime::set_mock_now('2010-03-01 12:00:00'); {
$author = $this->objFromFixture('Member', 'editor'); SS_Datetime::set_mock_now("2010-03-01 12:00:00");
$page = $this->objFromFixture('Page', 'contact');
// page 'contact' is owned by the authorgroup /** @var Member $author */
$author = $this->objFromFixture("Member", "editor");
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "contact");
$this->assertFalse($page->canBeReviewedBy($author)); $this->assertFalse($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
} }
public function testCanBeReviewedByGroup() { public function testCanBeReviewedByGroup()
SS_Datetime::set_mock_now('2010-03-01 12:00:00'); {
$author = $this->objFromFixture('Member', 'author'); SS_Datetime::set_mock_now("2010-03-01 12:00:00");
$page = $this->objFromFixture('Page', 'contact');
// page 'contact' is owned by the authorgroup /** @var Member $author */
$author = $this->objFromFixture("Member", "author");
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "contact");
$this->assertTrue($page->canBeReviewedBy($author)); $this->assertTrue($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
} }
public function testCanBeReviewedFromInheritedSetting() { public function testCanBeReviewedFromInheritedSetting()
SS_Datetime::set_mock_now('2013-03-01 12:00:00'); {
$author = $this->objFromFixture('Member', 'author'); SS_Datetime::set_mock_now("2013-03-01 12:00:00");
$parentPage = $this->objFromFixture('Page', 'contact');
// This saves the parentPages.NextReview date to the child page /** @var Member $author */
$parentPage->NextReviewDate = '2013-01-01'; $author = $this->objFromFixture("Member", "author");
/** @var Page|SiteTreeContentReview $parentPage */
$parentPage = $this->objFromFixture("Page", "contact");
$parentPage->NextReviewDate = "2013-01-01";
$parentPage->write(); $parentPage->write();
$page = $this->objFromFixture('Page', 'contact-child'); /** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "contact-child");
$this->assertTrue($page->canBeReviewedBy($author)); $this->assertTrue($page->canBeReviewedBy($author));
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
} }
public function testReviewActionVisibleForAuthor() { public function testReviewActionVisibleForAuthor()
SS_Datetime::set_mock_now('2020-03-01 12:00:00'); {
$page = $this->objFromFixture('Page', 'contact'); SS_Datetime::set_mock_now("2020-03-01 12:00:00");
$author = $this->objFromFixture('Member', 'author');
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "contact");
/** @var Member $author */
$author = $this->objFromFixture("Member", "author");
$this->logInAs($author); $this->logInAs($author);
$fields = $page->getCMSActions(); $fields = $page->getCMSActions();
$this->assertNotNull($fields->fieldByName('action_reviewed'));
$this->assertNotNull($fields->fieldByName("action_reviewed"));
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
} }
public function testReviewActionNotVisibleForEditor() { public function testReviewActionNotVisibleForEditor()
SS_Datetime::set_mock_now('2020-03-01 12:00:00'); {
$page = $this->objFromFixture('Page', 'contact'); SS_Datetime::set_mock_now("2020-03-01 12:00:00");
$author = $this->objFromFixture('Member', 'editor');
/** @var Page|SiteTreeContentReview $page */
$page = $this->objFromFixture("Page", "contact");
/** @var Member $author */
$author = $this->objFromFixture("Member", "editor");
$this->logInAs($author); $this->logInAs($author);
$fields = $page->getCMSActions(); $fields = $page->getCMSActions();
$this->assertNull($fields->fieldByName('action_reviewed'));
$this->assertNull($fields->fieldByName("action_reviewed"));
SS_Datetime::clear_mock_now(); SS_Datetime::clear_mock_now();
} }
} }