diff --git a/model/DataList.php b/model/DataList.php index bf7710168..7bbbbd41d 100644 --- a/model/DataList.php +++ b/model/DataList.php @@ -500,27 +500,37 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab throw new InvalidArgumentException('Incorrect number of arguments passed to exclude()'); } - $SQL_Statements = array(); - foreach($whereArguments as $fieldName => $value) { - if($fieldName == 'ID') { - $fieldName = sprintf('"%s"."ID"', ClassInfo::baseDataClass($this->dataClass)); - } else { - $fieldName = '"' . Convert::raw2sql($fieldName) . '"'; + 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; + $list->excludeFilterContext($field, $filterType, $modifiers, $value, $subquery); } - - if(is_array($value)){ - $SQL_Statements[] = ($fieldName . ' NOT IN (\''.implode('\',\'', Convert::raw2sql($value)).'\')'); - } else { - $SQL_Statements[] = ($fieldName . ' != \''.Convert::raw2sql($value).'\''); - } - } - - if(!count($SQL_Statements)) return $this; - - return $this->alterDataQuery_30(function($query) use ($SQL_Statements){ - $query->whereAny($SQL_Statements); }); } + + /** + * Translates the comparisator to the sql query + * + * @param string $field - the fieldname in the db + * @param string $comparisators - example StartsWith, relates to a filtercontext + * @param string $value - the value that the filtercontext will use for matching + * @param DataQuery $dataQuery - The (sub)query to add the exclusion clauses to + * @todo Deprecated SearchContexts and pull their functionality into the core of the ORM + */ + private function excludeFilterContext($field, $comparisators, $modifiers, $value, $dataQuery) { + $t = singleton($this->dataClass())->dbObject($field); + $className = "{$comparisators}Filter"; + if(!class_exists($className)){ + throw new InvalidArgumentException('There are no '.$comparisators.' comparisator'); + } + $t = new $className($field, $value, $modifiers); + $t->exclude($dataQuery); + } /** * This method returns a copy of this list that does not contain any DataObjects that exists in $list diff --git a/tests/model/DataListTest.php b/tests/model/DataListTest.php index 29ca2f11c..bfadbb20c 100644 --- a/tests/model/DataListTest.php +++ b/tests/model/DataListTest.php @@ -501,7 +501,7 @@ class DataListTest extends SapphireTest { */ public function testMultipleExclude() { $list = DataObjectTest_TeamComment::get(); - $list->exclude(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob')); + $list = $list->exclude(array('Name'=>'Bob', 'Comment'=>'This is a team comment by Bob')); $this->assertEquals(2, $list->count()); } @@ -514,9 +514,17 @@ class DataListTest extends SapphireTest { $list = $list->exclude('Name', 'Bob'); $this->assertContains( - 'WHERE ("Comment" = \'Phil is a unique guy, and comments on team2\') AND ("Name" != \'Bob\')', + 'WHERE ("DataObjectTest_TeamComment"."Comment" = ' + . '\'Phil is a unique guy, and comments on team2\') ' + . 'AND (("DataObjectTest_TeamComment"."Name" != \'Bob\'))', $list->sql()); } + + public function testExcludeWithSearchFilter() { + $list = DataObjectTest_TeamComment::get(); + $list = $list->exclude('Name:LessThan', 'Bob'); + $this->assertContains('WHERE (("DataObjectTest_TeamComment"."Name" >= \'Bob\'))', $list->sql()); + } /** * $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob with Age 21 or 43