mirror of
https://github.com/Icinga/icingaweb2-module-director.git
synced 2025-07-26 23:34:10 +02:00
ExtensibleSet: basic implementation & tests
This commit is contained in:
parent
40d2e9f120
commit
23dd4721ec
199
library/Director/IcingaConfig/ExtensibleSet.php
Normal file
199
library/Director/IcingaConfig/ExtensibleSet.php
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Icinga\Module\Director\IcingaConfig;
|
||||||
|
|
||||||
|
use Icinga\Exception\InvalidPropertyException;
|
||||||
|
|
||||||
|
class ExtensibleSet
|
||||||
|
{
|
||||||
|
protected $ownValues;
|
||||||
|
|
||||||
|
protected $plusValues = array();
|
||||||
|
|
||||||
|
protected $minusValues = array();
|
||||||
|
|
||||||
|
protected $resolvedValues;
|
||||||
|
|
||||||
|
protected $allowedValues;
|
||||||
|
|
||||||
|
protected $inheritedValues = array();
|
||||||
|
|
||||||
|
public function __construct($values = null)
|
||||||
|
{
|
||||||
|
if (null !== $values) {
|
||||||
|
$this->override($values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function override($values)
|
||||||
|
{
|
||||||
|
$this->ownValues = array();
|
||||||
|
$this->inheritedValues = array();
|
||||||
|
|
||||||
|
$this->addValuesTo($this->ownValues, $values);
|
||||||
|
|
||||||
|
return $this->addResolvedValues($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function extend($values)
|
||||||
|
{
|
||||||
|
$this->addValuesTo($this->plusValues, $values);
|
||||||
|
return $this->addResolvedValues($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function blacklist($values)
|
||||||
|
{
|
||||||
|
$this->addValuesTo($this->minusValues, $values);
|
||||||
|
|
||||||
|
if ($this->hasBeenResolved()) {
|
||||||
|
$this->removeValuesFrom($this->resolvedValues, $values);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getResolvedValues()
|
||||||
|
{
|
||||||
|
if (! $this->hasBeenResolved()) {
|
||||||
|
$this->recalculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
sort($this->resolvedValues);
|
||||||
|
|
||||||
|
return $this->resolvedValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function hasBeenResolved()
|
||||||
|
{
|
||||||
|
return $this->resolvedValues !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function inheritFrom(ExtensibleSet $parent)
|
||||||
|
{
|
||||||
|
if ($this->ownValues !== null) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->hasBeenResolved()) {
|
||||||
|
$this->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->inheritedValues = array();
|
||||||
|
|
||||||
|
$this->addValuesTo(
|
||||||
|
$this->inheritedValues,
|
||||||
|
$this->stripBlacklistedValues($parent->getResolvedValues())
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->recalculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function stripBlacklistedValues($array)
|
||||||
|
{
|
||||||
|
$this->removeValuesFrom($array, $this->minusValues);
|
||||||
|
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forgetInheritedValues()
|
||||||
|
{
|
||||||
|
$this->inheritedValues = array();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function assertValidValue($value)
|
||||||
|
{
|
||||||
|
if (null === $this->allowedValues) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($value, $this->allowedValues)) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidPropertyException(
|
||||||
|
'Got invalid property "%s", allowed are: (%s)',
|
||||||
|
$value,
|
||||||
|
implode(', ', $this->allowedValues)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addValuesTo(&$array, $values)
|
||||||
|
{
|
||||||
|
foreach ($this->wantArray($values) as $value) {
|
||||||
|
$this->addTo($array, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addResolvedValues($values)
|
||||||
|
{
|
||||||
|
if (! $this->hasBeenResolved()) {
|
||||||
|
$this->resolvedValues = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->addValuesTo(
|
||||||
|
$this->resolvedValues,
|
||||||
|
$this->stripBlacklistedValues($this->wantArray($values))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function removeValuesFrom(&$array, $values)
|
||||||
|
{
|
||||||
|
foreach ($this->wantArray($values) as $value) {
|
||||||
|
$this->removeFrom($array, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addTo(&$array, $value)
|
||||||
|
{
|
||||||
|
if (! in_array($value, $array)) {
|
||||||
|
$this->assertValidValue($value);
|
||||||
|
$array[] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function removeFrom(&$array, $value)
|
||||||
|
{
|
||||||
|
if (false !== ($pos = array_search($value, $array))) {
|
||||||
|
unset($array[$pos]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function recalculate()
|
||||||
|
{
|
||||||
|
$this->resolvedValues = array();
|
||||||
|
if ($this->ownValues === null) {
|
||||||
|
$this->addValuesTo($this->resolvedValues, $this->inheritedValues);
|
||||||
|
} else {
|
||||||
|
$this->addValuesTo($this->resolvedValues, $this->ownValues);
|
||||||
|
}
|
||||||
|
$this->addValuesTo($this->resolvedValues, $this->plusValues);
|
||||||
|
$this->removeFrom($this->resolvedValues, $this->minusValues);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function reset()
|
||||||
|
{
|
||||||
|
$this->resolvedValues = null;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function wantArray($values)
|
||||||
|
{
|
||||||
|
if (is_array($values)) {
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array($values);
|
||||||
|
}
|
||||||
|
}
|
135
test/php/library/Director/IcingaConfig/ExtensibleSetTest.php
Normal file
135
test/php/library/Director/IcingaConfig/ExtensibleSetTest.php
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Icinga\Module\Director\IcingaConfig;
|
||||||
|
|
||||||
|
use Icinga\Module\Director\IcingaConfig\ExtensibleSet;
|
||||||
|
use Icinga\Module\Director\Test\BaseTestCase;
|
||||||
|
|
||||||
|
class ExtensibleSetTest extends BaseTestCase
|
||||||
|
{
|
||||||
|
public function testNoValuesResultInEmptySet()
|
||||||
|
{
|
||||||
|
$set = new ExtensibleSet();
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
array(),
|
||||||
|
$set->getResolvedValues()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValuesPassedToConstructorAreAccepted()
|
||||||
|
{
|
||||||
|
$values = array('Val1', 'Val2', 'Val4');
|
||||||
|
$set = new ExtensibleSet($values);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
$values,
|
||||||
|
$set->getResolvedValues()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSingleValuesCanBeBlacklisted()
|
||||||
|
{
|
||||||
|
$values = array('Val1', 'Val2', 'Val4');
|
||||||
|
$set = new ExtensibleSet($values);
|
||||||
|
$set->blacklist('Val2');
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
array('Val1', 'Val4'),
|
||||||
|
$set->getResolvedValues()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMultipleValuesCanBeBlacklisted()
|
||||||
|
{
|
||||||
|
$values = array('Val1', 'Val2', 'Val4');
|
||||||
|
$set = new ExtensibleSet($values);
|
||||||
|
$set->blacklist(array('Val4', 'Val1'));
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
array('Val2'),
|
||||||
|
$set->getResolvedValues()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSimpleInheritanceWorksFine()
|
||||||
|
{
|
||||||
|
$values = array('Val1', 'Val2', 'Val4');
|
||||||
|
$parent = new ExtensibleSet($values);
|
||||||
|
$child = new ExtensibleSet();
|
||||||
|
$child->inheritFrom($parent);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
$values,
|
||||||
|
$child->getResolvedValues()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWeCanInheritFromMultipleParents()
|
||||||
|
{
|
||||||
|
$p1set = array('p1a', 'p1c');
|
||||||
|
$p2set = array('p2a', 'p2d');
|
||||||
|
$parent1 = new ExtensibleSet($p1set);
|
||||||
|
$parent2 = new ExtensibleSet($p2set);
|
||||||
|
$child = new ExtensibleSet();
|
||||||
|
$child->inheritFrom($parent1)->inheritFrom($parent2);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
$p2set,
|
||||||
|
$child->getResolvedValues()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOwnValuesOverrideParents()
|
||||||
|
{
|
||||||
|
$cset = array('p1a', 'p1c');
|
||||||
|
$pset = array('p2a', 'p2d');
|
||||||
|
$child = new ExtensibleSet($cset);
|
||||||
|
$parent = new ExtensibleSet($pset);
|
||||||
|
$child->inheritFrom($parent);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
$cset,
|
||||||
|
$child->getResolvedValues()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInheritedValuesCanBeBlacklisted()
|
||||||
|
{
|
||||||
|
$pset = array('p1', 'p2', 'p3');
|
||||||
|
|
||||||
|
$child = new ExtensibleSet();
|
||||||
|
$child->blacklist('p2');
|
||||||
|
|
||||||
|
$parent = new ExtensibleSet($pset);
|
||||||
|
$child->inheritFrom($parent);
|
||||||
|
$child->blacklist(array('not', 'yet', 'p1'));
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
array('p3'),
|
||||||
|
$child->getResolvedValues()
|
||||||
|
);
|
||||||
|
|
||||||
|
$child->blacklist(array('p3'));
|
||||||
|
$this->assertEquals(
|
||||||
|
array(),
|
||||||
|
$child->getResolvedValues()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInheritedValuesCanBeExtended()
|
||||||
|
{
|
||||||
|
$pset = array('p1', 'p2', 'p3');
|
||||||
|
|
||||||
|
$child = new ExtensibleSet();
|
||||||
|
$child->extend('p5');
|
||||||
|
|
||||||
|
$parent = new ExtensibleSet($pset);
|
||||||
|
$child->inheritFrom($parent);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
array('p1', 'p2', 'p3', 'p5'),
|
||||||
|
$child->getResolvedValues()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user