1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Utils;
9:
10: use Nette;
11:
12:
13: 14: 15:
16: class Arrays
17: {
18:
19: 20: 21:
22: final public function __construct()
23: {
24: throw new Nette\StaticClassException;
25: }
26:
27:
28: 29: 30: 31: 32: 33: 34: 35:
36: public static function get(array $arr, $key, $default = NULL)
37: {
38: foreach (is_array($key) ? $key : array($key) as $k) {
39: if (is_array($arr) && array_key_exists($k, $arr)) {
40: $arr = $arr[$k];
41: } else {
42: if (func_num_args() < 3) {
43: throw new Nette\InvalidArgumentException("Missing item '$k'.");
44: }
45: return $default;
46: }
47: }
48: return $arr;
49: }
50:
51:
52: 53: 54: 55: 56: 57: 58:
59: public static function & getRef(& $arr, $key)
60: {
61: foreach (is_array($key) ? $key : array($key) as $k) {
62: if (is_array($arr) || $arr === NULL) {
63: $arr = & $arr[$k];
64: } else {
65: throw new Nette\InvalidArgumentException('Traversed item is not an array.');
66: }
67: }
68: return $arr;
69: }
70:
71:
72: 73: 74: 75:
76: public static function mergeTree($arr1, $arr2)
77: {
78: $res = $arr1 + $arr2;
79: foreach (array_intersect_key($arr1, $arr2) as $k => $v) {
80: if (is_array($v) && is_array($arr2[$k])) {
81: $res[$k] = self::mergeTree($v, $arr2[$k]);
82: }
83: }
84: return $res;
85: }
86:
87:
88: 89: 90: 91:
92: public static function searchKey($arr, $key)
93: {
94: $foo = array($key => NULL);
95: return array_search(key($foo), array_keys($arr), TRUE);
96: }
97:
98:
99: 100: 101: 102:
103: public static function insertBefore(array & $arr, $key, array $inserted)
104: {
105: $offset = self::searchKey($arr, $key);
106: $arr = array_slice($arr, 0, $offset, TRUE) + $inserted + array_slice($arr, $offset, count($arr), TRUE);
107: }
108:
109:
110: 111: 112: 113:
114: public static function insertAfter(array & $arr, $key, array $inserted)
115: {
116: $offset = self::searchKey($arr, $key);
117: $offset = $offset === FALSE ? count($arr) : $offset + 1;
118: $arr = array_slice($arr, 0, $offset, TRUE) + $inserted + array_slice($arr, $offset, count($arr), TRUE);
119: }
120:
121:
122: 123: 124: 125:
126: public static function renameKey(array & $arr, $oldKey, $newKey)
127: {
128: $offset = self::searchKey($arr, $oldKey);
129: if ($offset !== FALSE) {
130: $keys = array_keys($arr);
131: $keys[$offset] = $newKey;
132: $arr = array_combine($keys, $arr);
133: }
134: }
135:
136:
137: 138: 139: 140:
141: public static function grep(array $arr, $pattern, $flags = 0)
142: {
143: return Strings::pcre('preg_grep', array($pattern, $arr, $flags));
144: }
145:
146:
147: 148: 149: 150:
151: public static function flatten(array $arr, $preserveKeys = FALSE)
152: {
153: $res = array();
154: $cb = $preserveKeys
155: ? function ($v, $k) use (& $res) { $res[$k] = $v; }
156: : function ($v) use (& $res) { $res[] = $v; };
157: array_walk_recursive($arr, $cb);
158: return $res;
159: }
160:
161:
162: 163: 164: 165:
166: public static function isList($value)
167: {
168: return is_array($value) && (!$value || array_keys($value) === range(0, count($value) - 1));
169: }
170:
171:
172: 173: 174: 175:
176: public static function associate(array $arr, $path)
177: {
178: $parts = is_array($path)
179: ? $path
180: : preg_split('#(\[\]|->|=|\|)#', $path, NULL, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
181:
182: if (!$parts || $parts[0] === '=' || $parts[0] === '|' || $parts === array('->')) {
183: throw new Nette\InvalidArgumentException("Invalid path '$path'.");
184: }
185:
186: $res = $parts[0] === '->' ? new \stdClass : array();
187:
188: foreach ($arr as $rowOrig) {
189: $row = (array) $rowOrig;
190: $x = & $res;
191:
192: for ($i = 0; $i < count($parts); $i++) {
193: $part = $parts[$i];
194: if ($part === '[]') {
195: $x = & $x[];
196:
197: } elseif ($part === '=') {
198: if (isset($parts[++$i])) {
199: $x = $row[$parts[$i]];
200: $row = NULL;
201: }
202:
203: } elseif ($part === '->') {
204: if (isset($parts[++$i])) {
205: $x = & $x->{$row[$parts[$i]]};
206: } else {
207: $row = is_object($rowOrig) ? $rowOrig : (object) $row;
208: }
209:
210: } elseif ($part !== '|') {
211: $x = & $x[(string) $row[$part]];
212: }
213: }
214:
215: if ($x === NULL) {
216: $x = $row;
217: }
218: }
219:
220: return $res;
221: }
222:
223:
224: 225: 226: 227:
228: public static function normalize(array $arr, $filling = NULL)
229: {
230: $res = array();
231: foreach ($arr as $k => $v) {
232: $res[is_int($k) ? $v : $k] = is_int($k) ? $filling : $v;
233: }
234: return $res;
235: }
236:
237:
238: 239: 240: 241: 242: 243: 244: 245:
246: public static function pick(array & $arr, $key, $default = NULL)
247: {
248: if (array_key_exists($key, $arr)) {
249: $value = $arr[$key];
250: unset($arr[$key]);
251: return $value;
252:
253: } elseif (func_num_args() < 3) {
254: throw new Nette\InvalidArgumentException("Missing item '$key'.");
255:
256: } else {
257: return $default;
258: }
259: }
260:
261: }
262: