connection = $connection; $this->query = $connection->query($this->getQueryName(), $columns); } /** * Return a iterator for all rows of the result set * * @return IdoQuery */ public function getIterator() { return $this->getQuery(); } /** * Return the current position of the result set's iterator * * @return int */ public function getIteratorPosition() { return $this->query->getIteratorPosition(); } /** * Get the query name this data view relies on * * By default this is this class' name without its namespace * * @return string */ public static function getQueryName() { $tableName = explode('\\', get_called_class()); $tableName = end($tableName); return $tableName; } public function where($condition, $value = null) { $this->query->where($condition, $value); return $this; } public function dump() { if (! $this->isSorted) { $this->order(); } return $this->query->dump(); } /** * Retrieve columns provided by this view * * @return array */ abstract public function getColumns(); /** * Create view from request * * @param Request $request * @param array $columns * * @return static * @deprecated Use $backend->select()->from($viewName) instead */ public static function fromRequest($request, array $columns = null) { $view = new static(MonitoringBackend::instance($request->getParam('backend')), $columns); $view->applyUrlFilter($request); return $view; } protected function getHookedColumns() { $columns = array(); foreach (Hook::all('monitoring/dataviewExtension') as $hook) { foreach ($hook->getAdditionalQueryColumns($this->getQueryName()) as $col) { $columns[] = $col; } } return $columns; } // TODO: This is not the right place for this, move it away protected function applyUrlFilter($request = null) { $url = Url::fromRequest(); $limit = $url->shift('limit'); $sort = $url->shift('sort'); $dir = $url->shift('dir'); $page = $url->shift('page'); $format = $url->shift('format'); $view = $url->shift('showCompact'); $view = $url->shift('backend'); foreach ($url->getParams() as $k => $v) { $this->where($k, $v); } if ($sort) { $this->order($sort, $dir); } } /** * Create view from params * * @param array $params * @param array $columns * * @return static */ public static function fromParams(array $params, array $columns = null) { $view = new static(MonitoringBackend::instance($params['backend']), $columns); foreach ($params as $key => $value) { if ($view->isValidFilterTarget($key)) { $view->where($key, $value); } } if (isset($params['sort'])) { $order = isset($params['order']) ? $params['order'] : null; if ($order !== null) { if (strtolower($order) === 'desc') { $order = self::SORT_DESC; } else { $order = self::SORT_ASC; } } $view->sort($params['sort'], $order); } return $view; } /** * Check whether the given column is a valid filter column * * @param string $column * * @return bool */ public function isValidFilterTarget($column) { // Customvar if ($column[0] === '_' && preg_match('/^_(?:host|service)_/i', $column)) { return true; } return in_array($column, $this->getColumns()) || in_array($column, $this->getStaticFilterColumns()); } /** * Return all filter columns with their optional label as key * * This will merge the results of self::getColumns(), self::getStaticFilterColumns() and * self::getDynamicFilterColumns() *once*. (i.e. subsequent calls of this function will * return the same result.) * * @return array */ public function getFilterColumns() { if ($this->filterColumns === null) { $columns = array_merge( $this->getColumns(), $this->getStaticFilterColumns(), $this->getDynamicFilterColumns() ); $this->filterColumns = array(); foreach ($columns as $label => $column) { if (is_int($label)) { $label = ucwords(str_replace('_', ' ', $column)); } if ($this->query->isCaseInsensitive($column)) { $label .= ' ' . t('(Case insensitive)'); } $this->filterColumns[$label] = $column; } } return $this->filterColumns; } /** * Return all static filter columns * * @return array */ public function getStaticFilterColumns() { return array(); } /** * Return all dynamic filter columns such as custom variables * * @return array */ public function getDynamicFilterColumns() { $columns = array(); if (! $this->query->allowsCustomVars()) { return $columns; } $query = MonitoringBackend::instance() ->select() ->from('customvar', array('varname', 'object_type')) ->where('is_json', 0) ->where('object_type_id', array(1, 2)) ->getQuery()->group(array('varname', 'object_type')); foreach ($query as $row) { if ($row->object_type === 'host') { $label = t('Host') . ' ' . ucwords(str_replace('_', ' ', $row->varname)); $columns[$label] = '_host_' . $row->varname; } else { // $row->object_type === 'service' $label = t('Service') . ' ' . ucwords(str_replace('_', ' ', $row->varname)); $columns[$label] = '_service_' . $row->varname; } } return $columns; } /** * Return the current filter * * @return Filter */ public function getFilter() { return $this->query->getFilter(); } /** * Return a pivot table for the given columns based on the current query * * @param string $xAxisColumn The column to use for the x axis * @param string $yAxisColumn The column to use for the y axis * @param Filter $xAxisFilter The filter to apply on a query for the x axis * @param Filter $yAxisFilter The filter to apply on a query for the y axis * * @return PivotTable */ public function pivot($xAxisColumn, $yAxisColumn, Filter $xAxisFilter = null, Filter $yAxisFilter = null) { $pivot = new PivotTable($this->query, $xAxisColumn, $yAxisColumn); return $pivot->setXAxisFilter($xAxisFilter)->setYAxisFilter($yAxisFilter); } /** * Sort the rows, according to the specified sort column and order * * @param string $column Sort column * @param string $order Sort order, one of the SORT_ constants * * @return $this * @throws QueryException If the sort column is not allowed * @see DataView::SORT_ASC * @see DataView::SORT_DESC * @deprecated Use DataView::order() instead */ public function sort($column = null, $order = null) { $sortRules = $this->getSortRules(); if ($column === null) { // Use first available sort rule as default if (empty($sortRules)) { return $this; } $sortColumns = reset($sortRules); if (! isset($sortColumns['columns'])) { $sortColumns['columns'] = array(key($sortRules)); } } else { if (isset($sortRules[$column])) { $sortColumns = $sortRules[$column]; if (! isset($sortColumns['columns'])) { $sortColumns['columns'] = array($column); } } else { $sortColumns = array( 'columns' => array($column), 'order' => $order ); }; } $order = $order === null ? (isset($sortColumns['order']) ? $sortColumns['order'] : static::SORT_ASC) : $order; $order = (strtoupper($order) === static::SORT_ASC) ? 'ASC' : 'DESC'; foreach ($sortColumns['columns'] as $column) { list($column, $direction) = $this->query->splitOrder($column); if (! $this->isValidFilterTarget($column)) { throw new QueryException( mt('monitoring', 'The sort column "%s" is not allowed in "%s".'), $column, get_class($this) ); } $this->query->order($column, $direction !== null ? $direction : $order); } $this->isSorted = true; return $this; } /** * Retrieve default sorting rules for particular columns. These involve sort order and potential additional to sort * * @return array */ public function getSortRules() { return array(); } /** * Sort result set either by the given column (and direction) or the sort defaults * * @param string $column * @param string $direction * * @return $this */ public function order($column = null, $direction = null) { return $this->sort($column, $direction); } /** * Whether an order is set * * @return bool */ public function hasOrder() { return $this->query->hasOrder(); } /** * Get the order if any * * @return array|null */ public function getOrder() { return $this->query->getOrder(); } public function getMappedField($field) { return $this->query->getMappedField($field); } /** * Return the query which was created in the constructor * * @return \Icinga\Data\SimpleQuery */ public function getQuery() { if (! $this->isSorted) { $this->order(); } return $this->query; } public function applyFilter(Filter $filter) { $this->validateFilterColumns($filter); return $this->addFilter($filter); } /** * 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); } } } public function clearFilter() { $this->query->clearFilter(); return $this; } /** * @deprecated(EL): Only use DataView::applyFilter() for applying filter because all other functions are missing * column validation. Filter::matchAny() for the IdoQuery (or the DbQuery or the SimpleQuery I didn't have a look) * is required for the filter to work properly. */ public function setFilter(Filter $filter) { $this->query->setFilter($filter); return $this; } /** * Get the view's search columns * * @return string[] */ public function getSearchColumns() { return array(); } /** * @deprecated(EL): Only use DataView::applyFilter() for applying filter because all other functions are missing * column validation. */ public function addFilter(Filter $filter) { $this->query->addFilter($filter); return $this; } /** * Count result set * * @return int */ public function count() { return $this->query->count(); } /** * Set whether the query should peek ahead for more results * * Enabling this causes the current query limit to be increased by one. The potential extra row being yielded will * be removed from the result set. Note that this only applies when fetching multiple results of limited queries. * * @return $this */ public function peekAhead($state = true) { $this->query->peekAhead($state); return $this; } /** * Return whether the query did not yield all available results * * @return bool */ public function hasMore() { return $this->query->hasMore(); } /** * Return whether this query will or has yielded any result * * @return bool */ public function hasResult() { return $this->query->hasResult(); } /** * Set a limit count and offset * * @param int $count Number of rows to return * @param int $offset Start returning after this many rows * * @return self */ public function limit($count = null, $offset = null) { $this->query->limit($count, $offset); return $this; } /** * Whether a limit is set * * @return bool */ public function hasLimit() { return $this->query->hasLimit(); } /** * Get the limit if any * * @return int|null */ public function getLimit() { return $this->query->getLimit(); } /** * Whether an offset is set * * @return bool */ public function hasOffset() { return $this->query->hasOffset(); } /** * Get the offset if any * * @return int|null */ public function getOffset() { return $this->query->getOffset(); } /** * Retrieve an array containing all rows of the result set * * @return array */ public function fetchAll() { return $this->getQuery()->fetchAll(); } /** * Fetch the first row of the result set * * @return mixed */ public function fetchRow() { return $this->getQuery()->fetchRow(); } /** * Fetch the first column of all rows of the result set as an array * * @return array */ public function fetchColumn() { return $this->getQuery()->fetchColumn(); } /** * Fetch the first column of the first row of the result set * * @return string */ public function fetchOne() { return $this->getQuery()->fetchOne(); } /** * Fetch all rows of the result set as an array of key-value pairs * * The first column is the key, the second column is the value. * * @return array */ public function fetchPairs() { return $this->getQuery()->fetchPairs(); } }