public function has($relation, $operator = '>=', $value = 1, $replace = true)
{
// Make sure the Filters behaviour is added to the model
if (!$this->behavioursDispatcher->hasObserverClass('FOF30\\Model\\DataModel\\Behaviour\\RelationFilters')) {
$this->addBehaviour('relationFilters');
}
$filter = array('relation' => $relation, 'method' => $operator, 'operator' => $operator, 'value' => $value);
// Handle method aliases
switch ($operator) {
case '<>':
$filter['method'] = 'search';
$filter['operator'] = '!=';
break;
case 'lt':
$filter['method'] = 'search';
$filter['operator'] = '<';
break;
case 'le':
$filter['method'] = 'search';
$filter['operator'] = '<=';
break;
case 'gt':
$filter['method'] = 'search';
$filter['operator'] = '>';
break;
case 'ge':
$filter['method'] = 'search';
$filter['operator'] = '>=';
break;
case 'eq':
$filter['method'] = 'search';
$filter['operator'] = '=';
break;
case 'neq':
case 'ne':
$filter['method'] = 'search';
$filter['operator'] = '!=';
break;
case '<':
case '!<':
case '<=':
case '!<=':
case '>':
case '!>':
case '>=':
case '!>=':
case '!=':
case '=':
$filter['method'] = 'search';
$filter['operator'] = $operator;
break;
case 'like':
case '~':
case '%':
$filter['method'] = 'partial';
break;
case '==':
case '=[]':
case '=()':
case 'in':
$filter['method'] = 'exact';
break;
case '()':
case '[]':
case '[)':
case '(]':
$filter['method'] = 'between';
break;
case ')(':
case ')[':
case '](':
case '][':
$filter['method'] = 'outside';
break;
case '*=':
case 'every':
$filter['method'] = 'interval';
break;
case '?=':
$filter['method'] = 'search';
break;
case 'callback':
$filter['method'] = 'callback';
$filter['operator'] = 'callback';
break;
default:
throw new InvalidSearchMethod('Operator ' . $operator . ' is unsupported');
break;
}
// Handle real methods
switch ($filter['method']) {
case 'between':
case 'outside':
if (is_array($value) && count($value) > 1) {
// Get the from and to values from the $value array
if (isset($value['from']) && isset($value['to'])) {
$filter['from'] = $value['from'];
$filter['to'] = $value['to'];
} else {
$filter['from'] = array_shift($value);
$filter['to'] = array_shift($value);
}
unset($filter['value']);
} else {
// $value is not a from/to array. Treat as = (between) or != (outside)
if (is_array($value)) {
$value = array_shift($value);
}
$filter['operator'] = $filter['method'] == 'between' ? '=' : '!=';
$filter['value'] = $value;
$filter['method'] = 'search';
}
break;
case 'interval':
if (is_array($value) && count($value) > 1) {
// Get the value and interval from the $value array
if (isset($value['value']) && isset($value['interval'])) {
$filter['value'] = $value['value'];
$filter['interval'] = $value['interval'];
} else {
$filter['value'] = array_shift($value);
$filter['interval'] = array_shift($value);
}
} else {
// $value is not a value/interval array. Treat as =
if (is_array($value)) {
$value = array_shift($value);
}
$filter['value'] = $value;
$filter['method'] = 'search';
$filter['operator'] = '=';
}
break;
case 'search':
// We don't have to do anything if the operator is already set
if (isset($filter['operator'])) {
break;
}
if (is_array($value) && count($value) > 1) {
// Get the operator and value from the $value array
if (isset($value['operator']) && isset($value['value'])) {
$filter['operator'] = $value['operator'];
$filter['value'] = $value['value'];
} else {
$filter['operator'] = array_shift($value);
$filter['value'] = array_shift($value);
}
}
break;
case 'callback':
if (!is_callable($filter['value'])) {
$filter['method'] = 'search';
$filter['operator'] = '=';
$filter['value'] = 1;
}
break;
}
if ($replace && !empty($this->relationFilters)) {
foreach ($this->relationFilters as $k => $v) {
if ($v['relation'] == $relation) {
unset($this->relationFilters[$k]);
}
}
}
$this->relationFilters[] = $filter;
return $this;
}