diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..872cde0 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,28 @@ +Copyright (c) 2015, ilateral +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of silverstripe-contacts nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..da0611e --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +Silverstripe System Messages Module +=================================== + +Module for the Silverstripe CMS that adds content manageable messages to a site +(that can be closed by via a user) via a template variable. + +## Author +This module was created by [i-lateral](http://www.i-lateral.com). + +## Installation + +Preferable you should installl this via composer using: + # composer require "i-lateral/silverstripe-systemmessages:0.*" + +Alternativley install this module by downloading and adding to: + +[silverstripe-root]/systemmessages + +Then run: + + http://yoursiteurl.com/dev/build/?flush=1 + +Or: + + # sake dev/build flush=1 + +## Usage + +Once installed, you must add the template variable: + + $SystemMessages.RenderedMessage + +to any templates you require messages to appear on. + +You can manage messages in the admin area using the +"Messages" tab. \ No newline at end of file diff --git a/_config.php b/_config.php new file mode 100644 index 0000000..b3d9bbc --- /dev/null +++ b/_config.php @@ -0,0 +1 @@ + + */ +class SystemMessages extends ViewableData +{ + + /** + * Get the most recent, open system message for the current + * user. + * + * @return SystemMessage + */ + public function Message() { + return $this->OpenMessages()->first(); + } + + /** + * Get the most recent message and render into a template + * + * @return string HTML of the message + */ + public function RenderedMessage() { + return $this->renderWith( + "SystemMessage", + $this->Message() + ); + } + + public function OpenMessages() { + $now = SS_Datetime::now()->Value; + $return = ArrayList::create(); + $member = Member::currentUser(); + $filter = array( + "StartDate:LessThan" => $now, + "ExpiryDate:GreaterThan" => $now + ); + + // Get all applicable messages + $messages = SystemMessage::get() + ->filter($filter) + ->sort("StartDate", "ASC"); + + // Loop through messages and only add relevent to the list + foreach ($messages as $message) { + if ($message->isOpen($member)) { + $return->add($message); + } + } + + return $return; + } + +} \ No newline at end of file diff --git a/code/admin/SystemMessageAdmin.php b/code/admin/SystemMessageAdmin.php new file mode 100644 index 0000000..73ac2e3 --- /dev/null +++ b/code/admin/SystemMessageAdmin.php @@ -0,0 +1,13 @@ +owner->request->param("ID"); + $message = SystemMessage::get()->byID($id); + $member = Member::currentUser(); + + // If not a message then generate an error + if (!$message) { + return $this->owner->httpError(500); + } + + if ($member) { + $message->close($member); + } else { + $message->close(); + } + + return $this->owner->redirectBack(); + } +} \ No newline at end of file diff --git a/code/extensions/SystemMessageMemberExtension.php b/code/extensions/SystemMessageMemberExtension.php new file mode 100644 index 0000000..fbca3e2 --- /dev/null +++ b/code/extensions/SystemMessageMemberExtension.php @@ -0,0 +1,8 @@ + "SystemMessage" + ); +} \ No newline at end of file diff --git a/code/model/SystemMessage.php b/code/model/SystemMessage.php new file mode 100644 index 0000000..5b71742 --- /dev/null +++ b/code/model/SystemMessage.php @@ -0,0 +1,96 @@ + + */ +class SystemMessage extends DataObject +{ + private static $db = array( + "Content" => "HTMLText", + "ButtonText" => "Varchar", + "StartDate" => "SS_Datetime", + "ExpiryDate" => "SS_Datetime" + ); + + private static $has_one = array( + 'Link' => 'Link' + ); + + private static $belongs_many_many = array( + "ClosedBy" => "Member" + ); + + /** + * Link to close this message + * + * @return string + */ + public function CloseLink() + { + return Controller::curr()->Link("closesystemmessage"); + } + + /** + * Has the current message been closed by the selected member + * + * @param Member $member A member object to check + * @return Boolean + */ + public function isClosedByMember(Member $member) + { + $match = $this->ClosedBy()->byID($member->ID); + return ($match) ? true : false; + } + + /** + * Is the current message closed (either by the passed member or a + * cookie) + * + * @param Int $memberID ID of member to search for (if not set current member is used) + * @return Boolean + */ + public function isClosed(Member $member = null) + { + $match = false; + + if ($member) { + $match = $this->isClosedByMember($member); + } else { + $match = Cookie::get("systemmessage.closed.{$this->ID}"); + } + + return ($match) ? true : false; + } + + /** + * Is the current message open (either by the passed member or a + * cookie) + * + * @param Int $memberID ID of member to search for (if not set current member is used) + * @return Boolean + */ + public function isOpen(Member $member = null) + { + return !$this->isClosed($member); + } + + /** + * Close this message for the current user, either + * via the database or by a cookie + * + * @param Member $member If we want to close for a member + * @return NULL + */ + public function Close(Member $member = null) + { + if ($member) { + $member->ClosedMessages()->add($this); + } else { + Cookie::set("systemmessage.closed.{$this->ID}", true); + } + } +} \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..198de81 --- /dev/null +++ b/composer.json @@ -0,0 +1,28 @@ +{ + "name": "i-lateral/silverstripe-systemmessages", + "description": "Add popup notification messages to a Silverstripe site", + "type": "silverstripe-module", + "homepage": "http://github.com/i-lateral/silverstripe-systemmessages", + "keywords": ["silverstripe", "messages", "notifications"], + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Morven Lewis-Everley", + "email": "morven@ilateral.co.uk" + }, + { + "name": "Mark Anderson", + "email": "mark@ilateral.co.uk" + } + ], + "support": { + "issues": "http://github.com/i-lateral/silverstripe-systemmessages/issues" + }, + "require": { + "silverstripe/framework": ">=3.1", + "sheadawson/silverstripe-linkable": "1.1.*" + }, + "extra": { + "installer-name": "carousel" + } +} diff --git a/tests/SystemMessageTest.php b/tests/SystemMessageTest.php new file mode 100644 index 0000000..9dda695 --- /dev/null +++ b/tests/SystemMessageTest.php @@ -0,0 +1,64 @@ +objFromFixture('Member', 'User1'); + $message = $this->objFromFixture('SystemMessage', 'SecondMessage'); + $this->assertNotFalse($message->isClosedByMember($member)); + $this->assertNotFalse($message->isClosed($member)); + $this->assertFalse($message->isOpen($member)); + } + + /** + * Test to see if message is closed via cookie is flagged as "closed" or + * "open" + */ + public function testClosedByCookie() + { + // Get message and set Cookie + $message = $this->objFromFixture('SystemMessage', 'FirstMessage'); + Cookie::set("systemmessage.closed.{$message->ID}", true); + + $this->assertNotFalse($message->isClosed()); + $this->assertFalse($message->isOpen()); + } + + /** + * A message that is past shouldnt be visible + * + */ + public function testExpired() + { + SS_Datetime::set_mock_now('2013-10-10 20:00:00'); + + $messages = SystemMessages::create()->OpenMessages(); + + $this->assertEquals("First Message", $messages->first()->Content); + + SS_Datetime::clear_mock_now(); + } + + /** + * A message that hasn't started yet should not be visible + * + */ + public function testNotStarted() + { + SS_Datetime::set_mock_now('2013-08-10 20:00:00'); + + $messages = SystemMessages::create()->OpenMessages(); + + $this->assertEquals("Second Message", $messages->first()->Content); + + SS_Datetime::clear_mock_now(); + } +} \ No newline at end of file diff --git a/tests/SystemMessages.yml b/tests/SystemMessages.yml new file mode 100644 index 0000000..2d555e1 --- /dev/null +++ b/tests/SystemMessages.yml @@ -0,0 +1,19 @@ +# Mock date is set to 2013-10-01 20:00:00 +Member: + User1: + FirstName: User + Surname: One + User2: + FirstName: User + Surname: Two + +SystemMessage: + FirstMessage: + Content: 'First Message' + StartDate: '2013-10-01 15:00:00' + ExpiryDate: '2013-11-01 15:00:00' + SecondMessage: + Content: 'Second Message' + ClosedBy: =>Member.User1 + StartDate: '2013-08-01 15:00:00' + ExpiryDate: '2013-09-01 15:00:00' \ No newline at end of file