File: CArrayHelper.php

package info (click to toggle)
zabbix 1%3A4.0.4%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 83,104 kB
  • sloc: php: 162,280; ansic: 154,778; sql: 96,479; sh: 5,281; makefile: 1,340; java: 1,068; cpp: 227; perl: 41; xml: 29
file content (266 lines) | stat: -rw-r--r-- 6,963 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
<?php
/*
 ** Zabbix
** Copyright (C) 2001-2019 Zabbix SIA
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
**/


class CArrayHelper {

	/**
	 * @var array
	 */
	protected static $fields;

	private function __construct() {}

	/**
	 * Get from array only values with given keys.
	 * If requested key is not in given array exception is thrown.
	 *
	 * @static
	 * @throws InvalidArgumentException
	 *
	 * @param array $array
	 * @param array $keys
	 *
	 * @return array
	 */
	public static function getByKeysStrict(array $array, array $keys) {
		$result = [];
		foreach ($keys as $key) {
			if (!isset($array[$key])) {
				throw new InvalidArgumentException(sprintf('Array does not have element with key "%1$s".', $key));
			}
			$result[$key] = $array[$key];
		}

		return $result;
	}

	/**
	 * Get values with the $keys from $array.
	 * If the requested key is not in the given array it is skipped.
	 *
	 * @static
	 *
	 * @param array $array
	 * @param array $keys
	 *
	 * @return array
	 */
	public static function getByKeys(array $array, array $keys) {
		$result = [];
		foreach ($keys as $key) {
			if (array_key_exists($key, $array)) {
				$result[$key] = $array[$key];
			}
		}

		return $result;
	}

	/**
	 * Select sub-array of array items with keys in given numeric range.
	 *
	 * @static
	 *
	 * @param array $array    Array with numeric keys to test for given range.
	 * @param int   $start    Range start value.
	 * @param int   $end      Range end value.
	 *
	 * @return array
	 */
	public static function getByKeysRange(array $array, $start, $end) {
		$result = [];
		foreach ($array as $key => $val) {
			if ($key >= $start && $key <= $end) {
				$result[$key] = $val;
			}
		}

		return $result;
	}

	/**
	 * Renames array elements keys according to given map.
	 *
	 * @param array $array
	 * @param array $field_map
	 *
	 * @return array
	 */
	public static function renameKeys(array $array, array $field_map) {
		foreach ($field_map as $old_key => $new_key) {
			if (array_key_exists($old_key, $array)) {
				$array[$new_key] = $array[$old_key];
				unset($array[$old_key]);
			}
		}

		return $array;
	}

	/**
	 * Renames keys according to given map for given array of the objects.
	 *
	 * @param array $array
	 * @param array $field_map
	 *
	 * @return array
	 */
	public static function renameObjectsKeys(array $array, array $field_map) {
		foreach ($array as &$object) {
			foreach ($field_map as $old_key => $new_key) {
				$object[$new_key] = $object[$old_key];
				unset($object[$old_key]);
			}
		}
		unset($object);

		return $array;
	}

	/**
	 * Sort array by multiple fields.
	 *
	 * @static
	 *
	 * @param array $array  array to sort passed by reference
	 * @param array $fields fields to sort, can be either string with field name or array with 'field' and 'order' keys
	 */
	public static function sort(array &$array, array $fields) {
		foreach ($fields as $fid => $field) {
			if (!is_array($field)) {
				$fields[$fid] = ['field' => $field, 'order' => ZBX_SORT_UP];
			}
		}
		self::$fields = $fields;
		uasort($array, ['self', 'compare']);
	}

	/**
	 * Method to be used as callback for uasort function in sort method.
	 *
	 * @TODO: with PHP 5.3+ this should be changed to closure
	 * @static
	 *
	 * @param $a
	 * @param $b
	 *
	 * @return int
	 */
	protected static function compare($a, $b) {
		foreach (self::$fields as $field) {
			// if field is not set or is null, treat it as smallest string
			// strnatcasecmp() has unexpected behaviour with null values
			if (!isset($a[$field['field']]) && !isset($b[$field['field']])) {
				$cmp = 0;
			}
			elseif (!isset($a[$field['field']])) {
				$cmp = -1;
			}
			elseif (!isset($b[$field['field']])) {
				$cmp = 1;
			}
			else {
				$cmp = strnatcasecmp($a[$field['field']], $b[$field['field']]);
			}

			if ($cmp != 0) {
				return $cmp * ($field['order'] == ZBX_SORT_UP?1:-1);
			}
		}
		return 0;
	}

	/**
	 * Unset values that are contained in $a2 from $a1. Skip arrays and keys given in $skipKeys.
	 *
	 * @param array $a1         array to modify
	 * @param array $a2         array to compare with
	 * @param array $skipKeys   fields to ignore
	 *
	 * @return array
	 */
	public static function unsetEqualValues(array $a1, array $a2, array $skipKeys = []) {
		// ignore given fields
		foreach ($skipKeys as $key) {
			unset($a2[$key]);
		}

		foreach ($a1 as $key => $value) {
			// check if the values under $key are equal, skip arrays
			if (isset($a2[$key]) && !is_array($value) && !is_array($a2[$key])
					&& (string) $a1[$key] === (string) $a2[$key]) {
				unset($a1[$key]);
			}
		}

		return $a1;
	}

	/**
	 * Checks if array $arrays contains arrays with duplicate values under the $uniqueField key. If a duplicate exists,
	 * returns the first duplicate, otherwise returns null.
	 *
	 * Example 1:
	 * $data = array(
	 *     array('name' => 'CPU load'),
	 * 	   array('name' => 'CPU load'),
	 * 	   array('name' => 'Free memory')
	 * );
	 * var_dump(CArrayHelper::findDuplicate($data, 'name')); // returns array with index 1
	 *
	 * Example 2:
	 * $data = array(
	 *     array('host' => 'Zabbix server', 'name' => 'CPU load'),
	 * 	   array('host' => 'Zabbix server', 'name' => 'Free memory'),
	 * 	   array('host' => 'Linux server', 'name' => 'CPU load'),
	 * 	   array('host' => 'Zabbix server', 'name' => 'CPU load')
	 * );
	 * var_dump(CArrayHelper::findDuplicate($data, 'name', 'host')); // returns array with index 3
	 *
	 * @param array $arrays         an array of arrays
	 * @param string $uniqueField   key to be used as unique criteria
	 * @param string $uniqueField2	second key to be used as unique criteria
	 *
	 * @return null|array           the first duplicate found or null if there are no duplicates
	 */
	public static function findDuplicate(array $arrays, $uniqueField, $uniqueField2 = null) {
		$uniqueValues = [];

		foreach ($arrays as $array) {
			$value = $array[$uniqueField];

			if ($uniqueField2 !== null) {
				$uniqueByValue = $array[$uniqueField2];

				if (isset($uniqueValues[$uniqueByValue]) && isset($uniqueValues[$uniqueByValue][$value])) {
					return $array;
				}
				$uniqueValues[$uniqueByValue][$value] = $value;
			}
			else {
				if (isset($uniqueValues[$value])) {
					return $array;
				}
				$uniqueValues[$value] = $value;
			}
		}
	}
}