PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/fuel/core/classes/arr.php

https://bitbucket.org/codeyash/bootstrap
PHP | 896 lines | 524 code | 96 blank | 276 comment | 53 complexity | 2e33c64abb998347cd560fa7b6ef4540 MD5 | raw file
Possible License(s): MIT, Apache-2.0
  1. <?php
  2. /**
  3. * Part of the Fuel framework.
  4. *
  5. * @package Fuel
  6. * @version 1.5
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2013 Fuel Development Team
  10. * @link http://fuelphp.com
  11. */
  12. namespace Fuel\Core;
  13. /**
  14. * The Arr class provides a few nice functions for making
  15. * dealing with arrays easier
  16. *
  17. * @package Fuel
  18. * @subpackage Core
  19. */
  20. class Arr
  21. {
  22. /**
  23. * Gets a dot-notated key from an array, with a default value if it does
  24. * not exist.
  25. *
  26. * @param array $array The search array
  27. * @param mixed $key The dot-notated key or array of keys
  28. * @param string $default The default value
  29. * @return mixed
  30. */
  31. public static function get($array, $key, $default = null)
  32. {
  33. if ( ! is_array($array) and ! $array instanceof \ArrayAccess)
  34. {
  35. throw new \InvalidArgumentException('First parameter must be an array or ArrayAccess object.');
  36. }
  37. if (is_null($key))
  38. {
  39. return $array;
  40. }
  41. if (is_array($key))
  42. {
  43. $return = array();
  44. foreach ($key as $k)
  45. {
  46. $return[$k] = static::get($array, $k, $default);
  47. }
  48. return $return;
  49. }
  50. foreach (explode('.', $key) as $key_part)
  51. {
  52. if (($array instanceof \ArrayAccess and isset($array[$key_part])) === false)
  53. {
  54. if ( ! is_array($array) or ! array_key_exists($key_part, $array))
  55. {
  56. return \Fuel::value($default);
  57. }
  58. }
  59. $array = $array[$key_part];
  60. }
  61. return $array;
  62. }
  63. /**
  64. * Set an array item (dot-notated) to the value.
  65. *
  66. * @param array $array The array to insert it into
  67. * @param mixed $key The dot-notated key to set or array of keys
  68. * @param mixed $value The value
  69. * @return void
  70. */
  71. public static function set(&$array, $key, $value = null)
  72. {
  73. if (is_null($key))
  74. {
  75. $array = $value;
  76. return;
  77. }
  78. if (is_array($key))
  79. {
  80. foreach ($key as $k => $v)
  81. {
  82. static::set($array, $k, $v);
  83. }
  84. }
  85. else
  86. {
  87. $keys = explode('.', $key);
  88. while (count($keys) > 1)
  89. {
  90. $key = array_shift($keys);
  91. if ( ! isset($array[$key]) or ! is_array($array[$key]))
  92. {
  93. $array[$key] = array();
  94. }
  95. $array =& $array[$key];
  96. }
  97. $array[array_shift($keys)] = $value;
  98. }
  99. }
  100. /**
  101. * Pluck an array of values from an array.
  102. *
  103. * @param array $array collection of arrays to pluck from
  104. * @param string $key key of the value to pluck
  105. * @param string $index optional return array index key, true for original index
  106. * @return array array of plucked values
  107. */
  108. public static function pluck($array, $key, $index = null)
  109. {
  110. $return = array();
  111. $get_deep = strpos($key, '.') !== false;
  112. if ( ! $index)
  113. {
  114. foreach ($array as $i => $a)
  115. {
  116. $return[] = (is_object($a) and ! ($a instanceof \ArrayAccess)) ? $a->{$key} :
  117. ($get_deep ? static::get($a, $key) : $a[$key]);
  118. }
  119. }
  120. else
  121. {
  122. foreach ($array as $i => $a)
  123. {
  124. $index !== true and $i = (is_object($a) and ! ($a instanceof \ArrayAccess)) ? $a->{$index} : $a[$index];
  125. $return[$i] = (is_object($a) and ! ($a instanceof \ArrayAccess)) ? $a->{$key} :
  126. ($get_deep ? static::get($a, $key) : $a[$key]);
  127. }
  128. }
  129. return $return;
  130. }
  131. /**
  132. * Array_key_exists with a dot-notated key from an array.
  133. *
  134. * @param array $array The search array
  135. * @param mixed $key The dot-notated key or array of keys
  136. * @return mixed
  137. */
  138. public static function key_exists($array, $key)
  139. {
  140. foreach (explode('.', $key) as $key_part)
  141. {
  142. if ( ! is_array($array) or ! array_key_exists($key_part, $array))
  143. {
  144. return false;
  145. }
  146. $array = $array[$key_part];
  147. }
  148. return true;
  149. }
  150. /**
  151. * Unsets dot-notated key from an array
  152. *
  153. * @param array $array The search array
  154. * @param mixed $key The dot-notated key or array of keys
  155. * @return mixed
  156. */
  157. public static function delete(&$array, $key)
  158. {
  159. if (is_null($key))
  160. {
  161. return false;
  162. }
  163. if (is_array($key))
  164. {
  165. $return = array();
  166. foreach ($key as $k)
  167. {
  168. $return[$k] = static::delete($array, $k);
  169. }
  170. return $return;
  171. }
  172. $key_parts = explode('.', $key);
  173. if ( ! is_array($array) or ! array_key_exists($key_parts[0], $array))
  174. {
  175. return false;
  176. }
  177. $this_key = array_shift($key_parts);
  178. if ( ! empty($key_parts))
  179. {
  180. $key = implode('.', $key_parts);
  181. return static::delete($array[$this_key], $key);
  182. }
  183. else
  184. {
  185. unset($array[$this_key]);
  186. }
  187. return true;
  188. }
  189. /**
  190. * Converts a multi-dimensional associative array into an array of key => values with the provided field names
  191. *
  192. * @param array $assoc the array to convert
  193. * @param string $key_field the field name of the key field
  194. * @param string $val_field the field name of the value field
  195. * @return array
  196. * @throws \InvalidArgumentException
  197. */
  198. public static function assoc_to_keyval($assoc, $key_field, $val_field)
  199. {
  200. if ( ! is_array($assoc) and ! $assoc instanceof \Iterator)
  201. {
  202. throw new \InvalidArgumentException('The first parameter must be an array.');
  203. }
  204. $output = array();
  205. foreach ($assoc as $row)
  206. {
  207. if (isset($row[$key_field]) and isset($row[$val_field]))
  208. {
  209. $output[$row[$key_field]] = $row[$val_field];
  210. }
  211. }
  212. return $output;
  213. }
  214. /**
  215. * Converts the given 1 dimensional non-associative array to an associative
  216. * array.
  217. *
  218. * The array given must have an even number of elements or null will be returned.
  219. *
  220. * Arr::to_assoc(array('foo','bar'));
  221. *
  222. * @param string $arr the array to change
  223. * @return array|null the new array or null
  224. * @throws \BadMethodCallException
  225. */
  226. public static function to_assoc($arr)
  227. {
  228. if (($count = count($arr)) % 2 > 0)
  229. {
  230. throw new \BadMethodCallException('Number of values in to_assoc must be even.');
  231. }
  232. $keys = $vals = array();
  233. for ($i = 0; $i < $count - 1; $i += 2)
  234. {
  235. $keys[] = array_shift($arr);
  236. $vals[] = array_shift($arr);
  237. }
  238. return array_combine($keys, $vals);
  239. }
  240. /**
  241. * Checks if the given array is an assoc array.
  242. *
  243. * @param array $arr the array to check
  244. * @return bool true if its an assoc array, false if not
  245. */
  246. public static function is_assoc($arr)
  247. {
  248. if ( ! is_array($arr))
  249. {
  250. throw new \InvalidArgumentException('The parameter must be an array.');
  251. }
  252. $counter = 0;
  253. foreach ($arr as $key => $unused)
  254. {
  255. if ( ! is_int($key) or $key !== $counter++)
  256. {
  257. return true;
  258. }
  259. }
  260. return false;
  261. }
  262. /**
  263. * Flattens a multi-dimensional associative array down into a 1 dimensional
  264. * associative array.
  265. *
  266. * @param array the array to flatten
  267. * @param string what to glue the keys together with
  268. * @param bool whether to reset and start over on a new array
  269. * @param bool whether to flatten only associative array's, or also indexed ones
  270. * @return array
  271. */
  272. public static function flatten($array, $glue = ':', $reset = true, $indexed = true)
  273. {
  274. static $return = array();
  275. static $curr_key = array();
  276. if ($reset)
  277. {
  278. $return = array();
  279. $curr_key = array();
  280. }
  281. foreach ($array as $key => $val)
  282. {
  283. $curr_key[] = $key;
  284. if (is_array($val) and ($indexed or array_values($val) !== $val))
  285. {
  286. static::flatten_assoc($val, $glue, false);
  287. }
  288. else
  289. {
  290. $return[implode($glue, $curr_key)] = $val;
  291. }
  292. array_pop($curr_key);
  293. }
  294. return $return;
  295. }
  296. /**
  297. * Flattens a multi-dimensional associative array down into a 1 dimensional
  298. * associative array.
  299. *
  300. * @param array the array to flatten
  301. * @param string what to glue the keys together with
  302. * @param bool whether to reset and start over on a new array
  303. * @return array
  304. */
  305. public static function flatten_assoc($array, $glue = ':', $reset = true)
  306. {
  307. return static::flatten($array, $glue, $reset, false);
  308. }
  309. /**
  310. * Reverse a flattened array in its original form.
  311. *
  312. * @param array $array flattened array
  313. * @param string $glue glue used in flattening
  314. * @return array the unflattened array
  315. */
  316. public static function reverse_flatten($array, $glue = ':')
  317. {
  318. $return = array();
  319. foreach ($array as $key => $value)
  320. {
  321. if (stripos($key, $glue) !== false)
  322. {
  323. $keys = explode($glue, $key);
  324. $temp =& $return;
  325. while (count($keys) > 1)
  326. {
  327. $key = array_shift($keys);
  328. $key = is_numeric($key) ? (int) $key : $key;
  329. if ( ! isset($temp[$key]) or ! is_array($temp[$key]))
  330. {
  331. $temp[$key] = array();
  332. }
  333. $temp =& $temp[$key];
  334. }
  335. $key = array_shift($keys);
  336. $key = is_numeric($key) ? (int) $key : $key;
  337. $temp[$key] = $value;
  338. }
  339. else
  340. {
  341. $key = is_numeric($key) ? (int) $key : $key;
  342. $return[$key] = $value;
  343. }
  344. }
  345. return $return;
  346. }
  347. /**
  348. * Filters an array on prefixed associative keys.
  349. *
  350. * @param array the array to filter.
  351. * @param string prefix to filter on.
  352. * @param bool whether to remove the prefix.
  353. * @return array
  354. */
  355. public static function filter_prefixed($array, $prefix, $remove_prefix = true)
  356. {
  357. $return = array();
  358. foreach ($array as $key => $val)
  359. {
  360. if (preg_match('/^'.$prefix.'/', $key))
  361. {
  362. if ($remove_prefix === true)
  363. {
  364. $key = preg_replace('/^'.$prefix.'/','',$key);
  365. }
  366. $return[$key] = $val;
  367. }
  368. }
  369. return $return;
  370. }
  371. /**
  372. * Recursive version of PHP's array_filter()
  373. *
  374. * @param array the array to filter.
  375. * @param callback the callback that determines whether or not a value is filtered
  376. * @return array
  377. */
  378. public static function filter_recursive($array, $callback = null)
  379. {
  380. foreach ($array as &$value)
  381. {
  382. if (is_array($value))
  383. {
  384. $value = $callback === null ? static::filter_recursive($value) : static::filter_recursive($value, $callback);
  385. }
  386. }
  387. return $callback === null ? array_filter($array) : array_filter($array, $callback);
  388. }
  389. /**
  390. * Removes items from an array that match a key prefix.
  391. *
  392. * @param array the array to remove from
  393. * @param string prefix to filter on
  394. * @return array
  395. */
  396. public static function remove_prefixed($array, $prefix)
  397. {
  398. foreach ($array as $key => $val)
  399. {
  400. if (preg_match('/^'.$prefix.'/', $key))
  401. {
  402. unset($array[$key]);
  403. }
  404. }
  405. return $array;
  406. }
  407. /**
  408. * Filters an array on suffixed associative keys.
  409. *
  410. * @param array the array to filter.
  411. * @param string suffix to filter on.
  412. * @param bool whether to remove the suffix.
  413. * @return array
  414. */
  415. public static function filter_suffixed($array, $suffix, $remove_suffix = true)
  416. {
  417. $return = array();
  418. foreach ($array as $key => $val)
  419. {
  420. if (preg_match('/'.$suffix.'$/', $key))
  421. {
  422. if ($remove_suffix === true)
  423. {
  424. $key = preg_replace('/'.$suffix.'$/','',$key);
  425. }
  426. $return[$key] = $val;
  427. }
  428. }
  429. return $return;
  430. }
  431. /**
  432. * Removes items from an array that match a key suffix.
  433. *
  434. * @param array the array to remove from
  435. * @param string suffix to filter on
  436. * @return array
  437. */
  438. public static function remove_suffixed($array, $suffix)
  439. {
  440. foreach ($array as $key => $val)
  441. {
  442. if (preg_match('/'.$suffix.'$/', $key))
  443. {
  444. unset($array[$key]);
  445. }
  446. }
  447. return $array;
  448. }
  449. /**
  450. * Filters an array by an array of keys
  451. *
  452. * @param array the array to filter.
  453. * @param array the keys to filter
  454. * @param bool if true, removes the matched elements.
  455. * @return array
  456. */
  457. public static function filter_keys($array, $keys, $remove = false)
  458. {
  459. $return = array();
  460. foreach ($keys as $key)
  461. {
  462. if (array_key_exists($key, $array))
  463. {
  464. $remove or $return[$key] = $array[$key];
  465. if($remove)
  466. {
  467. unset($array[$key]);
  468. }
  469. }
  470. }
  471. return $remove ? $array : $return;
  472. }
  473. /**
  474. * Insert value(s) into an array, mostly an array_splice alias
  475. * WARNING: original array is edited by reference, only boolean success is returned
  476. *
  477. * @param array the original array (by reference)
  478. * @param array|mixed the value(s) to insert, if you want to insert an array it needs to be in an array itself
  479. * @param int the numeric position at which to insert, negative to count from the end backwards
  480. * @return bool false when array shorter then $pos, otherwise true
  481. */
  482. public static function insert(array &$original, $value, $pos)
  483. {
  484. if (count($original) < abs($pos))
  485. {
  486. \Error::notice('Position larger than number of elements in array in which to insert.');
  487. return false;
  488. }
  489. array_splice($original, $pos, 0, $value);
  490. return true;
  491. }
  492. /**
  493. * Insert value(s) into an array, mostly an array_splice alias
  494. * WARNING: original array is edited by reference, only boolean success is returned
  495. *
  496. * @param array the original array (by reference)
  497. * @param array|mixed the value(s) to insert, if you want to insert an array it needs to be in an array itself
  498. * @param int the numeric position at which to insert, negative to count from the end backwards
  499. * @return bool false when array shorter then $pos, otherwise true
  500. */
  501. public static function insert_assoc(array &$original, array $values, $pos)
  502. {
  503. if (count($original) < abs($pos))
  504. {
  505. return false;
  506. }
  507. $original = array_slice($original, 0, $pos, true) + $values + array_slice($original, $pos, null, true);
  508. return true;
  509. }
  510. /**
  511. * Insert value(s) into an array before a specific key
  512. * WARNING: original array is edited by reference, only boolean success is returned
  513. *
  514. * @param array the original array (by reference)
  515. * @param array|mixed the value(s) to insert, if you want to insert an array it needs to be in an array itself
  516. * @param string|int the key before which to insert
  517. * @param bool wether the input is an associative array
  518. * @return bool false when key isn't found in the array, otherwise true
  519. */
  520. public static function insert_before_key(array &$original, $value, $key, $is_assoc = false)
  521. {
  522. $pos = array_search($key, array_keys($original));
  523. if ($pos === false)
  524. {
  525. \Error::notice('Unknown key before which to insert the new value into the array.');
  526. return false;
  527. }
  528. return $is_assoc ? static::insert_assoc($original, $value, $pos) : static::insert($original, $value, $pos);
  529. }
  530. /**
  531. * Insert value(s) into an array after a specific key
  532. * WARNING: original array is edited by reference, only boolean success is returned
  533. *
  534. * @param array the original array (by reference)
  535. * @param array|mixed the value(s) to insert, if you want to insert an array it needs to be in an array itself
  536. * @param string|int the key after which to insert
  537. * @param bool wether the input is an associative array
  538. * @return bool false when key isn't found in the array, otherwise true
  539. */
  540. public static function insert_after_key(array &$original, $value, $key, $is_assoc = false)
  541. {
  542. $pos = array_search($key, array_keys($original));
  543. if ($pos === false)
  544. {
  545. \Error::notice('Unknown key after which to insert the new value into the array.');
  546. return false;
  547. }
  548. return $is_assoc ? static::insert_assoc($original, $value, $pos + 1) : static::insert($original, $value, $pos + 1);
  549. }
  550. /**
  551. * Insert value(s) into an array after a specific value (first found in array)
  552. *
  553. * @param array the original array (by reference)
  554. * @param array|mixed the value(s) to insert, if you want to insert an array it needs to be in an array itself
  555. * @param string|int the value after which to insert
  556. * @param bool wether the input is an associative array
  557. * @return bool false when value isn't found in the array, otherwise true
  558. */
  559. public static function insert_after_value(array &$original, $value, $search, $is_assoc = false)
  560. {
  561. $key = array_search($search, $original);
  562. if ($key === false)
  563. {
  564. \Error::notice('Unknown value after which to insert the new value into the array.');
  565. return false;
  566. }
  567. return static::insert_after_key($original, $value, $key, $is_assoc);
  568. }
  569. /**
  570. * Insert value(s) into an array before a specific value (first found in array)
  571. *
  572. * @param array the original array (by reference)
  573. * @param array|mixed the value(s) to insert, if you want to insert an array it needs to be in an array itself
  574. * @param string|int the value after which to insert
  575. * @param bool wether the input is an associative array
  576. * @return bool false when value isn't found in the array, otherwise true
  577. */
  578. public static function insert_before_value(array &$original, $value, $search, $is_assoc = false)
  579. {
  580. $key = array_search($search, $original);
  581. if ($key === false)
  582. {
  583. \Error::notice('Unknown value before which to insert the new value into the array.');
  584. return false;
  585. }
  586. return static::insert_before_key($original, $value, $key, $is_assoc);
  587. }
  588. /**
  589. * Sorts a multi-dimensional array by it's values.
  590. *
  591. * @access public
  592. * @param array The array to fetch from
  593. * @param string The key to sort by
  594. * @param string The order (asc or desc)
  595. * @param int The php sort type flag
  596. * @return array
  597. */
  598. public static function sort($array, $key, $order = 'asc', $sort_flags = SORT_REGULAR)
  599. {
  600. if ( ! is_array($array))
  601. {
  602. throw new \InvalidArgumentException('Arr::sort() - $array must be an array.');
  603. }
  604. if (empty($array))
  605. {
  606. return $array;
  607. }
  608. foreach ($array as $k => $v)
  609. {
  610. $b[$k] = static::get($v, $key);
  611. }
  612. switch ($order)
  613. {
  614. case 'asc':
  615. asort($b, $sort_flags);
  616. break;
  617. case 'desc':
  618. arsort($b, $sort_flags);
  619. break;
  620. default:
  621. throw new \InvalidArgumentException('Arr::sort() - $order must be asc or desc.');
  622. break;
  623. }
  624. foreach ($b as $key => $val)
  625. {
  626. $c[] = $array[$key];
  627. }
  628. return $c;
  629. }
  630. /**
  631. * Sorts an array on multitiple values, with deep sorting support.
  632. *
  633. * @param array $array collection of arrays/objects to sort
  634. * @param array $conditions sorting conditions
  635. * @param bool @ignore_case wether to sort case insensitive
  636. */
  637. public static function multisort($array, $conditions, $ignore_case = false)
  638. {
  639. $temp = array();
  640. $keys = array_keys($conditions);
  641. foreach($keys as $key)
  642. {
  643. $temp[$key] = static::pluck($array, $key, true);
  644. is_array($conditions[$key]) or $conditions[$key] = array($conditions[$key]);
  645. }
  646. $args = array();
  647. foreach ($keys as $key)
  648. {
  649. $args[] = $ignore_case ? array_map('strtolower', $temp[$key]) : $temp[$key];
  650. foreach($conditions[$key] as $flag)
  651. {
  652. $args[] = $flag;
  653. }
  654. }
  655. $args[] = &$array;
  656. call_user_func_array('array_multisort', $args);
  657. return $array;
  658. }
  659. /**
  660. * Find the average of an array
  661. *
  662. * @param array the array containing the values
  663. * @return numeric the average value
  664. */
  665. public static function average($array)
  666. {
  667. // No arguments passed, lets not divide by 0
  668. if ( ! ($count = count($array)) > 0)
  669. {
  670. return 0;
  671. }
  672. return (array_sum($array) / $count);
  673. }
  674. /**
  675. * Replaces key names in an array by names in $replace
  676. *
  677. * @param array the array containing the key/value combinations
  678. * @param array|string key to replace or array containing the replacement keys
  679. * @param string the replacement key
  680. * @return array the array with the new keys
  681. */
  682. public static function replace_key($source, $replace, $new_key = null)
  683. {
  684. if(is_string($replace))
  685. {
  686. $replace = array($replace => $new_key);
  687. }
  688. if ( ! is_array($source) or ! is_array($replace))
  689. {
  690. throw new \InvalidArgumentException('Arr::replace_key() - $source must an array. $replace must be an array or string.');
  691. }
  692. $result = array();
  693. foreach ($source as $key => $value)
  694. {
  695. if (array_key_exists($key, $replace))
  696. {
  697. $result[$replace[$key]] = $value;
  698. }
  699. else
  700. {
  701. $result[$key] = $value;
  702. }
  703. }
  704. return $result;
  705. }
  706. /**
  707. * Merge 2 arrays recursively, differs in 2 important ways from array_merge_recursive()
  708. * - When there's 2 different values and not both arrays, the latter value overwrites the earlier
  709. * instead of merging both into an array
  710. * - Numeric keys that don't conflict aren't changed, only when a numeric key already exists is the
  711. * value added using array_push()
  712. *
  713. * @param array multiple variables all of which must be arrays
  714. * @return array
  715. * @throws \InvalidArgumentException
  716. */
  717. public static function merge()
  718. {
  719. $array = func_get_arg(0);
  720. $arrays = array_slice(func_get_args(), 1);
  721. if ( ! is_array($array))
  722. {
  723. throw new \InvalidArgumentException('Arr::merge() - all arguments must be arrays.');
  724. }
  725. foreach ($arrays as $arr)
  726. {
  727. if ( ! is_array($arr))
  728. {
  729. throw new \InvalidArgumentException('Arr::merge() - all arguments must be arrays.');
  730. }
  731. foreach ($arr as $k => $v)
  732. {
  733. // numeric keys are appended
  734. if (is_int($k))
  735. {
  736. array_key_exists($k, $array) ? array_push($array, $v) : $array[$k] = $v;
  737. }
  738. elseif (is_array($v) and array_key_exists($k, $array) and is_array($array[$k]))
  739. {
  740. $array[$k] = static::merge($array[$k], $v);
  741. }
  742. else
  743. {
  744. $array[$k] = $v;
  745. }
  746. }
  747. }
  748. return $array;
  749. }
  750. /**
  751. * Prepends a value with an asociative key to an array.
  752. * Will overwrite if the value exists.
  753. *
  754. * @param array $arr the array to prepend to
  755. * @param string|array $key the key or array of keys and values
  756. * @param mixed $valye the value to prepend
  757. */
  758. public static function prepend(&$arr, $key, $value = null)
  759. {
  760. $arr = (is_array($key) ? $key : array($key => $value)) + $arr;
  761. }
  762. /**
  763. * Recursive in_array
  764. *
  765. * @param mixed $needle what to search for
  766. * @param array $haystack array to search in
  767. * @return bool wether the needle is found in the haystack.
  768. */
  769. public static function in_array_recursive($needle, $haystack, $strict = false)
  770. {
  771. foreach ($haystack as $value)
  772. {
  773. if ( ! $strict and $needle == $value)
  774. {
  775. return true;
  776. }
  777. elseif ($needle === $value)
  778. {
  779. return true;
  780. }
  781. elseif (is_array($value) and static::in_array_recursive($needle, $value, $strict))
  782. {
  783. return true;
  784. }
  785. }
  786. return false;
  787. }
  788. /**
  789. * Checks if the given array is a multidimensional array.
  790. *
  791. * @param array $arr the array to check
  792. * @param array $all_keys if true, check that all elements are arrays
  793. * @return bool true if its a multidimensional array, false if not
  794. */
  795. public static function is_multi($arr, $all_keys = false)
  796. {
  797. $values = array_filter($arr, 'is_array');
  798. return $all_keys ? count($arr) === count($values) : count($values) > 0;
  799. }
  800. }