Start to implement advanced search query language
This commit is contained in:
parent
0fa64fc9bd
commit
e22985df50
|
|
@ -46,9 +46,11 @@ class Projectinfo extends Base
|
|||
|
||||
if ($search !== '') {
|
||||
|
||||
$paginator
|
||||
->setQuery($this->taskFinder->getSearchQuery($project['id'], $search))
|
||||
->calculate();
|
||||
// $paginator
|
||||
// ->setQuery($this->taskFinder->getSearchQuery($project['id'], $search))
|
||||
// ->calculate();
|
||||
|
||||
$paginator->setQuery($this->taskFilter->search($search)->filterByProject($project['id'])->getQuery())->calculate();
|
||||
|
||||
$nb_tasks = $paginator->getTotal();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
|
||||
namespace Core;
|
||||
|
||||
/**
|
||||
* Lexer
|
||||
*
|
||||
* @package core
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Lexer
|
||||
{
|
||||
/**
|
||||
* Current position
|
||||
*
|
||||
* @access private
|
||||
* @var integer
|
||||
*/
|
||||
private $offset = 0;
|
||||
|
||||
/**
|
||||
* Token map
|
||||
*
|
||||
* @access private
|
||||
* @var array
|
||||
*/
|
||||
private $tokenMap = array(
|
||||
"/^(assignee:)/" => 'T_ASSIGNEE',
|
||||
"/^(color:)/" => 'T_COLOR',
|
||||
"/^(due:)/" => 'T_DUE',
|
||||
"/^(title:)/" => 'T_TITLE',
|
||||
"/^(\s+)/" => 'T_WHITESPACE',
|
||||
'/^([<=>]{0,2}[0-9]{4}-[0-9]{2}-[0-9]{2})/' => 'T_DATE',
|
||||
'/^(yesterday|tomorrow|today)/' => 'T_DATE',
|
||||
'/^("(.*?)")/' => 'T_STRING',
|
||||
"/^(\w+)/" => 'T_STRING',
|
||||
);
|
||||
|
||||
/**
|
||||
* Tokenize input string
|
||||
*
|
||||
* @access public
|
||||
* @param string $input
|
||||
* @return array
|
||||
*/
|
||||
public function tokenize($input)
|
||||
{
|
||||
$tokens = array();
|
||||
$this->offset = 0;
|
||||
|
||||
while (isset($input[$this->offset])) {
|
||||
|
||||
$result = $this->match(substr($input, $this->offset));
|
||||
|
||||
if ($result === false) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$tokens[] = $result;
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a token that match and move the offset
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @return array|boolean
|
||||
*/
|
||||
public function match($string)
|
||||
{
|
||||
foreach ($this->tokenMap as $pattern => $name) {
|
||||
if (preg_match($pattern, $string, $matches)) {
|
||||
|
||||
$this->offset += strlen($matches[1]);
|
||||
|
||||
return array(
|
||||
'match' => trim($matches[1], '"'),
|
||||
'token' => $name,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the output of tokenizer to be easily parsed by the database filter
|
||||
*
|
||||
* Example: ['T_ASSIGNEE' => ['user1', 'user2'], 'T_TITLE' => 'task title']
|
||||
*
|
||||
* @access public
|
||||
* @param array $tokens
|
||||
* @return array
|
||||
*/
|
||||
public function map(array $tokens)
|
||||
{
|
||||
$map = array(
|
||||
'T_TITLE' => '',
|
||||
);
|
||||
|
||||
while (false !== ($token = current($tokens))) {
|
||||
|
||||
switch ($token['token']) {
|
||||
case 'T_ASSIGNEE':
|
||||
case 'T_COLOR':
|
||||
$next = next($tokens);
|
||||
|
||||
if ($next !== false && $next['token'] === 'T_STRING') {
|
||||
$map[$token['token']][] = $next['match'];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'T_DUE':
|
||||
$next = next($tokens);
|
||||
|
||||
if ($next !== false && $next['token'] === 'T_DATE') {
|
||||
$map[$token['token']] = $next['match'];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$map['T_TITLE'] .= $token['match'];
|
||||
break;
|
||||
}
|
||||
|
||||
next($tokens);
|
||||
}
|
||||
|
||||
$map['T_TITLE'] = trim($map['T_TITLE']);
|
||||
|
||||
if (empty($map['T_TITLE'])) {
|
||||
unset($map['T_TITLE']);
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
}
|
||||
|
|
@ -99,6 +99,29 @@ class Color extends Base
|
|||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Find a color id from the name or the id
|
||||
*
|
||||
* @access public
|
||||
* @param string $color
|
||||
* @return string
|
||||
*/
|
||||
public function find($color)
|
||||
{
|
||||
$color = strtolower($color);
|
||||
|
||||
foreach ($this->default_colors as $color_id => $params) {
|
||||
if ($color_id === $color) {
|
||||
return $color_id;
|
||||
}
|
||||
else if ($color === strtolower($params['name'])) {
|
||||
return $color_id;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available colors
|
||||
*
|
||||
|
|
|
|||
|
|
@ -23,6 +23,42 @@ class TaskFilter extends Base
|
|||
*/
|
||||
public $query;
|
||||
|
||||
/**
|
||||
* Apply filters according to the search input
|
||||
*
|
||||
* @access public
|
||||
* @param string $input
|
||||
* @return TaskFilter
|
||||
*/
|
||||
public function search($input)
|
||||
{
|
||||
$tree = $this->lexer->map($this->lexer->tokenize($input));
|
||||
$this->query = $this->taskFinder->getExtendedQuery();
|
||||
|
||||
if (empty($tree)) {
|
||||
$this->query->addCondition('1 = 0');
|
||||
}
|
||||
|
||||
foreach ($tree as $filter => $value) {
|
||||
switch ($filter) {
|
||||
case 'T_ASSIGNEE':
|
||||
$this->filterByAssignee($value);
|
||||
break;
|
||||
case 'T_COLOR':
|
||||
$this->filterByColors($value);
|
||||
break;
|
||||
case 'T_DUE':
|
||||
$this->filterByDueDate($value);
|
||||
break;
|
||||
case 'T_TITLE':
|
||||
$this->filterByTitle($value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new query
|
||||
*
|
||||
|
|
@ -163,6 +199,35 @@ class TaskFilter extends Base
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter by assignee names
|
||||
*
|
||||
* @access public
|
||||
* @param array $values List of assignees
|
||||
* @return TaskFilter
|
||||
*/
|
||||
public function filterByAssignee(array $values)
|
||||
{
|
||||
$this->query->beginOr();
|
||||
|
||||
foreach ($values as $assignee) {
|
||||
|
||||
switch ($assignee) {
|
||||
case 'me':
|
||||
$this->query->eq('owner_id', $this->userSession->getId());
|
||||
break;
|
||||
case 'nobody':
|
||||
$this->query->eq('owner_id', 0);
|
||||
break;
|
||||
default:
|
||||
$this->query->ilike(User::TABLE.'.username', '%'.$assignee.'%');
|
||||
$this->query->ilike(User::TABLE.'.name', '%'.$assignee.'%');
|
||||
}
|
||||
}
|
||||
|
||||
$this->query->closeOr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter by color
|
||||
*
|
||||
|
|
@ -179,6 +244,26 @@ class TaskFilter extends Base
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter by colors
|
||||
*
|
||||
* @access public
|
||||
* @param array $colors
|
||||
* @return TaskFilter
|
||||
*/
|
||||
public function filterByColors(array $colors)
|
||||
{
|
||||
$this->query->beginOr();
|
||||
|
||||
foreach ($colors as $color) {
|
||||
$this->filterByColor($this->color->find($color));
|
||||
}
|
||||
|
||||
$this->query->closeOr();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter by column
|
||||
*
|
||||
|
|
@ -227,6 +312,18 @@ class TaskFilter extends Base
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter by due date
|
||||
*
|
||||
* @access public
|
||||
* @param string $date ISO8601 date format
|
||||
* @return TaskFilter
|
||||
*/
|
||||
public function filterByDueDate($date)
|
||||
{
|
||||
return $this->filterWithOperator('date_due', $date, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter by due date (range)
|
||||
*
|
||||
|
|
@ -294,6 +391,17 @@ class TaskFilter extends Base
|
|||
return $this->query->findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PicoDb query
|
||||
*
|
||||
* @access public
|
||||
* @return \PicoDb\Table
|
||||
*/
|
||||
public function getQuery()
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the results to the ajax autocompletion
|
||||
*
|
||||
|
|
@ -465,4 +573,36 @@ class TaskFilter extends Base
|
|||
|
||||
return $vEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter with an operator
|
||||
*
|
||||
* @access public
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @param boolean $is_date
|
||||
* @return TaskFilter
|
||||
*/
|
||||
private function filterWithOperator($field, $value, $is_date)
|
||||
{
|
||||
$operators = array(
|
||||
'<=' => 'lte',
|
||||
'>=' => 'gte',
|
||||
'<' => 'lt',
|
||||
'>' => 'gt',
|
||||
);
|
||||
|
||||
foreach ($operators as $operator => $method) {
|
||||
|
||||
if (strpos($value, $operator) === 0) {
|
||||
$value = substr($value, strlen($operator));
|
||||
$this->query->$method($field, $is_date ? $this->dateParser->getTimestampFromIsoFormat($value) : $value);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
$this->query->eq($field, $is_date ? $this->dateParser->getTimestampFromIsoFormat($value) : $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ class ClassProvider implements ServiceProviderInterface
|
|||
'EmailClient',
|
||||
'Helper',
|
||||
'HttpClient',
|
||||
'Lexer',
|
||||
'MemoryCache',
|
||||
'Request',
|
||||
'Session',
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ Using Kanboard
|
|||
|
||||
### More
|
||||
|
||||
- [Search syntax](search.markdown)
|
||||
- [Command line interface](cli.markdown)
|
||||
- [Syntax guide](syntax-guide.markdown)
|
||||
- [Frequently asked questions](faq.markdown)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
Advanced Search Syntax
|
||||
======================
|
||||
|
||||
Kanboard use a simple query language for advanced search.
|
||||
|
||||
Example of query
|
||||
----------------
|
||||
|
||||
This example will returns all tasks assigned to me with a due date for tomorrow and that have a title that contains "my title":
|
||||
|
||||
```
|
||||
assigne:me due:tomorrow my title
|
||||
```
|
||||
|
||||
Search by assignee
|
||||
------------------
|
||||
|
||||
Attribute: **assignee**
|
||||
|
||||
Query with the full name:
|
||||
|
||||
```
|
||||
assignee:"Frederic Guillot"
|
||||
```
|
||||
|
||||
Query with the username:
|
||||
|
||||
```
|
||||
assignee:fguillot
|
||||
```
|
||||
|
||||
Multiple assignee lookup:
|
||||
|
||||
```
|
||||
assignee:user1 assignee:"John Doe"
|
||||
```
|
||||
|
||||
Kanboard will search tasks assigned to the "user1" or "John Doe".
|
||||
|
||||
Query for unassigned tasks:
|
||||
|
||||
```
|
||||
assignee:nobody
|
||||
```
|
||||
|
||||
Query for my assigned tasks
|
||||
|
||||
```
|
||||
assignee:me
|
||||
```
|
||||
|
||||
Search by color
|
||||
---------------
|
||||
|
||||
Attribute: **color**
|
||||
|
||||
Query to search by color id:
|
||||
|
||||
```
|
||||
color:blue
|
||||
```
|
||||
|
||||
Query to search by color name:
|
||||
|
||||
```
|
||||
color:"Deep Orange"
|
||||
```
|
||||
|
||||
Search by due date
|
||||
------------------
|
||||
|
||||
Attribute: **due**
|
||||
|
||||
Query to search tasks due today:
|
||||
|
||||
```
|
||||
due:today
|
||||
```
|
||||
|
||||
Query to search tasks due tomorrow:
|
||||
|
||||
```
|
||||
due:tomorrow
|
||||
```
|
||||
|
||||
Query to search tasks due yesterday:
|
||||
|
||||
```
|
||||
due:yesterday
|
||||
```
|
||||
|
||||
Query to search tasks due with the exact date:
|
||||
|
||||
```
|
||||
due:2015-06-29
|
||||
```
|
||||
|
||||
The date must use the ISO8601 format: **YYYY-MM-DD**.
|
||||
|
||||
Operators supported:
|
||||
|
||||
- Greater than: **due:>2015-06-29**
|
||||
- Lower than: **due:<2015-06-29**
|
||||
- Greater than or equal: **due:>=2015-06-29**
|
||||
- Lower than or equal: **due:<=2015-06-29**
|
||||
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__.'/Base.php';
|
||||
|
||||
use Core\Lexer;
|
||||
|
||||
class LexerTest extends Base
|
||||
{
|
||||
public function testAssigneeQuery()
|
||||
{
|
||||
$lexer = new Lexer;
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'assignee:', 'token' => 'T_ASSIGNEE'), array('match' => 'me', 'token' => 'T_STRING')),
|
||||
$lexer->tokenize('assignee:me')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'assignee:', 'token' => 'T_ASSIGNEE'), array('match' => 'everybody', 'token' => 'T_STRING')),
|
||||
$lexer->tokenize('assignee:everybody')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'assignee:', 'token' => 'T_ASSIGNEE'), array('match' => 'nobody', 'token' => 'T_STRING')),
|
||||
$lexer->tokenize('assignee:nobody')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_ASSIGNEE' => array('nobody')),
|
||||
$lexer->map($lexer->tokenize('assignee:nobody'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_ASSIGNEE' => array('John Doe', 'me')),
|
||||
$lexer->map($lexer->tokenize('assignee:"John Doe" assignee:me'))
|
||||
);
|
||||
}
|
||||
|
||||
public function testColorQuery()
|
||||
{
|
||||
$lexer = new Lexer;
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'color:', 'token' => 'T_COLOR'), array('match' => 'Blue', 'token' => 'T_STRING')),
|
||||
$lexer->tokenize('color:Blue')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'color:', 'token' => 'T_COLOR'), array('match' => 'Dark Grey', 'token' => 'T_STRING')),
|
||||
$lexer->tokenize('color:"Dark Grey"')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_COLOR' => array('Blue')),
|
||||
$lexer->map($lexer->tokenize('color:Blue'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_COLOR' => array('Dark Grey')),
|
||||
$lexer->map($lexer->tokenize('color:"Dark Grey"'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(),
|
||||
$lexer->map($lexer->tokenize('color: '))
|
||||
);
|
||||
}
|
||||
|
||||
public function testDueDateQuery()
|
||||
{
|
||||
$lexer = new Lexer;
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'due:', 'token' => 'T_DUE'), array('match' => '2015-05-01', 'token' => 'T_DATE')),
|
||||
$lexer->tokenize('due:2015-05-01')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'due:', 'token' => 'T_DUE'), array('match' => '<2015-05-01', 'token' => 'T_DATE')),
|
||||
$lexer->tokenize('due:<2015-05-01')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'due:', 'token' => 'T_DUE'), array('match' => '>2015-05-01', 'token' => 'T_DATE')),
|
||||
$lexer->tokenize('due:>2015-05-01')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'due:', 'token' => 'T_DUE'), array('match' => '<=2015-05-01', 'token' => 'T_DATE')),
|
||||
$lexer->tokenize('due:<=2015-05-01')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'due:', 'token' => 'T_DUE'), array('match' => '>=2015-05-01', 'token' => 'T_DATE')),
|
||||
$lexer->tokenize('due:>=2015-05-01')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'due:', 'token' => 'T_DUE'), array('match' => 'yesterday', 'token' => 'T_DATE')),
|
||||
$lexer->tokenize('due:yesterday')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(array('match' => 'due:', 'token' => 'T_DUE'), array('match' => 'tomorrow', 'token' => 'T_DATE')),
|
||||
$lexer->tokenize('due:tomorrow')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(),
|
||||
$lexer->tokenize('due:#2015-05-01')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(),
|
||||
$lexer->tokenize('due:01-05-1024')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_DUE' => '2015-05-01'),
|
||||
$lexer->map($lexer->tokenize('due:2015-05-01'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_DUE' => '<2015-05-01'),
|
||||
$lexer->map($lexer->tokenize('due:<2015-05-01'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_DUE' => 'today'),
|
||||
$lexer->map($lexer->tokenize('due:today'))
|
||||
);
|
||||
}
|
||||
|
||||
public function testMultipleCriterias()
|
||||
{
|
||||
$lexer = new Lexer;
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_COLOR' => array('Dark Grey'), 'T_ASSIGNEE' => array('Fred G'), 'T_TITLE' => 'my task title'),
|
||||
$lexer->map($lexer->tokenize('color:"Dark Grey" assignee:"Fred G" my task title'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_TITLE' => 'my title', 'T_COLOR' => array('yellow')),
|
||||
$lexer->map($lexer->tokenize('my title color:yellow'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_TITLE' => 'my title', 'T_DUE' => '2015-04-01'),
|
||||
$lexer->map($lexer->tokenize('my title due:2015-04-01'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_TITLE' => 'awesome', 'T_DUE' => '<=2015-04-01'),
|
||||
$lexer->map($lexer->tokenize('due:<=2015-04-01 awesome'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_TITLE' => 'awesome', 'T_DUE' => 'today'),
|
||||
$lexer->map($lexer->tokenize('due:today awesome'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_TITLE' => 'my title', 'T_COLOR' => array('yellow'), 'T_DUE' => '2015-04-01'),
|
||||
$lexer->map($lexer->tokenize('my title color:yellow due:2015-04-01'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_TITLE' => 'my title', 'T_COLOR' => array('yellow'), 'T_DUE' => '2015-04-01', 'T_ASSIGNEE' => array('John Doe')),
|
||||
$lexer->map($lexer->tokenize('my title color:yellow due:2015-04-01 assignee:"John Doe"'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_TITLE' => 'my title'),
|
||||
$lexer->map($lexer->tokenize('my title color:'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_TITLE' => 'my title'),
|
||||
$lexer->map($lexer->tokenize('my title color:assignee:'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('T_TITLE' => 'my title'),
|
||||
$lexer->map($lexer->tokenize('my title '))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(),
|
||||
$lexer->map($lexer->tokenize('color:assignee:'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,180 @@
|
|||
|
||||
require_once __DIR__.'/Base.php';
|
||||
|
||||
use Model\Project;
|
||||
use Model\User;
|
||||
use Model\TaskFilter;
|
||||
use Model\TaskCreation;
|
||||
use Model\DateParser;
|
||||
|
||||
class TaskFilterTest extends Base
|
||||
{
|
||||
public function testSearchWithEmptyResult()
|
||||
{
|
||||
$dp = new DateParser($this->container);
|
||||
$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' => 'my task title is awesome', 'date_due' => $dp->getTimestampFromIsoFormat('-2 days'))));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'my task title is amazing', 'date_due' => $dp->getTimestampFromIsoFormat('+1 day'))));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'Bob at work', 'date_due' => $dp->getTimestampFromIsoFormat('-1 day'))));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'youpi', 'date_due' => $dp->getTimestampFromIsoFormat(time()))));
|
||||
|
||||
$this->assertEmpty($tf->search('search something')->findAll());
|
||||
}
|
||||
|
||||
public function testSearchWithDueDate()
|
||||
{
|
||||
$dp = new DateParser($this->container);
|
||||
$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' => 'my task title is awesome', 'date_due' => $dp->getTimestampFromIsoFormat('-2 days'))));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'my task title is amazing', 'date_due' => $dp->getTimestampFromIsoFormat('+1 day'))));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'Bob at work', 'date_due' => $dp->getTimestampFromIsoFormat('-1 day'))));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'youpi', 'date_due' => $dp->getTimestampFromIsoFormat(time()))));
|
||||
|
||||
$tf->search('due:>'.date('Y-m-d'));
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(1, $tasks);
|
||||
$this->assertEquals('my task title is amazing', $tasks[0]['title']);
|
||||
|
||||
$tf->search('due:>='.date('Y-m-d'));
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(2, $tasks);
|
||||
$this->assertEquals('my task title is amazing', $tasks[0]['title']);
|
||||
$this->assertEquals('youpi', $tasks[1]['title']);
|
||||
|
||||
$tf->search('due:<'.date('Y-m-d'));
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(2, $tasks);
|
||||
$this->assertEquals('my task title is awesome', $tasks[0]['title']);
|
||||
$this->assertEquals('Bob at work', $tasks[1]['title']);
|
||||
|
||||
$tf->search('due:<='.date('Y-m-d'));
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(3, $tasks);
|
||||
$this->assertEquals('my task title is awesome', $tasks[0]['title']);
|
||||
$this->assertEquals('Bob at work', $tasks[1]['title']);
|
||||
$this->assertEquals('youpi', $tasks[2]['title']);
|
||||
|
||||
$tf->search('due:tomorrow');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(1, $tasks);
|
||||
$this->assertEquals('my task title is amazing', $tasks[0]['title']);
|
||||
|
||||
$tf->search('due:yesterday');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(1, $tasks);
|
||||
$this->assertEquals('Bob at work', $tasks[0]['title']);
|
||||
|
||||
$tf->search('due:today');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(1, $tasks);
|
||||
$this->assertEquals('youpi', $tasks[0]['title']);
|
||||
}
|
||||
|
||||
public function testSearchWithColor()
|
||||
{
|
||||
$p = new Project($this->container);
|
||||
$u = new User($this->container);
|
||||
$tc = new TaskCreation($this->container);
|
||||
$tf = new TaskFilter($this->container);
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
$this->assertEquals(2, $u->create(array('username' => 'bob', 'name' => 'Bob Ryan')));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'my task title is awesome', 'color_id' => 'light_green')));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'my task title is amazing', 'color_id' => 'blue')));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'Bob at work')));
|
||||
|
||||
$tf->search('color:"Light Green"');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(1, $tasks);
|
||||
$this->assertEquals('my task title is awesome', $tasks[0]['title']);
|
||||
|
||||
$tf->search('color:"Light Green" amazing');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertEmpty($tasks);
|
||||
|
||||
$tf->search('color:"plop');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertEmpty($tasks);
|
||||
|
||||
$tf->search('color:unknown');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(3, $tasks);
|
||||
|
||||
$tf->search('color:blue amazing');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(1, $tasks);
|
||||
$this->assertEquals('my task title is amazing', $tasks[0]['title']);
|
||||
|
||||
$tf->search('color:blue color:Yellow');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(2, $tasks);
|
||||
$this->assertEquals('my task title is amazing', $tasks[0]['title']);
|
||||
$this->assertEquals('Bob at work', $tasks[1]['title']);
|
||||
}
|
||||
|
||||
public function testSearchWithAssignee()
|
||||
{
|
||||
$p = new Project($this->container);
|
||||
$u = new User($this->container);
|
||||
$tc = new TaskCreation($this->container);
|
||||
$tf = new TaskFilter($this->container);
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
$this->assertEquals(2, $u->create(array('username' => 'bob', 'name' => 'Bob Ryan')));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'my task title is awesome', 'owner_id' => 1)));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'my task title is amazing', 'owner_id' => 0)));
|
||||
$this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'Bob at work', 'owner_id' => 2)));
|
||||
|
||||
$tf->search('assignee:john');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertEmpty($tasks);
|
||||
|
||||
$tf->search('assignee:admin my task title');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(1, $tasks);
|
||||
$this->assertEquals('my task title is awesome', $tasks[0]['title']);
|
||||
|
||||
$tf->search('my task title');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(2, $tasks);
|
||||
$this->assertEquals('my task title is awesome', $tasks[0]['title']);
|
||||
$this->assertEquals('my task title is amazing', $tasks[1]['title']);
|
||||
|
||||
$tf->search('my task title assignee:nobody');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(1, $tasks);
|
||||
$this->assertEquals('my task title is amazing', $tasks[0]['title']);
|
||||
|
||||
$tf->search('assignee:"Bob ryan" assignee:nobody');
|
||||
$tasks = $tf->findAll();
|
||||
$this->assertNotEmpty($tasks);
|
||||
$this->assertCount(2, $tasks);
|
||||
$this->assertEquals('my task title is amazing', $tasks[0]['title']);
|
||||
$this->assertEquals('Bob at work', $tasks[1]['title']);
|
||||
}
|
||||
|
||||
public function testCopy()
|
||||
{
|
||||
$tf = new TaskFilter($this->container);
|
||||
|
|
|
|||
Loading…
Reference in New Issue