mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge remote branch 'origin/master' into translation-staging
This commit is contained in:
commit
b0fc307ac0
@ -161,12 +161,30 @@ Then there is the most complex task when you want to find Sam and Sig that has e
|
||||
'FirstName' => array('Sam', 'Sig'),
|
||||
'Age' => array(17, 74)
|
||||
));
|
||||
// SQL: WHERE ("FirstName" IN ('Sam', 'Sig) AND "Age" IN ('17', '74))
|
||||
|
||||
This would be equivalent to a SQL query of
|
||||
In case you want to match multiple criteria non-exclusively (with an "OR" disjunctive),
|
||||
use the `filterAny()` method instead:
|
||||
|
||||
:::
|
||||
... WHERE ("FirstName" IN ('Sam', 'Sig) AND "Age" IN ('17', '74));
|
||||
:::php
|
||||
$members = Member::get()->filterAny(array(
|
||||
'FirstName' => 'Sam',
|
||||
'Age' => 17,
|
||||
));
|
||||
// SQL: WHERE ("FirstName" = 'Sam' OR "Age" = '17')
|
||||
|
||||
You can also combine both conjunctive ("AND") and disjunctive ("OR") statements.
|
||||
|
||||
:::php
|
||||
$members = Member::get()
|
||||
->filter(array(
|
||||
'LastName' => 'Minnée'
|
||||
))
|
||||
->filterAny(array(
|
||||
'FirstName' => 'Sam',
|
||||
'Age' => 17,
|
||||
));
|
||||
// SQL: WHERE ("LastName" = 'Minnée' AND ("FirstName" = 'Sam' OR "Age" = '17'))
|
||||
|
||||
### Exclude
|
||||
|
||||
|
@ -385,6 +385,68 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a copy of this list which does not contain items matching any of these charactaristics.
|
||||
*
|
||||
* @example // filter bob from list
|
||||
* $list = $list->filterAny('Name', 'bob');
|
||||
* // SQL: WHERE "Name" = 'bob'
|
||||
* @example // filter aziz and bob from list
|
||||
* $list = $list->filterAny('Name', array('aziz', 'bob');
|
||||
* // SQL: WHERE ("Name" IN ('aziz','bob'))
|
||||
* @example // filter by bob or anybody aged 21
|
||||
* $list = $list->filterAny(array('Name'=>'bob, 'Age'=>21));
|
||||
* // SQL: WHERE ("Name" = 'bob' OR "Age" = '21')
|
||||
* @example // filter by bob or anybody aged 21 or 43
|
||||
* $list = $list->filterAny(array('Name'=>'bob, 'Age'=>array(21, 43)));
|
||||
* // SQL: WHERE ("Name" = 'bob' OR ("Age" IN ('21', '43'))
|
||||
* @example // bob age 21 or 43, phil age 21 or 43 would be excluded
|
||||
* $list = $list->filterAny(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43)));
|
||||
* // SQL: WHERE (("Name" IN ('bob', 'phil')) OR ("Age" IN ('21', '43'))
|
||||
*
|
||||
* @todo extract the sql from this method into a SQLGenerator class
|
||||
*
|
||||
* @param string|array See {@link filter()}
|
||||
* @return DataList
|
||||
*/
|
||||
public function filterAny() {
|
||||
$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 exclude()');
|
||||
}
|
||||
|
||||
return $this->alterDataQuery(function($query, $list) use ($whereArguments) {
|
||||
$subquery = $query->disjunctiveGroup();
|
||||
|
||||
foreach($whereArguments as $field => $value) {
|
||||
$fieldArgs = explode(':', $field);
|
||||
$field = array_shift($fieldArgs);
|
||||
$filterType = array_shift($fieldArgs);
|
||||
$modifiers = $fieldArgs;
|
||||
|
||||
// This is here since PHP 5.3 can't call protected/private methods in a closure.
|
||||
$t = singleton($list->dataClass())->dbObject($field);
|
||||
if($filterType) {
|
||||
$className = "{$filterType}Filter";
|
||||
} else {
|
||||
$className = 'ExactMatchFilter';
|
||||
}
|
||||
if(!class_exists($className)){
|
||||
$className = 'ExactMatchFilter';
|
||||
array_unshift($modifiers, $filterType);
|
||||
}
|
||||
$t = new $className($field, $value, $modifiers);
|
||||
$t->apply($subquery);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter this DataList by a callback function.
|
||||
* The function will be passed each record of the DataList in turn, and must return true for the record to be
|
||||
|
@ -457,6 +457,91 @@ class DataListTest extends SapphireTest {
|
||||
$this->assertEquals(2, $gtList->count());
|
||||
}
|
||||
|
||||
public function testFilterAny() {
|
||||
$list = DataObjectTest_TeamComment::get();
|
||||
$list = $list->filterAny('Name', 'Bob');
|
||||
$this->assertEquals(1, $list->count());
|
||||
}
|
||||
|
||||
public function testFilterAnyMultipleArray() {
|
||||
$list = DataObjectTest_TeamComment::get();
|
||||
$list = $list->filterAny(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob'));
|
||||
$this->assertEquals(1, $list->count());
|
||||
$this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
|
||||
}
|
||||
|
||||
public function testFilterAnyOnFilter() {
|
||||
$list = DataObjectTest_TeamComment::get();
|
||||
$list = $list->filter(array(
|
||||
'TeamID'=>$this->idFromFixture('DataObjectTest_Team', 'team1')
|
||||
));
|
||||
$list = $list->filterAny(array(
|
||||
'Name'=>array('Phil', 'Joe'),
|
||||
'Comment'=>'This is a team comment by Bob'
|
||||
));
|
||||
$list = $list->sort('Name');
|
||||
$this->assertEquals(2, $list->count());
|
||||
$this->assertEquals(
|
||||
'Bob',
|
||||
$list->offsetGet(0)->Name,
|
||||
'Results should include comments from Bob, matched by comment and team'
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Joe',
|
||||
$list->offsetGet(1)->Name,
|
||||
'Results should include comments by Joe, matched by name and team (not by comment)'
|
||||
);
|
||||
|
||||
$list = DataObjectTest_TeamComment::get();
|
||||
$list = $list->filter(array(
|
||||
'TeamID'=>$this->idFromFixture('DataObjectTest_Team', 'team1')
|
||||
));
|
||||
$list = $list->filterAny(array(
|
||||
'Name'=>array('Phil', 'Joe'),
|
||||
'Comment'=>'This is a team comment by Bob'
|
||||
));
|
||||
$list = $list->sort('Name');
|
||||
$list = $list->filter(array('Name' => 'Bob'));
|
||||
$this->assertEquals(1, $list->count());
|
||||
$this->assertEquals(
|
||||
'Bob',
|
||||
$list->offsetGet(0)->Name,
|
||||
'Results should include comments from Bob, matched by name and team'
|
||||
);
|
||||
}
|
||||
|
||||
public function testFilterAnyMultipleWithArrayFilter() {
|
||||
$list = DataObjectTest_TeamComment::get();
|
||||
$list = $list->filterAny(array('Name'=>array('Bob','Phil')));
|
||||
$this->assertEquals(2, $list->count(), 'There should be two comments');
|
||||
$this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob');
|
||||
$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
|
||||
}
|
||||
|
||||
public function testFilterAnyArrayInArray() {
|
||||
$list = DataObjectTest_TeamComment::get();
|
||||
$list = $list->filterAny(array(
|
||||
'Name'=>array('Bob','Phil'),
|
||||
'TeamID'=>array($this->idFromFixture('DataObjectTest_Team', 'team1'))))
|
||||
->sort('Name');
|
||||
$this->assertEquals(3, $list->count());
|
||||
$this->assertEquals(
|
||||
'Bob',
|
||||
$list->offsetGet(0)->Name,
|
||||
'Results should include comments from Bob, matched by name and team'
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Joe',
|
||||
$list->offsetGet(1)->Name,
|
||||
'Results should include comments by Joe, matched by team (not by name)'
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Phil',
|
||||
$list->offsetGet(2)->Name,
|
||||
'Results should include comments from Phil, matched by name (even if he\'s not in Team1)'
|
||||
);
|
||||
}
|
||||
|
||||
public function testFilterAndExcludeById() {
|
||||
$id = $this->idFromFixture('DataObjectTest_SubTeam', 'subteam1');
|
||||
$list = DataObjectTest_SubTeam::get()->filter('ID', $id);
|
||||
|
Loading…
Reference in New Issue
Block a user