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

/classes/kohana/arr.php

https://github.com/popovag/kohana_core
PHP | 457 lines | 217 code | 37 blank | 203 comment | 21 complexity | 6b9df67e8b71c5e4f53b8707830a334a MD5 | raw file
  1. <?php defined('SYSPATH') or die('No direct access allowed.');
  2. /**
  3. * Array helper.
  4. *
  5. * @package Kohana
  6. * @category Helpers
  7. * @author Kohana Team
  8. * @copyright (c) 2007-2009 Kohana Team
  9. * @license http://kohanaphp.com/license
  10. */
  11. class Kohana_Arr {
  12. /**
  13. * Tests if an array is associative or not.
  14. *
  15. * // Returns TRUE
  16. * Arr::is_assoc(array('username' => 'john.doe'));
  17. *
  18. * // Returns FALSE
  19. * Arr::is_assoc('foo', 'bar');
  20. *
  21. * @param array array to check
  22. * @return boolean
  23. */
  24. public static function is_assoc(array $array)
  25. {
  26. // Keys of the array
  27. $keys = array_keys($array);
  28. // If the array keys of the keys match the keys, then the array must
  29. // not be associative (e.g. the keys array looked like {0:0, 1:1...}).
  30. return array_keys($keys) !== $keys;
  31. }
  32. /**
  33. * Gets a value from an array using a dot separated path.
  34. *
  35. * // Get the value of $array['foo']['bar']
  36. * $value = Arr::path($array, 'foo.bar');
  37. *
  38. * Using a wildcard "*" will search intermediate arrays and return an array.
  39. *
  40. * // Get the values of "color" in theme
  41. * $colors = Arr::path($array, 'theme.*.color');
  42. *
  43. * @param array array to search
  44. * @param string key path, dot separated
  45. * @param mixed default value if the path is not set
  46. * @return mixed
  47. */
  48. public static function path($array, $path, $default = NULL)
  49. {
  50. // Remove outer dots, wildcards, or spaces
  51. $path = trim($path, '.* ');
  52. // Split the keys by slashes
  53. $keys = explode('.', $path);
  54. do
  55. {
  56. $key = array_shift($keys);
  57. if (ctype_digit($key))
  58. {
  59. // Make the key an integer
  60. $key = (int) $key;
  61. }
  62. if (isset($array[$key]))
  63. {
  64. if ($keys)
  65. {
  66. if (is_array($array[$key]))
  67. {
  68. // Dig down into the next part of the path
  69. $array = $array[$key];
  70. }
  71. else
  72. {
  73. // Unable to dig deeper
  74. break;
  75. }
  76. }
  77. else
  78. {
  79. // Found the path requested
  80. return $array[$key];
  81. }
  82. }
  83. elseif ($key === '*')
  84. {
  85. // Handle wildcards
  86. if (empty($keys))
  87. {
  88. return $array;
  89. }
  90. $values = array();
  91. foreach ($array as $arr)
  92. {
  93. if ($value = Arr::path($arr, implode('.', $keys)))
  94. {
  95. $values[] = $value;
  96. }
  97. }
  98. if ($values)
  99. {
  100. // Found the values requested
  101. return $values;
  102. }
  103. else
  104. {
  105. // Unable to dig deeper
  106. break;
  107. }
  108. }
  109. else
  110. {
  111. // Unable to dig deeper
  112. break;
  113. }
  114. }
  115. while ($keys);
  116. // Unable to find the value requested
  117. return $default;
  118. }
  119. /**
  120. * Fill an array with a range of numbers.
  121. *
  122. * // Fill an array with values 5, 10, 15, 20
  123. * $values = Arr::range(5, 20);
  124. *
  125. * @param integer stepping
  126. * @param integer ending number
  127. * @return array
  128. */
  129. public static function range($step = 10, $max = 100)
  130. {
  131. if ($step < 1)
  132. return array();
  133. $array = array();
  134. for ($i = $step; $i <= $max; $i += $step)
  135. {
  136. $array[$i] = $i;
  137. }
  138. return $array;
  139. }
  140. /**
  141. * Retrieve a single key from an array. If the key does not exist in the
  142. * array, the default value will be returned instead.
  143. *
  144. * // Get the value "username" from $_POST, if it exists
  145. * $username = Arr::get($_POST, 'username');
  146. *
  147. * // Get the value "sorting" from $_GET, if it exists
  148. * $sorting = Arr::get($_GET, 'sorting');
  149. *
  150. * @param array array to extract from
  151. * @param string key name
  152. * @param mixed default value
  153. * @return mixed
  154. */
  155. public static function get($array, $key, $default = NULL)
  156. {
  157. return isset($array[$key]) ? $array[$key] : $default;
  158. }
  159. /**
  160. * Retrieves multiple keys from an array. If the key does not exist in the
  161. * array, the default value will be added instead.
  162. *
  163. * // Get the values "username", "password" from $_POST
  164. * $auth = Arr::extract($_POST, array('username', 'password'));
  165. *
  166. * @param array array to extract keys from
  167. * @param array list of key names
  168. * @param mixed default value
  169. * @return array
  170. */
  171. public static function extract($array, array $keys, $default = NULL)
  172. {
  173. $found = array();
  174. foreach ($keys as $key)
  175. {
  176. $found[$key] = isset($array[$key]) ? $array[$key] : $default;
  177. }
  178. return $found;
  179. }
  180. /**
  181. * Binary search algorithm.
  182. *
  183. * @deprecated Use [array_search](http://php.net/array_search) instead
  184. *
  185. * @param mixed the value to search for
  186. * @param array an array of values to search in
  187. * @param boolean sort the array now
  188. * @return integer the index of the match
  189. * @return FALSE no matching index found
  190. */
  191. public static function binary_search($needle, $haystack, $sort = FALSE)
  192. {
  193. return array_search($needle, $haystack);
  194. }
  195. /**
  196. * Adds a value to the beginning of an associative array.
  197. *
  198. * // Add an empty value to the start of a select list
  199. * Arr::unshift_assoc($array, 'none', 'Select a value');
  200. *
  201. * @param array array to modify
  202. * @param string array key name
  203. * @param mixed array value
  204. * @return array
  205. */
  206. public static function unshift( array & $array, $key, $val)
  207. {
  208. $array = array_reverse($array, TRUE);
  209. $array[$key] = $val;
  210. $array = array_reverse($array, TRUE);
  211. return $array;
  212. }
  213. /**
  214. * Recursive version of [array_map](http://php.net/array_map), applies the
  215. * same callback to all elements in an array, including sub-arrays.
  216. *
  217. * // Apply "strip_tags" to every element in the array
  218. * $array = Arr::map('strip_tags', $array);
  219. *
  220. * [!!] Unlike `array_map`, this method requires a callback and will only map
  221. * a single array.
  222. *
  223. * @param mixed callback applied to every element in the array
  224. * @param array array to map
  225. * @return array
  226. */
  227. public static function map($callback, $array)
  228. {
  229. foreach ($array as $key => $val)
  230. {
  231. if (is_array($val))
  232. {
  233. $array[$key] = Arr::map($callback, $val);
  234. }
  235. else
  236. {
  237. $array[$key] = call_user_func($callback, $val);
  238. }
  239. }
  240. return $array;
  241. }
  242. /**
  243. * Merges one or more arrays recursively and preserves all keys.
  244. * Note that this does not work the same as [array_merge_recursive](http://php.net/array_merge_recursive)!
  245. *
  246. * $john = array('name' => 'john', 'children' => array('fred', 'paul', 'sally', 'jane'));
  247. * $mary = array('name' => 'mary', 'children' => array('jane'));
  248. *
  249. * // John and Mary are married, merge them together
  250. * $john = Arr::merge($john, $mary);
  251. *
  252. * // The output of $john will now be:
  253. * array('name' => 'mary', 'children' => array('fred', 'paul', 'sally', 'jane'))
  254. *
  255. * @param array initial array
  256. * @param array array to merge
  257. * @param array ...
  258. * @return array
  259. */
  260. public static function merge(array $a1, array $a2)
  261. {
  262. $result = array();
  263. for ($i = 0, $total = func_num_args(); $i < $total; $i++)
  264. {
  265. // Get the next array
  266. $arr = func_get_arg($i);
  267. // Is the array associative?
  268. $assoc = Arr::is_assoc($arr);
  269. foreach ($arr as $key => $val)
  270. {
  271. if (isset($result[$key]))
  272. {
  273. if (is_array($val))
  274. {
  275. if (Arr::is_assoc($val))
  276. {
  277. // Associative arrays are merged recursively
  278. $result[$key] = Arr::merge($result[$key], $val);
  279. }
  280. else
  281. {
  282. // Find the values that are not already present
  283. $diff = array_diff($val, $result[$key]);
  284. // Indexed arrays are merged to prevent duplicates
  285. $result[$key] = array_merge($result[$key], $diff);
  286. }
  287. }
  288. else
  289. {
  290. if ($assoc)
  291. {
  292. // Associative values are replaced
  293. $result[$key] = $val;
  294. }
  295. elseif ( ! in_array($val, $result, TRUE))
  296. {
  297. // Indexed values are added only if they do not yet exist
  298. $result[] = $val;
  299. }
  300. }
  301. }
  302. else
  303. {
  304. // New values are added
  305. $result[$key] = $val;
  306. }
  307. }
  308. }
  309. return $result;
  310. }
  311. /**
  312. * Overwrites an array with values from input arrays.
  313. * Keys that do not exist in the first array will not be added!
  314. *
  315. * $a1 = array('name' => 'john', 'mood' => 'happy', 'food' => 'bacon');
  316. * $a2 = array('name' => 'jack', 'food' => 'tacos', 'drink' => 'beer');
  317. *
  318. * // Overwrite the values of $a1 with $a2
  319. * $array = Arr::overwrite($a1, $a2);
  320. *
  321. * // The output of $array will now be:
  322. * array('name' => 'jack', 'mood' => 'happy', 'food' => 'bacon')
  323. *
  324. * @param array master array
  325. * @param array input arrays that will overwrite existing values
  326. * @return array
  327. */
  328. public static function overwrite($array1, $array2)
  329. {
  330. foreach (array_intersect_key($array2, $array1) as $key => $value)
  331. {
  332. $array1[$key] = $value;
  333. }
  334. if (func_num_args() > 2)
  335. {
  336. foreach (array_slice(func_get_args(), 2) as $array2)
  337. {
  338. foreach (array_intersect_key($array2, $array1) as $key => $value)
  339. {
  340. $array1[$key] = $value;
  341. }
  342. }
  343. }
  344. return $array1;
  345. }
  346. /**
  347. * Creates a callable function and parameter list from a string representation.
  348. * Note that this function does not validate the callback string.
  349. *
  350. * // Get the callback function and parameters
  351. * list($func, $params) = Arr::callback('Foo::bar(apple,orange)');
  352. *
  353. * // Get the result of the callback
  354. * $result = call_user_func_array($func, $params);
  355. *
  356. * @param string callback string
  357. * @return array function, params
  358. */
  359. public static function callback($str)
  360. {
  361. // Overloaded as parts are found
  362. $command = $params = NULL;
  363. // command[param,param]
  364. if (preg_match('/^([^\(]*+)\((.*)\)$/', $str, $match))
  365. {
  366. // command
  367. $command = $match[1];
  368. if ($match[2] !== '')
  369. {
  370. // param,param
  371. $params = preg_split('/(?<!\\\\),/', $match[2]);
  372. $params = str_replace('\,', ',', $params);
  373. }
  374. }
  375. else
  376. {
  377. // command
  378. $command = $str;
  379. }
  380. if (strpos($command, '::') !== FALSE)
  381. {
  382. // Create a static method callable command
  383. $command = explode('::', $command, 2);
  384. }
  385. return array($command, $params);
  386. }
  387. /**
  388. * Convert a multi-dimensional array into a single-dimensional array.
  389. *
  390. * $array = array('set' => array('one' => 'something'), 'two' => 'other');
  391. *
  392. * // Flatten the array
  393. * $array = Arr::flatten($array);
  394. *
  395. * // The array will now be
  396. * array('one' => 'something', 'two' => 'other');
  397. *
  398. * [!!] The keys of array values will be discarded.
  399. *
  400. * @param array array to flatten
  401. * @return array
  402. * @since 3.0.6
  403. */
  404. public static function flatten($array)
  405. {
  406. $flat = array();
  407. foreach ($array as $key => $value)
  408. {
  409. if (is_array($value))
  410. {
  411. $flat += Arr::flatten($value);
  412. }
  413. else
  414. {
  415. $flat[$key] = $value;
  416. }
  417. }
  418. return $flat;
  419. }
  420. } // End arr