PropertyModifierArrayFilter: new modifier

fixes #908
This commit is contained in:
Thomas Gelf 2017-04-20 12:33:54 +02:00
parent 6234648a1f
commit c284dfef88
3 changed files with 269 additions and 0 deletions

View File

@ -0,0 +1,148 @@
<?php
namespace Icinga\Module\Director\PropertyModifier;
use Icinga\Data\Filter\FilterExpression;
use Icinga\Exception\ConfigurationError;
use Icinga\Exception\InvalidPropertyException;
use Icinga\Module\Director\Hook\PropertyModifierHook;
use Icinga\Module\Director\Web\Form\QuickForm;
class PropertyModifierArrayFilter extends PropertyModifierHook
{
/** @var FilterExpression */
private $filterExpression;
public function getName()
{
return 'Filter Array Values';
}
public function hasArraySupport()
{
return true;
}
public static function addSettingsFormFields(QuickForm $form)
{
$form->addElement('select', 'filter_method', array(
'label' => $form->translate('Filter method'),
'required' => true,
'value' => 'wildcard',
'multiOptions' => $form->optionalEnum(array(
'wildcard' => $form->translate('Simple match with wildcards (*)'),
'regex' => $form->translate('Regular Expression'),
)),
));
$form->addElement('text', 'filter_string', array(
'label' => 'Filter',
'description' => $form->translate(
'The string/pattern you want to search for. Depends on the'
. ' chosen method, use www.* or *linux* for wildcard matches'
. ' and expression like /^www\d+\./ in case you opted for a'
. ' regular expression'
),
'required' => true,
));
$form->addElement('select', 'policy', array(
'label' => $form->translate('Policy'),
'required' => true,
'description' => $form->translate(
'What should happen with matching elements?'
),
'value' => 'keep',
'multiOptions' => array(
'keep' => $form->translate('Keep matching elements'),
'reject' => $form->translate('Reject matching elements'),
),
));
$form->addElement('select', 'when_empty', array(
'label' => $form->translate('When empty'),
'required' => true,
'description' => $form->translate(
'What should happen when the result array is empty?'
),
'value' => 'empty_array',
'multiOptions' => $form->optionalEnum(array(
'empty_array' => $form->translate('return an empty array'),
'null' => $form->translate('return NULL'),
))
));
}
public function matchesRegexp($string, $expression)
{
return preg_match($expression, $string);
}
public function matchesWildcard($string, $expression)
{
return $this->filterExpression->matches(
(object) array('value' => $string)
);
}
public function transform($value)
{
if (empty($value)) {
return $this->emptyValue();
}
if (! is_array($value)) {
throw new InvalidPropertyException(
'The ArrayFilter property modifier be applied to arrays only'
);
}
$method = $this->getSetting('filter_method');
$filter = $this->getSetting('filter_string');
$policy = $this->getSetting('policy');
switch ($method) {
case 'wildcard':
$func = 'matchesWildcard';
$this->filterExpression = new FilterExpression('value', '=', $filter);
break;
case 'regex':
$func = 'matchesRegexp';
break;
default:
throw new ConfigurationError(
'%s is not a valid value for an ArrayFilter filter_method',
var_export($method, 1)
);
}
$result = array();
foreach ($value as $val) {
if ($this->$func($val, $filter)) {
if ($policy === 'keep') {
$result[] = $val;
}
} else {
if ($policy === 'reject') {
$result[] = $val;
}
}
}
if (empty($result)) {
return $this->emptyValue();
}
return $result;
}
protected function emptyValue()
{
if ($this->getSetting('when_empty', 'empty_array') === 'empty_array') {
return array();
} else {
return null;
}
}
}

View File

@ -39,6 +39,7 @@ $this->provideHook('director/PropertyModifier', $prefix . 'PropertyModifier\\Pro
$this->provideHook('director/PropertyModifier', $prefix . 'PropertyModifier\\PropertyModifierJsonDecode');
$this->provideHook('director/PropertyModifier', $prefix . 'PropertyModifier\\PropertyModifierToInt');
$this->provideHook('director/PropertyModifier', $prefix . 'PropertyModifier\\PropertyModifierLConfCustomVar');
$this->provideHook('director/PropertyModifier', $prefix . 'PropertyModifier\\PropertyModifierArrayFilter');
$this->provideHook('director/Job', $prefix . 'Job\\HousekeepingJob');
$this->provideHook('director/Job', $prefix . 'Job\\ConfigJob');

View File

@ -0,0 +1,120 @@
<?php
namespace Tests\Icinga\Module\Director\Objects;
use Icinga\Module\Director\PropertyModifier\PropertyModifierArrayFilter;
use Icinga\Module\Director\Test\BaseTestCase;
class PropertyModifierArrayFilterTest extends BaseTestCase
{
/**
* Allowed settings:
*
* filter_method: wildcard, regex
* filter_string
*
* policy: keep, reject
* when_empty: empty_array, null
*/
/** @var array */
private $testArray = array(
'www.example.com',
'example.com',
'www',
'wwexample.com',
'example.www',
'',
);
public function testKeepMatchingWildcards()
{
$modifier = new PropertyModifierArrayFilter();
$modifier->setSettings(array(
'filter_method' => 'wildcard',
'filter_string' => 'www*',
'policy' => 'keep',
'when_empty' => 'empty_array',
));
$this->assertEquals(
array('www.example.com', 'www'),
$modifier->transform($this->testArray)
);
}
public function testRejectMatchingWildcards()
{
$modifier = new PropertyModifierArrayFilter();
$modifier->setSettings(array(
'filter_method' => 'wildcard',
'filter_string' => 'www*',
'policy' => 'reject',
'when_empty' => 'empty_array',
));
$this->assertEquals(
array('example.com', 'wwexample.com', 'example.www', ''),
$modifier->transform($this->testArray)
);
}
public function testKeepMatchingRegularExpression()
{
$modifier = new PropertyModifierArrayFilter();
$modifier->setSettings(array(
'filter_method' => 'regex',
'filter_string' => '/^w{3}.*/',
'policy' => 'keep',
'when_empty' => 'empty_array',
));
$this->assertEquals(
array('www.example.com', 'www'),
$modifier->transform($this->testArray)
);
}
public function testRejectMatchingRegularExpression()
{
$modifier = new PropertyModifierArrayFilter();
$modifier->setSettings(array(
'filter_method' => 'regex',
'filter_string' => '/^w{3}.*/',
'policy' => 'reject',
'when_empty' => 'empty_array',
));
$this->assertEquals(
array('example.com', 'wwexample.com', 'example.www', ''),
$modifier->transform($this->testArray)
);
}
public function testGivesEmptyArrayOrNullAccordingToConfig()
{
$modifier = new PropertyModifierArrayFilter();
$modifier->setSettings(array(
'filter_method' => 'wildcard',
'filter_string' => 'no-match',
'policy' => 'keep',
'when_empty' => 'empty_array',
));
$this->assertEquals(
array(),
$modifier->transform($this->testArray)
);
$modifier->setSetting('when_empty', 'null');
$this->assertNull(
$modifier->transform($this->testArray)
);
}
public function testAnnouncesArraySupport()
{
$modifier = new PropertyModifierArrayFilter();
$this->assertTrue($modifier->hasArraySupport());
}
}