ArrayUtil.php
7 months ago
BlocksUtil.php
5 months ago
COTMigrationUtil.php
1 year ago
DatabaseUtil.php
1 year ago
FilesystemUtil.php
3 months ago
HtmlSanitizer.php
2 years ago
LegacyRestApiStub.php
4 weeks ago
PluginInstaller.php
1 year ago
ProductUtil.php
9 months ago
Types.php
1 year ago
URL.php
1 year ago
URLException.php
4 years ago
Users.php
4 months ago
WebhookUtil.php
4 weeks ago
ArrayUtil.php
127 lines
| 1 | <?php |
| 2 | declare( strict_types=1 ); |
| 3 | |
| 4 | namespace Automattic\WooCommerce\Internal\Utilities; |
| 5 | |
| 6 | /** |
| 7 | * A class of utilities for dealing with arrays. |
| 8 | */ |
| 9 | class ArrayUtil { |
| 10 | |
| 11 | /** |
| 12 | * Determines if the given array is a list. |
| 13 | * |
| 14 | * An array is considered a list if its keys consist of consecutive numbers from 0 to count($array)-1. |
| 15 | * |
| 16 | * Polyfill for array_is_list() in PHP 8.1. |
| 17 | * |
| 18 | * @param array $arr The array being evaluated. |
| 19 | * |
| 20 | * @return bool True if array is a list, false otherwise. |
| 21 | */ |
| 22 | public static function array_is_list( array $arr ): bool { |
| 23 | if ( function_exists( 'array_is_list' ) ) { |
| 24 | return array_is_list( $arr ); |
| 25 | } |
| 26 | |
| 27 | if ( ( array() === $arr ) || ( array_values( $arr ) === $arr ) ) { |
| 28 | return true; |
| 29 | } |
| 30 | |
| 31 | $next_key = -1; |
| 32 | |
| 33 | foreach ( $arr as $k => $v ) { |
| 34 | if ( ++$next_key !== $k ) { |
| 35 | return false; |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | return true; |
| 40 | } |
| 41 | |
| 42 | /** |
| 43 | * Merge two lists of associative arrays by a key. |
| 44 | * |
| 45 | * @param array $arr1 The first array. |
| 46 | * @param array $arr2 The second array. |
| 47 | * @param string $key The key to merge by. |
| 48 | * |
| 49 | * @return array The merged list sorted by the key values. |
| 50 | */ |
| 51 | public static function merge_by_key( array $arr1, array $arr2, string $key ): array { |
| 52 | $merged = array(); |
| 53 | // Overwrite items in $arr1 with items in $arr2 if they have the same key entry value. |
| 54 | // The rest of items in $arr1 will be appended. |
| 55 | foreach ( $arr1 as $item1 ) { |
| 56 | $found = false; |
| 57 | foreach ( $arr2 as $item2 ) { |
| 58 | if ( $item1[ $key ] === $item2[ $key ] ) { |
| 59 | $merged[] = array_merge( $item1, $item2 ); |
| 60 | $found = true; |
| 61 | break; |
| 62 | } |
| 63 | } |
| 64 | if ( ! $found ) { |
| 65 | $merged[] = $item1; |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | // Append items from $arr2 that are don't have a corresponding key entry value in $arr1. |
| 70 | foreach ( $arr2 as $item2 ) { |
| 71 | $found = false; |
| 72 | foreach ( $arr1 as $item1 ) { |
| 73 | if ( $item1[ $key ] === $item2[ $key ] ) { |
| 74 | $found = true; |
| 75 | break; |
| 76 | } |
| 77 | } |
| 78 | if ( ! $found ) { |
| 79 | $merged[] = $item2; |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | // Sort the merged list by the key values. |
| 84 | usort( |
| 85 | $merged, |
| 86 | function ( $a, $b ) use ( $key ) { |
| 87 | return $a[ $key ] <=> $b[ $key ]; |
| 88 | } |
| 89 | ); |
| 90 | |
| 91 | return array_values( $merged ); |
| 92 | } |
| 93 | |
| 94 | /** |
| 95 | * Recursively filters null values from an array. |
| 96 | * |
| 97 | * This method removes all null values from the array, including nested arrays. |
| 98 | * Array keys are preserved for associative arrays. For lists (sequential numeric |
| 99 | * keys starting from 0), the array is reindexed to maintain the list structure. |
| 100 | * |
| 101 | * @param array $arr The array to filter. |
| 102 | * |
| 103 | * @return array The filtered array with null values removed. |
| 104 | */ |
| 105 | public static function filter_null_values_recursive( array $arr ): array { |
| 106 | $is_list = self::array_is_list( $arr ); |
| 107 | $filtered = array(); |
| 108 | |
| 109 | foreach ( $arr as $key => $value ) { |
| 110 | // Skip null values. |
| 111 | if ( is_null( $value ) ) { |
| 112 | continue; |
| 113 | } |
| 114 | |
| 115 | // Recursively filter nested arrays. |
| 116 | if ( is_array( $value ) ) { |
| 117 | $filtered[ $key ] = self::filter_null_values_recursive( $value ); |
| 118 | } else { |
| 119 | $filtered[ $key ] = $value; |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | // Reindex if the original array was a list. |
| 124 | return $is_list ? array_values( $filtered ) : $filtered; |
| 125 | } |
| 126 | } |
| 127 |