mirror of
https://github.com/Icinga/icingaweb2-module-director.git
synced 2025-07-31 01:34:12 +02:00
FormDataFilter: new implementation for assignments
First prototype
This commit is contained in:
parent
a735df89a0
commit
9349ba0f2a
@ -7,7 +7,6 @@ use Icinga\Module\Director\Web\Form\QuickSubForm;
|
||||
|
||||
class AssignListSubForm extends QuickSubForm
|
||||
{
|
||||
|
||||
protected $object;
|
||||
|
||||
public function setObject($object)
|
||||
@ -16,20 +15,15 @@ class AssignListSubForm extends QuickSubForm
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setValue($value)
|
||||
{
|
||||
var_dump($value);
|
||||
}
|
||||
|
||||
public function setup()
|
||||
{
|
||||
$idx = -1;
|
||||
|
||||
if ($this->object && $this->object->supportsAssignments()) {
|
||||
// $this->setElementValue('assignlist', $object->assignments()->getFormValues());
|
||||
foreach ($this->object->assignments()->getFormValues() as $values) {
|
||||
|
||||
foreach ($this->object->assignments()->getValues() as $values) {
|
||||
$idx++;
|
||||
$sub = new AssignmentSubForm();
|
||||
$sub = $this->loadForm('assignmentSub');
|
||||
$sub->setObject($this->object);
|
||||
$sub->setup();
|
||||
$sub->populate($values);
|
||||
@ -38,7 +32,7 @@ class AssignListSubForm extends QuickSubForm
|
||||
}
|
||||
|
||||
$idx++;
|
||||
$sub = new AssignmentSubForm();
|
||||
$sub = $this->loadForm('assignmentSub');
|
||||
$sub->setObject($this->object);
|
||||
$sub->setup();
|
||||
$this->addSubForm($sub, $idx);
|
||||
@ -48,6 +42,7 @@ class AssignListSubForm extends QuickSubForm
|
||||
'ignore' => true,
|
||||
));
|
||||
$this->getElement('addmore')->setDecorators(array('ViewHelper'));
|
||||
|
||||
}
|
||||
|
||||
public function loadDefaultDecorators()
|
||||
@ -56,7 +51,7 @@ class AssignListSubForm extends QuickSubForm
|
||||
'FormElements',
|
||||
array('HtmlTag', array(
|
||||
'tag' => 'ul',
|
||||
'class' => 'assign-rule'
|
||||
'class' => 'assign-rule required'
|
||||
)),
|
||||
array('Fieldset', array(
|
||||
'legend' => 'Assignment rules',
|
||||
|
@ -24,44 +24,13 @@ class AssignmentSubForm extends QuickSubForm
|
||||
'class' => 'assign-type',
|
||||
'value' => 'assign'
|
||||
));
|
||||
$this->addElement('select', 'property', array(
|
||||
'label' => $this->translate('Property'),
|
||||
'class' => 'assign-property autosubmit',
|
||||
'multiOptions' => $this->optionalEnum(IcingaHost::enumProperties($this->object->getConnection(), 'host.'))
|
||||
));
|
||||
$this->addElement('select', 'operator', array(
|
||||
'label' => $this->translate('Operator'),
|
||||
'multiOptions' => array(
|
||||
'=' => '=',
|
||||
'!=' => '!=',
|
||||
'>' => '>',
|
||||
'>=' => '>=',
|
||||
'<=' => '<=',
|
||||
'<' => '<',
|
||||
),
|
||||
'required' => $this->valueIsEmpty($this->getValue('property')),
|
||||
'value' => '=',
|
||||
'class' => 'assign-operator',
|
||||
|
||||
$this->addElement('dataFilter', 'filter_string', array(
|
||||
'columns' => IcingaHost::enumProperties($this->db)
|
||||
));
|
||||
|
||||
$this->addElement('text', 'expression', array(
|
||||
'label' => $this->translate('Expression'),
|
||||
'placeholder' => $this->translate('Expression'),
|
||||
'class' => 'assign-expression',
|
||||
'required' => !$this->valueIsEmpty($this->getValue('property'))
|
||||
));
|
||||
/*
|
||||
$this->addElement('submit', 'remove', array(
|
||||
'label' => '-',
|
||||
'ignore' => true
|
||||
));
|
||||
$this->addElement('submit', 'add', array(
|
||||
'label' => '+',
|
||||
'ignore' => true
|
||||
));
|
||||
*/
|
||||
foreach ($this->getElements() as $el) {
|
||||
$el->setDecorators(array('ViewHelper'));
|
||||
$el->setDecorators(array('ViewHelper', 'Errors'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,12 +161,12 @@ class IcingaServiceForm extends DirectorObjectForm
|
||||
return $this;
|
||||
}
|
||||
|
||||
$sub = new AssignListSubForm();
|
||||
$sub = $this->loadForm('assignListSub');
|
||||
$sub->setObject($this->getObject());
|
||||
$sub->setup();
|
||||
$sub->setOrder(30);
|
||||
|
||||
$this->addSubForm($sub, 'assignlist');
|
||||
$this->addSubForm($sub, 'assignments');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
479
application/views/helpers/FormDataFilter.php
Normal file
479
application/views/helpers/FormDataFilter.php
Normal file
@ -0,0 +1,479 @@
|
||||
<?php
|
||||
|
||||
use Icinga\Data\Filter\Filter;
|
||||
use Icinga\Data\Filter\FilterChain;
|
||||
use Icinga\Data\Filter\FilterExpression;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Module\Director\Objects\IcingaObject;
|
||||
use Icinga\Module\Director\Objects\IcingaObjectGroup;
|
||||
use Icinga\Module\Director\Web\Form\IconHelper;
|
||||
|
||||
/**
|
||||
* View helper for extensible sets
|
||||
*
|
||||
* Avoid complaints about class names:
|
||||
* @codingStandardsIgnoreStart
|
||||
*/
|
||||
class Zend_View_Helper_FormDataFilter extends Zend_View_Helper_FormElement
|
||||
{
|
||||
private $currentId;
|
||||
|
||||
private $fieldName;
|
||||
|
||||
private $addTo;
|
||||
|
||||
private $cachedColumnSelect;
|
||||
|
||||
private $query;
|
||||
|
||||
/**
|
||||
* Generates an 'extensible set' element.
|
||||
*
|
||||
* @codingStandardsIgnoreEnd
|
||||
*
|
||||
* @param string|array $name If a string, the element name. If an
|
||||
* array, all other parameters are ignored, and the array elements
|
||||
* are used in place of added parameters.
|
||||
*
|
||||
* @param mixed $value The element value.
|
||||
*
|
||||
* @param array $attribs Attributes for the element tag.
|
||||
*
|
||||
* @return string The element XHTML.
|
||||
*/
|
||||
public function formDataFilter($name, $value = null, $attribs = null)
|
||||
{
|
||||
$info = $this->_getInfo($name, $value, $attribs);
|
||||
extract($info); // id, name, value, attribs, options, listsep, disable
|
||||
if (array_key_exists('columns', $attribs)) {
|
||||
$this->setColumns($attribs['columns']);
|
||||
unset($attribs['columns']);
|
||||
}
|
||||
|
||||
if (array_key_exists('addTo', $attribs)) {
|
||||
$this->addTo = $attribs['addTo'];
|
||||
unset($attribs['addTo']);
|
||||
}
|
||||
|
||||
// TODO: check for columns in attribs, preserve & remove them from the
|
||||
// array use attribs? class etc? disabled?
|
||||
// override _getInfo?
|
||||
|
||||
$this->fieldName = $name;
|
||||
// $this->fieldName = $id;
|
||||
if ($value === null) {
|
||||
$value = Filter::matchAll();
|
||||
} elseif (is_string($value)) {
|
||||
$value = Filter::fromQueryString($value);
|
||||
}
|
||||
|
||||
return $this->renderFilter($value);
|
||||
}
|
||||
|
||||
protected function renderFilter(Filter $filter, $level = 0)
|
||||
{
|
||||
if ($level === 0 && $filter->isChain() && $filter->isEmpty()) {
|
||||
return '<ul class="filter-expression filter-root"><li class="active">'
|
||||
. $this->renderNewFilter()
|
||||
. '</li></ul>';
|
||||
}
|
||||
|
||||
if ($filter instanceof FilterChain) {
|
||||
return $this->renderFilterChain($filter, $level);
|
||||
} elseif ($filter instanceof FilterExpression) {
|
||||
return $this->renderFilterExpression($filter, $level);
|
||||
} else {
|
||||
throw new ProgrammingError('Got a Filter being neither expression nor chain');
|
||||
}
|
||||
}
|
||||
|
||||
protected function emptyExpression()
|
||||
{
|
||||
return Filter::expression('', '=', '');
|
||||
}
|
||||
|
||||
protected function renderFilterChain(FilterChain $filter, $level)
|
||||
{
|
||||
$parts = array();
|
||||
foreach ($filter->filters() as $f) {
|
||||
$parts[] = '<li>'
|
||||
. $this->renderFilter($f, $level + 1)
|
||||
. '</li>';
|
||||
}
|
||||
|
||||
if ($this->addTo && $this->addTo == $filter->getId()) {
|
||||
$parts[] = '<li style="background: #ffb">'
|
||||
. $this->renderNewFilter()
|
||||
// . $this->cancelLink()
|
||||
. '</li>';
|
||||
}
|
||||
|
||||
return $this->beginChain($filter) . implode('', $parts) . $this->endChain($filter);
|
||||
}
|
||||
|
||||
protected function beginChain(FilterChain $filter)
|
||||
{
|
||||
$root = $filter->isRootNode() === 0 ? ' class="filter-root"' : '';
|
||||
|
||||
$list = $filter->isEmpty() ? '' : '<ul' . $root . '>' . "\n";
|
||||
|
||||
return '<div class="filter-chain'
|
||||
. '"><span class="handle"> </span>'
|
||||
. $this->selectOperator($filter)
|
||||
. $this->removeLink($filter)
|
||||
. ($filter->count() === 1 ? $this->stripLink($filter) : '')
|
||||
. $this->addLink($filter)
|
||||
. $list;
|
||||
}
|
||||
|
||||
protected function endChain(FilterChain $filter)
|
||||
{
|
||||
$list = $filter->isEmpty() ? '' : "</ul>\n";
|
||||
return $list . "</div>\n";
|
||||
}
|
||||
|
||||
protected function beginExpression(FilterExpression $filter)
|
||||
{
|
||||
$root = $filter->isRootNode() === 0 ? ' filter-root' : '';
|
||||
return '<div class="filter-expression' . $root . '">' . "\n";
|
||||
}
|
||||
|
||||
protected function endExpression(FilterExpression $filter)
|
||||
{
|
||||
return "</div>\n";
|
||||
}
|
||||
|
||||
protected function eventuallyAddTo($html, Filter $filter, $level)
|
||||
{
|
||||
if ($this->addTo && $this->addTo === $filter->getId()) {
|
||||
// $filter->replaceWith(Filter::matchAll(clone($filter)));
|
||||
// $and = $filt = Filter::matchAll(clone($filter));
|
||||
// return $this->renderFilterChain($filter, $level);
|
||||
|
||||
$html .= preg_replace(
|
||||
//'/ class="autosubmit"/',
|
||||
'/ class="/',
|
||||
' class="autofocus',
|
||||
$this->selectOperator()
|
||||
) . '<ul><li>'
|
||||
. $html
|
||||
. '</li><li class="active">'
|
||||
. $this->renderNewFilter() /*.$this->cancelLink()*/
|
||||
. '</li></ul>';
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
protected function filterExpressionHtml(FilterExpression $filter, $level)
|
||||
{
|
||||
return $this->selectColumn($filter)
|
||||
. $this->selectSign($filter)
|
||||
. $this->element($filter)
|
||||
. $this->removeLink($filter)
|
||||
. $this->addLink($filter);
|
||||
}
|
||||
|
||||
protected function renderFilterExpression(FilterExpression $filter, $level)
|
||||
{
|
||||
return $this->beginExpression($filter)
|
||||
. $this->eventuallyAddTo(
|
||||
$this->filterExpressionHtml($filter, $level),
|
||||
$filter,
|
||||
$level
|
||||
) . $this->endExpression($filter);
|
||||
}
|
||||
|
||||
protected function element(Filter $filter = null)
|
||||
{
|
||||
if ($filter) {
|
||||
// TODO: Make this configurable
|
||||
$type = 'host';
|
||||
|
||||
$dummy = IcingaObject::createByType($type);
|
||||
$col = $filter->getColumn();
|
||||
if ($dummy->hasProperty($col)) {
|
||||
if ($dummy->propertyIsBoolean($col)) {
|
||||
return $this->boolean($filter);
|
||||
}
|
||||
}
|
||||
|
||||
if ($col === 'groups' && $dummy->supportsGroups()) {
|
||||
return $this->selectGroup($type, $filter);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->text($filter);
|
||||
}
|
||||
|
||||
protected function selectGroup($type, Filter $filter)
|
||||
{
|
||||
$available = IcingaObjectGroup::enumForType($type);
|
||||
|
||||
return $this->select(
|
||||
$this->elementId('value', $filter),
|
||||
$this->optionalEnum($available),
|
||||
$filter->getExpression()
|
||||
);
|
||||
}
|
||||
|
||||
protected function boolean(Filter $filter = null)
|
||||
{
|
||||
$value = $filter === null ? '' : $filter->getExpression();
|
||||
|
||||
$el = new Icinga\Module\Director\Web\Form\Element\Boolean(
|
||||
$this->elementId('value', $filter),
|
||||
array(
|
||||
'value' => $value,
|
||||
'decorators' => array('ViewHelper'),
|
||||
)
|
||||
);
|
||||
|
||||
return $el;
|
||||
}
|
||||
|
||||
protected function text(Filter $filter = null)
|
||||
{
|
||||
$value = $filter === null ? '' : $filter->getExpression();
|
||||
if (is_array($value)) {
|
||||
return $this->view->formExtensibleSet(
|
||||
$this->elementId('value', $filter),
|
||||
$value
|
||||
);
|
||||
|
||||
$value = '(' . implode('|', $value) . ')';
|
||||
}
|
||||
|
||||
return $this->view->formText(
|
||||
$this->elementId('value', $filter),
|
||||
$value
|
||||
);
|
||||
}
|
||||
|
||||
protected function renderNewFilter()
|
||||
{
|
||||
return $this->selectColumn()
|
||||
. $this->selectSign()
|
||||
. $this->element();
|
||||
}
|
||||
|
||||
protected function arrayForSelect($array, $flip = false)
|
||||
{
|
||||
$res = array();
|
||||
foreach ($array as $k => $v) {
|
||||
if (is_int($k)) {
|
||||
$res[$v] = ucwords(str_replace('_', ' ', $v));
|
||||
} elseif ($flip) {
|
||||
$res[$v] = $k;
|
||||
} else {
|
||||
$res[$k] = $v;
|
||||
}
|
||||
}
|
||||
// sort($res);
|
||||
return $res;
|
||||
}
|
||||
|
||||
protected function elementId($field, Filter $filter = null)
|
||||
{
|
||||
$prefix = $this->fieldName . '[id_';
|
||||
$suffix = '][' . $field . ']';
|
||||
|
||||
if ($filter === null) {
|
||||
return $prefix . 'new_' . ($this->addTo ?: '0') . $suffix;
|
||||
} else {
|
||||
return $prefix . $filter->getId() . $suffix;
|
||||
}
|
||||
}
|
||||
|
||||
protected function selectOperator(Filter $filter = null)
|
||||
{
|
||||
$ops = array(
|
||||
'AND' => 'AND',
|
||||
'OR' => 'OR',
|
||||
'NOT' => 'NOT'
|
||||
);
|
||||
|
||||
return $this->view->formSelect(
|
||||
$this->elementId('operator', $filter),
|
||||
$filter === null ? null : $filter->getOperatorName(),
|
||||
array(
|
||||
'class' => 'operator autosubmit',
|
||||
),
|
||||
$ops
|
||||
);
|
||||
return $this->select(
|
||||
$this->elementId('operator', $filter),
|
||||
$ops,
|
||||
$filter === null ? null : $filter->getOperatorName(),
|
||||
array('class' => 'operator autosubmit')
|
||||
);
|
||||
}
|
||||
|
||||
protected function selectSign(Filter $filter = null)
|
||||
{
|
||||
$signs = array(
|
||||
'=' => '=',
|
||||
'!=' => '!=',
|
||||
'>' => '>',
|
||||
'<' => '<',
|
||||
'>=' => '>=',
|
||||
'<=' => '<=',
|
||||
'in' => 'in',
|
||||
'true' => 'is true (or set)',
|
||||
);
|
||||
|
||||
if ($filter === null) {
|
||||
$sign = null;
|
||||
} else {
|
||||
if ($filter->getExpression() === true) {
|
||||
$sign = 'true';
|
||||
} elseif (is_array($filter->getExpression())) {
|
||||
$sign = 'in';
|
||||
} else {
|
||||
$sign = $filter->getSign();
|
||||
}
|
||||
}
|
||||
|
||||
$class = 'sign autosubmit';
|
||||
if (strlen($sign) > 3) {
|
||||
$class .= ' wide';
|
||||
}
|
||||
|
||||
return $this->select(
|
||||
$this->elementId('sign', $filter),
|
||||
$signs,
|
||||
$sign,
|
||||
array('class' => $class)
|
||||
);
|
||||
}
|
||||
|
||||
public function setColumns(array $columns = null)
|
||||
{
|
||||
$this->cachedColumnSelect = $columns ? $this->arrayForSelect($columns) : null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function selectColumn(Filter $filter = null)
|
||||
{
|
||||
$active = $filter === null ? null : $filter->getColumn();
|
||||
|
||||
if (! $this->hasColumnList()) {
|
||||
return $this->view->formText(
|
||||
$this->elementId('column', $filter),
|
||||
$active
|
||||
);
|
||||
}
|
||||
|
||||
$cols = $this->getColumnList();
|
||||
if ($active && !isset($cols[$active])) {
|
||||
$cols[$active] = str_replace(
|
||||
'_',
|
||||
' ',
|
||||
ucfirst(ltrim($active, '_'))
|
||||
); // ??
|
||||
}
|
||||
|
||||
$cols = $this->optionalEnum($cols);
|
||||
|
||||
return $this->select(
|
||||
$this->elementId('column', $filter),
|
||||
$cols,
|
||||
$active,
|
||||
array('class' => 'autosubmit')
|
||||
);
|
||||
}
|
||||
|
||||
protected function optionalEnum($enum)
|
||||
{
|
||||
return array_merge(
|
||||
array(null => $this->view->translate('- please choose -')),
|
||||
$enum
|
||||
);
|
||||
}
|
||||
|
||||
protected function hasColumnList()
|
||||
{
|
||||
return $this->cachedColumnSelect !== null || $this->query !== null;
|
||||
}
|
||||
|
||||
protected function getColumnList()
|
||||
{
|
||||
if ($this->cachedColumnSelect === null) {
|
||||
$this->fetchColumnList();
|
||||
}
|
||||
|
||||
return $this->cachedColumnSelect;
|
||||
}
|
||||
|
||||
protected function fetchColumnList()
|
||||
{
|
||||
if ($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');
|
||||
}
|
||||
}
|
||||
|
||||
protected function select($name, $list, $selected, $attributes = null)
|
||||
{
|
||||
return $this->view->formSelect($name, $selected, $attributes, $list);
|
||||
}
|
||||
|
||||
protected function removeLink(Filter $filter)
|
||||
{
|
||||
return $this->filterActionButton(
|
||||
$filter,
|
||||
'cancel',
|
||||
t('Remove this part of your filter')
|
||||
);
|
||||
}
|
||||
|
||||
protected function addLink(Filter $filter)
|
||||
{
|
||||
return $this->filterActionButton(
|
||||
$filter,
|
||||
'plus',
|
||||
t('Add another filter')
|
||||
);
|
||||
}
|
||||
|
||||
protected function stripLink(Filter $filter)
|
||||
{
|
||||
return $this->filterActionButton(
|
||||
$filter,
|
||||
'minus',
|
||||
t('Strip this operator, preserve child nodes')
|
||||
);
|
||||
}
|
||||
|
||||
protected function filterActionButton(Filter $filter, $action, $title)
|
||||
{
|
||||
return $this->iconButton(
|
||||
$this->getActionButtonName($filter),
|
||||
$action,
|
||||
$title
|
||||
);
|
||||
}
|
||||
|
||||
protected function getActionButtonName(Filter $filter)
|
||||
{
|
||||
return sprintf(
|
||||
'%s[id_%s][action]',
|
||||
$this->fieldName,
|
||||
$filter->getId()
|
||||
);
|
||||
}
|
||||
|
||||
protected function iconButton($name, $icon, $title)
|
||||
{
|
||||
return $this->view->formSubmit(
|
||||
$name,
|
||||
IconHelper::instance()->iconCharacter($icon),
|
||||
array('class' => 'icon-button', 'title' => $title)
|
||||
);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace Icinga\Module\Director\Objects;
|
||||
|
||||
use Icinga\Data\Filter\Filter;
|
||||
use Icinga\Exception\IcingaException;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Module\Director\IcingaConfig\AssignRenderer;
|
||||
use Icinga\Module\Director\IcingaConfig\IcingaConfigHelper as c;
|
||||
@ -18,9 +19,15 @@ class IcingaObjectAssignments
|
||||
public function __construct(IcingaObject $object)
|
||||
{
|
||||
if (! $object->supportsAssignments()) {
|
||||
if ($object->hasProperty('object_type')) {
|
||||
$type = $object->object_type;
|
||||
} else {
|
||||
$type = get_class($object);
|
||||
}
|
||||
|
||||
throw new ProgrammingError(
|
||||
'I can only assign for applied objects, got %s',
|
||||
$object->object_type
|
||||
$type
|
||||
);
|
||||
}
|
||||
|
||||
@ -43,13 +50,14 @@ class IcingaObjectAssignments
|
||||
return $this->setValues(array($values));
|
||||
}
|
||||
|
||||
$this->current = array();
|
||||
if (is_object($values)) {
|
||||
$values = (array) $values;
|
||||
}
|
||||
|
||||
$this->current = array();
|
||||
|
||||
ksort($values);
|
||||
foreach ((array) $values as $type => $value) {
|
||||
foreach ($values as $type => $value) {
|
||||
if (is_numeric($type)) {
|
||||
$this->addRule($value);
|
||||
} else {
|
||||
@ -107,6 +115,16 @@ class IcingaObjectAssignments
|
||||
$rows[$val['assign_type']] = array();
|
||||
}
|
||||
|
||||
if (array_key_exists('filter_string', $val)) {
|
||||
$filter = $val['filter_string'];
|
||||
|
||||
if (! $filter->isEmpty()) {
|
||||
$rows[$val['assign_type']][] = $filter;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($val['property'])) {
|
||||
continue;
|
||||
}
|
||||
@ -132,10 +150,17 @@ class IcingaObjectAssignments
|
||||
|
||||
protected function addRule($string, $type = 'assign')
|
||||
{
|
||||
if (is_array($string) && array_key_exists('assign_type', $string)) {
|
||||
$type = $string['assign_type'];
|
||||
$string = $string['filter_string'];
|
||||
}
|
||||
// TODO: validate
|
||||
//echo "ADD RULE\n";
|
||||
//var_dump($string);
|
||||
//echo "ADD RULE END\n";
|
||||
$this->current[] = array(
|
||||
'assign_type' => $type,
|
||||
'filter_string' => $this->rerenderFilter($string)
|
||||
'filter_string' => $string instanceof Filter ? $this->renderFilter($string) : $string
|
||||
);
|
||||
|
||||
return $this;
|
||||
@ -227,9 +252,14 @@ class IcingaObjectAssignments
|
||||
return $this->stored;
|
||||
}
|
||||
|
||||
protected function renderFilter(Filter $filter)
|
||||
{
|
||||
return rawurldecode($filter->toQueryString());
|
||||
}
|
||||
|
||||
protected function rerenderFilter($string)
|
||||
{
|
||||
return rawurldecode(Filter::fromQueryString($string)->toQueryString());
|
||||
return $this->renderFilterFilter::fromQueryString($string);
|
||||
}
|
||||
|
||||
protected function createPlain($dbRows)
|
||||
|
206
library/Director/Web/Form/Element/DataFilter.php
Normal file
206
library/Director/Web/Form/Element/DataFilter.php
Normal file
@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Web\Form\Element;
|
||||
|
||||
use Icinga\Data\Filter\Filter;
|
||||
use Icinga\Module\Director\Web\Form\IconHelper;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Input control for extensible sets
|
||||
*/
|
||||
class DataFilter extends FormElement
|
||||
{
|
||||
/**
|
||||
* Default form view helper to use for rendering
|
||||
* @var string
|
||||
*/
|
||||
public $helper = 'formDataFilter';
|
||||
|
||||
/**
|
||||
* @codingStandardsIgnoreStart
|
||||
*/
|
||||
protected function _filterValue(&$value, &$key)
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
try {
|
||||
if ($value instanceof Filter) {
|
||||
// OK
|
||||
} elseif (is_string($value)) {
|
||||
$value = Filter::fromQueryString($value);
|
||||
} else {
|
||||
$value = $this->arrayToFilter($value);
|
||||
}
|
||||
|
||||
if ($value->isEmpty()) {
|
||||
$value = Filter::matchAll(Filter::expression('', '=', ''));
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$value = null;
|
||||
// TODO: getFile, getLine
|
||||
// Hint: cannot addMessage at it would loop through getValue
|
||||
$this->addErrorMessage($e->getMessage());
|
||||
$this->_isErrorForced = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected function arrayToFilter($array)
|
||||
{
|
||||
if ($array === null) {
|
||||
return Filter::matchAll();
|
||||
}
|
||||
|
||||
$firstKey = key($array);
|
||||
if (! in_array($firstKey, array('id_1', 'id_new_0'))) {
|
||||
die('FCK: ' . key($array));
|
||||
}
|
||||
|
||||
$entry = array_shift($array);
|
||||
$filter = $this->entryToFilter($entry);
|
||||
if ($firstKey === 'id_new_0') {
|
||||
$this->setAttrib('addTo', '0');
|
||||
}
|
||||
|
||||
$remove = $strip = null;
|
||||
|
||||
// TODO: This is for the first entry, duplicates code and has debug info
|
||||
$filterId = $this->idToFilterId($firstKey);
|
||||
switch ($this->entryAction($entry)) {
|
||||
case 'cancel':
|
||||
$remove = $filterId;
|
||||
echo "cancel";
|
||||
break;
|
||||
|
||||
case 'minus':
|
||||
$strip = $filterId;
|
||||
echo "minus";
|
||||
break;
|
||||
|
||||
case 'plus':
|
||||
$this->setAttrib('addTo', $filterId);
|
||||
echo "plus";
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($array as $id => $entry) {
|
||||
// TODO: addTo from FilterEditor
|
||||
|
||||
$sub = $this->entryToFilter($entry);
|
||||
$filterId = $this->idToFilterId($id);
|
||||
|
||||
switch ($this->entryAction($entry)) {
|
||||
case 'cancel':
|
||||
$remove = $filterId;
|
||||
break;
|
||||
|
||||
case 'minus':
|
||||
$strip = $filterId;
|
||||
break;
|
||||
|
||||
case 'plus':
|
||||
$this->setAttrib('addTo', $filterId);
|
||||
break;
|
||||
}
|
||||
|
||||
$parentId = $this->parentIdFor($filterId);
|
||||
$filter->getById($parentId)->addFilter($sub);
|
||||
}
|
||||
|
||||
if ($remove) {
|
||||
if ($filter->getById($remove)->isRootNode()) {
|
||||
$filter = Filter::matchAll();
|
||||
} else {
|
||||
$filter->removeId($remove);
|
||||
}
|
||||
}
|
||||
|
||||
if ($strip) {
|
||||
$subId = $strip . '-1';
|
||||
if ($filter->getId() === $strip) {
|
||||
$filter = $filter->getById($strip . '-1');
|
||||
} else {
|
||||
$filter->replaceById($strip, $filter->getById($strip . '-1'));
|
||||
}
|
||||
}
|
||||
|
||||
return $filter;
|
||||
}
|
||||
|
||||
protected function parentIdFor($id)
|
||||
{
|
||||
if (false === ($pos = strrpos($id, '-'))) {
|
||||
return '0';
|
||||
} else {
|
||||
return substr($id, 0, $pos);
|
||||
}
|
||||
}
|
||||
|
||||
protected function idToFilterId($id)
|
||||
{
|
||||
if (! preg_match('/^id_(new_)?(\d+(?:-\d+)*)$/', $id, $m)) {
|
||||
die('nono' . $id);
|
||||
}
|
||||
|
||||
return $m[2];
|
||||
}
|
||||
|
||||
protected function entryToFilter($entry)
|
||||
{
|
||||
if (array_key_exists('operator', $entry)) {
|
||||
return Filter::chain($entry['operator']);
|
||||
} else {
|
||||
if ($entry['sign'] === 'true') {
|
||||
return Filter::expression(
|
||||
$entry['column'],
|
||||
'=',
|
||||
true
|
||||
);
|
||||
} elseif ($entry['sign'] === 'in') {
|
||||
if (array_key_exists('value', $entry)) {
|
||||
if (is_array($entry['value'])) {
|
||||
$value = array_filter($entry['value'], 'strlen');
|
||||
} elseif (empty($entry['value'])) {
|
||||
$value = array();
|
||||
} else {
|
||||
$value = array($entry['value']);
|
||||
}
|
||||
} else {
|
||||
$value = array();
|
||||
}
|
||||
return Filter::expression(
|
||||
$entry['column'],
|
||||
'=',
|
||||
$value
|
||||
);
|
||||
} else {
|
||||
return Filter::expression(
|
||||
$entry['column'],
|
||||
$entry['sign'],
|
||||
array_key_exists('value', $entry) ? $entry['value'] : null
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function entryAction($entry)
|
||||
{
|
||||
if (array_key_exists('action', $entry)) {
|
||||
return IconHelper::instance()->characterIconName($entry['action']);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function isValid($value, $context = null)
|
||||
{
|
||||
if (! $value instanceof Filter) {
|
||||
// TODO: try, return false on E
|
||||
$filter = $this->arrayToFilter($value);
|
||||
}
|
||||
|
||||
$this->setValue($filter);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user