src/includes/DataTypes/Arrays.php
<?php
namespace DeepWebSolutions\Framework\Helpers\DataTypes;
\defined( 'ABSPATH' ) || exit;
/**
* A collection of very useful array manipulation helpers to be used throughout the projects.
*
* @since 1.0.0
* @version 1.5.6
* @author Antonius Hegyes <a.hegyes@deep-web-solutions.com>
* @package DeepWebSolutions\WP-Framework\Helpers\DataTypes
*/
final class Arrays {
// region POLYFILLS
/**
* Checks whether a given array is a list or not. An array is considered a list if its keys consist of consecutive numbers from 0 to count($array)-1.
*
* @since 1.5.6
* @version 1.5.6
*
* @see https://www.php.net/manual/en/function.array-is-list.php#126574
*
* @param array $array The array to check.
*
* @return bool True if the array is a list, false otherwise.
*/
public static function is_list( array $array ): bool {
if ( \PHP_VERSION_ID >= 80100 && \function_exists( '\array_is_list' ) ) {
return \array_is_list( $array );
}
return array() === $array || ( \array_keys( $array ) === \range( 0, \count( $array ) - 1 ) );
}
// endregion
/**
* Returns a given variable if it is an array or a default value if not.
*
* @since 1.4.0
* @version 1.4.0
*
* @param mixed $array Variable to check.
* @param array|null $default The default value to return if check fails. By default, null.
*
* @return array|null
*/
public static function validate( $array, ?array $default = null ): ?array {
return \is_array( $array ) ? $array : $default;
}
/**
* Attempts to turn a variable of unknown type into an array.
*
* @since 1.4.0
* @version 1.4.0
*
* @param mixed $array Variable to cast.
* @param array|null $default The default value to return if all fails. By default, null.
*
* @return array|null
*/
public static function maybe_cast( $array, ?array $default = null ): ?array {
if ( ! \is_null( self::validate( $array ) ) ) {
return $array;
}
if ( ! \is_null( $array ) ) {
return array( $array );
}
return $default;
}
/**
* Attempts to cast a variable from an input stream into an array.
*
* @since 1.4.0
* @version 1.4.0
*
* @param int $input_type One of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, or INPUT_ENV.
* @param string $variable_name Name of a variable to get.
* @param array|null $default The default value to return if all fails.
*
* @return array|null
*/
public static function maybe_cast_input( int $input_type, string $variable_name, ?array $default = null ): ?array {
if ( \filter_has_var( $input_type, $variable_name ) ) {
$array = \filter_input( $input_type, $variable_name, FILTER_UNSAFE_RAW, FILTER_FORCE_ARRAY );
return self::maybe_cast( $array, $default );
}
return $default;
}
/**
* Attempts to resolve a potential callable to an array value.
*
* @since 1.7.0
* @version 1.7.0
*
* @param mixed|callable $array Potential callable to resolve.
* @param array|null $default Default value to return on failure. By default, null.
* @param array $args Arguments to pass on to the callable. By default, none.
*
* @return array|null
*/
public static function resolve( $array, ?array $default = null, array $args = array() ): ?array {
return self::maybe_cast( Callables::maybe_resolve( $array, $args ), $default );
}
/**
* Validates an array of values against a safe-list. Returns a new array containing only valid entries.
*
* @since 1.4.0
* @version 1.4.0
*
* @param array $entries Array of entries to validate.
* @param array $allowed Array of allowed entries.
* @param mixed|null $default The value to replace invalid entries with.
*
* @return array
*/
public static function validate_allowed( array $entries, array $allowed, $default = null ): array {
return \array_map(
static function( $entry ) use ( $allowed, $default ) {
$is_allowed = \in_array( $entry, $allowed, true );
if ( false === $is_allowed && Strings::validate( $entry ) ) {
$entry = \trim( $entry );
$is_allowed = \in_array( $entry, $allowed, true );
}
return $is_allowed ? $entry : $default;
},
$entries
);
}
/**
* Checks whether an array has any string keys or if they are all numerical.
*
* @since 1.0.0
* @version 1.0.0
*
* @param array $array The array to check.
*
* @return bool True if it has string keys, false otherwise.
*/
public static function has_string_keys( array $array ): bool {
return \count( \array_filter( \array_keys( $array ), '\is_string' ) ) > 0;
}
/**
* Inserts new array entries after a given key within an existing array. If the key is not found,
* appends entries at the end of the array.
*
* @since 1.0.0
* @version 1.0.2
* @see https://gist.github.com/wpscholar/0deadce1bbfa4adb4e4c
*
* @param array $array Associative array to insert the new entries into.
* @param string|int $key Key to insert the entries after.
* @param array $new_entries The new entries to insert.
*
* @return array
*/
public static function insert_after( array $array, $key, array $new_entries ): array {
$index = \array_search( $key, \array_keys( $array ), true );
$position = ( false === $index ) ? \count( $array ) : ( $index + 1 );
if ( empty( $array ) || self::has_string_keys( $array ) ) {
$array = \array_slice( $array, 0, $position, true ) + $new_entries + \array_slice( $array, $position, null, true );
} else {
\array_splice( $array, $position, 0, $new_entries );
}
return $array;
}
/**
* Returns all the entries in a given array that match a given needle.
*
* @since 1.0.0
* @version 1.4.0
*
* @param array $array Array to search through.
* @param mixed $needle The value to search for.
* @param callable|null $callback Optional callback to run the value through before needle comparison.
* @param bool $strict Whether to perform type checks or not.
*
* @return array|null
*/
public static function search_values( array $array, $needle, ?callable $callback = null, bool $strict = true ): ?array {
$comparison_array = \is_callable( $callback ) ? \array_map( $callback, $array ) : $array;
foreach ( $comparison_array as $key => $value ) {
if ( ( $strict && $needle === $value ) || ( ! $strict && $needle == $value ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
continue;
}
unset( $array[ $key ] );
}
return empty( $array ) ? null : $array;
}
/**
* Returns all the keys in a given array that match a given needle.
*
* @since 1.0.0
* @version 1.0.0
*
* @param array $array Array whose keys to search through.
* @param mixed $needle The value to search for.
* @param callable|null $callback Optional callback to run the key through before needle comparison.
* @param bool $strict Whether to perform type checks or not.
*
* @return array|null
*/
public static function search_keys( array $array, $needle, ?callable $callback = null, bool $strict = false ): ?array {
return self::search_values( \array_keys( $array ), $needle, $callback, $strict );
}
}