1 <?php
2 /**
3 * @copyright Copyright © 2amigOS! Consulting Group 2013-
4 * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
5 * @package foundation.components
6 * @version 1.0.0
7 */
8
9 namespace foundation\helpers;
10
11 /**
12 * ArrayHelper has array utility methods
13 *
14 * @author Antonio Ramirez <amigo.cobos@gmail.com>
15 * @package foundation\helpers
16 */
17 class ArrayHelper
18 {
19 /**
20 * Copies the values from one option array to another.
21 * @param array $names the items names to copy.
22 * @param array $from the items to copy from.
23 * @param array $to the items to copy to.
24 * @return array with copied items.
25 */
26 public static function copy($names, $from, $to)
27 {
28 if (is_array($from) && is_array($to)) {
29 foreach ($names as $key) {
30 if (isset($from[$key]) && !isset($to[$key])) {
31 $to[$key] = static::getValue($from, $key);
32 }
33 }
34 }
35 return $to;
36 }
37
38 /**
39 * Moves the item values from one array to another.
40 * @param array $names the item names to move.
41 * @param array $from the values to move from.
42 * @param array $to the items to move to.
43 * @return array with moved items.
44 */
45 public static function move($names, $from, $to)
46 {
47 if (is_array($from) && is_array($to)) {
48 foreach ($names as $key) {
49 if (isset($from[$key]) && !isset($to[$key])) {
50 $to[$key] = static::remove($from, $key);
51 }
52 }
53 }
54 return $to;
55 }
56
57 /**
58 * Sets multiple default values for the given array.
59 * @param array $array the items to set defaults for.
60 * @param array $defaults the default items.
61 * @return array the array with default values.
62 */
63 public static function multipleDefaultValues($array, $defaults)
64 {
65 foreach ($defaults as $name => $value) {
66 $array = static::defaultValue($name, $value, $array);
67 }
68
69 return $array;
70 }
71
72 /**
73 * Sets the default value for an item in the given array.
74 * @param string $name the name of the item.
75 * @param mixed $value the default value.
76 * @param array $array the items.
77 * @return mixed
78 */
79 public static function defaultValue($name, $value, $array)
80 {
81 if (!isset($array[$name]))
82 $array[$name] = $value;
83
84 return $array;
85 }
86
87 /**
88 * Adds a new option to the given array. If the key does not exists, it will create one, if it exists it will append
89 * the value and also makes sure the uniqueness of them.
90 *
91 * @param string $key the key name at the array
92 * @param string $value the value to add / append
93 * @param array $array the options to modify
94 * @param string $glue how the values will be joined
95 * @return array
96 */
97 public static function addValue($key, $value, &$array, $glue = ' ')
98 {
99 if (isset($array[$key])) {
100 if (!is_array($array[$key]))
101 $array[$key] = explode($glue, $array[$key]);
102 $array[$key][] = $value;
103 $array[$key] = array_unique($array[$key]);
104 $array[$key] = implode($glue, $array[$key]);
105 } else
106 $array[$key] = $value;
107 return $array;
108 }
109
110 /**
111 * Retrieves the value of an array element or object property with the given key or property name.
112 * If the key does not exist in the array, the default value will be returned instead.
113 *
114 * @param array|object $array array or object to extract value from
115 * @param string|\Closure $key key name of the array element, or property name of the object,
116 * or an anonymous function returning the value. The anonymous function signature should be:
117 * `function($array, $defaultValue)`.
118 * @param mixed $default the default value to be returned if the specified key does not exist
119 * @return mixed the value of the
120 */
121 public static function getValue($array, $key, $default = null)
122 {
123 if ($key instanceof \Closure) {
124 return $key($array, $default);
125 } elseif (is_array($array)) {
126 return isset($array[$key]) || array_key_exists($key, $array) ? $array[$key] : $default;
127 } else {
128 return $array->$key;
129 }
130 }
131
132 /**
133 * Removes an item from the given options and returns the value.
134 *
135 * If no key is found, then default value will be returned.
136 *
137 * @param $array
138 * @param $key
139 * @param null $default
140 * @return mixed|null
141 */
142 public static function removeValue(&$array, $key, $default = null)
143 {
144 if (is_array($array)) {
145 $value = static::getValue($array, $key, $default);
146 unset($array[$key]);
147 return static::value($value);
148 }
149 return self::value($default);
150 }
151
152 /**
153 * Removes the array values from the given array.
154 * @param array $array the items to remove from.
155 * @param array $names names to remove from the array.
156 * @return array the items.
157 */
158 public static function removeKeys($array, $names)
159 {
160 return array_diff_key($array, array_flip($names));
161 }
162
163 /**
164 * Divide an array into two arrays. One with keys and the other with values.
165 *
166 * @param array $array
167 * @return array
168 */
169 public static function divide($array)
170 {
171 return array(array_keys($array), array_values($array));
172 }
173
174 /**
175 * Pluck an array of values from an array.
176 *
177 * @param array $array
178 * @param string $key
179 * @return array
180 */
181 public static function pluck($array, $key)
182 {
183 return array_map(
184 function ($v) use ($key) {
185 return is_object($v) ? $v->$key : $v[$key];
186
187 },
188 $array
189 );
190 }
191
192 /**
193 * Get a subset of the items from the given array.
194 *
195 * @param array $array
196 * @param array $keys
197 * @return array
198 */
199 public static function only($array, $keys)
200 {
201 return array_intersect_key($array, array_flip((array)$keys));
202 }
203
204 /**
205 * Get all of the given array except for a specified array of items.
206 *
207 * @param array $array
208 * @param array $keys
209 * @return array
210 */
211 public static function except($array, $keys)
212 {
213 return array_diff_key($array, array_flip((array)$keys));
214 }
215
216 /**
217 * Return the first element in an array which passes a given truth test.
218 *
219 * <code>
220 * // Return the first array element that equals "Taylor"
221 * $value = ArrayX::first($array, function($k, $v) {return $v == 'Taylor';});
222 *
223 * // Return a default value if no matching element is found
224 * $value = ArrayX::first($array, function($k, $v) {return $v == 'Taylor'}, 'Default');
225 * </code>
226 *
227 * @param array $array
228 * @param Closure $callback
229 * @param mixed $default
230 * @return mixed
231 */
232 public static function first($array, $callback, $default = null)
233 {
234 foreach ($array as $key => $value) {
235 if (call_user_func($callback, $key, $value)) {
236 return $value;
237 }
238 }
239
240 return value($default);
241 }
242
243 /**
244 * Return the first element of an array.
245 *
246 * This is simply a convenient wrapper around the "reset" method.
247 *
248 * @param array $array
249 * @return mixed
250 */
251 public static function head($array)
252 {
253 return reset($array);
254 }
255
256 /**
257 * Merges two or more arrays into one recursively.
258 * If each array has an element with the same string key value, the latter
259 * will overwrite the former (different from array_merge_recursive).
260 * Recursive merging will be conducted if both arrays have an element of array
261 * type and are having the same key.
262 * For integer-keyed elements, the elements from the latter array will
263 * be appended to the former array.
264 * @param array $a array to be merged to
265 * @param array $b array to be merged from. You can specifiy additional
266 * arrays via third argument, fourth argument etc.
267 * @return array the merged array (the original arrays are not changed.)
268 */
269 public static function merge($a, $b)
270 {
271 $args = func_get_args();
272 $res = array_shift($args);
273 while (!empty($args)) {
274 $next = array_shift($args);
275 foreach ($next as $k => $v) {
276 if (is_integer($k)) {
277 isset($res[$k]) ? $res[] = $v : $res[$k] = $v;
278 } elseif (is_array($v) && isset($res[$k]) && is_array($res[$k])) {
279 $res[$k] = static::merge($res[$k], $v);
280 } else {
281 $res[$k] = $v;
282 }
283 }
284 }
285 return $res;
286 }
287
288 /**
289 * Searches for a given value in an array of arrays, objects and scalar
290 * values. You can optionally specify a field of the nested arrays and
291 * objects to search in.
292 *
293 * Credits to Util.php
294 *
295 * @param array $array The array to search
296 * @param string $search The value to search for
297 * @param bool $field The field to search in, if not specified all fields will be searched
298 * @return bool|mixed|string false on failure or the array key on
299 * @link https://github.com/brandonwamboldt/utilphp/blob/master/util.php
300 */
301 public static function search(array $array, $search, $field = false)
302 {
303 $search = (string)$search;
304
305 foreach ($array as $key => $elem) {
306
307 $key = (string)$key;
308
309 if ($field) {
310 if ((is_object($elem) && $elem->{$field} === $search)
311 || (is_array($elem) && $elem[$field] === $search)
312 || (is_scalar($elem) && $elem === $search)
313 ) {
314 return $key;
315 }
316
317 } else {
318 if (is_object($elem)) {
319 $elem = (array)$elem;
320
321 if (in_array($search, $elem)) {
322 return $key;
323 }
324 } else {
325 if ((is_array($elem) && in_array($search, $elem)) || (is_scalar($elem) && $elem === $search)) {
326 return $key;
327 }
328 }
329 }
330 }
331 return false;
332 }
333
334 /**
335 * Returns an array containing all the elements of arr1 after applying
336 * the callback function to each one.
337 *
338 * Credits to Util.php
339 *
340 * @param array $array an array to run through the callback function
341 * @param $callback Callback function to run for each element in each array
342 * @param bool $on_nonscalar whether or not to call the callback function on nonscalar values (objects, resr, etc)
343 * @return array
344 * @link https://github.com/brandonwamboldt/utilphp/blob/master/util.php
345 */
346 public static function map(array $array, $callback, $on_nonscalar = false)
347 {
348 foreach ($array as $key => $value) {
349 if (is_array($value)) {
350 $args = array($value, $callback, $on_nonscalar);
351 $array[$key] = call_user_func_array(array(__CLASS__, __FUNCTION__), $args);
352 } else {
353 if (is_scalar($value) || $on_nonscalar) {
354 $array[$key] = call_user_func($callback, $value);
355 }
356 }
357 }
358
359 return $array;
360 }
361
362 /**
363 * Return the value of the given item.
364 *
365 * If the given item is a Closure the result of the Closure will be returned.
366 *
367 * @param mixed $value
368 * @return mixed
369 */
370 protected static function value($value)
371 {
372 return (is_callable($value) and !is_string($value)) ? call_user_func($value) : $value;
373 }
374 }