diff --git a/application/controllers/FilterController.php b/application/controllers/FilterController.php
index ed9761b70..3754e4070 100644
--- a/application/controllers/FilterController.php
+++ b/application/controllers/FilterController.php
@@ -71,13 +71,14 @@ class FilterController extends ActionController
$this->setupQueries();
$this->view->form->setRequest($this->getRequest());
-
if ($this->view->form->isSubmittedAndValid()) {
$tree = $this->registry->createQueryTreeForFilter($this->view->form->getValue('query'));
$this->view->tree = new \Icinga\Web\Widget\FilterBadgeRenderer($tree);
-
+ $view = \Icinga\Module\Monitoring\DataView\HostAndServiceStatus::fromRequest($this->getRequest());
+ $cv = new \Icinga\Module\Monitoring\Filter\Backend\IdoQueryConverter($view);
+ $this->view->sqlString = $cv->treeToSql($tree);
+ $this->view->params = $cv->getParams();
} else if ($this->getRequest()->getHeader('accept') == 'application/json') {
-
$this->getResponse()->setHeader('Content-Type', 'application/json');
$this->_helper->json($this->parse($this->getRequest()->getParam('query', '')));
}
diff --git a/application/views/scripts/filter/index.phtml b/application/views/scripts/filter/index.phtml
index 1bcdb6a43..5e6a63d37 100644
--- a/application/views/scripts/filter/index.phtml
+++ b/application/views/scripts/filter/index.phtml
@@ -4,4 +4,8 @@ echo $this->form;
if ($this->tree) {
echo $this->tree->render($this);
+ echo '
';
+ echo $this->sqlString;
+ echo '
';
+ print_r($this->params);
}
\ No newline at end of file
diff --git a/library/Icinga/Data/Filterable.php b/library/Icinga/Data/Filterable.php
new file mode 100644
index 000000000..376384ad2
--- /dev/null
+++ b/library/Icinga/Data/Filterable.php
@@ -0,0 +1,38 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+
+namespace Icinga\Data;
+
+
+interface Filterable
+{
+ public function isValidFilterTarget($targetOrColumn);
+ public function resolveFilterTarget($targetOrColumn);
+
+}
\ No newline at end of file
diff --git a/library/Icinga/Filter/Domain.php b/library/Icinga/Filter/Domain.php
index e5e5ca197..bbfea2b4f 100644
--- a/library/Icinga/Filter/Domain.php
+++ b/library/Icinga/Filter/Domain.php
@@ -134,9 +134,6 @@ class Domain extends QueryProposer
foreach ($this->attributes as $attributeHandler) {
if ($attributeHandler->isValidQuery($query)) {
$node = $attributeHandler->convertToTreeNode($query);
- if ($node) {
- $node->context = $this->label;
- }
return $node;
}
}
diff --git a/library/Icinga/Filter/Query/Node.php b/library/Icinga/Filter/Query/Node.php
index 92c3c9475..ab32f478c 100644
--- a/library/Icinga/Filter/Query/Node.php
+++ b/library/Icinga/Filter/Query/Node.php
@@ -45,6 +45,7 @@ class Node
const OPERATOR_GREATER_EQ = '>=';
const OPERATOR_LESS_EQ = '<=';
+ const CONTEXT_TIMESTRING = 'timestring';
/**
* Array containing all possible operators
*
@@ -90,6 +91,13 @@ class Node
*/
public $right;
+ /**
+ * Additional information for this node (like that it represents a date)
+ *
+ * @var mixed
+ */
+ public $context;
+
/**
* Factory method for creating operator nodes
*
diff --git a/library/Icinga/Filter/Type/TimeRangeSpecifier.php b/library/Icinga/Filter/Type/TimeRangeSpecifier.php
index 5b511160c..1a0bbab22 100644
--- a/library/Icinga/Filter/Type/TimeRangeSpecifier.php
+++ b/library/Icinga/Filter/Type/TimeRangeSpecifier.php
@@ -166,7 +166,9 @@ class TimeRangeSpecifier extends FilterType
if ($operator === null || $timeQuery === null) {
return null;
}
- return Node::createOperatorNode($operator, $leftOperand, $timeQuery);
+ $node = Node::createOperatorNode($operator, $leftOperand, $timeQuery);
+ $node->context = Node::CONTEXT_TIMESTRING;
+ return $node;
}
/**
diff --git a/library/Icinga/Web/Widget/FilterBadgeRenderer.php b/library/Icinga/Web/Widget/FilterBadgeRenderer.php
new file mode 100644
index 000000000..02c27bdd5
--- /dev/null
+++ b/library/Icinga/Web/Widget/FilterBadgeRenderer.php
@@ -0,0 +1,81 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+
+namespace Icinga\Web\Widget;
+
+
+use Icinga\Filter\Query\Tree;
+use Icinga\Filter\Query\Node;
+use Zend_View_Abstract;
+
+class FilterBadgeRenderer implements Widget
+{
+ private $tree;
+ private $conjunctionCellar = '';
+
+
+ public function __construct(Tree $tree)
+ {
+ $this->tree = $tree;
+ }
+
+ private function nodeToBadge(Node $node)
+ {
+ if ($node->type === Node::TYPE_OPERATOR) {
+ return ' '
+ . $this->conjunctionCellar . ' '
+ . ucfirst($node->left) . ' '
+ . $node->operator . ' '
+ . $node->right . '';
+ }
+ $result = '';
+ $result .= $this->nodeToBadge($node->left);
+ $this->conjunctionCellar = $node->type;
+ $result .= $this->nodeToBadge($node->right);
+ return $result;
+
+ }
+
+
+
+ /**
+ * Renders this widget via the given view and returns the
+ * HTML as a string
+ *
+ * @param \Zend_View_Abstract $view
+ * @return string
+ */
+ public function render(Zend_View_Abstract $view)
+ {
+ if ($this->tree->root == null) {
+ return '';
+ }
+ return $this->nodeToBadge($this->tree->root);
+ }
+}
\ No newline at end of file
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/AbstractQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/AbstractQuery.php
index 411b2e539..8bb47a051 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/AbstractQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/AbstractQuery.php
@@ -232,7 +232,7 @@ abstract class AbstractQuery extends Query
return array_key_exists($alias, $this->idxAliasColumn);
}
- protected function aliasToColumnName($alias)
+ public function aliasToColumnName($alias)
{
return $this->idxAliasColumn[$alias];
}
@@ -402,4 +402,15 @@ abstract class AbstractQuery extends Query
return $filter;
}
+
+ public function getMappedColumn($name)
+ {
+ foreach ($this->columnMap as $column => $results) {
+ if (isset($results[$name])) {
+ return $results[$name];
+ }
+ }
+
+ return null;
+ }
}
diff --git a/modules/monitoring/library/Monitoring/DataView/DataView.php b/modules/monitoring/library/Monitoring/DataView/DataView.php
index 3d6b2a48f..718170ee1 100644
--- a/modules/monitoring/library/Monitoring/DataView/DataView.php
+++ b/modules/monitoring/library/Monitoring/DataView/DataView.php
@@ -150,7 +150,7 @@ abstract class DataView
*
* @return bool
*/
- protected function isValidFilterColumn($column)
+ public function isValidFilterColumn($column)
{
return in_array($column, $this->getColumns()) || in_array($column, $this->getFilterColumns());
}
diff --git a/modules/monitoring/library/Monitoring/DataView/HostAndServiceStatus.php b/modules/monitoring/library/Monitoring/DataView/HostAndServiceStatus.php
index cd9f073ec..bb6c0d6f5 100644
--- a/modules/monitoring/library/Monitoring/DataView/HostAndServiceStatus.php
+++ b/modules/monitoring/library/Monitoring/DataView/HostAndServiceStatus.php
@@ -121,7 +121,7 @@ class HostAndServiceStatus extends DataView
return array('hostgroups', 'servicegroups', 'service_problems');
}
- protected function isValidFilterColumn($column)
+ public function isValidFilterColumn($column)
{
if ($column[0] === '_'
&& preg_match('/^_(?:host|service)_/', $column)
diff --git a/modules/monitoring/library/Monitoring/Filter/Backend/IdoQueryConverter.php b/modules/monitoring/library/Monitoring/Filter/Backend/IdoQueryConverter.php
index 134b5aa16..36fa8319f 100644
--- a/modules/monitoring/library/Monitoring/Filter/Backend/IdoQueryConverter.php
+++ b/modules/monitoring/library/Monitoring/Filter/Backend/IdoQueryConverter.php
@@ -31,15 +31,90 @@ namespace Icinga\Module\Monitoring\Filter\Backend;
use Icinga\Filter\Query\Tree;
+use Icinga\Filter\Query\Node;
+use Icinga\Module\Monitoring\DataView\DataView;
+
class IdoQueryConverter
{
+ private $view;
+ private $query;
+ private $params = array();
+ public function getParams()
+ {
+ return $this->params;
+ }
+
+ public function __construct(DataView $view, array $initialParams = array())
+ {
+ $this->view = $view;
+ $this->query = $this->view->getQuery();
+ $this->params = $initialParams;
+ }
+
+ private function getSqlOperator($operator)
+ {
+ switch($operator) {
+ case Node::OPERATOR_EQUALS:
+ return 'LIKE';
+ case Node::OPERATOR_EQUALS_NOT:
+ return 'NOT LIKE';
+ default:
+ return $operator;
+ }
+ }
+
+ private function nodeToSqlQuery(Node $node)
+ {
+ if ($node->type !== Node::TYPE_OPERATOR) {
+ return $this->parseConjunctionNode($node);
+ } else {
+ return $this->parseOperatorNode($node);
+ }
+ }
+
+ private function parseConjunctionNode(Node $node)
+ {
+ $queryString = '';
+ $leftQuery = $this->nodeToSqlQuery($node->left);
+ $rightQuery = $this->nodeToSqlQuery($node->right);
+ if ($leftQuery != '') {
+ $queryString .= $leftQuery . ' ';
+ }
+ if ($rightQuery != '') {
+ $queryString .= (($queryString !== '') ? $node->type . ' ' : ' ') . $rightQuery;
+ }
+ return $queryString;
+ }
+
+ private function parseOperatorNode(Node $node)
+ {
+ if (!$this->view->isValidFilterColumn($node->left) && $this->query->getMappedColumn($node->left)) {
+ return '';
+ }
+ $queryString = $this->query->getMappedColumn($node->left);
+ $queryString .= ' ' . (is_integer($node->right) ? $node->operator : $this->getSqlOperator($node->operator));
+ $queryString .= ' ? ';
+ $this->params[] = $this->getParameterValue($node);
+ return $queryString;
+ }
+
+ private function getParameterValue(Node $node) {
+
+ switch($node->context) {
+ case Node::CONTEXT_TIMESTRING:
+ return strtotime($node->right);
+ default:
+ return $node->right;
+ }
+ }
public function treeToSql(Tree $tree)
{
- if ($tree->root = null) {
+ if ($tree->root == null) {
return '';
}
+ return $this->nodeToSqlQuery($tree->root);
}
}
\ No newline at end of file