mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
added filterByCallback() to interface SS_Filterable and all implementing classes
This commit is contained in:
parent
ba1e688729
commit
d9b74874fc
@ -211,6 +211,25 @@ You can also combine both conjunctive ("AND") and disjunctive ("OR") statements.
|
|||||||
));
|
));
|
||||||
// WHERE ("LastName" = 'Minnée' AND ("FirstName" = 'Sam' OR "Age" = '17'))
|
// WHERE ("LastName" = 'Minnée' AND ("FirstName" = 'Sam' OR "Age" = '17'))
|
||||||
|
|
||||||
|
### Filter with PHP / filterByCallback
|
||||||
|
|
||||||
|
It is also possible to filter by a PHP callback, however this will force the
|
||||||
|
data model to fetch all records and loop them in PHP, thus `filter()` or `filterAny()`
|
||||||
|
are to be preferred over `filterByCallback()`.
|
||||||
|
Please note that because `filterByCallback()` has to run in PHP, it will always return
|
||||||
|
an `ArrayList` (even if called on a `DataList`, this however might change in future).
|
||||||
|
The first parameter to the callback is the item, the second parameter is the list itself.
|
||||||
|
The callback will run once for each record, if the callback returns true, this record
|
||||||
|
will be added to the list of returned items.
|
||||||
|
The below example will get all Members that have an expired or not encrypted password.
|
||||||
|
|
||||||
|
:::php
|
||||||
|
$membersWithBadPassword = Member::get()->filterByCallback(function($item, $list) {
|
||||||
|
if ($item->isPasswordExpired() || $item->PasswordEncryption = 'none') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
### Exclude
|
### Exclude
|
||||||
|
|
||||||
The `exclude()` method is the opposite to the filter in that it removes entries
|
The `exclude()` method is the opposite to the filter in that it removes entries
|
||||||
|
@ -476,6 +476,27 @@ class ArrayList extends ViewableData implements SS_List, SS_Filterable, SS_Sorta
|
|||||||
return $firstElement;
|
return $firstElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SS_Filterable::filterByCallback()
|
||||||
|
*
|
||||||
|
* @example $list = $list->filterByCallback(function($item, $list) { return $item->Age == 9; })
|
||||||
|
* @param callable $callback
|
||||||
|
* @return ArrayList
|
||||||
|
*/
|
||||||
|
public function filterByCallback($callback) {
|
||||||
|
if(!is_callable($callback)) {
|
||||||
|
throw new LogicException(sprintf(
|
||||||
|
"SS_Filterable::filterByCallback() passed callback must be callable, '%s' given",
|
||||||
|
gettype($callback)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
$output = ArrayList::create();
|
||||||
|
foreach($this as $item) {
|
||||||
|
if(call_user_func($callback, $item, $this)) $output->push($item);
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exclude the list to not contain items with these charactaristics
|
* Exclude the list to not contain items with these charactaristics
|
||||||
*
|
*
|
||||||
|
@ -406,21 +406,24 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
|
||||||
* included. Returns the filtered list.
|
|
||||||
*
|
|
||||||
* Note that, in the current implementation, the filtered list will be an ArrayList, but this may change in a
|
* Note that, in the current implementation, the filtered list will be an ArrayList, but this may change in a
|
||||||
* future implementation.
|
* future implementation.
|
||||||
|
* @see SS_Filterable::filterByCallback()
|
||||||
|
*
|
||||||
|
* @example $list = $list->filterByCallback(function($item, $list) { return $item->Age == 9; })
|
||||||
|
* @param callable $callback
|
||||||
|
* @return ArrayList (this may change in future implementations)
|
||||||
*/
|
*/
|
||||||
public function filterByCallback($callback) {
|
public function filterByCallback($callback) {
|
||||||
if(!is_callable($callback)) {
|
if(!is_callable($callback)) {
|
||||||
throw new LogicException("DataList::filterByCallback() must be passed something callable.");
|
throw new LogicException(sprintf(
|
||||||
|
"SS_Filterable::filterByCallback() passed callback must be callable, '%s' given",
|
||||||
|
gettype($callback)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
$output = ArrayList::create();
|
||||||
$output = new ArrayList;
|
|
||||||
foreach($this as $item) {
|
foreach($this as $item) {
|
||||||
if($callback($item)) $output->push($item);
|
if(call_user_func($callback, $item, $this)) $output->push($item);
|
||||||
}
|
}
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
|
@ -44,4 +44,13 @@ interface SS_Filterable {
|
|||||||
*/
|
*/
|
||||||
public function exclude();
|
public function exclude();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new instance of this list that excludes any items with these charactaristics
|
||||||
|
* Filter this List by a callback function. The function will be passed each record of the List in turn,
|
||||||
|
* and must return true for the record to be included. Returns the filtered list.
|
||||||
|
*
|
||||||
|
* @example $list = $list->filterByCallback(function($item, $list) { return $item->Age == 9; })
|
||||||
|
* @return SS_Filterable
|
||||||
|
*/
|
||||||
|
public function filterByCallback($callback);
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,29 @@ abstract class SS_ListDecorator extends ViewableData implements SS_List, SS_Sort
|
|||||||
return call_user_func_array(array($this->list, 'filter'), $args);
|
return call_user_func_array(array($this->list, 'filter'), $args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that, in the current implementation, the filtered list will be an ArrayList, but this may change in a
|
||||||
|
* future implementation.
|
||||||
|
* @see SS_Filterable::filterByCallback()
|
||||||
|
*
|
||||||
|
* @example $list = $list->filterByCallback(function($item, $list) { return $item->Age == 9; })
|
||||||
|
* @param callable $callback
|
||||||
|
* @return ArrayList (this may change in future implementations)
|
||||||
|
*/
|
||||||
|
public function filterByCallback($callback) {
|
||||||
|
if(!is_callable($callback)) {
|
||||||
|
throw new LogicException(sprintf(
|
||||||
|
"SS_Filterable::filterByCallback() passed callback must be callable, '%s' given",
|
||||||
|
gettype($callback)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
$output = ArrayList::create();
|
||||||
|
foreach($this->list as $item) {
|
||||||
|
if(call_user_func($callback, $item, $this->list)) $output->push($item);
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
public function limit($limit, $offset = 0) {
|
public function limit($limit, $offset = 0) {
|
||||||
return $this->list->limit($limit, $offset);
|
return $this->list->limit($limit, $offset);
|
||||||
}
|
}
|
||||||
|
@ -439,6 +439,32 @@ class ArrayListTest extends SapphireTest {
|
|||||||
$this->assertEquals($expected, $list->toArray(), 'List should only contain Steve and Steve and Clair');
|
$this->assertEquals($expected, $list->toArray(), 'List should only contain Steve and Steve and Clair');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* $list = $list->filterByCallback(function($item, $list) { return $item->Age == 21; })
|
||||||
|
*/
|
||||||
|
public function testFilterByCallback() {
|
||||||
|
$list = new ArrayList(array(
|
||||||
|
array('Name' => 'Steve', 'ID' => 1, 'Age' => 21),
|
||||||
|
array('Name' => 'Bob', 'ID' => 2, 'Age' => 18),
|
||||||
|
array('Name' => 'Clair', 'ID' => 2, 'Age' => 21),
|
||||||
|
array('Name' => 'Oscar', 'ID' => 2, 'Age' => 52),
|
||||||
|
array('Name' => 'Mike', 'ID' => 3, 'Age' => 43)
|
||||||
|
));
|
||||||
|
|
||||||
|
$list = $list->filterByCallback(function ($item, $list) {
|
||||||
|
return $item->Age == 21;
|
||||||
|
});
|
||||||
|
|
||||||
|
$expected = array(
|
||||||
|
new ArrayData(array('Name' => 'Steve', 'ID' => 1, 'Age' => 21)),
|
||||||
|
new ArrayData(array('Name' => 'Clair', 'ID' => 2, 'Age' => 21)),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $list->count());
|
||||||
|
$this->assertEquals($expected, $list->toArray(), 'List should only contain Steve and Clair');
|
||||||
|
$this->assertTrue($list instanceof SS_Filterable, 'The List should be of type SS_Filterable');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* $list->exclude('Name', 'bob'); // exclude bob from list
|
* $list->exclude('Name', 'bob'); // exclude bob from list
|
||||||
*/
|
*/
|
||||||
|
@ -671,6 +671,24 @@ class DataListTest extends SapphireTest {
|
|||||||
$this->assertEquals(0, $list->exclude('ID', $obj->ID)->count());
|
$this->assertEquals(0, $list->exclude('ID', $obj->ID)->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* $list = $list->filterByCallback(function($item, $list) { return $item->Age == 21; })
|
||||||
|
*/
|
||||||
|
public function testFilterByCallback() {
|
||||||
|
$team1ID = $this->idFromFixture('DataObjectTest_Team', 'team1');
|
||||||
|
$list = DataObjectTest_TeamComment::get();
|
||||||
|
$list = $list->filterByCallback(function ($item, $list) use ($team1ID) {
|
||||||
|
return $item->TeamID == $team1ID;
|
||||||
|
});
|
||||||
|
|
||||||
|
$result = $list->column('Name');
|
||||||
|
$expected = array_intersect($result, array('Joe', 'Bob'));
|
||||||
|
|
||||||
|
$this->assertEquals(2, $list->count());
|
||||||
|
$this->assertEquals($expected, $result, 'List should only contain comments from Team 1 (Joe and Bob)');
|
||||||
|
$this->assertTrue($list instanceof SS_Filterable, 'The List should be of type SS_Filterable');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* $list->exclude('Name', 'bob'); // exclude bob from list
|
* $list->exclude('Name', 'bob'); // exclude bob from list
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user