Skip to content

Commit

Permalink
Add Psalm annotations and minor fixes (#77)
Browse files Browse the repository at this point in the history
* Set ErrorLevel 2
* Add psalm annotations for modifiers and getArguments
* Add annotations for toArray and performMerge
* Add annotations for reverse merge
* Add annotations for getValue
* Add annotations for ArraySorter
* Add annotations for modifiers
* Fix CS, set ErrorLevel 2 for psalm
  • Loading branch information
Fantom409 committed Dec 8, 2020
1 parent f0c3042 commit 7d5d264
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 7 deletions.
2 changes: 1 addition & 1 deletion psalm.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<psalm
errorLevel="6"
errorLevel="2"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
Expand Down
66 changes: 64 additions & 2 deletions src/ArrayHelper.php
Expand Up @@ -63,6 +63,7 @@ public static function toArray($object, array $properties = [], bool $recursive
{
if (is_array($object)) {
if ($recursive) {
/** @var mixed $value */
foreach ($object as $key => $value) {
if (is_array($value) || is_object($value)) {
$object[$key] = static::toArray($value, $properties, true);
Expand All @@ -78,10 +79,16 @@ public static function toArray($object, array $properties = [], bool $recursive
$className = get_class($object);
if (!empty($properties[$className])) {
$result = [];
/**
* @var int|string $key
* @var string $name
*/
foreach ($properties[$className] as $key => $name) {
if (is_int($key)) {
/** @var mixed */
$result[$name] = $object->$name;
} else {
/** @var mixed */
$result[$key] = static::getValue($object, $name);
}
}
Expand All @@ -93,7 +100,12 @@ public static function toArray($object, array $properties = [], bool $recursive
$result = $object->toArray([], [], $recursive);
} else {
$result = [];
/**
* @var string $key
* @var mixed $value
*/
foreach ($object as $key => $value) {
/** @var mixed */
$result[$key] = $value;
}
}
Expand Down Expand Up @@ -135,16 +147,20 @@ private static function performMerge(array ...$args): array
{
$res = array_shift($args) ?: [];
while (!empty($args)) {
/** @psalm-var mixed $v */
foreach (array_shift($args) as $k => $v) {
if (is_int($k)) {
if (array_key_exists($k, $res) && $res[$k] !== $v) {
/** @var mixed */
$res[] = $v;
} else {
/** @var mixed */
$res[$k] = $v;
}
} elseif (is_array($v) && isset($res[$k]) && is_array($res[$k])) {
$res[$k] = self::performMerge($res[$k], $v);
} else {
/** @var mixed */
$res[$k] = $v;
}
}
Expand All @@ -157,16 +173,20 @@ private static function performReverseBlockMerge(array ...$args): array
{
$res = array_pop($args) ?: [];
while (!empty($args)) {
/** @psalm-var mixed $v */
foreach (array_pop($args) as $k => $v) {
if (is_int($k)) {
if (array_key_exists($k, $res) && $res[$k] !== $v) {
/** @var mixed */
$res[] = $v;
} else {
/** @var mixed */
$res[$k] = $v;
}
} elseif (is_array($v) && isset($res[$k]) && is_array($res[$k])) {
$res[$k] = self::performReverseBlockMerge($v, $res[$k]);
} elseif (!isset($res[$k])) {
/** @var mixed */
$res[$k] = $v;
}
}
Expand All @@ -190,6 +210,7 @@ private static function performReverseBlockMerge(array ...$args): array
public static function applyModifiers(array $data): array
{
$modifiers = [];
/** @psalm-var mixed $v */
foreach ($data as $k => $v) {
if ($v instanceof ModifierInterface) {
$modifiers[$k] = $v;
Expand Down Expand Up @@ -250,8 +271,10 @@ public static function getValue($array, $key, $default = null)
}

if (is_array($key)) {
/** @psalm-var array<mixed,string|int> $key */
$lastKey = array_pop($key);
foreach ($key as $keyPart) {
/** @var mixed */
$array = static::getRootValue($array, $keyPart, $default);
}
return static::getRootValue($array, $lastKey, $default);
Expand All @@ -261,7 +284,7 @@ public static function getValue($array, $key, $default = null)
}

/**
* @param array|object $array array or object to extract value from
* @param mixed $array array or object to extract value from, otherwise method will return $default
* @param float|int|string $key key name of the array element or property name of the object,
* @param mixed $default the default value to be returned if the specified array key does not exist. Not used when
* getting value from an object.
Expand Down Expand Up @@ -365,11 +388,14 @@ public static function getValueByPath($array, $path, $default = null, string $de
* @param array|float|int|string|null $key the path of where do you want to write a value to `$array`
* the path can be described by an array of keys
* if the path is null then `$array` will be assigned the `$value`
* @psalm-param array<mixed, string|int|float>|float|int|string|null $key
*
* @param mixed $value the value to be written
*/
public static function setValue(array &$array, $key, $value): void
{
if ($key === null) {
/** @var mixed */
$array = $value;
return;
}
Expand All @@ -387,6 +413,7 @@ public static function setValue(array &$array, $key, $value): void
$array = &$array[$k];
}

/** @var mixed */
$array[static::normalizeArrayKey(array_shift($keys))] = $value;
}

Expand Down Expand Up @@ -489,6 +516,8 @@ private static function parsePath($path, string $delimiter)
*
* @param array $array the array to extract value from
* @param array|float|int|string $key key name of the array element or associative array at the key path specified
* @psalm-param array<mixed, float|int|string>|float|int|string $key
*
* @param mixed $default the default value to be returned if the specified key does not exist
*
* @return mixed the value of the element if found, default value otherwise
Expand All @@ -507,6 +536,7 @@ public static function remove(array &$array, $key, $default = null)

$key = static::normalizeArrayKey(array_shift($keys));
if (array_key_exists($key, $array)) {
/** @var mixed */
$value = $array[$key];
unset($array[$key]);
return $value;
Expand Down Expand Up @@ -563,8 +593,10 @@ public static function removeByPath(array &$array, $path, $default = null, strin
public static function removeValue(array &$array, $value): array
{
$result = [];
/** @psalm-var mixed $val */
foreach ($array as $key => $val) {
if ($val === $value) {
/** @var mixed */
$result[$key] = $val;
unset($array[$key]);
}
Expand Down Expand Up @@ -666,6 +698,8 @@ public static function removeValue(array &$array, $value): array
* ```
*
* @param array $array the array that needs to be indexed or grouped
* @psalm-param array<mixed, array|object> $array
*
* @param Closure|string|null $key the column name or anonymous function which result will be used to index the array
* @param Closure[]|string|string[]|null $groups the array of keys, that will be used to group the input array
* by one or more keys. If the $key attribute or its value for the particular element is null and $groups is not
Expand All @@ -680,6 +714,14 @@ public static function index(array $array, $key, $groups = []): array
$groups = (array)$groups;

foreach ($array as $element) {
/** @psalm-suppress DocblockTypeContradiction */
if (!is_array($element) && !is_object($element)) {
throw new \InvalidArgumentException(
'index() can not get value from ' . gettype($element)
. '. The $array should be either multidimensional array or an array of objects.'
);
}

$lastArray = &$result;

foreach ($groups as $group) {
Expand Down Expand Up @@ -727,6 +769,8 @@ public static function index(array $array, $key, $groups = []): array
* ```
*
* @param array $array
* @psalm-param array<mixed, array|object> $array
*
* @param Closure|string $name
* @param bool $keepKeys whether to maintain the array keys. If false, the resulting array
* will be re-indexed with integers.
Expand All @@ -738,10 +782,12 @@ public static function getColumn(array $array, $name, bool $keepKeys = true): ar
$result = [];
if ($keepKeys) {
foreach ($array as $k => $element) {
/** @var mixed */
$result[$k] = static::getValue($element, $name);
}
} else {
foreach ($array as $element) {
/** @var mixed */
$result[] = static::getValue($element, $name);
}
}
Expand Down Expand Up @@ -785,6 +831,8 @@ public static function getColumn(array $array, $name, bool $keepKeys = true): ar
* ```
*
* @param array $array
* @psalm-param array<mixed, array|object> $array
*
* @param Closure|string $from
* @param Closure|string $to
* @param Closure|string|null $group
Expand All @@ -800,6 +848,7 @@ public static function map(array $array, $from, $to, $group = null): array
$result = [];
foreach ($array as $element) {
$key = static::getValue($element, $from);
/** @var mixed */
$result[static::getValue($element, $group)][$key] = static::getValue($element, $to);
}

Expand All @@ -824,7 +873,7 @@ public static function keyExists(array $array, string $key, bool $caseSensitive
}

foreach (array_keys($array) as $k) {
if (strcasecmp($key, $k) === 0) {
if (strcasecmp($key, (string) $k) === 0) {
return true;
}
}
Expand All @@ -839,6 +888,8 @@ public static function keyExists(array $array, string $key, bool $caseSensitive
* Only string values will be encoded.
*
* @param array $data data to be encoded
* @psalm-param array<mixed, mixed> $data
*
* @param bool $valuesOnly whether to encode array values only. If false,
* both the array keys and array values will be encoded.
* @param string|null $encoding The encoding to use, defaults to `ini_get('default_charset')`.
Expand All @@ -850,6 +901,7 @@ public static function keyExists(array $array, string $key, bool $caseSensitive
public static function htmlEncode(array $data, bool $valuesOnly = true, string $encoding = null): array
{
$d = [];
/** @var mixed $value */
foreach ($data as $key => $value) {
if (!$valuesOnly && is_string($key)) {
/** @psalm-suppress PossiblyNullArgument */
Expand All @@ -861,6 +913,7 @@ public static function htmlEncode(array $data, bool $valuesOnly = true, string $
} elseif (is_array($value)) {
$d[$key] = static::htmlEncode($value, $valuesOnly, $encoding);
} else {
/** @var mixed */
$d[$key] = $value;
}
}
Expand All @@ -875,6 +928,8 @@ public static function htmlEncode(array $data, bool $valuesOnly = true, string $
* Only string values will be decoded.
*
* @param array $data data to be decoded
* @psalm-param array<mixed, mixed> $data
*
* @param bool $valuesOnly whether to decode array values only. If false,
* both the array keys and array values will be decoded.
*
Expand All @@ -885,6 +940,7 @@ public static function htmlEncode(array $data, bool $valuesOnly = true, string $
public static function htmlDecode(array $data, bool $valuesOnly = true): array
{
$d = [];
/** @psalm-var mixed $value */
foreach ($data as $key => $value) {
if (!$valuesOnly && is_string($key)) {
$key = htmlspecialchars_decode($key, ENT_QUOTES);
Expand All @@ -894,6 +950,7 @@ public static function htmlDecode(array $data, bool $valuesOnly = true): array
} elseif (is_array($value)) {
$d[$key] = static::htmlDecode($value);
} else {
/** @var mixed */
$d[$key] = $value;
}
}
Expand Down Expand Up @@ -922,6 +979,7 @@ public static function isAssociative(array $array, bool $allStrings = true): boo
}

if ($allStrings) {
/** @psalm-suppress MixedAssignment */
foreach ($array as $key => $value) {
if (!is_string($key)) {
return false;
Expand All @@ -931,6 +989,7 @@ public static function isAssociative(array $array, bool $allStrings = true): boo
return true;
}

/** @psalm-suppress MixedAssignment */
foreach ($array as $key => $value) {
if (is_string($key)) {
return true;
Expand Down Expand Up @@ -964,6 +1023,7 @@ public static function isIndexed(array $array, bool $consecutive = false): bool
return array_keys($array) === range(0, count($array) - 1);
}

/** @psalm-var mixed $value */
foreach ($array as $key => $value) {
if (!is_int($key)) {
return false;
Expand Down Expand Up @@ -995,6 +1055,7 @@ public static function isIn($needle, iterable $haystack, bool $strict = false):
return in_array($needle, $haystack, $strict);
}

/** @psalm-var mixed $value */
foreach ($haystack as $value) {
if ($needle == $value && (!$strict || $needle === $value)) {
return true;
Expand All @@ -1020,6 +1081,7 @@ public static function isIn($needle, iterable $haystack, bool $strict = false):
*/
public static function isSubset(iterable $needles, iterable $haystack, bool $strict = false): bool
{
/** @psalm-var mixed $needle */
foreach ($needles as $needle) {
if (!static::isIn($needle, $haystack, $strict)) {
return false;
Expand Down
17 changes: 14 additions & 3 deletions src/ArraySorter.php
Expand Up @@ -37,9 +37,14 @@ class ArraySorter
* elements, a property name of the objects, or an anonymous function returning the values for comparison
* purpose. The anonymous function signature should be: `function($item)`.
* To sort by multiple keys, provide an array of keys here.
* @psalm-param array<mixed,\Closure|string>|\Closure|string $key
*
* @param array|int $direction the sorting direction. It can be either `SORT_ASC` or `SORT_DESC`.
* When sorting by multiple keys with different sorting directions, use an array of sorting directions.
* @psalm-param array<mixed, int>|int $direction
*
* @param array|int $sortFlag the PHP sort flag. Valid values include
* @psalm-param array<mixed, int>|int $sortFlag
* `SORT_REGULAR`, `SORT_NUMERIC`, `SORT_STRING`, `SORT_LOCALE_STRING`, `SORT_NATURAL` and `SORT_FLAG_CASE`.
* Please refer to [PHP manual](http://php.net/manual/en/function.sort.php)
* for more details. When sorting by multiple keys with different sort flags, use an array of sort flags.
Expand Down Expand Up @@ -96,6 +101,7 @@ private static function getKeys(array $array, $key): array
// Check if the array is multidimensional
if (count($keysTemp) !== count($keysTemp, COUNT_RECURSIVE)) {
// If it is multidimensional then get keys
/** @var array */
$keys = $keysTemp[0];
}
}
Expand All @@ -108,16 +114,21 @@ private static function getKeys(array $array, $key): array
*
* @param array $array the array to be sorted
* @param array $keys array of keys
* @psalm-param array<mixed, string|\Closure> $keys
*
* @param array $direction array of sorting directions
* @param array $sortFlag array of sort flags
* @psalm-param array<mixed, int> $direction
*
* @param array $sortFlags array of sort flags
* @psalm-param array<mixed, int> $sortFlags
*
* @return array return the arguments
*/
private static function getArguments(array $array, array $keys, array $direction, array $sortFlag): array
private static function getArguments(array $array, array $keys, array $direction, array $sortFlags): array
{
$args = [];
foreach ($keys as $i => $iKey) {
$flag = $sortFlag[$i];
$flag = $sortFlags[$i];
$args[] = ArrayHelper::getColumn($array, $iKey);
$args[] = $direction[$i];
$args[] = $flag;
Expand Down
3 changes: 3 additions & 0 deletions src/Modifier/InsertValueBeforeKey.php
Expand Up @@ -58,10 +58,13 @@ public function __construct($value, string $key)
public function apply(array $data, $key): array
{
$res = [];
/** @psalm-var mixed $v */
foreach ($data as $k => $v) {
if ($k === $this->key) {
/** @var mixed */
$res[$key] = $this->value;
}
/** @var mixed */
$res[$k] = $v;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Modifier/ModifierInterface.php
Expand Up @@ -11,7 +11,7 @@ interface ModifierInterface
{
/**
* @param array $data
* @param mixed $key
* @param int|string $key
*
* @return array
*/
Expand Down

0 comments on commit 7d5d264

Please sign in to comment.