diff options
-rw-r--r-- | app/Controller/Projectinfo.php | 8 | ||||
-rw-r--r-- | app/Core/Lexer.php | 2 | ||||
-rw-r--r-- | app/Model/TaskFilter.php | 27 | ||||
-rw-r--r-- | app/Model/TaskFinder.php | 15 | ||||
-rw-r--r-- | docs/search.markdown | 9 | ||||
-rw-r--r-- | tests/units/LexerTest.php | 25 | ||||
-rw-r--r-- | tests/units/TaskFilterTest.php | 45 |
7 files changed, 110 insertions, 21 deletions
diff --git a/app/Controller/Projectinfo.php b/app/Controller/Projectinfo.php index c30c1652..22b9861c 100644 --- a/app/Controller/Projectinfo.php +++ b/app/Controller/Projectinfo.php @@ -45,12 +45,8 @@ class Projectinfo extends Base ->setDirection('DESC'); if ($search !== '') { - - // $paginator - // ->setQuery($this->taskFinder->getSearchQuery($project['id'], $search)) - // ->calculate(); - - $paginator->setQuery($this->taskFilter->search($search)->filterByProject($project['id'])->getQuery())->calculate(); + $paginator->setQuery($this->taskFilter->search($search)->filterByProject($project['id'])->getQuery()) + ->calculate(); $nb_tasks = $paginator->getTotal(); } diff --git a/app/Core/Lexer.php b/app/Core/Lexer.php index ccd29588..ad0631d5 100644 --- a/app/Core/Lexer.php +++ b/app/Core/Lexer.php @@ -30,6 +30,7 @@ class Lexer "/^(due:)/" => 'T_DUE', "/^(status:)/" => 'T_STATUS', "/^(description:)/" => 'T_DESCRIPTION', + "/^(category:)/" => 'T_CATEGORY', "/^(\s+)/" => 'T_WHITESPACE', '/^([<=>]{0,2}[0-9]{4}-[0-9]{2}-[0-9]{2})/' => 'T_DATE', '/^(yesterday|tomorrow|today)/' => 'T_DATE', @@ -107,6 +108,7 @@ class Lexer switch ($token['token']) { case 'T_ASSIGNEE': case 'T_COLOR': + case 'T_CATEGORY': $next = next($tokens); if ($next !== false && $next['token'] === 'T_STRING') { diff --git a/app/Model/TaskFilter.php b/app/Model/TaskFilter.php index bdfbb190..b14dad0a 100644 --- a/app/Model/TaskFilter.php +++ b/app/Model/TaskFilter.php @@ -59,6 +59,9 @@ class TaskFilter extends Base case 'T_DESCRIPTION': $this->filterByDescription($value); break; + case 'T_CATEGORY': + $this->filterByCategoryName($value); + break; } } @@ -203,6 +206,30 @@ class TaskFilter extends Base } /** + * Filter by category + * + * @access public + * @param array $values List of assignees + * @return TaskFilter + */ + public function filterByCategoryName(array $values) + { + $this->query->join(Category::TABLE, 'id', 'category_id'); + $this->query->beginOr(); + + foreach ($values as $category) { + if ($category === 'none') { + $this->query->eq(Task::TABLE.'.category_id', 0); + } + else { + $this->query->eq(Category::TABLE.'.name', $category); + } + } + + $this->query->closeOr(); + } + + /** * Filter by assignee * * @access public diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php index 9c46f4a9..e007187f 100644 --- a/app/Model/TaskFinder.php +++ b/app/Model/TaskFinder.php @@ -27,21 +27,6 @@ class TaskFinder extends Base } /** - * Get query for task search - * - * @access public - * @param integer $project_id Project id - * @param string $search Search terms - * @return \PicoDb\Table - */ - public function getSearchQuery($project_id, $search) - { - return $this->getExtendedQuery() - ->eq('project_id', $project_id) - ->ilike('title', '%'.$search.'%'); - } - - /** * Get query for assigned user tasks * * @access public diff --git a/docs/search.markdown b/docs/search.markdown index bcd889be..8cb839b1 100644 --- a/docs/search.markdown +++ b/docs/search.markdown @@ -118,3 +118,12 @@ Search by description Attribute: **description** Example: `description:"text search"` + +Search by category +------------------ + +Attribute: **category** + +- Find tasks with a specific category: `category:"Feature Request"` +- Find all tasks that have those category: `category:"Bug" category:"Improvements"` +- Find tasks with no category assigned: `category:none` diff --git a/tests/units/LexerTest.php b/tests/units/LexerTest.php index e2b97566..4d0d67ad 100644 --- a/tests/units/LexerTest.php +++ b/tests/units/LexerTest.php @@ -66,6 +66,31 @@ class LexerTest extends Base ); } + public function testCategoryQuery() + { + $lexer = new Lexer; + + $this->assertEquals( + array(array('match' => 'category:', 'token' => 'T_CATEGORY'), array('match' => 'Feature Request', 'token' => 'T_STRING')), + $lexer->tokenize('category:"Feature Request"') + ); + + $this->assertEquals( + array('T_CATEGORY' => array('Feature Request')), + $lexer->map($lexer->tokenize('category:"Feature Request"')) + ); + + $this->assertEquals( + array('T_CATEGORY' => array('Feature Request', 'Bug')), + $lexer->map($lexer->tokenize('category:"Feature Request" category:Bug')) + ); + + $this->assertEquals( + array(), + $lexer->map($lexer->tokenize('category: ')) + ); + } + public function testStatusQuery() { $lexer = new Lexer; diff --git a/tests/units/TaskFilterTest.php b/tests/units/TaskFilterTest.php index 494a0f1b..cec30394 100644 --- a/tests/units/TaskFilterTest.php +++ b/tests/units/TaskFilterTest.php @@ -7,6 +7,7 @@ use Model\User; use Model\TaskFilter; use Model\TaskCreation; use Model\DateParser; +use Model\Category; class TaskFilterTest extends Base { @@ -74,6 +75,50 @@ class TaskFilterTest extends Base $this->assertEmpty($tasks); } + public function testSearchWithCategory() + { + $p = new Project($this->container); + $c = new Category($this->container); + $tc = new TaskCreation($this->container); + $tf = new TaskFilter($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'test'))); + $this->assertEquals(1, $c->create(array('name' => 'Feature request', 'project_id' => 1))); + $this->assertEquals(2, $c->create(array('name' => 'hé hé', 'project_id' => 1))); + $this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'task1'))); + $this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'task2', 'category_id' => 1))); + $this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'task3', 'category_id' => 2))); + + $tf->search('category:"Feature request"'); + $tasks = $tf->findAll(); + $this->assertNotEmpty($tasks); + $this->assertCount(1, $tasks); + $this->assertEquals('task2', $tasks[0]['title']); + + $tf->search('category:"hé hé"'); + $tasks = $tf->findAll(); + $this->assertNotEmpty($tasks); + $this->assertCount(1, $tasks); + $this->assertEquals('task3', $tasks[0]['title']); + + $tf->search('category:"Feature request" category:"hé hé"'); + $tasks = $tf->findAll(); + $this->assertNotEmpty($tasks); + $this->assertCount(2, $tasks); + $this->assertEquals('task2', $tasks[0]['title']); + $this->assertEquals('task3', $tasks[1]['title']); + + $tf->search('category:none'); + $tasks = $tf->findAll(); + $this->assertNotEmpty($tasks); + $this->assertCount(1, $tasks); + $this->assertEquals('task1', $tasks[0]['title']); + + $tf->search('category:"not found"'); + $tasks = $tf->findAll(); + $this->assertEmpty($tasks); + } + public function testSearchWithDueDate() { $dp = new DateParser($this->container); |