summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/Core/Lexer.php3
-rw-r--r--app/Model/TaskFilter.php19
-rw-r--r--docs/search.markdown7
-rw-r--r--tests/units/LexerTest.php30
-rw-r--r--tests/units/TaskFilterTest.php31
5 files changed, 90 insertions, 0 deletions
diff --git a/app/Core/Lexer.php b/app/Core/Lexer.php
index d277f998..f6978bbd 100644
--- a/app/Core/Lexer.php
+++ b/app/Core/Lexer.php
@@ -33,6 +33,8 @@ class Lexer
"/^(category:)/" => 'T_CATEGORY',
"/^(column:)/" => 'T_COLUMN',
"/^(project:)/" => 'T_PROJECT',
+ "/^(ref:)/" => 'T_REFERENCE',
+ "/^(reference:)/" => 'T_REFERENCE',
"/^(\s+)/" => 'T_WHITESPACE',
'/^([<=>]{0,2}[0-9]{4}-[0-9]{2}-[0-9]{2})/' => 'T_DATE',
'/^(yesterday|tomorrow|today)/' => 'T_DATE',
@@ -124,6 +126,7 @@ class Lexer
case 'T_STATUS':
case 'T_DUE':
case 'T_DESCRIPTION':
+ case 'T_REFERENCE':
$next = next($tokens);
if ($next !== false && ($next['token'] === 'T_DATE' || $next['token'] === 'T_STRING')) {
diff --git a/app/Model/TaskFilter.php b/app/Model/TaskFilter.php
index e9d9ccbd..0bac3f46 100644
--- a/app/Model/TaskFilter.php
+++ b/app/Model/TaskFilter.php
@@ -68,6 +68,9 @@ class TaskFilter extends Base
case 'T_COLUMN':
$this->filterByColumnName($value);
break;
+ case 'T_REFERENCE':
+ $this->filterByReference($value);
+ break;
}
}
@@ -141,6 +144,22 @@ class TaskFilter extends Base
}
/**
+ * Filter by reference
+ *
+ * @access public
+ * @param string $reference
+ * @return TaskFilter
+ */
+ public function filterByReference($reference)
+ {
+ if (! empty($reference)) {
+ $this->query->eq(Task::TABLE.'.reference', $reference);
+ }
+
+ return $this;
+ }
+
+ /**
* Filter by title
*
* @access public
diff --git a/docs/search.markdown b/docs/search.markdown
index 1d254b29..99b76393 100644
--- a/docs/search.markdown
+++ b/docs/search.markdown
@@ -144,3 +144,10 @@ Attribute: **column**
- Find tasks by column name: `column:"Work in progress"`
- Find tasks for several columns: `column:"Backlog" column:ready`
+
+Search by external reference
+----------------------------
+
+The task reference is an external id of your task, by example a ticket number from another software.
+
+- Find tasks with a reference: `ref:1234` or `reference:TICKET-1234`
diff --git a/tests/units/LexerTest.php b/tests/units/LexerTest.php
index 38974357..0e3a61ae 100644
--- a/tests/units/LexerTest.php
+++ b/tests/units/LexerTest.php
@@ -171,6 +171,36 @@ class LexerTest extends Base
);
}
+ public function testReferenceQuery()
+ {
+ $lexer = new Lexer;
+
+ $this->assertEquals(
+ array(array('match' => 'ref:', 'token' => 'T_REFERENCE'), array('match' => '123', 'token' => 'T_STRING')),
+ $lexer->tokenize('ref:123')
+ );
+
+ $this->assertEquals(
+ array(array('match' => 'reference:', 'token' => 'T_REFERENCE'), array('match' => '456', 'token' => 'T_STRING')),
+ $lexer->tokenize('reference:456')
+ );
+
+ $this->assertEquals(
+ array('T_REFERENCE' => '123'),
+ $lexer->map($lexer->tokenize('reference:123'))
+ );
+
+ $this->assertEquals(
+ array('T_REFERENCE' => '456'),
+ $lexer->map($lexer->tokenize('ref:456'))
+ );
+
+ $this->assertEquals(
+ array(),
+ $lexer->map($lexer->tokenize('ref: '))
+ );
+ }
+
public function testDescriptionQuery()
{
$lexer = new Lexer;
diff --git a/tests/units/TaskFilterTest.php b/tests/units/TaskFilterTest.php
index c68e8880..6a48f194 100644
--- a/tests/units/TaskFilterTest.php
+++ b/tests/units/TaskFilterTest.php
@@ -27,6 +27,37 @@ class TaskFilterTest extends Base
$this->assertEmpty($tf->search('search something')->findAll());
}
+ public function testSearchWithReference()
+ {
+ $p = new Project($this->container);
+ $tc = new TaskCreation($this->container);
+ $tf = new TaskFilter($this->container);
+
+ $this->assertEquals(1, $p->create(array('name' => 'test')));
+ $this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'task1')));
+ $this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'task2', 'reference' => 123)));
+
+ $tf->search('ref:123');
+ $tasks = $tf->findAll();
+ $this->assertNotEmpty($tasks);
+ $this->assertCount(1, $tasks);
+ $this->assertEquals('task2', $tasks[0]['title']);
+
+ $tf->search('reference:123');
+ $tasks = $tf->findAll();
+ $this->assertNotEmpty($tasks);
+ $this->assertCount(1, $tasks);
+ $this->assertEquals('task2', $tasks[0]['title']);
+
+ $tf->search('ref:plop');
+ $tasks = $tf->findAll();
+ $this->assertEmpty($tasks);
+
+ $tf->search('ref:');
+ $tasks = $tf->findAll();
+ $this->assertEmpty($tasks);
+ }
+
public function testSearchWithStatus()
{
$p = new Project($this->container);