Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add static utilities #82

Merged
merged 4 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading