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
33b1ff3e57
@ -205,13 +205,18 @@ This would be equivalent to a SQL query of
|
|||||||
|
|
||||||
### Search Filter Modifiers
|
### Search Filter Modifiers
|
||||||
|
|
||||||
The where clauses showcased in the previous two sections (filter and exclude) specify case-insensitive exact
|
The where clauses showcased in the previous two sections (filter and exclude) specify exact
|
||||||
matches by default. However, there are a number of suffixes that you can put on field names to change this
|
matches by default. However, there are a number of suffixes that you can put on field names to change this
|
||||||
behaviour `":StartsWith"`, `":EndsWith"`, `":PartialMatch"`, `":GreaterThan"`, `":LessThan"`, `":Negation"`.
|
behaviour `":StartsWith"`, `":EndsWith"`, `":PartialMatch"`, `":GreaterThan"`, `":LessThan"`, `":Negation"`.
|
||||||
|
|
||||||
Each of these suffixes is represented in the ORM as a subclass of `[api:SearchFilter]`. Developers can define
|
Each of these suffixes is represented in the ORM as a subclass of `[api:SearchFilter]`. Developers can define
|
||||||
their own SearchFilters if needing to extend the ORM filter and exclude behaviours.
|
their own SearchFilters if needing to extend the ORM filter and exclude behaviours.
|
||||||
|
|
||||||
|
These suffixes can also take modifiers themselves. The modifiers currently supported are `":not"`, `":nocase"`
|
||||||
|
and `":case"`. These negate the filter, make it case-insensitive and make it case-sensitive respectively. The
|
||||||
|
default comparison uses the database's default. For MySQL and MSSQL, this is case-insensitive. For PostgreSQL,
|
||||||
|
this is case-sensitive.
|
||||||
|
|
||||||
The following is a query which will return everyone whose first name doesn't start with S, who has logged in
|
The following is a query which will return everyone whose first name doesn't start with S, who has logged in
|
||||||
since 1/1/2011.
|
since 1/1/2011.
|
||||||
|
|
||||||
|
@ -374,38 +374,15 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
|
|||||||
* Return a new instance of the list with an added filter
|
* Return a new instance of the list with an added filter
|
||||||
*/
|
*/
|
||||||
public function addFilter($filterArray) {
|
public function addFilter($filterArray) {
|
||||||
$SQL_Statements = array();
|
|
||||||
foreach($filterArray as $field => $value) {
|
foreach($filterArray as $field => $value) {
|
||||||
if(is_array($value)) {
|
$fieldArgs = explode(':', $field);
|
||||||
$customQuery = 'IN (\''.implode('\',\'',Convert::raw2sql($value)).'\')';
|
$field = array_shift($fieldArgs);
|
||||||
} else {
|
$filterType = array_shift($fieldArgs);
|
||||||
$customQuery = '= \''.Convert::raw2sql($value).'\'';
|
$modifiers = $fieldArgs;
|
||||||
}
|
$this->applyFilterContext($field, $filterType, $modifiers, $value);
|
||||||
|
|
||||||
if(stristr($field,':')) {
|
|
||||||
$fieldArgs = explode(':',$field);
|
|
||||||
$field = array_shift($fieldArgs);
|
|
||||||
foreach($fieldArgs as $fieldArg){
|
|
||||||
$comparisor = $this->applyFilterContext($field, $fieldArg, $value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if($field == 'ID') {
|
|
||||||
$field = sprintf('"%s"."ID"', ClassInfo::baseDataClass($this->dataClass));
|
|
||||||
} else {
|
|
||||||
$field = '"' . Convert::raw2sql($field) . '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
$SQL_Statements[] = $field . ' ' . $customQuery;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!count($SQL_Statements)) return $this;
|
return $this;
|
||||||
|
|
||||||
return $this->alterDataQuery_30(function($query) use ($SQL_Statements){
|
|
||||||
foreach($SQL_Statements as $SQL_Statement){
|
|
||||||
$query->where($SQL_Statement);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -459,16 +436,22 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
|
|||||||
*
|
*
|
||||||
* @param string $field - the fieldname in the db
|
* @param string $field - the fieldname in the db
|
||||||
* @param string $comparisators - example StartsWith, relates to a filtercontext
|
* @param string $comparisators - example StartsWith, relates to a filtercontext
|
||||||
|
* @param array $modifiers - Modifiers to pass to the filter, ie not,nocase
|
||||||
* @param string $value - the value that the filtercontext will use for matching
|
* @param string $value - the value that the filtercontext will use for matching
|
||||||
* @todo Deprecated SearchContexts and pull their functionality into the core of the ORM
|
* @todo Deprecated SearchContexts and pull their functionality into the core of the ORM
|
||||||
*/
|
*/
|
||||||
private function applyFilterContext($field, $comparisators, $value) {
|
private function applyFilterContext($field, $comparisators, $modifiers, $value) {
|
||||||
$t = singleton($this->dataClass())->dbObject($field);
|
$t = singleton($this->dataClass())->dbObject($field);
|
||||||
$className = "{$comparisators}Filter";
|
if($comparisators) {
|
||||||
if(!class_exists($className)){
|
$className = "{$comparisators}Filter";
|
||||||
throw new InvalidArgumentException('There are no '.$comparisators.' comparisator');
|
} else {
|
||||||
|
$className = 'ExactMatchFilter';
|
||||||
}
|
}
|
||||||
$t = new $className($field,$value);
|
if(!class_exists($className)){
|
||||||
|
$className = 'ExactMatchFilter';
|
||||||
|
array_unshift($modifiers, $comparisators);
|
||||||
|
}
|
||||||
|
$t = new $className($field, $value, $modifiers);
|
||||||
$t->apply($this->dataQuery());
|
$t->apply($this->dataQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,25 +483,29 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
|
|||||||
throw new InvalidArgumentException('Incorrect number of arguments passed to exclude()');
|
throw new InvalidArgumentException('Incorrect number of arguments passed to exclude()');
|
||||||
}
|
}
|
||||||
|
|
||||||
$SQL_Statements = array();
|
return $this->alterDataQuery(function($query, $list) use ($whereArguments) {
|
||||||
foreach($whereArguments as $fieldName => $value) {
|
$subquery = $query->disjunctiveGroup();
|
||||||
if($fieldName == 'ID') {
|
|
||||||
$fieldName = sprintf('"%s"."ID"', ClassInfo::baseDataClass($this->dataClass));
|
foreach($whereArguments as $field => $value) {
|
||||||
} else {
|
$fieldArgs = explode(':', $field);
|
||||||
$fieldName = '"' . Convert::raw2sql($fieldName) . '"';
|
$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->exclude($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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,23 +17,102 @@
|
|||||||
* @subpackage search
|
* @subpackage search
|
||||||
*/
|
*/
|
||||||
class EndsWithFilter extends SearchFilter {
|
class EndsWithFilter extends SearchFilter {
|
||||||
|
protected function comparison($exclude = false) {
|
||||||
|
$modifiers = $this->getModifiers();
|
||||||
|
if(($extras = array_diff($modifiers, array('not', 'nocase', 'case'))) != array()) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
get_class($this) . ' does not accept ' . implode(', ', $extras) . ' as modifiers');
|
||||||
|
}
|
||||||
|
if(DB::getConn() instanceof PostgreSQLDatabase) {
|
||||||
|
if(in_array('case', $modifiers)) {
|
||||||
|
$comparison = 'LIKE';
|
||||||
|
} else {
|
||||||
|
$comparison = 'ILIKE';
|
||||||
|
}
|
||||||
|
} elseif(in_array('case', $modifiers)) {
|
||||||
|
$comparison = 'LIKE BINARY';
|
||||||
|
} else {
|
||||||
|
$comparison = 'LIKE';
|
||||||
|
}
|
||||||
|
if($exclude) {
|
||||||
|
$comparison = 'NOT ' . $comparison;
|
||||||
|
}
|
||||||
|
return $comparison;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a match on the trailing characters of a field value.
|
* Applies a match on the trailing characters of a field value.
|
||||||
*
|
*
|
||||||
* @return unknown
|
* @return DataQuery
|
||||||
*/
|
*/
|
||||||
public function apply(DataQuery $query) {
|
protected function applyOne(DataQuery $query) {
|
||||||
$this->model = $query->applyRelation($this->relation);
|
$this->model = $query->applyRelation($this->relation);
|
||||||
return $query->where(sprintf(
|
return $query->where(sprintf(
|
||||||
"%s %s '%%%s'",
|
"%s %s '%%%s'",
|
||||||
$this->getDbName(),
|
$this->getDbName(),
|
||||||
(DB::getConn() instanceof PostgreSQLDatabase) ? 'ILIKE' : 'LIKE',
|
$this->comparison(false),
|
||||||
Convert::raw2sql($this->getValue())
|
Convert::raw2sql($this->getValue())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a match on the trailing characters of a field value.
|
||||||
|
* Matches against one of the many values.
|
||||||
|
*
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function applyMany(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
$connectives = array();
|
||||||
|
foreach($this->getValue() as $value) {
|
||||||
|
$connectives[] = sprintf(
|
||||||
|
"%s %s '%%%s'",
|
||||||
|
$this->getDbName(),
|
||||||
|
$this->comparison(false),
|
||||||
|
Convert::raw2sql($value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$whereClause = implode(' OR ', $connectives);
|
||||||
|
return $query->where($whereClause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excludes a match on the trailing characters of a field value.
|
||||||
|
*
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
return $query->where(sprintf(
|
||||||
|
"%s NOT %s '%%%s'",
|
||||||
|
$this->getDbName(),
|
||||||
|
$this->comparison(true),
|
||||||
|
Convert::raw2sql($this->getValue())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excludes a match on the trailing characters of a field value.
|
||||||
|
* Excludes a field if it matches any of the values.
|
||||||
|
*
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function excludeMany(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
$connectives = array();
|
||||||
|
foreach($this->getValue() as $value) {
|
||||||
|
$connectives[] = sprintf(
|
||||||
|
"%s NOT %s '%%%s'",
|
||||||
|
$this->getDbName(),
|
||||||
|
$this->comparison(true),
|
||||||
|
Convert::raw2sql($value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$whereClause = implode(' AND ', $connectives);
|
||||||
|
return $query->where($whereClause);
|
||||||
|
}
|
||||||
|
|
||||||
public function isEmpty() {
|
public function isEmpty() {
|
||||||
return $this->getValue() == null || $this->getValue() == '';
|
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,22 +14,134 @@
|
|||||||
* @subpackage search
|
* @subpackage search
|
||||||
*/
|
*/
|
||||||
class ExactMatchFilter extends SearchFilter {
|
class ExactMatchFilter extends SearchFilter {
|
||||||
|
protected function comparison($exclude = false) {
|
||||||
|
$modifiers = $this->getModifiers();
|
||||||
|
if(($extras = array_diff($modifiers, array('not', 'nocase', 'case'))) != array()) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
get_class($this) . ' does not accept ' . implode(', ', $extras) . ' as modifiers');
|
||||||
|
}
|
||||||
|
if(!in_array('case', $modifiers) && !in_array('nocase', $modifiers)) {
|
||||||
|
if($exclude) {
|
||||||
|
return '!=';
|
||||||
|
} else {
|
||||||
|
return '=';
|
||||||
|
}
|
||||||
|
} elseif(DB::getConn() instanceof PostgreSQLDatabase) {
|
||||||
|
if(in_array('case', $modifiers)) {
|
||||||
|
$comparison = 'LIKE';
|
||||||
|
} else {
|
||||||
|
$comparison = 'ILIKE';
|
||||||
|
}
|
||||||
|
} elseif(in_array('case', $modifiers)) {
|
||||||
|
$comparison = 'LIKE BINARY';
|
||||||
|
} else {
|
||||||
|
$comparison = 'LIKE';
|
||||||
|
}
|
||||||
|
if($exclude) {
|
||||||
|
$comparison = 'NOT ' . $comparison;
|
||||||
|
}
|
||||||
|
return $comparison;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies an exact match (equals) on a field value.
|
* Applies an exact match (equals) on a field value.
|
||||||
*
|
*
|
||||||
* @return unknown
|
* @return DataQuery
|
||||||
*/
|
*/
|
||||||
public function apply(DataQuery $query) {
|
protected function applyOne(DataQuery $query) {
|
||||||
$this->model = $query->applyRelation($this->relation);
|
$this->model = $query->applyRelation($this->relation);
|
||||||
return $query->where(sprintf(
|
return $query->where(sprintf(
|
||||||
"%s = '%s'",
|
"%s %s '%s'",
|
||||||
$this->getDbName(),
|
$this->getDbName(),
|
||||||
|
$this->comparison(false),
|
||||||
Convert::raw2sql($this->getValue())
|
Convert::raw2sql($this->getValue())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies an exact match (equals) on a field value against multiple
|
||||||
|
* possible values.
|
||||||
|
*
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function applyMany(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
$values = array();
|
||||||
|
foreach($this->getValue() as $value) {
|
||||||
|
$values[] = Convert::raw2sql($value);
|
||||||
|
}
|
||||||
|
if($this->comparison(false) == '=') {
|
||||||
|
// Neither :case nor :nocase
|
||||||
|
$valueStr = "'" . implode("', '", $values) . "'";
|
||||||
|
return $query->where(sprintf(
|
||||||
|
'%s IN (%s)',
|
||||||
|
$this->getDbName(),
|
||||||
|
$valueStr
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
foreach($values as &$v) {
|
||||||
|
$v = sprintf(
|
||||||
|
"%s %s '%s'",
|
||||||
|
$this->getDbName(),
|
||||||
|
$this->comparison(false),
|
||||||
|
$v
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$where = implode(' OR ', $values);
|
||||||
|
return $query->where($where);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excludes an exact match (equals) on a field value.
|
||||||
|
*
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
return $query->where(sprintf(
|
||||||
|
"%s %s '%s'",
|
||||||
|
$this->getDbName(),
|
||||||
|
$this->comparison(true),
|
||||||
|
Convert::raw2sql($this->getValue())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excludes an exact match (equals) on a field value against multiple
|
||||||
|
* possible values.
|
||||||
|
*
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function excludeMany(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
$values = array();
|
||||||
|
foreach($this->getValue() as $value) {
|
||||||
|
$values[] = Convert::raw2sql($value);
|
||||||
|
}
|
||||||
|
if($this->comparison(false) == '=') {
|
||||||
|
// Neither :case nor :nocase
|
||||||
|
$valueStr = "'" . implode("', '", $values) . "'";
|
||||||
|
return $query->where(sprintf(
|
||||||
|
'%s NOT IN (%s)',
|
||||||
|
$this->getDbName(),
|
||||||
|
$valueStr
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
foreach($values as &$v) {
|
||||||
|
$v = sprintf(
|
||||||
|
"%s %s '%s'",
|
||||||
|
$this->getDbName(),
|
||||||
|
$this->comparison(true),
|
||||||
|
$v
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$where = implode(' OR ', $values);
|
||||||
|
return $query->where($where);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function isEmpty() {
|
public function isEmpty() {
|
||||||
return $this->getValue() == null || $this->getValue() == '';
|
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,46 +7,46 @@
|
|||||||
/**
|
/**
|
||||||
* Checks if a value is in a given set.
|
* Checks if a value is in a given set.
|
||||||
* SQL syntax used: Column IN ('val1','val2')
|
* SQL syntax used: Column IN ('val1','val2')
|
||||||
|
* @deprecated 3.1 Use ExactMatchFilter instead
|
||||||
*
|
*
|
||||||
* @todo Add negation (NOT IN)6
|
|
||||||
* @package framework
|
* @package framework
|
||||||
* @subpackage search
|
* @subpackage search
|
||||||
*/
|
*/
|
||||||
class ExactMatchMultiFilter extends SearchFilter {
|
class ExactMatchMultiFilter extends SearchFilter {
|
||||||
|
function __construct($fullName, $value = false, array $modifiers = array()) {
|
||||||
|
Deprecation::notice('3.1', 'Use ExactMatchFilter instead.');
|
||||||
|
parent::__construct($fullName, $value, $modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
public function apply(DataQuery $query) {
|
public function apply(DataQuery $query) {
|
||||||
$this->model = $query->applyRelation($this->relation);
|
if (!is_array($this->getValue())) {
|
||||||
// hack
|
|
||||||
// PREVIOUS $values = explode(',',$this->getValue());
|
|
||||||
$values = array();
|
|
||||||
if (is_string($this->getValue())) {
|
|
||||||
$values = explode(',',$this->getValue());
|
$values = explode(',',$this->getValue());
|
||||||
|
} else {
|
||||||
|
$values = $this->getValue();
|
||||||
}
|
}
|
||||||
else {
|
$filter = new ExactMatchFilter($this->getFullName(), $values, $this->getModifiers());
|
||||||
foreach($this->getValue() as $v) {
|
return $filter->apply($query);
|
||||||
$values[] = $v;
|
}
|
||||||
}
|
|
||||||
|
protected function applyOne(DataQuery $query) {
|
||||||
|
/* NO OP */
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exclude(DataQuery $query) {
|
||||||
|
if (!is_array($this->getValue())) {
|
||||||
|
$values = explode(',',$this->getValue());
|
||||||
|
} else {
|
||||||
|
$values = $this->getValue();
|
||||||
}
|
}
|
||||||
|
$filter = new ExactMatchFilter($this->getFullName(), $values, $this->getModifiers());
|
||||||
|
return $filter->exclude($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
if(! $values) return false;
|
/* NO OP */
|
||||||
for($i = 0; $i < count($values); $i++) {
|
|
||||||
if(! is_numeric($values[$i])) {
|
|
||||||
// @todo Fix string replacement to only replace leading and tailing quotes
|
|
||||||
$values[$i] = str_replace("'", '', $values[$i]);
|
|
||||||
$values[$i] = Convert::raw2sql($values[$i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$SQL_valueStr = "'" . implode("','", $values) . "'";
|
|
||||||
|
|
||||||
return $query->where(sprintf(
|
|
||||||
"%s IN (%s)",
|
|
||||||
$this->getDbName(),
|
|
||||||
$SQL_valueStr
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isEmpty() {
|
public function isEmpty() {
|
||||||
return $this->getValue() == null || $this->getValue() == '';
|
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
class FulltextFilter extends SearchFilter {
|
class FulltextFilter extends SearchFilter {
|
||||||
|
|
||||||
public function apply(DataQuery $query) {
|
protected function applyOne(DataQuery $query) {
|
||||||
return $query->where(sprintf(
|
return $query->where(sprintf(
|
||||||
"MATCH (%s) AGAINST ('%s')",
|
"MATCH (%s) AGAINST ('%s')",
|
||||||
$this->getDbName(),
|
$this->getDbName(),
|
||||||
@ -35,7 +35,15 @@ class FulltextFilter extends SearchFilter {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
|
return $query->where(sprintf(
|
||||||
|
"NOT MATCH (%s) AGAINST ('%s')",
|
||||||
|
$this->getDbName(),
|
||||||
|
Convert::raw2sql($this->getValue())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
public function isEmpty() {
|
public function isEmpty() {
|
||||||
return $this->getValue() == null || $this->getValue() == '';
|
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
class GreaterThanFilter extends SearchFilter {
|
class GreaterThanFilter extends SearchFilter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return $query
|
* @return DataQuery
|
||||||
*/
|
*/
|
||||||
public function apply(DataQuery $query) {
|
protected function applyOne(DataQuery $query) {
|
||||||
$this->model = $query->applyRelation($this->relation);
|
$this->model = $query->applyRelation($this->relation);
|
||||||
$value = $this->getDbFormattedValue();
|
$value = $this->getDbFormattedValue();
|
||||||
|
|
||||||
@ -22,7 +22,20 @@ class GreaterThanFilter extends SearchFilter {
|
|||||||
return $query->where($filter);
|
return $query->where($filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
$value = $this->getDbFormattedValue();
|
||||||
|
|
||||||
|
if(is_numeric($value)) $filter = sprintf("%s <= %s", $this->getDbName(), Convert::raw2sql($value));
|
||||||
|
else $filter = sprintf("%s <= '%s'", $this->getDbName(), Convert::raw2sql($value));
|
||||||
|
|
||||||
|
return $query->where($filter);
|
||||||
|
}
|
||||||
|
|
||||||
public function isEmpty() {
|
public function isEmpty() {
|
||||||
return $this->getValue() == null || $this->getValue() == '';
|
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
class LessThanFilter extends SearchFilter {
|
class LessThanFilter extends SearchFilter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return $query
|
* @return DataQuery
|
||||||
*/
|
*/
|
||||||
public function apply(DataQuery $query) {
|
protected function applyOne(DataQuery $query) {
|
||||||
$this->model = $query->applyRelation($this->relation);
|
$this->model = $query->applyRelation($this->relation);
|
||||||
$value = $this->getDbFormattedValue();
|
$value = $this->getDbFormattedValue();
|
||||||
|
|
||||||
@ -22,7 +22,20 @@ class LessThanFilter extends SearchFilter {
|
|||||||
return $query->where($filter);
|
return $query->where($filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
$value = $this->getDbFormattedValue();
|
||||||
|
|
||||||
|
if(is_numeric($value)) $filter = sprintf("%s >= %s", $this->getDbName(), Convert::raw2sql($value));
|
||||||
|
else $filter = sprintf("%s >= '%s'", $this->getDbName(), Convert::raw2sql($value));
|
||||||
|
|
||||||
|
return $query->where($filter);
|
||||||
|
}
|
||||||
|
|
||||||
public function isEmpty() {
|
public function isEmpty() {
|
||||||
return $this->getValue() == null || $this->getValue() == '';
|
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,19 +2,33 @@
|
|||||||
/**
|
/**
|
||||||
* Matches on rows where the field is not equal to the given value.
|
* Matches on rows where the field is not equal to the given value.
|
||||||
*
|
*
|
||||||
|
* @deprecated 3.1 Use ExactMatchFilter:not instead
|
||||||
* @package framework
|
* @package framework
|
||||||
* @subpackage search
|
* @subpackage search
|
||||||
*/
|
*/
|
||||||
class NegationFilter extends SearchFilter {
|
class NegationFilter extends SearchFilter {
|
||||||
|
function __construct($fullName, $value = false, array $modifiers = array()) {
|
||||||
public function apply(DataQuery $query) {
|
Deprecation::notice('3.1', 'Use ExactMatchFilter:not instead.');
|
||||||
$this->model = $query->applyRelation($this->relation);
|
$modifiers[] = 'not';
|
||||||
return $query->where(sprintf(
|
parent::__construct($fullName, $value, $modifiers);
|
||||||
"%s != '%s'",
|
|
||||||
$this->getDbName(),
|
|
||||||
Convert::raw2sql($this->getValue())
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function apply(DataQuery $query) {
|
||||||
|
$filter = new ExactMatchFilter($this->getFullName(), $this->getValue(), $this->getModifiers());
|
||||||
|
return $filter->apply($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function applyOne(DataQuery $query) {
|
||||||
|
/* NO OP */
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exclude(DataQuery $query) {
|
||||||
|
$filter = new ExactMatchFilter($this->getFullName(), $this->getValue(), $this->getModifiers());
|
||||||
|
return $filter->exclude($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
|
/* NO OP */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,24 +11,68 @@
|
|||||||
* @subpackage search
|
* @subpackage search
|
||||||
*/
|
*/
|
||||||
class PartialMatchFilter extends SearchFilter {
|
class PartialMatchFilter extends SearchFilter {
|
||||||
|
protected function comparison($exclude = false) {
|
||||||
|
$modifiers = $this->getModifiers();
|
||||||
|
if(($extras = array_diff($modifiers, array('not', 'nocase', 'case'))) != array()) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
get_class($this) . ' does not accept ' . implode(', ', $extras) . ' as modifiers');
|
||||||
|
}
|
||||||
|
if(DB::getConn() instanceof PostgreSQLDatabase) {
|
||||||
|
if(in_array('case', $modifiers)) {
|
||||||
|
$comparison = 'LIKE';
|
||||||
|
} else {
|
||||||
|
$comparison = 'ILIKE';
|
||||||
|
}
|
||||||
|
} elseif(in_array('case', $modifiers)) {
|
||||||
|
$comparison = 'LIKE BINARY';
|
||||||
|
} else {
|
||||||
|
$comparison = 'LIKE';
|
||||||
|
}
|
||||||
|
if($exclude) {
|
||||||
|
$comparison = 'NOT ' . $comparison;
|
||||||
|
}
|
||||||
|
return $comparison;
|
||||||
|
}
|
||||||
|
|
||||||
public function apply(DataQuery $query) {
|
protected function applyOne(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
$comparison = $this->comparison(false);
|
||||||
|
$where = sprintf("%s %s '%%%s%%'", $this->getDbName(), $comparison, Convert::raw2sql($this->getValue()));
|
||||||
|
|
||||||
|
return $query->where($where);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function applyMany(DataQuery $query) {
|
||||||
$this->model = $query->applyRelation($this->relation);
|
$this->model = $query->applyRelation($this->relation);
|
||||||
$where = array();
|
$where = array();
|
||||||
$comparison = (DB::getConn() instanceof PostgreSQLDatabase) ? 'ILIKE' : 'LIKE';
|
$comparison = $this->comparison(false);
|
||||||
if(is_array($this->getValue())) {
|
foreach($this->getValue() as $value) {
|
||||||
foreach($this->getValue() as $value) {
|
$where[]= sprintf("%s %s '%%%s%%'", $this->getDbName(), $comparison, Convert::raw2sql($value));
|
||||||
$where[]= sprintf("%s %s '%%%s%%'", $this->getDbName(), $comparison, Convert::raw2sql($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$where[] = sprintf("%s %s '%%%s%%'", $this->getDbName(), $comparison, Convert::raw2sql($this->getValue()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query->where(implode(' OR ', $where));
|
return $query->where(implode(' OR ', $where));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
$comparison = $this->comparison(true);
|
||||||
|
$where = sprintf("%s %s '%%%s%%'", $this->getDbName(), $comparison, Convert::raw2sql($this->getValue()));
|
||||||
|
|
||||||
|
return $query->where($where);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function excludeMany(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
$where = array();
|
||||||
|
$comparison = $this->comparison(true);
|
||||||
|
foreach($this->getValue() as $value) {
|
||||||
|
$where[]= sprintf("%s %s '%%%s%%'", $this->getDbName(), $comparison, Convert::raw2sql($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query->where(implode(' AND ', $where));
|
||||||
|
}
|
||||||
|
|
||||||
public function isEmpty() {
|
public function isEmpty() {
|
||||||
return $this->getValue() == null || $this->getValue() == '';
|
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,11 @@ abstract class SearchFilter extends Object {
|
|||||||
*/
|
*/
|
||||||
protected $value;
|
protected $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $modifiers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string Name of a has-one, has-many or many-many relation (not the classname).
|
* @var string Name of a has-one, has-many or many-many relation (not the classname).
|
||||||
* Set in the constructor as part of the name in dot-notation, and used in
|
* Set in the constructor as part of the name in dot-notation, and used in
|
||||||
@ -43,12 +48,14 @@ abstract class SearchFilter extends Object {
|
|||||||
* the necessary tables (e.g. "Comments.Name" to join the "Comments" has-many relationship and
|
* the necessary tables (e.g. "Comments.Name" to join the "Comments" has-many relationship and
|
||||||
* search the "Name" column when applying this filter to a SiteTree class).
|
* search the "Name" column when applying this filter to a SiteTree class).
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
|
* @param array $modifiers
|
||||||
*/
|
*/
|
||||||
public function __construct($fullName, $value = false) {
|
public function __construct($fullName, $value = false, array $modifiers = array()) {
|
||||||
$this->fullName = $fullName;
|
$this->fullName = $fullName;
|
||||||
// sets $this->name and $this->relation
|
// sets $this->name and $this->relation
|
||||||
$this->addRelation($fullName);
|
$this->addRelation($fullName);
|
||||||
$this->value = $value;
|
$this->value = $value;
|
||||||
|
$this->modifiers = array_map('strtolower', $modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,6 +103,24 @@ abstract class SearchFilter extends Object {
|
|||||||
return $this->value;
|
return $this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current modifiers to apply to the filter
|
||||||
|
*
|
||||||
|
* @param array $modifiers
|
||||||
|
*/
|
||||||
|
public function setModifiers(array $modifiers) {
|
||||||
|
$this->modifiers = array_map('strtolower', $modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor for the current modifiers to apply to the filter.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getModifiers() {
|
||||||
|
return $this->modifiers;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The original name of the field.
|
* The original name of the field.
|
||||||
*
|
*
|
||||||
@ -173,10 +198,74 @@ abstract class SearchFilter extends Object {
|
|||||||
/**
|
/**
|
||||||
* Apply filter criteria to a SQL query.
|
* Apply filter criteria to a SQL query.
|
||||||
*
|
*
|
||||||
* @param SQLQuery $query
|
* @param DataQuery $query
|
||||||
* @return SQLQuery
|
* @return DataQuery
|
||||||
*/
|
*/
|
||||||
abstract public function apply(DataQuery $query);
|
public function apply(DataQuery $query) {
|
||||||
|
if(($key = array_search('not', $this->modifiers)) !== false) {
|
||||||
|
unset($this->modifiers[$key]);
|
||||||
|
return $this->exclude($query);
|
||||||
|
}
|
||||||
|
if(is_array($this->value)) {
|
||||||
|
return $this->applyMany($query);
|
||||||
|
} else {
|
||||||
|
return $this->applyOne($query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply filter criteria to a SQL query with a single value.
|
||||||
|
*
|
||||||
|
* @param DataQuery $query
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
abstract protected function applyOne(DataQuery $query);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply filter criteria to a SQL query with an array of values.
|
||||||
|
*
|
||||||
|
* @param DataQuery $query
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function applyMany(DataQuery $query) {
|
||||||
|
throw new InvalidArgumentException(get_class($this) . "can't be used to filter by a list of items.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exclude filter criteria from a SQL query.
|
||||||
|
*
|
||||||
|
* @param DataQuery $query
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
public function exclude(DataQuery $query) {
|
||||||
|
if(($key = array_search('not', $this->modifiers)) !== false) {
|
||||||
|
unset($this->modifiers[$key]);
|
||||||
|
return $this->apply($query);
|
||||||
|
}
|
||||||
|
if(is_array($this->value)) {
|
||||||
|
return $this->excludeMany($query);
|
||||||
|
} else {
|
||||||
|
return $this->excludeOne($query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exclude filter criteria from a SQL query with a single value.
|
||||||
|
*
|
||||||
|
* @param DataQuery $query
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
abstract protected function excludeOne(DataQuery $query);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exclude filter criteria from a SQL query with an array of values.
|
||||||
|
*
|
||||||
|
* @param DataQuery $query
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function excludeMany(DataQuery $query) {
|
||||||
|
throw new InvalidArgumentException(get_class($this) . "can't be used to filter by a list of items.");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if a field has a value,
|
* Determines if a field has a value,
|
||||||
|
@ -17,23 +17,102 @@
|
|||||||
* @subpackage search
|
* @subpackage search
|
||||||
*/
|
*/
|
||||||
class StartsWithFilter extends SearchFilter {
|
class StartsWithFilter extends SearchFilter {
|
||||||
|
protected function comparison($exclude = false) {
|
||||||
|
$modifiers = $this->getModifiers();
|
||||||
|
if(($extras = array_diff($modifiers, array('not', 'nocase', 'case'))) != array()) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
get_class($this) . ' does not accept ' . implode(', ', $extras) . ' as modifiers');
|
||||||
|
}
|
||||||
|
if(DB::getConn() instanceof PostgreSQLDatabase) {
|
||||||
|
if(in_array('case', $modifiers)) {
|
||||||
|
$comparison = 'LIKE';
|
||||||
|
} else {
|
||||||
|
$comparison = 'ILIKE';
|
||||||
|
}
|
||||||
|
} elseif(in_array('case', $modifiers)) {
|
||||||
|
$comparison = 'LIKE BINARY';
|
||||||
|
} else {
|
||||||
|
$comparison = 'LIKE';
|
||||||
|
}
|
||||||
|
if($exclude) {
|
||||||
|
$comparison = 'NOT ' . $comparison;
|
||||||
|
}
|
||||||
|
return $comparison;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a substring match on a field value.
|
* Applies a match on the starting characters of a field value.
|
||||||
*
|
*
|
||||||
* @return unknown
|
* @return DataQuery
|
||||||
*/
|
*/
|
||||||
public function apply(DataQuery $query) {
|
protected function applyOne(DataQuery $query) {
|
||||||
$this->model = $query->applyRelation($this->relation);
|
$this->model = $query->applyRelation($this->relation);
|
||||||
return $query->where(sprintf(
|
return $query->where(sprintf(
|
||||||
"%s %s '%s%%'",
|
"%s %s '%s%%'",
|
||||||
$this->getDbName(),
|
$this->getDbName(),
|
||||||
(DB::getConn() instanceof PostgreSQLDatabase) ? 'ILIKE' : 'LIKE',
|
$this->comparison(false),
|
||||||
Convert::raw2sql($this->getValue())
|
Convert::raw2sql($this->getValue())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a match on the starting characters of a field value.
|
||||||
|
* Matches against one of the many values.
|
||||||
|
*
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function applyMany(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
$connectives = array();
|
||||||
|
foreach($this->getValue() as $value) {
|
||||||
|
$connectives[] = sprintf(
|
||||||
|
"%s %s '%s%%'",
|
||||||
|
$this->getDbName(),
|
||||||
|
$this->comparison(false),
|
||||||
|
Convert::raw2sql($value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$whereClause = implode(' OR ', $connectives);
|
||||||
|
return $query->where($whereClause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excludes a match on the starting characters of a field value.
|
||||||
|
*
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
return $query->where(sprintf(
|
||||||
|
"%s %s '%s%%'",
|
||||||
|
$this->getDbName(),
|
||||||
|
$this->comparison(true),
|
||||||
|
Convert::raw2sql($this->getValue())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excludes a match on the starting characters of a field value.
|
||||||
|
* Excludes a field if it matches any of the values.
|
||||||
|
*
|
||||||
|
* @return DataQuery
|
||||||
|
*/
|
||||||
|
protected function excludeMany(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
$connectives = array();
|
||||||
|
foreach($this->getValue() as $value) {
|
||||||
|
$connectives[] = sprintf(
|
||||||
|
"%s %s '%s%%'",
|
||||||
|
$this->getDbName(),
|
||||||
|
$this->comparison(true),
|
||||||
|
Convert::raw2sql($value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$whereClause = implode(' AND ', $connectives);
|
||||||
|
return $query->where($whereClause);
|
||||||
|
}
|
||||||
|
|
||||||
public function isEmpty() {
|
public function isEmpty() {
|
||||||
return $this->getValue() == null || $this->getValue() == '';
|
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,29 +6,47 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a value starts with one of the items of in a given set.
|
* Checks if a value starts with one of the items of in a given set.
|
||||||
* SQL syntax used: Column IN ('val1','val2')
|
* @deprecated 3.1 Use StartsWithFilter instead
|
||||||
*
|
*
|
||||||
* @todo Add negation (NOT IN)6
|
* @todo Add negation (NOT IN)6
|
||||||
* @package framework
|
* @package framework
|
||||||
* @subpackage search
|
* @subpackage search
|
||||||
*/
|
*/
|
||||||
class StartsWithMultiFilter extends SearchFilter {
|
class StartsWithMultiFilter extends SearchFilter {
|
||||||
|
function __construct($fullName, $value = false, array $modifiers = array()) {
|
||||||
|
Deprecation::notice('3.1', 'Use StartsWithFilter instead.');
|
||||||
|
parent::__construct($fullName, $value, $modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
public function apply(DataQuery $query) {
|
public function apply(DataQuery $query) {
|
||||||
$this->model = $query->applyRelation($this->relation);
|
if (!is_array($this->getValue())) {
|
||||||
$values = explode(',', $this->getValue());
|
$values = explode(',',$this->getValue());
|
||||||
|
} else {
|
||||||
foreach($values as $value) {
|
$values = $this->getValue();
|
||||||
$matches[] = sprintf("%s LIKE '%s%%'",
|
|
||||||
$this->getDbName(),
|
|
||||||
Convert::raw2sql(str_replace("'", '', $value))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
$filter = new StartsWithFilter($this->getFullName(), $values, $this->getModifiers());
|
||||||
|
return $filter->apply($query);
|
||||||
|
}
|
||||||
|
|
||||||
return $query->where(implode(" OR ", $matches));
|
protected function applyOne(DataQuery $query) {
|
||||||
|
/* NO OP */
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exclude(DataQuery $query) {
|
||||||
|
if (!is_array($this->getValue())) {
|
||||||
|
$values = explode(',',$this->getValue());
|
||||||
|
} else {
|
||||||
|
$values = $this->getValue();
|
||||||
|
}
|
||||||
|
$filter = new StartsWithFilter($this->getFullName(), $values, $this->getModifiers());
|
||||||
|
return $filter->exclude($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
|
/* NO OP */
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isEmpty() {
|
public function isEmpty() {
|
||||||
return $this->getValue() == null || $this->getValue() == '';
|
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,22 +12,33 @@
|
|||||||
* @subpackage search
|
* @subpackage search
|
||||||
*/
|
*/
|
||||||
class SubstringFilter extends PartialMatchFilter {
|
class SubstringFilter extends PartialMatchFilter {
|
||||||
public function __construct($fullName, $value = false) {
|
public function __construct($fullName, $value = false, array $modifiers = array()) {
|
||||||
Deprecation::notice('3.0', 'PartialMatchFilter instead.');
|
Deprecation::notice('3.0', 'PartialMatchFilter instead.');
|
||||||
SearchFilter::__construct($fullName, $value);
|
parent::__construct($fullName, $value, $modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function apply(DataQuery $query) {
|
public function apply(DataQuery $query) {
|
||||||
$this->model = $query->applyRelation($this->relation);
|
$values = $this->getValue();
|
||||||
return $query->where(sprintf(
|
$filter = new PartialMatchFilter($this->getFullName(), $values, $this->getModifiers());
|
||||||
"LOCATE('%s', %s) != 0",
|
return $filter->apply($query);
|
||||||
Convert::raw2sql($this->getValue()),
|
}
|
||||||
$this->getDbName()
|
|
||||||
));
|
protected function applyOne(DataQuery $query) {
|
||||||
|
/* NO OP */
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exclude(DataQuery $query) {
|
||||||
|
$values = $this->getValue();
|
||||||
|
$filter = new PartialMatchFilter($this->getFullName(), $values, $this->getModifiers());
|
||||||
|
return $filter->exclude($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
|
/* NO OP */
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isEmpty() {
|
public function isEmpty() {
|
||||||
return $this->getValue() == null || $this->getValue() == '';
|
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ class WithinRangeFilter extends SearchFilter {
|
|||||||
$this->max = $max;
|
$this->max = $max;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function apply(DataQuery $query) {
|
protected function applyOne(DataQuery $query) {
|
||||||
$this->model = $query->applyRelation($this->relation);
|
$this->model = $query->applyRelation($this->relation);
|
||||||
return $query->where(sprintf(
|
return $query->where(sprintf(
|
||||||
"%s >= '%s' AND %s <= '%s'",
|
"%s >= '%s' AND %s <= '%s'",
|
||||||
@ -36,5 +36,14 @@ class WithinRangeFilter extends SearchFilter {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function excludeOne(DataQuery $query) {
|
||||||
|
$this->model = $query->applyRelation($this->relation);
|
||||||
|
return $query->where(sprintf(
|
||||||
|
"%s < '%s' OR %s > '%s'",
|
||||||
|
$this->getDbName(),
|
||||||
|
Convert::raw2sql($this->min),
|
||||||
|
$this->getDbName(),
|
||||||
|
Convert::raw2sql($this->max)
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,10 +442,21 @@ class DataListTest extends SapphireTest {
|
|||||||
$list = $list->filter(array(
|
$list = $list->filter(array(
|
||||||
'Name'=>array('Bob','Phil'),
|
'Name'=>array('Bob','Phil'),
|
||||||
'TeamID'=>array($this->idFromFixture('DataObjectTest_Team', 'team1'))));
|
'TeamID'=>array($this->idFromFixture('DataObjectTest_Team', 'team1'))));
|
||||||
$this->assertEquals(1, $list->count(), 'There should be one comments');
|
$this->assertEquals(1, $list->count(), 'There should be one comment');
|
||||||
$this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
|
$this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFilterWithModifiers() {
|
||||||
|
$list = DataObjectTest_TeamComment::get();
|
||||||
|
$nocaseList = $list->filter('Name:nocase', 'bob');
|
||||||
|
$this->assertEquals(1, $nocaseList->count(), 'There should be one comment');
|
||||||
|
$caseList = $list->filter('Name:case', 'bob');
|
||||||
|
$this->assertEquals(0, $caseList->count(), 'There should be no comments');
|
||||||
|
$gtList = $list->filter('TeamID:GreaterThan:not',
|
||||||
|
$this->idFromFixture('DataObjectTest_Team', 'team1'));
|
||||||
|
$this->assertEquals(2, $gtList->count());
|
||||||
|
}
|
||||||
|
|
||||||
public function testFilterAndExcludeById() {
|
public function testFilterAndExcludeById() {
|
||||||
$id = $this->idFromFixture('DataObjectTest_SubTeam', 'subteam1');
|
$id = $this->idFromFixture('DataObjectTest_SubTeam', 'subteam1');
|
||||||
$list = DataObjectTest_SubTeam::get()->filter('ID', $id);
|
$list = DataObjectTest_SubTeam::get()->filter('ID', $id);
|
||||||
@ -501,7 +512,7 @@ class DataListTest extends SapphireTest {
|
|||||||
*/
|
*/
|
||||||
public function testMultipleExclude() {
|
public function testMultipleExclude() {
|
||||||
$list = DataObjectTest_TeamComment::get();
|
$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());
|
$this->assertEquals(2, $list->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,10 +525,18 @@ class DataListTest extends SapphireTest {
|
|||||||
$list = $list->exclude('Name', 'Bob');
|
$list = $list->exclude('Name', 'Bob');
|
||||||
|
|
||||||
$this->assertContains(
|
$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());
|
$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
|
* $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob with Age 21 or 43
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user