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