Skip to content

Commit

Permalink
Merge pull request #82 from heimrichhannot/feature/static-utils
Browse files Browse the repository at this point in the history
Add static utilities
  • Loading branch information
ericges authored Mar 26, 2024
2 parents a75129f + bec2a5e commit daa00a0
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 63 deletions.
15 changes: 15 additions & 0 deletions src/StaticUtil/AbstractStaticUtil.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace HeimrichHannot\UtilsBundle\StaticUtil;

/**
* @internal
* @codeCoverageIgnore
*/
abstract class AbstractStaticUtil
{
public function __call(string $name, array $arguments)
{
return static::$name(...$arguments);
}
}
32 changes: 32 additions & 0 deletions src/StaticUtil/SUtils.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace HeimrichHannot\UtilsBundle\StaticUtil;

class SUtils
{
protected static array $instances = [];

public static function array(): StaticArrayUtil
{
return static::getInstance(StaticArrayUtil::class);
}

public static function class(): StaticClassUtil
{
return static::getInstance(StaticClassUtil::class);
}

/**
* @template T
* @param class-string<T> $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];
}
}
100 changes: 100 additions & 0 deletions src/StaticUtil/StaticArrayUtil.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

namespace HeimrichHannot\UtilsBundle\StaticUtil;

class StaticArrayUtil extends AbstractStaticUtil
{
/**
* Insert a new entry before a specific or multiple keys in array.
* If the keys not exist, the new entry is added to the end of the array.
* Array is passed as reference.
*
* @param array $array Array the new entry should inserted to
* @param array|string $keys The key or keys where the new entry should be added before
* @param string $newKey The key of the entry that should be added
* @param mixed $newValue The value of the entry that should be added
*/
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;
}
}

/**
* 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;
}
}
24 changes: 24 additions & 0 deletions src/StaticUtil/StaticClassUtil.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace HeimrichHannot\UtilsBundle\StaticUtil;

class StaticClassUtil extends AbstractStaticUtil
{
/**
* Check if a class or any of its parents implements a trait.
*
* @param object|class-string $class The class to check.
* @param class-string $trait The trait to check for.
* @return bool True if the class or any of its parents implements the trait, false otherwise.
*/
public static function hasTrait(object|string $class, string $trait): bool
{
do {
if (in_array($trait, class_uses($class))) {
return true;
}
} while ($class = get_parent_class($class));

return false;
}
}
73 changes: 19 additions & 54 deletions src/Util/ArrayUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

namespace HeimrichHannot\UtilsBundle\Util;

use HeimrichHannot\UtilsBundle\StaticUtil\StaticArrayUtil;

class ArrayUtil
{
/**
Expand All @@ -19,26 +21,12 @@ class ArrayUtil
* @param array|string $keys The key or keys where the new entry should be added before
* @param string $newKey The key of the entry that should be added
* @param mixed $newValue The value of the entry that should be added
*
* @deprecated Use {@see StaticArrayUtil::insertBeforeKey() SUtil::array()->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);
}

/**
Expand All @@ -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);
}
}
13 changes: 5 additions & 8 deletions src/Util/ClassUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
17 changes: 17 additions & 0 deletions tests/StaticUtil/SUtilsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace HeimrichHannot\UtilsBundle\Tests\StaticUtil;

use Contao\TestCase\ContaoTestCase;
use HeimrichHannot\UtilsBundle\StaticUtil\StaticArrayUtil;
use HeimrichHannot\UtilsBundle\StaticUtil\StaticClassUtil;
use HeimrichHannot\UtilsBundle\StaticUtil\SUtils;

class SUtilsTest extends ContaoTestCase
{
public function testSUtils()
{
$this->assertInstanceOf(StaticArrayUtil::class, SUtils::array());
$this->assertInstanceOf(StaticClassUtil::class, SUtils::class());
}
}
Loading

0 comments on commit daa00a0

Please sign in to comment.