mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-11 17:58:41 +00:00
Fix multimap implementation and add tests
This commit is contained in:
parent
5b3178e049
commit
105d4f355b
|
|
@ -90,7 +90,7 @@ class MultiMap implements \Countable
|
|||
$inserted = false;
|
||||
|
||||
if ($this->keyType !== KeyType::SINGLE) {
|
||||
$keys = [implode(':', $keys)];
|
||||
$keys = [\implode(':', $keys)];
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
|
|
@ -202,7 +202,7 @@ class MultiMap implements \Countable
|
|||
{
|
||||
if (\is_array($key)) {
|
||||
if ($this->orderType === OrderType::LOOSE) {
|
||||
$keys = Permutation::permut($key);
|
||||
$keys = Permutation::permut($key, [], false);
|
||||
|
||||
foreach ($keys as $key => $value) {
|
||||
$key = \implode(':', $value);
|
||||
|
|
@ -231,7 +231,7 @@ class MultiMap implements \Countable
|
|||
*/
|
||||
public function set($key, $value) : bool
|
||||
{
|
||||
if ($this->keyType === KeyType::MULTIPLE && is_array($key)) {
|
||||
if ($this->keyType === KeyType::MULTIPLE && \is_array($key)) {
|
||||
return $this->setMultiple($key, $value);
|
||||
}
|
||||
|
||||
|
|
@ -250,19 +250,17 @@ class MultiMap implements \Countable
|
|||
*/
|
||||
private function setMultiple($key, $value) : bool
|
||||
{
|
||||
if ($this->orderType !== OrderType::LOOSE) {
|
||||
$permutation = Permutation::permut($key);
|
||||
if ($this->orderType !== OrderType::STRICT) {
|
||||
$permutation = Permutation::permut($key, [], false);
|
||||
|
||||
foreach ($permutation as $permut) {
|
||||
if ($this->set(implode(':', $permut), $value)) {
|
||||
if ($this->set(\implode(':', $permut), $value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return $this->set(implode(':', $key), $value);
|
||||
return $this->set(\implode(':', $key), $value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -297,7 +295,7 @@ class MultiMap implements \Countable
|
|||
*/
|
||||
public function remove($key) : bool
|
||||
{
|
||||
if ($this->keyType === KeyType::MULTIPLE && is_array($key)) {
|
||||
if ($this->keyType === KeyType::MULTIPLE && \is_array($key)) {
|
||||
return $this->removeMultiple($key);
|
||||
}
|
||||
|
||||
|
|
@ -316,17 +314,17 @@ class MultiMap implements \Countable
|
|||
private function removeMultiple($key) : bool
|
||||
{
|
||||
if ($this->orderType !== OrderType::LOOSE) {
|
||||
return $this->remove(implode(':', $key));
|
||||
return $this->remove(\implode(':', $key));
|
||||
}
|
||||
|
||||
$keys = Permutation::permut($key);
|
||||
$found = true;
|
||||
$keys = Permutation::permut($key, [], false);
|
||||
$found = false;
|
||||
|
||||
foreach ($keys as $key => $value) {
|
||||
$allFound = $this->remove(implode(':', $value));
|
||||
$allFound = $this->remove(\implode(':', $value));
|
||||
|
||||
if (!$allFound) {
|
||||
$found = false;
|
||||
if ($allFound) {
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -399,43 +397,11 @@ class MultiMap implements \Countable
|
|||
*/
|
||||
public function removeKey($key) : bool
|
||||
{
|
||||
if ($this->keyType === KeyType::MULTIPLE && is_array($key)) {
|
||||
return $this->removeKeyMultiple($key);
|
||||
} else {
|
||||
return $this->removeKeySingle($key);
|
||||
if ($this->keyType === KeyType::MULTIPLE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove key.
|
||||
*
|
||||
* This only removes the value if no other key exists for this value.
|
||||
*
|
||||
* @param mixed $key Key used to identify value
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function removeKeyMultiple($key) : bool
|
||||
{
|
||||
if ($this->orderType === OrderType::LOOSE) {
|
||||
$keys = Permutation::permut($key);
|
||||
|
||||
$removed = false;
|
||||
|
||||
foreach ($keys as $key => $value) {
|
||||
$removed = $this->removeKey(implode(':', $value));
|
||||
|
||||
if (!$removed) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $removed;
|
||||
} else {
|
||||
return $this->removeKey(implode(':', $key));
|
||||
}
|
||||
return $this->removeKeySingle($key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -493,7 +459,9 @@ class MultiMap implements \Countable
|
|||
public function getSiblingsMultiple($key) : array
|
||||
{
|
||||
if ($this->orderType === OrderType::LOOSE) {
|
||||
return Permutation::permut($key);
|
||||
$key = \is_array($key) ? $key : [$key];
|
||||
|
||||
return Permutation::permut($key, [], false);
|
||||
}
|
||||
|
||||
return [];
|
||||
|
|
|
|||
|
|
@ -45,12 +45,12 @@ final class Permutation
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function permut(array $toPermute, array $result = []) : array
|
||||
public static function permut(array $toPermute, array $result = [], bool $concat = true) : array
|
||||
{
|
||||
$permutations = [];
|
||||
|
||||
if (empty($toPermute)) {
|
||||
$permutations[] = \implode('', $result);
|
||||
$permutations[] = $concat ? \implode('', $result) : $result;
|
||||
} else {
|
||||
foreach ($toPermute as $key => $val) {
|
||||
$newArr = $toPermute;
|
||||
|
|
@ -59,7 +59,7 @@ final class Permutation
|
|||
|
||||
unset($newArr[$key]);
|
||||
|
||||
$permutations = array_merge($permutations, self::permut($newArr, $newres));
|
||||
$permutations = \array_merge($permutations, self::permut($newArr, $newres, $concat));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ final class Permutation
|
|||
*/
|
||||
public static function isPermutation(string $a, string $b) : bool
|
||||
{
|
||||
return count_chars($a, 1) === count_chars($b, 1);
|
||||
return \count_chars($a, 1) === \count_chars($b, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -93,7 +93,7 @@ final class Permutation
|
|||
*/
|
||||
public static function isPalindrome(string $a, string $filter = 'a-zA-Z0-9') : bool
|
||||
{
|
||||
$a = \strtolower(preg_replace('/[^' . $filter . ']/', '', $a));
|
||||
$a = \strtolower(\preg_replace('/[^' . $filter . ']/', '', $a));
|
||||
|
||||
return $a === \strrev($a);
|
||||
}
|
||||
|
|
@ -112,11 +112,11 @@ final class Permutation
|
|||
*/
|
||||
public static function permutate($toPermute, array $key)
|
||||
{
|
||||
if (!is_array($toPermute) && !is_string($toPermute)) {
|
||||
if (!\is_array($toPermute) && !\is_string($toPermute)) {
|
||||
throw new \InvalidArgumentException('Parameter has to be array or string');
|
||||
}
|
||||
|
||||
$length = is_array($toPermute) ? \count($toPermute) : \strlen($toPermute);
|
||||
$length = \is_array($toPermute) ? \count($toPermute) : \strlen($toPermute);
|
||||
|
||||
if (\count($key) > $length) {
|
||||
throw new \InvalidArgumentException('There mustn not be more keys than permutation elements.');
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
namespace phpOMS\tests\Stdlib\Map;
|
||||
|
||||
use phpOMS\Stdlib\Map\MultiMap;
|
||||
use phpOMS\Stdlib\Map\KeyType;
|
||||
use phpOMS\Stdlib\Map\OrderType;
|
||||
|
||||
class MultiMapTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
|
|
@ -43,7 +45,7 @@ class MultiMapTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertFalse($map->remove('someKey'));
|
||||
}
|
||||
|
||||
public function testBasicAdd()
|
||||
public function testBasicAddAny()
|
||||
{
|
||||
$map = new MultiMap();
|
||||
|
||||
|
|
@ -54,7 +56,7 @@ class MultiMapTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals('val1', $map->get('b'));
|
||||
}
|
||||
|
||||
public function testOverwrite()
|
||||
public function testOverwriteAny()
|
||||
{
|
||||
$map = new MultiMap();
|
||||
|
||||
|
|
@ -66,7 +68,7 @@ class MultiMapTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals('val2', $map->get('b'));
|
||||
}
|
||||
|
||||
public function testOverwritePartialFalse()
|
||||
public function testOverwritePartialFalseAny()
|
||||
{
|
||||
$map = new MultiMap();
|
||||
|
||||
|
|
@ -79,7 +81,7 @@ class MultiMapTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals('val3', $map->get('c'));
|
||||
}
|
||||
|
||||
public function testOverwriteFalseFalse()
|
||||
public function testOverwriteFalseFalseAny()
|
||||
{
|
||||
$map = new MultiMap();
|
||||
|
||||
|
|
@ -93,7 +95,7 @@ class MultiMapTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals('val3', $map->get('c'));
|
||||
}
|
||||
|
||||
public function testSet()
|
||||
public function testSetAny()
|
||||
{
|
||||
$map = new MultiMap();
|
||||
|
||||
|
|
@ -112,7 +114,7 @@ class MultiMapTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals('val3', $map->get('c'));
|
||||
}
|
||||
|
||||
public function testRemap()
|
||||
public function testRemapAny()
|
||||
{
|
||||
$map = new MultiMap();
|
||||
|
||||
|
|
@ -142,7 +144,7 @@ class MultiMapTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals('val3', $map->get('c'));
|
||||
}
|
||||
|
||||
public function testMapInfo()
|
||||
public function testMapInfoAny()
|
||||
{
|
||||
$map = new MultiMap();
|
||||
|
||||
|
|
@ -159,7 +161,7 @@ class MultiMapTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertTrue(\is_array($map->values()));
|
||||
}
|
||||
|
||||
public function testSiblings()
|
||||
public function testSiblingsAny()
|
||||
{
|
||||
$map = new MultiMap();
|
||||
|
||||
|
|
@ -177,7 +179,7 @@ class MultiMapTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals(['a'], $siblings);
|
||||
}
|
||||
|
||||
public function testRemove()
|
||||
public function testRemoveAny()
|
||||
{
|
||||
$map = new MultiMap();
|
||||
|
||||
|
|
@ -190,9 +192,6 @@ class MultiMapTest extends \PHPUnit\Framework\TestCase
|
|||
$removed = $map->remove('d');
|
||||
self::assertFalse($removed);
|
||||
|
||||
$removed = $map->remove('d');
|
||||
self::assertFalse($removed);
|
||||
|
||||
$removed = $map->remove('c');
|
||||
self::assertTrue($removed);
|
||||
self::assertEquals(2, \count($map->keys()));
|
||||
|
|
@ -206,4 +205,169 @@ class MultiMapTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals(1, \count($map->keys()));
|
||||
self::assertEquals(1, \count($map->values()));
|
||||
}
|
||||
|
||||
public function testBasicAddExact()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val1');
|
||||
self::assertEquals(1, $map->count());
|
||||
self::assertTrue($inserted);
|
||||
self::assertEquals('val1', $map->get(['a', 'b']));
|
||||
self::assertEquals('val1', $map->get(['b', 'a']));
|
||||
}
|
||||
|
||||
public function testBasicAddExactOrdered()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE, OrderType::STRICT);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val1');
|
||||
self::assertEquals(1, $map->count());
|
||||
self::assertTrue($inserted);
|
||||
self::assertEquals('val1', $map->get(['a', 'b']));
|
||||
self::assertEquals(null, $map->get(['b', 'a']));
|
||||
}
|
||||
|
||||
public function testOverwriteExact()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val1');
|
||||
$inserted = $map->add(['a', 'b'], 'val2');
|
||||
self::assertEquals(1, $map->count());
|
||||
self::assertTrue($inserted);
|
||||
self::assertEquals('val2', $map->get(['a', 'b']));
|
||||
}
|
||||
|
||||
public function testOverwritePartialFalseExact()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val2');
|
||||
$inserted = $map->add(['a', 'c'], 'val3', false);
|
||||
self::assertEquals(2, $map->count());
|
||||
self::assertTrue($inserted);
|
||||
self::assertEquals('val2', $map->get(['a', 'b']));
|
||||
self::assertEquals('val3', $map->get(['c', 'a']));
|
||||
}
|
||||
|
||||
public function testOverwriteFalseFalseExact()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val2');
|
||||
$inserted = $map->add(['a', 'c'], 'val3', false);
|
||||
$inserted = $map->add(['a', 'c'], 'val4', false);
|
||||
self::assertEquals(2, $map->count());
|
||||
self::assertFalse($inserted);
|
||||
self::assertEquals('val2', $map->get(['a', 'b']));
|
||||
self::assertEquals('val3', $map->get(['a', 'c']));
|
||||
}
|
||||
|
||||
public function testSetExact()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val2');
|
||||
$inserted = $map->add(['a', 'c'], 'val3', false);
|
||||
|
||||
$set = $map->set('d', 'val4');
|
||||
self::assertFalse($set);
|
||||
self::assertEquals(2, $map->count());
|
||||
|
||||
$set = $map->set(['a', 'b'], 'val4');
|
||||
self::assertEquals(2, $map->count());
|
||||
self::assertTrue($set);
|
||||
self::assertEquals('val4', $map->get(['a', 'b']));
|
||||
self::assertEquals('val4', $map->get(['b', 'a']));
|
||||
}
|
||||
|
||||
public function testSetExactOrdered()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE, OrderType::STRICT);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val2');
|
||||
$inserted = $map->add(['a', 'c'], 'val3', false);
|
||||
|
||||
$set = $map->set('c', 'val4');
|
||||
self::assertFalse($set);
|
||||
self::assertEquals(2, $map->count());
|
||||
|
||||
$set = $map->set(['a', 'b'], 'val4');
|
||||
self::assertEquals(2, $map->count());
|
||||
self::assertTrue($set);
|
||||
self::assertEquals('val4', $map->get(['a', 'b']));
|
||||
|
||||
$set = $map->set(['b', 'a'], 'val5');
|
||||
self::assertEquals(2, $map->count());
|
||||
self::assertFalse($set);
|
||||
}
|
||||
|
||||
public function testRemapExact()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val2');
|
||||
$remap = $map->remap(['a', 'b'], ['c', 'd']);
|
||||
|
||||
self::assertFalse($remap);
|
||||
}
|
||||
|
||||
public function testSiblingsExact()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val2');
|
||||
self::assertEquals([['a', 'b'], ['b', 'a']], $map->getSiblings(['a', 'b']));
|
||||
}
|
||||
|
||||
public function testSiblingsExactOrdered()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE, OrderType::STRICT);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val2');
|
||||
self::assertEquals([], $map->getSiblings(['a', 'b']));
|
||||
}
|
||||
|
||||
public function testRemoveExact()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val2');
|
||||
$inserted = $map->add(['a', 'c'], 'val3', false);
|
||||
|
||||
self::assertEquals(2, \count($map->keys()));
|
||||
self::assertEquals(2, \count($map->values()));
|
||||
|
||||
$removed = $map->remove('d');
|
||||
self::assertFalse($removed);
|
||||
|
||||
$removed = $map->remove(['a', 'b']);
|
||||
self::assertTrue($removed);
|
||||
self::assertEquals(1, \count($map->keys()));
|
||||
self::assertEquals(1, \count($map->values()));
|
||||
|
||||
self::assertFalse($map->removeKey(['a', 'b']));
|
||||
}
|
||||
|
||||
public function testRemoveExactOrdered()
|
||||
{
|
||||
$map = new MultiMap(KeyType::MULTIPLE, OrderType::STRICT);
|
||||
|
||||
$inserted = $map->add(['a', 'b'], 'val2');
|
||||
$inserted = $map->add(['a', 'c'], 'val3', false);
|
||||
|
||||
self::assertEquals(2, \count($map->keys()));
|
||||
self::assertEquals(2, \count($map->values()));
|
||||
|
||||
$removed = $map->remove(['b', 'a']);
|
||||
self::assertFalse($removed);
|
||||
|
||||
$removed = $map->remove(['a', 'b']);
|
||||
self::assertTrue($removed);
|
||||
self::assertEquals(1, \count($map->keys()));
|
||||
self::assertEquals(1, \count($map->values()));
|
||||
|
||||
self::assertFalse($map->removeKey(['a', 'b']));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user