protected function selectColumn(Filter $filter = null) { $active = $filter === null ? null : $filter->getColumn(); if ($this->cachedColumnSelect === null && $this->query === null) { return sprintf('<input type="text" name="%s" value="%s" />', $this->elementId('column', $filter), $this->view()->escape($active)); } if ($this->cachedColumnSelect === null && $this->query instanceof FilterColumns) { $this->cachedColumnSelect = $this->arrayForSelect($this->query->getFilterColumns(), true); asort($this->cachedColumnSelect); } elseif ($this->cachedColumnSelect === null) { throw new ProgrammingError('No columns set nor does the query provide any'); } $cols = $this->cachedColumnSelect; if ($active && !isset($cols[$active])) { $cols[$active] = str_replace('_', ' ', ucfirst(ltrim($active, '_'))); } return $this->select($this->elementId('column', $filter), $cols, $active); }
protected function validateFilterColumns(Filter $filter) { if ($filter->isExpression()) { $valid = false; foreach ($this->allowedColumns as $column) { if (is_callable($column)) { if (call_user_func($column, $filter->getColumn())) { $valid = true; break; } } elseif ($filter->getColumn() === $column) { $valid = true; break; } } if (!$valid) { throw new QueryException('Invalid filter column provided: %s', $filter->getColumn()); } } else { foreach ($filter->filters() as $subFilter) { $this->validateFilterColumns($subFilter); } } }
protected function requireFilterColumns(Filter $filter) { if ($filter instanceof FilterExpression) { if ($filter->getExpression() === '*') { return; // Wildcard only filters are ignored so stop early here to avoid joining a table for nothing } $alias = $filter->getColumn(); $this->requireColumn($alias); if ($this->isCustomvar($alias)) { $column = $this->getCustomvarColumnName($alias); } else { $column = $this->aliasToColumnName($alias); } if (isset($this->columnsWithoutCollation[$alias])) { $expression = $filter->getExpression(); if (is_array($expression)) { $filter->setExpression(array_map('strtolower', $expression)); } else { $filter->setExpression(strtolower($expression)); } } $filter->setColumn($column); } else { foreach ($filter->filters() as $filter) { $this->requireFilterColumns($filter); } } }
/** * Render and return the given filter expression * * @param Filter $filter * * @return string */ protected function renderFilterExpression(Filter $filter) { $column = $filter->getColumn(); $sign = $filter->getSign(); $value = $filter->getExpression(); if (is_array($value) && $sign === '=') { // TODO: Should we support this? Doesn't work for blub* return $column . ' IN (' . $this->dbAdapter->quote($value) . ')'; } elseif ($sign === '=' && strpos($value, '*') !== false) { return $column . ' LIKE ' . $this->dbAdapter->quote(preg_replace('~\\*~', '%', $value)); } elseif ($sign === '!=' && strpos($value, '*') !== false) { return $column . ' NOT LIKE ' . $this->dbAdapter->quote(preg_replace('~\\*~', '%', $value)); } else { return $column . ' ' . $sign . ' ' . $this->dbAdapter->quote($value); } }
/** * Recurse the given filter and ensure that any string conversion is case-insensitive * * @param Filter $filter */ protected function lowerColumnsWithoutCollation(Filter $filter) { if ($filter instanceof FilterExpression) { if (in_array($filter->getColumn(), $this->columnsWithoutCollation) && strpos($filter->getColumn(), 'LOWER') !== 0) { $filter->setColumn('LOWER(' . $filter->getColumn() . ')'); $expression = $filter->getExpression(); if (is_array($expression)) { $filter->setExpression(array_map('strtolower', $expression)); } else { $filter->setExpression(strtolower($expression)); } } } else { foreach ($filter->filters() as $chainedFilter) { $this->lowerColumnsWithoutCollation($chainedFilter); } } }
/** * Validates recursive the Filter columns against the isValidFilterTarget() method * * @param Filter $filter * * @throws \Icinga\Data\Filter\FilterException */ public function validateFilterColumns(Filter $filter) { if ($filter instanceof FilterMatch) { if (!$this->isValidFilterTarget($filter->getColumn())) { throw new QueryException(mt('monitoring', 'The filter column "%s" is not allowed here.'), $filter->getColumn()); } } if (method_exists($filter, 'filters')) { foreach ($filter->filters() as $filter) { $this->validateFilterColumns($filter); } } }
/** * Render and return the given filter expression * * @param Filter $filter * * @return string */ protected function renderFilterExpression(Filter $filter) { $column = $filter->getColumn(); $sign = $filter->getSign(); $value = $filter->getExpression(); if (is_array($value)) { if ($sign === '=') { return $column . ' IN (' . $this->dbAdapter->quote($value) . ')'; } elseif ($sign === '!=') { return sprintf('(%1$s NOT IN (%2$s) OR %1$s IS NULL)', $column, $this->dbAdapter->quote($value)); } throw new ProgrammingError('Unable to render array expressions with operators other than equal or not equal'); } elseif ($sign === '=' && strpos($value, '*') !== false) { if ($value === '*') { // We'll ignore such filters as it prevents index usage and because "*" means anything, so whether we're // using a real column with a valid comparison here or just an expression which can only be evaluated to // true makes no difference, except for performance reasons... return new Zend_Db_Expr('TRUE'); } return $column . ' LIKE ' . $this->dbAdapter->quote(preg_replace('~\\*~', '%', $value)); } elseif ($sign === '!=' && strpos($value, '*') !== false) { if ($value === '*') { // We'll ignore such filters as it prevents index usage and because "*" means nothing, so whether we're // using a real column with a valid comparison here or just an expression which cannot be evaluated to // true makes no difference, except for performance reasons... return new Zend_Db_Expr('FALSE'); } return sprintf('(%1$s NOT LIKE %2$s OR %1$s IS NULL)', $column, $this->dbAdapter->quote(preg_replace('~\\*~', '%', $value))); } elseif ($sign === '!=') { return sprintf('(%1$s != %2$s OR %1$s IS NULL)', $column, $this->dbAdapter->quote($value)); } else { return sprintf('%s %s %s', $column, $sign, $this->dbAdapter->quote($value)); } }
/** * Render and return the given filter expression * * @param Filter $filter * * @return string */ protected function renderFilterExpression(Filter $filter) { $column = $filter->getColumn(); $sign = $filter->getSign(); $value = $filter->getExpression(); if (is_array($value)) { if ($sign === '=') { return $column . ' IN (' . $this->dbAdapter->quote($value) . ')'; } elseif ($sign === '!=') { return $column . ' NOT IN (' . $this->dbAdapter->quote($value) . ')'; } throw new ProgrammingError('Unable to render array expressions with operators other than equal or not equal'); } elseif ($sign === '=' && strpos($value, '*') !== false) { if ($value === '*') { // We'll ignore such filters as it prevents index usage and because "*" means anything, anything means // all whereas all means that whether we use a filter to match anything or no filter at all makes no // difference, except for performance reasons... return ''; } return $column . ' LIKE ' . $this->dbAdapter->quote(preg_replace('~\\*~', '%', $value)); } elseif ($sign === '!=' && strpos($value, '*') !== false) { if ($value === '*') { // We'll ignore such filters as it prevents index usage and because "*" means nothing, so whether we're // using a real column with a valid comparison here or just an expression which cannot be evaluated to // true makes no difference, except for performance reasons... return $this->dbAdapter->quote(0); } return $column . ' NOT LIKE ' . $this->dbAdapter->quote(preg_replace('~\\*~', '%', $value)); } else { return $column . ' ' . $sign . ' ' . $this->dbAdapter->quote($value); } }
protected function selectColumn(Filter $filter = null) { $active = $filter === null ? null : $filter->getColumn(); if ($this->query === null) { return sprintf('<input type="text" name="%s" value="%s" />', $this->elementId('column', $filter), $this->view()->escape($active)); } if ($this->cachedColumnSelect === null) { $this->cachedColumnSelect = $this->arrayForSelect($this->query->getColumns()); asort($this->cachedColumnSelect); } $cols = $this->cachedColumnSelect; $seen = false; foreach ($cols as $k => &$v) { $v = str_replace('_', ' ', ucfirst($v)); if ($k === $active) { $seen = true; } } if (!$seen) { $cols[$active] = str_replace('_', ' ', ucfirst(ltrim($active, '_'))); } return $this->select($this->elementId('column', $filter), $cols, $active); }
/** * Render and return the given filter expression. * * This handles non-chain parts of the Filter. * * @param Filter $filter * @return string * @throws ProgrammingError */ protected function renderFilterExpression(Filter $filter) { /** @var FilterMatch $filter (just for resolving) */ $column = $filter->getColumn(); $sign = $filter->getSign(); $value = $filter->getExpression(); // array or lists if (is_array($value)) { if ($sign === '=' || $sign === '!=') { return array('query_string' => array('default_field' => $column, 'query' => '"' . join('" "', $value) . '"')); } throw new ProgrammingError('Unable to render array expressions with operators other than equal or not equal'); } elseif (strpos($value, '*') !== false) { if ($value === '*') { // (sign =) We'll ignore such filters as it prevents index usage and because "*" means anything, anything means // all whereas all means that whether we use a filter to match anything or no filter at all makes no // difference, except for performance reasons... // (sign !=) We'll ignore such filters as it prevents index usage and because "*" means nothing, so whether we're // using a real column with a valid comparison here or just an expression which cannot be evaluated to // true makes no difference, except for performance reasons... return null; } if ($sign === '=' || $sign === '!=') { return array('query_string' => array('default_field' => $column, 'query' => $value, 'analyze_wildcard' => true)); } throw new ProgrammingError('Unable to render expressions wildcards other than equal or not equal'); } else { // simple comparison via match if ($sign === '=' || $sign === '!=') { return array('match' => array($column => $value)); } elseif (preg_match('/^[<>]=?$/', $sign)) { $param_map = array('>' => 'gt', '<' => 'lt', '>=' => 'gte', '<=' => 'lte'); return array('range' => array($column => array($param_map[$sign] => $value))); } throw new ProgrammingError('Unable to render string expressions with operators other than equality and range'); } }
public function addFilter(Filter $filter) { // TODO: This should be considered a quick fix only. // Drop this entirely once support for Icinga\Data\Filter is available if ($filter->isExpression()) { $this->where($filter->getColumn(), $filter->getExpression()); } elseif ($filter->isChain()) { foreach ($filter->filters() as $chainOrExpression) { $this->addFilter($chainOrExpression); } } }