comparison vendor/zendframework/zend-stdlib/src/ArrayUtils.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 7a779792577d
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
4 *
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
9
10 namespace Zend\Stdlib;
11
12 use Traversable;
13 use Zend\Stdlib\ArrayUtils\MergeRemoveKey;
14 use Zend\Stdlib\ArrayUtils\MergeReplaceKeyInterface;
15
16 /**
17 * Utility class for testing and manipulation of PHP arrays.
18 *
19 * Declared abstract, as we have no need for instantiation.
20 */
21 abstract class ArrayUtils
22 {
23 /**
24 * Compatibility Flag for ArrayUtils::filter
25 */
26 const ARRAY_FILTER_USE_BOTH = 1;
27
28 /**
29 * Compatibility Flag for ArrayUtils::filter
30 */
31 const ARRAY_FILTER_USE_KEY = 2;
32
33 /**
34 * Test whether an array contains one or more string keys
35 *
36 * @param mixed $value
37 * @param bool $allowEmpty Should an empty array() return true
38 * @return bool
39 */
40 public static function hasStringKeys($value, $allowEmpty = false)
41 {
42 if (!is_array($value)) {
43 return false;
44 }
45
46 if (!$value) {
47 return $allowEmpty;
48 }
49
50 return count(array_filter(array_keys($value), 'is_string')) > 0;
51 }
52
53 /**
54 * Test whether an array contains one or more integer keys
55 *
56 * @param mixed $value
57 * @param bool $allowEmpty Should an empty array() return true
58 * @return bool
59 */
60 public static function hasIntegerKeys($value, $allowEmpty = false)
61 {
62 if (!is_array($value)) {
63 return false;
64 }
65
66 if (!$value) {
67 return $allowEmpty;
68 }
69
70 return count(array_filter(array_keys($value), 'is_int')) > 0;
71 }
72
73 /**
74 * Test whether an array contains one or more numeric keys.
75 *
76 * A numeric key can be one of the following:
77 * - an integer 1,
78 * - a string with a number '20'
79 * - a string with negative number: '-1000'
80 * - a float: 2.2120, -78.150999
81 * - a string with float: '4000.99999', '-10.10'
82 *
83 * @param mixed $value
84 * @param bool $allowEmpty Should an empty array() return true
85 * @return bool
86 */
87 public static function hasNumericKeys($value, $allowEmpty = false)
88 {
89 if (!is_array($value)) {
90 return false;
91 }
92
93 if (!$value) {
94 return $allowEmpty;
95 }
96
97 return count(array_filter(array_keys($value), 'is_numeric')) > 0;
98 }
99
100 /**
101 * Test whether an array is a list
102 *
103 * A list is a collection of values assigned to continuous integer keys
104 * starting at 0 and ending at count() - 1.
105 *
106 * For example:
107 * <code>
108 * $list = array('a', 'b', 'c', 'd');
109 * $list = array(
110 * 0 => 'foo',
111 * 1 => 'bar',
112 * 2 => array('foo' => 'baz'),
113 * );
114 * </code>
115 *
116 * @param mixed $value
117 * @param bool $allowEmpty Is an empty list a valid list?
118 * @return bool
119 */
120 public static function isList($value, $allowEmpty = false)
121 {
122 if (!is_array($value)) {
123 return false;
124 }
125
126 if (!$value) {
127 return $allowEmpty;
128 }
129
130 return (array_values($value) === $value);
131 }
132
133 /**
134 * Test whether an array is a hash table.
135 *
136 * An array is a hash table if:
137 *
138 * 1. Contains one or more non-integer keys, or
139 * 2. Integer keys are non-continuous or misaligned (not starting with 0)
140 *
141 * For example:
142 * <code>
143 * $hash = array(
144 * 'foo' => 15,
145 * 'bar' => false,
146 * );
147 * $hash = array(
148 * 1995 => 'Birth of PHP',
149 * 2009 => 'PHP 5.3.0',
150 * 2012 => 'PHP 5.4.0',
151 * );
152 * $hash = array(
153 * 'formElement,
154 * 'options' => array( 'debug' => true ),
155 * );
156 * </code>
157 *
158 * @param mixed $value
159 * @param bool $allowEmpty Is an empty array() a valid hash table?
160 * @return bool
161 */
162 public static function isHashTable($value, $allowEmpty = false)
163 {
164 if (!is_array($value)) {
165 return false;
166 }
167
168 if (!$value) {
169 return $allowEmpty;
170 }
171
172 return (array_values($value) !== $value);
173 }
174
175 /**
176 * Checks if a value exists in an array.
177 *
178 * Due to "foo" == 0 === TRUE with in_array when strict = false, an option
179 * has been added to prevent this. When $strict = 0/false, the most secure
180 * non-strict check is implemented. if $strict = -1, the default in_array
181 * non-strict behaviour is used.
182 *
183 * @param mixed $needle
184 * @param array $haystack
185 * @param int|bool $strict
186 * @return bool
187 */
188 public static function inArray($needle, array $haystack, $strict = false)
189 {
190 if (!$strict) {
191 if (is_int($needle) || is_float($needle)) {
192 $needle = (string) $needle;
193 }
194 if (is_string($needle)) {
195 foreach ($haystack as &$h) {
196 if (is_int($h) || is_float($h)) {
197 $h = (string) $h;
198 }
199 }
200 }
201 }
202 return in_array($needle, $haystack, $strict);
203 }
204
205 /**
206 * Convert an iterator to an array.
207 *
208 * Converts an iterator to an array. The $recursive flag, on by default,
209 * hints whether or not you want to do so recursively.
210 *
211 * @param array|Traversable $iterator The array or Traversable object to convert
212 * @param bool $recursive Recursively check all nested structures
213 * @throws Exception\InvalidArgumentException if $iterator is not an array or a Traversable object
214 * @return array
215 */
216 public static function iteratorToArray($iterator, $recursive = true)
217 {
218 if (!is_array($iterator) && !$iterator instanceof Traversable) {
219 throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable object');
220 }
221
222 if (!$recursive) {
223 if (is_array($iterator)) {
224 return $iterator;
225 }
226
227 return iterator_to_array($iterator);
228 }
229
230 if (method_exists($iterator, 'toArray')) {
231 return $iterator->toArray();
232 }
233
234 $array = [];
235 foreach ($iterator as $key => $value) {
236 if (is_scalar($value)) {
237 $array[$key] = $value;
238 continue;
239 }
240
241 if ($value instanceof Traversable) {
242 $array[$key] = static::iteratorToArray($value, $recursive);
243 continue;
244 }
245
246 if (is_array($value)) {
247 $array[$key] = static::iteratorToArray($value, $recursive);
248 continue;
249 }
250
251 $array[$key] = $value;
252 }
253
254 return $array;
255 }
256
257 /**
258 * Merge two arrays together.
259 *
260 * If an integer key exists in both arrays and preserveNumericKeys is false, the value
261 * from the second array will be appended to the first array. If both values are arrays, they
262 * are merged together, else the value of the second array overwrites the one of the first array.
263 *
264 * @param array $a
265 * @param array $b
266 * @param bool $preserveNumericKeys
267 * @return array
268 */
269 public static function merge(array $a, array $b, $preserveNumericKeys = false)
270 {
271 foreach ($b as $key => $value) {
272 if ($value instanceof MergeReplaceKeyInterface) {
273 $a[$key] = $value->getData();
274 } elseif (isset($a[$key]) || array_key_exists($key, $a)) {
275 if ($value instanceof MergeRemoveKey) {
276 unset($a[$key]);
277 } elseif (!$preserveNumericKeys && is_int($key)) {
278 $a[] = $value;
279 } elseif (is_array($value) && is_array($a[$key])) {
280 $a[$key] = static::merge($a[$key], $value, $preserveNumericKeys);
281 } else {
282 $a[$key] = $value;
283 }
284 } else {
285 if (!$value instanceof MergeRemoveKey) {
286 $a[$key] = $value;
287 }
288 }
289 }
290
291 return $a;
292 }
293
294 /**
295 * Compatibility Method for array_filter on <5.6 systems
296 *
297 * @param array $data
298 * @param callable $callback
299 * @param null|int $flag
300 * @return array
301 */
302 public static function filter(array $data, $callback, $flag = null)
303 {
304 if (! is_callable($callback)) {
305 throw new Exception\InvalidArgumentException(sprintf(
306 'Second parameter of %s must be callable',
307 __METHOD__
308 ));
309 }
310
311 if (version_compare(PHP_VERSION, '5.6.0') >= 0) {
312 return array_filter($data, $callback, $flag);
313 }
314
315 $output = [];
316 foreach ($data as $key => $value) {
317 $params = [$value];
318
319 if ($flag === static::ARRAY_FILTER_USE_BOTH) {
320 $params[] = $key;
321 }
322
323 if ($flag === static::ARRAY_FILTER_USE_KEY) {
324 $params = [$key];
325 }
326
327 $response = call_user_func_array($callback, $params);
328 if ($response) {
329 $output[$key] = $value;
330 }
331 }
332
333 return $output;
334 }
335 }