diff --git a/src/StaticUtil/AbstractStaticUtil.php b/src/StaticUtil/AbstractStaticUtil.php new file mode 100644 index 00000000..72639ee9 --- /dev/null +++ b/src/StaticUtil/AbstractStaticUtil.php @@ -0,0 +1,15 @@ + $class + * @return T The instance of the given class. + */ + protected static function getInstance(string $class): object + { + if (!isset(static::$instances[$class])) { + static::$instances[$class] = new $class; + } + + return static::$instances[$class]; + } +} \ No newline at end of file diff --git a/src/StaticUtil/StaticArrayUtil.php b/src/StaticUtil/StaticArrayUtil.php new file mode 100644 index 00000000..35527399 --- /dev/null +++ b/src/StaticUtil/StaticArrayUtil.php @@ -0,0 +1,100 @@ + $value) { + if (\in_array($k, $keys)) { + $new[$newKey] = $newValue; + } + $new[$k] = $value; + } + $array = $new; + } else { + $array[$newKey] = $newValue; + } + } + + /** + * Insert a value into an existing array by key name. + * + * Additional options: + * - (bool) strict: Strict behavior for array search. Default false + * - (bool) attachMissingKey: Attach value to the end of the array if the key does not exist. Default: true + * - (int) offset: Add additional offset. + * + * @param array $array The target array + * @param string $key the existing target key in the array + * @param mixed $value the new value to be inserted + * @param array{ + * strict?: bool, + * attachMissingKey?: bool, + * offset?: int + * } $options Additional options + */ + public static function insertAfterKey(array &$array, string $key, mixed $value, string $newKey = null, array $options = []): void + { + $options = array_merge([ + 'strict' => false, + 'attachMissingKey' => true, + 'offset' => 0, + ], $options); + + $keys = array_keys($array); + $index = array_search($key, $keys, $options['strict']); + + if (false === $index && false === $options['attachMissingKey']) { + return; + } + $pos = false === $index ? count($array) : $index + 1; + $pos = $pos + $options['offset']; + + if ($newKey) { + $value = [$newKey => $value]; + } else { + $value = [$value]; + } + + $array = array_combine( + array_merge(array_slice($keys, 0, $pos), array_keys($value), array_slice($keys, $pos)), + array_merge(array_slice($array, 0, $pos), $value, array_slice($array, $pos)) + ); + } + + /** + * Removes a value from an array. + * + * @return bool Returns true if the value has been found and removed, false in other cases + */ + public static function removeValue(mixed $value, array &$array): bool + { + $position = array_search($value, $array); + + if (false !== $position) { + unset($array[$position]); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/StaticUtil/StaticClassUtil.php b/src/StaticUtil/StaticClassUtil.php new file mode 100644 index 00000000..d7cf1fd0 --- /dev/null +++ b/src/StaticUtil/StaticClassUtil.php @@ -0,0 +1,24 @@ +insertBeforeKey(...)} instead. */ public static function insertBeforeKey(array &$array, array|string $keys, string $newKey, mixed $newValue): void { - if (!\is_array($keys)) { - $keys = [$keys]; - } - - if (array_intersect($keys, array_keys($array))) { - $new = []; - - foreach ($array as $k => $value) { - if (\in_array($k, $keys)) { - $new[$newKey] = $newValue; - } - $new[$k] = $value; - } - $array = $new; - } else { - $array[$newKey] = $newValue; - } + StaticArrayUtil::insertBeforeKey($array, $keys, $newKey, $newValue); } /** @@ -47,59 +35,36 @@ public static function insertBeforeKey(array &$array, array|string $keys, string * Additional options: * - (bool) strict: Strict behavior for array search. Default false * - (bool) attachIfKeyNotExist: Attach value at the end of the array if key not exist. Default: true - * - (int) offset: Add an additional offset + * - (int) offset: Add additional offset * * @param array $array The target array * @param string $key the existing target key in the array * @param mixed $value the new value to be inserted * @param array{ - * strict?: bool, - * attachIfKeyNotExist?: bool, - * offset?: int + * strict?: bool, + * attachIfKeyNotExist?: bool, + * offset?: int * } $options Additional options + * + * @deprecated Use {@see StaticArrayUtil::insertAfterKey() SUtil::array()->insertAfterKey(...)} instead. + * Beware: The option keys have changed! */ public function insertAfterKey(array &$array, string $key, mixed $value, string $newKey = null, array $options = []): void { - $options = array_merge([ - 'strict' => false, - 'attachIfKeyNotExist' => true, - 'offset' => 0, - ], $options); - - $keys = array_keys($array); - $index = array_search($key, $keys, $options['strict']); + $options['attachMissingKey'] ??= $options['attachIfKeyNotExist'] ?? true; - if (false === $index && false === $options['attachIfKeyNotExist']) { - return; - } - $pos = false === $index ? \count($array) : $index + 1; - $pos = $pos + $options['offset']; - - if ($newKey) { - $value = [$newKey => $value]; - } else { - $value = [$value]; - } - - $array = array_combine( - array_merge(\array_slice($keys, 0, $pos), array_keys($value), \array_slice($keys, $pos)), - array_merge(\array_slice($array, 0, $pos), $value, \array_slice($array, $pos)) - ); + StaticArrayUtil::insertAfterKey($array, $key, $value, $newKey, $options); } /** - * Removes a value in an array. + * Removes a value from an array. + * + * @return bool True if the value was found and removed, false otherwise. * - * @return bool Returns true if the value has been found and removed, false in other cases + * @deprecated Use {@see StaticArrayUtil::removeValue() SUtil::array()->removeValue(...)} instead. */ public function removeValue(mixed $value, array &$array): bool { - if (false !== ($intPosition = array_search($value, $array))) { - unset($array[$intPosition]); - - return true; - } - - return false; + return StaticArrayUtil::removeValue($value, $array); } } diff --git a/src/Util/ClassUtil.php b/src/Util/ClassUtil.php index 98193398..70347af4 100644 --- a/src/Util/ClassUtil.php +++ b/src/Util/ClassUtil.php @@ -2,20 +2,17 @@ namespace HeimrichHannot\UtilsBundle\Util; +use HeimrichHannot\UtilsBundle\StaticUtil\StaticClassUtil; + class ClassUtil { /** * Return true if the given class or a parent class implements the given trait + * + * @deprecated Use {@see StaticClassUtil::hasTrait() SUtil::class()->hasTrait(...)} instead. */ public function classImplementsTrait(object|string $class, string $trait): bool { - do { - if (in_array($trait, class_uses($class))) { - return true; - } - - } while($class = get_parent_class($class)); - - return false; + return StaticClassUtil::hasTrait($class, $trait); } } \ No newline at end of file diff --git a/tests/StaticUtil/SUtilsTest.php b/tests/StaticUtil/SUtilsTest.php new file mode 100644 index 00000000..bddaba0d --- /dev/null +++ b/tests/StaticUtil/SUtilsTest.php @@ -0,0 +1,17 @@ +assertInstanceOf(StaticArrayUtil::class, SUtils::array()); + $this->assertInstanceOf(StaticClassUtil::class, SUtils::class()); + } +} \ No newline at end of file diff --git a/tests/StaticUtil/StaticArrayUtilTest.php b/tests/StaticUtil/StaticArrayUtilTest.php new file mode 100644 index 00000000..5f9039ff --- /dev/null +++ b/tests/StaticUtil/StaticArrayUtilTest.php @@ -0,0 +1,77 @@ +getTestInstance(); + $array = ['a' => 'A', 'b' => 'B', 'c' => 'C']; + + $instance::insertBeforeKey($array, 'e', 'f', 'F'); + $this->assertSame( + ['a' => 'A', 'b' => 'B', 'c' => 'C', 'f' => 'F'], $array); + + $instance::insertBeforeKey($array, ['z'], 'h', 'H'); + $this->assertSame( + ['a' => 'A', 'b' => 'B', 'c' => 'C', 'f' => 'F', 'h' => 'H'], $array); + + $instance::insertBeforeKey($array, ['f', 'h'], 'd', 'D'); + $this->assertSame( + ['a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D', 'f' => 'F', 'h' => 'H'], $array); + } + + public function testInsertAfterKey() + { + $arrayUtil = $this->getTestInstance(); + + $target = ['hello' => 'world']; + $arrayUtil->insertAfterKey($target, 'foo', 'bar'); + $this->assertSame(['hello' => 'world', 0 => 'bar'], $target); + + $target = ['hello' => 'world']; + $arrayUtil->insertAfterKey($target, 'foo', 'bar', 'foobar'); + $this->assertSame(['hello' => 'world', 'foobar' => 'bar'], $target); + + $target = ['hello' => 'world']; + $arrayUtil->insertAfterKey($target, 'foo', 'bar', null, ['attachMissingKey' => false]); + $this->assertSame(['hello' => 'world'], $target); + + $target = ['hello' => 'world', 'foo' => 'bar', 'heimrich' => 'hannot']; + $arrayUtil->insertAfterKey($target, 'hello', 'camp', 'contao', ['offset' => 1]); + $this->assertSame(['hello' => 'world', 'foo' => 'bar', 'contao' => 'camp', 'heimrich' => 'hannot'], $target); + + $target = ['1' => 'world', 'foo' => 'bar', 'heimrich' => 'hannot']; + $arrayUtil->insertAfterKey($target, 1, 'camp', 'contao', ['strict' => false]); + $this->assertSame(['1' => 'world', 'contao' => 'camp', 'foo' => 'bar', 'heimrich' => 'hannot'], $target); + + $target = ['1' => 'world', 'foo' => 'bar', 'heimrich' => 'hannot']; + $arrayUtil->insertAfterKey($target, 1, 'camp', 'contao', ['strict' => true]); + $this->assertSame(['1' => 'world', 'foo' => 'bar', 'heimrich' => 'hannot', 'contao' => 'camp'], $target); + } + + public function testRemoveValue() + { + $arrayUtil = $this->getTestInstance(); + + $array = [0 => 0, 1 => 1, 2 => 2]; + $result = $arrayUtil->removeValue(1, $array); + $this->assertTrue($result); + $this->assertCount(2, $array); + $this->assertArrayHasKey(0, $array); + $this->assertArrayHasKey(2, $array); + + $result = $arrayUtil->removeValue(1, $array); + $this->assertFalse($result); + } +} \ No newline at end of file diff --git a/tests/Util/Type/ArrayUtilTest.php b/tests/Util/Type/ArrayUtilTest.php index da878b00..b6cd3b1b 100644 --- a/tests/Util/Type/ArrayUtilTest.php +++ b/tests/Util/Type/ArrayUtilTest.php @@ -14,7 +14,7 @@ class ArrayUtilTest extends AbstractUtilsTestCase { - public function getTestInstance(array $parameters = [], ?MockBuilder $mockBuilder = null) + public function getTestInstance(array $parameters = [], ?MockBuilder $mockBuilder = null): ArrayUtil { return new ArrayUtil(); }