; foreach ($merged as $key => $value) { if ( is_array($value) && isset($defaults[$key]) && is_array($defaults[$key]) ) { // Recursively merge arrays $merged[$key] = static::mergeMissingValues( $value, $defaults[$key] ); } elseif ( isset($defaults[$key]) && (is_null($value) || $value === '') ) { // Replace null or empty values $merged[$key] = $defaults[$key]; } } return $merged; } /** * Return matching items from array (similar to mysql's %LIKE%) * * @param string|regex $pattern * @param array $array * @return array|false */ public static function like($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~'. preg_quote($pattern, '~') . '~i'; } return preg_grep($pattern, $array); } /** * Return non-matching items from array (similar to mysql's NOT %LIKE%) * * @param string|regex $pattern * @param array $array * @return array|false */ public static function notLike($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~'. preg_quote($pattern, '~') . '~i'; } return preg_grep($pattern, $array, PREG_GREP_INVERT); } /** * Return matching starting of items from array (similar to mysql's %LIKE) * * @param string|regex $pattern * @param array $array * @return array|false */ public static function startsLike($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~^'. preg_quote($pattern, '~') . '~i'; } return preg_grep($pattern, $array); } /** * Return non-matching starting of items from array (similar to mysql's NOT %LIKE) * * @param string|regex $pattern * @param array $array * @return array|false */ public static function DoesNotStartLike($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~^(?!' . preg_quote($pattern, '~') . ')~i'; } return preg_grep($pattern, $array); } /** * Return matching ending of items from array (similar to mysql's LIKE%) * * @param string|regex $pattern * @param array $array * @return array|false */ public static function endsLike($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~'. preg_quote($pattern, '~') . '$~i'; } return preg_grep($pattern, $array); } /** * Return non-matching ending of items from array (similar to mysql's NOT LIKE%) * * @param string|regex $pattern * @param array $array * @return array|false */ public static function DoesNotEndLike($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~'. preg_quote($pattern, '~') . '$~i'; } return preg_grep($pattern, $array, PREG_GREP_INVERT); } /** * Return matching items from array by keys * * @param string|regex $pattern * @param array $array * @return array|false */ public static function keysLike($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~'. preg_quote($pattern, '~') . '~i'; } $values = []; $keys = preg_grep($pattern, array_keys($array)); foreach ($keys as $key) { $values[$key] = $array[$key]; } return $values; } /** * Return non-matching items from array by keys * * @param string|regex $pattern * @param array $array * @return array|false */ public static function keysNotLike($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~'. preg_quote($pattern, '~') . '~i'; } $values = []; $keys = preg_grep($pattern, array_keys($array), 1); foreach ($keys as $key) { $values[$key] = $array[$key]; } return $values; } /** * Return matching starting of items from array by keys * * @param string|regex $pattern * @param array $array * @return array|false */ public static function keysStartLike($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~^'. preg_quote($pattern, '~') . '~i'; } $values = []; $keys = preg_grep($pattern, array_keys($array)); foreach ($keys as $key) { $values[$key] = $array[$key]; } return $values; } /** * Return non-matching starting of items from array by keys * * @param string|regex $pattern * @param array $array * @return array|false */ public static function keysDoesNotStartLike($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~^(?!' . preg_quote($pattern, '~') . ')~i'; } $values = []; $keys = preg_grep($pattern, array_keys($array)); foreach ($keys as $key) { $values[$key] = $array[$key]; } return $values; } /** * Return matching ending of items from array by keys * * @param string|regex $pattern * @param array $array * @return array|false */ public static function keysEndLike($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~'. preg_quote($pattern, '~') . '$~i'; } $values = []; $keys = preg_grep($pattern, array_keys($array)); foreach ($keys as $key) { $values[$key] = $array[$key]; } return $values; } /** * Return non-matching ending of items from array by keys * * @param string|regex $pattern * @param array $array * @return array|false */ public static function keysDoesNotEndLike($array, $pattern) { if (!preg_match('/^([\/#~]).*\1$/', $pattern)) { $pattern = '~'. preg_quote($pattern, '~') . '$~i'; } $values = []; $keys = preg_grep($pattern, array_keys($array), PREG_GREP_INVERT); foreach ($keys as $key) { $values[$key] = $array[$key]; } return $values; } /** * Insert a new item in the array at the given position. * * @param array $array * @param int $pos * @param mixed $newItem * @return array */ public static function insertAt($array, $pos, $newItem) { if (!isset($array[$pos])) { $array[] = $newItem; } else { $array = array_splice($array, $pos, 0, $newItem); } return $array; } /** * Inserts an item before the specified key in the given array. If the * key is not found, inserts the item at the beginning of the array. * * @param array $array * @param mixed $key * @param mixed $newKey * @param mixed $newValue * @return array $newArray */ public static function insertBefore($array, $key, $newKey, $newValue) { $newArray = []; $keyFound = false; foreach ($array as $k => $v) { if ($k === $key) { $newArray[$newKey] = $newValue; $keyFound = true; } $newArray[$k] = $v; } if (!$keyFound) { $newArray = [$newKey => $newValue] + $newArray; } return $newArray; } /** * Inserts an item after the specified key in the given array. If the * key is not found, inserts the item at the end of the array. * * @param array $array * @param mixed $key * @param mixed $newKey * @param mixed $newValue * @return array $newArray */ public static function insertAfter($array, $key, $newKey, $newValue): array { $newArray = []; $keyFound = false; foreach ($array as $k => $v) { $newArray[$k] = $v; if ($k === $key) { $newArray[$newKey] = $newValue; $keyFound = true; } } if (!$keyFound) { $newArray[$newKey] = $newValue; } return $newArray; } /** * Tests whether at least one element in the array passes * the test implemented by the provided callback. * * @param array $array * @param callable $callback * @return bool */ public static function some($array, callable $callback) { foreach ($array as $k => $v) { if ($callback($v, $k, $array)) { return true; } } return false; } /** * Tests whether all elements in the array pass the * test implemented by the provided callback. * * @param array $array * @param callable $callback * @return bool */ public static function every($array, callable $callback) { foreach ($array as $k => $v) { if (!$callback($v, $k, $array)) { return false; } } return true; } /** * Finds the first element in the array that satisfies the * condition implemented by the callback function. * * @param array $array * @param callable $callback * @return mixed */ public static function find($array, callable $callback, $findKey = false) { foreach ($array as $k => $v) { if ($callback($v, $k, $array)) { return $findKey ? $k : $v; } } return null; } /** * Finds the first key in the array that satisfies the * condition implemented by the callback function. * * @param array $array * @param callable $callback * @return mixed */ public static function findKey($array, callable $callback) { return static::find($array, $callback, true); } }