From c250f3b1b8b42652cd2f3b3f19ce36624e384ff0 Mon Sep 17 00:00:00 2001 From: Rafael de Camargo Date: Wed, 17 Jul 2019 18:32:16 -0300 Subject: Add option to clone filters on project duplication * Fixed missing metadata option from project "create from" * Added option to clone project custom filters * Added append option to custom field tests * Added a test that uses the "append" option * Fixed disabled swimlane duplication error with Postgresql --- app/Model/CustomFilterModel.php | 35 ++++++++++++++++++ app/Model/ProjectDuplicationModel.php | 2 ++ app/Model/SwimlaneModel.php | 2 +- app/Template/project_creation/create.php | 2 ++ app/Template/project_view/duplicate.php | 1 + tests/units/Model/CustomFilterTest.php | 12 +++++++ tests/units/Model/ProjectDuplicationModelTest.php | 44 +++++++++++++++++++++-- 7 files changed, 95 insertions(+), 3 deletions(-) diff --git a/app/Model/CustomFilterModel.php b/app/Model/CustomFilterModel.php index a4c23b5c..7eb02a01 100644 --- a/app/Model/CustomFilterModel.php +++ b/app/Model/CustomFilterModel.php @@ -101,4 +101,39 @@ class CustomFilterModel extends Base { return $this->db->table(self::TABLE)->eq('id', $filter_id)->remove(); } + + /** + * Duplicate custom filters from a project to another one, must be executed inside a transaction + * + * @param integer $src_project_id Source project id + * @param integer $dst_project_id Destination project id + * @return boolean + */ + public function duplicate($src_project_id, $dst_project_id) + { + $filters = $this->db + ->table(self::TABLE) + ->columns( + self::TABLE.'.user_id', + self::TABLE.'.filter', + self::TABLE.'.name', + self::TABLE.'.is_shared', + self::TABLE.'.append' + ) + ->eq('project_id', $src_project_id) + ->findAll(); + + foreach ($filters as $filter) { + $filter['project_id'] = $dst_project_id; + // Avoid SQL error with Postgres + $filter['is_shared'] = $filter['is_shared'] ?: 0; + $filter['append'] = $filter['append'] ?: 0; + + if (! $this->db->table(self::TABLE)->save($filter)) { + return false; + } + } + + return true; + } } diff --git a/app/Model/ProjectDuplicationModel.php b/app/Model/ProjectDuplicationModel.php index a8f57709..90a9f03d 100644 --- a/app/Model/ProjectDuplicationModel.php +++ b/app/Model/ProjectDuplicationModel.php @@ -28,6 +28,7 @@ class ProjectDuplicationModel extends Base 'projectPermissionModel', 'actionModel', 'tagDuplicationModel', + 'customFilterModel', 'projectMetadataModel', 'projectTaskDuplicationModel', ); @@ -50,6 +51,7 @@ class ProjectDuplicationModel extends Base 'actionModel', 'swimlaneModel', 'tagDuplicationModel', + 'customFilterModel', 'projectMetadataModel', 'projectTaskDuplicationModel', ); diff --git a/app/Model/SwimlaneModel.php b/app/Model/SwimlaneModel.php index 2b3be912..0d204ae2 100644 --- a/app/Model/SwimlaneModel.php +++ b/app/Model/SwimlaneModel.php @@ -443,7 +443,7 @@ class SwimlaneModel extends Base 'name' => $swimlane['name'], 'description' => $swimlane['description'], 'position' => $swimlane['position'], - 'is_active' => $swimlane['is_active'], + 'is_active' => $swimlane['is_active'] ? self::ACTIVE : self::INACTIVE, // Avoid SQL error with Postgres 'project_id' => $projectDstId, ); diff --git a/app/Template/project_creation/create.php b/app/Template/project_creation/create.php index 01952f14..12eb3215 100644 --- a/app/Template/project_creation/create.php +++ b/app/Template/project_creation/create.php @@ -30,6 +30,8 @@ form->checkbox('categoryModel', t('Categories'), 1, true) ?> form->checkbox('tagDuplicationModel', t('Tags'), 1, true) ?> form->checkbox('actionModel', t('Actions'), 1, true) ?> + form->checkbox('customFilterModel', t('Custom filters'), 1, true) ?> + form->checkbox('projectMetadataModel', t('Metadata'), 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 e2f3677c..f0268f6b 100644 --- a/app/Template/project_view/duplicate.php +++ b/app/Template/project_view/duplicate.php @@ -18,6 +18,7 @@ form->checkbox('categoryModel', t('Categories'), 1, true) ?> form->checkbox('tagDuplicationModel', t('Tags'), 1, true) ?> form->checkbox('actionModel', t('Actions'), 1, true) ?> + form->checkbox('customFilterModel', t('Custom filters'), 1, true) ?> form->checkbox('projectMetadataModel', t('Metadata'), 1, false) ?> form->checkbox('projectTaskDuplicationModel', t('Tasks'), 1, false) ?> diff --git a/tests/units/Model/CustomFilterTest.php b/tests/units/Model/CustomFilterTest.php index 463a1c91..f21cdfcd 100644 --- a/tests/units/Model/CustomFilterTest.php +++ b/tests/units/Model/CustomFilterTest.php @@ -16,6 +16,7 @@ class CustomFilterTest extends Base $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); $this->assertEquals(1, $cf->create(array('name' => 'My filter 1', 'filter' => 'status:open color:blue', 'project_id' => 1, 'user_id' => 1))); $this->assertEquals(2, $cf->create(array('name' => 'My filter 2', 'filter' => 'status:open color:red', 'project_id' => 1, 'user_id' => 1, 'is_shared' => 1))); + $this->assertEquals(3, $cf->create(array('name' => 'My filter 3', 'filter' => 'status:open color:green', 'project_id' => 1, 'user_id' => 1, 'append' => 1))); $filter = $cf->getById(1); $this->assertNotEmpty($filter); @@ -24,6 +25,7 @@ class CustomFilterTest extends Base $this->assertEquals(1, $filter['project_id']); $this->assertEquals(1, $filter['user_id']); $this->assertEquals(0, $filter['is_shared']); + $this->assertEquals(0, $filter['append']); $filter = $cf->getById(2); $this->assertNotEmpty($filter); @@ -32,6 +34,16 @@ class CustomFilterTest extends Base $this->assertEquals(1, $filter['project_id']); $this->assertEquals(1, $filter['user_id']); $this->assertEquals(1, $filter['is_shared']); + $this->assertEquals(0, $filter['append']); + + $filter = $cf->getById(3); + $this->assertNotEmpty($filter); + $this->assertEquals('My filter 3', $filter['name']); + $this->assertEquals('status:open color:green', $filter['filter']); + $this->assertEquals(1, $filter['project_id']); + $this->assertEquals(1, $filter['user_id']); + $this->assertEquals(0, $filter['is_shared']); + $this->assertEquals(1, $filter['append']); } public function testModification() diff --git a/tests/units/Model/ProjectDuplicationModelTest.php b/tests/units/Model/ProjectDuplicationModelTest.php index ac93d67c..e704f981 100644 --- a/tests/units/Model/ProjectDuplicationModelTest.php +++ b/tests/units/Model/ProjectDuplicationModelTest.php @@ -17,6 +17,7 @@ use Kanboard\Model\SwimlaneModel; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; +use Kanboard\Model\CustomFilterModel; use Kanboard\Core\Security\Role; class ProjectDuplicationModelTest extends Base @@ -24,8 +25,8 @@ class ProjectDuplicationModelTest extends Base public function testGetSelections() { $projectDuplicationModel = new ProjectDuplicationModel($this->container); - $this->assertCount(7, $projectDuplicationModel->getOptionalSelection()); - $this->assertCount(10, $projectDuplicationModel->getPossibleSelection()); + $this->assertCount(8, $projectDuplicationModel->getOptionalSelection()); + $this->assertCount(11, $projectDuplicationModel->getPossibleSelection()); } public function testGetClonedProjectName() @@ -539,6 +540,9 @@ 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))); + // make the first swimlane inactive (keep positions) + $this->assertTrue($swimlaneModel->disable(1, 1)); + $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('projectPermissionModel', 'swimlaneModel', 'projectTaskDuplicationModel'))); // Check if Swimlanes have been duplicated @@ -546,12 +550,16 @@ class ProjectDuplicationModelTest extends Base $this->assertCount(4, $swimlanes); $this->assertEquals(5, $swimlanes[0]['id']); $this->assertEquals('Default swimlane', $swimlanes[0]['name']); + $this->assertEquals(0, $swimlanes[0]['is_active']); $this->assertEquals(6, $swimlanes[1]['id']); $this->assertEquals('S1', $swimlanes[1]['name']); + $this->assertEquals(1, $swimlanes[1]['is_active']); $this->assertEquals(7, $swimlanes[2]['id']); $this->assertEquals('S2', $swimlanes[2]['name']); + $this->assertEquals(1, $swimlanes[2]['is_active']); $this->assertEquals(8, $swimlanes[3]['id']); $this->assertEquals('S3', $swimlanes[3]['name']); + $this->assertEquals(1, $swimlanes[3]['is_active']); // Check if Tasks have been duplicated $tasks = $taskFinderModel->getAll(2); @@ -603,4 +611,36 @@ class ProjectDuplicationModelTest extends Base $tags = $taskTagModel->getList(6); $this->assertEquals('C', $tags[6]); } + + public function testCloneProjectWithCustomFilters() + { + $projectModel = new ProjectModel($this->container); + $customFilterModel = new CustomFilterModel($this->container); + $projectDuplicationModel = new ProjectDuplicationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + + $this->assertEquals(1, $customFilterModel->create(array('name' => 'My filter 1', 'filter' => 'status:open color:blue', 'project_id' => 1, 'user_id' => 1, 'append' => 1))); + $this->assertEquals(2, $customFilterModel->create(array('name' => 'My filter 2', 'filter' => 'status:open color:red', 'project_id' => 1, 'user_id' => 1, 'is_shared' => 1))); + + $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('customFilterModel'))); + + $filter = $customFilterModel->getById(3); + $this->assertNotEmpty($filter); + $this->assertEquals('My filter 1', $filter['name']); + $this->assertEquals('status:open color:blue', $filter['filter']); + $this->assertEquals(2, $filter['project_id']); + $this->assertEquals(1, $filter['user_id']); + $this->assertEquals(0, $filter['is_shared']); + $this->assertEquals(1, $filter['append']); + + $filter = $customFilterModel->getById(4); + $this->assertNotEmpty($filter); + $this->assertEquals('My filter 2', $filter['name']); + $this->assertEquals('status:open color:red', $filter['filter']); + $this->assertEquals(2, $filter['project_id']); + $this->assertEquals(1, $filter['user_id']); + $this->assertEquals(1, $filter['is_shared']); + $this->assertEquals(0, $filter['append']); + } } -- cgit v1.2.3