diff --git a/_config/config.yml b/_config/config.yml
index b901cde..93a3716 100644
--- a/_config/config.yml
+++ b/_config/config.yml
@@ -6,4 +6,7 @@ Group:
- ContentReviewOwner
Member:
extensions:
- - ContentReviewOwner
\ No newline at end of file
+ - ContentReviewOwner
+CMSPageEditController:
+ extensions:
+ - ContentReviewCMSPageEditController
\ No newline at end of file
diff --git a/code/ContentReviewEmails.php b/code/ContentReviewEmails.php
index 90fe9c6..0833314 100644
--- a/code/ContentReviewEmails.php
+++ b/code/ContentReviewEmails.php
@@ -52,6 +52,14 @@ class ContentReviewEmails extends BuildTask {
"LiveSiteLink" => Controller::join_links($page->Link(), "?stage=Live"),
));
$email->send();
+
+ $message = ''._t('ContentReviewEmails.EMAIL_HEADING','Page due for review').'
'.
+ 'The page "'.$page->Title.'" is due for review today by you.
+ '. _t('ContentReviewEmails.REVIEWPAGELINK','Review the page in the CMS') .' —
+ '. _t('ContentReviewEmails.VIEWPUBLISHEDLINK','View this page on the website') .'';
+ if(class_exists('Notification')) {
+ Notification::notify($recipient, $message);
+ }
}
}
}
diff --git a/code/SiteTreeContentReview.php b/code/SiteTreeContentReview.php
index 3517751..9016d6b 100644
--- a/code/SiteTreeContentReview.php
+++ b/code/SiteTreeContentReview.php
@@ -49,7 +49,7 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
* @return string
*/
public function getEditorName() {
- if( $member = Member::currentUser() ) {
+ if($member = Member::currentUser()) {
return $member->FirstName .' '. $member->Surname;
}
return NULL;
@@ -163,15 +163,55 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
)
)->setDescription(_t('ContentReview.REVIEWFREQUENCYDESCRIPTION', 'The review date will be set to this far in the future whenever the page is published'));
+ $notesField = TextareaField::create('ReviewNotes', 'Review Notes');
+
$fields->addFieldsToTab("Root.Review", array(
new HeaderField(_t('ContentReview.REVIEWHEADER', "Content review"), 2),
$userField,
$groupField,
$reviewDate,
$reviewFrequency,
- new TextareaField('ReviewNotes', 'Review Notes')
+ $notesField
));
}
+
+ /**
+ *
+ * @param \FieldList $actions
+ */
+ public function updateCMSActions(\FieldList $actions) {
+ if($this->canBeReviewedBy(Member::currentUser())) {
+ $reviewAction = FormAction::create('reviewed', _t('ContentReview.BUTTONREVIEWED', 'Content reviewed'))
+ ->setAttribute('data-icon', 'pencil')
+ ->setAttribute('data-text-alternate', _t('ContentReview.BUTTONREVIEWED', 'Content reviewed'));
+ $actions->push($reviewAction);
+ }
+ }
+
+ /**
+ * Check if a review is due by a member for this owner
+ *
+ * @param Member $member
+ * @return boolean
+ */
+ public function canBeReviewedBy(Member $member) {
+ if(!$this->owner->obj('NextReviewDate')->exists()) {
+ return false;
+ }
+ if($this->owner->obj('NextReviewDate')->InFuture()) {
+ return false;
+ }
+ if($this->DirectGroups()->count() == 0 && $this->DirectUsers()->count() == 0) {
+ return false;
+ }
+ if($member->inGroups($this->DirectGroups())) {
+ return true;
+ }
+ if($this->DirectUsers()->find('ID', $member->ID)) {
+ return true;
+ }
+ return false;
+ }
/**
* Set the review data from the review period, if set.
diff --git a/code/extensions/ContentReviewCMSPageEditController.php b/code/extensions/ContentReviewCMSPageEditController.php
new file mode 100644
index 0000000..2c28393
--- /dev/null
+++ b/code/extensions/ContentReviewCMSPageEditController.php
@@ -0,0 +1,81 @@
+byID($SQL_id);
+ if($record && !$record->canEdit()) {
+ return Security::permissionFailure($this);
+ }
+ if(!$record || !$record->ID) {
+ throw new SS_HTTPResponse_Exception("Bad record ID #$SQL_id", 404);
+ }
+
+ $fields = new FieldList();
+ $fields->push(HiddenField::create('ID', 'ID', $SQL_id));
+ $fields->push(TextareaField::create('ReviewNotes', 'Review notes'));
+
+ $actions = new FieldList(
+ FormAction::create('save_review', 'Save')
+ );
+
+ $form = CMSForm::create($this->owner, "EditForm", $fields, $actions)->setHTMLID('Form_EditForm');
+ $form->setResponseNegotiator($this->owner->getResponseNegotiator());
+ $form->loadDataFrom($record);
+ $form->disableDefaultAction();
+
+ // TODO Can't merge $FormAttributes in template at the moment
+ $form->setTemplate($this->owner->getTemplatesWithSuffix('LeftAndMain_EditForm'));
+ return $form->forTemplate();
+ }
+
+ /**
+ * Save the review notes and redirect back to the page edit form
+ *
+ * @param array $data
+ * @param Form $form
+ * @return string - html
+ */
+ public function save_review($data, Form $form) {
+ if(!isset($data['ID'])) {
+ throw new SS_HTTPResponse_Exception("No record ID", 404);
+ }
+ $SQL_id = Convert::raw2sql($data['ID']);
+ $record = SiteTree::get()->byID($SQL_id);
+ if($record && !$record->canEdit()) {
+ return Security::permissionFailure($this);
+ }
+ if(!$record || !$record->ID) {
+ throw new SS_HTTPResponse_Exception("Bad record ID #$SQL_id", 404);
+ }
+
+ $record->ReviewNotes = $data['ReviewNotes'];
+ $record->write();
+ return $this->owner->redirect($this->owner->Link('show/'.$SQL_id));
+ }
+}
diff --git a/javascript/contentreview.js b/javascript/contentreview.js
new file mode 100644
index 0000000..afc35a5
--- /dev/null
+++ b/javascript/contentreview.js
@@ -0,0 +1,8 @@
+/*jslint browser: true, nomen: true, white: true */ /*global $, jQuery*/
+
+jQuery(function($) {
+ "use strict";
+
+ $.entwine('ss', function($) {
+ });
+});
\ No newline at end of file
diff --git a/tests/ContentReviewTest.php b/tests/ContentReviewTest.php
index 69971bd..047e604 100644
--- a/tests/ContentReviewTest.php
+++ b/tests/ContentReviewTest.php
@@ -102,4 +102,52 @@ class ContentReviewTest extends FunctionalTest {
$this->assertTrue($page->doPublish());
$this->assertEquals('', $page->OwnerNames);
}
+
+ public function testCanNotBeReviewBecauseNoReviewDate() {
+ SS_Datetime::set_mock_now('2010-01-01 12:00:00');
+ $author = $this->objFromFixture('Member', 'author');
+ $page = $this->objFromFixture('Page', 'no-review');
+ // page 'no-review' is owned by author, but there is no review date
+ $this->assertFalse($page->canBeReviewedBy($author));
+ }
+
+ public function testCanNotBeReviewedBecauseInFuture() {
+ SS_Datetime::set_mock_now('2010-01-01 12:00:00');
+ $author = $this->objFromFixture('Member', 'author');
+ $page = $this->objFromFixture('Page', 'staff');
+ // page 'staff' is owned by author, but the review date is in the future
+ $this->assertFalse($page->canBeReviewedBy($author));
+ }
+
+ public function testCanNotBeReviewedByUser() {
+ SS_Datetime::set_mock_now('2010-03-01 12:00:00');
+ $author = $this->objFromFixture('Member', 'author');
+ $page = $this->objFromFixture('Page', 'home');
+ // page 'home' doesnt have any owners
+ $this->assertFalse($page->canBeReviewedBy($author));
+ }
+
+ public function testCanBeReviewedByUser() {
+ SS_Datetime::set_mock_now('2010-03-01 12:00:00');
+ $author = $this->objFromFixture('Member', 'author');
+ $page = $this->objFromFixture('Page', 'staff');
+ // page 'staff' is owned by author
+ $this->assertTrue($page->canBeReviewedBy($author));
+ }
+
+ public function testCanNotBeReviewedByGroup() {
+ SS_Datetime::set_mock_now('2010-03-01 12:00:00');
+ $author = $this->objFromFixture('Member', 'editor');
+ $page = $this->objFromFixture('Page', 'contact');
+ // page 'contact' is owned by the authorgroup
+ $this->assertFalse($page->canBeReviewedBy($author));
+ }
+
+ public function testCanBeReviewedByGroup() {
+ SS_Datetime::set_mock_now('2010-03-01 12:00:00');
+ $author = $this->objFromFixture('Member', 'author');
+ $page = $this->objFromFixture('Page', 'contact');
+ // page 'contact' is owned by the authorgroup
+ $this->assertTrue($page->canBeReviewedBy($author));
+ }
}
diff --git a/tests/ContentReviewTest.yml b/tests/ContentReviewTest.yml
index 6739d92..90e0f48 100644
--- a/tests/ContentReviewTest.yml
+++ b/tests/ContentReviewTest.yml
@@ -45,4 +45,8 @@ Page:
ContentReviewUsers: =>Member.author
contact:
Title: Contact Us
- NextReviewDate: 2010-02-21
\ No newline at end of file
+ NextReviewDate: 2010-02-21
+ ContentReviewGroups: =>Group.authorgroup
+ no-review:
+ Title: Page without review date
+ ContentReviewUsers: =>Member.author
\ No newline at end of file