View difference between Paste ID: TyWzLWuK and 8tBQidic
SHOW: | | - or go back to the newest paste.
1
<?php
2-
abstract class Fw_Recursive_Array_Helper {
2+
final class Fw_Recursive_Array_Helper {
3
	const ESCAPE = '\\';
4
	const SEPARATOR = '.';
5
6
	/**
7
	 * @param mixed $array
8
	 * @param string $path
9
	 * @param mixed $default
10
	 * @throws InvalidArgumentException
11
	 * @return mixed
12
	 */
13
	static public function get($array, $path, $default = null) {
14
		if (!assert_string($path)) {
15
			throw new InvalidArgumentException('Path must be a string');
16
		}
17
18
		$parts = self::separate($path);
19
		$value = $array;
20
21
		if (!self::has($array, $path)) {
22
			return $default;
23
		}
24
25
		while (count($parts)) {
26
			$part = array_shift($parts);
27
28
			if (array_key_exists($part, $value)) {
29
				$value = $value[$part];
30
			}
31
		}
32
33
		return $value;
34
	}
35
36
	/**
37
	 * Determines if $path exists in $array
38
	 *
39
	 * @param mixed $array
40
	 * @param string $path
41
	 * @return unknown
42
	 */
43
	static public function has($array, $path) {
44
		if (!assert_string($path)) {
45
			return false;
46
		}
47
48
		$parts = explode(self::SEPARATOR, $path);
49
50
		while (count($parts)) {
51
			$part = array_shift($parts);
52
53
			if (self::isAcceptedArrayType($array) && array_key_exists($part, $array)) {
54
				$array = $array[$part];
55
			} else {
56
				return false;
57
			}
58
		}
59
60
		return true;
61
	}
62
63
	/**
64
	 * Sets $value in $array where $path is the recursive Path inside $array
65
	 *
66
	 * @param mixed $array
67
	 * @param string $path
68
	 * @param mixed $value
69
	 * @throws InvalidArgumentException
70
	 * @return array
71
	 */
72
	static public function set(&$array, $path, $value) {
73
		if (!assert_string($path)) {
74
			throw new InvalidArgumentException('Path must be a string');
75
		}
76
77
		if (!self::isAcceptedArrayType($array)) {
78
			$array = array();
79
		}
80
81
		$parts = self::separate($path);
82
83
		if (count($parts) > 1) {
84
			$part = array_shift($parts);
85
86
			if (!self::isAcceptedArrayType($array)) {
87
				$array = array();
88
			}
89
90
			if (!array_key_exists($part, $array)) {
91
				$array[$part] = null;
92
			}
93
94
			$array[$part] = self::set($array[$part], join(self::SEPARATOR, $parts), $value);
95
		} else {
96
			$array[$path] = $value;
97
		}
98
99
		return $array;
100
	}
101
102
	/**
103
	 * @param string $array
104
	 * @param string $path
105
	 * @return array
106
	 */
107
	static public function clear(array &$array, $path) {
108
		$path = self::separate($path);
109
		self::clearKey($array, $path);
110
		return $array;
111
	}
112
113
	/**
114
	 * @param array $array
115
	 * @param array $path
116
	 * @return array
117
	 */
118
	static private function clearKey(array &$array, array $path) {
119
		if (count($path)) {
120
			$key = array_shift($path);
121
			if (array_key_exists($key, $array)) {
122
				if (count($path)) {
123
					return self::clearKey($array[$key], $path);
124
				}
125
				unset($array[$key]);
126
			}
127
		}
128
		return $array;
129
	}
130
131
	/**
132
	 * Returns parts of $path that are separated by an escape-char
133
	 * Example:
134
	 * escape = \
135
	 * separator = .
136
	 * $path = 'a.bb.ccc.bb...a\.\.'
137
	 * result = array('a', 'bb', 'ccc', 'bb', '', '', 'a..')
138
	 *
139
	 * @param string $path
140
	 * @return array
141
	 */
142
	static private function separate($path) {
143
		$res = array();
144
		$idx = 0;
145
146
		for ($i = 0; $i < strlen($path); $i++) {
147
			$char = $path[$i];
148
149
			if ($char == self::ESCAPE) {
150
				$i++;
151
			} elseif ($char == self::SEPARATOR) {
152
				$idx++;
153
154
				if (!array_key_exists($idx, $res)) {
155
					$res[$idx] = '';
156
				}
157
			} else {
158
				if (!array_key_exists($idx, $res)) {
159
					$res[$idx] = '';
160
				}
161
162
				$res[$idx] .= $char;
163
			}
164
		}
165
166
		return $res;
167
	}
168
169
	/**
170
	 * Returns true when $array is an array or an ArrayObject
171
	 *
172
	 * @param mixed $array
173
	 * @return bool
174
	 */
175
	static private function isAcceptedArrayType($array) {
176
		return is_array($array) || $array instanceof ArrayObject;
177
	}
178
}