API Add excludeAny() and tests for complicated excludes/filters (#7838)

This commit is contained in:
Andrew Aitken-Fincham 2018-02-07 20:20:17 +00:00 committed by Damian Mooyman
parent ef6b03a35a
commit 860fa2a05a
2 changed files with 182 additions and 6 deletions

View File

@ -587,9 +587,8 @@ class DataList extends ViewableData implements SS_List, Filterable, Sortable, Li
}
/**
* Return a copy of this list which does not contain any items with these charactaristics
* Return a copy of this list which does not contain any items that match all params
*
* @see SS_List::exclude()
* @example $list = $list->exclude('Name', 'bob'); // exclude bob from list
* @example $list = $list->exclude('Name', array('aziz', 'bob'); // exclude aziz and bob from list
* @example $list = $list->exclude(array('Name'=>'bob, 'Age'=>21)); // exclude bob that has Age 21
@ -599,7 +598,9 @@ class DataList extends ViewableData implements SS_List, Filterable, Sortable, Li
*
* @todo extract the sql from this method into a SQLGenerator class
*
* @param string|array Escaped SQL statement. If passed as array, all keys and values will be escaped internally
* @param string|array
* @param string [optional]
*
* @return $this
*/
public function exclude()
@ -625,6 +626,43 @@ class DataList extends ViewableData implements SS_List, Filterable, Sortable, Li
});
}
/**
* Return a copy of this list which does not contain any items with any of these params
*
* @example $list = $list->excludeAny('Name', 'bob'); // exclude bob from list
* @example $list = $list->excludeAny('Name', array('aziz', 'bob'); // exclude aziz and bob from list
* @example $list = $list->excludeAny(array('Name'=>'bob, 'Age'=>21)); // exclude bob or Age 21
* @example $list = $list->excludeAny(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob or Age 21 or 43
* @example $list = $list->excludeAny(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43)));
* // bob, phil, 21 or 43 would be excluded
*
* @param string|array
* @param string [optional]
*
* @return $this
*/
public function excludeAny()
{
$numberFuncArgs = count(func_get_args());
$whereArguments = array();
if ($numberFuncArgs == 1 && is_array(func_get_arg(0))) {
$whereArguments = func_get_arg(0);
} elseif ($numberFuncArgs == 2) {
$whereArguments[func_get_arg(0)] = func_get_arg(1);
} else {
throw new InvalidArgumentException('Incorrect number of arguments passed to excludeAny()');
}
return $this->alterDataQuery(function (DataQuery $dataQuery) use ($whereArguments) {
foreach ($whereArguments as $field => $value) {
$filter = $this->createSearchFilter($field, $value);
$filter->exclude($dataQuery);
}
return $dataQuery;
});
}
/**
* This method returns a copy of this list that does not contain any DataObjects that exists in $list
*

View File

@ -1509,14 +1509,61 @@ class DataListTest extends SapphireTest
$this->assertEquals(2, $list->count());
}
/**
* Test doesn't exclude if only matches one
* $list->exclude(array('Name'=>'bob, 'Age'=>21)); // exclude bob that has Age 21
*/
public function testMultipleExcludeMultipleMatches()
{
$list = TeamComment::get();
$list = $list->exclude(array('Name'=>'Bob', 'Comment'=>'Phil is a unique guy, and comments on team2'));
$this->assertCount(3, $list);
}
/**
* // exclude only those that match both
*/
public function testMultipleExcludeArraysMultipleMatches()
{
$list = TeamComment::get();
$list = $list->exclude(array(
'Name'=> array('Bob', 'Phil'),
'Comment'=> array(
'This is a team comment by Bob',
'Phil is a unique guy, and comments on team2'
)
));
$this->assertListEquals([['Name' => 'Joe']], $list);
}
/**
* Exclude only which matches both params
*/
public function testMultipleExcludeArraysMultipleMatchesOneMiss()
{
$list = TeamComment::get();
$list = $list->exclude(array(
'Name' => array('Bob', 'Phil'),
'Comment' => array(
'Does not match any comments',
'Phil is a unique guy, and comments on team2'
)
));
$list = $list->sort('Name');
$this->assertListEquals(
[
['Name' => 'Bob'],
['Name' => 'Joe'],
],
$list
);
}
/**
* Test that if an exclude() is applied to a filter(), the filter() is still preserved.
*/
public function testExcludeOnFilter()
{
/**
* @var DataList $list
*/
$list = TeamComment::get();
$list = $list->filter('Comment', 'Phil is a unique guy, and comments on team2');
$list = $list->exclude('Name', 'Bob');
@ -1528,6 +1575,58 @@ class DataListTest extends SapphireTest
$sql
);
$this->assertEquals(array('Phil is a unique guy, and comments on team2', 'Bob'), $parameters);
$this->assertListEquals([['Name' => 'Phil']], $list);
}
/**
* Test that if a complicated exclude() is applied to a filter(), the filter() is still preserved.
*/
public function testComplicatedExcludeOnFilter()
{
$list = TeamComment::get();
$list = $list->filter('Name', array('Phil', 'Bob'));
$list = $list->exclude('Name', array('Bob', 'Joe'));
$sql = $list->sql($parameters);
$this->assertSQLContains(
'WHERE ("DataObjectTest_TeamComment"."Name" IN (?, ?)) AND (("DataObjectTest_TeamComment"."Name" NOT IN (?, ?) '
. 'OR "DataObjectTest_TeamComment"."Name" IS NULL))',
$sql
);
$this->assertEquals(array('Phil', 'Bob', 'Bob', 'Joe'), $parameters);
$this->assertListEquals([['Name' => 'Phil']], $list);
}
/**
* Test that if a very complicated exclude() is applied to a filter(), the filter() is still preserved.
*/
public function testVeryComplicatedExcludeOnFilter()
{
$list = TeamComment::get();
$list = $list->filter('Name', array('Phil', 'Bob'));
$list = $list->exclude(array(
'Name' => array('Joe', 'Phil'),
'Comment' => array('Matches no comments', 'Not a matching comment')
));
$sql = $list->sql($parameters);
$this->assertSQLContains(
'WHERE ("DataObjectTest_TeamComment"."Name" IN (?, ?)) '
. 'AND (("DataObjectTest_TeamComment"."Name" NOT IN (?, ?) '
. 'OR "DataObjectTest_TeamComment"."Name" IS NULL) '
. 'OR ("DataObjectTest_TeamComment"."Comment" NOT IN (?, ?) '
. 'OR "DataObjectTest_TeamComment"."Comment" IS NULL))',
$sql
);
$this->assertEquals(array('Phil', 'Bob', 'Joe', 'Phil', 'Matches no comments', 'Not a matching comment'), $parameters);
$list = $list->sort('Name');
$this->assertListEquals(
[
['Name' => 'Bob'],
['Name' => 'Phil'],
],
$list
);
}
public function testExcludeWithSearchFilter()
@ -1540,6 +1639,45 @@ class DataListTest extends SapphireTest
$this->assertEquals(array('Bob'), $parameters);
}
/**
* Test that Bob and Phil are excluded (one match each)
*/
public function testExcludeAny()
{
$list = TeamComment::get();
$list = $list->excludeAny(array(
'Name' => 'Bob',
'Comment' => 'Phil is a unique guy, and comments on team2'
));
$this->assertListEquals([['Name' => 'Joe']], $list);
}
/**
* Test that Bob and Phil are excluded by Name
*/
public function testExcludeAnyArrays()
{
$list = TeamComment::get();
$list = $list->excludeAny(array(
'Name' => array('Bob', 'Phil'),
'Comment' => 'No matching comments'
));
$this->assertListEquals([['Name' => 'Joe']], $list);
}
/**
* Test that Bob is excluded by Name, Phil by comment
*/
public function testExcludeAnyMultiArrays()
{
$list = TeamComment::get();
$list = $list->excludeAny(array(
'Name' => array('Bob', 'Fred'),
'Comment' => array('No matching comments', 'Phil is a unique guy, and comments on team2')
));
$this->assertListEquals([['Name' => 'Joe']], $list);
}
/**
* Test exact match filter with empty array items
*