From ec0ecc5b0387924f061865f4ec12dbfc5b7018fe Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 17 Jul 2016 17:15:14 -0400 Subject: Added event for removed comments with some refactoring --- app/Subscriber/NotificationSubscriber.php | 1 + 1 file changed, 1 insertion(+) (limited to 'app/Subscriber') diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index db11e585..6cd7675c 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -28,6 +28,7 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn SubtaskModel::EVENT_UPDATE => 'handleEvent', CommentModel::EVENT_CREATE => 'handleEvent', CommentModel::EVENT_UPDATE => 'handleEvent', + CommentModel::EVENT_REMOVE => 'handleEvent', CommentModel::EVENT_USER_MENTION => 'handleEvent', TaskFileModel::EVENT_CREATE => 'handleEvent', ); -- cgit v1.2.3 From cbe52e57200a66522d88dfc5d5f46de8eb87ffb2 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 17 Jul 2016 18:47:06 -0400 Subject: File events refactoring --- app/Core/Base.php | 2 + app/Event/FileEvent.php | 7 --- app/Event/ProjectFileEvent.php | 7 +++ app/Event/TaskFileEvent.php | 7 +++ app/EventBuilder/ProjectFileEventBuilder.php | 50 ++++++++++++++++++++++ app/EventBuilder/TaskFileEventBuilder.php | 50 ++++++++++++++++++++++ app/Job/NotificationJob.php | 7 +-- app/Job/ProjectFileEventJob.php | 45 +++++++++++++++++++ app/Job/TaskFileEventJob.php | 45 +++++++++++++++++++ app/Model/FileModel.php | 22 +++++----- app/Model/ProjectFileModel.php | 9 ++-- app/Model/TaskFileModel.php | 23 +++++----- app/ServiceProvider/ClassProvider.php | 2 + app/Subscriber/BaseSubscriber.php | 24 ----------- app/Subscriber/NotificationSubscriber.php | 10 ++--- app/Subscriber/ProjectDailySummarySubscriber.php | 2 +- .../ProjectModificationDateSubscriber.php | 2 +- .../EventBuilder/ProjectFileEventBuilderTest.php | 33 ++++++++++++++ .../EventBuilder/TaskFileEventBuilderTest.php | 36 ++++++++++++++++ tests/units/Job/ProjectFileEventJobTest.php | 43 +++++++++++++++++++ tests/units/Job/TaskFileEventJobTest.php | 46 ++++++++++++++++++++ 21 files changed, 398 insertions(+), 74 deletions(-) delete mode 100644 app/Event/FileEvent.php create mode 100644 app/Event/ProjectFileEvent.php create mode 100644 app/Event/TaskFileEvent.php create mode 100644 app/EventBuilder/ProjectFileEventBuilder.php create mode 100644 app/EventBuilder/TaskFileEventBuilder.php create mode 100644 app/Job/ProjectFileEventJob.php create mode 100644 app/Job/TaskFileEventJob.php create mode 100644 tests/units/EventBuilder/ProjectFileEventBuilderTest.php create mode 100644 tests/units/EventBuilder/TaskFileEventBuilderTest.php create mode 100644 tests/units/Job/ProjectFileEventJobTest.php create mode 100644 tests/units/Job/TaskFileEventJobTest.php (limited to 'app/Subscriber') diff --git a/app/Core/Base.php b/app/Core/Base.php index e413a4ac..09e04456 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -151,6 +151,8 @@ use Pimple\Container; * @property \Kanboard\Core\Filter\LexerBuilder $taskLexer * @property \Kanboard\Core\Filter\LexerBuilder $projectActivityLexer * @property \Kanboard\Job\CommentEventJob $commentEventJob + * @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob + * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob * @property \Kanboard\Job\NotificationJob $notificationJob * @property \Psr\Log\LoggerInterface $logger * @property \PicoDb\Database $db diff --git a/app/Event/FileEvent.php b/app/Event/FileEvent.php deleted file mode 100644 index 482a4eab..00000000 --- a/app/Event/FileEvent.php +++ /dev/null @@ -1,7 +0,0 @@ -fileId = $fileId; + return $this; + } + + /** + * Build event data + * + * @access public + * @return GenericEvent|null + */ + public function build() + { + $file = $this->projectFileModel->getById($this->fileId); + + if (empty($file)) { + $this->logger->debug(__METHOD__.': File not found'); + return null; + } + + return new ProjectFileEvent(array( + 'file' => $file, + 'project' => $this->projectModel->getById($file['project_id']), + )); + } +} diff --git a/app/EventBuilder/TaskFileEventBuilder.php b/app/EventBuilder/TaskFileEventBuilder.php new file mode 100644 index 00000000..7f1ce3b3 --- /dev/null +++ b/app/EventBuilder/TaskFileEventBuilder.php @@ -0,0 +1,50 @@ +fileId = $fileId; + return $this; + } + + /** + * Build event data + * + * @access public + * @return GenericEvent|null + */ + public function build() + { + $file = $this->taskFileModel->getById($this->fileId); + + if (empty($file)) { + $this->logger->debug(__METHOD__.': File not found'); + return null; + } + + return new TaskFileEvent(array( + 'file' => $file, + 'task' => $this->taskFinderModel->getDetails($file['task_id']), + )); + } +} diff --git a/app/Job/NotificationJob.php b/app/Job/NotificationJob.php index cfd0699d..ed568e47 100644 --- a/app/Job/NotificationJob.php +++ b/app/Job/NotificationJob.php @@ -70,13 +70,8 @@ class NotificationJob extends BaseJob $values['subtask'] = $this->subtaskModel->getById($event['id'], true); $values['task'] = $this->taskFinderModel->getDetails($values['subtask']['task_id']); break; - case 'Kanboard\Event\FileEvent': - $values['file'] = $event; - $values['task'] = $this->taskFinderModel->getDetails($values['file']['task_id']); - break; - case 'Kanboard\Event\CommentEvent': + default: $values = $event; - break; } return $values; diff --git a/app/Job/ProjectFileEventJob.php b/app/Job/ProjectFileEventJob.php new file mode 100644 index 00000000..d68949c5 --- /dev/null +++ b/app/Job/ProjectFileEventJob.php @@ -0,0 +1,45 @@ +jobParams = array($fileId, $eventName); + return $this; + } + + /** + * Execute job + * + * @param int $fileId + * @param string $eventName + * @return $this + */ + public function execute($fileId, $eventName) + { + $event = ProjectFileEventBuilder::getInstance($this->container) + ->withFileId($fileId) + ->build(); + + if ($event !== null) { + $this->dispatcher->dispatch($eventName, $event); + } + } +} diff --git a/app/Job/TaskFileEventJob.php b/app/Job/TaskFileEventJob.php new file mode 100644 index 00000000..de2c40db --- /dev/null +++ b/app/Job/TaskFileEventJob.php @@ -0,0 +1,45 @@ +jobParams = array($fileId, $eventName); + return $this; + } + + /** + * Execute job + * + * @param int $fileId + * @param string $eventName + * @return $this + */ + public function execute($fileId, $eventName) + { + $event = TaskFileEventBuilder::getInstance($this->container) + ->withFileId($fileId) + ->build(); + + if ($event !== null) { + $this->dispatcher->dispatch($eventName, $event); + } + } +} diff --git a/app/Model/FileModel.php b/app/Model/FileModel.php index 8cdea9a0..98032f9d 100644 --- a/app/Model/FileModel.php +++ b/app/Model/FileModel.php @@ -5,7 +5,6 @@ namespace Kanboard\Model; use Exception; use Kanboard\Core\Base; use Kanboard\Core\Thumbnail; -use Kanboard\Event\FileEvent; use Kanboard\Core\ObjectStorage\ObjectStorageException; /** @@ -44,13 +43,13 @@ abstract class FileModel extends Base abstract protected function getPathPrefix(); /** - * Get event name + * Fire file creation event * * @abstract * @access protected - * @return string + * @param integer $file_id */ - abstract protected function getEventName(); + abstract protected function fireCreationEvent($file_id); /** * Get PicoDb query to get all files @@ -130,16 +129,16 @@ abstract class FileModel extends Base * Create a file entry in the database * * @access public - * @param integer $id Foreign key - * @param string $name Filename - * @param string $path Path on the disk - * @param integer $size File size + * @param integer $foreign_key_id Foreign key + * @param string $name Filename + * @param string $path Path on the disk + * @param integer $size File size * @return bool|integer */ - public function create($id, $name, $path, $size) + public function create($foreign_key_id, $name, $path, $size) { $values = array( - $this->getForeignKey() => $id, + $this->getForeignKey() => $foreign_key_id, 'name' => substr($name, 0, 255), 'path' => $path, 'is_image' => $this->isImage($name) ? 1 : 0, @@ -152,8 +151,7 @@ abstract class FileModel extends Base if ($result) { $file_id = (int) $this->db->getLastId(); - $event = new FileEvent($values + array('file_id' => $file_id)); - $this->dispatcher->dispatch($this->getEventName(), $event); + $this->fireCreationEvent($file_id); return $file_id; } diff --git a/app/Model/ProjectFileModel.php b/app/Model/ProjectFileModel.php index b464bb2a..4de4d66d 100644 --- a/app/Model/ProjectFileModel.php +++ b/app/Model/ProjectFileModel.php @@ -61,14 +61,13 @@ class ProjectFileModel extends FileModel } /** - * Get event name + * Fire file creation event * - * @abstract * @access protected - * @return string + * @param integer $file_id */ - protected function getEventName() + protected function fireCreationEvent($file_id) { - return self::EVENT_CREATE; + $this->queueManager->push($this->projectFileEventJob->withParams($file_id, self::EVENT_CREATE)); } } diff --git a/app/Model/TaskFileModel.php b/app/Model/TaskFileModel.php index 7603019a..0163da28 100644 --- a/app/Model/TaskFileModel.php +++ b/app/Model/TaskFileModel.php @@ -60,18 +60,6 @@ class TaskFileModel extends FileModel return 'tasks'; } - /** - * Get event name - * - * @abstract - * @access protected - * @return string - */ - protected function getEventName() - { - return self::EVENT_CREATE; - } - /** * Get projectId from fileId * @@ -101,4 +89,15 @@ class TaskFileModel extends FileModel $original_filename = e('Screenshot taken %s', $this->helper->dt->datetime(time())).'.png'; return $this->uploadContent($task_id, $original_filename, $blob); } + + /** + * Fire file creation event + * + * @access protected + * @param integer $file_id + */ + protected function fireCreationEvent($file_id) + { + $this->queueManager->push($this->taskFileEventJob->withParams($file_id, self::EVENT_CREATE)); + } } diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 43ade56e..428a8015 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -28,6 +28,8 @@ class ClassProvider implements ServiceProviderInterface ), 'Job' => array( 'CommentEventJob', + 'TaskFileEventJob', + 'ProjectFileEventJob', 'NotificationJob', ), 'Model' => array( diff --git a/app/Subscriber/BaseSubscriber.php b/app/Subscriber/BaseSubscriber.php index fdea29f6..92441962 100644 --- a/app/Subscriber/BaseSubscriber.php +++ b/app/Subscriber/BaseSubscriber.php @@ -12,28 +12,4 @@ use Kanboard\Core\Base; */ class BaseSubscriber extends Base { - /** - * Method called - * - * @access private - * @var array - */ - private $called = array(); - - /** - * Check if a listener has been executed - * - * @access public - * @param string $key - * @return boolean - */ - public function isExecuted($key = '') - { - if (isset($this->called[$key])) { - return true; - } - - $this->called[$key] = true; - return false; - } } diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index 6cd7675c..47222f73 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -36,12 +36,10 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn public function handleEvent(GenericEvent $event, $eventName) { - if (!$this->isExecuted($eventName)) { - $this->logger->debug('Subscriber executed: ' . __METHOD__); + $this->logger->debug('Subscriber executed: ' . __METHOD__); - $this->queueManager->push(NotificationJob::getInstance($this->container) - ->withParams($event, $eventName, get_class($event)) - ); - } + $this->queueManager->push(NotificationJob::getInstance($this->container) + ->withParams($event, $eventName, get_class($event)) + ); } } diff --git a/app/Subscriber/ProjectDailySummarySubscriber.php b/app/Subscriber/ProjectDailySummarySubscriber.php index 6971a121..7e3c11c3 100644 --- a/app/Subscriber/ProjectDailySummarySubscriber.php +++ b/app/Subscriber/ProjectDailySummarySubscriber.php @@ -22,7 +22,7 @@ class ProjectDailySummarySubscriber extends BaseSubscriber implements EventSubsc public function execute(TaskEvent $event) { - if (isset($event['project_id']) && !$this->isExecuted()) { + if (isset($event['project_id'])) { $this->logger->debug('Subscriber executed: '.__METHOD__); $this->queueManager->push(ProjectMetricJob::getInstance($this->container)->withParams($event['project_id'])); } diff --git a/app/Subscriber/ProjectModificationDateSubscriber.php b/app/Subscriber/ProjectModificationDateSubscriber.php index fee04eaa..97923af9 100644 --- a/app/Subscriber/ProjectModificationDateSubscriber.php +++ b/app/Subscriber/ProjectModificationDateSubscriber.php @@ -24,7 +24,7 @@ class ProjectModificationDateSubscriber extends BaseSubscriber implements EventS public function execute(GenericEvent $event) { - if (isset($event['project_id']) && !$this->isExecuted()) { + if (isset($event['project_id'])) { $this->logger->debug('Subscriber executed: '.__METHOD__); $this->projectModel->updateModificationDate($event['project_id']); } diff --git a/tests/units/EventBuilder/ProjectFileEventBuilderTest.php b/tests/units/EventBuilder/ProjectFileEventBuilderTest.php new file mode 100644 index 00000000..bfe22719 --- /dev/null +++ b/tests/units/EventBuilder/ProjectFileEventBuilderTest.php @@ -0,0 +1,33 @@ +container); + $projectFileEventBuilder->withFileId(42); + $this->assertNull($projectFileEventBuilder->build()); + } + + public function testBuild() + { + $projectModel = new ProjectModel($this->container); + $projectFileModel = new ProjectFileModel($this->container); + $projectFileEventBuilder = new ProjectFileEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $projectFileModel->create(1, 'Test', '/tmp/test', 123)); + + $event = $projectFileEventBuilder->withFileId(1)->build(); + + $this->assertInstanceOf('Kanboard\Event\ProjectFileEvent', $event); + $this->assertNotEmpty($event['file']); + $this->assertNotEmpty($event['project']); + } +} diff --git a/tests/units/EventBuilder/TaskFileEventBuilderTest.php b/tests/units/EventBuilder/TaskFileEventBuilderTest.php new file mode 100644 index 00000000..c253b913 --- /dev/null +++ b/tests/units/EventBuilder/TaskFileEventBuilderTest.php @@ -0,0 +1,36 @@ +container); + $taskFileEventBuilder->withFileId(42); + $this->assertNull($taskFileEventBuilder->build()); + } + + public function testBuild() + { + $taskFileModel = new TaskFileModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskFileEventBuilder = new TaskFileEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $taskFileModel->create(1, 'Test', '/tmp/test', 123)); + + $event = $taskFileEventBuilder->withFileId(1)->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskFileEvent', $event); + $this->assertNotEmpty($event['file']); + $this->assertNotEmpty($event['task']); + } +} diff --git a/tests/units/Job/ProjectFileEventJobTest.php b/tests/units/Job/ProjectFileEventJobTest.php new file mode 100644 index 00000000..f266d293 --- /dev/null +++ b/tests/units/Job/ProjectFileEventJobTest.php @@ -0,0 +1,43 @@ +container); + $projectFileEventJob->withParams(123, 'foobar'); + + $this->assertSame(array(123, 'foobar'), $projectFileEventJob->getJobParams()); + } + + public function testWithMissingFile() + { + $this->container['dispatcher']->addListener(ProjectFileModel::EVENT_CREATE, function() {}); + + $projectFileEventJob = new ProjectFileEventJob($this->container); + $projectFileEventJob->execute(42, ProjectFileModel::EVENT_CREATE); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertEmpty($called); + } + + public function testTriggerEvents() + { + $this->container['dispatcher']->addListener(ProjectFileModel::EVENT_CREATE, function() {}); + + $projectModel = new ProjectModel($this->container); + $projectFileModel = new ProjectFileModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $projectFileModel->create(1, 'Test', '/tmp/test', 123)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(ProjectFileModel::EVENT_CREATE.'.closure', $called); + } +} diff --git a/tests/units/Job/TaskFileEventJobTest.php b/tests/units/Job/TaskFileEventJobTest.php new file mode 100644 index 00000000..921fe801 --- /dev/null +++ b/tests/units/Job/TaskFileEventJobTest.php @@ -0,0 +1,46 @@ +container); + $taskFileEventJob->withParams(123, 'foobar'); + + $this->assertSame(array(123, 'foobar'), $taskFileEventJob->getJobParams()); + } + + public function testWithMissingFile() + { + $this->container['dispatcher']->addListener(TaskFileModel::EVENT_CREATE, function() {}); + + $taskFileEventJob = new TaskFileEventJob($this->container); + $taskFileEventJob->execute(42, TaskFileModel::EVENT_CREATE); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertEmpty($called); + } + + public function testTriggerEvents() + { + $this->container['dispatcher']->addListener(TaskFileModel::EVENT_CREATE, function() {}); + + $taskFileModel = new TaskFileModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $taskFileModel->create(1, 'Test', '/tmp/test', 123)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskFileModel::EVENT_CREATE.'.closure', $called); + } +} -- cgit v1.2.3 From d9d37882228771bca0c7f53f5ffcef90ba7ac1c5 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 17 Jul 2016 20:33:27 -0400 Subject: Subtasks events refactoring and show delete in activity stream --- app/Core/Base.php | 1 + app/EventBuilder/SubtaskEventBuilder.php | 79 ++++++++++++++++++++++ app/Job/NotificationJob.php | 4 -- app/Job/SubtaskEventJob.php | 48 +++++++++++++ app/Model/NotificationModel.php | 5 ++ app/Model/SubtaskModel.php | 22 ++---- app/ServiceProvider/ClassProvider.php | 6 -- app/ServiceProvider/JobProvider.php | 52 ++++++++++++++ app/ServiceProvider/QueueProvider.php | 6 +- app/Subscriber/NotificationSubscriber.php | 1 + app/Template/event/subtask_delete.php | 15 ++++ app/Template/notification/subtask_delete.php | 11 +++ app/common.php | 1 + tests/units/Base.php | 1 + .../units/EventBuilder/SubtaskEventBuilderTest.php | 62 +++++++++++++++++ tests/units/Job/SubtaskEventJobTest.php | 52 ++++++++++++++ tests/units/Model/SubtaskModelTest.php | 70 +------------------ 17 files changed, 339 insertions(+), 97 deletions(-) create mode 100644 app/EventBuilder/SubtaskEventBuilder.php create mode 100644 app/Job/SubtaskEventJob.php create mode 100644 app/ServiceProvider/JobProvider.php create mode 100644 app/Template/event/subtask_delete.php create mode 100644 app/Template/notification/subtask_delete.php create mode 100644 tests/units/EventBuilder/SubtaskEventBuilderTest.php create mode 100644 tests/units/Job/SubtaskEventJobTest.php (limited to 'app/Subscriber') diff --git a/app/Core/Base.php b/app/Core/Base.php index 09e04456..6650680b 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -151,6 +151,7 @@ use Pimple\Container; * @property \Kanboard\Core\Filter\LexerBuilder $taskLexer * @property \Kanboard\Core\Filter\LexerBuilder $projectActivityLexer * @property \Kanboard\Job\CommentEventJob $commentEventJob + * @property \Kanboard\Job\SubtaskEventJob $subtaskEventJob * @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob * @property \Kanboard\Job\NotificationJob $notificationJob diff --git a/app/EventBuilder/SubtaskEventBuilder.php b/app/EventBuilder/SubtaskEventBuilder.php new file mode 100644 index 00000000..f0271257 --- /dev/null +++ b/app/EventBuilder/SubtaskEventBuilder.php @@ -0,0 +1,79 @@ +subtaskId = $subtaskId; + return $this; + } + + /** + * Set values + * + * @param array $values + * @return $this + */ + public function withValues(array $values) + { + $this->values = $values; + return $this; + } + + /** + * Build event data + * + * @access public + * @return GenericEvent|null + */ + public function build() + { + $eventData = array(); + $eventData['subtask'] = $this->subtaskModel->getById($this->subtaskId, true); + + if (empty($eventData['subtask'])) { + $this->logger->debug(__METHOD__.': Subtask not found'); + return null; + } + + if (! empty($this->values)) { + $eventData['changes'] = array_diff_assoc($this->values, $eventData['subtask']); + } + + $eventData['task'] = $this->taskFinderModel->getDetails($eventData['subtask']['task_id']); + return new SubtaskEvent($eventData); + } +} diff --git a/app/Job/NotificationJob.php b/app/Job/NotificationJob.php index ed568e47..5a52eb31 100644 --- a/app/Job/NotificationJob.php +++ b/app/Job/NotificationJob.php @@ -66,10 +66,6 @@ class NotificationJob extends BaseJob case 'Kanboard\Event\TaskEvent': $values['task'] = $this->taskFinderModel->getDetails($event['task_id']); break; - case 'Kanboard\Event\SubtaskEvent': - $values['subtask'] = $this->subtaskModel->getById($event['id'], true); - $values['task'] = $this->taskFinderModel->getDetails($values['subtask']['task_id']); - break; default: $values = $event; } diff --git a/app/Job/SubtaskEventJob.php b/app/Job/SubtaskEventJob.php new file mode 100644 index 00000000..1dc243ef --- /dev/null +++ b/app/Job/SubtaskEventJob.php @@ -0,0 +1,48 @@ +jobParams = array($subtaskId, $eventName, $values); + return $this; + } + + /** + * Execute job + * + * @param int $subtaskId + * @param string $eventName + * @param array $values + * @return $this + */ + public function execute($subtaskId, $eventName, array $values = array()) + { + $event = SubtaskEventBuilder::getInstance($this->container) + ->withSubtaskId($subtaskId) + ->withValues($values) + ->build(); + + if ($event !== null) { + $this->dispatcher->dispatch($eventName, $event); + } + } +} diff --git a/app/Model/NotificationModel.php b/app/Model/NotificationModel.php index df481fc7..ac8d9bae 100644 --- a/app/Model/NotificationModel.php +++ b/app/Model/NotificationModel.php @@ -70,6 +70,8 @@ class NotificationModel extends Base return e('%s updated a subtask for the task #%d', $event_author, $event_data['task']['id']); case SubtaskModel::EVENT_CREATE: return e('%s created a subtask for the task #%d', $event_author, $event_data['task']['id']); + case SubtaskModel::EVENT_DELETE: + return e('%s removed a subtask for the task #%d', $event_author, $event_data['task']['id']); case CommentModel::EVENT_UPDATE: return e('%s updated a comment on the task #%d', $event_author, $event_data['task']['id']); case CommentModel::EVENT_CREATE: @@ -110,6 +112,8 @@ class NotificationModel extends Base return e('New subtask on task #%d', $event_data['subtask']['task_id']); case SubtaskModel::EVENT_UPDATE: return e('Subtask updated on task #%d', $event_data['subtask']['task_id']); + case SubtaskModel::EVENT_DELETE: + return e('Subtask removed on task #%d', $event_data['subtask']['task_id']); case TaskModel::EVENT_CREATE: return e('New task #%d: %s', $event_data['task']['id'], $event_data['task']['title']); case TaskModel::EVENT_UPDATE: @@ -157,6 +161,7 @@ class NotificationModel extends Base return $event_data['comment']['task_id']; case SubtaskModel::EVENT_CREATE: case SubtaskModel::EVENT_UPDATE: + case SubtaskModel::EVENT_DELETE: return $event_data['subtask']['task_id']; case TaskModel::EVENT_CREATE: case TaskModel::EVENT_UPDATE: diff --git a/app/Model/SubtaskModel.php b/app/Model/SubtaskModel.php index a97bddbf..6dd1f26a 100644 --- a/app/Model/SubtaskModel.php +++ b/app/Model/SubtaskModel.php @@ -66,7 +66,7 @@ class SubtaskModel extends Base ->join(TaskModel::TABLE, 'id', 'task_id') ->findOneColumn(TaskModel::TABLE . '.project_id') ?: 0; } - + /** * Get available status * @@ -235,10 +235,7 @@ class SubtaskModel extends Base $subtask_id = $this->db->table(self::TABLE)->persist($values); if ($subtask_id !== false) { - $this->container['dispatcher']->dispatch( - self::EVENT_CREATE, - new SubtaskEvent(array('id' => $subtask_id) + $values) - ); + $this->queueManager->push($this->subtaskEventJob->withParams($subtask_id, self::EVENT_CREATE)); } return $subtask_id; @@ -255,13 +252,10 @@ class SubtaskModel extends Base public function update(array $values, $fire_events = true) { $this->prepare($values); - $subtask = $this->getById($values['id']); $result = $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values); if ($result && $fire_events) { - $event = $subtask; - $event['changes'] = array_diff_assoc($values, $subtask); - $this->container['dispatcher']->dispatch(self::EVENT_UPDATE, new SubtaskEvent($event)); + $this->queueManager->push($this->subtaskEventJob->withParams($values['id'], self::EVENT_UPDATE, $values)); } return $result; @@ -377,14 +371,8 @@ class SubtaskModel extends Base */ public function remove($subtask_id) { - $subtask = $this->getById($subtask_id); - $result = $this->db->table(self::TABLE)->eq('id', $subtask_id)->remove(); - - if ($result) { - $this->container['dispatcher']->dispatch(self::EVENT_DELETE, new SubtaskEvent($subtask)); - } - - return $result; + $this->subtaskEventJob->execute($subtask_id, self::EVENT_DELETE); + return $this->db->table(self::TABLE)->eq('id', $subtask_id)->remove(); } /** diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 428a8015..e32c0d43 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -26,12 +26,6 @@ class ClassProvider implements ServiceProviderInterface 'AverageLeadCycleTimeAnalytic', 'AverageTimeSpentColumnAnalytic', ), - 'Job' => array( - 'CommentEventJob', - 'TaskFileEventJob', - 'ProjectFileEventJob', - 'NotificationJob', - ), 'Model' => array( 'ActionModel', 'ActionParameterModel', diff --git a/app/ServiceProvider/JobProvider.php b/app/ServiceProvider/JobProvider.php new file mode 100644 index 00000000..bfea6e6e --- /dev/null +++ b/app/ServiceProvider/JobProvider.php @@ -0,0 +1,52 @@ +factory(function ($c) { + return new CommentEventJob($c); + }); + + $container['subtaskEventJob'] = $container->factory(function ($c) { + return new SubtaskEventJob($c); + }); + + $container['taskFileEventJob'] = $container->factory(function ($c) { + return new TaskFileEventJob($c); + }); + + $container['projectFileEventJob'] = $container->factory(function ($c) { + return new ProjectFileEventJob($c); + }); + + $container['notificationJob'] = $container->factory(function ($c) { + return new NotificationJob($c); + }); + + return $container; + } +} diff --git a/app/ServiceProvider/QueueProvider.php b/app/ServiceProvider/QueueProvider.php index 946b436a..570f2e77 100644 --- a/app/ServiceProvider/QueueProvider.php +++ b/app/ServiceProvider/QueueProvider.php @@ -15,9 +15,11 @@ use Pimple\ServiceProviderInterface; class QueueProvider implements ServiceProviderInterface { /** - * Registers services on the given container. + * Register providers * - * @param Container $container + * @access public + * @param \Pimple\Container $container + * @return \Pimple\Container */ public function register(Container $container) { diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index 47222f73..0b3760c4 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -26,6 +26,7 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn TaskModel::EVENT_ASSIGNEE_CHANGE => 'handleEvent', SubtaskModel::EVENT_CREATE => 'handleEvent', SubtaskModel::EVENT_UPDATE => 'handleEvent', + SubtaskModel::EVENT_DELETE => 'handleEvent', CommentModel::EVENT_CREATE => 'handleEvent', CommentModel::EVENT_UPDATE => 'handleEvent', CommentModel::EVENT_REMOVE => 'handleEvent', diff --git a/app/Template/event/subtask_delete.php b/app/Template/event/subtask_delete.php new file mode 100644 index 00000000..8ac11853 --- /dev/null +++ b/app/Template/event/subtask_delete.php @@ -0,0 +1,15 @@ +

+ text->e($author), + $this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) + ) ?> + dt->datetime($date_creation) ?> +

+
+

text->e($task['title']) ?>

+
    +
  • + text->e($subtask['title']) ?> (text->e($subtask['status_name']) ?>) +
  • +
+
diff --git a/app/Template/notification/subtask_delete.php b/app/Template/notification/subtask_delete.php new file mode 100644 index 00000000..8c5f262c --- /dev/null +++ b/app/Template/notification/subtask_delete.php @@ -0,0 +1,11 @@ +

text->e($task['title']) ?> (#)

+ +

+ +
    +
  • text->e($subtask['title']) ?>
  • +
  • text->e($subtask['status_name']) ?>
  • +
  • text->e($subtask['name'] ?: $subtask['username'] ?: '?') ?>
  • +
+ +render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/app/common.php b/app/common.php index 72be3603..15fd7a75 100644 --- a/app/common.php +++ b/app/common.php @@ -46,6 +46,7 @@ $container->register(new Kanboard\ServiceProvider\ActionProvider()); $container->register(new Kanboard\ServiceProvider\ExternalLinkProvider()); $container->register(new Kanboard\ServiceProvider\AvatarProvider()); $container->register(new Kanboard\ServiceProvider\FilterProvider()); +$container->register(new Kanboard\ServiceProvider\JobProvider()); $container->register(new Kanboard\ServiceProvider\QueueProvider()); $container->register(new Kanboard\ServiceProvider\ApiProvider()); $container->register(new Kanboard\ServiceProvider\CommandProvider()); diff --git a/tests/units/Base.php b/tests/units/Base.php index 9dbfb280..c471ee31 100644 --- a/tests/units/Base.php +++ b/tests/units/Base.php @@ -41,6 +41,7 @@ abstract class Base extends PHPUnit_Framework_TestCase $this->container->register(new Kanboard\ServiceProvider\RouteProvider()); $this->container->register(new Kanboard\ServiceProvider\AvatarProvider()); $this->container->register(new Kanboard\ServiceProvider\FilterProvider()); + $this->container->register(new Kanboard\ServiceProvider\JobProvider()); $this->container->register(new Kanboard\ServiceProvider\QueueProvider()); $this->container['dispatcher'] = new TraceableEventDispatcher( diff --git a/tests/units/EventBuilder/SubtaskEventBuilderTest.php b/tests/units/EventBuilder/SubtaskEventBuilderTest.php new file mode 100644 index 00000000..062bdfb4 --- /dev/null +++ b/tests/units/EventBuilder/SubtaskEventBuilderTest.php @@ -0,0 +1,62 @@ +container); + $subtaskEventBuilder->withSubtaskId(42); + $this->assertNull($subtaskEventBuilder->build()); + } + + public function testBuildWithoutChanges() + { + $subtaskModel = new SubtaskModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $subtaskEventBuilder = new SubtaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('task_id' => 1, 'title' => 'test'))); + + $event = $subtaskEventBuilder->withSubtaskId(1)->build(); + + $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); + $this->assertNotEmpty($event['subtask']); + $this->assertNotEmpty($event['task']); + $this->assertArrayNotHasKey('changes', $event); + } + + public function testBuildWithChanges() + { + $subtaskModel = new SubtaskModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $subtaskEventBuilder = new SubtaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('task_id' => 1, 'title' => 'test'))); + + $event = $subtaskEventBuilder + ->withSubtaskId(1) + ->withValues(array('title' => 'new title', 'user_id' => 1)) + ->build(); + + $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); + $this->assertNotEmpty($event['subtask']); + $this->assertNotEmpty($event['task']); + $this->assertNotEmpty($event['changes']); + $this->assertCount(2, $event['changes']); + $this->assertEquals('new title', $event['changes']['title']); + $this->assertEquals(1, $event['changes']['user_id']); + } +} diff --git a/tests/units/Job/SubtaskEventJobTest.php b/tests/units/Job/SubtaskEventJobTest.php new file mode 100644 index 00000000..265a8e2d --- /dev/null +++ b/tests/units/Job/SubtaskEventJobTest.php @@ -0,0 +1,52 @@ +container); + $subtaskEventJob->withParams(123, 'foobar', array('k' => 'v')); + + $this->assertSame(array(123, 'foobar', array('k' => 'v')), $subtaskEventJob->getJobParams()); + } + + public function testWithMissingSubtask() + { + $this->container['dispatcher']->addListener(SubtaskModel::EVENT_CREATE, function() {}); + + $SubtaskEventJob = new SubtaskEventJob($this->container); + $SubtaskEventJob->execute(42, SubtaskModel::EVENT_CREATE); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertEmpty($called); + } + + public function testTriggerEvents() + { + $this->container['dispatcher']->addListener(SubtaskModel::EVENT_CREATE, function() {}); + $this->container['dispatcher']->addListener(SubtaskModel::EVENT_UPDATE, function() {}); + $this->container['dispatcher']->addListener(SubtaskModel::EVENT_DELETE, function() {}); + + $subtaskModel = new SubtaskModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('task_id' => 1, 'title' => 'before'))); + $this->assertTrue($subtaskModel->update(array('id' => 1, 'title' => 'after'))); + $this->assertTrue($subtaskModel->remove(1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(SubtaskModel::EVENT_CREATE.'.closure', $called); + $this->assertArrayHasKey(SubtaskModel::EVENT_UPDATE.'.closure', $called); + $this->assertArrayHasKey(SubtaskModel::EVENT_DELETE.'.closure', $called); + } +} diff --git a/tests/units/Model/SubtaskModelTest.php b/tests/units/Model/SubtaskModelTest.php index 6451189d..7e438651 100644 --- a/tests/units/Model/SubtaskModelTest.php +++ b/tests/units/Model/SubtaskModelTest.php @@ -9,64 +9,6 @@ use Kanboard\Model\TaskFinderModel; class SubtaskModelTest extends Base { - public function onSubtaskCreated($event) - { - $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); - $data = $event->getAll(); - - $this->assertArrayHasKey('id', $data); - $this->assertArrayHasKey('title', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('time_estimated', $data); - $this->assertArrayHasKey('time_spent', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('task_id', $data); - $this->assertArrayHasKey('user_id', $data); - $this->assertArrayHasKey('position', $data); - $this->assertNotEmpty($data['task_id']); - $this->assertNotEmpty($data['id']); - } - - public function onSubtaskUpdated($event) - { - $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); - $data = $event->getAll(); - - $this->assertArrayHasKey('id', $data); - $this->assertArrayHasKey('title', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('time_estimated', $data); - $this->assertArrayHasKey('time_spent', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('task_id', $data); - $this->assertArrayHasKey('user_id', $data); - $this->assertArrayHasKey('position', $data); - $this->assertArrayHasKey('changes', $data); - $this->assertArrayHasKey('user_id', $data['changes']); - $this->assertArrayHasKey('status', $data['changes']); - - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $data['changes']['status']); - $this->assertEquals(1, $data['changes']['user_id']); - } - - public function onSubtaskDeleted($event) - { - $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); - $data = $event->getAll(); - - $this->assertArrayHasKey('id', $data); - $this->assertArrayHasKey('title', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('time_estimated', $data); - $this->assertArrayHasKey('time_spent', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('task_id', $data); - $this->assertArrayHasKey('user_id', $data); - $this->assertArrayHasKey('position', $data); - $this->assertNotEmpty($data['task_id']); - $this->assertNotEmpty($data['id']); - } - public function testCreation() { $taskCreationModel = new TaskCreationModel($this->container); @@ -75,9 +17,6 @@ class SubtaskModelTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->container['dispatcher']->addListener(SubtaskModel::EVENT_CREATE, array($this, 'onSubtaskCreated')); - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); $subtask = $subtaskModel->getById(1); @@ -101,8 +40,6 @@ class SubtaskModelTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - $this->container['dispatcher']->addListener(SubtaskModel::EVENT_UPDATE, array($this, 'onSubtaskUpdated')); - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); $this->assertTrue($subtaskModel->update(array('id' => 1, 'user_id' => 1, 'status' => SubtaskModel::STATUS_INPROGRESS))); @@ -128,8 +65,6 @@ class SubtaskModelTest extends Base $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - $this->container['dispatcher']->addListener(SubtaskModel::EVENT_DELETE, array($this, 'onSubtaskDeleted')); - $subtask = $subtaskModel->getById(1); $this->assertNotEmpty($subtask); @@ -269,7 +204,6 @@ class SubtaskModelTest extends Base $this->assertTrue($subtaskModel->duplicate(1, 2)); $subtasks = $subtaskModel->getAll(2); - $this->assertNotFalse($subtasks); $this->assertNotEmpty($subtasks); $this->assertEquals(2, count($subtasks)); @@ -383,7 +317,7 @@ class SubtaskModelTest extends Base $this->assertEquals(2, $task['time_spent']); $this->assertEquals(3, $task['time_estimated']); } - + public function testGetProjectId() { $taskCreationModel = new TaskCreationModel($this->container); @@ -393,7 +327,7 @@ class SubtaskModelTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - + $this->assertEquals(1, $subtaskModel->getProjectId(1)); $this->assertEquals(0, $subtaskModel->getProjectId(2)); } -- cgit v1.2.3 From 390082aa41cb81610089163b1cc3a256f3b3c513 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Tue, 19 Jul 2016 22:38:30 -0400 Subject: Refactoring of internal task events --- app/Action/Base.php | 13 +- app/Action/CommentCreationMoveTaskColumn.php | 12 +- app/Action/TaskAssignCategoryColor.php | 7 +- app/Action/TaskAssignColorCategory.php | 7 +- app/Action/TaskAssignColorColumn.php | 7 +- app/Action/TaskAssignColorPriority.php | 7 +- app/Action/TaskAssignColorUser.php | 7 +- app/Action/TaskAssignCurrentUserColumn.php | 7 +- app/Action/TaskAssignSpecificUser.php | 7 +- app/Action/TaskCloseColumn.php | 10 +- app/Action/TaskCreation.php | 1 + app/Action/TaskDuplicateAnotherProject.php | 14 +- app/Action/TaskEmail.php | 14 +- app/Action/TaskMoveAnotherProject.php | 8 +- app/Action/TaskMoveColumnAssigned.php | 19 +- app/Action/TaskMoveColumnCategoryChange.php | 19 +- app/Action/TaskMoveColumnUnAssigned.php | 19 +- app/Action/TaskUpdateStartDate.php | 7 +- app/Core/Base.php | 1 + app/EventBuilder/TaskEventBuilder.php | 123 ++++ app/Job/NotificationJob.php | 50 +- app/Job/TaskEventJob.php | 75 +++ app/Model/SubtaskModel.php | 1 - app/Model/TaskCreationModel.php | 32 +- app/Model/TaskModificationModel.php | 62 +- app/Model/TaskPositionModel.php | 28 +- app/Model/TaskProjectMoveModel.php | 7 +- app/Model/TaskStatusModel.php | 8 +- app/ServiceProvider/JobProvider.php | 5 + app/Subscriber/NotificationSubscriber.php | 6 +- .../ProjectModificationDateSubscriber.php | 6 +- tests/units/Action/BaseActionTest.php | 10 +- .../Action/CommentCreationMoveTaskColumnTest.php | 6 +- tests/units/Action/TaskAssignCategoryColorTest.php | 18 +- tests/units/Action/TaskAssignCategoryLinkTest.php | 43 +- tests/units/Action/TaskAssignColorCategoryTest.php | 18 +- tests/units/Action/TaskAssignColorColumnTest.php | 18 +- tests/units/Action/TaskAssignColorPriorityTest.php | 18 +- tests/units/Action/TaskAssignColorUserTest.php | 18 +- .../Action/TaskAssignCurrentUserColumnTest.php | 26 +- tests/units/Action/TaskAssignSpecificUserTest.php | 17 +- tests/units/Action/TaskCloseColumnTest.php | 18 +- tests/units/Action/TaskCloseTest.php | 15 +- .../Action/TaskDuplicateAnotherProjectTest.php | 18 +- tests/units/Action/TaskEmailTest.php | 19 +- tests/units/Action/TaskMoveAnotherProjectTest.php | 17 +- tests/units/Action/TaskMoveColumnAssignedTest.php | 18 +- .../Action/TaskMoveColumnCategoryChangeTest.php | 31 +- .../units/Action/TaskMoveColumnUnAssignedTest.php | 31 +- tests/units/Action/TaskOpenTest.php | 15 +- tests/units/Action/TaskUpdateStartDateTest.php | 17 +- tests/units/EventBuilder/TaskEventBuilderTest.php | 100 ++++ tests/units/Job/SubtaskEventJobTest.php | 4 +- tests/units/Job/TaskEventJobTest.php | 189 ++++++ tests/units/Model/TaskCreationModelTest.php | 2 +- tests/units/Model/TaskModificationModelTest.php | 13 +- tests/units/Model/TaskPositionModelTest.php | 631 +++++++++++++++++++++ tests/units/Model/TaskPositionTest.php | 631 --------------------- tests/units/Model/TaskProjectMoveModelTest.php | 2 +- 59 files changed, 1647 insertions(+), 905 deletions(-) create mode 100644 app/EventBuilder/TaskEventBuilder.php create mode 100644 app/Job/TaskEventJob.php create mode 100644 tests/units/EventBuilder/TaskEventBuilderTest.php create mode 100644 tests/units/Job/TaskEventJobTest.php create mode 100644 tests/units/Model/TaskPositionModelTest.php delete mode 100644 tests/units/Model/TaskPositionTest.php (limited to 'app/Subscriber') diff --git a/app/Action/Base.php b/app/Action/Base.php index e5c65a17..e0ed8bde 100644 --- a/app/Action/Base.php +++ b/app/Action/Base.php @@ -216,7 +216,8 @@ abstract class Base extends \Kanboard\Core\Base */ public function hasRequiredProject(array $data) { - return isset($data['project_id']) && $data['project_id'] == $this->getProjectId(); + return (isset($data['project_id']) && $data['project_id'] == $this->getProjectId()) || + (isset($data['task']['project_id']) && $data['task']['project_id'] == $this->getProjectId()); } /** @@ -226,10 +227,14 @@ abstract class Base extends \Kanboard\Core\Base * @param array $data Event data dictionary * @return bool True if all keys are there */ - public function hasRequiredParameters(array $data) + public function hasRequiredParameters(array $data, array $parameters = array()) { - foreach ($this->getEventRequiredParameters() as $parameter) { - if (! isset($data[$parameter])) { + $parameters = $parameters ?: $this->getEventRequiredParameters(); + + foreach ($parameters as $key => $value) { + if (is_array($value)) { + return isset($data[$key]) && $this->hasRequiredParameters($data[$key], $value); + } else if (! isset($data[$value])) { return false; } } diff --git a/app/Action/CommentCreationMoveTaskColumn.php b/app/Action/CommentCreationMoveTaskColumn.php index 1b16f481..8ab792ad 100644 --- a/app/Action/CommentCreationMoveTaskColumn.php +++ b/app/Action/CommentCreationMoveTaskColumn.php @@ -55,7 +55,13 @@ class CommentCreationMoveTaskColumn extends Base */ public function getEventRequiredParameters() { - return array('task_id', 'column_id'); + return array( + 'task_id', + 'task' => array( + 'column_id', + 'project_id', + ), + ); } /** @@ -71,7 +77,7 @@ class CommentCreationMoveTaskColumn extends Base return false; } - $column = $this->columnModel->getById($data['column_id']); + $column = $this->columnModel->getById($data['task']['column_id']); return (bool) $this->commentModel->create(array( 'comment' => t('Moved to column %s', $column['title']), @@ -89,6 +95,6 @@ class CommentCreationMoveTaskColumn extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskAssignCategoryColor.php b/app/Action/TaskAssignCategoryColor.php index fc486870..2df90b2c 100644 --- a/app/Action/TaskAssignCategoryColor.php +++ b/app/Action/TaskAssignCategoryColor.php @@ -60,7 +60,10 @@ class TaskAssignCategoryColor extends Base { return array( 'task_id', - 'color_id', + 'task' => array( + 'project_id', + 'color_id', + ), ); } @@ -90,6 +93,6 @@ class TaskAssignCategoryColor extends Base */ public function hasRequiredCondition(array $data) { - return $data['color_id'] == $this->getParam('color_id'); + return $data['task']['color_id'] == $this->getParam('color_id'); } } diff --git a/app/Action/TaskAssignColorCategory.php b/app/Action/TaskAssignColorCategory.php index 284b8f40..91860be4 100644 --- a/app/Action/TaskAssignColorCategory.php +++ b/app/Action/TaskAssignColorCategory.php @@ -60,7 +60,10 @@ class TaskAssignColorCategory extends Base { return array( 'task_id', - 'category_id', + 'task' => array( + 'project_id', + 'category_id', + ), ); } @@ -90,6 +93,6 @@ class TaskAssignColorCategory extends Base */ public function hasRequiredCondition(array $data) { - return $data['category_id'] == $this->getParam('category_id'); + return $data['task']['category_id'] == $this->getParam('category_id'); } } diff --git a/app/Action/TaskAssignColorColumn.php b/app/Action/TaskAssignColorColumn.php index 57fd6f44..6c674b1f 100644 --- a/app/Action/TaskAssignColorColumn.php +++ b/app/Action/TaskAssignColorColumn.php @@ -61,7 +61,10 @@ class TaskAssignColorColumn extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ), ); } @@ -91,6 +94,6 @@ class TaskAssignColorColumn extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskAssignColorPriority.php b/app/Action/TaskAssignColorPriority.php index eae1b771..57000ba8 100644 --- a/app/Action/TaskAssignColorPriority.php +++ b/app/Action/TaskAssignColorPriority.php @@ -60,7 +60,10 @@ class TaskAssignColorPriority extends Base { return array( 'task_id', - 'priority', + 'task' => array( + 'project_id', + 'priority', + ), ); } @@ -90,6 +93,6 @@ class TaskAssignColorPriority extends Base */ public function hasRequiredCondition(array $data) { - return $data['priority'] == $this->getParam('priority'); + return $data['task']['priority'] == $this->getParam('priority'); } } diff --git a/app/Action/TaskAssignColorUser.php b/app/Action/TaskAssignColorUser.php index 4bcf7a5c..385db793 100644 --- a/app/Action/TaskAssignColorUser.php +++ b/app/Action/TaskAssignColorUser.php @@ -61,7 +61,10 @@ class TaskAssignColorUser extends Base { return array( 'task_id', - 'owner_id', + 'task' => array( + 'project_id', + 'owner_id', + ), ); } @@ -91,6 +94,6 @@ class TaskAssignColorUser extends Base */ public function hasRequiredCondition(array $data) { - return $data['owner_id'] == $this->getParam('user_id'); + return $data['task']['owner_id'] == $this->getParam('user_id'); } } diff --git a/app/Action/TaskAssignCurrentUserColumn.php b/app/Action/TaskAssignCurrentUserColumn.php index bc28a90b..e4eade33 100644 --- a/app/Action/TaskAssignCurrentUserColumn.php +++ b/app/Action/TaskAssignCurrentUserColumn.php @@ -59,7 +59,10 @@ class TaskAssignCurrentUserColumn extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ), ); } @@ -93,6 +96,6 @@ class TaskAssignCurrentUserColumn extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskAssignSpecificUser.php b/app/Action/TaskAssignSpecificUser.php index 50a2b2ae..2c7dcacd 100644 --- a/app/Action/TaskAssignSpecificUser.php +++ b/app/Action/TaskAssignSpecificUser.php @@ -61,7 +61,10 @@ class TaskAssignSpecificUser extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ), ); } @@ -91,6 +94,6 @@ class TaskAssignSpecificUser extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskCloseColumn.php b/app/Action/TaskCloseColumn.php index 1edce8fa..4f1ffc92 100644 --- a/app/Action/TaskCloseColumn.php +++ b/app/Action/TaskCloseColumn.php @@ -55,7 +55,13 @@ class TaskCloseColumn extends Base */ public function getEventRequiredParameters() { - return array('task_id', 'column_id'); + return array( + 'task_id', + 'task' => array( + 'project_id', + 'column_id', + ) + ); } /** @@ -79,6 +85,6 @@ class TaskCloseColumn extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskCreation.php b/app/Action/TaskCreation.php index e9e5c5f3..0620afd3 100644 --- a/app/Action/TaskCreation.php +++ b/app/Action/TaskCreation.php @@ -52,6 +52,7 @@ class TaskCreation extends Base public function getEventRequiredParameters() { return array( + 'project_id', 'reference', 'title', ); diff --git a/app/Action/TaskDuplicateAnotherProject.php b/app/Action/TaskDuplicateAnotherProject.php index d70d2ee8..d6d8d51f 100644 --- a/app/Action/TaskDuplicateAnotherProject.php +++ b/app/Action/TaskDuplicateAnotherProject.php @@ -62,7 +62,10 @@ class TaskDuplicateAnotherProject extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ) ); } @@ -76,7 +79,12 @@ class TaskDuplicateAnotherProject extends Base public function doAction(array $data) { $destination_column_id = $this->columnModel->getFirstColumnId($this->getParam('project_id')); - return (bool) $this->taskProjectDuplicationModel->duplicateToProject($data['task_id'], $this->getParam('project_id'), null, $destination_column_id); + return (bool) $this->taskProjectDuplicationModel->duplicateToProject( + $data['task_id'], + $this->getParam('project_id'), + null, + $destination_column_id + ); } /** @@ -88,6 +96,6 @@ class TaskDuplicateAnotherProject extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id') && $data['project_id'] != $this->getParam('project_id'); + return $data['task']['column_id'] == $this->getParam('column_id') && $data['task']['project_id'] != $this->getParam('project_id'); } } diff --git a/app/Action/TaskEmail.php b/app/Action/TaskEmail.php index 7f9ba416..526e9aa8 100644 --- a/app/Action/TaskEmail.php +++ b/app/Action/TaskEmail.php @@ -62,7 +62,10 @@ class TaskEmail extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ), ); } @@ -78,13 +81,14 @@ class TaskEmail extends Base $user = $this->userModel->getById($this->getParam('user_id')); if (! empty($user['email'])) { - $task = $this->taskFinderModel->getDetails($data['task_id']); - $this->emailClient->send( $user['email'], $user['name'] ?: $user['username'], $this->getParam('subject'), - $this->template->render('notification/task_create', array('task' => $task, 'application_url' => $this->configModel->get('application_url'))) + $this->template->render('notification/task_create', array( + 'task' => $data['task'], + 'application_url' => $this->configModel->get('application_url'), + )) ); return true; @@ -102,6 +106,6 @@ class TaskEmail extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskMoveAnotherProject.php b/app/Action/TaskMoveAnotherProject.php index 66635a63..148b6b0c 100644 --- a/app/Action/TaskMoveAnotherProject.php +++ b/app/Action/TaskMoveAnotherProject.php @@ -61,8 +61,10 @@ class TaskMoveAnotherProject extends Base { return array( 'task_id', - 'column_id', - 'project_id', + 'task' => array( + 'project_id', + 'column_id', + ) ); } @@ -87,6 +89,6 @@ class TaskMoveAnotherProject extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id') && $data['project_id'] != $this->getParam('project_id'); + return $data['task']['column_id'] == $this->getParam('column_id') && $data['task']['project_id'] != $this->getParam('project_id'); } } diff --git a/app/Action/TaskMoveColumnAssigned.php b/app/Action/TaskMoveColumnAssigned.php index 7e3db9c5..1c1f657a 100644 --- a/app/Action/TaskMoveColumnAssigned.php +++ b/app/Action/TaskMoveColumnAssigned.php @@ -61,8 +61,13 @@ class TaskMoveColumnAssigned extends Base { return array( 'task_id', - 'column_id', - 'owner_id' + 'task' => array( + 'project_id', + 'column_id', + 'owner_id', + 'position', + 'swimlane_id', + ) ); } @@ -75,14 +80,12 @@ class TaskMoveColumnAssigned extends Base */ public function doAction(array $data) { - $original_task = $this->taskFinderModel->getById($data['task_id']); - return $this->taskPositionModel->movePosition( - $data['project_id'], + $data['task']['project_id'], $data['task_id'], $this->getParam('dest_column_id'), - $original_task['position'], - $original_task['swimlane_id'], + $data['task']['position'], + $data['task']['swimlane_id'], false ); } @@ -96,6 +99,6 @@ class TaskMoveColumnAssigned extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('src_column_id') && $data['owner_id'] > 0; + return $data['task']['column_id'] == $this->getParam('src_column_id') && $data['task']['owner_id'] > 0; } } diff --git a/app/Action/TaskMoveColumnCategoryChange.php b/app/Action/TaskMoveColumnCategoryChange.php index e4f88760..4c2b289a 100644 --- a/app/Action/TaskMoveColumnCategoryChange.php +++ b/app/Action/TaskMoveColumnCategoryChange.php @@ -60,8 +60,13 @@ class TaskMoveColumnCategoryChange extends Base { return array( 'task_id', - 'column_id', - 'category_id', + 'task' => array( + 'project_id', + 'column_id', + 'category_id', + 'position', + 'swimlane_id', + ) ); } @@ -74,14 +79,12 @@ class TaskMoveColumnCategoryChange extends Base */ public function doAction(array $data) { - $original_task = $this->taskFinderModel->getById($data['task_id']); - return $this->taskPositionModel->movePosition( - $data['project_id'], + $data['task']['project_id'], $data['task_id'], $this->getParam('dest_column_id'), - $original_task['position'], - $original_task['swimlane_id'], + $data['task']['position'], + $data['task']['swimlane_id'], false ); } @@ -95,6 +98,6 @@ class TaskMoveColumnCategoryChange extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] != $this->getParam('dest_column_id') && $data['category_id'] == $this->getParam('category_id'); + return $data['task']['column_id'] != $this->getParam('dest_column_id') && $data['task']['category_id'] == $this->getParam('category_id'); } } diff --git a/app/Action/TaskMoveColumnUnAssigned.php b/app/Action/TaskMoveColumnUnAssigned.php index c3ae9e1d..0e9a8a16 100644 --- a/app/Action/TaskMoveColumnUnAssigned.php +++ b/app/Action/TaskMoveColumnUnAssigned.php @@ -61,8 +61,13 @@ class TaskMoveColumnUnAssigned extends Base { return array( 'task_id', - 'column_id', - 'owner_id' + 'task' => array( + 'project_id', + 'column_id', + 'owner_id', + 'position', + 'swimlane_id', + ) ); } @@ -75,14 +80,12 @@ class TaskMoveColumnUnAssigned extends Base */ public function doAction(array $data) { - $original_task = $this->taskFinderModel->getById($data['task_id']); - return $this->taskPositionModel->movePosition( - $data['project_id'], + $data['task']['project_id'], $data['task_id'], $this->getParam('dest_column_id'), - $original_task['position'], - $original_task['swimlane_id'], + $data['task']['position'], + $data['task']['swimlane_id'], false ); } @@ -96,6 +99,6 @@ class TaskMoveColumnUnAssigned extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('src_column_id') && $data['owner_id'] == 0; + return $data['task']['column_id'] == $this->getParam('src_column_id') && $data['task']['owner_id'] == 0; } } diff --git a/app/Action/TaskUpdateStartDate.php b/app/Action/TaskUpdateStartDate.php index e5410a87..cc016da1 100644 --- a/app/Action/TaskUpdateStartDate.php +++ b/app/Action/TaskUpdateStartDate.php @@ -59,7 +59,10 @@ class TaskUpdateStartDate extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ), ); } @@ -89,6 +92,6 @@ class TaskUpdateStartDate extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Core/Base.php b/app/Core/Base.php index 6650680b..098bd880 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -152,6 +152,7 @@ use Pimple\Container; * @property \Kanboard\Core\Filter\LexerBuilder $projectActivityLexer * @property \Kanboard\Job\CommentEventJob $commentEventJob * @property \Kanboard\Job\SubtaskEventJob $subtaskEventJob + * @property \Kanboard\Job\TaskEventJob $taskEventJob * @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob * @property \Kanboard\Job\NotificationJob $notificationJob diff --git a/app/EventBuilder/TaskEventBuilder.php b/app/EventBuilder/TaskEventBuilder.php new file mode 100644 index 00000000..e7a5653d --- /dev/null +++ b/app/EventBuilder/TaskEventBuilder.php @@ -0,0 +1,123 @@ +taskId = $taskId; + return $this; + } + + /** + * Set task + * + * @param array $task + * @return $this + */ + public function withTask(array $task) + { + $this->task = $task; + return $this; + } + + /** + * Set values + * + * @param array $values + * @return $this + */ + public function withValues(array $values) + { + $this->values = $values; + return $this; + } + + /** + * Set changes + * + * @param array $changes + * @return $this + */ + public function withChanges(array $changes) + { + $this->changes = $changes; + return $this; + } + + /** + * Build event data + * + * @access public + * @return TaskEvent|null + */ + public function build() + { + $eventData = array(); + $eventData['task_id'] = $this->taskId; + $eventData['task'] = $this->taskFinderModel->getDetails($this->taskId); + + if (empty($eventData['task'])) { + $this->logger->debug(__METHOD__.': Task not found'); + return null; + } + + if (! empty($this->changes)) { + if (empty($this->task)) { + $this->task = $eventData['task']; + } + + $eventData['changes'] = array_diff_assoc($this->changes, $this->task); + unset($eventData['changes']['date_modification']); + } + + return new TaskEvent(array_merge($eventData, $this->values)); + } +} diff --git a/app/Job/NotificationJob.php b/app/Job/NotificationJob.php index 5a52eb31..8fb260e8 100644 --- a/app/Job/NotificationJob.php +++ b/app/Job/NotificationJob.php @@ -17,59 +17,27 @@ class NotificationJob extends BaseJob * * @param GenericEvent $event * @param string $eventName - * @param string $eventObjectName * @return $this */ - public function withParams(GenericEvent $event, $eventName, $eventObjectName) + public function withParams(GenericEvent $event, $eventName) { - $this->jobParams = array($event->getAll(), $eventName, $eventObjectName); + $this->jobParams = array($event->getAll(), $eventName); return $this; } /** * Execute job * - * @param array $event + * @param array $eventData * @param string $eventName - * @param string $eventObjectName */ - public function execute(array $event, $eventName, $eventObjectName) + public function execute(array $eventData, $eventName) { - $eventData = $this->getEventData($event, $eventObjectName); - - if (! empty($eventData)) { - if (! empty($event['mention'])) { - $this->userNotificationModel->sendUserNotification($event['mention'], $eventName, $eventData); - } else { - $this->userNotificationModel->sendNotifications($eventName, $eventData); - $this->projectNotificationModel->sendNotifications($eventData['task']['project_id'], $eventName, $eventData); - } - } - } - - /** - * Get event data - * - * @param array $event - * @param string $eventObjectName - * @return array - */ - public function getEventData(array $event, $eventObjectName) - { - $values = array(); - - if (! empty($event['changes'])) { - $values['changes'] = $event['changes']; + if (! empty($eventData['mention'])) { + $this->userNotificationModel->sendUserNotification($eventData['mention'], $eventName, $eventData); + } else { + $this->userNotificationModel->sendNotifications($eventName, $eventData); + $this->projectNotificationModel->sendNotifications($eventData['task']['project_id'], $eventName, $eventData); } - - switch ($eventObjectName) { - case 'Kanboard\Event\TaskEvent': - $values['task'] = $this->taskFinderModel->getDetails($event['task_id']); - break; - default: - $values = $event; - } - - return $values; } } diff --git a/app/Job/TaskEventJob.php b/app/Job/TaskEventJob.php new file mode 100644 index 00000000..46f7a16c --- /dev/null +++ b/app/Job/TaskEventJob.php @@ -0,0 +1,75 @@ +jobParams = array($taskId, $eventNames, $changes, $values, $task); + return $this; + } + + /** + * Execute job + * + * @param int $taskId + * @param array $eventNames + * @param array $changes + * @param array $values + * @param array $task + * @return $this + */ + public function execute($taskId, array $eventNames, array $changes = array(), array $values = array(), array $task = array()) + { + $event = TaskEventBuilder::getInstance($this->container) + ->withTaskId($taskId) + ->withChanges($changes) + ->withValues($values) + ->withTask($task) + ->build(); + + if ($event !== null) { + foreach ($eventNames as $eventName) { + $this->fireEvent($eventName, $event); + } + } + } + + /** + * Trigger event + * + * @access protected + * @param string $eventName + * @param TaskEvent $event + */ + protected function fireEvent($eventName, TaskEvent $event) + { + $this->logger->debug(__METHOD__.' Event fired: '.$eventName); + $this->dispatcher->dispatch($eventName, $event); + + if ($eventName === TaskModel::EVENT_CREATE) { + $this->userMentionModel->fireEvents($event['task']['description'], TaskModel::EVENT_USER_MENTION, $event); + } + } +} diff --git a/app/Model/SubtaskModel.php b/app/Model/SubtaskModel.php index 6dd1f26a..f3fc72ba 100644 --- a/app/Model/SubtaskModel.php +++ b/app/Model/SubtaskModel.php @@ -4,7 +4,6 @@ namespace Kanboard\Model; use PicoDb\Database; use Kanboard\Core\Base; -use Kanboard\Event\SubtaskEvent; /** * Subtask Model diff --git a/app/Model/TaskCreationModel.php b/app/Model/TaskCreationModel.php index cd70a028..1c0fd7d9 100644 --- a/app/Model/TaskCreationModel.php +++ b/app/Model/TaskCreationModel.php @@ -3,7 +3,6 @@ namespace Kanboard\Model; use Kanboard\Core\Base; -use Kanboard\Event\TaskEvent; /** * Task Creation @@ -42,7 +41,10 @@ class TaskCreationModel extends Base $this->taskTagModel->save($values['project_id'], $task_id, $tags); } - $this->fireEvents($task_id, $values); + $this->queueManager->push($this->taskEventJob->withParams( + $task_id, + array(TaskModel::EVENT_CREATE_UPDATE, TaskModel::EVENT_CREATE) + )); } return (int) $task_id; @@ -51,10 +53,10 @@ class TaskCreationModel extends Base /** * Prepare data * - * @access public + * @access protected * @param array $values Form values */ - public function prepare(array &$values) + protected function prepare(array &$values) { $values = $this->dateParser->convert($values, array('date_due')); $values = $this->dateParser->convert($values, array('date_started'), true); @@ -84,26 +86,4 @@ class TaskCreationModel extends Base $values['date_moved'] = $values['date_creation']; $values['position'] = $this->taskFinderModel->countByColumnAndSwimlaneId($values['project_id'], $values['column_id'], $values['swimlane_id']) + 1; } - - /** - * Fire events - * - * @access private - * @param integer $task_id Task id - * @param array $values Form values - */ - private function fireEvents($task_id, array $values) - { - $event = new TaskEvent(array('task_id' => $task_id) + $values); - - $this->logger->debug('Event fired: '.TaskModel::EVENT_CREATE_UPDATE); - $this->logger->debug('Event fired: '.TaskModel::EVENT_CREATE); - - $this->dispatcher->dispatch(TaskModel::EVENT_CREATE_UPDATE, $event); - $this->dispatcher->dispatch(TaskModel::EVENT_CREATE, $event); - - if (! empty($values['description'])) { - $this->userMentionModel->fireEvents($values['description'], TaskModel::EVENT_USER_MENTION, $event); - } - } } diff --git a/app/Model/TaskModificationModel.php b/app/Model/TaskModificationModel.php index be5f53c8..16b48f3d 100644 --- a/app/Model/TaskModificationModel.php +++ b/app/Model/TaskModificationModel.php @@ -3,7 +3,6 @@ namespace Kanboard\Model; use Kanboard\Core\Base; -use Kanboard\Event\TaskEvent; /** * Task Modification @@ -23,14 +22,14 @@ class TaskModificationModel extends Base */ public function update(array $values, $fire_events = true) { - $original_task = $this->taskFinderModel->getById($values['id']); + $task = $this->taskFinderModel->getById($values['id']); - $this->updateTags($values, $original_task); + $this->updateTags($values, $task); $this->prepare($values); - $result = $this->db->table(TaskModel::TABLE)->eq('id', $original_task['id'])->update($values); + $result = $this->db->table(TaskModel::TABLE)->eq('id', $task['id'])->update($values); if ($fire_events && $result) { - $this->fireEvents($original_task, $values); + $this->fireEvents($task, $values); } return $result; @@ -39,43 +38,56 @@ class TaskModificationModel extends Base /** * Fire events * - * @access public - * @param array $task - * @param array $new_values + * @access protected + * @param array $task + * @param array $changes */ - public function fireEvents(array $task, array $new_values) + protected function fireEvents(array $task, array $changes) { $events = array(); - $event_data = array_merge($task, $new_values, array('task_id' => $task['id'])); - // Values changed - $event_data['changes'] = array_diff_assoc($new_values, $task); - unset($event_data['changes']['date_modification']); - - if ($this->isFieldModified('owner_id', $event_data['changes'])) { + if ($this->isAssigneeChanged($task, $changes)) { $events[] = TaskModel::EVENT_ASSIGNEE_CHANGE; - } elseif (! empty($event_data['changes'])) { + } elseif ($this->isModified($task, $changes)) { $events[] = TaskModel::EVENT_CREATE_UPDATE; $events[] = TaskModel::EVENT_UPDATE; } - foreach ($events as $event) { - $this->logger->debug('Event fired: '.$event); - $this->dispatcher->dispatch($event, new TaskEvent($event_data)); + if (! empty($events)) { + $this->queueManager->push($this->taskEventJob + ->withParams($task['id'], $events, $changes, array(), $task) + ); } } + /** + * Return true if the task have been modified + * + * @access protected + * @param array $task + * @param array $changes + * @return bool + */ + protected function isModified(array $task, array $changes) + { + $diff = array_diff_assoc($changes, $task); + unset($diff['date_modification']); + return count($diff) > 0; + } + /** * Return true if the field is the only modified value * - * @access public - * @param string $field - * @param array $changes - * @return boolean + * @access protected + * @param array $task + * @param array $changes + * @return bool */ - public function isFieldModified($field, array $changes) + protected function isAssigneeChanged(array $task, array $changes) { - return isset($changes[$field]) && count($changes) === 1; + $diff = array_diff_assoc($changes, $task); + unset($diff['date_modification']); + return isset($changes['owner_id']) && $task['owner_id'] != $changes['owner_id'] && count($diff) === 1; } /** diff --git a/app/Model/TaskPositionModel.php b/app/Model/TaskPositionModel.php index 9fdb8f7d..d6d2a0af 100644 --- a/app/Model/TaskPositionModel.php +++ b/app/Model/TaskPositionModel.php @@ -3,7 +3,6 @@ namespace Kanboard\Model; use Kanboard\Core\Base; -use Kanboard\Event\TaskEvent; /** * Task Position @@ -212,8 +211,7 @@ class TaskPositionModel extends Base */ private function fireEvents(array $task, $new_column_id, $new_position, $new_swimlane_id) { - $event_data = array( - 'task_id' => $task['id'], + $changes = array( 'project_id' => $task['project_id'], 'position' => $new_position, 'column_id' => $new_column_id, @@ -226,14 +224,26 @@ class TaskPositionModel extends Base ); if ($task['swimlane_id'] != $new_swimlane_id) { - $this->logger->debug('Event fired: '.TaskModel::EVENT_MOVE_SWIMLANE); - $this->dispatcher->dispatch(TaskModel::EVENT_MOVE_SWIMLANE, new TaskEvent($event_data)); + $this->queueManager->push($this->taskEventJob->withParams( + $task['id'], + array(TaskModel::EVENT_MOVE_SWIMLANE), + $changes, + $changes + )); } elseif ($task['column_id'] != $new_column_id) { - $this->logger->debug('Event fired: '.TaskModel::EVENT_MOVE_COLUMN); - $this->dispatcher->dispatch(TaskModel::EVENT_MOVE_COLUMN, new TaskEvent($event_data)); + $this->queueManager->push($this->taskEventJob->withParams( + $task['id'], + array(TaskModel::EVENT_MOVE_COLUMN), + $changes, + $changes + )); } elseif ($task['position'] != $new_position) { - $this->logger->debug('Event fired: '.TaskModel::EVENT_MOVE_POSITION); - $this->dispatcher->dispatch(TaskModel::EVENT_MOVE_POSITION, new TaskEvent($event_data)); + $this->queueManager->push($this->taskEventJob->withParams( + $task['id'], + array(TaskModel::EVENT_MOVE_POSITION), + $changes, + $changes + )); } } } diff --git a/app/Model/TaskProjectMoveModel.php b/app/Model/TaskProjectMoveModel.php index eda23c0b..ae3ae084 100644 --- a/app/Model/TaskProjectMoveModel.php +++ b/app/Model/TaskProjectMoveModel.php @@ -2,8 +2,6 @@ namespace Kanboard\Model; -use Kanboard\Event\TaskEvent; - /** * Task Project Move * @@ -32,9 +30,8 @@ class TaskProjectMoveModel extends TaskDuplicationModel $this->checkDestinationProjectValues($values); $this->tagDuplicationModel->syncTaskTagsToAnotherProject($task_id, $project_id); - if ($this->db->table(TaskModel::TABLE)->eq('id', $task['id'])->update($values)) { - $event = new TaskEvent(array_merge($task, $values, array('task_id' => $task['id']))); - $this->dispatcher->dispatch(TaskModel::EVENT_MOVE_PROJECT, $event); + if ($this->db->table(TaskModel::TABLE)->eq('id', $task_id)->update($values)) { + $this->queueManager->push($this->taskEventJob->withParams($task_id, array(TaskModel::EVENT_MOVE_PROJECT), $values)); } return true; diff --git a/app/Model/TaskStatusModel.php b/app/Model/TaskStatusModel.php index 4d573f0e..ea304beb 100644 --- a/app/Model/TaskStatusModel.php +++ b/app/Model/TaskStatusModel.php @@ -3,7 +3,6 @@ namespace Kanboard\Model; use Kanboard\Core\Base; -use Kanboard\Event\TaskEvent; /** * Task Status @@ -101,10 +100,10 @@ class TaskStatusModel extends Base * @param integer $task_id Task id * @param integer $status Task status * @param integer $date_completed Timestamp - * @param string $event Event name + * @param string $event_name Event name * @return boolean */ - private function changeStatus($task_id, $status, $date_completed, $event) + private function changeStatus($task_id, $status, $date_completed, $event_name) { if (! $this->taskFinderModel->exists($task_id)) { return false; @@ -120,8 +119,7 @@ class TaskStatusModel extends Base )); if ($result) { - $this->logger->debug('Event fired: '.$event); - $this->dispatcher->dispatch($event, new TaskEvent(array('task_id' => $task_id) + $this->taskFinderModel->getById($task_id))); + $this->queueManager->push($this->taskEventJob->withParams($task_id, array($event_name))); } return $result; diff --git a/app/ServiceProvider/JobProvider.php b/app/ServiceProvider/JobProvider.php index bfea6e6e..c7f323f1 100644 --- a/app/ServiceProvider/JobProvider.php +++ b/app/ServiceProvider/JobProvider.php @@ -6,6 +6,7 @@ use Kanboard\Job\CommentEventJob; use Kanboard\Job\NotificationJob; use Kanboard\Job\ProjectFileEventJob; use Kanboard\Job\SubtaskEventJob; +use Kanboard\Job\TaskEventJob; use Kanboard\Job\TaskFileEventJob; use Pimple\Container; use Pimple\ServiceProviderInterface; @@ -35,6 +36,10 @@ class JobProvider implements ServiceProviderInterface return new SubtaskEventJob($c); }); + $container['taskEventJob'] = $container->factory(function ($c) { + return new TaskEventJob($c); + }); + $container['taskFileEventJob'] = $container->factory(function ($c) { return new TaskFileEventJob($c); }); diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index 0b3760c4..104927a0 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -3,7 +3,6 @@ namespace Kanboard\Subscriber; use Kanboard\Event\GenericEvent; -use Kanboard\Job\NotificationJob; use Kanboard\Model\TaskModel; use Kanboard\Model\CommentModel; use Kanboard\Model\SubtaskModel; @@ -38,9 +37,6 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn public function handleEvent(GenericEvent $event, $eventName) { $this->logger->debug('Subscriber executed: ' . __METHOD__); - - $this->queueManager->push(NotificationJob::getInstance($this->container) - ->withParams($event, $eventName, get_class($event)) - ); + $this->queueManager->push($this->notificationJob->withParams($event, $eventName)); } } diff --git a/app/Subscriber/ProjectModificationDateSubscriber.php b/app/Subscriber/ProjectModificationDateSubscriber.php index 97923af9..1ffe0248 100644 --- a/app/Subscriber/ProjectModificationDateSubscriber.php +++ b/app/Subscriber/ProjectModificationDateSubscriber.php @@ -24,9 +24,7 @@ class ProjectModificationDateSubscriber extends BaseSubscriber implements EventS public function execute(GenericEvent $event) { - if (isset($event['project_id'])) { - $this->logger->debug('Subscriber executed: '.__METHOD__); - $this->projectModel->updateModificationDate($event['project_id']); - } + $this->logger->debug('Subscriber executed: '.__METHOD__); + $this->projectModel->updateModificationDate($event['task']['project_id']); } } diff --git a/tests/units/Action/BaseActionTest.php b/tests/units/Action/BaseActionTest.php index 1d50c70e..feeba3f9 100644 --- a/tests/units/Action/BaseActionTest.php +++ b/tests/units/Action/BaseActionTest.php @@ -23,7 +23,7 @@ class DummyAction extends Kanboard\Action\Base public function getEventRequiredParameters() { - return array('p1', 'p2'); + return array('p1', 'p2', 'p3' => array('p4')); } public function doAction(array $data) @@ -60,7 +60,7 @@ class BaseActionTest extends Base public function testGetEventRequiredParameters() { $dummyAction = new DummyAction($this->container); - $this->assertEquals(array('p1', 'p2'), $dummyAction->getEventRequiredParameters()); + $this->assertEquals(array('p1', 'p2', 'p3' => array('p4')), $dummyAction->getEventRequiredParameters()); } public function testGetCompatibleEvents() @@ -113,7 +113,7 @@ class BaseActionTest extends Base $dummyAction = new DummyAction($this->container); $dummyAction->setProjectId(1234); - $this->assertTrue($dummyAction->hasRequiredParameters(array('p1' => 12, 'p2' => 34))); + $this->assertTrue($dummyAction->hasRequiredParameters(array('p1' => 12, 'p2' => 34, 'p3' => array('p4' => 'foobar')))); $this->assertFalse($dummyAction->hasRequiredParameters(array('p1' => 12))); $this->assertFalse($dummyAction->hasRequiredParameters(array())); } @@ -125,7 +125,7 @@ class BaseActionTest extends Base $dummyAction->addEvent('my.event', 'My Event Overrided'); $events = $dummyAction->getEvents(); - $this->assertcount(2, $events); + $this->assertCount(2, $events); $this->assertEquals(array('my.event', 'foobar'), $events); } @@ -136,7 +136,7 @@ class BaseActionTest extends Base $dummyAction->setParam('p1', 'something'); $dummyAction->addEvent('foobar', 'FooBar'); - $event = new GenericEvent(array('project_id' => 1234, 'p1' => 'something', 'p2' => 'abc')); + $event = new GenericEvent(array('project_id' => 1234, 'p1' => 'something', 'p2' => 'abc', 'p3' => array('p4' => 'a'))); $this->assertTrue($dummyAction->execute($event, 'foobar')); $this->assertFalse($dummyAction->execute($event, 'foobar')); diff --git a/tests/units/Action/CommentCreationMoveTaskColumnTest.php b/tests/units/Action/CommentCreationMoveTaskColumnTest.php index 5eaf515e..b3d21287 100644 --- a/tests/units/Action/CommentCreationMoveTaskColumnTest.php +++ b/tests/units/Action/CommentCreationMoveTaskColumnTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\CommentModel; @@ -22,7 +22,7 @@ class CommentCreationMoveTaskColumnTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array('task' => array('project_id' => 1, 'column_id' => 2), 'task_id' => 1)); $action = new CommentCreationMoveTaskColumn($this->container); $action->setProjectId(1); @@ -45,7 +45,7 @@ class CommentCreationMoveTaskColumnTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + $event = new TaskEvent(array('task' => array('project_id' => 1, 'column_id' => 3), 'task_id' => 1)); $action = new CommentCreationMoveTaskColumn($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignCategoryColorTest.php b/tests/units/Action/TaskAssignCategoryColorTest.php index 09c08264..5a0f7d03 100644 --- a/tests/units/Action/TaskAssignCategoryColorTest.php +++ b/tests/units/Action/TaskAssignCategoryColorTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\CategoryModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; @@ -23,7 +23,13 @@ class TaskAssignCategoryColorTest extends Base $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'color_id' => 'red')); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'color_id' => 'red', + ) + )); $action = new TaskAssignCategoryColor($this->container); $action->setProjectId(1); @@ -47,7 +53,13 @@ class TaskAssignCategoryColorTest extends Base $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'color_id' => 'blue')); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'color_id' => 'blue', + ) + )); $action = new TaskAssignCategoryColor($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignCategoryLinkTest.php b/tests/units/Action/TaskAssignCategoryLinkTest.php index 712c3c02..d7e68f72 100644 --- a/tests/units/Action/TaskAssignCategoryLinkTest.php +++ b/tests/units/Action/TaskAssignCategoryLinkTest.php @@ -14,19 +14,19 @@ class TaskAssignCategoryLinkTest extends Base { public function testAssignCategory() { - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $c = new CategoryModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); $action->setParam('category_id', 1); $action->setParam('link_id', 2); - $this->assertEquals(1, $p->create(array('name' => 'P1'))); - $this->assertEquals(1, $c->create(array('name' => 'C1', 'project_id' => 1))); - $this->assertEquals(1, $tc->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'C1', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); $event = new TaskLinkEvent(array( 'project_id' => 1, @@ -37,25 +37,24 @@ class TaskAssignCategoryLinkTest extends Base $this->assertTrue($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); - $task = $tf->getById(1); + $task = $taskFinderModel->getById(1); $this->assertEquals(1, $task['category_id']); } public function testWhenLinkDontMatch() { - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $c = new CategoryModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); $action->setParam('category_id', 1); $action->setParam('link_id', 1); - $this->assertEquals(1, $p->create(array('name' => 'P1'))); - $this->assertEquals(1, $c->create(array('name' => 'C1', 'project_id' => 1))); - $this->assertEquals(1, $tc->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'C1', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); $event = new TaskLinkEvent(array( 'project_id' => 1, @@ -69,19 +68,19 @@ class TaskAssignCategoryLinkTest extends Base public function testThatExistingCategoryWillNotChange() { - $tc = new TaskCreationModel($this->container); - $p = new ProjectModel($this->container); - $c = new CategoryModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); $action->setParam('category_id', 2); $action->setParam('link_id', 2); - $this->assertEquals(1, $p->create(array('name' => 'P1'))); - $this->assertEquals(1, $c->create(array('name' => 'C1', 'project_id' => 1))); - $this->assertEquals(2, $c->create(array('name' => 'C2', 'project_id' => 1))); - $this->assertEquals(1, $tc->create(array('title' => 'T1', 'project_id' => 1, 'category_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'C1', 'project_id' => 1))); + $this->assertEquals(2, $categoryModel->create(array('name' => 'C2', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1, 'category_id' => 1))); $event = new TaskLinkEvent(array( 'project_id' => 1, diff --git a/tests/units/Action/TaskAssignColorCategoryTest.php b/tests/units/Action/TaskAssignColorCategoryTest.php index 6502035f..16ad1290 100644 --- a/tests/units/Action/TaskAssignColorCategoryTest.php +++ b/tests/units/Action/TaskAssignColorCategoryTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\CategoryModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; @@ -23,7 +23,13 @@ class TaskAssignColorCategoryTest extends Base $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'category_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'category_id' => 1, + ) + )); $action = new TaskAssignColorCategory($this->container); $action->setProjectId(1); @@ -45,7 +51,13 @@ class TaskAssignColorCategoryTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'category_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'category_id' => 2, + ) + )); $action = new TaskAssignColorCategory($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignColorColumnTest.php b/tests/units/Action/TaskAssignColorColumnTest.php index d4ba8e01..ccfb9e88 100644 --- a/tests/units/Action/TaskAssignColorColumnTest.php +++ b/tests/units/Action/TaskAssignColorColumnTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -20,7 +20,13 @@ class TaskAssignColorColumnTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskAssignColorColumn($this->container); $action->setProjectId(1); @@ -42,7 +48,13 @@ class TaskAssignColorColumnTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskAssignColorColumn($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignColorPriorityTest.php b/tests/units/Action/TaskAssignColorPriorityTest.php index 2fce8e66..0ea874cd 100644 --- a/tests/units/Action/TaskAssignColorPriorityTest.php +++ b/tests/units/Action/TaskAssignColorPriorityTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\CategoryModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; @@ -23,7 +23,13 @@ class TaskAssignColorPriorityTest extends Base $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'priority' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'priority' => 1, + ) + )); $action = new TaskAssignColorPriority($this->container); $action->setProjectId(1); @@ -45,7 +51,13 @@ class TaskAssignColorPriorityTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'priority' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'priority' => 2, + ) + )); $action = new TaskAssignColorPriority($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignColorUserTest.php b/tests/units/Action/TaskAssignColorUserTest.php index 370f9070..45faa3ff 100644 --- a/tests/units/Action/TaskAssignColorUserTest.php +++ b/tests/units/Action/TaskAssignColorUserTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -20,7 +20,13 @@ class TaskAssignColorUserTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'owner_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'owner_id' => 1, + ) + )); $action = new TaskAssignColorUser($this->container); $action->setProjectId(1); @@ -42,7 +48,13 @@ class TaskAssignColorUserTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'owner_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'owner_id' => 2, + ) + )); $action = new TaskAssignColorUser($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignCurrentUserColumnTest.php b/tests/units/Action/TaskAssignCurrentUserColumnTest.php index 6fdbda63..3b64d718 100644 --- a/tests/units/Action/TaskAssignCurrentUserColumnTest.php +++ b/tests/units/Action/TaskAssignCurrentUserColumnTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -22,7 +22,13 @@ class TaskAssignCurrentUserColumnTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskAssignCurrentUserColumn($this->container); $action->setProjectId(1); @@ -45,7 +51,13 @@ class TaskAssignCurrentUserColumnTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskAssignCurrentUserColumn($this->container); $action->setProjectId(1); @@ -62,7 +74,13 @@ class TaskAssignCurrentUserColumnTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskAssignCurrentUserColumn($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignSpecificUserTest.php b/tests/units/Action/TaskAssignSpecificUserTest.php index 78ec314f..0e63fc13 100644 --- a/tests/units/Action/TaskAssignSpecificUserTest.php +++ b/tests/units/Action/TaskAssignSpecificUserTest.php @@ -3,6 +3,7 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -20,7 +21,13 @@ class TaskAssignSpecificUserTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test', 'owner_id' => 0))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskAssignSpecificUser($this->container); $action->setProjectId(1); @@ -42,7 +49,13 @@ class TaskAssignSpecificUserTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskAssignSpecificUser($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskCloseColumnTest.php b/tests/units/Action/TaskCloseColumnTest.php index f9a938f0..7afb0478 100644 --- a/tests/units/Action/TaskCloseColumnTest.php +++ b/tests/units/Action/TaskCloseColumnTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -20,7 +20,13 @@ class TaskCloseColumnTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskCloseColumn($this->container); $action->setProjectId(1); @@ -41,7 +47,13 @@ class TaskCloseColumnTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskCloseColumn($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskCloseTest.php b/tests/units/Action/TaskCloseTest.php index 3df10cb8..589ef133 100644 --- a/tests/units/Action/TaskCloseTest.php +++ b/tests/units/Action/TaskCloseTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -19,7 +19,12 @@ class TaskCloseTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + ) + )); $action = new TaskClose($this->container); $action->setProjectId(1); @@ -40,7 +45,11 @@ class TaskCloseTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1)); + $event = new TaskEvent(array( + 'task' => array( + 'project_id' => 1, + ) + )); $action = new TaskClose($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskDuplicateAnotherProjectTest.php b/tests/units/Action/TaskDuplicateAnotherProjectTest.php index 98ff187f..5cd0c977 100644 --- a/tests/units/Action/TaskDuplicateAnotherProjectTest.php +++ b/tests/units/Action/TaskDuplicateAnotherProjectTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\TaskCreationModel; @@ -21,7 +21,13 @@ class TaskDuplicateAnotherProjectTest extends Base $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskDuplicateAnotherProject($this->container); $action->setProjectId(1); @@ -43,7 +49,13 @@ class TaskDuplicateAnotherProjectTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskDuplicateAnotherProject($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskEmailTest.php b/tests/units/Action/TaskEmailTest.php index df71aaf8..421c89ca 100644 --- a/tests/units/Action/TaskEmailTest.php +++ b/tests/units/Action/TaskEmailTest.php @@ -2,7 +2,8 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; +use Kanboard\Model\TaskFinderModel; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\ProjectModel; @@ -16,16 +17,20 @@ class TaskEmailTest extends Base $userModel = new UserModel($this->container); $projectModel = new ProjectModel($this->container); $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); $this->assertTrue($userModel->update(array('id' => 1, 'email' => 'admin@localhost'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => $taskFinderModel->getDetails(1) + )); $action = new TaskEmail($this->container); $action->setProjectId(1); - $action->setParam('column_id', 2); + $action->setParam('column_id', 1); $action->setParam('user_id', 1); $action->setParam('subject', 'My email subject'); @@ -47,7 +52,13 @@ class TaskEmailTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskEmail($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskMoveAnotherProjectTest.php b/tests/units/Action/TaskMoveAnotherProjectTest.php index d36df47b..a41fd03f 100644 --- a/tests/units/Action/TaskMoveAnotherProjectTest.php +++ b/tests/units/Action/TaskMoveAnotherProjectTest.php @@ -3,6 +3,7 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\TaskCreationModel; @@ -21,7 +22,13 @@ class TaskMoveAnotherProjectTest extends Base $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskMoveAnotherProject($this->container); $action->setProjectId(1); @@ -44,7 +51,13 @@ class TaskMoveAnotherProjectTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskMoveAnotherProject($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskMoveColumnAssignedTest.php b/tests/units/Action/TaskMoveColumnAssignedTest.php index f8982969..aa9d3592 100644 --- a/tests/units/Action/TaskMoveColumnAssignedTest.php +++ b/tests/units/Action/TaskMoveColumnAssignedTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\TaskCreationModel; @@ -19,9 +19,12 @@ class TaskMoveColumnAssignedTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test', 'owner_id' => 1))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 1, 'owner_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => $taskFinderModel->getDetails(1), + )); $action = new TaskMoveColumnAssigned($this->container); $action->setProjectId(1); @@ -43,7 +46,14 @@ class TaskMoveColumnAssignedTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3, 'owner_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + 'owner_id' => 1, + ) + )); $action = new TaskMoveColumnAssigned($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskMoveColumnCategoryChangeTest.php b/tests/units/Action/TaskMoveColumnCategoryChangeTest.php index c42383f8..7e0856df 100644 --- a/tests/units/Action/TaskMoveColumnCategoryChangeTest.php +++ b/tests/units/Action/TaskMoveColumnCategoryChangeTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\CategoryModel; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskFinderModel; @@ -24,7 +24,16 @@ class TaskMoveColumnCategoryChangeTest extends Base $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 1, 'category_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 1, + 'category_id' => 1, + 'position' => 1, + 'swimlane_id' => 0, + ) + )); $action = new TaskMoveColumnCategoryChange($this->container); $action->setProjectId(1); @@ -50,7 +59,14 @@ class TaskMoveColumnCategoryChangeTest extends Base $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2, 'category_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + 'category_id' => 1, + ) + )); $action = new TaskMoveColumnCategoryChange($this->container); $action->setProjectId(1); @@ -72,7 +88,14 @@ class TaskMoveColumnCategoryChangeTest extends Base $this->assertEquals(2, $categoryModel->create(array('name' => 'c2', 'project_id' => 1))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 1, 'category_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 1, + 'category_id' => 2, + ) + )); $action = new TaskMoveColumnCategoryChange($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskMoveColumnUnAssignedTest.php b/tests/units/Action/TaskMoveColumnUnAssignedTest.php index befae36b..b45dec08 100644 --- a/tests/units/Action/TaskMoveColumnUnAssignedTest.php +++ b/tests/units/Action/TaskMoveColumnUnAssignedTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\TaskCreationModel; @@ -21,7 +21,16 @@ class TaskMoveColumnUnAssignedTest extends Base $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 1, 'owner_id' => 0)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 1, + 'owner_id' => 0, + 'position' => 1, + 'swimlane_id' => 0, + ) + )); $action = new TaskMoveColumnUnAssigned($this->container); $action->setProjectId(1); @@ -43,7 +52,14 @@ class TaskMoveColumnUnAssignedTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2, 'owner_id' => 0)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + 'owner_id' => 0, + ) + )); $action = new TaskMoveColumnUnAssigned($this->container); $action->setProjectId(1); @@ -60,7 +76,14 @@ class TaskMoveColumnUnAssignedTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 1, 'owner_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 1, + 'owner_id' => 1, + ) + )); $action = new TaskMoveColumnUnAssigned($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskOpenTest.php b/tests/units/Action/TaskOpenTest.php index 1018e2ea..825c6ac9 100644 --- a/tests/units/Action/TaskOpenTest.php +++ b/tests/units/Action/TaskOpenTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -19,7 +19,12 @@ class TaskOpenTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test', 'is_active' => 0))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + ) + )); $action = new TaskOpen($this->container); $action->setProjectId(1); @@ -40,7 +45,11 @@ class TaskOpenTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1)); + $event = new TaskEvent(array( + 'task' => array( + 'project_id' => 1, + ) + )); $action = new TaskOpen($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskUpdateStartDateTest.php b/tests/units/Action/TaskUpdateStartDateTest.php index ddd9eafd..8d609b3e 100644 --- a/tests/units/Action/TaskUpdateStartDateTest.php +++ b/tests/units/Action/TaskUpdateStartDateTest.php @@ -3,6 +3,7 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -20,7 +21,13 @@ class TaskUpdateStartDateTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskUpdateStartDate($this->container); $action->setProjectId(1); @@ -41,7 +48,13 @@ class TaskUpdateStartDateTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskUpdateStartDate($this->container); $action->setProjectId(1); diff --git a/tests/units/EventBuilder/TaskEventBuilderTest.php b/tests/units/EventBuilder/TaskEventBuilderTest.php new file mode 100644 index 00000000..e6334fe2 --- /dev/null +++ b/tests/units/EventBuilder/TaskEventBuilderTest.php @@ -0,0 +1,100 @@ +container); + $taskEventBuilder->withTaskId(42); + $this->assertNull($taskEventBuilder->build()); + } + + public function testBuildWithTask() + { + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskEventBuilder = new TaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'before', 'project_id' => 1))); + + $event = $taskEventBuilder + ->withTaskId(1) + ->withTask(array('title' => 'before')) + ->withChanges(array('title' => 'after')) + ->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); + $this->assertNotEmpty($event['task']); + $this->assertEquals(1, $event['task_id']); + $this->assertEquals(array('title' => 'after'), $event['changes']); + } + + public function testBuildWithoutChanges() + { + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskEventBuilder = new TaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + + $event = $taskEventBuilder->withTaskId(1)->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); + $this->assertNotEmpty($event['task']); + $this->assertEquals(1, $event['task_id']); + $this->assertArrayNotHasKey('changes', $event); + } + + public function testBuildWithChanges() + { + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskEventBuilder = new TaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + + $event = $taskEventBuilder + ->withTaskId(1) + ->withChanges(array('title' => 'new title')) + ->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); + $this->assertNotEmpty($event['task']); + $this->assertNotEmpty($event['changes']); + $this->assertEquals('new title', $event['changes']['title']); + } + + public function testBuildWithChangesAndValues() + { + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskEventBuilder = new TaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + + $event = $taskEventBuilder + ->withTaskId(1) + ->withChanges(array('title' => 'new title', 'project_id' => 1)) + ->withValues(array('key' => 'value')) + ->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); + $this->assertNotEmpty($event['task']); + $this->assertNotEmpty($event['changes']); + $this->assertNotEmpty($event['key']); + $this->assertEquals('value', $event['key']); + + $this->assertCount(1, $event['changes']); + $this->assertEquals('new title', $event['changes']['title']); + } +} diff --git a/tests/units/Job/SubtaskEventJobTest.php b/tests/units/Job/SubtaskEventJobTest.php index 265a8e2d..66c3db05 100644 --- a/tests/units/Job/SubtaskEventJobTest.php +++ b/tests/units/Job/SubtaskEventJobTest.php @@ -21,8 +21,8 @@ class SubtaskEventJobTest extends Base { $this->container['dispatcher']->addListener(SubtaskModel::EVENT_CREATE, function() {}); - $SubtaskEventJob = new SubtaskEventJob($this->container); - $SubtaskEventJob->execute(42, SubtaskModel::EVENT_CREATE); + $subtaskEventJob = new SubtaskEventJob($this->container); + $subtaskEventJob->execute(42, SubtaskModel::EVENT_CREATE); $called = $this->container['dispatcher']->getCalledListeners(); $this->assertEmpty($called); diff --git a/tests/units/Job/TaskEventJobTest.php b/tests/units/Job/TaskEventJobTest.php new file mode 100644 index 00000000..c399faad --- /dev/null +++ b/tests/units/Job/TaskEventJobTest.php @@ -0,0 +1,189 @@ +container); + $taskEventJob->withParams(123, array('foobar'), array('k' => 'v'), array('k1' => 'v1'), array('k2' => 'v2')); + + $this->assertSame( + array(123, array('foobar'), array('k' => 'v'), array('k1' => 'v1'), array('k2' => 'v2')), + $taskEventJob->getJobParams() + ); + } + + public function testWithMissingTask() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE, function() {}); + + $taskEventJob = new TaskEventJob($this->container); + $taskEventJob->execute(42, array(TaskModel::EVENT_CREATE)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertEmpty($called); + } + + public function testTriggerCreateEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE, function() {}); + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_CREATE.'.closure', $called); + $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); + } + + public function testTriggerUpdateEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_UPDATE, function() {}); + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskModificationModel = new TaskModificationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($taskModificationModel->update(array('id' => 1, 'title' => 'new title'))); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_UPDATE.'.closure', $called); + $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); + } + + public function testTriggerAssigneeChangeEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_ASSIGNEE_CHANGE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskModificationModel = new TaskModificationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($taskModificationModel->update(array('id' => 1, 'owner_id' => 1))); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_ASSIGNEE_CHANGE.'.closure', $called); + } + + public function testTriggerCloseEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_CLOSE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskStatusModel = new TaskStatusModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($taskStatusModel->close(1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_CLOSE.'.closure', $called); + } + + public function testTriggerOpenEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_OPEN, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskStatusModel = new TaskStatusModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($taskStatusModel->close(1)); + $this->assertTrue($taskStatusModel->open(1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_OPEN.'.closure', $called); + } + + public function testTriggerMovePositionEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_POSITION, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskPositionModel = new TaskPositionModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'test 2', 'project_id' => 1))); + $this->assertTrue($taskPositionModel->movePosition(1, 1, 1, 2)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_POSITION.'.closure', $called); + } + + public function testTriggerMoveColumnEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_COLUMN, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskPositionModel = new TaskPositionModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 2)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_COLUMN.'.closure', $called); + } + + public function testTriggerMoveSwimlaneEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_SWIMLANE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskPositionModel = new TaskPositionModel($this->container); + $projectModel = new ProjectModel($this->container); + $swimlaneModel = new SwimlaneModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $swimlaneModel->create(array('name' => 'S1', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertTrue($taskPositionModel->movePosition(1, 1, 1, 1, 1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_SWIMLANE.'.closure', $called); + } + + public function testTriggerMoveProjectEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_PROJECT, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskProjectMoveModel = new TaskProjectMoveModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertTrue($taskProjectMoveModel->moveToProject(1, 1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_PROJECT.'.closure', $called); + } +} diff --git a/tests/units/Model/TaskCreationModelTest.php b/tests/units/Model/TaskCreationModelTest.php index f97c61dc..ce9996d9 100644 --- a/tests/units/Model/TaskCreationModelTest.php +++ b/tests/units/Model/TaskCreationModelTest.php @@ -17,7 +17,7 @@ class TaskCreationModelTest extends Base $event_data = $event->getAll(); $this->assertNotEmpty($event_data); $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals('test', $event_data['title']); + $this->assertEquals('test', $event_data['task']['title']); } public function testNoTitle() diff --git a/tests/units/Model/TaskModificationModelTest.php b/tests/units/Model/TaskModificationModelTest.php index c81f968b..f70561b3 100644 --- a/tests/units/Model/TaskModificationModelTest.php +++ b/tests/units/Model/TaskModificationModelTest.php @@ -18,7 +18,8 @@ class TaskModificationModelTest extends Base $event_data = $event->getAll(); $this->assertNotEmpty($event_data); $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals('Task #1', $event_data['title']); + $this->assertEquals('After', $event_data['task']['title']); + $this->assertEquals('After', $event_data['changes']['title']); } public function onUpdate($event) @@ -28,7 +29,7 @@ class TaskModificationModelTest extends Base $event_data = $event->getAll(); $this->assertNotEmpty($event_data); $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals('Task #1', $event_data['title']); + $this->assertEquals('After', $event_data['task']['title']); } public function onAssigneeChange($event) @@ -38,7 +39,7 @@ class TaskModificationModelTest extends Base $event_data = $event->getAll(); $this->assertNotEmpty($event_data); $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals(1, $event_data['owner_id']); + $this->assertEquals(1, $event_data['changes']['owner_id']); } public function testThatNoEventAreFiredWhenNoChanges() @@ -66,19 +67,19 @@ class TaskModificationModelTest extends Base $taskFinderModel = new TaskFinderModel($this->container); $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Before', 'project_id' => 1))); $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, array($this, 'onCreateUpdate')); $this->container['dispatcher']->addListener(TaskModel::EVENT_UPDATE, array($this, 'onUpdate')); - $this->assertTrue($taskModificationModel->update(array('id' => 1, 'title' => 'Task #1'))); + $this->assertTrue($taskModificationModel->update(array('id' => 1, 'title' => 'After'))); $called = $this->container['dispatcher']->getCalledListeners(); $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.TaskModificationModelTest::onCreateUpdate', $called); $this->assertArrayHasKey(TaskModel::EVENT_UPDATE.'.TaskModificationModelTest::onUpdate', $called); $task = $taskFinderModel->getById(1); - $this->assertEquals('Task #1', $task['title']); + $this->assertEquals('After', $task['title']); } public function testChangeAssignee() diff --git a/tests/units/Model/TaskPositionModelTest.php b/tests/units/Model/TaskPositionModelTest.php new file mode 100644 index 00000000..03caf7ed --- /dev/null +++ b/tests/units/Model/TaskPositionModelTest.php @@ -0,0 +1,631 @@ +container); + $taskStatusModel = new TaskStatusModel($this->container); + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $columnModel = new ColumnModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(0, $taskModel->getProgress($taskFinderModel->getById(1), $columnModel->getList(1))); + + $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 1)); + $this->assertEquals(25, $taskModel->getProgress($taskFinderModel->getById(1), $columnModel->getList(1))); + + $this->assertTrue($taskPositionModel->movePosition(1, 1, 3, 1)); + $this->assertEquals(50, $taskModel->getProgress($taskFinderModel->getById(1), $columnModel->getList(1))); + + $this->assertTrue($taskPositionModel->movePosition(1, 1, 4, 1)); + $this->assertEquals(75, $taskModel->getProgress($taskFinderModel->getById(1), $columnModel->getList(1))); + + $this->assertTrue($taskStatusModel->close(1)); + $this->assertEquals(100, $taskModel->getProgress($taskFinderModel->getById(1), $columnModel->getList(1))); + } + + public function testMoveTaskToWrongPosition() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + + // We move the task 2 to the position 0 + $this->assertFalse($taskPositionModel->movePosition(1, 1, 3, 0)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + } + + public function testMoveTaskToGreaterPosition() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + + // We move the task 2 to the position 42 + $this->assertTrue($taskPositionModel->movePosition(1, 1, 1, 42)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + } + + public function testMoveTaskToEmptyColumn() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + + // We move the task 1 to the column 3 + $this->assertTrue($taskPositionModel->movePosition(1, 1, 3, 1)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(3, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + } + + public function testMoveTaskToAnotherColumn() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(3, $taskCreationModel->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(4, $taskCreationModel->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 2))); + $this->assertEquals(5, $taskCreationModel->create(array('title' => 'Task #5', 'project_id' => 1, 'column_id' => 2))); + $this->assertEquals(6, $taskCreationModel->create(array('title' => 'Task #6', 'project_id' => 1, 'column_id' => 2))); + $this->assertEquals(7, $taskCreationModel->create(array('title' => 'Task #7', 'project_id' => 1, 'column_id' => 3))); + $this->assertEquals(8, $taskCreationModel->create(array('title' => 'Task #8', 'project_id' => 1, 'column_id' => 1))); + + // We move the task 3 to the column 3 + $this->assertTrue($taskPositionModel->movePosition(1, 3, 3, 2)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(3, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(5); + $this->assertEquals(5, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(6); + $this->assertEquals(6, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(3, $task['position']); + + $task = $taskFinderModel->getById(7); + $this->assertEquals(7, $task['id']); + $this->assertEquals(3, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(8); + $this->assertEquals(8, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(3, $task['position']); + } + + public function testMoveTaskTop() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(3, $taskCreationModel->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(4, $taskCreationModel->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); + + // Move the last task to the top + $this->assertTrue($taskPositionModel->movePosition(1, 4, 1, 1)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(3, $task['position']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(4, $task['position']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + } + + public function testMoveTaskBottom() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(3, $taskCreationModel->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(4, $taskCreationModel->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); + + // Move the first task to the bottom + $this->assertTrue($taskPositionModel->movePosition(1, 1, 1, 4)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(4, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(3, $task['position']); + } + + public function testMovePosition() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $counter = 1; + $task_per_column = 5; + + foreach (array(1, 2, 3, 4) as $column_id) { + for ($i = 1; $i <= $task_per_column; $i++, $counter++) { + $task = array( + 'title' => 'Task #'.$i.'-'.$column_id, + 'project_id' => 1, + 'column_id' => $column_id, + 'owner_id' => 0, + ); + + $this->assertEquals($counter, $taskCreationModel->create($task)); + + $task = $taskFinderModel->getById($counter); + $this->assertNotEmpty($task); + $this->assertEquals($i, $task['position']); + } + } + + // We move task id #4, column 1, position 4 to the column 2, position 3 + $this->assertTrue($taskPositionModel->movePosition(1, 4, 2, 3)); + + // We check the new position of the task + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(3, $task['position']); + + // The tasks before have the correct position + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(3, $task['position']); + + $task = $taskFinderModel->getById(7); + $this->assertEquals(7, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + + // The tasks after have the correct position + $task = $taskFinderModel->getById(5); + $this->assertEquals(5, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(4, $task['position']); + + $task = $taskFinderModel->getById(8); + $this->assertEquals(8, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(4, $task['position']); + + // The number of tasks per column + $this->assertEquals($task_per_column - 1, $taskFinderModel->countByColumnId(1, 1)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 2)); + $this->assertEquals($task_per_column, $taskFinderModel->countByColumnId(1, 3)); + $this->assertEquals($task_per_column, $taskFinderModel->countByColumnId(1, 4)); + + // We move task id #1, column 1, position 1 to the column 4, position 6 (last position) + $this->assertTrue($taskPositionModel->movePosition(1, 1, 4, $task_per_column + 1)); + + // We check the new position of the task + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(4, $task['column_id']); + $this->assertEquals($task_per_column + 1, $task['position']); + + // The tasks before have the correct position + $task = $taskFinderModel->getById(20); + $this->assertEquals(20, $task['id']); + $this->assertEquals(4, $task['column_id']); + $this->assertEquals($task_per_column, $task['position']); + + // The tasks after have the correct position + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + + // The number of tasks per column + $this->assertEquals($task_per_column - 2, $taskFinderModel->countByColumnId(1, 1)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 2)); + $this->assertEquals($task_per_column, $taskFinderModel->countByColumnId(1, 3)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 4)); + + // Our previous moved task should stay at the same place + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(3, $task['position']); + + // Test wrong position number + $this->assertFalse($taskPositionModel->movePosition(1, 2, 3, 0)); + $this->assertFalse($taskPositionModel->movePosition(1, 2, 3, -2)); + + // Wrong column + $this->assertFalse($taskPositionModel->movePosition(1, 2, 22, 2)); + + // Test position greater than the last position + $this->assertTrue($taskPositionModel->movePosition(1, 11, 1, 22)); + + $task = $taskFinderModel->getById(11); + $this->assertEquals(11, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals($taskFinderModel->countByColumnId(1, 1), $task['position']); + + $task = $taskFinderModel->getById(5); + $this->assertEquals(5, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals($taskFinderModel->countByColumnId(1, 1) - 1, $task['position']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(3, $task['position']); + + $this->assertEquals($task_per_column - 1, $taskFinderModel->countByColumnId(1, 1)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 2)); + $this->assertEquals($task_per_column - 1, $taskFinderModel->countByColumnId(1, 3)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 4)); + + // Our previous moved task should stay at the same place + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(3, $task['position']); + + // Test moving task to position 1 + $this->assertTrue($taskPositionModel->movePosition(1, 14, 1, 1)); + + $task = $taskFinderModel->getById(14); + $this->assertEquals(14, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $this->assertEquals($task_per_column, $taskFinderModel->countByColumnId(1, 1)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 2)); + $this->assertEquals($task_per_column - 2, $taskFinderModel->countByColumnId(1, 3)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 4)); + } + + public function testMoveTaskSwimlane() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $swimlaneModel = new SwimlaneModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $swimlaneModel->create(array('project_id' => 1, 'name' => 'test 1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(3, $taskCreationModel->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(4, $taskCreationModel->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(5, $taskCreationModel->create(array('title' => 'Task #5', 'project_id' => 1, 'column_id' => 1))); + + // Move the task to the swimlane + $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 1, 1)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(3, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + // Move the task to the swimlane + $this->assertTrue($taskPositionModel->movePosition(1, 2, 2, 1, 1)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + // Move the task 5 to the last column + $this->assertTrue($taskPositionModel->movePosition(1, 5, 4, 1, 0)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $task = $taskFinderModel->getById(5); + $this->assertEquals(5, $task['id']); + $this->assertEquals(4, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + } + + public function testEvents() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $swimlaneModel = new SwimlaneModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $swimlaneModel->create(array('project_id' => 1, 'name' => 'test 1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 2))); + + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_COLUMN, array($this, 'onMoveColumn')); + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_POSITION, array($this, 'onMovePosition')); + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_SWIMLANE, array($this, 'onMoveSwimlane')); + + // We move the task 1 to the column 2 + $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 1)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_COLUMN.'.TaskPositionModelTest::onMoveColumn', $called); + $this->assertEquals(1, count($called)); + + // We move the task 1 to the position 2 + $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 2)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_POSITION.'.TaskPositionModelTest::onMovePosition', $called); + $this->assertEquals(2, count($called)); + + // Move to another swimlane + $this->assertTrue($taskPositionModel->movePosition(1, 1, 3, 1, 1)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(3, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_SWIMLANE.'.TaskPositionModelTest::onMoveSwimlane', $called); + $this->assertEquals(3, count($called)); + } + + public function onMoveColumn($event) + { + $this->assertInstanceOf('Kanboard\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('Kanboard\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('Kanboard\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(3, $event_data['column_id']); + $this->assertEquals(1, $event_data['project_id']); + $this->assertEquals(1, $event_data['swimlane_id']); + } +} diff --git a/tests/units/Model/TaskPositionTest.php b/tests/units/Model/TaskPositionTest.php deleted file mode 100644 index 7ab6950e..00000000 --- a/tests/units/Model/TaskPositionTest.php +++ /dev/null @@ -1,631 +0,0 @@ -container); - $ts = new TaskStatusModel($this->container); - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $columnModel = new ColumnModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(0, $t->getProgress($tf->getById(1), $columnModel->getList(1))); - - $this->assertTrue($tp->movePosition(1, 1, 2, 1)); - $this->assertEquals(25, $t->getProgress($tf->getById(1), $columnModel->getList(1))); - - $this->assertTrue($tp->movePosition(1, 1, 3, 1)); - $this->assertEquals(50, $t->getProgress($tf->getById(1), $columnModel->getList(1))); - - $this->assertTrue($tp->movePosition(1, 1, 4, 1)); - $this->assertEquals(75, $t->getProgress($tf->getById(1), $columnModel->getList(1))); - - $this->assertTrue($ts->close(1)); - $this->assertEquals(100, $t->getProgress($tf->getById(1), $columnModel->getList(1))); - } - - public function testMoveTaskToWrongPosition() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - - $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' => 1))); - - // We move the task 2 to the position 0 - $this->assertFalse($tp->movePosition(1, 1, 3, 0)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - } - - public function testMoveTaskToGreaterPosition() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - - $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' => 1))); - - // We move the task 2 to the position 42 - $this->assertTrue($tp->movePosition(1, 1, 1, 42)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - } - - public function testMoveTaskToEmptyColumn() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - - $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' => 1))); - - // We move the task 1 to the column 3 - $this->assertTrue($tp->movePosition(1, 1, 3, 1)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(3, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - } - - public function testMoveTaskToAnotherColumn() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - - $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' => 1))); - $this->assertEquals(3, $tc->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(4, $tc->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 2))); - $this->assertEquals(5, $tc->create(array('title' => 'Task #5', 'project_id' => 1, 'column_id' => 2))); - $this->assertEquals(6, $tc->create(array('title' => 'Task #6', 'project_id' => 1, 'column_id' => 2))); - $this->assertEquals(7, $tc->create(array('title' => 'Task #7', 'project_id' => 1, 'column_id' => 3))); - $this->assertEquals(8, $tc->create(array('title' => 'Task #8', 'project_id' => 1, 'column_id' => 1))); - - // We move the task 3 to the column 3 - $this->assertTrue($tp->movePosition(1, 3, 3, 2)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(3, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(5); - $this->assertEquals(5, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(6); - $this->assertEquals(6, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(3, $task['position']); - - $task = $tf->getById(7); - $this->assertEquals(7, $task['id']); - $this->assertEquals(3, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(8); - $this->assertEquals(8, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(3, $task['position']); - } - - public function testMoveTaskTop() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $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' => 1))); - $this->assertEquals(3, $tc->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(4, $tc->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); - - // Move the last task to the top - $this->assertTrue($tp->movePosition(1, 4, 1, 1)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(3, $task['position']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(4, $task['position']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - } - - public function testMoveTaskBottom() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $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' => 1))); - $this->assertEquals(3, $tc->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(4, $tc->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); - - // Move the first task to the bottom - $this->assertTrue($tp->movePosition(1, 1, 1, 4)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(4, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(3, $task['position']); - } - - public function testMovePosition() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $counter = 1; - $task_per_column = 5; - - foreach (array(1, 2, 3, 4) as $column_id) { - for ($i = 1; $i <= $task_per_column; $i++, $counter++) { - $task = array( - 'title' => 'Task #'.$i.'-'.$column_id, - 'project_id' => 1, - 'column_id' => $column_id, - 'owner_id' => 0, - ); - - $this->assertEquals($counter, $tc->create($task)); - - $task = $tf->getById($counter); - $this->assertNotEmpty($task); - $this->assertEquals($i, $task['position']); - } - } - - // We move task id #4, column 1, position 4 to the column 2, position 3 - $this->assertTrue($tp->movePosition(1, 4, 2, 3)); - - // We check the new position of the task - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(3, $task['position']); - - // The tasks before have the correct position - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(3, $task['position']); - - $task = $tf->getById(7); - $this->assertEquals(7, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - - // The tasks after have the correct position - $task = $tf->getById(5); - $this->assertEquals(5, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(4, $task['position']); - - $task = $tf->getById(8); - $this->assertEquals(8, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(4, $task['position']); - - // The number of tasks per column - $this->assertEquals($task_per_column - 1, $tf->countByColumnId(1, 1)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 2)); - $this->assertEquals($task_per_column, $tf->countByColumnId(1, 3)); - $this->assertEquals($task_per_column, $tf->countByColumnId(1, 4)); - - // We move task id #1, column 1, position 1 to the column 4, position 6 (last position) - $this->assertTrue($tp->movePosition(1, 1, 4, $task_per_column + 1)); - - // We check the new position of the task - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(4, $task['column_id']); - $this->assertEquals($task_per_column + 1, $task['position']); - - // The tasks before have the correct position - $task = $tf->getById(20); - $this->assertEquals(20, $task['id']); - $this->assertEquals(4, $task['column_id']); - $this->assertEquals($task_per_column, $task['position']); - - // The tasks after have the correct position - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - - // The number of tasks per column - $this->assertEquals($task_per_column - 2, $tf->countByColumnId(1, 1)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 2)); - $this->assertEquals($task_per_column, $tf->countByColumnId(1, 3)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 4)); - - // Our previous moved task should stay at the same place - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(3, $task['position']); - - // Test wrong position number - $this->assertFalse($tp->movePosition(1, 2, 3, 0)); - $this->assertFalse($tp->movePosition(1, 2, 3, -2)); - - // Wrong column - $this->assertFalse($tp->movePosition(1, 2, 22, 2)); - - // Test position greater than the last position - $this->assertTrue($tp->movePosition(1, 11, 1, 22)); - - $task = $tf->getById(11); - $this->assertEquals(11, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals($tf->countByColumnId(1, 1), $task['position']); - - $task = $tf->getById(5); - $this->assertEquals(5, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals($tf->countByColumnId(1, 1) - 1, $task['position']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(3, $task['position']); - - $this->assertEquals($task_per_column - 1, $tf->countByColumnId(1, 1)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 2)); - $this->assertEquals($task_per_column - 1, $tf->countByColumnId(1, 3)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 4)); - - // Our previous moved task should stay at the same place - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(3, $task['position']); - - // Test moving task to position 1 - $this->assertTrue($tp->movePosition(1, 14, 1, 1)); - - $task = $tf->getById(14); - $this->assertEquals(14, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $this->assertEquals($task_per_column, $tf->countByColumnId(1, 1)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 2)); - $this->assertEquals($task_per_column - 2, $tf->countByColumnId(1, 3)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 4)); - } - - public function testMoveTaskSwimlane() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $s = new SwimlaneModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $s->create(array('project_id' => 1, 'name' => 'test 1'))); - $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' => 1))); - $this->assertEquals(3, $tc->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(4, $tc->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(5, $tc->create(array('title' => 'Task #5', 'project_id' => 1, 'column_id' => 1))); - - // Move the task to the swimlane - $this->assertTrue($tp->movePosition(1, 1, 2, 1, 1)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(3, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - // Move the task to the swimlane - $this->assertTrue($tp->movePosition(1, 2, 2, 1, 1)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - // Move the task 5 to the last column - $this->assertTrue($tp->movePosition(1, 5, 4, 1, 0)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $task = $tf->getById(5); - $this->assertEquals(5, $task['id']); - $this->assertEquals(4, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - } - - public function testEvents() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $s = new SwimlaneModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $s->create(array('project_id' => 1, 'name' => 'test 1'))); - - $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(TaskModel::EVENT_MOVE_COLUMN, array($this, 'onMoveColumn')); - $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_POSITION, array($this, 'onMovePosition')); - $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_SWIMLANE, array($this, 'onMoveSwimlane')); - - // We move the task 1 to the column 2 - $this->assertTrue($tp->movePosition(1, 1, 2, 1)); - - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::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)); - - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_POSITION.'.TaskPositionTest::onMovePosition', $called); - $this->assertEquals(2, count($called)); - - // Move to another swimlane - $this->assertTrue($tp->movePosition(1, 1, 3, 1, 1)); - - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(3, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_SWIMLANE.'.TaskPositionTest::onMoveSwimlane', $called); - $this->assertEquals(3, count($called)); - } - - public function onMoveColumn($event) - { - $this->assertInstanceOf('Kanboard\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('Kanboard\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('Kanboard\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(3, $event_data['column_id']); - $this->assertEquals(1, $event_data['project_id']); - $this->assertEquals(1, $event_data['swimlane_id']); - } -} diff --git a/tests/units/Model/TaskProjectMoveModelTest.php b/tests/units/Model/TaskProjectMoveModelTest.php index c4282638..52f61b28 100644 --- a/tests/units/Model/TaskProjectMoveModelTest.php +++ b/tests/units/Model/TaskProjectMoveModelTest.php @@ -24,7 +24,7 @@ class TaskProjectMoveModelTest extends Base $event_data = $event->getAll(); $this->assertNotEmpty($event_data); $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals('test', $event_data['title']); + $this->assertEquals('test', $event_data['task']['title']); } public function testMoveAnotherProject() -- cgit v1.2.3 From 3dd20c9c78e61028a4c7db232c7b2b30662a2987 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Wed, 20 Jul 2016 21:47:23 -0400 Subject: Rename CommentModel::EVENT_REMOVE to CommentModel::EVENT_DELETE --- app/Model/CommentModel.php | 4 ++-- app/Model/NotificationModel.php | 6 +++--- app/Subscriber/NotificationSubscriber.php | 2 +- app/Template/event/comment_delete.php | 11 +++++++++++ app/Template/event/comment_remove.php | 11 ----------- app/Template/notification/comment_delete.php | 7 +++++++ app/Template/notification/comment_remove.php | 7 ------- tests/units/Job/CommentEventJobTest.php | 4 ++-- 8 files changed, 26 insertions(+), 26 deletions(-) create mode 100644 app/Template/event/comment_delete.php delete mode 100644 app/Template/event/comment_remove.php create mode 100644 app/Template/notification/comment_delete.php delete mode 100644 app/Template/notification/comment_remove.php (limited to 'app/Subscriber') diff --git a/app/Model/CommentModel.php b/app/Model/CommentModel.php index 6b983858..a9e48bd3 100644 --- a/app/Model/CommentModel.php +++ b/app/Model/CommentModel.php @@ -26,7 +26,7 @@ class CommentModel extends Base */ const EVENT_UPDATE = 'comment.update'; const EVENT_CREATE = 'comment.create'; - const EVENT_REMOVE = 'comment.remove'; + const EVENT_DELETE = 'comment.delete'; const EVENT_USER_MENTION = 'comment.user.mention'; /** @@ -166,7 +166,7 @@ class CommentModel extends Base */ public function remove($comment_id) { - $this->commentEventJob->execute($comment_id, self::EVENT_REMOVE); + $this->commentEventJob->execute($comment_id, self::EVENT_DELETE); return $this->db->table(self::TABLE)->eq('id', $comment_id)->remove(); } } diff --git a/app/Model/NotificationModel.php b/app/Model/NotificationModel.php index ac8d9bae..925d646e 100644 --- a/app/Model/NotificationModel.php +++ b/app/Model/NotificationModel.php @@ -76,7 +76,7 @@ class NotificationModel extends Base return e('%s updated a comment on the task #%d', $event_author, $event_data['task']['id']); case CommentModel::EVENT_CREATE: return e('%s commented on the task #%d', $event_author, $event_data['task']['id']); - case CommentModel::EVENT_REMOVE: + case CommentModel::EVENT_DELETE: return e('%s removed a comment on the task #%d', $event_author, $event_data['task']['id']); case TaskFileModel::EVENT_CREATE: return e('%s attached a file to the task #%d', $event_author, $event_data['task']['id']); @@ -106,7 +106,7 @@ class NotificationModel extends Base return e('New comment on task #%d', $event_data['comment']['task_id']); case CommentModel::EVENT_UPDATE: return e('Comment updated on task #%d', $event_data['comment']['task_id']); - case CommentModel::EVENT_REMOVE: + case CommentModel::EVENT_DELETE: return e('Comment removed on task #%d', $event_data['comment']['task_id']); case SubtaskModel::EVENT_CREATE: return e('New subtask on task #%d', $event_data['subtask']['task_id']); @@ -157,7 +157,7 @@ class NotificationModel extends Base return $event_data['file']['task_id']; case CommentModel::EVENT_CREATE: case CommentModel::EVENT_UPDATE: - case CommentModel::EVENT_REMOVE: + case CommentModel::EVENT_DELETE: return $event_data['comment']['task_id']; case SubtaskModel::EVENT_CREATE: case SubtaskModel::EVENT_UPDATE: diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index 104927a0..7de24e49 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -28,7 +28,7 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn SubtaskModel::EVENT_DELETE => 'handleEvent', CommentModel::EVENT_CREATE => 'handleEvent', CommentModel::EVENT_UPDATE => 'handleEvent', - CommentModel::EVENT_REMOVE => 'handleEvent', + CommentModel::EVENT_DELETE => 'handleEvent', CommentModel::EVENT_USER_MENTION => 'handleEvent', TaskFileModel::EVENT_CREATE => 'handleEvent', ); diff --git a/app/Template/event/comment_delete.php b/app/Template/event/comment_delete.php new file mode 100644 index 00000000..ead7d56a --- /dev/null +++ b/app/Template/event/comment_delete.php @@ -0,0 +1,11 @@ +

+ text->e($author), + $this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) + ) ?> + dt->datetime($date_creation) ?> +

+
+

text->e($task['title']) ?>

+
text->markdown($comment['comment']) ?>
+
diff --git a/app/Template/event/comment_remove.php b/app/Template/event/comment_remove.php deleted file mode 100644 index ead7d56a..00000000 --- a/app/Template/event/comment_remove.php +++ /dev/null @@ -1,11 +0,0 @@ -

- text->e($author), - $this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) - ) ?> - dt->datetime($date_creation) ?> -

-
-

text->e($task['title']) ?>

-
text->markdown($comment['comment']) ?>
-
diff --git a/app/Template/notification/comment_delete.php b/app/Template/notification/comment_delete.php new file mode 100644 index 00000000..928623ec --- /dev/null +++ b/app/Template/notification/comment_delete.php @@ -0,0 +1,7 @@ +

text->e($task['title']) ?> (#)

+ +

+ +text->markdown($comment['comment']) ?> + +render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/app/Template/notification/comment_remove.php b/app/Template/notification/comment_remove.php deleted file mode 100644 index 928623ec..00000000 --- a/app/Template/notification/comment_remove.php +++ /dev/null @@ -1,7 +0,0 @@ -

text->e($task['title']) ?> (#)

- -

- -text->markdown($comment['comment']) ?> - -render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/tests/units/Job/CommentEventJobTest.php b/tests/units/Job/CommentEventJobTest.php index 88742feb..8571af8e 100644 --- a/tests/units/Job/CommentEventJobTest.php +++ b/tests/units/Job/CommentEventJobTest.php @@ -32,7 +32,7 @@ class CommentEventJobTest extends Base { $this->container['dispatcher']->addListener(CommentModel::EVENT_CREATE, function() {}); $this->container['dispatcher']->addListener(CommentModel::EVENT_UPDATE, function() {}); - $this->container['dispatcher']->addListener(CommentModel::EVENT_REMOVE, function() {}); + $this->container['dispatcher']->addListener(CommentModel::EVENT_DELETE, function() {}); $commentModel = new CommentModel($this->container); $taskCreationModel = new TaskCreationModel($this->container); @@ -47,6 +47,6 @@ class CommentEventJobTest extends Base $called = $this->container['dispatcher']->getCalledListeners(); $this->assertArrayHasKey(CommentModel::EVENT_CREATE.'.closure', $called); $this->assertArrayHasKey(CommentModel::EVENT_UPDATE.'.closure', $called); - $this->assertArrayHasKey(CommentModel::EVENT_REMOVE.'.closure', $called); + $this->assertArrayHasKey(CommentModel::EVENT_DELETE.'.closure', $called); } } -- cgit v1.2.3 From b6119e7dee84869a619dedccd9c80df4422a4f5b Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 23 Jul 2016 14:05:15 -0400 Subject: Added internal task links to activity stream --- ChangeLog | 1 + app/Action/TaskAssignCategoryLink.php | 13 +- app/Action/TaskAssignColorLink.php | 10 +- app/Core/Base.php | 1 + app/EventBuilder/TaskLinkEventBuilder.php | 89 +++++++++++ app/Helper/HookHelper.php | 2 +- app/Job/TaskLinkEventJob.php | 45 ++++++ app/Model/NotificationModel.php | 39 ++--- app/Model/TaskLinkModel.php | 173 ++++++++++++--------- app/ServiceProvider/JobProvider.php | 5 + app/Subscriber/NotificationSubscriber.php | 3 + .../event/task_internal_link_create_update.php | 16 ++ app/Template/event/task_internal_link_delete.php | 16 ++ app/Template/notification/task_file_create.php | 2 +- .../task_internal_link_create_update.php | 11 ++ .../notification/task_internal_link_delete.php | 11 ++ tests/units/Action/TaskAssignCategoryLinkTest.php | 51 +++--- tests/units/Action/TaskAssignColorLinkTest.php | 45 ++++-- .../EventBuilder/TaskLinkEventBuilderTest.php | 70 +++++++++ tests/units/Job/TaskLinkEventJobTest.php | 65 ++++++++ tests/units/Model/NotificationModelTest.php | 39 ++--- tests/units/Model/TaskLinkModelTest.php | 28 ++++ tests/units/Notification/MailNotificationTest.php | 117 ++++++++++++++ tests/units/Notification/MailTest.php | 117 -------------- .../units/Notification/WebhookNotificationTest.php | 29 ++++ tests/units/Notification/WebhookTest.php | 29 ---- 26 files changed, 705 insertions(+), 322 deletions(-) create mode 100644 app/EventBuilder/TaskLinkEventBuilder.php create mode 100644 app/Job/TaskLinkEventJob.php create mode 100644 app/Template/event/task_internal_link_create_update.php create mode 100644 app/Template/event/task_internal_link_delete.php create mode 100644 app/Template/notification/task_internal_link_create_update.php create mode 100644 app/Template/notification/task_internal_link_delete.php create mode 100644 tests/units/EventBuilder/TaskLinkEventBuilderTest.php create mode 100644 tests/units/Job/TaskLinkEventJobTest.php create mode 100644 tests/units/Notification/MailNotificationTest.php delete mode 100644 tests/units/Notification/MailTest.php create mode 100644 tests/units/Notification/WebhookNotificationTest.php delete mode 100644 tests/units/Notification/WebhookTest.php (limited to 'app/Subscriber') diff --git a/ChangeLog b/ChangeLog index a1e39436..ee57c86c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Version 1.0.32 (unreleased) New features: * New automated action to close tasks without activity in a specific column +* Added internal task links to activity stream * Added new event for removed comments * Added search filter for task priority * Added the possibility to hide tasks in dashboard for a specific column diff --git a/app/Action/TaskAssignCategoryLink.php b/app/Action/TaskAssignCategoryLink.php index 6937edd1..d4a4c0ec 100644 --- a/app/Action/TaskAssignCategoryLink.php +++ b/app/Action/TaskAssignCategoryLink.php @@ -60,8 +60,10 @@ class TaskAssignCategoryLink extends Base public function getEventRequiredParameters() { return array( - 'task_id', - 'link_id', + 'task_link' => array( + 'task_id', + 'link_id', + ) ); } @@ -75,7 +77,7 @@ class TaskAssignCategoryLink extends Base public function doAction(array $data) { $values = array( - 'id' => $data['task_id'], + 'id' => $data['task_link']['task_id'], 'category_id' => $this->getParam('category_id'), ); @@ -91,9 +93,8 @@ class TaskAssignCategoryLink extends Base */ public function hasRequiredCondition(array $data) { - if ($data['link_id'] == $this->getParam('link_id')) { - $task = $this->taskFinderModel->getById($data['task_id']); - return empty($task['category_id']); + if ($data['task_link']['link_id'] == $this->getParam('link_id')) { + return empty($data['task']['category_id']); } return false; diff --git a/app/Action/TaskAssignColorLink.php b/app/Action/TaskAssignColorLink.php index 9ab5458b..9759f622 100644 --- a/app/Action/TaskAssignColorLink.php +++ b/app/Action/TaskAssignColorLink.php @@ -59,8 +59,10 @@ class TaskAssignColorLink extends Base public function getEventRequiredParameters() { return array( - 'task_id', - 'link_id', + 'task_link' => array( + 'task_id', + 'link_id', + ) ); } @@ -74,7 +76,7 @@ class TaskAssignColorLink extends Base public function doAction(array $data) { $values = array( - 'id' => $data['task_id'], + 'id' => $data['task_link']['task_id'], 'color_id' => $this->getParam('color_id'), ); @@ -90,6 +92,6 @@ class TaskAssignColorLink extends Base */ public function hasRequiredCondition(array $data) { - return $data['link_id'] == $this->getParam('link_id'); + return $data['task_link']['link_id'] == $this->getParam('link_id'); } } diff --git a/app/Core/Base.php b/app/Core/Base.php index 098bd880..20a2d391 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -154,6 +154,7 @@ use Pimple\Container; * @property \Kanboard\Job\SubtaskEventJob $subtaskEventJob * @property \Kanboard\Job\TaskEventJob $taskEventJob * @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob + * @property \Kanboard\Job\TaskLinkEventJob $taskLinkEventJob * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob * @property \Kanboard\Job\NotificationJob $notificationJob * @property \Psr\Log\LoggerInterface $logger diff --git a/app/EventBuilder/TaskLinkEventBuilder.php b/app/EventBuilder/TaskLinkEventBuilder.php new file mode 100644 index 00000000..8be5299f --- /dev/null +++ b/app/EventBuilder/TaskLinkEventBuilder.php @@ -0,0 +1,89 @@ +taskLinkId = $taskLinkId; + return $this; + } + + /** + * Build event data + * + * @access public + * @return TaskLinkEvent|null + */ + public function build() + { + $taskLink = $this->taskLinkModel->getById($this->taskLinkId); + + if (empty($taskLink)) { + $this->logger->debug(__METHOD__.': TaskLink not found'); + return null; + } + + return new TaskLinkEvent(array( + 'task_link' => $taskLink, + 'task' => $this->taskFinderModel->getDetails($taskLink['task_id']), + )); + } + + /** + * Get event title with author + * + * @access public + * @param string $author + * @param string $eventName + * @param array $eventData + * @return string + */ + public function buildTitleWithAuthor($author, $eventName, array $eventData) + { + if ($eventName === TaskLinkModel::EVENT_CREATE_UPDATE) { + return e('%s set a new internal link for the task #%d', $author, $eventData['task']['id']); + } elseif ($eventName === TaskLinkModel::EVENT_DELETE) { + return e('%s removed an internal link for the task #%d', $author, $eventData['task']['id']); + } + + return ''; + } + + /** + * Get event title without author + * + * @access public + * @param string $eventName + * @param array $eventData + * @return string + */ + public function buildTitleWithoutAuthor($eventName, array $eventData) + { + if ($eventName === TaskLinkModel::EVENT_CREATE_UPDATE) { + return e('A new internal link for the task #%d have been defined', $eventData['task']['id']); + } elseif ($eventName === TaskLinkModel::EVENT_DELETE) { + return e('Internal link removed for the task #%d', $eventData['task']['id']); + } + + return ''; + } +} diff --git a/app/Helper/HookHelper.php b/app/Helper/HookHelper.php index 2d13ebcc..cb4dc1ef 100644 --- a/app/Helper/HookHelper.php +++ b/app/Helper/HookHelper.php @@ -56,7 +56,7 @@ class HookHelper extends Base * @access public * @param string $hook * @param string $template - * @return \Kanboard\Helper\Hook + * @return $this */ public function attach($hook, $template) { diff --git a/app/Job/TaskLinkEventJob.php b/app/Job/TaskLinkEventJob.php new file mode 100644 index 00000000..669608ad --- /dev/null +++ b/app/Job/TaskLinkEventJob.php @@ -0,0 +1,45 @@ +jobParams = array($taskLinkId, $eventName); + return $this; + } + + /** + * Execute job + * + * @param int $taskLinkId + * @param string $eventName + * @return $this + */ + public function execute($taskLinkId, $eventName) + { + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId($taskLinkId) + ->build(); + + if ($event !== null) { + $this->dispatcher->dispatch($eventName, $event); + } + } +} diff --git a/app/Model/NotificationModel.php b/app/Model/NotificationModel.php index 925d646e..39c1f581 100644 --- a/app/Model/NotificationModel.php +++ b/app/Model/NotificationModel.php @@ -3,6 +3,7 @@ namespace Kanboard\Model; use Kanboard\Core\Base; +use Kanboard\EventBuilder\TaskLinkEventBuilder; /** * Notification @@ -85,7 +86,9 @@ class NotificationModel extends Base case CommentModel::EVENT_USER_MENTION: return e('%s mentioned you in a comment on the task #%d', $event_author, $event_data['task']['id']); default: - return e('Notification'); + return TaskLinkEventBuilder::getInstance($this->container) + ->buildTitleWithAuthor($event_author, $event_name, $event_data) ?: + e('Notification'); } } @@ -138,7 +141,9 @@ class NotificationModel extends Base case CommentModel::EVENT_USER_MENTION: return e('You were mentioned in a comment on the task #%d', $event_data['task']['id']); default: - return e('Notification'); + return TaskLinkEventBuilder::getInstance($this->container) + ->buildTitleWithoutAuthor($event_name, $event_data) ?: + e('Notification'); } } @@ -152,32 +157,10 @@ class NotificationModel extends Base */ public function getTaskIdFromEvent($event_name, array $event_data) { - switch ($event_name) { - case TaskFileModel::EVENT_CREATE: - return $event_data['file']['task_id']; - case CommentModel::EVENT_CREATE: - case CommentModel::EVENT_UPDATE: - case CommentModel::EVENT_DELETE: - return $event_data['comment']['task_id']; - case SubtaskModel::EVENT_CREATE: - case SubtaskModel::EVENT_UPDATE: - case SubtaskModel::EVENT_DELETE: - return $event_data['subtask']['task_id']; - case TaskModel::EVENT_CREATE: - case TaskModel::EVENT_UPDATE: - case TaskModel::EVENT_CLOSE: - case TaskModel::EVENT_OPEN: - case TaskModel::EVENT_MOVE_COLUMN: - case TaskModel::EVENT_MOVE_POSITION: - case TaskModel::EVENT_MOVE_SWIMLANE: - case TaskModel::EVENT_ASSIGNEE_CHANGE: - case CommentModel::EVENT_USER_MENTION: - case TaskModel::EVENT_USER_MENTION: - return $event_data['task']['id']; - case TaskModel::EVENT_OVERDUE: - return $event_data['tasks'][0]['id']; - default: - return 0; + if ($event_name === TaskModel::EVENT_OVERDUE) { + return $event_data['tasks'][0]['id']; } + + return isset($event_data['task']['id']) ? $event_data['task']['id'] : 0; } } diff --git a/app/Model/TaskLinkModel.php b/app/Model/TaskLinkModel.php index 09978eae..e8d3c5df 100644 --- a/app/Model/TaskLinkModel.php +++ b/app/Model/TaskLinkModel.php @@ -3,7 +3,6 @@ namespace Kanboard\Model; use Kanboard\Core\Base; -use Kanboard\Event\TaskLinkEvent; /** * TaskLink model @@ -26,7 +25,8 @@ class TaskLinkModel extends Base * * @var string */ - const EVENT_CREATE_UPDATE = 'tasklink.create_update'; + const EVENT_CREATE_UPDATE = 'task_internal_link.create_update'; + const EVENT_DELETE = 'task_internal_link.delete'; /** * Get projectId from $task_link_id @@ -53,7 +53,19 @@ class TaskLinkModel extends Base */ public function getById($task_link_id) { - return $this->db->table(self::TABLE)->eq('id', $task_link_id)->findOne(); + return $this->db + ->table(self::TABLE) + ->columns( + self::TABLE.'.id', + self::TABLE.'.opposite_task_id', + self::TABLE.'.task_id', + self::TABLE.'.link_id', + LinkModel::TABLE.'.label', + LinkModel::TABLE.'.opposite_id AS opposite_link_id' + ) + ->eq(self::TABLE.'.id', $task_link_id) + ->join(LinkModel::TABLE, 'id', 'link_id') + ->findOne(); } /** @@ -139,20 +151,6 @@ class TaskLinkModel extends Base return $result; } - /** - * Publish events - * - * @access private - * @param array $events - */ - private function fireEvents(array $events) - { - foreach ($events as $event) { - $event['project_id'] = $this->taskFinderModel->getProjectId($event['task_id']); - $this->container['dispatcher']->dispatch(self::EVENT_CREATE_UPDATE, new TaskLinkEvent($event)); - } - } - /** * Create a new link * @@ -160,42 +158,25 @@ class TaskLinkModel extends Base * @param integer $task_id Task id * @param integer $opposite_task_id Opposite task id * @param integer $link_id Link id - * @return integer Task link id + * @return integer|boolean */ public function create($task_id, $opposite_task_id, $link_id) { - $events = array(); $this->db->startTransaction(); - // Get opposite link $opposite_link_id = $this->linkModel->getOppositeLinkId($link_id); + $task_link_id1 = $this->createTaskLink($task_id, $opposite_task_id, $link_id); + $task_link_id2 = $this->createTaskLink($opposite_task_id, $task_id, $opposite_link_id); - $values = array( - 'task_id' => $task_id, - 'opposite_task_id' => $opposite_task_id, - 'link_id' => $link_id, - ); - - // Create the original task link - $this->db->table(self::TABLE)->insert($values); - $task_link_id = $this->db->getLastId(); - $events[] = $values; - - // Create the opposite task link - $values = array( - 'task_id' => $opposite_task_id, - 'opposite_task_id' => $task_id, - 'link_id' => $opposite_link_id, - ); - - $this->db->table(self::TABLE)->insert($values); - $events[] = $values; + if ($task_link_id1 === false || $task_link_id2 === false) { + $this->db->cancelTransaction(); + return false; + } $this->db->closeTransaction(); + $this->fireEvents(array($task_link_id1, $task_link_id2), self::EVENT_CREATE_UPDATE); - $this->fireEvents($events); - - return (int) $task_link_id; + return $task_link_id1; } /** @@ -210,46 +191,24 @@ class TaskLinkModel extends Base */ public function update($task_link_id, $task_id, $opposite_task_id, $link_id) { - $events = array(); $this->db->startTransaction(); - // Get original task link $task_link = $this->getById($task_link_id); - - // Find opposite task link $opposite_task_link = $this->getOppositeTaskLink($task_link); - - // Get opposite link $opposite_link_id = $this->linkModel->getOppositeLinkId($link_id); - // Update the original task link - $values = array( - 'task_id' => $task_id, - 'opposite_task_id' => $opposite_task_id, - 'link_id' => $link_id, - ); - - $rs1 = $this->db->table(self::TABLE)->eq('id', $task_link_id)->update($values); - $events[] = $values; + $result1 = $this->updateTaskLink($task_link_id, $task_id, $opposite_task_id, $link_id); + $result2 = $this->updateTaskLink($opposite_task_link['id'], $opposite_task_id, $task_id, $opposite_link_id); - // Update the opposite link - $values = array( - 'task_id' => $opposite_task_id, - 'opposite_task_id' => $task_id, - 'link_id' => $opposite_link_id, - ); - - $rs2 = $this->db->table(self::TABLE)->eq('id', $opposite_task_link['id'])->update($values); - $events[] = $values; + if ($result1 === false || $result2 === false) { + $this->db->cancelTransaction(); + return false; + } $this->db->closeTransaction(); + $this->fireEvents(array($task_link_id, $opposite_task_link['id']), self::EVENT_CREATE_UPDATE); - if ($rs1 && $rs2) { - $this->fireEvents($events); - return true; - } - - return false; + return true; } /** @@ -261,21 +220,83 @@ class TaskLinkModel extends Base */ public function remove($task_link_id) { + $this->taskLinkEventJob->execute($task_link_id, self::EVENT_DELETE); + $this->db->startTransaction(); $link = $this->getById($task_link_id); $link_id = $this->linkModel->getOppositeLinkId($link['link_id']); - $this->db->table(self::TABLE)->eq('id', $task_link_id)->remove(); + $result1 = $this->db + ->table(self::TABLE) + ->eq('id', $task_link_id) + ->remove(); - $this->db + $result2 = $this->db ->table(self::TABLE) ->eq('opposite_task_id', $link['task_id']) ->eq('task_id', $link['opposite_task_id']) - ->eq('link_id', $link_id)->remove(); + ->eq('link_id', $link_id) + ->remove(); + + if ($result1 === false || $result2 === false) { + $this->db->cancelTransaction(); + return false; + } $this->db->closeTransaction(); return true; } + + /** + * Publish events + * + * @access protected + * @param integer[] $task_link_ids + * @param string $eventName + */ + protected function fireEvents(array $task_link_ids, $eventName) + { + foreach ($task_link_ids as $task_link_id) { + $this->queueManager->push($this->taskLinkEventJob->withParams($task_link_id, $eventName)); + } + } + + /** + * Create task link + * + * @access protected + * @param integer $task_id + * @param integer $opposite_task_id + * @param integer $link_id + * @return integer|boolean + */ + protected function createTaskLink($task_id, $opposite_task_id, $link_id) + { + return $this->db->table(self::TABLE)->persist(array( + 'task_id' => $task_id, + 'opposite_task_id' => $opposite_task_id, + 'link_id' => $link_id, + )); + } + + /** + * Update task link + * + * @access protected + * @param integer $task_link_id + * @param integer $task_id + * @param integer $opposite_task_id + * @param integer $link_id + * @return boolean + */ + protected function updateTaskLink($task_link_id, $task_id, $opposite_task_id, $link_id) + { + return $this->db->table(self::TABLE)->eq('id', $task_link_id)->update(array( + 'task_id' => $task_id, + 'opposite_task_id' => $opposite_task_id, + 'link_id' => $link_id, + )); + } } diff --git a/app/ServiceProvider/JobProvider.php b/app/ServiceProvider/JobProvider.php index c7f323f1..5b42794b 100644 --- a/app/ServiceProvider/JobProvider.php +++ b/app/ServiceProvider/JobProvider.php @@ -8,6 +8,7 @@ use Kanboard\Job\ProjectFileEventJob; use Kanboard\Job\SubtaskEventJob; use Kanboard\Job\TaskEventJob; use Kanboard\Job\TaskFileEventJob; +use Kanboard\Job\TaskLinkEventJob; use Pimple\Container; use Pimple\ServiceProviderInterface; @@ -44,6 +45,10 @@ class JobProvider implements ServiceProviderInterface return new TaskFileEventJob($c); }); + $container['taskLinkEventJob'] = $container->factory(function ($c) { + return new TaskLinkEventJob($c); + }); + $container['projectFileEventJob'] = $container->factory(function ($c) { return new ProjectFileEventJob($c); }); diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index 7de24e49..7cc68b26 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -3,6 +3,7 @@ namespace Kanboard\Subscriber; use Kanboard\Event\GenericEvent; +use Kanboard\Model\TaskLinkModel; use Kanboard\Model\TaskModel; use Kanboard\Model\CommentModel; use Kanboard\Model\SubtaskModel; @@ -31,6 +32,8 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn CommentModel::EVENT_DELETE => 'handleEvent', CommentModel::EVENT_USER_MENTION => 'handleEvent', TaskFileModel::EVENT_CREATE => 'handleEvent', + TaskLinkModel::EVENT_CREATE_UPDATE => 'handleEvent', + TaskLinkModel::EVENT_DELETE => 'handleEvent', ); } diff --git a/app/Template/event/task_internal_link_create_update.php b/app/Template/event/task_internal_link_create_update.php new file mode 100644 index 00000000..de257977 --- /dev/null +++ b/app/Template/event/task_internal_link_create_update.php @@ -0,0 +1,16 @@ +

+ text->e($author), + $this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) + ) ?> + dt->datetime($date_creation) ?> +

+
+

+ url->link(t('#%d', $task_link['opposite_task_id']), 'TaskViewController', 'show', array('task_id' => $task_link['opposite_task_id'])), + $this->text->e($task_link['label']) + ) ?> +

+
diff --git a/app/Template/event/task_internal_link_delete.php b/app/Template/event/task_internal_link_delete.php new file mode 100644 index 00000000..e537bf81 --- /dev/null +++ b/app/Template/event/task_internal_link_delete.php @@ -0,0 +1,16 @@ +

+ text->e($author), + $this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) + ) ?> + dt->datetime($date_creation) ?> +

+
+

+ text->e($task_link['label']), + $this->url->link(t('#%d', $task_link['opposite_task_id']), 'TaskViewController', 'show', array('task_id' => $task_link['opposite_task_id'])) + ) ?> +

+
diff --git a/app/Template/notification/task_file_create.php b/app/Template/notification/task_file_create.php index feab8dd2..c19f7279 100644 --- a/app/Template/notification/task_file_create.php +++ b/app/Template/notification/task_file_create.php @@ -2,4 +2,4 @@

-render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> \ No newline at end of file +render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/app/Template/notification/task_internal_link_create_update.php b/app/Template/notification/task_internal_link_create_update.php new file mode 100644 index 00000000..73cad84d --- /dev/null +++ b/app/Template/notification/task_internal_link_create_update.php @@ -0,0 +1,11 @@ +

text->e($task['title']) ?> (#)

+ +

+ url->link(t('#%d', $task_link['opposite_task_id']), 'TaskViewController', 'show', array('task_id' => $task_link['opposite_task_id'])), + $this->text->e($task_link['label']) + ) ?> +

+ +render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/app/Template/notification/task_internal_link_delete.php b/app/Template/notification/task_internal_link_delete.php new file mode 100644 index 00000000..bb54e0a7 --- /dev/null +++ b/app/Template/notification/task_internal_link_delete.php @@ -0,0 +1,11 @@ +

text->e($task['title']) ?> (#)

+ +

+ text->e($task_link['label']), + $this->url->link(t('#%d', $task_link['opposite_task_id']), 'TaskViewController', 'show', array('task_id' => $task_link['opposite_task_id'])) + ) ?> +

+ +render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/tests/units/Action/TaskAssignCategoryLinkTest.php b/tests/units/Action/TaskAssignCategoryLinkTest.php index d7e68f72..b9d7e9d9 100644 --- a/tests/units/Action/TaskAssignCategoryLinkTest.php +++ b/tests/units/Action/TaskAssignCategoryLinkTest.php @@ -2,12 +2,12 @@ require_once __DIR__.'/../Base.php'; +use Kanboard\EventBuilder\TaskLinkEventBuilder; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; use Kanboard\Model\TaskLinkModel; use Kanboard\Model\CategoryModel; -use Kanboard\Event\TaskLinkEvent; use Kanboard\Action\TaskAssignCategoryLink; class TaskAssignCategoryLinkTest extends Base @@ -18,6 +18,7 @@ class TaskAssignCategoryLinkTest extends Base $taskFinderModel = new TaskFinderModel($this->container); $projectModel = new ProjectModel($this->container); $categoryModel = new CategoryModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); @@ -27,13 +28,12 @@ class TaskAssignCategoryLinkTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); $this->assertEquals(1, $categoryModel->create(array('name' => 'C1', 'project_id' => 1))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 2)); - $event = new TaskLinkEvent(array( - 'project_id' => 1, - 'task_id' => 1, - 'opposite_task_id' => 2, - 'link_id' => 2, - )); + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId(1) + ->build(); $this->assertTrue($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); @@ -44,51 +44,58 @@ class TaskAssignCategoryLinkTest extends Base public function testWhenLinkDontMatch() { $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); $projectModel = new ProjectModel($this->container); $categoryModel = new CategoryModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); $action->setParam('category_id', 1); - $action->setParam('link_id', 1); + $action->setParam('link_id', 2); $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); $this->assertEquals(1, $categoryModel->create(array('name' => 'C1', 'project_id' => 1))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); - $event = new TaskLinkEvent(array( - 'project_id' => 1, - 'task_id' => 1, - 'opposite_task_id' => 2, - 'link_id' => 2, - )); + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId(1) + ->build(); $this->assertFalse($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(0, $task['category_id']); } public function testThatExistingCategoryWillNotChange() { $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); $projectModel = new ProjectModel($this->container); $categoryModel = new CategoryModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); - $action->setParam('category_id', 2); + $action->setParam('category_id', 1); $action->setParam('link_id', 2); $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); $this->assertEquals(1, $categoryModel->create(array('name' => 'C1', 'project_id' => 1))); - $this->assertEquals(2, $categoryModel->create(array('name' => 'C2', 'project_id' => 1))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1, 'category_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 2)); - $event = new TaskLinkEvent(array( - 'project_id' => 1, - 'task_id' => 1, - 'opposite_task_id' => 2, - 'link_id' => 2, - )); + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId(1) + ->build(); $this->assertFalse($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['category_id']); } } diff --git a/tests/units/Action/TaskAssignColorLinkTest.php b/tests/units/Action/TaskAssignColorLinkTest.php index 07d0969b..27364bc9 100644 --- a/tests/units/Action/TaskAssignColorLinkTest.php +++ b/tests/units/Action/TaskAssignColorLinkTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\EventBuilder\TaskLinkEventBuilder; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -13,42 +13,55 @@ class TaskAssignColorLinkTest extends Base { public function testChangeColor() { - $projectModel = new ProjectModel($this->container); $taskCreationModel = new TaskCreationModel($this->container); $taskFinderModel = new TaskFinderModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'link_id' => 1)); + $projectModel = new ProjectModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $action = new TaskAssignColorLink($this->container); $action->setProjectId(1); + $action->setParam('link_id', 2); $action->setParam('color_id', 'red'); - $action->setParam('link_id', 1); + + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 2)); + + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId(1) + ->build(); $this->assertTrue($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); $task = $taskFinderModel->getById(1); - $this->assertNotEmpty($task); $this->assertEquals('red', $task['color_id']); } public function testWithWrongLink() { - $projectModel = new ProjectModel($this->container); $taskCreationModel = new TaskCreationModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'link_id' => 2)); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $action = new TaskAssignColorLink($this->container); $action->setProjectId(1); + $action->setParam('link_id', 2); $action->setParam('color_id', 'red'); - $action->setParam('link_id', 1); + + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId(1) + ->build(); $this->assertFalse($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals('yellow', $task['color_id']); } } diff --git a/tests/units/EventBuilder/TaskLinkEventBuilderTest.php b/tests/units/EventBuilder/TaskLinkEventBuilderTest.php new file mode 100644 index 00000000..7364d651 --- /dev/null +++ b/tests/units/EventBuilder/TaskLinkEventBuilderTest.php @@ -0,0 +1,70 @@ +container); + $taskLinkEventBuilder->withTaskLinkId(42); + $this->assertNull($taskLinkEventBuilder->build()); + } + + public function testBuild() + { + $taskLinkModel = new TaskLinkModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskLinkEventBuilder = new TaskLinkEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'task 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'task 2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + + $event = $taskLinkEventBuilder->withTaskLinkId(1)->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskLinkEvent', $event); + $this->assertNotEmpty($event['task_link']); + $this->assertNotEmpty($event['task']); + } + + public function testBuildTitle() + { + $taskLinkModel = new TaskLinkModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskLinkEventBuilder = new TaskLinkEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'task 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'task 2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + + $eventData = $taskLinkEventBuilder->withTaskLinkId(1)->build(); + + $title = $taskLinkEventBuilder->buildTitleWithAuthor('Foobar', TaskLinkModel::EVENT_CREATE_UPDATE, $eventData->getAll()); + $this->assertEquals('Foobar set a new internal link for the task #1', $title); + + $title = $taskLinkEventBuilder->buildTitleWithAuthor('Foobar', TaskLinkModel::EVENT_DELETE, $eventData->getAll()); + $this->assertEquals('Foobar removed an internal link for the task #1', $title); + + $title = $taskLinkEventBuilder->buildTitleWithAuthor('Foobar', 'not found', $eventData->getAll()); + $this->assertSame('', $title); + + $title = $taskLinkEventBuilder->buildTitleWithoutAuthor(TaskLinkModel::EVENT_CREATE_UPDATE, $eventData->getAll()); + $this->assertEquals('A new internal link for the task #1 have been defined', $title); + + $title = $taskLinkEventBuilder->buildTitleWithoutAuthor(TaskLinkModel::EVENT_DELETE, $eventData->getAll()); + $this->assertEquals('Internal link removed for the task #1', $title); + + $title = $taskLinkEventBuilder->buildTitleWithoutAuthor('not found', $eventData->getAll()); + $this->assertSame('', $title); + } +} diff --git a/tests/units/Job/TaskLinkEventJobTest.php b/tests/units/Job/TaskLinkEventJobTest.php new file mode 100644 index 00000000..1949316a --- /dev/null +++ b/tests/units/Job/TaskLinkEventJobTest.php @@ -0,0 +1,65 @@ +container); + $taskLinkEventJob->withParams(123, 'foobar'); + + $this->assertSame(array(123, 'foobar'), $taskLinkEventJob->getJobParams()); + } + + public function testWithMissingLink() + { + $this->container['dispatcher']->addListener(TaskLinkModel::EVENT_CREATE_UPDATE, function() {}); + + $taskLinkEventJob = new TaskLinkEventJob($this->container); + $taskLinkEventJob->execute(42, TaskLinkModel::EVENT_CREATE_UPDATE); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertEmpty($called); + } + + public function testTriggerCreationEvents() + { + $this->container['dispatcher']->addListener(TaskLinkModel::EVENT_CREATE_UPDATE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'task 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'task 2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskLinkModel::EVENT_CREATE_UPDATE.'.closure', $called); + } + + public function testTriggerDeleteEvents() + { + $this->container['dispatcher']->addListener(TaskLinkModel::EVENT_DELETE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'task 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'task 2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + $this->assertTrue($taskLinkModel->remove(1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskLinkModel::EVENT_DELETE.'.closure', $called); + } +} diff --git a/tests/units/Model/NotificationModelTest.php b/tests/units/Model/NotificationModelTest.php index 889f3349..0bd9db6e 100644 --- a/tests/units/Model/NotificationModelTest.php +++ b/tests/units/Model/NotificationModelTest.php @@ -7,6 +7,7 @@ use Kanboard\Model\TaskCreationModel; use Kanboard\Model\SubtaskModel; use Kanboard\Model\CommentModel; use Kanboard\Model\TaskFileModel; +use Kanboard\Model\TaskLinkModel; use Kanboard\Model\TaskModel; use Kanboard\Model\ProjectModel; use Kanboard\Model\NotificationModel; @@ -23,47 +24,38 @@ class NotificationModelTest extends Base $subtaskModel = new SubtaskModel($this->container); $commentModel = new CommentModel($this->container); $taskFileModel = new TaskFileModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); $this->assertEquals(1, $subtaskModel->create(array('title' => 'test', 'task_id' => 1))); $this->assertEquals(1, $commentModel->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); $this->assertEquals(1, $taskFileModel->create(1, 'test', 'blah', 123)); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); $task = $taskFinderModel->getDetails(1); $subtask = $subtaskModel->getById(1, true); $comment = $commentModel->getById(1); $file = $commentModel->getById(1); + $tasklink = $taskLinkModel->getById(1); - $this->assertNotEmpty($task); - $this->assertNotEmpty($subtask); - $this->assertNotEmpty($comment); - $this->assertNotEmpty($file); - - foreach (NotificationSubscriber::getSubscribedEvents() as $event_name => $values) { - $title = $notificationModel->getTitleWithoutAuthor($event_name, array( - 'task' => $task, - 'comment' => $comment, - 'subtask' => $subtask, - 'file' => $file, - 'changes' => array() - )); - - $this->assertNotEmpty($title); - - $title = $notificationModel->getTitleWithAuthor('foobar', $event_name, array( + foreach (NotificationSubscriber::getSubscribedEvents() as $eventName => $values) { + $eventData = array( 'task' => $task, 'comment' => $comment, 'subtask' => $subtask, 'file' => $file, + 'task_link' => $tasklink, 'changes' => array() - )); + ); - $this->assertNotEmpty($title); + $this->assertNotEmpty($notificationModel->getTitleWithoutAuthor($eventName, $eventData)); + $this->assertNotEmpty($notificationModel->getTitleWithAuthor('Foobar', $eventName, $eventData)); } $this->assertNotEmpty($notificationModel->getTitleWithoutAuthor(TaskModel::EVENT_OVERDUE, array('tasks' => array(array('id' => 1))))); - $this->assertNotEmpty($notificationModel->getTitleWithoutAuthor('unkown', array())); + $this->assertNotEmpty($notificationModel->getTitleWithoutAuthor('unknown', array())); } public function testGetTaskIdFromEvent() @@ -75,6 +67,7 @@ class NotificationModelTest extends Base $subtaskModel = new SubtaskModel($this->container); $commentModel = new CommentModel($this->container); $taskFileModel = new TaskFileModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); @@ -86,18 +79,20 @@ class NotificationModelTest extends Base $subtask = $subtaskModel->getById(1, true); $comment = $commentModel->getById(1); $file = $commentModel->getById(1); + $tasklink = $taskLinkModel->getById(1); $this->assertNotEmpty($task); $this->assertNotEmpty($subtask); $this->assertNotEmpty($comment); $this->assertNotEmpty($file); - foreach (NotificationSubscriber::getSubscribedEvents() as $event_name => $values) { - $task_id = $notificationModel->getTaskIdFromEvent($event_name, array( + foreach (NotificationSubscriber::getSubscribedEvents() as $eventName => $values) { + $task_id = $notificationModel->getTaskIdFromEvent($eventName, array( 'task' => $task, 'comment' => $comment, 'subtask' => $subtask, 'file' => $file, + 'task_link' => $tasklink, 'changes' => array() )); diff --git a/tests/units/Model/TaskLinkModelTest.php b/tests/units/Model/TaskLinkModelTest.php index 78590891..01a7888b 100644 --- a/tests/units/Model/TaskLinkModelTest.php +++ b/tests/units/Model/TaskLinkModelTest.php @@ -9,6 +9,34 @@ use Kanboard\Model\ProjectModel; class TaskLinkModelTest extends Base { + public function testGeyById() + { + $taskLinkModel = new TaskLinkModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A'))); + $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B'))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 6)); + + $taskLink = $taskLinkModel->getById(1); + $this->assertEquals(1, $taskLink['id']); + $this->assertEquals(1, $taskLink['task_id']); + $this->assertEquals(2, $taskLink['opposite_task_id']); + $this->assertEquals(6, $taskLink['link_id']); + $this->assertEquals(7, $taskLink['opposite_link_id']); + $this->assertEquals('is a child of', $taskLink['label']); + + $taskLink = $taskLinkModel->getById(2); + $this->assertEquals(2, $taskLink['id']); + $this->assertEquals(2, $taskLink['task_id']); + $this->assertEquals(1, $taskLink['opposite_task_id']); + $this->assertEquals(7, $taskLink['link_id']); + $this->assertEquals(6, $taskLink['opposite_link_id']); + $this->assertEquals('is a parent of', $taskLink['label']); + } + // Check postgres issue: "Cardinality violation: 7 ERROR: more than one row returned by a subquery used as an expression" public function testGetTaskWithMultipleMilestoneLink() { diff --git a/tests/units/Notification/MailNotificationTest.php b/tests/units/Notification/MailNotificationTest.php new file mode 100644 index 00000000..6579d9bc --- /dev/null +++ b/tests/units/Notification/MailNotificationTest.php @@ -0,0 +1,117 @@ +container); + $projectModel = new ProjectModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $commentModel = new CommentModel($this->container); + $fileModel = new TaskFileModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'test', 'task_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); + $this->assertEquals(1, $fileModel->create(1, 'test', 'blah', 123)); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + + $task = $taskFinderModel->getDetails(1); + $subtask = $subtaskModel->getById(1, true); + $comment = $commentModel->getById(1); + $file = $commentModel->getById(1); + $tasklink = $taskLinkModel->getById(1); + + $this->assertNotEmpty($task); + $this->assertNotEmpty($subtask); + $this->assertNotEmpty($comment); + $this->assertNotEmpty($file); + + foreach (NotificationSubscriber::getSubscribedEvents() as $eventName => $values) { + $eventData = array( + 'task' => $task, + 'comment' => $comment, + 'subtask' => $subtask, + 'file' => $file, + 'task_link' => $tasklink, + 'changes' => array() + ); + $this->assertNotEmpty($mailNotification->getMailContent($eventName, $eventData)); + $this->assertNotEmpty($mailNotification->getMailSubject($eventName, $eventData)); + } + } + + public function testSendWithEmailAddress() + { + $mailNotification = new MailNotification($this->container); + $projectModel = new ProjectModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $userModel = new UserModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($userModel->update(array('id' => 1, 'email' => 'test@localhost'))); + + $this->container['emailClient'] = $this + ->getMockBuilder('\Kanboard\Core\Mail\Client') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('send')) + ->getMock(); + + $this->container['emailClient'] + ->expects($this->once()) + ->method('send') + ->with( + $this->equalTo('test@localhost'), + $this->equalTo('admin'), + $this->equalTo('[test][New task] test (#1)'), + $this->stringContains('test') + ); + + $mailNotification->notifyUser($userModel->getById(1), TaskModel::EVENT_CREATE, array('task' => $taskFinderModel->getDetails(1))); + } + + public function testSendWithoutEmailAddress() + { + $mailNotification = new MailNotification($this->container); + $projectModel = new ProjectModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $userModel = new UserModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + + $this->container['emailClient'] = $this + ->getMockBuilder('\Kanboard\Core\Mail\Client') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('send')) + ->getMock(); + + $this->container['emailClient'] + ->expects($this->never()) + ->method('send'); + + $mailNotification->notifyUser($userModel->getById(1), TaskModel::EVENT_CREATE, array('task' => $taskFinderModel->getDetails(1))); + } +} diff --git a/tests/units/Notification/MailTest.php b/tests/units/Notification/MailTest.php deleted file mode 100644 index 9f077ac8..00000000 --- a/tests/units/Notification/MailTest.php +++ /dev/null @@ -1,117 +0,0 @@ -container); - $p = new ProjectModel($this->container); - $tf = new TaskFinderModel($this->container); - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $c = new CommentModel($this->container); - $f = new TaskFileModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'test', 'task_id' => 1))); - $this->assertEquals(1, $c->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); - $this->assertEquals(1, $f->create(1, 'test', 'blah', 123)); - - $task = $tf->getDetails(1); - $subtask = $s->getById(1, true); - $comment = $c->getById(1); - $file = $c->getById(1); - - $this->assertNotEmpty($task); - $this->assertNotEmpty($subtask); - $this->assertNotEmpty($comment); - $this->assertNotEmpty($file); - - foreach (NotificationSubscriber::getSubscribedEvents() as $event => $values) { - $this->assertNotEmpty($en->getMailContent($event, array( - 'task' => $task, - 'comment' => $comment, - 'subtask' => $subtask, - 'file' => $file, - 'changes' => array()) - )); - - $this->assertNotEmpty($en->getMailSubject($event, array( - 'task' => $task, - 'comment' => $comment, - 'subtask' => $subtask, - 'file' => $file, - 'changes' => array()) - )); - } - } - - public function testSendWithEmailAddress() - { - $en = new MailNotification($this->container); - $p = new ProjectModel($this->container); - $tf = new TaskFinderModel($this->container); - $tc = new TaskCreationModel($this->container); - $u = new UserModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - $this->assertTrue($u->update(array('id' => 1, 'email' => 'test@localhost'))); - - $this->container['emailClient'] = $this - ->getMockBuilder('\Kanboard\Core\Mail\Client') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('send')) - ->getMock(); - - $this->container['emailClient'] - ->expects($this->once()) - ->method('send') - ->with( - $this->equalTo('test@localhost'), - $this->equalTo('admin'), - $this->equalTo('[test][New task] test (#1)'), - $this->stringContains('test') - ); - - $en->notifyUser($u->getById(1), TaskModel::EVENT_CREATE, array('task' => $tf->getDetails(1))); - } - - public function testSendWithoutEmailAddress() - { - $en = new MailNotification($this->container); - $p = new ProjectModel($this->container); - $tf = new TaskFinderModel($this->container); - $tc = new TaskCreationModel($this->container); - $u = new UserModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - - $this->container['emailClient'] = $this - ->getMockBuilder('\Kanboard\Core\Mail\Client') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('send')) - ->getMock(); - - $this->container['emailClient'] - ->expects($this->never()) - ->method('send'); - - $en->notifyUser($u->getById(1), TaskModel::EVENT_CREATE, array('task' => $tf->getDetails(1))); - } -} diff --git a/tests/units/Notification/WebhookNotificationTest.php b/tests/units/Notification/WebhookNotificationTest.php new file mode 100644 index 00000000..6fbc349c --- /dev/null +++ b/tests/units/Notification/WebhookNotificationTest.php @@ -0,0 +1,29 @@ +container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $this->container['dispatcher']->addSubscriber(new NotificationSubscriber($this->container)); + + $configModel->save(array('webhook_url' => 'http://localhost/?task-creation')); + + $this->container['httpClient'] + ->expects($this->once()) + ->method('postJson') + ->with($this->stringContains('http://localhost/?task-creation&token='), $this->anything()); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + } +} diff --git a/tests/units/Notification/WebhookTest.php b/tests/units/Notification/WebhookTest.php deleted file mode 100644 index 5a9eb1c7..00000000 --- a/tests/units/Notification/WebhookTest.php +++ /dev/null @@ -1,29 +0,0 @@ -container); - $p = new ProjectModel($this->container); - $tc = new TaskCreationModel($this->container); - $this->container['dispatcher']->addSubscriber(new NotificationSubscriber($this->container)); - - $c->save(array('webhook_url' => 'http://localhost/?task-creation')); - - $this->container['httpClient'] - ->expects($this->once()) - ->method('postJson') - ->with($this->stringContains('http://localhost/?task-creation&token='), $this->anything()); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test'))); - } -} -- cgit v1.2.3 From adb5023cfc075ce5d6f73a4ba5b4ab51f6c500c0 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 23 Jul 2016 20:30:06 -0400 Subject: Add unit test for ProjectMetricJob --- app/Core/Base.php | 1 + app/ServiceProvider/JobProvider.php | 5 +++ app/Subscriber/ProjectDailySummarySubscriber.php | 7 +--- tests/units/Job/ProjectMetricJobTest.php | 47 ++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 tests/units/Job/ProjectMetricJobTest.php (limited to 'app/Subscriber') diff --git a/app/Core/Base.php b/app/Core/Base.php index 6931d93a..41f5d2e0 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -157,6 +157,7 @@ use Pimple\Container; * @property \Kanboard\Job\TaskLinkEventJob $taskLinkEventJob * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob * @property \Kanboard\Job\NotificationJob $notificationJob + * @property \Kanboard\Job\ProjectMetricJob $projectMetricJob * @property \Psr\Log\LoggerInterface $logger * @property \PicoDb\Database $db * @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher diff --git a/app/ServiceProvider/JobProvider.php b/app/ServiceProvider/JobProvider.php index 5b42794b..2194b11c 100644 --- a/app/ServiceProvider/JobProvider.php +++ b/app/ServiceProvider/JobProvider.php @@ -5,6 +5,7 @@ namespace Kanboard\ServiceProvider; use Kanboard\Job\CommentEventJob; use Kanboard\Job\NotificationJob; use Kanboard\Job\ProjectFileEventJob; +use Kanboard\Job\ProjectMetricJob; use Kanboard\Job\SubtaskEventJob; use Kanboard\Job\TaskEventJob; use Kanboard\Job\TaskFileEventJob; @@ -57,6 +58,10 @@ class JobProvider implements ServiceProviderInterface return new NotificationJob($c); }); + $container['projectMetricJob'] = $container->factory(function ($c) { + return new ProjectMetricJob($c); + }); + return $container; } } diff --git a/app/Subscriber/ProjectDailySummarySubscriber.php b/app/Subscriber/ProjectDailySummarySubscriber.php index 7e3c11c3..eaa9d468 100644 --- a/app/Subscriber/ProjectDailySummarySubscriber.php +++ b/app/Subscriber/ProjectDailySummarySubscriber.php @@ -3,7 +3,6 @@ namespace Kanboard\Subscriber; use Kanboard\Event\TaskEvent; -use Kanboard\Job\ProjectMetricJob; use Kanboard\Model\TaskModel; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -22,9 +21,7 @@ class ProjectDailySummarySubscriber extends BaseSubscriber implements EventSubsc public function execute(TaskEvent $event) { - if (isset($event['project_id'])) { - $this->logger->debug('Subscriber executed: '.__METHOD__); - $this->queueManager->push(ProjectMetricJob::getInstance($this->container)->withParams($event['project_id'])); - } + $this->logger->debug('Subscriber executed: '.__METHOD__); + $this->queueManager->push($this->projectMetricJob->withParams($event['task']['project_id'])); } } diff --git a/tests/units/Job/ProjectMetricJobTest.php b/tests/units/Job/ProjectMetricJobTest.php new file mode 100644 index 00000000..e5b0474d --- /dev/null +++ b/tests/units/Job/ProjectMetricJobTest.php @@ -0,0 +1,47 @@ +container); + $projectMetricJob->withParams(123); + + $this->assertSame( + array(123), + $projectMetricJob->getJobParams() + ); + } + + public function testJob() + { + $this->container['projectDailyColumnStatsModel'] = $this + ->getMockBuilder('\Kanboard\Model\ProjectDailyColumnStatsModel') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('updateTotals')) + ->getMock(); + + $this->container['projectDailyStatsModel'] = $this + ->getMockBuilder('\Kanboard\Model\ProjectDailyStatsModel') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('updateTotals')) + ->getMock(); + + $this->container['projectDailyColumnStatsModel'] + ->expects($this->once()) + ->method('updateTotals') + ->with(42, date('Y-m-d')); + + $this->container['projectDailyStatsModel'] + ->expects($this->once()) + ->method('updateTotals') + ->with(42, date('Y-m-d')); + + $job = new ProjectMetricJob($this->container); + $job->execute(42); + } +} -- cgit v1.2.3 From 220bc9cdcc483e71d5df629e9c7eb26c562b969f Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 23 Jul 2016 20:58:16 -0400 Subject: Add unit test RecurringTaskSubscriber --- app/Subscriber/RecurringTaskSubscriber.php | 14 +- .../Subscriber/RecurringTaskSubscriberTest.php | 164 +++++++++++++++++++++ 2 files changed, 172 insertions(+), 6 deletions(-) create mode 100644 tests/units/Subscriber/RecurringTaskSubscriberTest.php (limited to 'app/Subscriber') diff --git a/app/Subscriber/RecurringTaskSubscriber.php b/app/Subscriber/RecurringTaskSubscriber.php index 21cd3996..3e2848f8 100644 --- a/app/Subscriber/RecurringTaskSubscriber.php +++ b/app/Subscriber/RecurringTaskSubscriber.php @@ -19,12 +19,13 @@ class RecurringTaskSubscriber extends BaseSubscriber implements EventSubscriberI public function onMove(TaskEvent $event) { $this->logger->debug('Subscriber executed: '.__METHOD__); + $task = $event['task']; - if ($event['recurrence_status'] == TaskModel::RECURRING_STATUS_PENDING) { - if ($event['recurrence_trigger'] == TaskModel::RECURRING_TRIGGER_FIRST_COLUMN && $this->columnModel->getFirstColumnId($event['project_id']) == $event['src_column_id']) { - $this->taskRecurrenceModel->duplicateRecurringTask($event['task_id']); - } elseif ($event['recurrence_trigger'] == TaskModel::RECURRING_TRIGGER_LAST_COLUMN && $this->columnModel->getLastColumnId($event['project_id']) == $event['dst_column_id']) { - $this->taskRecurrenceModel->duplicateRecurringTask($event['task_id']); + if ($task['recurrence_status'] == TaskModel::RECURRING_STATUS_PENDING) { + if ($task['recurrence_trigger'] == TaskModel::RECURRING_TRIGGER_FIRST_COLUMN && $this->columnModel->getFirstColumnId($task['project_id']) == $event['src_column_id']) { + $this->taskRecurrenceModel->duplicateRecurringTask($task['id']); + } elseif ($task['recurrence_trigger'] == TaskModel::RECURRING_TRIGGER_LAST_COLUMN && $this->columnModel->getLastColumnId($task['project_id']) == $event['dst_column_id']) { + $this->taskRecurrenceModel->duplicateRecurringTask($task['id']); } } } @@ -32,8 +33,9 @@ class RecurringTaskSubscriber extends BaseSubscriber implements EventSubscriberI public function onClose(TaskEvent $event) { $this->logger->debug('Subscriber executed: '.__METHOD__); + $task = $event['task']; - if ($event['recurrence_status'] == TaskModel::RECURRING_STATUS_PENDING && $event['recurrence_trigger'] == TaskModel::RECURRING_TRIGGER_CLOSE) { + if ($task['recurrence_status'] == TaskModel::RECURRING_STATUS_PENDING && $task['recurrence_trigger'] == TaskModel::RECURRING_TRIGGER_CLOSE) { $this->taskRecurrenceModel->duplicateRecurringTask($event['task_id']); } } diff --git a/tests/units/Subscriber/RecurringTaskSubscriberTest.php b/tests/units/Subscriber/RecurringTaskSubscriberTest.php new file mode 100644 index 00000000..d6aba7cf --- /dev/null +++ b/tests/units/Subscriber/RecurringTaskSubscriberTest.php @@ -0,0 +1,164 @@ +container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $subscriber = new RecurringTaskSubscriber($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + + $event = TaskEventBuilder::getInstance($this->container) + ->withTaskId(1) + ->buildEvent(); + + $subscriber->onMove($event); + $subscriber->onClose($event); + + $this->assertEquals(1, $taskFinderModel->countByProjectId(1)); + } + + public function testWithRecurrenceFirstColumn() + { + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $subscriber = new RecurringTaskSubscriber($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array( + 'title' => 'test', + 'project_id' => 1, + 'recurrence_status' => TaskModel::RECURRING_STATUS_PENDING, + 'recurrence_trigger' => TaskModel::RECURRING_TRIGGER_FIRST_COLUMN, + ))); + + $event = TaskEventBuilder::getInstance($this->container) + ->withTaskId(1) + ->withValues(array('src_column_id' => 1)) + ->buildEvent(); + + $subscriber->onMove($event); + $subscriber->onClose($event); + + $this->assertEquals(2, $taskFinderModel->countByProjectId(1)); + } + + public function testWithRecurrenceFirstColumnWithWrongColumn() + { + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $subscriber = new RecurringTaskSubscriber($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array( + 'title' => 'test', + 'project_id' => 1, + 'recurrence_status' => TaskModel::RECURRING_STATUS_PENDING, + 'recurrence_trigger' => TaskModel::RECURRING_TRIGGER_FIRST_COLUMN, + 'column_id' => 2, + ))); + + $event = TaskEventBuilder::getInstance($this->container) + ->withTaskId(1) + ->withValues(array('src_column_id' => 2)) + ->buildEvent(); + + $subscriber->onMove($event); + $subscriber->onClose($event); + + $this->assertEquals(1, $taskFinderModel->countByProjectId(1)); + } + + public function testWithRecurrenceLastColumn() + { + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $subscriber = new RecurringTaskSubscriber($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array( + 'title' => 'test', + 'project_id' => 1, + 'recurrence_status' => TaskModel::RECURRING_STATUS_PENDING, + 'recurrence_trigger' => TaskModel::RECURRING_TRIGGER_LAST_COLUMN, + ))); + + $event = TaskEventBuilder::getInstance($this->container) + ->withTaskId(1) + ->withValues(array('dst_column_id' => 4)) + ->buildEvent(); + + $subscriber->onMove($event); + $subscriber->onClose($event); + + $this->assertEquals(2, $taskFinderModel->countByProjectId(1)); + } + + public function testWithRecurrenceLastColumnWithWrongColumn() + { + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $subscriber = new RecurringTaskSubscriber($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array( + 'title' => 'test', + 'project_id' => 1, + 'recurrence_status' => TaskModel::RECURRING_STATUS_PENDING, + 'recurrence_trigger' => TaskModel::RECURRING_TRIGGER_LAST_COLUMN, + ))); + + $event = TaskEventBuilder::getInstance($this->container) + ->withTaskId(1) + ->withValues(array('dst_column_id' => 2)) + ->buildEvent(); + + $subscriber->onMove($event); + $subscriber->onClose($event); + + $this->assertEquals(1, $taskFinderModel->countByProjectId(1)); + } + + public function testWithRecurrenceOnClose() + { + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $subscriber = new RecurringTaskSubscriber($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array( + 'title' => 'test', + 'project_id' => 1, + 'recurrence_status' => TaskModel::RECURRING_STATUS_PENDING, + 'recurrence_trigger' => TaskModel::RECURRING_TRIGGER_CLOSE, + ))); + + $event = TaskEventBuilder::getInstance($this->container) + ->withTaskId(1) + ->withChanges(array('is_active' => 0)) + ->buildEvent(); + + $subscriber->onMove($event); + $subscriber->onClose($event); + + $this->assertEquals(2, $taskFinderModel->countByProjectId(1)); + } +} -- cgit v1.2.3 From 24555080fd3ca8607f0a798b5a0e4be98ff131f8 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 23 Jul 2016 21:48:59 -0400 Subject: Create new class SubtaskStatusModel --- app/Controller/SubtaskRestrictionController.php | 2 +- app/Controller/SubtaskStatusController.php | 2 +- app/Core/Base.php | 1 + app/Model/SubtaskModel.php | 184 +++++----------- app/Model/SubtaskStatusModel.php | 85 ++++++++ app/Model/TaskStatusModel.php | 2 +- app/ServiceProvider/ClassProvider.php | 1 + app/Subscriber/BootstrapSubscriber.php | 2 +- tests/units/Model/SubtaskModelTest.php | 110 ---------- tests/units/Model/SubtaskStatusModelTest.php | 123 +++++++++++ tests/units/Model/SubtaskTimeTrackingModelTest.php | 240 +++++++++++++++++++++ tests/units/Model/SubtaskTimeTrackingTest.php | 240 --------------------- 12 files changed, 506 insertions(+), 486 deletions(-) create mode 100644 app/Model/SubtaskStatusModel.php create mode 100644 tests/units/Model/SubtaskStatusModelTest.php create mode 100644 tests/units/Model/SubtaskTimeTrackingModelTest.php delete mode 100644 tests/units/Model/SubtaskTimeTrackingTest.php (limited to 'app/Subscriber') diff --git a/app/Controller/SubtaskRestrictionController.php b/app/Controller/SubtaskRestrictionController.php index 084fc0d9..cb642e1c 100644 --- a/app/Controller/SubtaskRestrictionController.php +++ b/app/Controller/SubtaskRestrictionController.php @@ -27,7 +27,7 @@ class SubtaskRestrictionController extends BaseController SubtaskModel::STATUS_TODO => t('Todo'), SubtaskModel::STATUS_DONE => t('Done'), ), - 'subtask_inprogress' => $this->subtaskModel->getSubtaskInProgress($this->userSession->getId()), + 'subtask_inprogress' => $this->subtaskStatusModel->getSubtaskInProgress($this->userSession->getId()), 'subtask' => $subtask, 'task' => $task, ))); diff --git a/app/Controller/SubtaskStatusController.php b/app/Controller/SubtaskStatusController.php index 699951fe..d4d356c3 100644 --- a/app/Controller/SubtaskStatusController.php +++ b/app/Controller/SubtaskStatusController.php @@ -20,7 +20,7 @@ class SubtaskStatusController extends BaseController $task = $this->getTask(); $subtask = $this->getSubtask(); - $status = $this->subtaskModel->toggleStatus($subtask['id']); + $status = $this->subtaskStatusModel->toggleStatus($subtask['id']); if ($this->request->getIntegerParam('refresh-table') === 0) { $subtask['status'] = $status; diff --git a/app/Core/Base.php b/app/Core/Base.php index 8b9bf085..563013bd 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -91,6 +91,7 @@ use Pimple\Container; * @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel * @property \Kanboard\Model\SubtaskModel $subtaskModel * @property \Kanboard\Model\SubtaskPositionModel $subtaskPositionModel + * @property \Kanboard\Model\SubtaskStatusModel $subtaskStatusModel * @property \Kanboard\Model\SubtaskTaskConversionModel $subtaskTaskConversionModel * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel * @property \Kanboard\Model\SwimlaneModel $swimlaneModel diff --git a/app/Model/SubtaskModel.php b/app/Model/SubtaskModel.php index 2ac6095c..568e27a4 100644 --- a/app/Model/SubtaskModel.php +++ b/app/Model/SubtaskModel.php @@ -21,25 +21,13 @@ class SubtaskModel extends Base const TABLE = 'subtasks'; /** - * Task "done" status - * - * @var integer - */ - const STATUS_DONE = 2; - - /** - * Task "in progress" status - * - * @var integer - */ - const STATUS_INPROGRESS = 1; - - /** - * Task "todo" status + * Subtask status * * @var integer */ const STATUS_TODO = 0; + const STATUS_INPROGRESS = 1; + const STATUS_DONE = 2; /** * Events @@ -81,26 +69,6 @@ class SubtaskModel extends Base ); } - /** - * Add subtask status status to the resultset - * - * @access public - * @param array $subtasks Subtasks - * @return array - */ - public function addStatusName(array $subtasks) - { - $status = $this->getStatusList(); - - foreach ($subtasks as &$subtask) { - $subtask['status_name'] = $status[$subtask['status']]; - $subtask['timer_start_date'] = isset($subtask['timer_start_date']) ? $subtask['timer_start_date'] : 0; - $subtask['is_timer_started'] = ! empty($subtask['timer_start_date']); - } - - return $subtasks; - } - /** * Get the query to fetch subtasks assigned to a user * @@ -176,35 +144,6 @@ class SubtaskModel extends Base return $this->db->table(self::TABLE)->eq('id', $subtask_id)->findOne(); } - /** - * Prepare data before insert/update - * - * @access public - * @param array $values Form values - */ - public function prepare(array &$values) - { - $this->helper->model->removeFields($values, array('another_subtask')); - $this->helper->model->resetFields($values, array('time_estimated', 'time_spent')); - } - - /** - * Prepare data before insert - * - * @access public - * @param array $values Form values - */ - public function prepareCreation(array &$values) - { - $this->prepare($values); - - $values['position'] = $this->getLastPosition($values['task_id']) + 1; - $values['status'] = isset($values['status']) ? $values['status'] : self::STATUS_TODO; - $values['time_estimated'] = isset($values['time_estimated']) ? $values['time_estimated'] : 0; - $values['time_spent'] = isset($values['time_spent']) ? $values['time_spent'] : 0; - $values['user_id'] = isset($values['user_id']) ? $values['user_id'] : 0; - } - /** * Get the position of the last column for a given project * @@ -260,74 +199,6 @@ class SubtaskModel extends Base return $result; } - /** - * Close all subtasks of a task - * - * @access public - * @param integer $task_id - * @return boolean - */ - public function closeAll($task_id) - { - return $this->db->table(self::TABLE)->eq('task_id', $task_id)->update(array('status' => self::STATUS_DONE)); - } - - /** - * Change the status of subtask - * - * @access public - * @param integer $subtask_id - * @return boolean|integer - */ - public function toggleStatus($subtask_id) - { - $subtask = $this->getById($subtask_id); - $status = ($subtask['status'] + 1) % 3; - - $values = array( - 'id' => $subtask['id'], - 'status' => $status, - 'task_id' => $subtask['task_id'], - ); - - if (empty($subtask['user_id']) && $this->userSession->isLogged()) { - $values['user_id'] = $this->userSession->getId(); - } - - return $this->update($values) ? $status : false; - } - - /** - * Get the subtask in progress for this user - * - * @access public - * @param integer $user_id - * @return array - */ - public function getSubtaskInProgress($user_id) - { - return $this->db->table(self::TABLE) - ->eq('status', self::STATUS_INPROGRESS) - ->eq('user_id', $user_id) - ->findOne(); - } - - /** - * Return true if the user have a subtask in progress - * - * @access public - * @param integer $user_id - * @return boolean - */ - public function hasSubtaskInProgress($user_id) - { - return $this->configModel->get('subtask_restriction') == 1 && - $this->db->table(self::TABLE) - ->eq('status', self::STATUS_INPROGRESS) - ->eq('user_id', $user_id) - ->exists(); - } - /** * Remove * @@ -368,4 +239,53 @@ class SubtaskModel extends Base } }); } + + /** + * Prepare data before insert/update + * + * @access protected + * @param array $values Form values + */ + protected function prepare(array &$values) + { + $this->helper->model->removeFields($values, array('another_subtask')); + $this->helper->model->resetFields($values, array('time_estimated', 'time_spent')); + } + + /** + * Prepare data before insert + * + * @access protected + * @param array $values Form values + */ + protected function prepareCreation(array &$values) + { + $this->prepare($values); + + $values['position'] = $this->getLastPosition($values['task_id']) + 1; + $values['status'] = isset($values['status']) ? $values['status'] : self::STATUS_TODO; + $values['time_estimated'] = isset($values['time_estimated']) ? $values['time_estimated'] : 0; + $values['time_spent'] = isset($values['time_spent']) ? $values['time_spent'] : 0; + $values['user_id'] = isset($values['user_id']) ? $values['user_id'] : 0; + } + + /** + * Add subtask status status to the resultset + * + * @access public + * @param array $subtasks Subtasks + * @return array + */ + public function addStatusName(array $subtasks) + { + $status = $this->getStatusList(); + + foreach ($subtasks as &$subtask) { + $subtask['status_name'] = $status[$subtask['status']]; + $subtask['timer_start_date'] = isset($subtask['timer_start_date']) ? $subtask['timer_start_date'] : 0; + $subtask['is_timer_started'] = ! empty($subtask['timer_start_date']); + } + + return $subtasks; + } } diff --git a/app/Model/SubtaskStatusModel.php b/app/Model/SubtaskStatusModel.php new file mode 100644 index 00000000..26cbb67d --- /dev/null +++ b/app/Model/SubtaskStatusModel.php @@ -0,0 +1,85 @@ +db->table(SubtaskModel::TABLE) + ->eq('status', SubtaskModel::STATUS_INPROGRESS) + ->eq('user_id', $user_id) + ->findOne(); + } + + /** + * Return true if the user have a subtask in progress + * + * @access public + * @param integer $user_id + * @return boolean + */ + public function hasSubtaskInProgress($user_id) + { + return $this->configModel->get('subtask_restriction') == 1 && + $this->db->table(SubtaskModel::TABLE) + ->eq('status', SubtaskModel::STATUS_INPROGRESS) + ->eq('user_id', $user_id) + ->exists(); + } + + /** + * Change the status of subtask + * + * @access public + * @param integer $subtask_id + * @return boolean|integer + */ + public function toggleStatus($subtask_id) + { + $subtask = $this->subtaskModel->getById($subtask_id); + $status = ($subtask['status'] + 1) % 3; + + $values = array( + 'id' => $subtask['id'], + 'status' => $status, + 'task_id' => $subtask['task_id'], + ); + + if (empty($subtask['user_id']) && $this->userSession->isLogged()) { + $values['user_id'] = $this->userSession->getId(); + } + + return $this->subtaskModel->update($values) ? $status : false; + } + + /** + * Close all subtasks of a task + * + * @access public + * @param integer $task_id + * @return boolean + */ + public function closeAll($task_id) + { + return $this->db + ->table(SubtaskModel::TABLE) + ->eq('task_id', $task_id) + ->update(array('status' => SubtaskModel::STATUS_DONE)); + } +} diff --git a/app/Model/TaskStatusModel.php b/app/Model/TaskStatusModel.php index ea304beb..dc114698 100644 --- a/app/Model/TaskStatusModel.php +++ b/app/Model/TaskStatusModel.php @@ -45,7 +45,7 @@ class TaskStatusModel extends Base */ public function close($task_id) { - $this->subtaskModel->closeAll($task_id); + $this->subtaskStatusModel->closeAll($task_id); return $this->changeStatus($task_id, TaskModel::STATUS_CLOSED, time(), TaskModel::EVENT_CLOSE); } diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index ad69d5fb..9a71148b 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -61,6 +61,7 @@ class ClassProvider implements ServiceProviderInterface 'RememberMeSessionModel', 'SubtaskModel', 'SubtaskPositionModel', + 'SubtaskStatusModel', 'SubtaskTaskConversionModel', 'SubtaskTimeTrackingModel', 'SwimlaneModel', diff --git a/app/Subscriber/BootstrapSubscriber.php b/app/Subscriber/BootstrapSubscriber.php index 7d12e9ae..3618f30f 100644 --- a/app/Subscriber/BootstrapSubscriber.php +++ b/app/Subscriber/BootstrapSubscriber.php @@ -21,7 +21,7 @@ class BootstrapSubscriber extends BaseSubscriber implements EventSubscriberInter $this->actionManager->attachEvents(); if ($this->userSession->isLogged()) { - $this->sessionStorage->hasSubtaskInProgress = $this->subtaskModel->hasSubtaskInProgress($this->userSession->getId()); + $this->sessionStorage->hasSubtaskInProgress = $this->subtaskStatusModel->hasSubtaskInProgress($this->userSession->getId()); } } diff --git a/tests/units/Model/SubtaskModelTest.php b/tests/units/Model/SubtaskModelTest.php index d270e177..23183d22 100644 --- a/tests/units/Model/SubtaskModelTest.php +++ b/tests/units/Model/SubtaskModelTest.php @@ -5,7 +5,6 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\SubtaskModel; use Kanboard\Model\ProjectModel; -use Kanboard\Model\TaskFinderModel; class SubtaskModelTest extends Base { @@ -74,115 +73,6 @@ class SubtaskModelTest extends Base $this->assertEmpty($subtask); } - public function testToggleStatusWithoutSession() - { - $taskCreationModel = new TaskCreationModel($this->container); - $subtaskModel = new SubtaskModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - } - - public function testToggleStatusWithSession() - { - $taskCreationModel = new TaskCreationModel($this->container); - $subtaskModel = new SubtaskModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - // Set the current logged user - $this->container['sessionStorage']->user = array('id' => 1); - - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); - $this->assertEquals(1, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); - $this->assertEquals(1, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(1, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - } - - public function testCloseAll() - { - $taskCreationModel = new TaskCreationModel($this->container); - $subtaskModel = new SubtaskModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); - - $this->assertTrue($subtaskModel->closeAll(1)); - - $subtasks = $subtaskModel->getAll(1); - $this->assertNotEmpty($subtasks); - - foreach ($subtasks as $subtask) { - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); - } - } - public function testDuplicate() { $taskCreationModel = new TaskCreationModel($this->container); diff --git a/tests/units/Model/SubtaskStatusModelTest.php b/tests/units/Model/SubtaskStatusModelTest.php new file mode 100644 index 00000000..af4c3955 --- /dev/null +++ b/tests/units/Model/SubtaskStatusModelTest.php @@ -0,0 +1,123 @@ +container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskStatusModel = new SubtaskStatusModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + } + + public function testToggleStatusWithSession() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + $subtaskStatusModel = new SubtaskStatusModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + // Set the current logged user + $this->container['sessionStorage']->user = array('id' => 1); + + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); + $this->assertEquals(1, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); + $this->assertEquals(1, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(1, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + } + + public function testCloseAll() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + $subtaskStatusModel = new SubtaskStatusModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); + + $this->assertTrue($subtaskStatusModel->closeAll(1)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertNotEmpty($subtasks); + + foreach ($subtasks as $subtask) { + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); + } + } +} diff --git a/tests/units/Model/SubtaskTimeTrackingModelTest.php b/tests/units/Model/SubtaskTimeTrackingModelTest.php new file mode 100644 index 00000000..cfee5b14 --- /dev/null +++ b/tests/units/Model/SubtaskTimeTrackingModelTest.php @@ -0,0 +1,240 @@ +container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); + + $this->assertFalse($subtaskTimeTrackingModel->hasTimer(1, 1)); + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(1, 1)); + $this->assertTrue($subtaskTimeTrackingModel->hasTimer(1, 1)); + $this->assertFalse($subtaskTimeTrackingModel->logStartTime(1, 1)); + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(1, 1)); + $this->assertFalse($subtaskTimeTrackingModel->hasTimer(1, 1)); + } + + public function testGetTimerStatus() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->container['sessionStorage']->user = array('id' => 1); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1, 'user_id' => 1))); + + // Nothing started + $subtasks = $subtaskModel->getAll(1); + $this->assertNotEmpty($subtasks); + $this->assertEquals(0, $subtasks[0]['timer_start_date']); + $this->assertFalse($subtasks[0]['is_timer_started']); + + $subtask = $subtaskModel->getById(1, true); + $this->assertNotEmpty($subtask); + $this->assertEquals(0, $subtask['timer_start_date']); + $this->assertFalse($subtask['is_timer_started']); + + // Start the clock + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(1, 1)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertNotEmpty($subtasks); + $this->assertEquals(time(), $subtasks[0]['timer_start_date'], '', 3); + $this->assertTrue($subtasks[0]['is_timer_started']); + + $subtask = $subtaskModel->getById(1, true); + $this->assertNotEmpty($subtask); + $this->assertEquals(time(), $subtask['timer_start_date'], '', 3); + $this->assertTrue($subtask['is_timer_started']); + + // Stop the clock + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(1, 1)); + $subtasks = $subtaskModel->getAll(1); + $this->assertNotEmpty($subtasks); + $this->assertEquals(0, $subtasks[0]['timer_start_date']); + $this->assertFalse($subtasks[0]['is_timer_started']); + + $subtask = $subtaskModel->getById(1, true); + $this->assertNotEmpty($subtask); + $this->assertEquals(0, $subtask['timer_start_date']); + $this->assertFalse($subtask['is_timer_started']); + } + + public function testLogStartTime() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); + + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(1, 1)); + + $timesheet = $subtaskTimeTrackingModel->getUserTimesheet(1); + $this->assertNotEmpty($timesheet); + $this->assertCount(1, $timesheet); + $this->assertNotEmpty($timesheet[0]['start']); + $this->assertEmpty($timesheet[0]['end']); + $this->assertEquals(1, $timesheet[0]['user_id']); + $this->assertEquals(1, $timesheet[0]['subtask_id']); + } + + public function testLogStartEnd() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); + + // No start time + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(1, 1)); + $timesheet = $subtaskTimeTrackingModel->getUserTimesheet(1); + $this->assertEmpty($timesheet); + + // Log start and end time + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(1, 1)); + sleep(1); + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(1, 1)); + + $timesheet = $subtaskTimeTrackingModel->getUserTimesheet(1); + $this->assertNotEmpty($timesheet); + $this->assertCount(1, $timesheet); + $this->assertNotEmpty($timesheet[0]['start']); + $this->assertNotEmpty($timesheet[0]['end']); + $this->assertEquals(1, $timesheet[0]['user_id']); + $this->assertEquals(1, $timesheet[0]['subtask_id']); + $this->assertNotEquals($timesheet[0]['start'], $timesheet[0]['end']); + } + + public function testCalculateSubtaskTime() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 2.2, 'time_estimated' => 3.3))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 1.1, 'time_estimated' => 4.4))); + + $time = $subtaskTimeTrackingModel->calculateSubtaskTime(1); + $this->assertCount(2, $time); + $this->assertEquals(3.3, $time['time_spent'], 'Total spent', 0.01); + $this->assertEquals(7.7, $time['time_estimated'], 'Total estimated', 0.01); + } + + public function testUpdateSubtaskTimeSpent() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 2.2))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); + + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(1, 1)); + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(2, 1)); + + // Fake start time + $this->container['db']->table(SubtaskTimeTrackingModel::TABLE)->update(array('start' => time() - 3600)); + + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(1, 1)); + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(2, 1)); + + $timesheet = $subtaskTimeTrackingModel->getUserTimesheet(1); + $this->assertNotEmpty($timesheet); + $this->assertCount(2, $timesheet); + $this->assertEquals(3600, $timesheet[0]['end'] - $timesheet[0]['start'], 'Wrong timestamps', 1); + $this->assertEquals(3600, $timesheet[1]['end'] - $timesheet[1]['start'], 'Wrong timestamps', 1); + + $time = $subtaskTimeTrackingModel->calculateSubtaskTime(1); + $this->assertEquals(4.2, $time['time_spent'], 'Total spent', 0.01); + $this->assertEquals(0, $time['time_estimated'], 'Total estimated', 0.01); + + $time = $subtaskTimeTrackingModel->calculateSubtaskTime(2); + $this->assertEquals(0, $time['time_spent'], 'Total spent', 0.01); + $this->assertEquals(0, $time['time_estimated'], 'Total estimated', 0.01); + } + + public function testUpdateTaskTimeTracking() + { + $taskFinderModel = new TaskFinderModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'test 2', 'project_id' => 1, 'time_estimated' => 1.5, 'time_spent' => 0.5))); + $this->assertEquals(3, $taskCreationModel->create(array('title' => 'test 3', 'project_id' => 1, 'time_estimated' => 4, 'time_spent' => 2))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1, 'time_spent' => 2.2))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_estimated' => 1))); + + $this->assertEquals(3, $subtaskModel->create(array('title' => 'subtask #3', 'task_id' => 2, 'time_spent' => 3.4))); + $this->assertEquals(4, $subtaskModel->create(array('title' => 'subtask #4', 'task_id' => 2, 'time_estimated' => 1.25))); + + $this->assertEquals(5, $subtaskModel->create(array('title' => 'subtask #5', 'task_id' => 3, 'time_spent' => 8))); + + $subtaskTimeTrackingModel->updateTaskTimeTracking(1); + $subtaskTimeTrackingModel->updateTaskTimeTracking(2); + $subtaskTimeTrackingModel->updateTaskTimeTracking(3); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(2.2, $task['time_spent'], 'Total spent', 0.01); + $this->assertEquals(1, $task['time_estimated'], 'Total estimated', 0.01); + + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(3.4, $task['time_spent'], 'Total spent', 0.01); + $this->assertEquals(1.25, $task['time_estimated'], 'Total estimated', 0.01); + + $task = $taskFinderModel->getById(3); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['time_estimated']); + $this->assertEquals(8, $task['time_spent']); + + $this->assertTrue($subtaskModel->remove(3)); + $this->assertTrue($subtaskModel->remove(4)); + + $subtaskTimeTrackingModel->updateTaskTimeTracking(2); + + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['time_estimated']); + $this->assertEquals(0, $task['time_spent']); + } +} diff --git a/tests/units/Model/SubtaskTimeTrackingTest.php b/tests/units/Model/SubtaskTimeTrackingTest.php deleted file mode 100644 index d5ae62ae..00000000 --- a/tests/units/Model/SubtaskTimeTrackingTest.php +++ /dev/null @@ -1,240 +0,0 @@ -container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); - - $this->assertFalse($st->hasTimer(1, 1)); - $this->assertTrue($st->logStartTime(1, 1)); - $this->assertTrue($st->hasTimer(1, 1)); - $this->assertFalse($st->logStartTime(1, 1)); - $this->assertTrue($st->logEndTime(1, 1)); - $this->assertFalse($st->hasTimer(1, 1)); - } - - public function testGetTimerStatus() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->container['sessionStorage']->user = array('id' => 1); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1, 'user_id' => 1))); - - // Nothing started - $subtasks = $s->getAll(1); - $this->assertNotEmpty($subtasks); - $this->assertEquals(0, $subtasks[0]['timer_start_date']); - $this->assertFalse($subtasks[0]['is_timer_started']); - - $subtask = $s->getById(1, true); - $this->assertNotEmpty($subtask); - $this->assertEquals(0, $subtask['timer_start_date']); - $this->assertFalse($subtask['is_timer_started']); - - // Start the clock - $this->assertTrue($st->logStartTime(1, 1)); - - $subtasks = $s->getAll(1); - $this->assertNotEmpty($subtasks); - $this->assertEquals(time(), $subtasks[0]['timer_start_date'], '', 3); - $this->assertTrue($subtasks[0]['is_timer_started']); - - $subtask = $s->getById(1, true); - $this->assertNotEmpty($subtask); - $this->assertEquals(time(), $subtask['timer_start_date'], '', 3); - $this->assertTrue($subtask['is_timer_started']); - - // Stop the clock - $this->assertTrue($st->logEndTime(1, 1)); - $subtasks = $s->getAll(1); - $this->assertNotEmpty($subtasks); - $this->assertEquals(0, $subtasks[0]['timer_start_date']); - $this->assertFalse($subtasks[0]['is_timer_started']); - - $subtask = $s->getById(1, true); - $this->assertNotEmpty($subtask); - $this->assertEquals(0, $subtask['timer_start_date']); - $this->assertFalse($subtask['is_timer_started']); - } - - public function testLogStartTime() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); - - $this->assertTrue($st->logStartTime(1, 1)); - - $timesheet = $st->getUserTimesheet(1); - $this->assertNotEmpty($timesheet); - $this->assertCount(1, $timesheet); - $this->assertNotEmpty($timesheet[0]['start']); - $this->assertEmpty($timesheet[0]['end']); - $this->assertEquals(1, $timesheet[0]['user_id']); - $this->assertEquals(1, $timesheet[0]['subtask_id']); - } - - public function testLogStartEnd() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); - - // No start time - $this->assertTrue($st->logEndTime(1, 1)); - $timesheet = $st->getUserTimesheet(1); - $this->assertEmpty($timesheet); - - // Log start and end time - $this->assertTrue($st->logStartTime(1, 1)); - sleep(1); - $this->assertTrue($st->logEndTime(1, 1)); - - $timesheet = $st->getUserTimesheet(1); - $this->assertNotEmpty($timesheet); - $this->assertCount(1, $timesheet); - $this->assertNotEmpty($timesheet[0]['start']); - $this->assertNotEmpty($timesheet[0]['end']); - $this->assertEquals(1, $timesheet[0]['user_id']); - $this->assertEquals(1, $timesheet[0]['subtask_id']); - $this->assertNotEquals($timesheet[0]['start'], $timesheet[0]['end']); - } - - public function testCalculateSubtaskTime() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 2.2, 'time_estimated' => 3.3))); - $this->assertEquals(2, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 1.1, 'time_estimated' => 4.4))); - - $time = $st->calculateSubtaskTime(1); - $this->assertCount(2, $time); - $this->assertEquals(3.3, $time['time_spent'], 'Total spent', 0.01); - $this->assertEquals(7.7, $time['time_estimated'], 'Total estimated', 0.01); - } - - public function testUpdateSubtaskTimeSpent() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 2.2))); - $this->assertEquals(2, $s->create(array('title' => 'subtask #2', 'task_id' => 1))); - - $this->assertTrue($st->logStartTime(1, 1)); - $this->assertTrue($st->logStartTime(2, 1)); - - // Fake start time - $this->container['db']->table(SubtaskTimeTrackingModel::TABLE)->update(array('start' => time() - 3600)); - - $this->assertTrue($st->logEndTime(1, 1)); - $this->assertTrue($st->logEndTime(2, 1)); - - $timesheet = $st->getUserTimesheet(1); - $this->assertNotEmpty($timesheet); - $this->assertCount(2, $timesheet); - $this->assertEquals(3600, $timesheet[0]['end'] - $timesheet[0]['start'], 'Wrong timestamps', 1); - $this->assertEquals(3600, $timesheet[1]['end'] - $timesheet[1]['start'], 'Wrong timestamps', 1); - - $time = $st->calculateSubtaskTime(1); - $this->assertEquals(4.2, $time['time_spent'], 'Total spent', 0.01); - $this->assertEquals(0, $time['time_estimated'], 'Total estimated', 0.01); - - $time = $st->calculateSubtaskTime(2); - $this->assertEquals(0, $time['time_spent'], 'Total spent', 0.01); - $this->assertEquals(0, $time['time_estimated'], 'Total estimated', 0.01); - } - - public function testUpdateTaskTimeTracking() - { - $tf = new TaskFinderModel($this->container); - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1))); - $this->assertEquals(2, $tc->create(array('title' => 'test 2', 'project_id' => 1, 'time_estimated' => 1.5, 'time_spent' => 0.5))); - $this->assertEquals(3, $tc->create(array('title' => 'test 3', 'project_id' => 1, 'time_estimated' => 4, 'time_spent' => 2))); - - $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1, 'time_spent' => 2.2))); - $this->assertEquals(2, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_estimated' => 1))); - - $this->assertEquals(3, $s->create(array('title' => 'subtask #3', 'task_id' => 2, 'time_spent' => 3.4))); - $this->assertEquals(4, $s->create(array('title' => 'subtask #4', 'task_id' => 2, 'time_estimated' => 1.25))); - - $this->assertEquals(5, $s->create(array('title' => 'subtask #5', 'task_id' => 3, 'time_spent' => 8))); - - $st->updateTaskTimeTracking(1); - $st->updateTaskTimeTracking(2); - $st->updateTaskTimeTracking(3); - - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(2.2, $task['time_spent'], 'Total spent', 0.01); - $this->assertEquals(1, $task['time_estimated'], 'Total estimated', 0.01); - - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(3.4, $task['time_spent'], 'Total spent', 0.01); - $this->assertEquals(1.25, $task['time_estimated'], 'Total estimated', 0.01); - - $task = $tf->getById(3); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['time_estimated']); - $this->assertEquals(8, $task['time_spent']); - - $this->assertTrue($s->remove(3)); - $this->assertTrue($s->remove(4)); - - $st->updateTaskTimeTracking(2); - - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['time_estimated']); - $this->assertEquals(0, $task['time_spent']); - } -} -- cgit v1.2.3 From 5884c65a02a13dd396525d0b8d1720d1c062a96e Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 23 Jul 2016 22:50:20 -0400 Subject: Remove SubtaskTimeTrackingSubscriber --- app/Model/SubtaskModel.php | 15 ++++--- app/Model/SubtaskStatusModel.php | 3 ++ app/Model/SubtaskTimeTrackingModel.php | 23 ++++++++++- app/ServiceProvider/EventDispatcherProvider.php | 2 - app/Subscriber/SubtaskTimeTrackingSubscriber.php | 48 ---------------------- tests/units/Job/SubtaskEventJobTest.php | 2 +- tests/units/Model/SubtaskModelTest.php | 42 ++++++++++++++++++- tests/units/Model/SubtaskTimeTrackingModelTest.php | 37 +++++++++++++++++ 8 files changed, 114 insertions(+), 58 deletions(-) delete mode 100644 app/Subscriber/SubtaskTimeTrackingSubscriber.php (limited to 'app/Subscriber') diff --git a/app/Model/SubtaskModel.php b/app/Model/SubtaskModel.php index 568e27a4..608ffce7 100644 --- a/app/Model/SubtaskModel.php +++ b/app/Model/SubtaskModel.php @@ -173,6 +173,7 @@ class SubtaskModel extends Base $subtask_id = $this->db->table(self::TABLE)->persist($values); if ($subtask_id !== false) { + $this->subtaskTimeTrackingModel->updateTaskTimeTracking($values['task_id']); $this->queueManager->push($this->subtaskEventJob->withParams($subtask_id, self::EVENT_CREATE)); } @@ -183,17 +184,21 @@ class SubtaskModel extends Base * Update * * @access public - * @param array $values Form values - * @param bool $fire_events If true, will be called an event + * @param array $values + * @param bool $fire_event * @return bool */ - public function update(array $values, $fire_events = true) + public function update(array $values, $fire_event = true) { $this->prepare($values); $result = $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values); - if ($result && $fire_events) { - $this->queueManager->push($this->subtaskEventJob->withParams($values['id'], self::EVENT_UPDATE, $values)); + if ($result) { + $this->subtaskTimeTrackingModel->updateTaskTimeTracking($values['task_id']); + + if ($fire_event) { + $this->queueManager->push($this->subtaskEventJob->withParams($values['id'], self::EVENT_UPDATE, $values)); + } } return $result; diff --git a/app/Model/SubtaskStatusModel.php b/app/Model/SubtaskStatusModel.php index 26cbb67d..c99d6055 100644 --- a/app/Model/SubtaskStatusModel.php +++ b/app/Model/SubtaskStatusModel.php @@ -63,8 +63,11 @@ class SubtaskStatusModel extends Base if (empty($subtask['user_id']) && $this->userSession->isLogged()) { $values['user_id'] = $this->userSession->getId(); + $subtask['user_id'] = $values['user_id']; } + $this->subtaskTimeTrackingModel->toggleTimer($subtask_id, $subtask['user_id'], $status); + return $this->subtaskModel->update($values) ? $status : false; } diff --git a/app/Model/SubtaskTimeTrackingModel.php b/app/Model/SubtaskTimeTrackingModel.php index 062e594a..3b1b97e4 100644 --- a/app/Model/SubtaskTimeTrackingModel.php +++ b/app/Model/SubtaskTimeTrackingModel.php @@ -159,6 +159,28 @@ class SubtaskTimeTrackingModel extends Base return $this->db->table(self::TABLE)->eq('subtask_id', $subtask_id)->eq('user_id', $user_id)->eq('end', 0)->exists(); } + /** + * Start or stop timer according to subtask status + * + * @access public + * @param integer $subtask_id + * @param integer $user_id + * @param integer $status + * @return boolean + */ + public function toggleTimer($subtask_id, $user_id, $status) + { + if ($this->configModel->get('subtask_time_tracking') == 1) { + if ($status == SubtaskModel::STATUS_INPROGRESS) { + return $this->subtaskTimeTrackingModel->logStartTime($subtask_id, $user_id); + } elseif ($status == SubtaskModel::STATUS_DONE) { + return $this->subtaskTimeTrackingModel->logEndTime($subtask_id, $user_id); + } + } + + return false; + } + /** * Log start time * @@ -252,7 +274,6 @@ class SubtaskTimeTrackingModel extends Base { $subtask = $this->subtaskModel->getById($subtask_id); - // Fire the event subtask.update return $this->subtaskModel->update(array( 'id' => $subtask['id'], 'time_spent' => $subtask['time_spent'] + $time_spent, diff --git a/app/ServiceProvider/EventDispatcherProvider.php b/app/ServiceProvider/EventDispatcherProvider.php index 57543fe4..ebf42cbf 100644 --- a/app/ServiceProvider/EventDispatcherProvider.php +++ b/app/ServiceProvider/EventDispatcherProvider.php @@ -11,7 +11,6 @@ use Kanboard\Subscriber\BootstrapSubscriber; use Kanboard\Subscriber\NotificationSubscriber; use Kanboard\Subscriber\ProjectDailySummarySubscriber; use Kanboard\Subscriber\ProjectModificationDateSubscriber; -use Kanboard\Subscriber\SubtaskTimeTrackingSubscriber; use Kanboard\Subscriber\TransitionSubscriber; use Kanboard\Subscriber\RecurringTaskSubscriber; @@ -31,7 +30,6 @@ class EventDispatcherProvider implements ServiceProviderInterface $container['dispatcher']->addSubscriber(new ProjectDailySummarySubscriber($container)); $container['dispatcher']->addSubscriber(new ProjectModificationDateSubscriber($container)); $container['dispatcher']->addSubscriber(new NotificationSubscriber($container)); - $container['dispatcher']->addSubscriber(new SubtaskTimeTrackingSubscriber($container)); $container['dispatcher']->addSubscriber(new TransitionSubscriber($container)); $container['dispatcher']->addSubscriber(new RecurringTaskSubscriber($container)); diff --git a/app/Subscriber/SubtaskTimeTrackingSubscriber.php b/app/Subscriber/SubtaskTimeTrackingSubscriber.php deleted file mode 100644 index 7e39c126..00000000 --- a/app/Subscriber/SubtaskTimeTrackingSubscriber.php +++ /dev/null @@ -1,48 +0,0 @@ - 'updateTaskTime', - SubtaskModel::EVENT_DELETE => 'updateTaskTime', - SubtaskModel::EVENT_UPDATE => array( - array('logStartEnd', 10), - array('updateTaskTime', 0), - ) - ); - } - - public function updateTaskTime(SubtaskEvent $event) - { - if (isset($event['task_id'])) { - $this->logger->debug('Subscriber executed: '.__METHOD__); - $this->subtaskTimeTrackingModel->updateTaskTimeTracking($event['task_id']); - } - } - - public function logStartEnd(SubtaskEvent $event) - { - if (isset($event['status']) && $this->configModel->get('subtask_time_tracking') == 1) { - $this->logger->debug('Subscriber executed: '.__METHOD__); - $subtask = $this->subtaskModel->getById($event['id']); - - if (empty($subtask['user_id'])) { - return false; - } - - if ($subtask['status'] == SubtaskModel::STATUS_INPROGRESS) { - return $this->subtaskTimeTrackingModel->logStartTime($subtask['id'], $subtask['user_id']); - } else { - return $this->subtaskTimeTrackingModel->logEndTime($subtask['id'], $subtask['user_id']); - } - } - } -} diff --git a/tests/units/Job/SubtaskEventJobTest.php b/tests/units/Job/SubtaskEventJobTest.php index 66c3db05..bdc30b51 100644 --- a/tests/units/Job/SubtaskEventJobTest.php +++ b/tests/units/Job/SubtaskEventJobTest.php @@ -41,7 +41,7 @@ class SubtaskEventJobTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); $this->assertEquals(1, $subtaskModel->create(array('task_id' => 1, 'title' => 'before'))); - $this->assertTrue($subtaskModel->update(array('id' => 1, 'title' => 'after'))); + $this->assertTrue($subtaskModel->update(array('id' => 1, 'task_id' => 1, 'title' => 'after'))); $this->assertTrue($subtaskModel->remove(1)); $called = $this->container['dispatcher']->getCalledListeners(); diff --git a/tests/units/Model/SubtaskModelTest.php b/tests/units/Model/SubtaskModelTest.php index 23183d22..eed37cf3 100644 --- a/tests/units/Model/SubtaskModelTest.php +++ b/tests/units/Model/SubtaskModelTest.php @@ -5,6 +5,7 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\SubtaskModel; use Kanboard\Model\ProjectModel; +use Kanboard\Model\TaskFinderModel; class SubtaskModelTest extends Base { @@ -30,6 +31,24 @@ class SubtaskModelTest extends Base $this->assertEquals(1, $subtask['position']); } + public function testCreationUpdateTaskTimeTracking() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1, 'time_estimated' => 2, 'time_spent' => 1))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_estimated' => 5, 'time_spent' => 5))); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(7, $task['time_estimated']); + $this->assertEquals(6, $task['time_spent']); + } + public function testModification() { $taskCreationModel = new TaskCreationModel($this->container); @@ -40,7 +59,7 @@ class SubtaskModelTest extends Base $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - $this->assertTrue($subtaskModel->update(array('id' => 1, 'user_id' => 1, 'status' => SubtaskModel::STATUS_INPROGRESS))); + $this->assertTrue($subtaskModel->update(array('id' => 1, 'task_id' => 1, 'user_id' => 1, 'status' => SubtaskModel::STATUS_INPROGRESS))); $subtask = $subtaskModel->getById(1); $this->assertNotEmpty($subtask); @@ -54,6 +73,27 @@ class SubtaskModelTest extends Base $this->assertEquals(1, $subtask['position']); } + public function testModificationUpdateTaskTimeTracking() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); + $this->assertTrue($subtaskModel->update(array('id' => 1, 'task_id' => 1, 'time_estimated' => 2, 'time_spent' => 1))); + $this->assertTrue($subtaskModel->update(array('id' => 2, 'task_id' => 1, 'time_estimated' => 2, 'time_spent' => 1))); + $this->assertTrue($subtaskModel->update(array('id' => 1, 'task_id' => 1, 'time_estimated' => 5, 'time_spent' => 5))); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(7, $task['time_estimated']); + $this->assertEquals(6, $task['time_spent']); + } + public function testRemove() { $taskCreationModel = new TaskCreationModel($this->container); diff --git a/tests/units/Model/SubtaskTimeTrackingModelTest.php b/tests/units/Model/SubtaskTimeTrackingModelTest.php index cfee5b14..8b0fe698 100644 --- a/tests/units/Model/SubtaskTimeTrackingModelTest.php +++ b/tests/units/Model/SubtaskTimeTrackingModelTest.php @@ -2,6 +2,7 @@ require_once __DIR__.'/../Base.php'; +use Kanboard\Model\ConfigModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\SubtaskModel; @@ -10,6 +11,42 @@ use Kanboard\Model\ProjectModel; class SubtaskTimeTrackingModelTest extends Base { + public function testToggleTimer() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); + + $this->assertFalse($subtaskTimeTrackingModel->toggleTimer(1, 1, SubtaskModel::STATUS_TODO)); + $this->assertTrue($subtaskTimeTrackingModel->toggleTimer(1, 1, SubtaskModel::STATUS_INPROGRESS)); + $this->assertTrue($subtaskTimeTrackingModel->toggleTimer(1, 1, SubtaskModel::STATUS_DONE)); + } + + public function testToggleTimerWhenFeatureDisabled() + { + $configModel = new ConfigModel($this->container); + $configModel->save(array('subtask_time_tracking' => '0')); + $this->container['memoryCache']->flush(); + + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); + + $this->assertFalse($subtaskTimeTrackingModel->toggleTimer(1, 1, SubtaskModel::STATUS_TODO)); + $this->assertFalse($subtaskTimeTrackingModel->toggleTimer(1, 1, SubtaskModel::STATUS_INPROGRESS)); + $this->assertFalse($subtaskTimeTrackingModel->toggleTimer(1, 1, SubtaskModel::STATUS_DONE)); + } + public function testHasTimer() { $taskCreationModel = new TaskCreationModel($this->container); -- cgit v1.2.3