diff options
75 files changed, 1079 insertions, 1170 deletions
diff --git a/app/Action/Base.php b/app/Action/Base.php index a2b07e3f..70dd871d 100644 --- a/app/Action/Base.php +++ b/app/Action/Base.php @@ -2,9 +2,8 @@ namespace Action; +use Event\GenericEvent; use Pimple\Container; -use Core\Listener; -use Core\Tool; /** * Base class for automatic actions @@ -21,9 +20,17 @@ use Core\Tool; * @property \Model\TaskFinder $taskFinder * @property \Model\TaskStatus $taskStatus */ -abstract class Base implements Listener +abstract class Base { /** + * Flag for called listener + * + * @access private + * @var boolean + */ + private $called = false; + + /** * Project id * * @access private @@ -114,6 +121,7 @@ abstract class Base implements Listener $this->container = $container; $this->project_id = $project_id; $this->event_name = $event_name; + $this->called = false; } /** @@ -136,7 +144,7 @@ abstract class Base implements Listener */ public function __get($name) { - return Tool::loadModel($this->container, $name); + return $this->container[$name]; } /** @@ -225,12 +233,20 @@ abstract class Base implements Listener * Execute the action * * @access public - * @param array $data Event data dictionary - * @return bool True if the action was executed or false when not executed + * @param \Event\GenericEvent $event Event data dictionary + * @return bool True if the action was executed or false when not executed */ - public function execute(array $data) + public function execute(GenericEvent $event) { + // Avoid infinite loop, a listener instance can be called only one time + if ($this->called) { + return false; + } + + $data = $event->getAll(); + if ($this->isExecutable($data)) { + $this->called = true; return $this->doAction($data); } diff --git a/app/Action/TaskAssignCategoryColor.php b/app/Action/TaskAssignCategoryColor.php index 4134b584..ba319a1f 100644 --- a/app/Action/TaskAssignCategoryColor.php +++ b/app/Action/TaskAssignCategoryColor.php @@ -67,7 +67,7 @@ class TaskAssignCategoryColor extends Base 'category_id' => $this->getParam('category_id'), ); - return $this->taskModification->update($values, false); + return $this->taskModification->update($values); } /** diff --git a/app/Action/TaskAssignCategoryLabel.php b/app/Action/TaskAssignCategoryLabel.php index da41a313..19064526 100644 --- a/app/Action/TaskAssignCategoryLabel.php +++ b/app/Action/TaskAssignCategoryLabel.php @@ -67,7 +67,7 @@ class TaskAssignCategoryLabel extends Base 'category_id' => isset($data['category_id']) ? $data['category_id'] : $this->getParam('category_id'), ); - return $this->taskModification->update($values, false); + return $this->taskModification->update($values); } /** diff --git a/app/Action/TaskAssignColorCategory.php b/app/Action/TaskAssignColorCategory.php index 68bca5d0..a362c68f 100644 --- a/app/Action/TaskAssignColorCategory.php +++ b/app/Action/TaskAssignColorCategory.php @@ -67,7 +67,7 @@ class TaskAssignColorCategory extends Base 'color_id' => $this->getParam('color_id'), ); - return $this->taskModification->update($values, false); + return $this->taskModification->update($values); } /** diff --git a/app/Action/TaskAssignColorUser.php b/app/Action/TaskAssignColorUser.php index d419ab4d..6161514d 100644 --- a/app/Action/TaskAssignColorUser.php +++ b/app/Action/TaskAssignColorUser.php @@ -68,7 +68,7 @@ class TaskAssignColorUser extends Base 'color_id' => $this->getParam('color_id'), ); - return $this->taskModification->update($values, false); + return $this->taskModification->update($values); } /** diff --git a/app/Action/TaskAssignCurrentUser.php b/app/Action/TaskAssignCurrentUser.php index 9317bf83..b2015100 100644 --- a/app/Action/TaskAssignCurrentUser.php +++ b/app/Action/TaskAssignCurrentUser.php @@ -62,12 +62,16 @@ class TaskAssignCurrentUser extends Base */ public function doAction(array $data) { + if (! $this->acl->isLogged()) { + return false; + } + $values = array( 'id' => $data['task_id'], 'owner_id' => $this->acl->getUserId(), ); - return $this->taskModification->update($values, false); + return $this->taskModification->update($values); } /** diff --git a/app/Action/TaskAssignSpecificUser.php b/app/Action/TaskAssignSpecificUser.php index c3b979c2..4c96f7f0 100644 --- a/app/Action/TaskAssignSpecificUser.php +++ b/app/Action/TaskAssignSpecificUser.php @@ -68,7 +68,7 @@ class TaskAssignSpecificUser extends Base 'owner_id' => $this->getParam('user_id'), ); - return $this->taskModification->update($values, false); + return $this->taskModification->update($values); } /** diff --git a/app/Action/TaskAssignUser.php b/app/Action/TaskAssignUser.php index d01c4073..f24ff415 100644 --- a/app/Action/TaskAssignUser.php +++ b/app/Action/TaskAssignUser.php @@ -64,7 +64,7 @@ class TaskAssignUser extends Base 'owner_id' => $data['owner_id'], ); - return $this->taskModification->update($values, false); + return $this->taskModification->update($values); } /** diff --git a/app/Action/TaskCreation.php b/app/Action/TaskCreation.php index 0c791688..9b7a0b13 100644 --- a/app/Action/TaskCreation.php +++ b/app/Action/TaskCreation.php @@ -63,7 +63,7 @@ class TaskCreation extends Base 'project_id' => $data['project_id'], 'title' => $data['title'], 'reference' => $data['reference'], - 'description' => $data['description'], + 'description' => isset($data['description']) ? $data['description'] : '', )); } diff --git a/app/Auth/Base.php b/app/Auth/Base.php index 9633af4f..2a3bdce0 100644 --- a/app/Auth/Base.php +++ b/app/Auth/Base.php @@ -2,7 +2,6 @@ namespace Auth; -use Core\Tool; use Pimple\Container; /** @@ -54,6 +53,6 @@ abstract class Base */ public function __get($name) { - return Tool::loadModel($this->container, $name); + return $this->container[$name]; } } diff --git a/app/Console/Base.php b/app/Console/Base.php index f955b428..5927443c 100644 --- a/app/Console/Base.php +++ b/app/Console/Base.php @@ -2,7 +2,6 @@ namespace Console; -use Core\Tool; use Pimple\Container; use Symfony\Component\Console\Command\Command; @@ -52,6 +51,6 @@ abstract class Base extends Command */ public function __get($name) { - return Tool::loadModel($this->container, $name); + return $this->container[$name]; } } diff --git a/app/Controller/Base.php b/app/Controller/Base.php index 5b99e6b8..8330f6d5 100644 --- a/app/Controller/Base.php +++ b/app/Controller/Base.php @@ -3,7 +3,6 @@ namespace Controller; use Pimple\Container; -use Core\Tool; use Core\Security; use Core\Request; use Core\Response; @@ -129,7 +128,7 @@ abstract class Base */ public function __get($name) { - return Tool::loadModel($this->container, $name); + return $this->container[$name]; } /** @@ -156,9 +155,6 @@ abstract class Base $this->response->hsts(); } - $this->config->setupTranslations(); - $this->config->setupTimezone(); - // Authentication if (! $this->authentication->isAuthenticated($controller, $action)) { @@ -173,30 +169,6 @@ abstract class Base if (! $this->acl->isPageAccessAllowed($controller, $action)) { $this->response->redirect('?controller=user&action=forbidden'); } - - // Attach events - $this->attachEvents(); - } - - /** - * Attach events - * - * @access private - */ - private function attachEvents() - { - $models = array( - 'projectActivity', // Order is important - 'projectDailySummary', - 'action', - 'project', - 'webhook', - 'notification', - ); - - foreach ($models as $model) { - $this->$model->attachEvents(); - } } /** diff --git a/app/Core/Event.php b/app/Core/Event.php deleted file mode 100644 index 935f8b9c..00000000 --- a/app/Core/Event.php +++ /dev/null @@ -1,175 +0,0 @@ -<?php - -namespace Core; - -/** - * Event dispatcher class - * - * @package core - * @author Frederic Guillot - */ -class Event -{ - /** - * Contains all listeners - * - * @access private - * @var array - */ - private $listeners = array(); - - /** - * The last listener executed - * - * @access private - * @var string - */ - private $lastListener = ''; - - /** - * The last triggered event - * - * @access private - * @var string - */ - private $lastEvent = ''; - - /** - * Triggered events list - * - * @access private - * @var array - */ - private $events = array(); - - /** - * Attach a listener object to an event - * - * @access public - * @param string $eventName Event name - * @param Listener $listener Object that implements the Listener interface - */ - public function attach($eventName, Listener $listener) - { - if (! isset($this->listeners[$eventName])) { - $this->listeners[$eventName] = array(); - } - - $this->listeners[$eventName][] = $listener; - } - - /** - * Trigger an event - * - * @access public - * @param string $eventName Event name - * @param array $data Event data - */ - public function trigger($eventName, array $data) - { - if (! $this->isEventTriggered($eventName)) { - - $this->events[$eventName] = $data; - - if (isset($this->listeners[$eventName])) { - - foreach ($this->listeners[$eventName] as $listener) { - - $this->lastEvent = $eventName; - - if ($listener->execute($data)) { - $this->lastListener = get_class($listener); - } - } - } - } - } - - /** - * Get the last listener executed - * - * @access public - * @return string Event name - */ - public function getLastListenerExecuted() - { - return $this->lastListener; - } - - /** - * Get the last fired event - * - * @access public - * @return string Event name - */ - public function getLastTriggeredEvent() - { - return $this->lastEvent; - } - - /** - * Get a list of triggered events - * - * @access public - * @return array - */ - public function getTriggeredEvents() - { - return $this->events; - } - - /** - * Get a list of triggered events - * - * @access public - * @return array - */ - public function getEventData($eventName) - { - return isset($this->events[$eventName]) ? $this->events[$eventName] : array(); - } - - /** - * Check if an event have been triggered - * - * @access public - * @param string $eventName Event name - * @return bool - */ - public function isEventTriggered($eventName) - { - return isset($this->events[$eventName]); - } - - /** - * Flush the list of triggered events - * - * @access public - */ - public function clearTriggeredEvents() - { - $this->events = array(); - $this->lastEvent = ''; - } - - /** - * Check if a listener bind to an event - * - * @access public - * @param string $eventName Event name - * @param mixed $instance Instance name or object itself - * @return bool Yes or no - */ - public function hasListener($eventName, $instance) - { - if (isset($this->listeners[$eventName])) { - foreach ($this->listeners[$eventName] as $listener) { - if ($listener instanceof $instance) { - return true; - } - } - } - - return false; - } -} diff --git a/app/Core/Listener.php b/app/Core/Listener.php deleted file mode 100644 index 9c96cd57..00000000 --- a/app/Core/Listener.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -namespace Core; - -/** - * Event listener interface - * - * @package core - * @author Frederic Guillot - */ -interface Listener -{ - /** - * Execute the listener - * - * @access public - * @param array $data Event data - * @return boolean - */ - public function execute(array $data); -} diff --git a/app/Core/Tool.php b/app/Core/Tool.php index c010d932..ade99cad 100644 --- a/app/Core/Tool.php +++ b/app/Core/Tool.php @@ -2,8 +2,6 @@ namespace Core; -use Pimple\Container; - /** * Tool class * @@ -33,23 +31,4 @@ class Tool fclose($fp); } } - - /** - * Load and register a model - * - * @static - * @access public - * @param Pimple\Container $container Container instance - * @param string $name Model name - * @return mixed - */ - public static function loadModel(Container $container, $name) - { - if (! isset($container[$name])) { - $class = '\Model\\'.ucfirst($name); - $container[$name] = new $class($container); - } - - return $container[$name]; - } } diff --git a/app/Event/Base.php b/app/Event/Base.php deleted file mode 100644 index 0217fa08..00000000 --- a/app/Event/Base.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -namespace Event; - -use Pimple\Container; -use Core\Listener; -use Core\Tool; - -/** - * Base Listener - * - * @package event - * @author Frederic Guillot - * - * @property \Model\Comment $comment - * @property \Model\Project $project - * @property \Model\ProjectActivity $projectActivity - * @property \Model\SubTask $subTask - * @property \Model\Task $task - * @property \Model\TaskFinder $taskFinder - */ -abstract class Base implements Listener -{ - /** - * Container instance - * - * @access protected - * @var \Pimple\Container - */ - protected $container; - - /** - * Constructor - * - * @access public - * @param \Pimple\Container $container - */ - public function __construct(Container $container) - { - $this->container = $container; - } - - /** - * Return class information - * - * @access public - * @return string - */ - public function __toString() - { - return get_called_class(); - } - - /** - * Load automatically models - * - * @access public - * @param string $name Model name - * @return mixed - */ - public function __get($name) - { - return Tool::loadModel($this->container, $name); - } - - /** - * Get event namespace - * - * Event = task.close | Namespace = task - * - * @access public - * @return string - */ - public function getEventNamespace() - { - $event_name = $this->container['event']->getLastTriggeredEvent(); - return substr($event_name, 0, strpos($event_name, '.')); - } -} diff --git a/app/Event/CommentEvent.php b/app/Event/CommentEvent.php new file mode 100644 index 00000000..75a132d7 --- /dev/null +++ b/app/Event/CommentEvent.php @@ -0,0 +1,7 @@ +<?php + +namespace Event; + +class CommentEvent extends GenericEvent +{ +} diff --git a/app/Event/FileEvent.php b/app/Event/FileEvent.php new file mode 100644 index 00000000..81bd83c9 --- /dev/null +++ b/app/Event/FileEvent.php @@ -0,0 +1,7 @@ +<?php + +namespace Event; + +class FileEvent extends GenericEvent +{ +} diff --git a/app/Event/GenericEvent.php b/app/Event/GenericEvent.php new file mode 100644 index 00000000..b29d8f32 --- /dev/null +++ b/app/Event/GenericEvent.php @@ -0,0 +1,45 @@ +<?php + +namespace Event; + +use ArrayAccess; +use Symfony\Component\EventDispatcher\Event as BaseEvent; + +class GenericEvent extends BaseEvent implements ArrayAccess +{ + private $container = array(); + + public function __construct(array $values = array()) + { + $this->container = $values; + } + + public function getAll() + { + return $this->container; + } + + public function offsetSet($offset, $value) + { + if (is_null($offset)) { + $this->container[] = $value; + } else { + $this->container[$offset] = $value; + } + } + + public function offsetExists($offset) + { + return isset($this->container[$offset]); + } + + public function offsetUnset($offset) + { + unset($this->container[$offset]); + } + + public function offsetGet($offset) + { + return isset($this->container[$offset]) ? $this->container[$offset] : null; + } +} diff --git a/app/Event/NotificationListener.php b/app/Event/NotificationListener.php deleted file mode 100644 index 3c049327..00000000 --- a/app/Event/NotificationListener.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php - -namespace Event; - -/** - * Notification listener - * - * @package event - * @author Frederic Guillot - */ -class NotificationListener extends Base -{ - /** - * Template name - * - * @accesss private - * @var string - */ - private $template = ''; - - /** - * Set template name - * - * @access public - * @param string $template Template name - */ - public function setTemplate($template) - { - $this->template = $template; - } - - /** - * Execute the action - * - * @access public - * @param array $data Event data dictionary - * @return bool True if the action was executed or false when not executed - */ - public function execute(array $data) - { - $values = $this->getTemplateData($data); - $users = $this->notification->getUsersList($values['task']['project_id']); - - if ($users) { - $this->notification->sendEmails($this->template, $users, $values); - return true; - } - - return false; - } - - /** - * Fetch data for the mail template - * - * @access public - * @param array $data Event data - * @return array - */ - public function getTemplateData(array $data) - { - $values = array(); - - switch ($this->getEventNamespace()) { - case 'task': - $values['task'] = $this->taskFinder->getDetails($data['task_id']); - break; - case 'subtask': - $values['subtask'] = $this->subtask->getById($data['id'], true); - $values['task'] = $this->taskFinder->getDetails($data['task_id']); - break; - case 'file': - $values['file'] = $data; - $values['task'] = $this->taskFinder->getDetails($data['task_id']); - break; - case 'comment': - $values['comment'] = $this->comment->getById($data['id']); - $values['task'] = $this->taskFinder->getDetails($values['comment']['task_id']); - break; - } - - return $values; - } -} diff --git a/app/Event/ProjectActivityListener.php b/app/Event/ProjectActivityListener.php deleted file mode 100644 index 75efe65d..00000000 --- a/app/Event/ProjectActivityListener.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -namespace Event; - -/** - * Project activity listener - * - * @package event - * @author Frederic Guillot - */ -class ProjectActivityListener extends Base -{ - /** - * Execute the action - * - * @access public - * @param array $data Event data dictionary - * @return bool True if the action was executed or false when not executed - */ - public function execute(array $data) - { - if (isset($data['task_id'])) { - - $values = $this->getValues($data); - - return $this->projectActivity->createEvent( - $values['task']['project_id'], - $values['task']['id'], - $this->acl->getUserId(), - $this->container['event']->getLastTriggeredEvent(), - $values - ); - } - - return false; - } - - /** - * Get event activity data - * - * @access private - * @param array $data Event data dictionary - * @return array - */ - private function getValues(array $data) - { - $values = array(); - $values['task'] = $this->taskFinder->getDetails($data['task_id']); - - switch ($this->getEventNamespace()) { - case 'subtask': - $values['subtask'] = $this->subTask->getById($data['id'], true); - break; - case 'comment': - $values['comment'] = $this->comment->getById($data['id']); - break; - } - - return $values; - } -} diff --git a/app/Event/ProjectDailySummaryListener.php b/app/Event/ProjectDailySummaryListener.php deleted file mode 100644 index cd593abc..00000000 --- a/app/Event/ProjectDailySummaryListener.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -namespace Event; - -/** - * Project daily summary listener - * - * @package event - * @author Frederic Guillot - */ -class ProjectDailySummaryListener extends Base -{ - /** - * Execute the action - * - * @access public - * @param array $data Event data dictionary - * @return bool True if the action was executed or false when not executed - */ - public function execute(array $data) - { - if (isset($data['project_id'])) { - return $this->projectDailySummary->updateTotals($data['project_id'], date('Y-m-d')); - } - - return false; - } -} diff --git a/app/Event/ProjectModificationDateListener.php b/app/Event/ProjectModificationDateListener.php deleted file mode 100644 index abc176b0..00000000 --- a/app/Event/ProjectModificationDateListener.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -namespace Event; - -/** - * Project modification date listener - * - * Update the "last_modified" field for a project - * - * @package event - * @author Frederic Guillot - */ -class ProjectModificationDateListener extends Base -{ - /** - * Execute the action - * - * @access public - * @param array $data Event data dictionary - * @return bool True if the action was executed or false when not executed - */ - public function execute(array $data) - { - if (isset($data['project_id'])) { - return $this->project->updateModificationDate($data['project_id']); - } - - return false; - } -} diff --git a/app/Event/SubtaskEvent.php b/app/Event/SubtaskEvent.php new file mode 100644 index 00000000..229db860 --- /dev/null +++ b/app/Event/SubtaskEvent.php @@ -0,0 +1,7 @@ +<?php + +namespace Event; + +class SubtaskEvent extends GenericEvent +{ +} diff --git a/app/Event/TaskEvent.php b/app/Event/TaskEvent.php new file mode 100644 index 00000000..e2fb30fe --- /dev/null +++ b/app/Event/TaskEvent.php @@ -0,0 +1,7 @@ +<?php + +namespace Event; + +class TaskEvent extends GenericEvent +{ +} diff --git a/app/Event/WebhookListener.php b/app/Event/WebhookListener.php deleted file mode 100644 index f7e23e07..00000000 --- a/app/Event/WebhookListener.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -namespace Event; - -/** - * Webhook task events - * - * @package event - * @author Frederic Guillot - */ -class WebhookListener extends Base -{ - /** - * Url to call - * - * @access private - * @var string - */ - private $url = ''; - - /** - * Set webhook url - * - * @access public - * @param string $url URL to call - */ - public function setUrl($url) - { - $this->url = $url; - } - - /** - * Execute the action - * - * @access public - * @param array $data Event data dictionary - * @return bool True if the action was executed or false when not executed - */ - public function execute(array $data) - { - $this->webhook->notify($this->url, $data); - return true; - } -} diff --git a/app/Model/Action.php b/app/Model/Action.php index f8dbd88e..3ed3dc26 100644 --- a/app/Model/Action.php +++ b/app/Model/Action.php @@ -248,7 +248,7 @@ class Action extends Base $listener->setParam($param['name'], $param['value']); } - $this->event->attach($action['event_name'], $listener); + $this->container['dispatcher']->addListener($action['event_name'], array($listener, 'execute')); } } diff --git a/app/Model/Base.php b/app/Model/Base.php index 56a4d8e8..a08bd87c 100644 --- a/app/Model/Base.php +++ b/app/Model/Base.php @@ -2,10 +2,7 @@ namespace Model; -use Core\Event; -use Core\Tool; use Pimple\Container; -use PicoDb\Database; /** * Base model class @@ -52,14 +49,6 @@ abstract class Base protected $db; /** - * Event dispatcher instance - * - * @access public - * @var \Core\Event - */ - public $event; - - /** * Container instance * * @access protected @@ -77,7 +66,6 @@ abstract class Base { $this->container = $container; $this->db = $this->container['db']; - $this->event = $this->container['event']; } /** @@ -89,7 +77,7 @@ abstract class Base */ public function __get($name) { - return Tool::loadModel($this->container, $name); + return $this->container[$name]; } /** diff --git a/app/Model/Comment.php b/app/Model/Comment.php index 3b7dfbc1..a36f2b45 100644 --- a/app/Model/Comment.php +++ b/app/Model/Comment.php @@ -2,6 +2,7 @@ namespace Model; +use Event\CommentEvent; use SimpleValidator\Validator; use SimpleValidator\Validators; @@ -107,7 +108,7 @@ class Comment extends Base $comment_id = $this->persist(self::TABLE, $values); if ($comment_id) { - $this->event->trigger(self::EVENT_CREATE, array('id' => $comment_id) + $values); + $this->container['dispatcher']->dispatch(self::EVENT_CREATE, new CommentEvent(array('id' => $comment_id) + $values)); } return $comment_id; @@ -127,7 +128,7 @@ class Comment extends Base ->eq('id', $values['id']) ->update(array('comment' => $values['comment'])); - $this->event->trigger(self::EVENT_UPDATE, $values); + $this->container['dispatcher']->dispatch(self::EVENT_UPDATE, new CommentEvent($values)); return $result; } diff --git a/app/Model/File.php b/app/Model/File.php index d5a0c7cd..20fba9bf 100644 --- a/app/Model/File.php +++ b/app/Model/File.php @@ -2,6 +2,8 @@ namespace Model; +use Event\FileEvent; + /** * File model * @@ -89,7 +91,10 @@ class File extends Base */ public function create($task_id, $name, $path, $is_image) { - $this->event->trigger(self::EVENT_CREATE, array('task_id' => $task_id, 'name' => $name)); + $this->container['dispatcher']->dispatch( + self::EVENT_CREATE, + new FileEvent(array('task_id' => $task_id, 'name' => $name)) + ); return $this->db->table(self::TABLE)->save(array( 'task_id' => $task_id, diff --git a/app/Model/GithubWebhook.php b/app/Model/GithubWebhook.php index 9c8bd366..f66358eb 100644 --- a/app/Model/GithubWebhook.php +++ b/app/Model/GithubWebhook.php @@ -2,6 +2,8 @@ namespace Model; +use Event\GenericEvent; + /** * Github Webhook model * @@ -88,7 +90,10 @@ class GithubWebhook extends Base } if ($task['is_active'] == Task::STATUS_OPEN) { - $this->event->trigger(self::EVENT_COMMIT, array('task_id' => $task_id) + $task); + $this->container['dispatcher']->dispatch( + self::EVENT_COMMIT, + new GenericEvent(array('task_id' => $task_id) + $task) + ); } } @@ -146,7 +151,11 @@ class GithubWebhook extends Base 'task_id' => $task['id'], ); - $this->event->trigger(self::EVENT_ISSUE_COMMENT, $event); + $this->container['dispatcher']->dispatch( + self::EVENT_ISSUE_COMMENT, + new GenericEvent($event) + ); + return true; } @@ -169,7 +178,11 @@ class GithubWebhook extends Base 'description' => $issue['body']."\n\n[".t('Github Issue').']('.$issue['html_url'].')', ); - $this->event->trigger(self::EVENT_ISSUE_OPENED, $event); + $this->container['dispatcher']->dispatch( + self::EVENT_ISSUE_OPENED, + new GenericEvent($event) + ); + return true; } @@ -191,7 +204,11 @@ class GithubWebhook extends Base 'reference' => $issue['number'], ); - $this->event->trigger(self::EVENT_ISSUE_CLOSED, $event); + $this->container['dispatcher']->dispatch( + self::EVENT_ISSUE_CLOSED, + new GenericEvent($event) + ); + return true; } @@ -216,7 +233,11 @@ class GithubWebhook extends Base 'reference' => $issue['number'], ); - $this->event->trigger(self::EVENT_ISSUE_REOPENED, $event); + $this->container['dispatcher']->dispatch( + self::EVENT_ISSUE_REOPENED, + new GenericEvent($event) + ); + return true; } @@ -244,7 +265,11 @@ class GithubWebhook extends Base 'reference' => $issue['number'], ); - $this->event->trigger(self::EVENT_ISSUE_ASSIGNEE_CHANGE, $event); + $this->container['dispatcher']->dispatch( + self::EVENT_ISSUE_ASSIGNEE_CHANGE, + new GenericEvent($event) + ); + return true; } @@ -271,7 +296,11 @@ class GithubWebhook extends Base 'reference' => $issue['number'], ); - $this->event->trigger(self::EVENT_ISSUE_ASSIGNEE_CHANGE, $event); + $this->container['dispatcher']->dispatch( + self::EVENT_ISSUE_ASSIGNEE_CHANGE, + new GenericEvent($event) + ); + return true; } @@ -299,7 +328,11 @@ class GithubWebhook extends Base 'label' => $label['name'], ); - $this->event->trigger(self::EVENT_ISSUE_LABEL_CHANGE, $event); + $this->container['dispatcher']->dispatch( + self::EVENT_ISSUE_LABEL_CHANGE, + new GenericEvent($event) + ); + return true; } @@ -328,7 +361,11 @@ class GithubWebhook extends Base 'category_id' => 0, ); - $this->event->trigger(self::EVENT_ISSUE_LABEL_CHANGE, $event); + $this->container['dispatcher']->dispatch( + self::EVENT_ISSUE_LABEL_CHANGE, + new GenericEvent($event) + ); + return true; } diff --git a/app/Model/Notification.php b/app/Model/Notification.php index 8d1fca09..ccda1488 100644 --- a/app/Model/Notification.php +++ b/app/Model/Notification.php @@ -94,37 +94,6 @@ class Notification extends Base } /** - * Attach events - * - * @access public - */ - public function attachEvents() - { - $events = array( - Task::EVENT_CREATE => 'task_creation', - Task::EVENT_UPDATE => 'task_update', - Task::EVENT_CLOSE => 'task_close', - Task::EVENT_OPEN => 'task_open', - Task::EVENT_MOVE_COLUMN => 'task_move_column', - Task::EVENT_MOVE_POSITION => 'task_move_position', - Task::EVENT_ASSIGNEE_CHANGE => 'task_assignee_change', - SubTask::EVENT_CREATE => 'subtask_creation', - SubTask::EVENT_UPDATE => 'subtask_update', - Comment::EVENT_CREATE => 'comment_creation', - Comment::EVENT_UPDATE => 'comment_update', - File::EVENT_CREATE => 'file_creation', - ); - - foreach ($events as $event_name => $template_name) { - - $listener = new NotificationListener($this->container); - $listener->setTemplate($template_name); - - $this->event->attach($event_name, $listener); - } - } - - /** * Send the email notifications * * @access public diff --git a/app/Model/Project.php b/app/Model/Project.php index c4ec232a..9c0adee9 100644 --- a/app/Model/Project.php +++ b/app/Model/Project.php @@ -4,7 +4,6 @@ namespace Model; use SimpleValidator\Validator; use SimpleValidator\Validators; -use Event\ProjectModificationDateListener; use Core\Security; /** @@ -489,34 +488,4 @@ class Project extends Base $v->getErrors() ); } - - /** - * Attach events - * - * @access public - */ - public function attachEvents() - { - $events = array( - Task::EVENT_CREATE_UPDATE, - Task::EVENT_CLOSE, - Task::EVENT_OPEN, - Task::EVENT_MOVE_COLUMN, - Task::EVENT_MOVE_POSITION, - Task::EVENT_ASSIGNEE_CHANGE, - GithubWebhook::EVENT_ISSUE_OPENED, - GithubWebhook::EVENT_ISSUE_CLOSED, - GithubWebhook::EVENT_ISSUE_REOPENED, - GithubWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE, - GithubWebhook::EVENT_ISSUE_LABEL_CHANGE, - GithubWebhook::EVENT_ISSUE_COMMENT, - GithubWebhook::EVENT_COMMIT, - ); - - $listener = new ProjectModificationDateListener($this->container); - - foreach ($events as $event_name) { - $this->event->attach($event_name, $listener); - } - } } diff --git a/app/Model/ProjectActivity.php b/app/Model/ProjectActivity.php index 000dfa09..b0a079dc 100644 --- a/app/Model/ProjectActivity.php +++ b/app/Model/ProjectActivity.php @@ -3,7 +3,6 @@ namespace Model; use Core\Template; -use Event\ProjectActivityListener; /** * Project activity model @@ -127,34 +126,6 @@ class ProjectActivity extends Base } /** - * Attach events to be able to record the history - * - * @access public - */ - public function attachEvents() - { - $events = array( - Task::EVENT_ASSIGNEE_CHANGE, - Task::EVENT_UPDATE, - Task::EVENT_CREATE, - Task::EVENT_CLOSE, - Task::EVENT_OPEN, - Task::EVENT_MOVE_COLUMN, - Task::EVENT_MOVE_POSITION, - Comment::EVENT_UPDATE, - Comment::EVENT_CREATE, - SubTask::EVENT_UPDATE, - SubTask::EVENT_CREATE, - ); - - $listener = new ProjectActivityListener($this->container); - - foreach ($events as $event_name) { - $this->event->attach($event_name, $listener); - } - } - - /** * Get the event html content * * @access public diff --git a/app/Model/ProjectDailySummary.php b/app/Model/ProjectDailySummary.php index 0ed3c02b..6c29758a 100644 --- a/app/Model/ProjectDailySummary.php +++ b/app/Model/ProjectDailySummary.php @@ -3,7 +3,6 @@ namespace Model; use Core\Template; -use Event\ProjectDailySummaryListener; /** * Project daily summary @@ -157,25 +156,4 @@ class ProjectDailySummary extends Base return $metrics; } - - /** - * Attach events to be able to record the metrics - * - * @access public - */ - public function attachEvents() - { - $events = array( - Task::EVENT_CREATE, - Task::EVENT_CLOSE, - Task::EVENT_OPEN, - Task::EVENT_MOVE_COLUMN, - ); - - $listener = new ProjectDailySummaryListener($this->container); - - foreach ($events as $event_name) { - $this->event->attach($event_name, $listener); - } - } } diff --git a/app/Model/SubTask.php b/app/Model/SubTask.php index f301ad62..12558429 100644 --- a/app/Model/SubTask.php +++ b/app/Model/SubTask.php @@ -2,6 +2,7 @@ namespace Model; +use Event\SubtaskEvent; use SimpleValidator\Validator; use SimpleValidator\Validators; @@ -146,7 +147,10 @@ class SubTask extends Base $subtask_id = $this->persist(self::TABLE, $values); if ($subtask_id) { - $this->event->trigger(self::EVENT_CREATE, array('id' => $subtask_id) + $values); + $this->container['dispatcher']->dispatch( + self::EVENT_CREATE, + new SubtaskEvent(array('id' => $subtask_id) + $values) + ); } return $subtask_id; @@ -165,7 +169,10 @@ class SubTask extends Base $result = $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values); if ($result) { - $this->event->trigger(self::EVENT_UPDATE, $values); + $this->container['dispatcher']->dispatch( + self::EVENT_UPDATE, + new SubtaskEvent($values) + ); } return $result; diff --git a/app/Model/Task.php b/app/Model/Task.php index 3cd03741..bc2913ec 100644 --- a/app/Model/Task.php +++ b/app/Model/Task.php @@ -30,6 +30,7 @@ class Task extends Base * * @var string */ + const EVENT_MOVE_PROJECT = 'task.move.project'; const EVENT_MOVE_COLUMN = 'task.move.column'; const EVENT_MOVE_POSITION = 'task.move.position'; const EVENT_MOVE_SWIMLANE = 'task.move.swimlane'; diff --git a/app/Model/TaskCreation.php b/app/Model/TaskCreation.php index de9f7ce1..6a2c0f9c 100644 --- a/app/Model/TaskCreation.php +++ b/app/Model/TaskCreation.php @@ -2,6 +2,8 @@ namespace Model; +use Event\TaskEvent; + /** * Task Creation * @@ -64,7 +66,7 @@ class TaskCreation extends Base private function fireEvents($task_id, array $values) { $values['task_id'] = $task_id; - $this->event->trigger(Task::EVENT_CREATE_UPDATE, $values); - $this->event->trigger(Task::EVENT_CREATE, $values); + $this->container['dispatcher']->dispatch(Task::EVENT_CREATE_UPDATE, new TaskEvent($values)); + $this->container['dispatcher']->dispatch(Task::EVENT_CREATE, new TaskEvent($values)); } } diff --git a/app/Model/TaskDuplication.php b/app/Model/TaskDuplication.php index 2410213b..172edb9f 100644 --- a/app/Model/TaskDuplication.php +++ b/app/Model/TaskDuplication.php @@ -2,6 +2,8 @@ namespace Model; +use Event\TaskEvent; + /** * Task Duplication * @@ -84,7 +86,14 @@ class TaskDuplication extends Base $this->checkDestinationProjectValues($values); - return $this->db->table(Task::TABLE)->eq('id', $task['id'])->update($values); + if ($this->db->table(Task::TABLE)->eq('id', $task['id'])->update($values)) { + $this->container['dispatcher']->dispatch( + Task::EVENT_MOVE_PROJECT, + new TaskEvent(array_merge($task, $values, array('task_id' => $task['id']))) + ); + } + + return true; } /** diff --git a/app/Model/TaskModification.php b/app/Model/TaskModification.php index b165ea24..dac52334 100644 --- a/app/Model/TaskModification.php +++ b/app/Model/TaskModification.php @@ -2,6 +2,8 @@ namespace Model; +use Event\TaskEvent; + /** * Task Modification * @@ -15,17 +17,16 @@ class TaskModification extends Base * * @access public * @param array $values - * @param boolean $fire_events * @return boolean */ - public function update(array $values, $fire_events = true) + public function update(array $values) { $original_task = $this->taskFinder->getById($values['id']); $this->prepare($values); $result = $this->db->table(Task::TABLE)->eq('id', $original_task['id'])->update($values); - if ($result && $fire_events) { + if ($result) { $this->fireEvents($original_task, $values); } @@ -51,7 +52,7 @@ class TaskModification extends Base } foreach ($events as $event) { - $this->event->trigger($event, $event_data); + $this->container['dispatcher']->dispatch($event, new TaskEvent($event_data)); } } diff --git a/app/Model/TaskPosition.php b/app/Model/TaskPosition.php index 9a9642e5..e5152b0b 100644 --- a/app/Model/TaskPosition.php +++ b/app/Model/TaskPosition.php @@ -2,6 +2,8 @@ namespace Model; +use Event\TaskEvent; + /** * Task Position * @@ -139,13 +141,13 @@ class TaskPosition extends Base ); if ($task['swimlane_id'] != $new_swimlane_id) { - $this->event->trigger(Task::EVENT_MOVE_SWIMLANE, $event_data); + $this->container['dispatcher']->dispatch(Task::EVENT_MOVE_SWIMLANE, new TaskEvent($event_data)); } else if ($task['column_id'] != $new_column_id) { - $this->event->trigger(Task::EVENT_MOVE_COLUMN, $event_data); + $this->container['dispatcher']->dispatch(Task::EVENT_MOVE_COLUMN, new TaskEvent($event_data)); } else if ($task['position'] != $new_position) { - $this->event->trigger(Task::EVENT_MOVE_POSITION, $event_data); + $this->container['dispatcher']->dispatch(Task::EVENT_MOVE_POSITION, new TaskEvent($event_data)); } } diff --git a/app/Model/TaskStatus.php b/app/Model/TaskStatus.php index 99faffde..225b3933 100644 --- a/app/Model/TaskStatus.php +++ b/app/Model/TaskStatus.php @@ -2,6 +2,8 @@ namespace Model; +use Event\TaskEvent; + /** * Task Status * @@ -84,9 +86,9 @@ class TaskStatus extends Base )); if ($result) { - $this->event->trigger( + $this->container['dispatcher']->dispatch( $event, - array('task_id' => $task_id) + $this->taskFinder->getById($task_id) + new TaskEvent(array('task_id' => $task_id) + $this->taskFinder->getById($task_id)) ); } diff --git a/app/Model/Webhook.php b/app/Model/Webhook.php index 14d50684..7edffa6e 100644 --- a/app/Model/Webhook.php +++ b/app/Model/Webhook.php @@ -2,8 +2,6 @@ namespace Model; -use Event\WebhookListener; - /** * Webhook model * @@ -34,87 +32,6 @@ class Webhook extends Base const HTTP_USER_AGENT = 'Kanboard Webhook'; /** - * URL to call for task creation - * - * @access private - * @var string - */ - private $url_task_creation = ''; - - /** - * URL to call for task modification - * - * @access private - * @var string - */ - private $url_task_modification = ''; - - /** - * Webook token - * - * @access private - * @var string - */ - private $token = ''; - - /** - * Attach events - * - * @access public - */ - public function attachEvents() - { - $this->url_task_creation = $this->config->get('webhook_url_task_creation'); - $this->url_task_modification = $this->config->get('webhook_url_task_modification'); - $this->token = $this->config->get('webhook_token'); - - if ($this->url_task_creation) { - $this->attachCreateEvents(); - } - - if ($this->url_task_modification) { - $this->attachUpdateEvents(); - } - } - - /** - * Attach events for task modification - * - * @access public - */ - public function attachUpdateEvents() - { - $events = array( - Task::EVENT_UPDATE, - Task::EVENT_CLOSE, - Task::EVENT_OPEN, - Task::EVENT_MOVE_COLUMN, - Task::EVENT_MOVE_POSITION, - Task::EVENT_ASSIGNEE_CHANGE, - ); - - $listener = new WebhookListener($this->container); - $listener->setUrl($this->url_task_modification); - - foreach ($events as $event_name) { - $this->event->attach($event_name, $listener); - } - } - - /** - * Attach events for task creation - * - * @access public - */ - public function attachCreateEvents() - { - $listener = new WebhookListener($this->container); - $listener->setUrl($this->url_task_creation); - - $this->event->attach(Task::EVENT_CREATE, $listener); - } - - /** * Call the external URL * * @access public @@ -123,6 +40,8 @@ class Webhook extends Base */ public function notify($url, array $task) { + $token = $this->config->get('webhook_token'); + $headers = array( 'Connection: close', 'User-Agent: '.self::HTTP_USER_AGENT, @@ -140,10 +59,10 @@ class Webhook extends Base )); if (strpos($url, '?') !== false) { - $url .= '&token='.$this->token; + $url .= '&token='.$token; } else { - $url .= '?token='.$this->token; + $url .= '?token='.$token; } @file_get_contents($url, false, $context); diff --git a/app/ServiceProvider/Database.php b/app/ServiceProvider/DatabaseProvider.php index 75e1f73e..fa5319a0 100644 --- a/app/ServiceProvider/Database.php +++ b/app/ServiceProvider/DatabaseProvider.php @@ -4,9 +4,9 @@ namespace ServiceProvider; use Pimple\Container; use Pimple\ServiceProviderInterface; -use PicoDb\Database as Dbal; +use PicoDb\Database; -class Database implements ServiceProviderInterface +class DatabaseProvider implements ServiceProviderInterface { public function register(Container $container) { @@ -55,7 +55,7 @@ class Database implements ServiceProviderInterface { require_once __DIR__.'/../Schema/Sqlite.php'; - return new Dbal(array( + return new Database(array( 'driver' => 'sqlite', 'filename' => DB_FILENAME )); @@ -70,7 +70,7 @@ class Database implements ServiceProviderInterface { require_once __DIR__.'/../Schema/Mysql.php'; - return new Dbal(array( + return new Database(array( 'driver' => 'mysql', 'hostname' => DB_HOSTNAME, 'username' => DB_USERNAME, @@ -89,7 +89,7 @@ class Database implements ServiceProviderInterface { require_once __DIR__.'/../Schema/Postgres.php'; - return new Dbal(array( + return new Database(array( 'driver' => 'postgres', 'hostname' => DB_HOSTNAME, 'username' => DB_USERNAME, diff --git a/app/ServiceProvider/Event.php b/app/ServiceProvider/Event.php deleted file mode 100644 index 0436aa7b..00000000 --- a/app/ServiceProvider/Event.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -namespace ServiceProvider; - -use Pimple\Container; -use Pimple\ServiceProviderInterface; -use Core\Event as EventDispatcher; - -class Event implements ServiceProviderInterface -{ - public function register(Container $container) - { - $container['event'] = new EventDispatcher; - } -} diff --git a/app/ServiceProvider/EventDispatcherProvider.php b/app/ServiceProvider/EventDispatcherProvider.php new file mode 100644 index 00000000..90210ba6 --- /dev/null +++ b/app/ServiceProvider/EventDispatcherProvider.php @@ -0,0 +1,28 @@ +<?php + +namespace ServiceProvider; + +use Pimple\Container; +use Pimple\ServiceProviderInterface; +use Subscriber\NotificationSubscriber; +use Subscriber\ProjectActivitySubscriber; +use Subscriber\ProjectDailySummarySubscriber; +use Subscriber\ProjectModificationDateSubscriber; +use Subscriber\WebhookSubscriber; +use Symfony\Component\EventDispatcher\EventDispatcher; + +class EventDispatcherProvider implements ServiceProviderInterface +{ + public function register(Container $container) + { + $container['dispatcher'] = new EventDispatcher; + $container['dispatcher']->addSubscriber(new ProjectActivitySubscriber($container)); + $container['dispatcher']->addSubscriber(new ProjectDailySummarySubscriber($container)); + $container['dispatcher']->addSubscriber(new ProjectModificationDateSubscriber($container)); + $container['dispatcher']->addSubscriber(new WebhookSubscriber($container)); + $container['dispatcher']->addSubscriber(new NotificationSubscriber($container)); + + // Automatic actions + $container['action']->attachEvents(); + } +} diff --git a/app/ServiceProvider/Logging.php b/app/ServiceProvider/LoggingProvider.php index 9737cadc..93f55a9c 100644 --- a/app/ServiceProvider/Logging.php +++ b/app/ServiceProvider/LoggingProvider.php @@ -8,7 +8,7 @@ use Monolog\Logger; use Monolog\Handler\StreamHandler; use Monolog\Handler\SyslogHandler; -class Logging implements ServiceProviderInterface +class LoggingProvider implements ServiceProviderInterface { public function register(Container $container) { diff --git a/app/ServiceProvider/Mailer.php b/app/ServiceProvider/MailerProvider.php index c82c16f6..f6b71363 100644 --- a/app/ServiceProvider/Mailer.php +++ b/app/ServiceProvider/MailerProvider.php @@ -8,7 +8,7 @@ use Swift_SmtpTransport; use Swift_SendmailTransport; use Swift_MailTransport; -class Mailer implements ServiceProviderInterface +class MailerProvider implements ServiceProviderInterface { public function register(Container $container) { diff --git a/app/ServiceProvider/ModelProvider.php b/app/ServiceProvider/ModelProvider.php new file mode 100644 index 00000000..1a940058 --- /dev/null +++ b/app/ServiceProvider/ModelProvider.php @@ -0,0 +1,63 @@ +<?php + +namespace ServiceProvider; + +use Model\Config; +use Model\Project; +use Model\Webhook; +use Pimple\Container; +use Pimple\ServiceProviderInterface; + +class ModelProvider implements ServiceProviderInterface +{ + private $models = array( + 'Acl', + 'Action', + 'Authentication', + 'Board', + 'Category', + 'Color', + 'Comment', + 'Config', + 'DateParser', + 'File', + 'GithubWebhook', + 'LastLogin', + 'Notification', + 'Project', + 'ProjectActivity', + 'ProjectAnalytics', + 'ProjectDailySummary', + 'ProjectPaginator', + 'ProjectPermission', + 'SubTask', + 'SubtaskPaginator', + 'Swimlane', + 'Task', + 'TaskCreation', + 'TaskDuplication', + 'TaskExport', + 'TaskFinder', + 'TaskModification', + 'TaskPaginator', + 'TaskPermission', + 'TaskPosition', + 'TaskStatus', + 'TaskValidator', + 'TimeTracking', + 'User', + 'Webhook', + ); + + public function register(Container $container) + { + foreach ($this->models as $model) { + + $class = '\Model\\'.$model; + + $container[lcfirst($model)] = function ($c) use ($class) { + return new $class($c); + }; + } + } +} diff --git a/app/Subscriber/Base.php b/app/Subscriber/Base.php new file mode 100644 index 00000000..1ed15327 --- /dev/null +++ b/app/Subscriber/Base.php @@ -0,0 +1,47 @@ +<?php + +namespace Subscriber; + +use Event\TaskEvent; +use Model\Task; +use Pimple\Container; + +/** + * Base subscriber class + * + * @package subscriber + * @author Frederic Guillot + */ +abstract class Base +{ + /** + * Container instance + * + * @access protected + * @var \Pimple\Container + */ + protected $container; + + /** + * Constructor + * + * @access public + * @param \Pimple\Container $container + */ + public function __construct(Container $container) + { + $this->container = $container; + } + + /** + * Load automatically models + * + * @access public + * @param string $name Model name + * @return mixed + */ + public function __get($name) + { + return $this->container[$name]; + } +} diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php new file mode 100644 index 00000000..4412636f --- /dev/null +++ b/app/Subscriber/NotificationSubscriber.php @@ -0,0 +1,81 @@ +<?php + +namespace Subscriber; + +use Event\GenericEvent; +use Model\Task; +use Model\Comment; +use Model\SubTask; +use Model\File; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +class NotificationSubscriber extends Base implements EventSubscriberInterface +{ + private $templates = array( + Task::EVENT_CREATE => 'task_creation', + Task::EVENT_UPDATE => 'task_update', + Task::EVENT_CLOSE => 'task_close', + Task::EVENT_OPEN => 'task_open', + Task::EVENT_MOVE_COLUMN => 'task_move_column', + Task::EVENT_MOVE_POSITION => 'task_move_position', + Task::EVENT_ASSIGNEE_CHANGE => 'task_assignee_change', + SubTask::EVENT_CREATE => 'subtask_creation', + SubTask::EVENT_UPDATE => 'subtask_update', + Comment::EVENT_CREATE => 'comment_creation', + Comment::EVENT_UPDATE => 'comment_update', + File::EVENT_CREATE => 'file_creation', + ); + + public static function getSubscribedEvents() + { + return array( + Task::EVENT_CREATE => array('execute', 0), + Task::EVENT_UPDATE => array('execute', 0), + Task::EVENT_CLOSE => array('execute', 0), + Task::EVENT_OPEN => array('execute', 0), + Task::EVENT_MOVE_COLUMN => array('execute', 0), + Task::EVENT_MOVE_POSITION => array('execute', 0), + Task::EVENT_ASSIGNEE_CHANGE => array('execute', 0), + SubTask::EVENT_CREATE => array('execute', 0), + SubTask::EVENT_UPDATE => array('execute', 0), + Comment::EVENT_CREATE => array('execute', 0), + Comment::EVENT_UPDATE => array('execute', 0), + File::EVENT_CREATE => array('execute', 0), + ); + } + + public function execute(GenericEvent $event) + { + $values = $this->getTemplateData($event); + $users = $this->notification->getUsersList($values['task']['project_id']); + + if ($users) { + $this->notification->sendEmails($this->templates[$event->getName()], $users, $values); + } + } + + public function getTemplateData(GenericEvent $event) + { + $values = array(); + + switch (get_class($event)) { + case 'Event\TaskEvent': + $values['task'] = $this->taskFinder->getDetails($event['task_id']); + break; + case 'Event\SubtaskEvent': + $values['subtask'] = $this->subTask->getById($event['id'], true); + $values['task'] = $this->taskFinder->getDetails($event['task_id']); + break; + case 'Event\FileEvent': + $values['file'] = $event->getAll(); + $values['task'] = $this->taskFinder->getDetails($event['task_id']); + break; + case 'Event\CommentEvent': + $values['comment'] = $this->comment->getById($event['id']); + $values['task'] = $this->taskFinder->getDetails($values['comment']['task_id']); + break; + } + + return $values; + } +} diff --git a/app/Subscriber/ProjectActivitySubscriber.php b/app/Subscriber/ProjectActivitySubscriber.php new file mode 100644 index 00000000..1aca8539 --- /dev/null +++ b/app/Subscriber/ProjectActivitySubscriber.php @@ -0,0 +1,63 @@ +<?php + +namespace Subscriber; + +use Event\GenericEvent; +use Model\Task; +use Model\Comment; +use Model\SubTask; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +class ProjectActivitySubscriber extends Base implements EventSubscriberInterface +{ + public static function getSubscribedEvents() + { + return array( + Task::EVENT_ASSIGNEE_CHANGE => array('execute', 0), + Task::EVENT_UPDATE => array('execute', 0), + Task::EVENT_CREATE => array('execute', 0), + Task::EVENT_CLOSE => array('execute', 0), + Task::EVENT_OPEN => array('execute', 0), + Task::EVENT_MOVE_COLUMN => array('execute', 0), + Task::EVENT_MOVE_POSITION => array('execute', 0), + Comment::EVENT_UPDATE => array('execute', 0), + Comment::EVENT_CREATE => array('execute', 0), + SubTask::EVENT_UPDATE => array('execute', 0), + SubTask::EVENT_CREATE => array('execute', 0), + ); + } + + public function execute(GenericEvent $event) + { + // Executed only when someone is logged + if ($this->container['acl']->isLogged() && isset($event['task_id'])) { + + $values = $this->getValues($event); + + $this->projectActivity->createEvent( + $values['task']['project_id'], + $values['task']['id'], + $this->acl->getUserId(), + $event->getName(), + $values + ); + } + } + + private function getValues(GenericEvent $event) + { + $values = array(); + $values['task'] = $this->taskFinder->getDetails($event['task_id']); + + switch (get_class($event)) { + case 'Event\SubtaskEvent': + $values['subtask'] = $this->subTask->getById($event['id'], true); + break; + case 'Event\CommentEvent': + $values['comment'] = $this->comment->getById($event['id']); + break; + } + + return $values; + } +} diff --git a/app/Subscriber/ProjectDailySummarySubscriber.php b/app/Subscriber/ProjectDailySummarySubscriber.php new file mode 100644 index 00000000..6d737734 --- /dev/null +++ b/app/Subscriber/ProjectDailySummarySubscriber.php @@ -0,0 +1,27 @@ +<?php + +namespace Subscriber; + +use Event\TaskEvent; +use Model\Task; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +class ProjectDailySummarySubscriber extends Base implements EventSubscriberInterface +{ + public static function getSubscribedEvents() + { + return array( + Task::EVENT_CREATE => array('execute', 0), + Task::EVENT_CLOSE => array('execute', 0), + Task::EVENT_OPEN => array('execute', 0), + Task::EVENT_MOVE_COLUMN => array('execute', 0), + ); + } + + public function execute(TaskEvent $event) + { + if (isset($event['project_id'])) { + $this->projectDailySummary->updateTotals($event['project_id'], date('Y-m-d')); + } + } +} diff --git a/app/Subscriber/ProjectModificationDateSubscriber.php b/app/Subscriber/ProjectModificationDateSubscriber.php new file mode 100644 index 00000000..3d5484f7 --- /dev/null +++ b/app/Subscriber/ProjectModificationDateSubscriber.php @@ -0,0 +1,38 @@ +<?php + +namespace Subscriber; + +use Event\GenericEvent; +use Model\Task; +use Model\GithubWebhook; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +class ProjectModificationDateSubscriber extends Base implements EventSubscriberInterface +{ + public static function getSubscribedEvents() + { + return array( + Task::EVENT_CREATE_UPDATE => array('execute', 0), + Task::EVENT_CLOSE => array('execute', 0), + Task::EVENT_OPEN => array('execute', 0), + Task::EVENT_MOVE_COLUMN => array('execute', 0), + Task::EVENT_MOVE_POSITION => array('execute', 0), + Task::EVENT_MOVE_PROJECT => array('execute', 0), + Task::EVENT_ASSIGNEE_CHANGE => array('execute', 0), + GithubWebhook::EVENT_ISSUE_OPENED => array('execute', 0), + GithubWebhook::EVENT_ISSUE_CLOSED => array('execute', 0), + GithubWebhook::EVENT_ISSUE_REOPENED => array('execute', 0), + GithubWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE => array('execute', 0), + GithubWebhook::EVENT_ISSUE_LABEL_CHANGE => array('execute', 0), + GithubWebhook::EVENT_ISSUE_COMMENT => array('execute', 0), + GithubWebhook::EVENT_COMMIT => array('execute', 0), + ); + } + + public function execute(GenericEvent $event) + { + if (isset($event['project_id'])) { + $this->project->updateModificationDate($event['project_id']); + } + } +} diff --git a/app/Subscriber/WebhookSubscriber.php b/app/Subscriber/WebhookSubscriber.php new file mode 100644 index 00000000..20d765e2 --- /dev/null +++ b/app/Subscriber/WebhookSubscriber.php @@ -0,0 +1,42 @@ +<?php + +namespace Subscriber; + +use Event\TaskEvent; +use Model\Task; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +class WebhookSubscriber extends Base implements EventSubscriberInterface +{ + public static function getSubscribedEvents() + { + return array( + Task::EVENT_CREATE => array('onTaskCreation', 0), + Task::EVENT_UPDATE => array('onTaskModification', 0), + Task::EVENT_CLOSE => array('onTaskModification', 0), + Task::EVENT_OPEN => array('onTaskModification', 0), + Task::EVENT_MOVE_COLUMN => array('onTaskModification', 0), + Task::EVENT_MOVE_POSITION => array('onTaskModification', 0), + Task::EVENT_ASSIGNEE_CHANGE => array('onTaskModification', 0), + ); + } + + public function onTaskCreation(TaskEvent $event) + { + $this->executeRequest('webhook_url_task_creation'); + } + + public function onTaskModification(TaskEvent $event) + { + $this->executeRequest('webhook_url_task_modification'); + } + + public function executeRequest($parameter) + { + $url = $this->config->get($parameter); + + if (! empty($url)) { + $this->webhook->notify($url, $event->getAll()); + } + } +} diff --git a/app/common.php b/app/common.php index addfe874..14d8f8ba 100644 --- a/app/common.php +++ b/app/common.php @@ -10,7 +10,11 @@ if (file_exists('config.php')) { require __DIR__.'/constants.php'; $container = new Pimple\Container; -$container->register(new ServiceProvider\Logging); -$container->register(new ServiceProvider\Database); -$container->register(new ServiceProvider\Event); -$container->register(new ServiceProvider\Mailer); +$container->register(new ServiceProvider\LoggingProvider); +$container->register(new ServiceProvider\DatabaseProvider); +$container->register(new ServiceProvider\ModelProvider); +$container->register(new ServiceProvider\EventDispatcherProvider); +$container->register(new ServiceProvider\MailerProvider); + +$container['config']->setupTranslations(); +$container['config']->setupTimezone(); diff --git a/composer.json b/composer.json index e62150ff..aa37e165 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,8 @@ "lusitanian/oauth": "0.3.5", "pimple/pimple": "~3.0", "monolog/monolog": "1.11.0", - "symfony/console": "@stable" + "symfony/console": "@stable", + "symfony/event-dispatcher": "~2.6" }, "autoload": { "psr-0": {"": "app/"}, @@ -17,5 +18,8 @@ "app/helpers.php", "app/functions.php" ] + }, + "require-dev": { + "symfony/stopwatch": "~2.6" } } diff --git a/composer.lock b/composer.lock index 9f5d9ae9..6a456880 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "0e4e7b65c1a5eb4ab8bd2fc051c9dc3d", + "hash": "eb21652f9ba05c40d2c904bbf9113c69", "packages": [ { "name": "erusev/parsedown", @@ -521,9 +521,115 @@ "description": "Symfony Console Component", "homepage": "http://symfony.com", "time": "2014-12-02 20:19:20" + }, + { + "name": "symfony/event-dispatcher", + "version": "v2.6.1", + "target-dir": "Symfony/Component/EventDispatcher", + "source": { + "type": "git", + "url": "https://github.com/symfony/EventDispatcher.git", + "reference": "720fe9bca893df7ad1b4546649473b5afddf0216" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/720fe9bca893df7ad1b4546649473b5afddf0216", + "reference": "720fe9bca893df7ad1b4546649473b5afddf0216", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.0", + "symfony/dependency-injection": "~2.6", + "symfony/expression-language": "~2.6", + "symfony/stopwatch": "~2.2" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "http://symfony.com", + "time": "2014-12-02 20:19:20" + } + ], + "packages-dev": [ + { + "name": "symfony/stopwatch", + "version": "v2.6.1", + "target-dir": "Symfony/Component/Stopwatch", + "source": { + "type": "git", + "url": "https://github.com/symfony/Stopwatch.git", + "reference": "261abd360cfb6ac65ea93ffd82073e2011d034fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/261abd360cfb6ac65ea93ffd82073e2011d034fc", + "reference": "261abd360cfb6ac65ea93ffd82073e2011d034fc", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Stopwatch\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Stopwatch Component", + "homepage": "http://symfony.com", + "time": "2014-12-02 20:19:20" } ], - "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": { diff --git a/jsonrpc.php b/jsonrpc.php index c2d216cf..2153e0ee 100644 --- a/jsonrpc.php +++ b/jsonrpc.php @@ -2,69 +2,28 @@ require __DIR__.'/app/common.php'; -$models = array( - 'Config', - 'Project', - 'ProjectPermission', - 'Task', - 'TaskCreation', - 'TaskModification', - 'TaskFinder', - 'TaskPosition', - 'TaskStatus', - 'TaskValidator', - 'User', - 'Category', - 'Comment', - 'SubTask', - 'Board', - 'Action', - 'Webhook', - 'Notification', -); - -$events = array( - 'actionModel', - 'projectModel', - 'webhookModel', - 'notificationModel', -); - -foreach ($models as $model) { - $variable = lcfirst($model).'Model'; - $class = '\Model\\'.$model; - $$variable = new $class($container); -} - -foreach ($events as $class) { - $$class->attachEvents(); -} - -$configModel->setupTranslations(); -$configModel->setupTimezone(); - $server = new JsonRPC\Server; -$server->authentication(array('jsonrpc' => $configModel->get('api_token'))); +$server->authentication(array('jsonrpc' => $container['config']->get('api_token'))); /** * Project procedures */ -$server->bind('getProjectById', $projectModel, 'getById'); -$server->bind('getProjectByName', $projectModel, 'getByName'); -$server->bind('getAllProjects', $projectModel, 'getAll'); -$server->bind('removeProject', $projectModel, 'remove'); -$server->bind('enableProject', $projectModel, 'enable'); -$server->bind('disableProject', $projectModel, 'disable'); -$server->bind('enableProjectPublicAccess', $projectModel, 'enablePublicAccess'); -$server->bind('disableProjectPublicAccess', $projectModel, 'disablePublicAccess'); - -$server->register('createProject', function($name) use ($projectModel) { +$server->bind('getProjectById', $container['project'], 'getById'); +$server->bind('getProjectByName', $container['project'], 'getByName'); +$server->bind('getAllProjects', $container['project'], 'getAll'); +$server->bind('removeProject', $container['project'], 'remove'); +$server->bind('enableProject', $container['project'], 'enable'); +$server->bind('disableProject', $container['project'], 'disable'); +$server->bind('enableProjectPublicAccess', $container['project'], 'enablePublicAccess'); +$server->bind('disableProjectPublicAccess', $container['project'], 'disablePublicAccess'); + +$server->register('createProject', function($name) use ($container) { $values = array('name' => $name); - list($valid,) = $projectModel->validateCreation($values); - return $valid ? $projectModel->create($values) : false; + list($valid,) = $container['project']->validateCreation($values); + return $valid ? $container['project']->create($values) : false; }); -$server->register('updateProject', function($id, $name, $is_active = null, $is_public = null, $token = null) use ($projectModel) { +$server->register('updateProject', function($id, $name, $is_active = null, $is_public = null, $token = null) use ($container) { $values = array( 'id' => $id, @@ -80,40 +39,40 @@ $server->register('updateProject', function($id, $name, $is_active = null, $is_p } } - list($valid,) = $projectModel->validateModification($values); - return $valid && $projectModel->update($values); + list($valid,) = $container['project']->validateModification($values); + return $valid && $container['project']->update($values); }); /** * Board procedures */ -$server->bind('getBoard', $boardModel, 'getBoard'); -$server->bind('getColumns', $boardModel, 'getColumns'); -$server->bind('getColumn', $boardModel, 'getColumn'); -$server->bind('moveColumnUp', $boardModel, 'moveUp'); -$server->bind('moveColumnDown', $boardModel, 'moveDown'); -$server->bind('updateColumn', $boardModel, 'updateColumn'); -$server->bind('addColumn', $boardModel, 'addColumn'); -$server->bind('removeColumn', $boardModel, 'removeColumn'); +$server->bind('getBoard', $container['board'], 'getBoard'); +$server->bind('getColumns', $container['board'], 'getColumns'); +$server->bind('getColumn', $container['board'], 'getColumn'); +$server->bind('moveColumnUp', $container['board'], 'moveUp'); +$server->bind('moveColumnDown', $container['board'], 'moveDown'); +$server->bind('updateColumn', $container['board'], 'updateColumn'); +$server->bind('addColumn', $container['board'], 'addColumn'); +$server->bind('removeColumn', $container['board'], 'removeColumn'); /** * Project permissions procedures */ -$server->bind('getMembers', $projectPermissionModel, 'getMembers'); -$server->bind('revokeUser', $projectPermissionModel, 'revokeUser'); -$server->bind('allowUser', $projectPermissionModel, 'allowUser'); +$server->bind('getMembers', $container['projectPermission'], 'getMembers'); +$server->bind('revokeUser', $container['projectPermission'], 'revokeUser'); +$server->bind('allowUser', $container['projectPermission'], 'allowUser'); /** * Task procedures */ -$server->bind('getTask', $taskFinderModel, 'getById'); -$server->bind('getAllTasks', $taskFinderModel, 'getAll'); -$server->bind('openTask', $taskStatusModel, 'open'); -$server->bind('closeTask', $taskStatusModel, 'close'); -$server->bind('removeTask', $taskModel, 'remove'); -$server->bind('moveTaskPosition', $taskPositionModel, 'movePosition'); +$server->bind('getTask', $container['taskFinder'], 'getById'); +$server->bind('getAllTasks', $container['taskFinder'], 'getAll'); +$server->bind('openTask', $container['taskStatus'], 'open'); +$server->bind('closeTask', $container['taskStatus'], 'close'); +$server->bind('removeTask', $container['task'], 'remove'); +$server->bind('moveTaskPosition', $container['taskPosition'], 'movePosition'); -$server->register('createTask', function($title, $project_id, $color_id = '', $column_id = 0, $owner_id = 0, $creator_id = 0, $date_due = '', $description = '', $category_id = 0, $score = 0, $swimlane_id = 0) use ($taskCreationModel, $taskValidatorModel) { +$server->register('createTask', function($title, $project_id, $color_id = '', $column_id = 0, $owner_id = 0, $creator_id = 0, $date_due = '', $description = '', $category_id = 0, $score = 0, $swimlane_id = 0) use ($container) { $values = array( 'title' => $title, @@ -129,16 +88,16 @@ $server->register('createTask', function($title, $project_id, $color_id = '', $c 'swimlane_id' => $swimlane_id, ); - list($valid,) = $taskValidatorModel->validateCreation($values); + list($valid,) = $container['taskValidator']->validateCreation($values); if (! $valid) { return false; } - return $taskCreationModel->create($values); + return $container['taskCreation']->create($values); }); -$server->register('updateTask', function($id, $title = null, $project_id = null, $color_id = null, $column_id = null, $owner_id = null, $creator_id = null, $date_due = null, $description = null, $category_id = null, $score = null, $swimlane_id = null) use ($taskModificationModel, $taskValidatorModel) { +$server->register('updateTask', function($id, $title = null, $project_id = null, $color_id = null, $column_id = null, $owner_id = null, $creator_id = null, $date_due = null, $description = null, $category_id = null, $score = null, $swimlane_id = null) use ($container) { $values = array( 'id' => $id, @@ -161,19 +120,19 @@ $server->register('updateTask', function($id, $title = null, $project_id = null, } } - list($valid) = $taskValidatorModel->validateApiModification($values); - return $valid && $taskModificationModel->update($values); + list($valid) = $container['taskValidator']->validateApiModification($values); + return $valid && $container['taskModification']->update($values); }); /** * User procedures */ -$server->bind('getUser', $userModel, 'getById'); -$server->bind('getAllUsers', $userModel, 'getAll'); -$server->bind('removeUser', $userModel, 'remove'); +$server->bind('getUser', $container['user'], 'getById'); +$server->bind('getAllUsers', $container['user'], 'getAll'); +$server->bind('removeUser', $container['user'], 'remove'); -$server->register('createUser', function($username, $password, $name = '', $email = '', $is_admin = 0, $default_project_id = 0) use ($userModel) { +$server->register('createUser', function($username, $password, $name = '', $email = '', $is_admin = 0, $default_project_id = 0) use ($container) { $values = array( 'username' => $username, @@ -185,16 +144,16 @@ $server->register('createUser', function($username, $password, $name = '', $emai 'default_project_id' => $default_project_id, ); - list($valid,) = $userModel->validateCreation($values); + list($valid,) = $container['user']->validateCreation($values); if (! $valid) { return false; } - return $userModel->create($values); + return $container['user']->create($values); }); -$server->register('updateUser', function($id, $username = null, $name = null, $email = null, $is_admin = null, $default_project_id = null) use ($userModel) { +$server->register('updateUser', function($id, $username = null, $name = null, $email = null, $is_admin = null, $default_project_id = null) use ($container) { $values = array( 'id' => $id, @@ -211,52 +170,52 @@ $server->register('updateUser', function($id, $username = null, $name = null, $e } } - list($valid,) = $userModel->validateApiModification($values); - return $valid && $userModel->update($values); + list($valid,) = $container['user']->validateApiModification($values); + return $valid && $container['user']->update($values); }); /** * Category procedures */ -$server->bind('getCategory', $categoryModel, 'getById'); -$server->bind('getAllCategories', $categoryModel, 'getAll'); -$server->bind('removeCategory', $categoryModel, 'remove'); +$server->bind('getCategory', $container['category'], 'getById'); +$server->bind('getAllCategories', $container['category'], 'getAll'); +$server->bind('removeCategory', $container['category'], 'remove'); -$server->register('createCategory', function($project_id, $name) use ($categoryModel) { +$server->register('createCategory', function($project_id, $name) use ($container) { $values = array( 'project_id' => $project_id, 'name' => $name, ); - list($valid,) = $categoryModel->validateCreation($values); + list($valid,) = $container['category']->validateCreation($values); if (! $valid) { return false; } - return $categoryModel->create($values); + return $container['category']->create($values); }); -$server->register('updateCategory', function($id, $name) use ($categoryModel) { +$server->register('updateCategory', function($id, $name) use ($container) { $values = array( 'id' => $id, 'name' => $name, ); - list($valid,) = $categoryModel->validateModification($values); - return $valid && $categoryModel->update($values); + list($valid,) = $container['category']->validateModification($values); + return $valid && $container['category']->update($values); }); /** * Comments procedures */ -$server->bind('getComment', $commentModel, 'getById'); -$server->bind('getAllComments', $commentModel, 'getAll'); -$server->bind('removeComment', $commentModel, 'remove'); +$server->bind('getComment', $container['comment'], 'getById'); +$server->bind('getAllComments', $container['comment'], 'getAll'); +$server->bind('removeComment', $container['comment'], 'remove'); -$server->register('createComment', function($task_id, $user_id, $content) use ($commentModel) { +$server->register('createComment', function($task_id, $user_id, $content) use ($container) { $values = array( 'task_id' => $task_id, @@ -264,34 +223,34 @@ $server->register('createComment', function($task_id, $user_id, $content) use ($ 'comment' => $content, ); - list($valid,) = $commentModel->validateCreation($values); + list($valid,) = $container['comment']->validateCreation($values); if (! $valid) { return false; } - return $commentModel->create($values); + return $container['comment']->create($values); }); -$server->register('updateComment', function($id, $content) use ($commentModel) { +$server->register('updateComment', function($id, $content) use ($container) { $values = array( 'id' => $id, 'comment' => $content, ); - list($valid,) = $commentModel->validateModification($values); - return $valid && $commentModel->update($values); + list($valid,) = $container['comment']->validateModification($values); + return $valid && $container['comment']->update($values); }); /** * Subtask procedures */ -$server->bind('getSubtask', $subTaskModel, 'getById'); -$server->bind('getAllSubtasks', $subTaskModel, 'getAll'); -$server->bind('removeSubtask', $subTaskModel, 'remove'); +$server->bind('getSubtask', $container['subTask'], 'getById'); +$server->bind('getAllSubtasks', $container['subTask'], 'getAll'); +$server->bind('removeSubtask', $container['subTask'], 'remove'); -$server->register('createSubtask', function($task_id, $title, $user_id = 0, $time_estimated = 0, $time_spent = 0, $status = 0) use ($subTaskModel) { +$server->register('createSubtask', function($task_id, $title, $user_id = 0, $time_estimated = 0, $time_spent = 0, $status = 0) use ($container) { $values = array( 'title' => $title, @@ -307,17 +266,16 @@ $server->register('createSubtask', function($task_id, $title, $user_id = 0, $tim unset($values[$key]); } } - - list($valid,) = $subTaskModel->validateCreation($values); + list($valid,) = $container['subTask']->validateCreation($values); if (! $valid) { return false; } - return $subTaskModel->create($values); + return $container['subTask']->create($values); }); -$server->register('updateSubtask', function($id, $task_id, $title = null, $user_id = null, $time_estimated = null, $time_spent = null, $status = null) use ($subTaskModel) { +$server->register('updateSubtask', function($id, $task_id, $title = null, $user_id = null, $time_estimated = null, $time_spent = null, $status = null) use ($container) { $values = array( 'id' => $id, @@ -335,15 +293,15 @@ $server->register('updateSubtask', function($id, $task_id, $title = null, $user_ } } - list($valid,) = $subTaskModel->validateApiModification($values); - return $valid && $subTaskModel->update($values); + list($valid,) = $container['subTask']->validateApiModification($values); + return $valid && $container['subTask']->update($values); }); /** * Application procedures */ -$server->register('getTimezone', function() use($configModel) { - return $configModel->get('application_timezone'); +$server->register('getTimezone', function() use ($container) { + return $container['config']->get('application_timezone'); }); /** diff --git a/tests/functionals/ApiTest.php b/tests/functionals/ApiTest.php index 3ce1fb19..eb1e0cd1 100644 --- a/tests/functionals/ApiTest.php +++ b/tests/functionals/ApiTest.php @@ -25,7 +25,7 @@ class Api extends PHPUnit_Framework_TestCase $pdo = new PDO('pgsql:host='.DB_HOSTNAME.';dbname='.DB_NAME, DB_USERNAME, DB_PASSWORD); } - $service = new ServiceProvider\Database; + $service = new ServiceProvider\DatabaseProvider; $service->getInstance(); $pdo->exec("UPDATE settings SET value='".API_KEY."' WHERE option='api_token'"); diff --git a/tests/units/ActionTaskAssignColorCategoryTest.php b/tests/units/ActionTaskAssignColorCategoryTest.php index ff41a4b9..c9665268 100644 --- a/tests/units/ActionTaskAssignColorCategoryTest.php +++ b/tests/units/ActionTaskAssignColorCategoryTest.php @@ -7,6 +7,7 @@ use Model\TaskCreation; use Model\TaskFinder; use Model\Project; use Model\Category; +use Event\GenericEvent; class ActionTaskAssignColorCategory extends Base { @@ -21,7 +22,7 @@ class ActionTaskAssignColorCategory extends Base ); $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testExecute() @@ -51,7 +52,7 @@ class ActionTaskAssignColorCategory extends Base ); // Our event should NOT be executed - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); // Our task should be assigned to the ategory_id=1 and have the green color $task = $tf->getById(1); @@ -69,7 +70,7 @@ class ActionTaskAssignColorCategory extends Base ); // Our event should be executed - $this->assertTrue($action->execute($event)); + $this->assertTrue($action->execute(new GenericEvent($event))); // Our task should have the blue color $task = $tf->getById(1); diff --git a/tests/units/ActionTaskAssignColorUserTest.php b/tests/units/ActionTaskAssignColorUserTest.php index d41a5ef4..c1bf3a34 100644 --- a/tests/units/ActionTaskAssignColorUserTest.php +++ b/tests/units/ActionTaskAssignColorUserTest.php @@ -6,6 +6,7 @@ use Model\Task; use Model\TaskCreation; use Model\TaskFinder; use Model\Project; +use Event\GenericEvent; class ActionTaskAssignColorUser extends Base { @@ -20,7 +21,7 @@ class ActionTaskAssignColorUser extends Base ); $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testExecute() @@ -44,7 +45,7 @@ class ActionTaskAssignColorUser extends Base ); // Our event should NOT be executed - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); // Our task should be assigned to nobody and have the green color $task = $tf->getById(1); @@ -60,7 +61,7 @@ class ActionTaskAssignColorUser extends Base ); // Our event should be executed - $this->assertTrue($action->execute($event)); + $this->assertTrue($action->execute(new GenericEvent($event))); // Our task should be assigned to nobody and have the blue color $task = $tf->getById(1); diff --git a/tests/units/ActionTaskAssignCurrentUserTest.php b/tests/units/ActionTaskAssignCurrentUserTest.php index afc659ce..374277ce 100644 --- a/tests/units/ActionTaskAssignCurrentUserTest.php +++ b/tests/units/ActionTaskAssignCurrentUserTest.php @@ -2,6 +2,7 @@ require_once __DIR__.'/Base.php'; +use Event\GenericEvent; use Model\Task; use Model\TaskCreation; use Model\TaskFinder; @@ -22,7 +23,7 @@ class ActionTaskAssignCurrentUser extends Base ); $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testBadColumn() @@ -36,7 +37,7 @@ class ActionTaskAssignCurrentUser extends Base 'column_id' => 3, ); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testExecute() @@ -65,7 +66,7 @@ class ActionTaskAssignCurrentUser extends Base ); // Our event should be executed - $this->assertTrue($action->execute($event)); + $this->assertTrue($action->execute(new GenericEvent($event))); // Our task should be assigned to the user 5 (from the session) $task = $tf->getById(1); diff --git a/tests/units/ActionTaskAssignSpecificUserTest.php b/tests/units/ActionTaskAssignSpecificUserTest.php index 07fa1e25..ac054ba6 100644 --- a/tests/units/ActionTaskAssignSpecificUserTest.php +++ b/tests/units/ActionTaskAssignSpecificUserTest.php @@ -2,6 +2,7 @@ require_once __DIR__.'/Base.php'; +use Event\GenericEvent; use Model\Task; use Model\TaskCreation; use Model\TaskFinder; @@ -21,7 +22,7 @@ class ActionTaskAssignSpecificUser extends Base ); $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testBadColumn() @@ -35,7 +36,7 @@ class ActionTaskAssignSpecificUser extends Base 'column_id' => 3, ); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testExecute() @@ -59,7 +60,7 @@ class ActionTaskAssignSpecificUser extends Base ); // Our event should be executed - $this->assertTrue($action->execute($event)); + $this->assertTrue($action->execute(new GenericEvent($event))); // Our task should be assigned to the user 1 $task = $tf->getById(1); diff --git a/tests/units/ActionTaskCloseTest.php b/tests/units/ActionTaskCloseTest.php index fd4f752d..a5087af0 100644 --- a/tests/units/ActionTaskCloseTest.php +++ b/tests/units/ActionTaskCloseTest.php @@ -2,6 +2,7 @@ require_once __DIR__.'/Base.php'; +use Event\GenericEvent; use Model\Task; use Model\TaskCreation; use Model\TaskFinder; @@ -45,7 +46,7 @@ class ActionTaskCloseTest extends Base ); $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testBadProject() @@ -60,7 +61,7 @@ class ActionTaskCloseTest extends Base ); $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testBadColumn() @@ -74,7 +75,7 @@ class ActionTaskCloseTest extends Base 'column_id' => 3, ); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testExecute() @@ -97,7 +98,7 @@ class ActionTaskCloseTest extends Base ); // Our event should be executed - $this->assertTrue($action->execute($event)); + $this->assertTrue($action->execute(new GenericEvent($event))); // Our task should be closed $task = $tf->getById(1); diff --git a/tests/units/ActionTaskDuplicateAnotherProjectTest.php b/tests/units/ActionTaskDuplicateAnotherProjectTest.php index d7f9d2c3..10c7c36a 100644 --- a/tests/units/ActionTaskDuplicateAnotherProjectTest.php +++ b/tests/units/ActionTaskDuplicateAnotherProjectTest.php @@ -2,6 +2,7 @@ require_once __DIR__.'/Base.php'; +use Event\GenericEvent; use Model\Task; use Model\TaskCreation; use Model\TaskFinder; @@ -21,7 +22,7 @@ class ActionTaskDuplicateAnotherProject extends Base ); $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testBadColumn() @@ -35,7 +36,7 @@ class ActionTaskDuplicateAnotherProject extends Base 'column_id' => 3, ); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testExecute() @@ -60,7 +61,7 @@ class ActionTaskDuplicateAnotherProject extends Base // Our event should NOT be executed because we define the same project $action->setParam('column_id', 2); $action->setParam('project_id', 1); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); // Our task should be assigned to the project 1 $task = $tf->getById(1); @@ -78,7 +79,7 @@ class ActionTaskDuplicateAnotherProject extends Base $action->setParam('column_id', 2); $action->setParam('project_id', 2); $this->assertTrue($action->hasRequiredCondition($event)); - $this->assertTrue($action->execute($event)); + $this->assertTrue($action->execute(new GenericEvent($event))); // Our task should be assigned to the project 1 $task = $tf->getById(1); diff --git a/tests/units/ActionTaskMoveAnotherProjectTest.php b/tests/units/ActionTaskMoveAnotherProjectTest.php index 605c3e55..3f0c3de6 100644 --- a/tests/units/ActionTaskMoveAnotherProjectTest.php +++ b/tests/units/ActionTaskMoveAnotherProjectTest.php @@ -2,6 +2,7 @@ require_once __DIR__.'/Base.php'; +use Event\GenericEvent; use Model\Task; use Model\TaskCreation; use Model\TaskFinder; @@ -21,7 +22,7 @@ class ActionTaskMoveAnotherProject extends Base ); $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testBadColumn() @@ -35,7 +36,7 @@ class ActionTaskMoveAnotherProject extends Base 'column_id' => 3, ); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); } public function testExecute() @@ -60,7 +61,7 @@ class ActionTaskMoveAnotherProject extends Base // Our event should NOT be executed because we define the same project $action->setParam('column_id', 2); $action->setParam('project_id', 1); - $this->assertFalse($action->execute($event)); + $this->assertFalse($action->execute(new GenericEvent($event))); // Our task should be assigned to the project 1 $task = $tf->getById(1); @@ -77,7 +78,7 @@ class ActionTaskMoveAnotherProject extends Base // Our event should be executed because we define a different project $action->setParam('column_id', 2); $action->setParam('project_id', 2); - $this->assertTrue($action->execute($event)); + $this->assertTrue($action->execute(new GenericEvent($event))); // Our task should be assigned to the project 2 $task = $tf->getById(1); diff --git a/tests/units/ActionTest.php b/tests/units/ActionTest.php index 84f383f7..77a939e0 100644 --- a/tests/units/ActionTest.php +++ b/tests/units/ActionTest.php @@ -10,21 +10,22 @@ use Model\TaskPosition; use Model\TaskCreation; use Model\TaskFinder; use Model\Category; +use Model\GithubWebhook; class ActionTest extends Base {/* - public function testFetchActions() + public function testSingleAction() { - $action = new Action($this->container); + $tp = new TaskPosition($this->container); + $tc = new TaskCreation($this->container); + $tf = new TaskFinder($this->container); $board = new Board($this->container); $project = new Project($this->container); + $action = new Action($this->container); + // We create a project $this->assertEquals(1, $project->create(array('name' => 'unit_test'))); - // We should have nothing - $this->assertEmpty($action->getAll()); - $this->assertEmpty($action->getAllByProject(1)); - // We create a new action $this->assertTrue($action->create(array( 'project_id' => 1, @@ -35,32 +36,6 @@ class ActionTest extends Base ) ))); - // We should have our action - $this->assertNotEmpty($action->getAll()); - $this->assertEquals($action->getAll(), $action->getAllByProject(1)); - - $actions = $action->getAll(); - - $this->assertEquals(1, count($actions)); - $this->assertEquals(1, $actions[0]['project_id']); - $this->assertEquals(Task::EVENT_MOVE_COLUMN, $actions[0]['event_name']); - $this->assertEquals('TaskClose', $actions[0]['action_name']); - $this->assertEquals('column_id', $actions[0]['params'][0]['name']); - $this->assertEquals(4, $actions[0]['params'][0]['value']); - } - - public function testEventMoveColumn() - { - $tp = new TaskPosition($this->container); - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $board = new Board($this->container); - $project = new Project($this->container); - $action = new Action($this->container); - - // We create a project - $this->assertEquals(1, $project->create(array('name' => 'unit_test'))); - // We create a task $this->assertEquals(1, $tc->create(array( 'title' => 'unit_test', @@ -70,17 +45,7 @@ class ActionTest extends Base 'column_id' => 1, ))); - // We create a new action - $this->assertTrue($action->create(array( - 'project_id' => 1, - 'event_name' => Task::EVENT_MOVE_COLUMN, - 'action_name' => 'TaskClose', - 'params' => array( - 'column_id' => 4, - ) - ))); - - // We bind events + // We attach events $action->attachEvents(); // Our task should be open @@ -91,87 +56,86 @@ class ActionTest extends Base // We move our task $tp->movePosition(1, 1, 4, 1); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_MOVE_COLUMN)); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_UPDATE)); - // Our task should be closed $t1 = $tf->getById(1); $this->assertEquals(4, $t1['column_id']); $this->assertEquals(0, $t1['is_active']); } */ - public function testExecuteMultipleActions() + public function testMultipleActions() { $tp = new TaskPosition($this->container); $tc = new TaskCreation($this->container); $tf = new TaskFinder($this->container); - $board = new Board($this->container); - $project = new Project($this->container); - $action = new Action($this->container); + $b = new Board($this->container); + $p = new Project($this->container); + $a = new Action($this->container); + $c = new Category($this->container); + $g = new GithubWebhook($this->container); - // We create 2 projects - $this->assertEquals(1, $project->create(array('name' => 'unit_test1'))); - $this->assertEquals(2, $project->create(array('name' => 'unit_test2'))); + // We create a project + $this->assertEquals(1, $p->create(array('name' => 'unit_test'))); + $this->assertEquals(1, $c->create(array('name' => 'unit_test'))); - // We create a task - $this->assertEquals(1, $tc->create(array( - 'title' => 'unit_test', + // We create a new action + $this->assertTrue($a->create(array( 'project_id' => 1, - 'owner_id' => 1, - 'color_id' => 'red', - 'column_id' => 1, + 'event_name' => GithubWebhook::EVENT_ISSUE_OPENED, + 'action_name' => 'TaskCreation', + 'params' => array() ))); - // We create 2 actions - $this->assertTrue($action->create(array( + $this->assertTrue($a->create(array( 'project_id' => 1, - 'event_name' => Task::EVENT_CLOSE, - 'action_name' => 'TaskDuplicateAnotherProject', + 'event_name' => GithubWebhook::EVENT_ISSUE_LABEL_CHANGE, + 'action_name' => 'TaskAssignCategoryLabel', 'params' => array( - 'column_id' => 4, - 'project_id' => 2, + 'label' => 'bug', + 'category_id' => 1, ) ))); - $this->assertTrue($action->create(array( + $this->assertTrue($a->create(array( 'project_id' => 1, - 'event_name' => Task::EVENT_MOVE_COLUMN, - 'action_name' => 'TaskClose', + 'event_name' => Task::EVENT_CREATE_UPDATE, + 'action_name' => 'TaskAssignColorCategory', 'params' => array( - 'column_id' => 4, + 'color_id' => 'red', + 'category_id' => 1, ) ))); - // We bind events - $action->attachEvents(); - - // Events should be attached - $this->assertTrue($this->container['event']->hasListener(Task::EVENT_CLOSE, 'Action\TaskDuplicateAnotherProject')); - $this->assertTrue($this->container['event']->hasListener(Task::EVENT_MOVE_COLUMN, 'Action\TaskClose')); - - // Our task should be open, linked to the first project and in the first column - $t1 = $tf->getById(1); - $this->assertEquals(1, $t1['is_active']); - $this->assertEquals(1, $t1['column_id']); - $this->assertEquals(1, $t1['project_id']); - - // We move our task - $tp->movePosition(1, 1, 4, 1); - - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_MOVE_COLUMN)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CLOSE)); - - // Our task should be closed - $t1 = $tf->getById(1); - $this->assertEquals(4, $t1['column_id']); - $this->assertEquals(0, $t1['is_active']); - - // Our task should be duplicated to the 2nd project - $t2 = $tf->getById(2); - $this->assertNotEmpty($t2); - $this->assertNotEquals(4, $t2['column_id']); - $this->assertEquals(1, $t2['is_active']); - $this->assertEquals(2, $t2['project_id']); - $this->assertEquals('unit_test', $t2['title']); + // We attach events + $a->attachEvents(); + $g->setProjectId(1); + + // We create a Github issue + $issue = array( + 'number' => 123, + 'title' => 'Bugs everywhere', + 'body' => 'There is a bug!', + 'html_url' => 'http://localhost/', + ); + + $this->assertTrue($g->handleIssueOpened($issue)); + + $task = $tf->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['is_active']); + $this->assertEquals(0, $task['category_id']); + $this->assertEquals('yellow', $task['color_id']); + + // We assign a label to our issue + $label = array( + 'name' => 'bug', + ); + + $this->assertTrue($g->handleIssueLabeled($issue, $label)); + + $task = $tf->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['is_active']); + $this->assertEquals(1, $task['category_id']); + $this->assertEquals('red', $task['color_id']); } } diff --git a/tests/units/Base.php b/tests/units/Base.php index 27960610..3e491969 100644 --- a/tests/units/Base.php +++ b/tests/units/Base.php @@ -3,6 +3,10 @@ require __DIR__.'/../../vendor/autoload.php'; require __DIR__.'/../../app/constants.php'; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; +use Symfony\Component\Stopwatch\Stopwatch; + date_default_timezone_set('UTC'); abstract class Base extends PHPUnit_Framework_TestCase @@ -23,8 +27,13 @@ abstract class Base extends PHPUnit_Framework_TestCase } $this->container = new Pimple\Container; - $this->container->register(new ServiceProvider\Database); - $this->container->register(new ServiceProvider\Event); + $this->container->register(new ServiceProvider\DatabaseProvider); + $this->container->register(new ServiceProvider\ModelProvider); + + $this->container['dispatcher'] = new TraceableEventDispatcher( + new EventDispatcher, + new Stopwatch + ); } public function tearDown() diff --git a/tests/units/ProjectTest.php b/tests/units/ProjectTest.php index 5fff8ad6..31481d96 100644 --- a/tests/units/ProjectTest.php +++ b/tests/units/ProjectTest.php @@ -2,6 +2,7 @@ require_once __DIR__.'/Base.php'; +use Subscriber\ProjectModificationDateSubscriber; use Model\Project; use Model\ProjectPermission; use Model\User; @@ -52,7 +53,6 @@ class ProjectTest extends Base $tc = new TaskCreation($this->container); $now = time(); - $p->attachEvents(); $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); @@ -62,9 +62,13 @@ class ProjectTest extends Base sleep(1); + $listener = new ProjectModificationDateSubscriber($this->container); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE_UPDATE, array($listener, 'execute')); + $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1))); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE)); - $this->assertEquals('Event\ProjectModificationDateListener', $this->container['event']->getLastListenerExecuted()); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(Task::EVENT_CREATE_UPDATE.'.Subscriber\ProjectModificationDateSubscriber::execute', $called); $project = $p->getById(1); $this->assertNotEmpty($project); diff --git a/tests/units/TaskCreationTest.php b/tests/units/TaskCreationTest.php index 48742a19..41a3f276 100644 --- a/tests/units/TaskCreationTest.php +++ b/tests/units/TaskCreationTest.php @@ -11,17 +11,31 @@ use Model\ProjectPermission; class TaskCreationTest extends Base { + public function onCreate($event) + { + $this->assertInstanceOf('Event\TaskEvent', $event); + + $event_data = $event->getAll(); + $this->assertNotEmpty($event_data); + $this->assertEquals(1, $event_data['task_id']); + $this->assertEquals('test', $event_data['title']); + } + public function testNoProjectId() { $p = new Project($this->container); $tc = new TaskCreation($this->container); $tf = new TaskFinder($this->container); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE_UPDATE, function() {}); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE, function() {}); + $this->assertEquals(1, $p->create(array('name' => 'test'))); $this->assertEquals(0, $tc->create(array('title' => 'test', 'project_id' => 0))); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_CREATE_UPDATE)); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_CREATE)); + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayNotHasKey(Task::EVENT_CREATE_UPDATE.'.closure', $called); + $this->assertArrayNotHasKey(Task::EVENT_CREATE.'.closure', $called); } public function testNoTitle() @@ -30,11 +44,15 @@ class TaskCreationTest extends Base $tc = new TaskCreation($this->container); $tf = new TaskFinder($this->container); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE_UPDATE, function() {}); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE, function() {}); + $this->assertEquals(1, $p->create(array('name' => 'test'))); $this->assertEquals(0, $tc->create(array('project_id' => 1))); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_CREATE_UPDATE)); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_CREATE)); + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayNotHasKey(Task::EVENT_CREATE_UPDATE.'.closure', $called); + $this->assertArrayNotHasKey(Task::EVENT_CREATE.'.closure', $called); } public function testMinimum() @@ -43,11 +61,15 @@ class TaskCreationTest extends Base $tc = new TaskCreation($this->container); $tf = new TaskFinder($this->container); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE_UPDATE, function() {}); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE, array($this, 'onCreate')); + $this->assertEquals(1, $p->create(array('name' => 'test'))); $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE_UPDATE)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE)); + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(Task::EVENT_CREATE_UPDATE.'.closure', $called); + $this->assertArrayHasKey(Task::EVENT_CREATE.'.TaskCreationTest::onCreate', $called); $task = $tf->getById(1); $this->assertNotEmpty($task); diff --git a/tests/units/TaskDuplicationTest.php b/tests/units/TaskDuplicationTest.php index 7b2983f8..6f1ee0e2 100644 --- a/tests/units/TaskDuplicationTest.php +++ b/tests/units/TaskDuplicationTest.php @@ -45,10 +45,15 @@ class TaskDuplicationTest extends Base $this->assertEquals(2, $task['category_id']); $this->assertEquals(4.4, $task['time_spent']); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE_UPDATE, function() {}); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE, function() {}); + // We duplicate our task $this->assertEquals(2, $td->duplicate(1)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE_UPDATE)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(Task::EVENT_CREATE_UPDATE.'.closure', $called); + $this->assertArrayHasKey(Task::EVENT_CREATE.'.closure', $called); // Check the values of the duplicated task $task = $tf->getById(2); @@ -82,10 +87,15 @@ class TaskDuplicationTest extends Base // We create a task $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 1, 'category_id' => 1))); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE_UPDATE, function() {}); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE, function() {}); + // We duplicate our task to the 2nd project $this->assertEquals(2, $td->duplicateToProject(1, 2)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE_UPDATE)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(Task::EVENT_CREATE_UPDATE.'.closure', $called); + $this->assertArrayHasKey(Task::EVENT_CREATE.'.closure', $called); // Check the values of the duplicated task $task = $tf->getById(2); @@ -121,8 +131,6 @@ class TaskDuplicationTest extends Base // We duplicate our task to the 2nd project $this->assertEquals(2, $td->duplicateToProject(1, 2)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE_UPDATE)); // Check the values of the duplicated task $task = $tf->getById(2); @@ -156,8 +164,6 @@ class TaskDuplicationTest extends Base // We duplicate our task to the 2nd project $this->assertEquals(2, $td->duplicateToProject(1, 2)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE_UPDATE)); // Check the values of the duplicated task $task = $tf->getById(2); @@ -191,8 +197,6 @@ class TaskDuplicationTest extends Base // We duplicate our task to the 2nd project $this->assertEquals(2, $td->duplicateToProject(1, 2)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE_UPDATE)); // Check the values of the duplicated task $task = $tf->getById(2); @@ -223,8 +227,6 @@ class TaskDuplicationTest extends Base // We duplicate our task to the 2nd project $this->assertEquals(2, $td->duplicateToProject(1, 2)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE_UPDATE)); // Check the values of the duplicated task $task = $tf->getById(2); @@ -265,6 +267,16 @@ class TaskDuplicationTest extends Base $this->assertEquals(5, $task['column_id']); } + public function onMoveProject($event) + { + $this->assertInstanceOf('Event\TaskEvent', $event); + + $event_data = $event->getAll(); + $this->assertNotEmpty($event_data); + $this->assertEquals(1, $event_data['task_id']); + $this->assertEquals('test', $event_data['title']); + } + public function testMoveAnotherProject() { $td = new TaskDuplication($this->container); @@ -281,9 +293,14 @@ class TaskDuplicationTest extends Base // We create a task $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'owner_id' => 1, 'category_id' => 10, 'position' => 333))); + $this->container['dispatcher']->addListener(Task::EVENT_MOVE_PROJECT, array($this, 'onMoveProject')); + // We duplicate our task to the 2nd project $this->assertTrue($td->moveToProject(1, 2)); + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(Task::EVENT_MOVE_PROJECT.'.TaskDuplicationTest::onMoveProject', $called); + // Check the values of the moved task $task = $tf->getById(1); $this->assertNotEmpty($task); diff --git a/tests/units/TaskModificationTest.php b/tests/units/TaskModificationTest.php index 9217c582..e6d8f8dc 100644 --- a/tests/units/TaskModificationTest.php +++ b/tests/units/TaskModificationTest.php @@ -12,6 +12,36 @@ use Model\ProjectPermission; class TaskModificationTest extends Base { + public function onCreateUpdate($event) + { + $this->assertInstanceOf('Event\TaskEvent', $event); + + $event_data = $event->getAll(); + $this->assertNotEmpty($event_data); + $this->assertEquals(1, $event_data['task_id']); + $this->assertEquals('Task #1', $event_data['title']); + } + + public function onUpdate($event) + { + $this->assertInstanceOf('Event\TaskEvent', $event); + + $event_data = $event->getAll(); + $this->assertNotEmpty($event_data); + $this->assertEquals(1, $event_data['task_id']); + $this->assertEquals('Task #1', $event_data['title']); + } + + public function onAssigneeChange($event) + { + $this->assertInstanceOf('Event\TaskEvent', $event); + + $event_data = $event->getAll(); + $this->assertNotEmpty($event_data); + $this->assertEquals(1, $event_data['task_id']); + $this->assertEquals(1, $event_data['owner_id']); + } + public function testChangeTitle() { $p = new Project($this->container); @@ -21,15 +51,15 @@ class TaskModificationTest extends Base $this->assertEquals(1, $p->create(array('name' => 'test'))); $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - $this->assertTrue($tm->update(array('id' => 1, 'title' => 'Task #1'))); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CREATE_UPDATE)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_UPDATE)); + $this->container['dispatcher']->addListener(Task::EVENT_CREATE_UPDATE, array($this, 'onCreateUpdate')); + $this->container['dispatcher']->addListener(Task::EVENT_UPDATE, array($this, 'onUpdate')); - $event_data = $this->container['event']->getEventData(Task::EVENT_UPDATE); - $this->assertNotEmpty($event_data); - $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals('Task #1', $event_data['title']); + $this->assertTrue($tm->update(array('id' => 1, 'title' => 'Task #1'))); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(Task::EVENT_CREATE_UPDATE.'.TaskModificationTest::onCreateUpdate', $called); + $this->assertArrayHasKey(Task::EVENT_UPDATE.'.TaskModificationTest::onUpdate', $called); $task = $tf->getById(1); $this->assertEquals('Task #1', $task['title']); @@ -48,14 +78,12 @@ class TaskModificationTest extends Base $task = $tf->getById(1); $this->assertEquals(0, $task['owner_id']); - $this->assertTrue($tm->update(array('id' => 1, 'owner_id' => 1))); + $this->container['dispatcher']->addListener(Task::EVENT_ASSIGNEE_CHANGE, array($this, 'onAssigneeChange')); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_ASSIGNEE_CHANGE)); + $this->assertTrue($tm->update(array('id' => 1, 'owner_id' => 1))); - $event_data = $this->container['event']->getEventData(Task::EVENT_ASSIGNEE_CHANGE); - $this->assertNotEmpty($event_data); - $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals(1, $event_data['owner_id']); + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(Task::EVENT_ASSIGNEE_CHANGE.'.TaskModificationTest::onAssigneeChange', $called); $task = $tf->getById(1); $this->assertEquals(1, $task['owner_id']); diff --git a/tests/units/TaskPositionTest.php b/tests/units/TaskPositionTest.php index dbc6c74b..21f1fd62 100644 --- a/tests/units/TaskPositionTest.php +++ b/tests/units/TaskPositionTest.php @@ -73,8 +73,6 @@ class TaskPositionTest extends Base // We move the task 3 to the column 3 $this->assertTrue($tp->movePosition(1, 3, 3, 2)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_MOVE_COLUMN)); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_MOVE_POSITION)); // Check tasks position $task = $tf->getById(1); @@ -470,6 +468,10 @@ class TaskPositionTest extends Base $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); $this->assertEquals(2, $tc->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 2))); + $this->container['dispatcher']->addListener(Task::EVENT_MOVE_COLUMN, array($this, 'onMoveColumn')); + $this->container['dispatcher']->addListener(Task::EVENT_MOVE_POSITION, array($this, 'onMovePosition')); + $this->container['dispatcher']->addListener(Task::EVENT_MOVE_SWIMLANE, array($this, 'onMoveSwimlane')); + // We move the task 1 to the column 2 $this->assertTrue($tp->movePosition(1, 1, 2, 1)); @@ -483,18 +485,9 @@ class TaskPositionTest extends Base $this->assertEquals(2, $task['column_id']); $this->assertEquals(2, $task['position']); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_MOVE_SWIMLANE)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_MOVE_COLUMN)); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_MOVE_POSITION)); - - $event_data = $this->container['event']->getEventData(Task::EVENT_MOVE_COLUMN); - $this->assertNotEmpty($event_data); - $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals(1, $event_data['position']); - $this->assertEquals(2, $event_data['column_id']); - $this->assertEquals(1, $event_data['project_id']); - - $this->container['event']->clearTriggeredEvents(); + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(Task::EVENT_MOVE_COLUMN.'.TaskPositionTest::onMoveColumn', $called); + $this->assertEquals(1, count($called)); // We move the task 1 to the position 2 $this->assertTrue($tp->movePosition(1, 1, 2, 2)); @@ -509,18 +502,9 @@ class TaskPositionTest extends Base $this->assertEquals(2, $task['column_id']); $this->assertEquals(1, $task['position']); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_MOVE_SWIMLANE)); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_MOVE_COLUMN)); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_MOVE_POSITION)); - - $event_data = $this->container['event']->getEventData(Task::EVENT_MOVE_POSITION); - $this->assertNotEmpty($event_data); - $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals(2, $event_data['position']); - $this->assertEquals(2, $event_data['column_id']); - $this->assertEquals(1, $event_data['project_id']); - - $this->container['event']->clearTriggeredEvents(); + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(Task::EVENT_MOVE_POSITION.'.TaskPositionTest::onMovePosition', $called); + $this->assertEquals(2, count($called)); // Move to another swimlane $this->assertTrue($tp->movePosition(1, 1, 3, 1, 1)); @@ -537,11 +521,40 @@ class TaskPositionTest extends Base $this->assertEquals(1, $task['position']); $this->assertEquals(0, $task['swimlane_id']); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_MOVE_SWIMLANE)); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_MOVE_POSITION)); - $this->assertFalse($this->container['event']->isEventTriggered(Task::EVENT_MOVE_POSITION)); + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(Task::EVENT_MOVE_SWIMLANE.'.TaskPositionTest::onMoveSwimlane', $called); + $this->assertEquals(3, count($called)); + } + + public function onMoveColumn($event) + { + $this->assertInstanceOf('Event\TaskEvent', $event); + + $event_data = $event->getAll(); + $this->assertNotEmpty($event_data); + $this->assertEquals(1, $event_data['task_id']); + $this->assertEquals(1, $event_data['position']); + $this->assertEquals(2, $event_data['column_id']); + $this->assertEquals(1, $event_data['project_id']); + } + + public function onMovePosition($event) + { + $this->assertInstanceOf('Event\TaskEvent', $event); + + $event_data = $event->getAll(); + $this->assertNotEmpty($event_data); + $this->assertEquals(1, $event_data['task_id']); + $this->assertEquals(2, $event_data['position']); + $this->assertEquals(2, $event_data['column_id']); + $this->assertEquals(1, $event_data['project_id']); + } + + public function onMoveSwimlane($event) + { + $this->assertInstanceOf('Event\TaskEvent', $event); - $event_data = $this->container['event']->getEventData(Task::EVENT_MOVE_SWIMLANE); + $event_data = $event->getAll(); $this->assertNotEmpty($event_data); $this->assertEquals(1, $event_data['task_id']); $this->assertEquals(1, $event_data['position']); diff --git a/tests/units/TaskStatusTest.php b/tests/units/TaskStatusTest.php index f2847bda..b1c3f695 100644 --- a/tests/units/TaskStatusTest.php +++ b/tests/units/TaskStatusTest.php @@ -33,6 +33,9 @@ class TaskStatusTest extends Base // We close the task + $this->container['dispatcher']->addListener(Task::EVENT_CLOSE, array($this, 'onTaskClose')); + $this->container['dispatcher']->addListener(Task::EVENT_OPEN, array($this, 'onTaskOpen')); + $this->assertTrue($ts->close(1)); $this->assertTrue($ts->isClosed(1)); @@ -42,8 +45,6 @@ class TaskStatusTest extends Base $this->assertEquals(time(), $task['date_completed']); $this->assertEquals(time(), $task['date_modification']); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_CLOSE)); - // We open the task again $this->assertTrue($ts->open(1)); @@ -55,6 +56,22 @@ class TaskStatusTest extends Base $this->assertEquals(0, $task['date_completed']); $this->assertEquals(time(), $task['date_modification']); - $this->assertTrue($this->container['event']->isEventTriggered(Task::EVENT_OPEN)); + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey('task.close.TaskStatusTest::onTaskClose', $called); + $this->assertArrayHasKey('task.open.TaskStatusTest::onTaskOpen', $called); + } + + public function onTaskOpen($event) + { + $this->assertInstanceOf('Event\TaskEvent', $event); + $this->assertArrayHasKey('task_id', $event); + $this->assertNotEmpty($event['task_id']); + } + + public function onTaskClose($event) + { + $this->assertInstanceOf('Event\TaskEvent', $event); + $this->assertArrayHasKey('task_id', $event); + $this->assertNotEmpty($event['task_id']); } } |