diff --git a/code/extensions/CommentUserNotificationsExtension.php b/code/extensions/CommentUserNotificationsExtension.php index 56a2b89..b2b4a81 100644 --- a/code/extensions/CommentUserNotificationsExtension.php +++ b/code/extensions/CommentUserNotificationsExtension.php @@ -6,102 +6,105 @@ * * @author Matt Peel */ -class CommentUserNotificationsExtension extends DataExtension { - /** - * Add a boolean to track which {@link Comment} objects (and therefore the {@link Member} that posted them) wantk - * - * - * - * to be notified when new comments are posted. - * - * @var array Additional database fields to add to the {@link Comment} class. - */ - private static $db = array( - "NotifyOfUpdates" => "Boolean" - ); +class CommentUserNotificationsExtension extends DataExtension +{ + /** + * Add a boolean to track which {@link Comment} objects (and therefore the {@link Member} that posted them) wantk + * + * + * + * to be notified when new comments are posted. + * + * @var array Additional database fields to add to the {@link Comment} class. + */ + private static $db = array( + "NotifyOfUpdates" => "Boolean" + ); - /** - * We hook into onAfterWrite() because we want to check this every time the comment is written - primarily because - * of the test that we perform to ensure that the comment isn't currently moderated. Most sites will moderate - * comments initially, and there's no point sending an email to a user if the comment is still awaiting moderation - * (and therefore the user can't see it yet). - * - * @todo This will lead to multiple emails being sent if a comment is edited after being posted - */ - public function onAfterWrite() { - parent::onAfterWrite(); + /** + * We hook into onAfterWrite() because we want to check this every time the comment is written - primarily because + * of the test that we perform to ensure that the comment isn't currently moderated. Most sites will moderate + * comments initially, and there's no point sending an email to a user if the comment is still awaiting moderation + * (and therefore the user can't see it yet). + * + * @todo This will lead to multiple emails being sent if a comment is edited after being posted + */ + public function onAfterWrite() + { + parent::onAfterWrite(); - $parentClass = $this->owner->BaseClass; - $parentID = $this->owner->ParentID; + $parentClass = $this->owner->BaseClass; + $parentID = $this->owner->ParentID; - // We only want to notify people if certain conditions are met: - // - The comment has passed moderation (aka. if required, it has been approved by an admin) - // - We are either seeing the Comment for the first time, or it has just passed moderation by an admin - if($this->shouldSendUserNotificationEmails()) { - if(ClassInfo::exists($parentClass)) { - $commentParent = $parentClass::get()->byID($parentID); + // We only want to notify people if certain conditions are met: + // - The comment has passed moderation (aka. if required, it has been approved by an admin) + // - We are either seeing the Comment for the first time, or it has just passed moderation by an admin + if ($this->shouldSendUserNotificationEmails()) { + if (ClassInfo::exists($parentClass)) { + $commentParent = $parentClass::get()->byID($parentID); - // Get all comments attached to this page, which we have to do manually as the has_one relationship is - // 'faked' by the Comment class (because it can be attached to multiple parent classes). - if($commentParent) { - $comments = Comment::get()->filter(array( - 'BaseClass' => $parentClass, - 'ParentID' => $parentID, - 'NotifyOfUpdates' => true - )); + // Get all comments attached to this page, which we have to do manually as the has_one relationship is + // 'faked' by the Comment class (because it can be attached to multiple parent classes). + if ($commentParent) { + $comments = Comment::get()->filter(array( + 'BaseClass' => $parentClass, + 'ParentID' => $parentID, + 'NotifyOfUpdates' => true + )); - // If we have comments, iterate over them to build a unique list of all email addresses to notify - if($comments) { - $emailList = array(); + // If we have comments, iterate over them to build a unique list of all email addresses to notify + if ($comments) { + $emailList = array(); - foreach($comments as $c) { - $author = $c->Author(); + foreach ($comments as $c) { + $author = $c->Author(); - if($author) { - if(!in_array($author->Email, $emailList)) { - $emailList[] = $author->Email; - } - } - } + if ($author) { + if (!in_array($author->Email, $emailList)) { + $emailList[] = $author->Email; + } + } + } - // Send an email to everyone in the list - if(sizeof($emailList) > 0) { - foreach($emailList as $emailAddress) { - $email = new Email(); - $email->setSubject('New Comment on "' . $commentParent->dbObject('Title')->XML() . '"'); - $email->setFrom(Email::getAdminEmail()); - $email->setTo($emailAddress); - $email->populateTemplate($this->owner); + // Send an email to everyone in the list + if (sizeof($emailList) > 0) { + foreach ($emailList as $emailAddress) { + $email = new Email(); + $email->setSubject('New Comment on "' . $commentParent->dbObject('Title')->XML() . '"'); + $email->setFrom(Email::getAdminEmail()); + $email->setTo($emailAddress); + $email->populateTemplate($this->owner); - $email->send(); - } - } - } - } - } - } - } + $email->send(); + } + } + } + } + } + } + } - private function shouldSendUserNotificationEmails() { - $changedFields = $this->owner->getChangedFields(); + private function shouldSendUserNotificationEmails() + { + $changedFields = $this->owner->getChangedFields(); - return - $changedFields && - ( - // New record, automatically moderated as moderation is not enabled for this site - ( - isset($changedFields['ID']) && - isset($changedFields['Moderated']) && - $changedFields['ID']['before'] == 0 && - $changedFields['Moderated']['after'] === true - ) - || - // Existing record, moderation has just been set - meaning it has been approved by an admin - ( - isset($changedFields['Moderated']) && - $changedFields['Moderated']['before'] == false && - $changedFields['Moderated']['after'] === true - ) - ); - } -} \ No newline at end of file + return + $changedFields && + ( + // New record, automatically moderated as moderation is not enabled for this site + ( + isset($changedFields['ID']) && + isset($changedFields['Moderated']) && + $changedFields['ID']['before'] == 0 && + $changedFields['Moderated']['after'] === true + ) + || + // Existing record, moderation has just been set - meaning it has been approved by an admin + ( + isset($changedFields['Moderated']) && + $changedFields['Moderated']['before'] == false && + $changedFields['Moderated']['after'] === true + ) + ); + } +} diff --git a/code/extensions/CommentingControllerUserNotificationsExtension.php b/code/extensions/CommentingControllerUserNotificationsExtension.php index c5e965d..9ed0691 100644 --- a/code/extensions/CommentingControllerUserNotificationsExtension.php +++ b/code/extensions/CommentingControllerUserNotificationsExtension.php @@ -6,89 +6,92 @@ * * @see Comment */ -class CommentingControllerUserNotificationsExtension extends Extension { - public static $allowed_actions = array( - 'unsubscribenotification' - ); +class CommentingControllerUserNotificationsExtension extends Extension +{ + public static $allowed_actions = array( + 'unsubscribenotification' + ); - /** - * Alter the comment form to add a checkbox to give users the ability to receive notifications when further - * comments are posted. The {@link CommentingController::doPostComment()} method will take care of saving this - * field for us, as it's part of the {@link Comment} DataObject - * - * @see CommentUserNotificationsExtension - * @param Form $form The Form object used to render the comments form - */ - public function alterCommentForm(Form $form) { - $form->Fields()->insertAfter( - CheckboxField::create( - 'NotifyOfUpdates', - _t('CommentInterface.NOTIFYOFUPDATES', 'Please notify me about new comments posted here.') - ), - 'Comment' - ); - } + /** + * Alter the comment form to add a checkbox to give users the ability to receive notifications when further + * comments are posted. The {@link CommentingController::doPostComment()} method will take care of saving this + * field for us, as it's part of the {@link Comment} DataObject + * + * @see CommentUserNotificationsExtension + * @param Form $form The Form object used to render the comments form + */ + public function alterCommentForm(Form $form) + { + $form->Fields()->insertAfter( + CheckboxField::create( + 'NotifyOfUpdates', + _t('CommentInterface.NOTIFYOFUPDATES', 'Please notify me about new comments posted here.') + ), + 'Comment' + ); + } - /** - * Uses $this->owner->request (a {@link SS_HTTPRequest} object) to determine which comment we want to unsubscribe - * the member from. If the current user isn't logged in, or is logged in as a different user, then we send them to - * the login screen. - */ - public function unsubscribenotification() { - $request = $this->owner->getRequest(); + /** + * Uses $this->owner->request (a {@link SS_HTTPRequest} object) to determine which comment we want to unsubscribe + * the member from. If the current user isn't logged in, or is logged in as a different user, then we send them to + * the login screen. + */ + public function unsubscribenotification() + { + $request = $this->owner->getRequest(); - $commentID = $request->param('ID'); - $member = Member::currentUser(); + $commentID = $request->param('ID'); + $member = Member::currentUser(); - if(!$commentID) { - $this->owner->httpError(403); - return; - } + if (!$commentID) { + $this->owner->httpError(403); + return; + } - $comment = Comment::get()->byID($commentID); + $comment = Comment::get()->byID($commentID); - if(!$comment) { - $this->owner->httpError(403); - return; - } + if (!$comment) { + $this->owner->httpError(403); + return; + } - if(!$member || $member->ID != $comment->AuthorID) { - return Security::permissionFailure( - $this->owner, - array( - 'default' => _t( - 'CommentingControllerUserNotificationsExtension.DEFAULTFAIL', - 'You must login to unsubscribe.' - ), - 'alreadyLoggedIn' => _t( - 'CommentingControllerUserNotificationsExtension.ALREADYLOGGEDINFAIL', - 'You must login as the correct user (the user who submitted the comment) to continue.' - ), - 'logInAgain' => _t( - 'CommentingControllerUserNotificationsExtension.LOGINAGAINFAIL', - 'You have been logged out. If you would like to login again, enter your credentials below.' - ) - ) - ); - } + if (!$member || $member->ID != $comment->AuthorID) { + return Security::permissionFailure( + $this->owner, + array( + 'default' => _t( + 'CommentingControllerUserNotificationsExtension.DEFAULTFAIL', + 'You must login to unsubscribe.' + ), + 'alreadyLoggedIn' => _t( + 'CommentingControllerUserNotificationsExtension.ALREADYLOGGEDINFAIL', + 'You must login as the correct user (the user who submitted the comment) to continue.' + ), + 'logInAgain' => _t( + 'CommentingControllerUserNotificationsExtension.LOGINAGAINFAIL', + 'You have been logged out. If you would like to login again, enter your credentials below.' + ) + ) + ); + } - // Currently logged in Member's ID matches the author of the comment, so we can unsubscribe them - // We want to find all comments posted to this object by this author, and unsubscribe all of them. - $allComments = Comment::get()->filter(array( - 'BaseClass' => $comment->BaseClass, - 'ParentID' => $comment->ParentID, - 'NotifyOfUpdates' => true - )); + // Currently logged in Member's ID matches the author of the comment, so we can unsubscribe them + // We want to find all comments posted to this object by this author, and unsubscribe all of them. + $allComments = Comment::get()->filter(array( + 'BaseClass' => $comment->BaseClass, + 'ParentID' => $comment->ParentID, + 'NotifyOfUpdates' => true + )); - foreach($allComments as $c) { - $c->NotifyOfUpdates = false; - $c->write(); - } + foreach ($allComments as $c) { + $c->NotifyOfUpdates = false; + $c->write(); + } - // This sets a session var that can be queried on the page that we redirect the user back to, so that we can - // display a nice message to let the user know their unsubscription was successful. - Session::set('CommentUserNotificationsUnsubscribed', '1'); + // This sets a session var that can be queried on the page that we redirect the user back to, so that we can + // display a nice message to let the user know their unsubscription was successful. + Session::set('CommentUserNotificationsUnsubscribed', '1'); - $this->owner->redirectBack(); - } -} \ No newline at end of file + $this->owner->redirectBack(); + } +} diff --git a/code/extensions/ControllerCommentUserNotificationsExtension.php b/code/extensions/ControllerCommentUserNotificationsExtension.php index 80e322e..26dbf66 100644 --- a/code/extensions/ControllerCommentUserNotificationsExtension.php +++ b/code/extensions/ControllerCommentUserNotificationsExtension.php @@ -4,84 +4,92 @@ * This class is injected into all {@link Controller} class instances, and provides some helper methods to determine * whether there are comment subscriptions for a given Member in the system */ -class ControllerCommentUserNotificationsExtension extends Extension { - /** - * Returns a {@link DataList} of {@link DataObject} objects that the currently logged in {@link Member} has - * requested. Note that this doesn't return {@link Comment} objects, as there may be many comments from one member, - * all of which may have `NotifyOfUpdates` selected, but in reality only one notification will be sent per comment - * thread. - * - * This can be used in any template as follows (assuming $Title exists all DataObjects that comments are bound to): - * <% loop CommentUserNotificationSubscriptions %> - *
  • $Title.XML – unsubscribe
  • - * <% end_loop %> - */ - public function CommentUserNotificationSubscriptions() { - return $this->CommentUserNotificationSubscriptionsFor(Member::currentUser()); - } +class ControllerCommentUserNotificationsExtension extends Extension +{ + /** + * Returns a {@link DataList} of {@link DataObject} objects that the currently logged in {@link Member} has + * requested. Note that this doesn't return {@link Comment} objects, as there may be many comments from one member, + * all of which may have `NotifyOfUpdates` selected, but in reality only one notification will be sent per comment + * thread. + * + * This can be used in any template as follows (assuming $Title exists all DataObjects that comments are bound to): + * <% loop CommentUserNotificationSubscriptions %> + *
  • $Title.XML – unsubscribe
  • + * <% end_loop %> + */ + public function CommentUserNotificationSubscriptions() + { + return $this->CommentUserNotificationSubscriptionsFor(Member::currentUser()); + } - /** - * This method is overly complex, because {@link Comment} doesn't have a standard 'Parent' has_one, as it can be - * attached to multiple different object types. - * - * @todo Can we fix this method without losing the flexibility that {@link Comment} provides? - * - * @see the above CommentUserNotificationSubscriptions() method for documentation - * @param Member $member The {@link Member} object to find comments posted by, where `NotifyOfUpdates` = 1 - * @return ArrayList The list of {@link ArrayData} objects that can be shown in the template - */ - public function CommentUserNotificationSubscriptionsFor(Member $member) { - if(!$member || !$member->isInDB()) return null; // No member (or no ID yet), so nothing to find + /** + * This method is overly complex, because {@link Comment} doesn't have a standard 'Parent' has_one, as it can be + * attached to multiple different object types. + * + * @todo Can we fix this method without losing the flexibility that {@link Comment} provides? + * + * @see the above CommentUserNotificationSubscriptions() method for documentation + * @param Member $member The {@link Member} object to find comments posted by, where `NotifyOfUpdates` = 1 + * @return ArrayList The list of {@link ArrayData} objects that can be shown in the template + */ + public function CommentUserNotificationSubscriptionsFor(Member $member) + { + if (!$member || !$member->isInDB()) { + return null; + } // No member (or no ID yet), so nothing to find - $allComments = Comment::get()->filter(array( - 'AuthorID' => $member->ID, - 'NotifyOfUpdates' => true - )); + $allComments = Comment::get()->filter(array( + 'AuthorID' => $member->ID, + 'NotifyOfUpdates' => true + )); - if(!$allComments) return null; + if (!$allComments) { + return null; + } - $allObjects = new ArrayList(); - $allAddedComments = new ArrayList(); + $allObjects = new ArrayList(); + $allAddedComments = new ArrayList(); - // @todo O(n^2) :( - foreach($allComments as $comment) { - $alreadyAdded = false; + // @todo O(n^2) :( + foreach ($allComments as $comment) { + $alreadyAdded = false; - foreach($allAddedComments as $obj) { - if($comment->BaseClass == $obj->BaseClass && $comment->ParentID == $obj->ParentID) { - $alreadyAdded = true; - break; - } - } + foreach ($allAddedComments as $obj) { + if ($comment->BaseClass == $obj->BaseClass && $comment->ParentID == $obj->ParentID) { + $alreadyAdded = true; + break; + } + } - if(!$alreadyAdded) { - $baseClass = $comment->BaseClass; - $baseObject = $baseClass::get()->byID($comment->ParentID); + if (!$alreadyAdded) { + $baseClass = $comment->BaseClass; + $baseObject = $baseClass::get()->byID($comment->ParentID); - if($baseObject) { - // @todo This could return the actual DataObject that we're expecting (e.g. the SiteTree object), - // but we can't add the 'CommentUserNotificationUnsubscribeLink' easily to it - $allObjects->push(new ArrayData(array( - 'CommentUserNotificationUnsubscribeLink' => Controller::join_links( - 'CommentingController', - 'unsubscribenotification', - $comment->ID - ), - 'Title' => $baseObject->Title - ))); + if ($baseObject) { + // @todo This could return the actual DataObject that we're expecting (e.g. the SiteTree object), + // but we can't add the 'CommentUserNotificationUnsubscribeLink' easily to it + $allObjects->push(new ArrayData(array( + 'CommentUserNotificationUnsubscribeLink' => Controller::join_links( + 'CommentingController', + 'unsubscribenotification', + $comment->ID + ), + 'Title' => $baseObject->Title + ))); - $allAddedComments->push($comment); // Keep track of what we've already added - } - } - } + $allAddedComments->push($comment); // Keep track of what we've already added + } + } + } - return $allObjects; - } + return $allObjects; + } - public function HasJustUnsubscribedFromUserCommentNotification() { - $hasUnsubscribed = Session::get('CommentUserNotificationsUnsubscribed'); - Session::clear('CommentUserNotificationsUnsubscribed'); + public function HasJustUnsubscribedFromUserCommentNotification() + { + $hasUnsubscribed = Session::get('CommentUserNotificationsUnsubscribed'); + Session::clear('CommentUserNotificationsUnsubscribed'); - return $hasUnsubscribed; - } -} \ No newline at end of file + return $hasUnsubscribed; + } +}