From ae440666a041a994cead8373e74c481b5fdd1dea Mon Sep 17 00:00:00 2001 From: Stig Lindqvist Date: Fri, 14 Feb 2014 14:49:43 +1300 Subject: [PATCH] Adding content reviewed actions to a sitetree --- _config/config.yml | 5 +- code/ContentReviewEmails.php | 8 ++ code/SiteTreeContentReview.php | 44 +++++++++- .../ContentReviewCMSPageEditController.php | 81 +++++++++++++++++++ javascript/contentreview.js | 8 ++ tests/ContentReviewTest.php | 48 +++++++++++ tests/ContentReviewTest.yml | 6 +- 7 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 code/extensions/ContentReviewCMSPageEditController.php create mode 100644 javascript/contentreview.js 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