From 6d5577fa0bc108fcafa92fc4ac4b9ed621bfe33e Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 2 Jul 2016 15:20:59 -0400 Subject: Handle project tags duplication --- app/Model/ProjectDuplicationModel.php | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'app/Model/ProjectDuplicationModel.php') diff --git a/app/Model/ProjectDuplicationModel.php b/app/Model/ProjectDuplicationModel.php index b67f8302..4db8f767 100644 --- a/app/Model/ProjectDuplicationModel.php +++ b/app/Model/ProjectDuplicationModel.php @@ -22,7 +22,15 @@ class ProjectDuplicationModel extends Base */ public function getOptionalSelection() { - return array('categoryModel', 'projectPermissionModel', 'actionModel', 'swimlaneModel', 'taskModel', 'projectMetadataModel'); + return array( + 'categoryModel', + 'projectPermissionModel', + 'actionModel', + 'swimlaneModel', + 'tagDuplicationModel', + 'projectMetadataModel', + 'taskModel', + ); } /** @@ -33,7 +41,16 @@ class ProjectDuplicationModel extends Base */ public function getPossibleSelection() { - return array('boardModel', 'categoryModel', 'projectPermissionModel', 'actionModel', 'swimlaneModel', 'taskModel', 'projectMetadataModel'); + return array( + 'boardModel', + 'categoryModel', + 'projectPermissionModel', + 'actionModel', + 'swimlaneModel', + 'tagDuplicationModel', + 'projectMetadataModel', + 'taskModel', + ); } /** -- cgit v1.2.3 From b7ac354e83af122e94cec1f9306aca6355a02a39 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 2 Jul 2016 15:29:48 -0400 Subject: Move Task::duplicate() to class ProjectTaskDuplicationModel --- app/Core/Base.php | 1 + app/Model/ProjectDuplicationModel.php | 4 +- app/Model/ProjectTaskDuplicationModel.php | 35 ++++++++++ app/Model/TaskModel.php | 83 +++++++++-------------- app/ServiceProvider/ClassProvider.php | 1 + app/Template/project_creation/create.php | 2 +- app/Template/project_view/duplicate.php | 2 +- tests/units/Model/ProjectDuplicationModelTest.php | 6 +- 8 files changed, 75 insertions(+), 59 deletions(-) create mode 100644 app/Model/ProjectTaskDuplicationModel.php (limited to 'app/Model/ProjectDuplicationModel.php') diff --git a/app/Core/Base.php b/app/Core/Base.php index a8274152..7320aebf 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -86,6 +86,7 @@ use Pimple\Container; * @property \Kanboard\Model\ProjectGroupRoleModel $projectGroupRoleModel * @property \Kanboard\Model\ProjectNotificationModel $projectNotificationModel * @property \Kanboard\Model\ProjectNotificationTypeModel $projectNotificationTypeModel + * @property \Kanboard\Model\ProjectTaskDuplicationModel $projectTaskDuplicationModel * @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel * @property \Kanboard\Model\SubtaskModel $subtaskModel * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel diff --git a/app/Model/ProjectDuplicationModel.php b/app/Model/ProjectDuplicationModel.php index 4db8f767..f6b9683e 100644 --- a/app/Model/ProjectDuplicationModel.php +++ b/app/Model/ProjectDuplicationModel.php @@ -29,7 +29,7 @@ class ProjectDuplicationModel extends Base 'swimlaneModel', 'tagDuplicationModel', 'projectMetadataModel', - 'taskModel', + 'projectTaskDuplicationModel', ); } @@ -49,7 +49,7 @@ class ProjectDuplicationModel extends Base 'swimlaneModel', 'tagDuplicationModel', 'projectMetadataModel', - 'taskModel', + 'projectTaskDuplicationModel', ); } diff --git a/app/Model/ProjectTaskDuplicationModel.php b/app/Model/ProjectTaskDuplicationModel.php new file mode 100644 index 00000000..5d2e1322 --- /dev/null +++ b/app/Model/ProjectTaskDuplicationModel.php @@ -0,0 +1,35 @@ +taskFinderModel->getAllIds($src_project_id, array(TaskModel::STATUS_OPEN, TaskModel::STATUS_CLOSED)); + + foreach ($task_ids as $task_id) { + if (! $this->taskProjectDuplicationModel->duplicateToProject($task_id, $dst_project_id)) { + return false; + } + } + + return true; + } +} diff --git a/app/Model/TaskModel.php b/app/Model/TaskModel.php index b945ee44..5df41f3c 100644 --- a/app/Model/TaskModel.php +++ b/app/Model/TaskModel.php @@ -17,80 +17,80 @@ class TaskModel extends Base * * @var string */ - const TABLE = 'tasks'; + const TABLE = 'tasks'; /** * Task status * * @var integer */ - const STATUS_OPEN = 1; - const STATUS_CLOSED = 0; + const STATUS_OPEN = 1; + const STATUS_CLOSED = 0; /** * Events * * @var string */ - const EVENT_MOVE_PROJECT = 'task.move.project'; - const EVENT_MOVE_COLUMN = 'task.move.column'; - const EVENT_MOVE_POSITION = 'task.move.position'; - const EVENT_MOVE_SWIMLANE = 'task.move.swimlane'; - const EVENT_UPDATE = 'task.update'; - const EVENT_CREATE = 'task.create'; - const EVENT_CLOSE = 'task.close'; - const EVENT_OPEN = 'task.open'; - const EVENT_CREATE_UPDATE = 'task.create_update'; + const EVENT_MOVE_PROJECT = 'task.move.project'; + const EVENT_MOVE_COLUMN = 'task.move.column'; + const EVENT_MOVE_POSITION = 'task.move.position'; + const EVENT_MOVE_SWIMLANE = 'task.move.swimlane'; + const EVENT_UPDATE = 'task.update'; + const EVENT_CREATE = 'task.create'; + const EVENT_CLOSE = 'task.close'; + const EVENT_OPEN = 'task.open'; + const EVENT_CREATE_UPDATE = 'task.create_update'; const EVENT_ASSIGNEE_CHANGE = 'task.assignee_change'; - const EVENT_OVERDUE = 'task.overdue'; - const EVENT_USER_MENTION = 'task.user.mention'; - const EVENT_DAILY_CRONJOB = 'task.cronjob.daily'; + const EVENT_OVERDUE = 'task.overdue'; + const EVENT_USER_MENTION = 'task.user.mention'; + const EVENT_DAILY_CRONJOB = 'task.cronjob.daily'; /** * Recurrence: status * * @var integer */ - const RECURRING_STATUS_NONE = 0; - const RECURRING_STATUS_PENDING = 1; - const RECURRING_STATUS_PROCESSED = 2; + const RECURRING_STATUS_NONE = 0; + const RECURRING_STATUS_PENDING = 1; + const RECURRING_STATUS_PROCESSED = 2; /** * Recurrence: trigger * * @var integer */ - const RECURRING_TRIGGER_FIRST_COLUMN = 0; - const RECURRING_TRIGGER_LAST_COLUMN = 1; - const RECURRING_TRIGGER_CLOSE = 2; + const RECURRING_TRIGGER_FIRST_COLUMN = 0; + const RECURRING_TRIGGER_LAST_COLUMN = 1; + const RECURRING_TRIGGER_CLOSE = 2; /** * Recurrence: timeframe * * @var integer */ - const RECURRING_TIMEFRAME_DAYS = 0; - const RECURRING_TIMEFRAME_MONTHS = 1; - const RECURRING_TIMEFRAME_YEARS = 2; + const RECURRING_TIMEFRAME_DAYS = 0; + const RECURRING_TIMEFRAME_MONTHS = 1; + const RECURRING_TIMEFRAME_YEARS = 2; /** * Recurrence: base date used to calculate new due date * * @var integer */ - const RECURRING_BASEDATE_DUEDATE = 0; - const RECURRING_BASEDATE_TRIGGERDATE = 1; + const RECURRING_BASEDATE_DUEDATE = 0; + const RECURRING_BASEDATE_TRIGGERDATE = 1; /** * Remove a task * * @access public - * @param integer $task_id Task id + * @param integer $task_id Task id * @return boolean */ public function remove($task_id) { - if (! $this->taskFinderModel->exists($task_id)) { + if (!$this->taskFinderModel->exists($task_id)) { return false; } @@ -105,7 +105,7 @@ class TaskModel extends Base * Example: "Fix bug #1234" will return 1234 * * @access public - * @param string $message Text + * @param string $message Text * @return integer */ public function getTaskIdFromText($message) @@ -179,8 +179,8 @@ class TaskModel extends Base * Get task progress based on the column position * * @access public - * @param array $task - * @param array $columns + * @param array $task + * @param array $columns * @return integer */ public function getProgress(array $task, array $columns) @@ -201,25 +201,4 @@ class TaskModel extends Base return round(($position * 100) / count($columns), 1); } - - /** - * Helper method to duplicate all tasks to another project - * - * @access public - * @param integer $src_project_id - * @param integer $dst_project_id - * @return boolean - */ - public function duplicate($src_project_id, $dst_project_id) - { - $task_ids = $this->taskFinderModel->getAllIds($src_project_id, array(TaskModel::STATUS_OPEN, TaskModel::STATUS_CLOSED)); - - foreach ($task_ids as $task_id) { - if (! $this->taskProjectDuplicationModel->duplicateToProject($task_id, $dst_project_id)) { - return false; - } - } - - return true; - } } diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 1f584fca..2d485e22 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -55,6 +55,7 @@ class ClassProvider implements ServiceProviderInterface 'ProjectNotificationModel', 'ProjectMetadataModel', 'ProjectGroupRoleModel', + 'ProjectTaskDuplicationModel', 'ProjectUserRoleModel', 'RememberMeSessionModel', 'SubtaskModel', diff --git a/app/Template/project_creation/create.php b/app/Template/project_creation/create.php index dc1bc370..d00883ba 100644 --- a/app/Template/project_creation/create.php +++ b/app/Template/project_creation/create.php @@ -26,7 +26,7 @@ form->checkbox('tagDuplicationModel', t('Tags'), 1, true) ?> form->checkbox('actionModel', t('Actions'), 1, true) ?> form->checkbox('swimlaneModel', t('Swimlanes'), 1, true) ?> - form->checkbox('taskModel', t('Tasks'), 1, false) ?> + form->checkbox('projectTaskDuplicationModel', t('Tasks'), 1, false) ?>
diff --git a/app/Template/project_view/duplicate.php b/app/Template/project_view/duplicate.php index a9680016..d66ff591 100644 --- a/app/Template/project_view/duplicate.php +++ b/app/Template/project_view/duplicate.php @@ -19,7 +19,7 @@ form->checkbox('actionModel', t('Actions'), 1, true) ?> form->checkbox('swimlaneModel', t('Swimlanes'), 1, false) ?> form->checkbox('projectMetadataModel', t('Metadata'), 1, false) ?> - form->checkbox('taskModel', t('Tasks'), 1, false) ?> + form->checkbox('projectTaskDuplicationModel', t('Tasks'), 1, false) ?>
diff --git a/tests/units/Model/ProjectDuplicationModelTest.php b/tests/units/Model/ProjectDuplicationModelTest.php index de7b0d79..41e59c9c 100644 --- a/tests/units/Model/ProjectDuplicationModelTest.php +++ b/tests/units/Model/ProjectDuplicationModelTest.php @@ -428,7 +428,7 @@ class ProjectDuplicationModelTest extends Base $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1, 'column_id' => 2))); $this->assertEquals(3, $taskCreationModel->create(array('title' => 'T3', 'project_id' => 1, 'column_id' => 3))); - $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('categoryModel', 'actionModel', 'taskModel'))); + $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('categoryModel', 'actionModel', 'projectTaskDuplicationModel'))); // Check if Tasks have been duplicated $tasks = $taskFinderModel->getAll(2); @@ -458,7 +458,7 @@ class ProjectDuplicationModelTest extends Base $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 1))); $this->assertEquals(3, $taskCreationModel->create(array('title' => 'T3', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); - $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('projectPermissionModel', 'swimlaneModel', 'taskModel'))); + $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('projectPermissionModel', 'swimlaneModel', 'projectTaskDuplicationModel'))); // Check if Swimlanes have been duplicated $swimlanes = $swimlaneModel->getAll(2); @@ -496,7 +496,7 @@ class ProjectDuplicationModelTest extends Base $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1, 'column_id' => 2, 'tags' => array('A', 'B')))); $this->assertEquals(3, $taskCreationModel->create(array('title' => 'T3', 'project_id' => 1, 'column_id' => 3, 'tags' => array('C')))); - $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('categoryModel', 'actionModel', 'tagDuplicationModel', 'taskModel'))); + $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('categoryModel', 'actionModel', 'tagDuplicationModel', 'projectTaskDuplicationModel'))); $tasks = $taskFinderModel->getAll(2); $this->assertCount(3, $tasks); -- cgit v1.2.3 From 10d577ad9d1b2976cdb080a7d7df3944e0db170f Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 2 Jul 2016 16:36:10 -0400 Subject: Handle priority for task and project duplication --- ChangeLog | 1 + app/Controller/ActionCreationController.php | 2 +- app/Core/Base.php | 1 + app/Model/ProjectDuplicationModel.php | 3 + app/Model/ProjectModel.php | 13 - app/Model/ProjectTaskPriorityModel.php | 74 +++++ app/Model/TaskDuplicationModel.php | 11 +- app/ServiceProvider/ClassProvider.php | 1 + tests/units/Model/ProjectDuplicationModelTest.php | 22 ++ tests/units/Model/ProjectModelTest.php | 306 +++++++++++++++++++ tests/units/Model/ProjectTaskPriorityModelTest.php | 84 ++++++ tests/units/Model/ProjectTest.php | 336 --------------------- 12 files changed, 502 insertions(+), 352 deletions(-) create mode 100644 app/Model/ProjectTaskPriorityModel.php create mode 100644 tests/units/Model/ProjectModelTest.php create mode 100644 tests/units/Model/ProjectTaskPriorityModelTest.php delete mode 100644 tests/units/Model/ProjectTest.php (limited to 'app/Model/ProjectDuplicationModel.php') diff --git a/ChangeLog b/ChangeLog index 7c04ba43..000400ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,7 @@ New features: Improvements: +* Handle priority for task and project duplication * Expose task reference field to the user interface * Improve ICal export * Added argument owner_id and identifier to project API calls diff --git a/app/Controller/ActionCreationController.php b/app/Controller/ActionCreationController.php index abd8abd3..9b228f28 100644 --- a/app/Controller/ActionCreationController.php +++ b/app/Controller/ActionCreationController.php @@ -81,7 +81,7 @@ class ActionCreationController extends BaseController 'colors_list' => $this->colorModel->getList(), 'categories_list' => $this->categoryModel->getList($project['id']), 'links_list' => $this->linkModel->getList(0, false), - 'priorities_list' => $this->projectModel->getPriorities($project), + 'priorities_list' => $this->projectTaskPriorityModel->getPriorities($project), 'project' => $project, 'available_actions' => $this->actionManager->getAvailableActions(), 'events' => $this->actionManager->getCompatibleEvents($values['action_name']), diff --git a/app/Core/Base.php b/app/Core/Base.php index 7320aebf..8103ec14 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -87,6 +87,7 @@ use Pimple\Container; * @property \Kanboard\Model\ProjectNotificationModel $projectNotificationModel * @property \Kanboard\Model\ProjectNotificationTypeModel $projectNotificationTypeModel * @property \Kanboard\Model\ProjectTaskDuplicationModel $projectTaskDuplicationModel + * @property \Kanboard\Model\ProjectTaskPriorityModel $projectTaskPriorityModel * @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel * @property \Kanboard\Model\SubtaskModel $subtaskModel * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel diff --git a/app/Model/ProjectDuplicationModel.php b/app/Model/ProjectDuplicationModel.php index f6b9683e..94b83c80 100644 --- a/app/Model/ProjectDuplicationModel.php +++ b/app/Model/ProjectDuplicationModel.php @@ -146,6 +146,9 @@ class ProjectDuplicationModel extends Base 'is_public' => 0, 'is_private' => $private ? 1 : $is_private, 'owner_id' => $owner_id, + 'priority_default' => $project['priority_default'], + 'priority_start' => $project['priority_start'], + 'priority_end' => $project['priority_end'], ); if (! $this->db->table(ProjectModel::TABLE)->save($values)) { diff --git a/app/Model/ProjectModel.php b/app/Model/ProjectModel.php index 7382537e..850531c9 100644 --- a/app/Model/ProjectModel.php +++ b/app/Model/ProjectModel.php @@ -245,19 +245,6 @@ class ProjectModel extends Base ->count(); } - /** - * Get Priority range from a project - * - * @access public - * @param array $project - * @return array - */ - public function getPriorities(array $project) - { - $range = range($project['priority_start'], $project['priority_end']); - return array_combine($range, $range); - } - /** * Gather some task metrics for a given project * diff --git a/app/Model/ProjectTaskPriorityModel.php b/app/Model/ProjectTaskPriorityModel.php new file mode 100644 index 00000000..c1a0257a --- /dev/null +++ b/app/Model/ProjectTaskPriorityModel.php @@ -0,0 +1,74 @@ +db + ->table(ProjectModel::TABLE) + ->columns('priority_default', 'priority_start', 'priority_end') + ->eq('id', $project_id) + ->findOne(); + } + + /** + * Get default task priority + * + * @access public + * @param int $project_id + * @return int + */ + public function getDefaultPriority($project_id) + { + return $this->db->table(ProjectModel::TABLE)->eq('id', $project_id)->findOneColumn('priority_default') ?: 0; + } + + /** + * Get priority for a destination project + * + * @access public + * @param integer $dst_project_id + * @param integer $priority + * @return integer + */ + public function getPriorityForProject($dst_project_id, $priority) + { + $settings = $this->getPrioritySettings($dst_project_id); + + if ($priority >= $settings['priority_start'] && $priority <= $settings['priority_end']) { + return $priority; + } + + return $settings['priority_default']; + } +} diff --git a/app/Model/TaskDuplicationModel.php b/app/Model/TaskDuplicationModel.php index 0dce891f..c9079653 100644 --- a/app/Model/TaskDuplicationModel.php +++ b/app/Model/TaskDuplicationModel.php @@ -18,7 +18,7 @@ class TaskDuplicationModel extends Base * @access protected * @var string[] */ - protected $fields_to_duplicate = array( + protected $fieldsToDuplicate = array( 'title', 'description', 'date_due', @@ -27,6 +27,7 @@ class TaskDuplicationModel extends Base 'column_id', 'owner_id', 'score', + 'priority', 'category_id', 'time_estimated', 'swimlane_id', @@ -95,6 +96,12 @@ class TaskDuplicationModel extends Base $values['column_id'] = $values['column_id'] ?: $this->columnModel->getFirstColumnId($values['project_id']); } + // Check if priority exists for destination project + $values['priority'] = $this->projectTaskPriorityModel->getPriorityForProject( + $values['project_id'], + empty($values['priority']) ? 0 : $values['priority'] + ); + return $values; } @@ -110,7 +117,7 @@ class TaskDuplicationModel extends Base $task = $this->taskFinderModel->getById($task_id); $values = array(); - foreach ($this->fields_to_duplicate as $field) { + foreach ($this->fieldsToDuplicate as $field) { $values[$field] = $task[$field]; } diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 2d485e22..e32c0d43 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -56,6 +56,7 @@ class ClassProvider implements ServiceProviderInterface 'ProjectMetadataModel', 'ProjectGroupRoleModel', 'ProjectTaskDuplicationModel', + 'ProjectTaskPriorityModel', 'ProjectUserRoleModel', 'RememberMeSessionModel', 'SubtaskModel', diff --git a/tests/units/Model/ProjectDuplicationModelTest.php b/tests/units/Model/ProjectDuplicationModelTest.php index 41e59c9c..54261728 100644 --- a/tests/units/Model/ProjectDuplicationModelTest.php +++ b/tests/units/Model/ProjectDuplicationModelTest.php @@ -141,6 +141,28 @@ class ProjectDuplicationModelTest extends Base $this->assertEquals(Role::PROJECT_MANAGER, $projectUserRoleModel->getUserRole(2, 1)); } + public function testCloneProjectWithDifferentPriorities() + { + $projectModel = new ProjectModel($this->container); + $projectDuplicationModel = new ProjectDuplicationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array( + 'name' => 'My project', + 'priority_default' => 2, + 'priority_start' => -2, + 'priority_end' => 8, + ))); + + $this->assertEquals(2, $projectDuplicationModel->duplicate(1)); + + $project = $projectModel->getById(2); + $this->assertNotEmpty($project); + $this->assertEquals('My project (Clone)', $project['name']); + $this->assertEquals(2, $project['priority_default']); + $this->assertEquals(-2, $project['priority_start']); + $this->assertEquals(8, $project['priority_end']); + } + public function testCloneProjectWithDifferentName() { $projectModel = new ProjectModel($this->container); diff --git a/tests/units/Model/ProjectModelTest.php b/tests/units/Model/ProjectModelTest.php new file mode 100644 index 00000000..81e0dd57 --- /dev/null +++ b/tests/units/Model/ProjectModelTest.php @@ -0,0 +1,306 @@ +container); + + foreach ($this->container['languageModel']->getLanguages() as $locale => $language) { + Translator::unload(); + Translator::load($locale); + $this->assertNotFalse($projectModel->create(array('name' => 'UnitTest '.$locale)), 'Unable to create project with '.$locale.':'.$language); + } + + Translator::unload(); + } + + public function testCreation() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(1, $project['is_active']); + $this->assertEquals(0, $project['is_public']); + $this->assertEquals(0, $project['is_private']); + $this->assertEquals(time(), $project['last_modified'], '', 1); + $this->assertEmpty($project['token']); + } + + public function testCreationWithDuplicateName() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'UnitTest'))); + } + + public function testCreationWithStartAndDate() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest', 'start_date' => '2015-01-01', 'end_date' => '2015-12-31'))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals('2015-01-01', $project['start_date']); + $this->assertEquals('2015-12-31', $project['end_date']); + } + + public function testCreationWithDefaultCategories() + { + $projectModel = new ProjectModel($this->container); + $configModel = new ConfigModel($this->container); + $categoryModel = new CategoryModel($this->container); + + // Multiple categories correctly formatted + + $this->assertTrue($configModel->save(array('project_categories' => 'Test1, Test2'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest1'))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + + $categories = $categoryModel->getAll(1); + $this->assertNotEmpty($categories); + $this->assertEquals(2, count($categories)); + $this->assertEquals('Test1', $categories[0]['name']); + $this->assertEquals('Test2', $categories[1]['name']); + + // Single category + + $this->assertTrue($configModel->save(array('project_categories' => 'Test1'))); + $this->container['memoryCache']->flush(); + $this->assertEquals(2, $projectModel->create(array('name' => 'UnitTest2'))); + + $project = $projectModel->getById(2); + $this->assertNotEmpty($project); + + $categories = $categoryModel->getAll(2); + $this->assertNotEmpty($categories); + $this->assertEquals(1, count($categories)); + $this->assertEquals('Test1', $categories[0]['name']); + + // Multiple categories badly formatted + + $this->assertTrue($configModel->save(array('project_categories' => 'ABC, , DEF 3, '))); + $this->container['memoryCache']->flush(); + $this->assertEquals(3, $projectModel->create(array('name' => 'UnitTest3'))); + + $project = $projectModel->getById(3); + $this->assertNotEmpty($project); + + $categories = $categoryModel->getAll(3); + $this->assertNotEmpty($categories); + $this->assertEquals(2, count($categories)); + $this->assertEquals('ABC', $categories[0]['name']); + $this->assertEquals('DEF 3', $categories[1]['name']); + + // No default categories + $this->assertTrue($configModel->save(array('project_categories' => ' '))); + $this->container['memoryCache']->flush(); + $this->assertEquals(4, $projectModel->create(array('name' => 'UnitTest4'))); + + $project = $projectModel->getById(4); + $this->assertNotEmpty($project); + + $categories = $categoryModel->getAll(4); + $this->assertEmpty($categories); + } + + public function testUpdateLastModifiedDate() + { + $projectModel = new ProjectModel($this->container); + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $now = time(); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals($now, $project['last_modified'], 'Wrong Timestamp', 1); + + sleep(1); + $this->assertTrue($projectModel->updateModificationDate(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertGreaterThan($now, $project['last_modified']); + } + + public function testGetAllIds() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $this->assertEmpty($projectModel->getAllByIds(array())); + $this->assertNotEmpty($projectModel->getAllByIds(array(1, 2))); + $this->assertCount(1, $projectModel->getAllByIds(array(1))); + } + + public function testIsLastModified() + { + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $now = time(); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals($now, $project['last_modified']); + + sleep(1); + + $listener = new ProjectModificationDateSubscriber($this->container); + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, array($listener, 'execute')); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1))); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.Kanboard\Subscriber\ProjectModificationDateSubscriber::execute', $called); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertTrue($projectModel->isModifiedSince(1, $now)); + } + + public function testRemove() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertTrue($projectModel->remove(1)); + $this->assertFalse($projectModel->remove(1234)); + } + + public function testEnable() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertTrue($projectModel->disable(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(0, $project['is_active']); + + $this->assertFalse($projectModel->disable(1111)); + } + + public function testDisable() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertTrue($projectModel->disable(1)); + $this->assertTrue($projectModel->enable(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(1, $project['is_active']); + + $this->assertFalse($projectModel->enable(1234567)); + } + + public function testEnablePublicAccess() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertTrue($projectModel->enablePublicAccess(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(1, $project['is_public']); + $this->assertNotEmpty($project['token']); + + $this->assertFalse($projectModel->enablePublicAccess(123)); + } + + public function testDisablePublicAccess() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertTrue($projectModel->enablePublicAccess(1)); + $this->assertTrue($projectModel->disablePublicAccess(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(0, $project['is_public']); + $this->assertEmpty($project['token']); + + $this->assertFalse($projectModel->disablePublicAccess(123)); + } + + public function testIdentifier() + { + $projectModel = new ProjectModel($this->container); + + // Creation + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest1', 'identifier' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'UnitTest2'))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals('TEST1', $project['identifier']); + + $project = $projectModel->getById(2); + $this->assertNotEmpty($project); + $this->assertEquals('', $project['identifier']); + + // Update + $this->assertTrue($projectModel->update(array('id' => '2', 'identifier' => 'test2'))); + + $project = $projectModel->getById(2); + $this->assertNotEmpty($project); + $this->assertEquals('TEST2', $project['identifier']); + + $project = $projectModel->getByIdentifier('test1'); + $this->assertNotEmpty($project); + $this->assertEquals('TEST1', $project['identifier']); + + $project = $projectModel->getByIdentifier(''); + $this->assertFalse($project); + } + + public function testThatProjectCreatorAreAlsoOwner() + { + $projectModel = new ProjectModel($this->container); + $userModel = new UserModel($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'user1', 'name' => 'Me'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'My project 1'), 2)); + $this->assertEquals(2, $projectModel->create(array('name' => 'My project 2'))); + + $project = $projectModel->getByIdWithOwner(1); + $this->assertNotEmpty($project); + $this->assertSame('My project 1', $project['name']); + $this->assertSame('Me', $project['owner_name']); + $this->assertSame('user1', $project['owner_username']); + $this->assertEquals(2, $project['owner_id']); + + $project = $projectModel->getByIdWithOwner(2); + $this->assertNotEmpty($project); + $this->assertSame('My project 2', $project['name']); + $this->assertEquals('', $project['owner_name']); + $this->assertEquals('', $project['owner_username']); + $this->assertEquals(0, $project['owner_id']); + } +} diff --git a/tests/units/Model/ProjectTaskPriorityModelTest.php b/tests/units/Model/ProjectTaskPriorityModelTest.php new file mode 100644 index 00000000..61661e5e --- /dev/null +++ b/tests/units/Model/ProjectTaskPriorityModelTest.php @@ -0,0 +1,84 @@ +container); + $projectTaskPriorityModel = new ProjectTaskPriorityModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'My project 2'))); + $this->assertEquals(0, $projectTaskPriorityModel->getDefaultPriority(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(0, $project['priority_default']); + $this->assertEquals(0, $project['priority_start']); + $this->assertEquals(3, $project['priority_end']); + + $this->assertEquals( + array(0 => 0, 1 => 1, 2 => 2, 3 => 3), + $projectTaskPriorityModel->getPriorities($project) + ); + + $this->assertTrue($projectModel->update(array('id' => 1, 'priority_start' => 2, 'priority_end' => 5, 'priority_default' => 4))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(4, $project['priority_default']); + $this->assertEquals(2, $project['priority_start']); + $this->assertEquals(5, $project['priority_end']); + + $this->assertEquals( + array(2 => 2, 3 => 3, 4 => 4, 5 => 5), + $projectTaskPriorityModel->getPriorities($project) + ); + + $this->assertEquals(4, $projectTaskPriorityModel->getDefaultPriority(1)); + } + + public function testGetPrioritySettings() + { + $projectModel = new ProjectModel($this->container); + $projectTaskPriorityModel = new ProjectTaskPriorityModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'My project 2'))); + + $expected = array( + 'priority_default' => 0, + 'priority_start' => 0, + 'priority_end' => 3, + ); + + $this->assertEquals($expected, $projectTaskPriorityModel->getPrioritySettings(1)); + $this->assertNull($projectTaskPriorityModel->getPrioritySettings(2)); + } + + public function testGetPriorityForProject() + { + $projectModel = new ProjectModel($this->container); + $projectTaskPriorityModel = new ProjectTaskPriorityModel($this->container); + + $this->assertEquals(1, $projectModel->create(array( + 'name' => 'My project 1', + 'priority_default' => 2, + 'priority_start' => -2, + 'priority_end' => 8, + ))); + + $this->assertEquals(2, $projectTaskPriorityModel->getPriorityForProject(1, 42)); + $this->assertEquals(0, $projectTaskPriorityModel->getPriorityForProject(1, 0)); + $this->assertEquals(1, $projectTaskPriorityModel->getPriorityForProject(1, 1)); + $this->assertEquals(-2, $projectTaskPriorityModel->getPriorityForProject(1, -2)); + $this->assertEquals(-1, $projectTaskPriorityModel->getPriorityForProject(1, -1)); + $this->assertEquals(8, $projectTaskPriorityModel->getPriorityForProject(1, 8)); + $this->assertEquals(5, $projectTaskPriorityModel->getPriorityForProject(1, 5)); + $this->assertEquals(2, $projectTaskPriorityModel->getPriorityForProject(1, 9)); + $this->assertEquals(2, $projectTaskPriorityModel->getPriorityForProject(1, -3)); + } +} diff --git a/tests/units/Model/ProjectTest.php b/tests/units/Model/ProjectTest.php deleted file mode 100644 index 472d7351..00000000 --- a/tests/units/Model/ProjectTest.php +++ /dev/null @@ -1,336 +0,0 @@ -container); - - foreach ($this->container['languageModel']->getLanguages() as $locale => $language) { - Translator::unload(); - Translator::load($locale); - $this->assertNotFalse($p->create(array('name' => 'UnitTest '.$locale)), 'Unable to create project with '.$locale.':'.$language); - } - - Translator::unload(); - } - - public function testCreation() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(1, $project['is_active']); - $this->assertEquals(0, $project['is_public']); - $this->assertEquals(0, $project['is_private']); - $this->assertEquals(time(), $project['last_modified'], '', 1); - $this->assertEmpty($project['token']); - } - - public function testCreationWithDuplicateName() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertEquals(2, $p->create(array('name' => 'UnitTest'))); - } - - public function testCreationWithStartAndDate() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest', 'start_date' => '2015-01-01', 'end_date' => '2015-12-31'))); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals('2015-01-01', $project['start_date']); - $this->assertEquals('2015-12-31', $project['end_date']); - } - - public function testCreationWithDefaultCategories() - { - $p = new ProjectModel($this->container); - $c = new ConfigModel($this->container); - $cat = new CategoryModel($this->container); - - // Multiple categories correctly formatted - - $this->assertTrue($c->save(array('project_categories' => 'Test1, Test2'))); - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - - $categories = $cat->getAll(1); - $this->assertNotEmpty($categories); - $this->assertEquals(2, count($categories)); - $this->assertEquals('Test1', $categories[0]['name']); - $this->assertEquals('Test2', $categories[1]['name']); - - // Single category - - $this->assertTrue($c->save(array('project_categories' => 'Test1'))); - $this->container['memoryCache']->flush(); - $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); - - $project = $p->getById(2); - $this->assertNotEmpty($project); - - $categories = $cat->getAll(2); - $this->assertNotEmpty($categories); - $this->assertEquals(1, count($categories)); - $this->assertEquals('Test1', $categories[0]['name']); - - // Multiple categories badly formatted - - $this->assertTrue($c->save(array('project_categories' => 'ABC, , DEF 3, '))); - $this->container['memoryCache']->flush(); - $this->assertEquals(3, $p->create(array('name' => 'UnitTest3'))); - - $project = $p->getById(3); - $this->assertNotEmpty($project); - - $categories = $cat->getAll(3); - $this->assertNotEmpty($categories); - $this->assertEquals(2, count($categories)); - $this->assertEquals('ABC', $categories[0]['name']); - $this->assertEquals('DEF 3', $categories[1]['name']); - - // No default categories - $this->assertTrue($c->save(array('project_categories' => ' '))); - $this->container['memoryCache']->flush(); - $this->assertEquals(4, $p->create(array('name' => 'UnitTest4'))); - - $project = $p->getById(4); - $this->assertNotEmpty($project); - - $categories = $cat->getAll(4); - $this->assertEmpty($categories); - } - - public function testUpdateLastModifiedDate() - { - $p = new ProjectModel($this->container); - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - - $now = time(); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals($now, $project['last_modified'], 'Wrong Timestamp', 1); - - sleep(1); - $this->assertTrue($p->updateModificationDate(1)); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertGreaterThan($now, $project['last_modified']); - } - - public function testGetAllIds() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - - $this->assertEmpty($p->getAllByIds(array())); - $this->assertNotEmpty($p->getAllByIds(array(1, 2))); - $this->assertCount(1, $p->getAllByIds(array(1))); - } - - public function testIsLastModified() - { - $p = new ProjectModel($this->container); - $tc = new TaskCreationModel($this->container); - - $now = time(); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals($now, $project['last_modified']); - - sleep(1); - - $listener = new ProjectModificationDateSubscriber($this->container); - $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, array($listener, 'execute')); - - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1))); - - $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.Kanboard\Subscriber\ProjectModificationDateSubscriber::execute', $called); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertTrue($p->isModifiedSince(1, $now)); - } - - public function testRemove() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertTrue($p->remove(1)); - $this->assertFalse($p->remove(1234)); - } - - public function testEnable() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertTrue($p->disable(1)); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(0, $project['is_active']); - - $this->assertFalse($p->disable(1111)); - } - - public function testDisable() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertTrue($p->disable(1)); - $this->assertTrue($p->enable(1)); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(1, $project['is_active']); - - $this->assertFalse($p->enable(1234567)); - } - - public function testEnablePublicAccess() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertTrue($p->enablePublicAccess(1)); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(1, $project['is_public']); - $this->assertNotEmpty($project['token']); - - $this->assertFalse($p->enablePublicAccess(123)); - } - - public function testDisablePublicAccess() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertTrue($p->enablePublicAccess(1)); - $this->assertTrue($p->disablePublicAccess(1)); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(0, $project['is_public']); - $this->assertEmpty($project['token']); - - $this->assertFalse($p->disablePublicAccess(123)); - } - - public function testIdentifier() - { - $p = new ProjectModel($this->container); - - // Creation - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1', 'identifier' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals('TEST1', $project['identifier']); - - $project = $p->getById(2); - $this->assertNotEmpty($project); - $this->assertEquals('', $project['identifier']); - - // Update - $this->assertTrue($p->update(array('id' => '2', 'identifier' => 'test2'))); - - $project = $p->getById(2); - $this->assertNotEmpty($project); - $this->assertEquals('TEST2', $project['identifier']); - - $project = $p->getByIdentifier('test1'); - $this->assertNotEmpty($project); - $this->assertEquals('TEST1', $project['identifier']); - - $project = $p->getByIdentifier(''); - $this->assertFalse($project); - } - - public function testThatProjectCreatorAreAlsoOwner() - { - $projectModel = new ProjectModel($this->container); - $userModel = new UserModel($this->container); - - $this->assertEquals(2, $userModel->create(array('username' => 'user1', 'name' => 'Me'))); - $this->assertEquals(1, $projectModel->create(array('name' => 'My project 1'), 2)); - $this->assertEquals(2, $projectModel->create(array('name' => 'My project 2'))); - - $project = $projectModel->getByIdWithOwner(1); - $this->assertNotEmpty($project); - $this->assertSame('My project 1', $project['name']); - $this->assertSame('Me', $project['owner_name']); - $this->assertSame('user1', $project['owner_username']); - $this->assertEquals(2, $project['owner_id']); - - $project = $projectModel->getByIdWithOwner(2); - $this->assertNotEmpty($project); - $this->assertSame('My project 2', $project['name']); - $this->assertEquals('', $project['owner_name']); - $this->assertEquals('', $project['owner_username']); - $this->assertEquals(0, $project['owner_id']); - } - - public function testPriority() - { - $projectModel = new ProjectModel($this->container); - $this->assertEquals(1, $projectModel->create(array('name' => 'My project 2'))); - - $project = $projectModel->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(0, $project['priority_default']); - $this->assertEquals(0, $project['priority_start']); - $this->assertEquals(3, $project['priority_end']); - - $this->assertEquals( - array(0 => 0, 1 => 1, 2 => 2, 3 => 3), - $projectModel->getPriorities($project) - ); - - $this->assertTrue($projectModel->update(array('id' => 1, 'priority_start' => 2, 'priority_end' => 5, 'priority_default' => 4))); - - $project = $projectModel->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(4, $project['priority_default']); - $this->assertEquals(2, $project['priority_start']); - $this->assertEquals(5, $project['priority_end']); - - $this->assertEquals( - array(2 => 2, 3 => 3, 4 => 4, 5 => 5), - $projectModel->getPriorities($project) - ); - } -} -- cgit v1.2.3 From 51b2193fc43a25f309a8510b64027d40bf21e12d Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 24 Jul 2016 12:09:41 -0400 Subject: Move dashboard pagination into separate classes --- app/Controller/DashboardController.php | 72 ++------------------ app/Controller/UserListController.php | 7 +- app/Core/Base.php | 4 ++ app/Model/ProjectDuplicationModel.php | 2 +- app/Model/ProjectModel.php | 2 +- app/Model/TaskFinderModel.php | 86 ++++++++++++------------ app/Pagination/ProjectPagination.php | 35 ++++++++++ app/Pagination/SubtaskPagination.php | 36 ++++++++++ app/Pagination/TaskPagination.php | 35 ++++++++++ app/Pagination/UserPagination.php | 32 +++++++++ app/ServiceProvider/ClassProvider.php | 6 ++ app/Template/dashboard/projects.php | 4 +- app/Template/dashboard/subtasks.php | 4 +- app/Template/dashboard/tasks.php | 8 +-- tests/units/Model/TaskFinderModelTest.php | 2 +- tests/units/Pagination/ProjectPaginationTest.php | 35 ++++++++++ tests/units/Pagination/SubtaskPaginationTest.php | 36 ++++++++++ tests/units/Pagination/TaskPaginationTest.php | 30 +++++++++ tests/units/Pagination/UserPaginationTest.php | 27 ++++++++ 19 files changed, 337 insertions(+), 126 deletions(-) create mode 100644 app/Pagination/ProjectPagination.php create mode 100644 app/Pagination/SubtaskPagination.php create mode 100644 app/Pagination/TaskPagination.php create mode 100644 app/Pagination/UserPagination.php create mode 100644 tests/units/Pagination/ProjectPaginationTest.php create mode 100644 tests/units/Pagination/SubtaskPaginationTest.php create mode 100644 tests/units/Pagination/TaskPaginationTest.php create mode 100644 tests/units/Pagination/UserPaginationTest.php (limited to 'app/Model/ProjectDuplicationModel.php') diff --git a/app/Controller/DashboardController.php b/app/Controller/DashboardController.php index 44874546..0133499f 100644 --- a/app/Controller/DashboardController.php +++ b/app/Controller/DashboardController.php @@ -2,9 +2,6 @@ namespace Kanboard\Controller; -use Kanboard\Model\ProjectModel; -use Kanboard\Model\SubtaskModel; - /** * Dashboard Controller * @@ -13,63 +10,6 @@ use Kanboard\Model\SubtaskModel; */ class DashboardController extends BaseController { - /** - * Get project pagination - * - * @access private - * @param integer $user_id - * @param string $action - * @param integer $max - * @return \Kanboard\Core\Paginator - */ - private function getProjectPaginator($user_id, $action, $max) - { - return $this->paginator - ->setUrl('DashboardController', $action, array('pagination' => 'projects', 'user_id' => $user_id)) - ->setMax($max) - ->setOrder(ProjectModel::TABLE.'.name') - ->setQuery($this->projectModel->getQueryColumnStats($this->projectPermissionModel->getActiveProjectIds($user_id))) - ->calculateOnlyIf($this->request->getStringParam('pagination') === 'projects'); - } - - /** - * Get task pagination - * - * @access private - * @param integer $user_id - * @param string $action - * @param integer $max - * @return \Kanboard\Core\Paginator - */ - private function getTaskPaginator($user_id, $action, $max) - { - return $this->paginator - ->setUrl('DashboardController', $action, array('pagination' => 'tasks', 'user_id' => $user_id)) - ->setMax($max) - ->setOrder('tasks.id') - ->setQuery($this->taskFinderModel->getUserQuery($user_id)) - ->calculateOnlyIf($this->request->getStringParam('pagination') === 'tasks'); - } - - /** - * Get subtask pagination - * - * @access private - * @param integer $user_id - * @param string $action - * @param integer $max - * @return \Kanboard\Core\Paginator - */ - private function getSubtaskPaginator($user_id, $action, $max) - { - return $this->paginator - ->setUrl('DashboardController', $action, array('pagination' => 'subtasks', 'user_id' => $user_id)) - ->setMax($max) - ->setOrder('tasks.id') - ->setQuery($this->subtaskModel->getUserQuery($user_id, array(SubTaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS))) - ->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks'); - } - /** * Dashboard overview * @@ -81,9 +21,9 @@ class DashboardController extends BaseController $this->response->html($this->helper->layout->dashboard('dashboard/show', array( 'title' => t('Dashboard'), - 'project_paginator' => $this->getProjectPaginator($user['id'], 'show', 10), - 'task_paginator' => $this->getTaskPaginator($user['id'], 'show', 10), - 'subtask_paginator' => $this->getSubtaskPaginator($user['id'], 'show', 10), + 'project_paginator' => $this->projectPagination->getDashboardPaginator($user['id'], 'show', 10), + 'task_paginator' => $this->taskPagination->getDashboardPaginator($user['id'], 'show', 10), + 'subtask_paginator' => $this->subtaskPagination->getDashboardPaginator($user['id'], 'show', 10), 'user' => $user, ))); } @@ -99,7 +39,7 @@ class DashboardController extends BaseController $this->response->html($this->helper->layout->dashboard('dashboard/tasks', array( 'title' => t('My tasks'), - 'paginator' => $this->getTaskPaginator($user['id'], 'tasks', 50), + 'paginator' => $this->taskPagination->getDashboardPaginator($user['id'], 'tasks', 50), 'user' => $user, ))); } @@ -115,7 +55,7 @@ class DashboardController extends BaseController $this->response->html($this->helper->layout->dashboard('dashboard/subtasks', array( 'title' => t('My subtasks'), - 'paginator' => $this->getSubtaskPaginator($user['id'], 'subtasks', 50), + 'paginator' => $this->subtaskPagination->getDashboardPaginator($user['id'], 'subtasks', 50), 'user' => $user, ))); } @@ -131,7 +71,7 @@ class DashboardController extends BaseController $this->response->html($this->helper->layout->dashboard('dashboard/projects', array( 'title' => t('My projects'), - 'paginator' => $this->getProjectPaginator($user['id'], 'projects', 25), + 'paginator' => $this->projectPagination->getDashboardPaginator($user['id'], 'projects', 25), 'user' => $user, ))); } diff --git a/app/Controller/UserListController.php b/app/Controller/UserListController.php index 31fcdd44..888583fa 100644 --- a/app/Controller/UserListController.php +++ b/app/Controller/UserListController.php @@ -17,12 +17,7 @@ class UserListController extends BaseController */ public function show() { - $paginator = $this->paginator - ->setUrl('UserListController', 'show') - ->setMax(30) - ->setOrder('username') - ->setQuery($this->userModel->getQuery()) - ->calculate(); + $paginator = $this->userPagination->getListingPaginator(); $this->response->html($this->helper->layout->app('user_list/show', array( 'title' => t('Users').' ('.$paginator->getTotal().')', diff --git a/app/Core/Base.php b/app/Core/Base.php index 563013bd..68604785 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -122,6 +122,10 @@ use Pimple\Container; * @property \Kanboard\Model\UserNotificationFilterModel $userNotificationFilterModel * @property \Kanboard\Model\UserUnreadNotificationModel $userUnreadNotificationModel * @property \Kanboard\Model\UserMetadataModel $userMetadataModel + * @property \Kanboard\Pagination\TaskPagination $taskPagination + * @property \Kanboard\Pagination\SubtaskPagination $subtaskPagination + * @property \Kanboard\Pagination\ProjectPagination $projectPagination + * @property \Kanboard\Pagination\UserPagination $userPagination * @property \Kanboard\Validator\ActionValidator $actionValidator * @property \Kanboard\Validator\AuthValidator $authValidator * @property \Kanboard\Validator\ColumnValidator $columnValidator diff --git a/app/Model/ProjectDuplicationModel.php b/app/Model/ProjectDuplicationModel.php index 94b83c80..d32fa367 100644 --- a/app/Model/ProjectDuplicationModel.php +++ b/app/Model/ProjectDuplicationModel.php @@ -159,7 +159,7 @@ class ProjectDuplicationModel extends Base } /** - * Make sure that the creator of the duplicated project is alsp owner + * Make sure that the creator of the duplicated project is also owner * * @access private * @param integer $dst_project_id diff --git a/app/Model/ProjectModel.php b/app/Model/ProjectModel.php index 850531c9..d2019b72 100644 --- a/app/Model/ProjectModel.php +++ b/app/Model/ProjectModel.php @@ -318,7 +318,7 @@ class ProjectModel extends Base public function getQueryColumnStats(array $project_ids) { if (empty($project_ids)) { - return $this->db->table(ProjectModel::TABLE)->limit(0); + return $this->db->table(ProjectModel::TABLE)->eq(ProjectModel::TABLE.'.id', 0); } return $this->db diff --git a/app/Model/TaskFinderModel.php b/app/Model/TaskFinderModel.php index 7268052c..924f339b 100644 --- a/app/Model/TaskFinderModel.php +++ b/app/Model/TaskFinderModel.php @@ -63,19 +63,19 @@ class TaskFinderModel extends Base return $this->db ->table(TaskModel::TABLE) ->columns( - 'tasks.id', - 'tasks.title', - 'tasks.date_due', - 'tasks.date_creation', - 'tasks.project_id', - 'tasks.color_id', - 'tasks.priority', - 'tasks.time_spent', - 'tasks.time_estimated', - 'tasks.is_active', - 'tasks.creator_id', - 'projects.name AS project_name', - 'columns.title AS column_title' + TaskModel::TABLE.'.id', + TaskModel::TABLE.'.title', + TaskModel::TABLE.'.date_due', + TaskModel::TABLE.'.date_creation', + TaskModel::TABLE.'.project_id', + TaskModel::TABLE.'.color_id', + TaskModel::TABLE.'.priority', + TaskModel::TABLE.'.time_spent', + TaskModel::TABLE.'.time_estimated', + TaskModel::TABLE.'.is_active', + TaskModel::TABLE.'.creator_id', + ProjectModel::TABLE.'.name AS project_name', + ColumnModel::TABLE.'.title AS column_title' ) ->join(ProjectModel::TABLE, 'id', 'project_id') ->join(ColumnModel::TABLE, 'id', 'column_id') @@ -103,36 +103,36 @@ class TaskFinderModel extends Base '(SELECT COUNT(*) FROM '.TaskLinkModel::TABLE.' WHERE '.TaskLinkModel::TABLE.'.task_id = tasks.id) AS nb_links', '(SELECT COUNT(*) FROM '.TaskExternalLinkModel::TABLE.' WHERE '.TaskExternalLinkModel::TABLE.'.task_id = tasks.id) AS nb_external_links', '(SELECT DISTINCT 1 FROM '.TaskLinkModel::TABLE.' WHERE '.TaskLinkModel::TABLE.'.task_id = tasks.id AND '.TaskLinkModel::TABLE.'.link_id = 9) AS is_milestone', - 'tasks.id', - 'tasks.reference', - 'tasks.title', - 'tasks.description', - 'tasks.date_creation', - 'tasks.date_modification', - 'tasks.date_completed', - 'tasks.date_started', - 'tasks.date_due', - 'tasks.color_id', - 'tasks.project_id', - 'tasks.column_id', - 'tasks.swimlane_id', - 'tasks.owner_id', - 'tasks.creator_id', - 'tasks.position', - 'tasks.is_active', - 'tasks.score', - 'tasks.category_id', - 'tasks.priority', - 'tasks.date_moved', - 'tasks.recurrence_status', - 'tasks.recurrence_trigger', - 'tasks.recurrence_factor', - 'tasks.recurrence_timeframe', - 'tasks.recurrence_basedate', - 'tasks.recurrence_parent', - 'tasks.recurrence_child', - 'tasks.time_estimated', - 'tasks.time_spent', + TaskModel::TABLE.'.id', + TaskModel::TABLE.'.reference', + TaskModel::TABLE.'.title', + TaskModel::TABLE.'.description', + TaskModel::TABLE.'.date_creation', + TaskModel::TABLE.'.date_modification', + TaskModel::TABLE.'.date_completed', + TaskModel::TABLE.'.date_started', + TaskModel::TABLE.'.date_due', + TaskModel::TABLE.'.color_id', + TaskModel::TABLE.'.project_id', + TaskModel::TABLE.'.column_id', + TaskModel::TABLE.'.swimlane_id', + TaskModel::TABLE.'.owner_id', + TaskModel::TABLE.'.creator_id', + TaskModel::TABLE.'.position', + TaskModel::TABLE.'.is_active', + TaskModel::TABLE.'.score', + TaskModel::TABLE.'.category_id', + TaskModel::TABLE.'.priority', + TaskModel::TABLE.'.date_moved', + TaskModel::TABLE.'.recurrence_status', + TaskModel::TABLE.'.recurrence_trigger', + TaskModel::TABLE.'.recurrence_factor', + TaskModel::TABLE.'.recurrence_timeframe', + TaskModel::TABLE.'.recurrence_basedate', + TaskModel::TABLE.'.recurrence_parent', + TaskModel::TABLE.'.recurrence_child', + TaskModel::TABLE.'.time_estimated', + TaskModel::TABLE.'.time_spent', UserModel::TABLE.'.username AS assignee_username', UserModel::TABLE.'.name AS assignee_name', UserModel::TABLE.'.email AS assignee_email', diff --git a/app/Pagination/ProjectPagination.php b/app/Pagination/ProjectPagination.php new file mode 100644 index 00000000..8f1fa87c --- /dev/null +++ b/app/Pagination/ProjectPagination.php @@ -0,0 +1,35 @@ +paginator + ->setUrl('DashboardController', $method, array('pagination' => 'projects', 'user_id' => $user_id)) + ->setMax($max) + ->setOrder(ProjectModel::TABLE.'.name') + ->setQuery($this->projectModel->getQueryColumnStats($this->projectPermissionModel->getActiveProjectIds($user_id))) + ->calculateOnlyIf($this->request->getStringParam('pagination') === 'projects'); + } +} diff --git a/app/Pagination/SubtaskPagination.php b/app/Pagination/SubtaskPagination.php new file mode 100644 index 00000000..f0cd6148 --- /dev/null +++ b/app/Pagination/SubtaskPagination.php @@ -0,0 +1,36 @@ +paginator + ->setUrl('DashboardController', $method, array('pagination' => 'subtasks', 'user_id' => $user_id)) + ->setMax($max) + ->setOrder(TaskModel::TABLE.'.id') + ->setQuery($this->subtaskModel->getUserQuery($user_id, array(SubtaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS))) + ->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks'); + } +} diff --git a/app/Pagination/TaskPagination.php b/app/Pagination/TaskPagination.php new file mode 100644 index 00000000..a395ab84 --- /dev/null +++ b/app/Pagination/TaskPagination.php @@ -0,0 +1,35 @@ +paginator + ->setUrl('DashboardController', $method, array('pagination' => 'tasks', 'user_id' => $user_id)) + ->setMax($max) + ->setOrder(TaskModel::TABLE.'.id') + ->setQuery($this->taskFinderModel->getUserQuery($user_id)) + ->calculateOnlyIf($this->request->getStringParam('pagination') === 'tasks'); + } +} diff --git a/app/Pagination/UserPagination.php b/app/Pagination/UserPagination.php new file mode 100644 index 00000000..430b7d2f --- /dev/null +++ b/app/Pagination/UserPagination.php @@ -0,0 +1,32 @@ +paginator + ->setUrl('UserListController', 'show') + ->setMax(30) + ->setOrder(UserModel::TABLE.'.username') + ->setQuery($this->userModel->getQuery()) + ->calculate(); + } +} diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 9a71148b..aab41c74 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -122,6 +122,12 @@ class ClassProvider implements ServiceProviderInterface 'TaskExport', 'TransitionExport', ), + 'Pagination' => array( + 'TaskPagination', + 'SubtaskPagination', + 'ProjectPagination', + 'UserPagination', + ), 'Core' => array( 'DateParser', 'Lexer', diff --git a/app/Template/dashboard/projects.php b/app/Template/dashboard/projects.php index 962e4d83..3a7f1d86 100644 --- a/app/Template/dashboard/projects.php +++ b/app/Template/dashboard/projects.php @@ -6,8 +6,8 @@ - - + + diff --git a/app/Template/dashboard/subtasks.php b/app/Template/dashboard/subtasks.php index 8e0aa3ce..ca550e4c 100644 --- a/app/Template/dashboard/subtasks.php +++ b/app/Template/dashboard/subtasks.php @@ -6,10 +6,10 @@
order('Id', 'id') ?>order('', 'is_private') ?>order('Id', \Kanboard\Model\ProjectModel::TABLE.'.id') ?>order('', \Kanboard\Model\ProjectModel::TABLE.'.is_private') ?> order(t('Project'), \Kanboard\Model\ProjectModel::TABLE.'.name') ?>
- + - + getCollection() as $subtask): ?> diff --git a/app/Template/dashboard/tasks.php b/app/Template/dashboard/tasks.php index b3257c33..d9cb4f9e 100644 --- a/app/Template/dashboard/tasks.php +++ b/app/Template/dashboard/tasks.php @@ -6,12 +6,12 @@
order('Id', 'tasks.id') ?>order('Id', \Kanboard\Model\TaskModel::TABLE.'.id') ?> order(t('Project'), 'project_name') ?> order(t('Task'), 'task_name') ?>order(t('Subtask'), 'title') ?>order(t('Subtask'), \Kanboard\Model\SubtaskModel::TABLE.'.title') ?>
- + - - + + - + getCollection() as $task): ?> diff --git a/tests/units/Model/TaskFinderModelTest.php b/tests/units/Model/TaskFinderModelTest.php index 72da3b6d..b2e2bd84 100644 --- a/tests/units/Model/TaskFinderModelTest.php +++ b/tests/units/Model/TaskFinderModelTest.php @@ -9,7 +9,7 @@ use Kanboard\Model\ProjectModel; class TaskFinderModelTest extends Base { - public function testGetTasksForDashboard() + public function testGetTasksForDashboardWithHiddenColumn() { $taskCreationModel = new TaskCreationModel($this->container); $taskFinderModel = new TaskFinderModel($this->container); diff --git a/tests/units/Pagination/ProjectPaginationTest.php b/tests/units/Pagination/ProjectPaginationTest.php new file mode 100644 index 00000000..35532d0d --- /dev/null +++ b/tests/units/Pagination/ProjectPaginationTest.php @@ -0,0 +1,35 @@ +container); + $projectUserRoleModel = new ProjectUserRoleModel($this->container); + $userModel = new UserModel($this->container); + $projectPagination = new ProjectPagination($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project #2', 'is_private' => 1))); + $this->assertEquals(3, $projectModel->create(array('name' => 'Project #3'))); + $this->assertEquals(4, $projectModel->create(array('name' => 'Project #4', 'is_private' => 1))); + + $this->assertEquals(2, $userModel->create(array('username' => 'test'))); + $this->assertTrue($projectUserRoleModel->addUser(1, 2, Role::PROJECT_MANAGER)); + $this->assertTrue($projectUserRoleModel->addUser(2, 2, Role::PROJECT_MANAGER)); + + $this->assertCount(2, $projectPagination->getDashboardPaginator(2, 'projects', 5)->getCollection()); + $this->assertCount(0, $projectPagination->getDashboardPaginator(3, 'projects', 5)->getCollection()); + $this->assertCount(2, $projectPagination->getDashboardPaginator(2, 'projects', 5)->setOrder(ProjectModel::TABLE.'.id')->getCollection()); + $this->assertCount(2, $projectPagination->getDashboardPaginator(2, 'projects', 5)->setOrder(ProjectModel::TABLE.'.is_private')->getCollection()); + $this->assertCount(2, $projectPagination->getDashboardPaginator(2, 'projects', 5)->setOrder(ProjectModel::TABLE.'.name')->getCollection()); + } +} diff --git a/tests/units/Pagination/SubtaskPaginationTest.php b/tests/units/Pagination/SubtaskPaginationTest.php new file mode 100644 index 00000000..26a51a8b --- /dev/null +++ b/tests/units/Pagination/SubtaskPaginationTest.php @@ -0,0 +1,36 @@ +container); + $projectModel = new ProjectModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskPagination = new SubtaskPagination($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('task_id' => 1, 'title' => 'subtask #1', 'user_id' => 1))); + $this->assertEquals(2, $subtaskModel->create(array('task_id' => 2, 'title' => 'subtask #1', 'user_id' => 1))); + $this->assertEquals(3, $subtaskModel->create(array('task_id' => 1, 'title' => 'subtask #1', 'user_id' => 1))); + $this->assertEquals(4, $subtaskModel->create(array('task_id' => 2, 'title' => 'subtask #1'))); + $this->assertEquals(5, $subtaskModel->create(array('task_id' => 1, 'title' => 'subtask #1'))); + + $this->assertCount(3, $subtaskPagination->getDashboardPaginator(1, 'subtasks', 5)->getCollection()); + $this->assertCount(0, $subtaskPagination->getDashboardPaginator(2, 'subtasks', 5)->getCollection()); + $this->assertCount(3, $subtaskPagination->getDashboardPaginator(1, 'subtasks', 5)->setOrder(TaskModel::TABLE.'.id')->getCollection()); + $this->assertCount(3, $subtaskPagination->getDashboardPaginator(1, 'subtasks', 5)->setOrder('project_name')->getCollection()); + $this->assertCount(3, $subtaskPagination->getDashboardPaginator(1, 'subtasks', 5)->setOrder('task_name')->getCollection()); + $this->assertCount(3, $subtaskPagination->getDashboardPaginator(1, 'subtasks', 5)->setOrder(SubtaskModel::TABLE.'.title')->getCollection()); + } +} diff --git a/tests/units/Pagination/TaskPaginationTest.php b/tests/units/Pagination/TaskPaginationTest.php new file mode 100644 index 00000000..027212e2 --- /dev/null +++ b/tests/units/Pagination/TaskPaginationTest.php @@ -0,0 +1,30 @@ +container); + $projectModel = new ProjectModel($this->container); + $taskPagination = new TaskPagination($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 1))); + + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->getCollection()); + $this->assertCount(0, $taskPagination->getDashboardPaginator(2, 'tasks', 5)->getCollection()); + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->setOrder(TaskModel::TABLE.'.id')->getCollection()); + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->setOrder('project_name')->getCollection()); + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->setOrder(TaskModel::TABLE.'.title')->getCollection()); + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->setOrder(TaskModel::TABLE.'.priority')->getCollection()); + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->setOrder(TaskModel::TABLE.'.date_due')->getCollection()); + } +} diff --git a/tests/units/Pagination/UserPaginationTest.php b/tests/units/Pagination/UserPaginationTest.php new file mode 100644 index 00000000..c475aacd --- /dev/null +++ b/tests/units/Pagination/UserPaginationTest.php @@ -0,0 +1,27 @@ +container); + $userPagination = new UserPagination($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'test1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'test2'))); + + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('id')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('username')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('name')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('email')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('role')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('twofactor_activated')->setDirection('DESC')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('is_ldap_user')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('is_active')->getCollection()); + } +} -- cgit v1.2.3
order('Id', 'tasks.id') ?>order('Id', \Kanboard\Model\TaskModel::TABLE.'.id') ?> order(t('Project'), 'project_name') ?>order(t('Task'), 'title') ?>order(t('Priority'), 'tasks.priority') ?>order(t('Task'), \Kanboard\Model\TaskModel::TABLE.'.title') ?>order(t('Priority'), \Kanboard\Model\TaskModel::TABLE.'.priority') ?> order(t('Due date'), 'date_due') ?>order(t('Due date'), \Kanboard\Model\TaskModel::TABLE.'.date_due') ?> order(t('Column'), 'column_title') ?>