Projekt

Obecné

Profil

Stáhnout (13.1 KB) Statistiky
| Větev: | Tag: | Revize:
1
<?php
2
/* SVN FILE: $Id: set.php 5117 2007-05-18 16:46:55Z phpnut $ */
3
/**
4
 * Library of array functions for Cake.
5
 *
6
 * PHP versions 4 and 5
7
 *
8
 * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
9
 * Copyright 2005-2007, Cake Software Foundation, Inc.
10
 *								1785 E. Sahara Avenue, Suite 490-204
11
 *								Las Vegas, Nevada 89104
12
 *
13
 * Licensed under The MIT License
14
 * Redistributions of files must retain the above copyright notice.
15
 *
16
 * @filesource
17
 * @copyright		Copyright 2005-2007, Cake Software Foundation, Inc.
18
 * @link				http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
19
 * @package			cake
20
 * @subpackage		cake.cake.libs
21
 * @since			CakePHP(tm) v 1.2.0
22
 * @version			$Revision: 5117 $
23
 * @modifiedby		$LastChangedBy: phpnut $
24
 * @lastmodified	$Date: 2007-05-18 11:46:55 -0500 (Fri, 18 May 2007) $
25
 * @license			http://www.opensource.org/licenses/mit-license.php The MIT License
26
 */
27
/**
28
 * Class used for manipulation of arrays.
29
 *
30
 * Long description for class
31
 *
32
 * @package		cake
33
 * @subpackage	cake.cake.libs
34
 */
35
class Set extends Object {
36
/**
37
 * Value of the Set object.
38
 *
39
 * @var array
40
 * @access public
41
 */
42
	var $value = array();
43
/**
44
 * Constructor. Defaults to an empty array.
45
 *
46
 * @access public
47
 */
48
	function __construct() {
49
		if (func_num_args() == 1 && is_array(func_get_arg(0))) {
50
			$this->value = func_get_arg(0);
51
		} else {
52
			$this->value = func_get_args();
53
		}
54
	}
55
/**
56
 * Returns the contents of the Set object
57
 *
58
 * @access public
59
 */
60
	function &get() {
61
		return $this->value;
62
	}
63
/**
64
 * This function can be thought of as a hybrid between PHP's array_merge and array_merge_recursive. The difference
65
 * to the two is that if an array key contains another array then the function behaves recursive (unlike array_merge)
66
 * but does not do if for keys containing strings (unlike array_merge_recursive). See the unit test for more information.
67
 *
68
 * Note: This function will work with an unlimited amount of arguments and typecasts non-array parameters into arrays.
69
 *
70
 * @param array $arr1
71
 * @param array $arr2
72
 * @return array
73
 * @access public
74
 */
75
	function merge($arr1, $arr2 = null) {
76
		$args = func_get_args();
77

    
78
		if(is_a($this, 'set')) {
79
			$backtrace = debug_backtrace();
80
			$previousCall = low($backtrace[1]['class'].'::'.$backtrace[1]['function']);
81
			if ($previousCall != 'set::merge') {
82
				$r =& $this->value;
83
				array_unshift($args, null);
84
			}
85
		}
86
		if(!isset($r)) {
87
			$r = (array)current($args);
88
		}
89

    
90
		while(($arg = next($args)) !== false) {
91
			if (is_a($arg, 'set')) {
92
				$arg = $arg->get();
93
			}
94

    
95
			foreach((array)$arg as $key => $val)	 {
96
				if(is_array($val) && isset($r[$key]) && is_array($r[$key])) {
97
					$r[$key] = Set::merge($r[$key], $val);
98
				} elseif(is_int($key)) {
99
					$r[] = $val;
100
				} else {
101
					$r[$key] = $val;
102
				}
103
			}
104
		}
105
		return $r;
106
	}
107
/**
108
 * Filters empty elements out of a route array, excluding '0'.
109
 *
110
 * @return mixed
111
 */
112
	function filter($var, $isArray = false) {
113
		if (is_array($var) && (!empty($var) || $isArray)) {
114
			$set = new Set();
115
			return array_filter($var, array(&$set, 'filter'));
116
		} else {
117
			if ($var === 0 || $var === '0' || !empty($var)) {
118
				return true;
119
			} else {
120
				return false;
121
			}
122
		}
123
	}
124
/**
125
 * Pushes the differences in $array2 onto the end of $array
126
 *
127
 * @param mixed $array
128
 * @param mixed $arrary2
129
 * @return array
130
 * @access public
131
 */
132
	function pushDiff($array = null, $array2 = null) {
133
		if ($array2 !== null && is_array($array2)) {
134
			foreach($array2 as $key => $value) {
135
				if (!array_key_exists($key, $array)) {
136
					$array[$key] = $value;
137
				} else {
138
					if (is_array($value)) {
139
						$array[$key] = Set::pushDiff($array[$key], $array2[$key]);
140
					}
141
				}
142
			}
143
			return $array;
144
		}
145

    
146
		if(!isset($this->value)) {
147
			$this->value = array();
148
		}
149
		$this->value = Set::pushDiff($this->value, Set::__array($array));
150
		return $this->value;
151
	}
152
/**
153
 * Maps the contents of the Set object to an object hierarchy
154
 *
155
 * @param string $class A class name of the type of object to map to
156
 * @return object
157
 * @access public
158
 */
159
	function map($class = 'stdClass', $tmp = 'stdClass') {
160
		if (is_array($class)) {
161
			$val = $class;
162
			$class = $tmp;
163
		} elseif (is_a($this, 'set')) {
164
			$val = $this->get();
165
		}
166

    
167
		if (empty($val) || $val == null) {
168
			return null;
169
		}
170
		return Set::__map($val, $class);
171
	}
172
	function __array($array) {
173
		if ($array == null) {
174
			$array = $this->value;
175
		} elseif (is_object($array) && (is_a($array, 'set'))) {
176
			$array = $array->get();
177
		} elseif (is_object($array)) {
178
			$array = get_object_vars($array);
179
		} elseif (!is_array($array)) {
180
			$array = array($array);
181
		}
182
		return $array;
183
	}
184
	function __map($value, $class, $identity = null) {
185

    
186
		if (is_object($value)) {
187
			return $value;
188
		}
189

    
190
		if (!empty($value) && Set::numeric(array_keys($value))) {
191
			$ret = array();
192
			foreach ($value as $key => $val) {
193
				$ret[$key] = Set::__map($val, $class);
194
			}
195
		} else {
196
			$ret = new $class;
197
			if ($identity != null) {
198
				$ret->__identity__ = $identity;
199
			}
200
		}
201

    
202
		if (empty($value)) {
203
			return $ret;
204
		}
205

    
206
		$keys = array_keys($value);
207
		foreach ($value as $key => $val) {
208
			if (!is_numeric($key) && strlen($key) > 1) {
209
				if ($key{0} == strtoupper($key{0}) && $key{1} == strtolower($key{1}) && (is_array($val) || is_object($val))) {
210
					if ($key == $keys[0]) {
211
						$ret = Set::__map($val, $class, $key);
212
					} else {
213
						$ret->{$key} = Set::__map($val, $class, $key);
214
					}
215
				} else {
216
					$ret->{$key} = $val;
217
				}
218
			}
219
		}
220
		return $ret;
221
	}
222
/**
223
 * Checks to see if all the values in the array are numeric
224
 *
225
 * @param array $array The array to check.  If null, the value of the current Set object
226
 * @return boolean
227
 * @access public
228
 */
229
	function numeric($array = null) {
230
		if ($array == null && (is_a($this, 'set') || is_a($this, 'Set'))) {
231
			$array = $this->get();
232
		}
233

    
234
		$numeric = true;
235
		$keys = array_keys($array);
236
		$count = count($keys);
237
		for ($i = 0; $i < $count; $i++) {
238
			if (!is_numeric($array[$keys[$i]])) {
239
				$numeric = false;
240
				break;
241
			}
242
		}
243
		return $numeric;
244
	}
245
/**
246
 * Return a value from an array list if the key exists.
247
 *
248
 * If a comma separated $list is passed arrays are numeric with the key of the first being 0
249
 * $list = 'no, yes' would translate to  $list = array(0 => 'no', 1 => 'yes');
250
 *
251
 * If an array is used, keys can be strings example: array('no' => 0, 'yes' => 1);
252
 *
253
 * $list defaults to 0 = no 1 = yes if param is not passed
254
 *
255
 * @param mixed $selected
256
 * @param mixed $list can be an array or a comma-separated list.
257
 * @return string the value of the array key or null if no match
258
 */
259
	function enum($select, $list = null) {
260
		if (empty($list) && is_a($this, 'Set')) {
261
			$list = $this->get();
262
		} elseif (empty($list)) {
263
			$list = array('no', 'yes');
264
		}
265

    
266
		$return = null;
267
		$list = Set::normalize($list, false);
268

    
269
		if (array_key_exists($select, $list)) {
270
			$return = $list[$select];
271
		}
272
		return $return;
273
	}
274
/**
275
 * Gets a value from an array or object.
276
 * The special {n}, as seen in the Model::generateList method, is taken care of here.
277
 *
278
 * @param array $data
279
 * @param mixed $path	As an array, or as a dot-separated string.
280
 * @return array
281
 */
282
	function extract($data, $path = null) {
283
		if ($path === null && is_a($this, 'set')) {
284
			$path = $data;
285
			$data = $this->get();
286
		}
287
		if (is_object($data)) {
288
			$data = get_object_vars($data);
289
		}
290

    
291
		if (!is_array($path)) {
292
			if (strpos($path, '/') !== 0 && strpos($path, './') === false) {
293
				$path = explode('.', $path);
294
			} else {
295
			}
296
		}
297
		$tmp = array();
298
		if (!is_array($path) || empty($path)) {
299
			return null;
300
		}
301

    
302
		foreach($path as $i => $key) {
303
			if (is_numeric($key) && intval($key) > 0 || $key == '0') {
304
				if (isset($data[intval($key)])) {
305
					$data = $data[intval($key)];
306
				} else {
307
					return null;
308
				}
309
			} elseif ($key == '{n}') {
310
				foreach($data as $j => $val) {
311
					$tmp[] = Set::extract($val, array_slice($path, $i + 1));
312
				}
313
				return $tmp;
314
			} else {
315
				if (isset($data[$key])) {
316
					$data = $data[$key];
317
				} else {
318
					return null;
319
				}
320
			}
321
		}
322
		return $data;
323
	}
324
/**
325
 * Inserts $data into an array as defined by $path.
326
 *
327
 * @param mixed $list
328
 * @param array $data
329
 * @param mixed $path A dot-separated string.
330
 * @return array
331
 */
332
	function insert($list, $path, $data = null) {
333
		if (empty($data) && is_a($this, 'Set')) {
334
			$data = $path;
335
			$path = $list;
336
			$list =& $this->get();
337
		}
338
		if (!is_array($path)) {
339
			$path = explode('.', $path);
340
		}
341
		$_list =& $list;
342

    
343
		foreach($path as $i => $key) {
344
			if (is_numeric($key) && intval($key) > 0 || $key == '0') {
345
				$key = intval($key);
346
			}
347
			if ($i == count($path) - 1) {
348
				$_list[$key] = $data;
349
			} else {
350
				if (!isset($_list[$key])) {
351
					$_list[$key] = array();
352
				}
353
				$_list =& $_list[$key];
354
			}
355
		}
356
		return $list;
357
	}
358
/**
359
 * Removes an element from a Set or array
360
 *
361
 * @param mixed $list
362
 * @param array $data
363
 * @param mixed $path A dot-separated string.
364
 * @return array
365
 */
366
	function remove($list, $path = null) {
367
		if (empty($path) && is_a($this, 'Set')) {
368
			$path = $list;
369
			$list =& $this->get();
370
		}
371
		if (!is_array($path)) {
372
			$path = explode('.', $path);
373
		}
374
		$_list =& $list;
375

    
376
		foreach($path as $i => $key) {
377
			if (is_numeric($key) && intval($key) > 0 || $key == '0') {
378
				$key = intval($key);
379
			}
380
			if ($i == count($path) - 1) {
381
				unset($_list[$key]);
382
			} else {
383
				if (!isset($_list[$key])) {
384
					return $list;
385
				}
386
				$_list =& $_list[$key];
387
			}
388
		}
389

    
390
		if (is_a($this, 'Set')) {
391
			$this->value = $list;
392
			return $this;
393
		} else {
394
			return $list;
395
		}
396
	}
397
/**
398
 * Checks if a particular path is set in an array
399
 *
400
 * @param mixed $data
401
 * @param mixed $path A dot-separated string.
402
 * @return array
403
 */
404
	function check($data, $path = null) {
405
		if (empty($path) && is_a($this, 'Set')) {
406
			$path = $data;
407
			$data = $this->get();
408
		}
409
		if (!is_array($path)) {
410
			$path = explode('.', $path);
411
		}
412

    
413
		foreach($path as $i => $key) {
414
			if (is_numeric($key) && intval($key) > 0 || $key == '0') {
415
				$key = intval($key);
416
			}
417
			if ($i == count($path) - 1) {
418
				return isset($data[$key]);
419
			} else {
420
				if (!isset($data[$key])) {
421
					return false;
422
				}
423
				$data =& $data[$key];
424
			}
425
		}
426
		return true;
427
	}
428
/**
429
 * Computes the difference between a Set and an array, two Sets, or two arrays
430
 *
431
 * @param mixed $val1
432
 * @param mixed $val2
433
 * @return array
434
 */
435
	function diff($val1, $val2 = null) {
436
		if ($val2 == null && (is_a($this, 'set') || is_a($this, 'Set'))) {
437
			$val2 = $val1;
438
			$val1 = $this->get();
439
		}
440
		if (is_object($val2) && (is_a($val2, 'set') || is_a($val2, 'Set'))) {
441
			$val2 = $val2->get();
442
		}
443

    
444
		$out = array();
445
		if (empty($val1)) {
446
			return (array)$val2;
447
		} elseif (empty($val2)) {
448
			return (array)$val1;
449
		}
450
		foreach ($val1 as $key => $val) {
451
			if (isset($val2[$key]) && $val2[$key] != $val) {
452
				$out[$key] = $val;
453
			} else if(!array_key_exists($key, $val2)){
454
				$out[$key] = $val;
455
			}
456
		}
457
		return $out;
458
	}
459
/**
460
 * Determines if two Sets or arrays are equal
461
 *
462
 * @param array $val1
463
 * @param array $val2
464
 * @return boolean
465
 */
466
	function isEqual($val1, $val2 = null) {
467
		if ($val2 == null && (is_a($this, 'set') || is_a($this, 'Set'))) {
468
			$val2 = $val1;
469
			$val1 = $this->get();
470
		}
471
	}
472
/**
473
 * Determines if one Set or array contains the exact keys and values of another.
474
 *
475
 * @param array $val1
476
 * @param array $val2
477
 * @return boolean
478
 */
479
	function contains($val1, $val2 = null) {
480
		if ($val2 == null && is_a($this, 'set')) {
481
			$val2 = $val1;
482
			$val1 = $this->get();
483
		} elseif ($val2 != null && is_object($val2) && is_a($val2, 'set')) {
484
			$val2 = $val2->get();
485
		}
486

    
487
		foreach ($val2 as $key => $val) {
488
			if (is_numeric($key)) {
489
				if (!in_array($val, $val1)) {
490
					return false;
491
				}
492
			} else {
493
				if (!isset($val1[$key]) || $val1[$key] != $val) {
494
					return false;
495
				}
496
			}
497
		}
498
		return true;
499
	}
500
/**
501
 * Counts the dimensions of an array
502
 *
503
 * @param array $array
504
 * @return int The number of dimensions in $array
505
 */
506
	function countDim($array = null) {
507
		if ($array === null) {
508
			$array = $this->get();
509
		} elseif (is_object($array) && is_a($array, 'set')) {
510
			$array = $array->get();
511
		}
512
		if (is_array(reset($array))) {
513
			$return = Set::countDim(reset($array)) + 1;
514
		} else {
515
			$return = 1;
516
		}
517
		return $return;
518
	}
519
/**
520
 * Normalizes a string or array list
521
 *
522
 * @param mixed $list
523
 * @param boolean $assoc If true, $list will be converted to an associative array
524
 * @param string $sep If $list is a string, it will be split into an array with $sep
525
 * @param boolean $trim If true, separated strings will be trimmed
526
 * @return array
527
 */
528
	function normalize($list, $assoc = true, $sep = ',', $trim = true) {
529
		if (is_string($list)) {
530
			$list = explode($sep, $list);
531
			if ($trim) {
532
				$list = array_map('trim', $list);
533
			}
534
			if ($assoc) {
535
				return Set::normalize($list);
536
			}
537
		} elseif (is_array($list)) {
538
			$keys = array_keys($list);
539
			$count = count($keys);
540
			$numeric = true;
541

    
542
			if (!$assoc) {
543
				for ($i = 0; $i < $count; $i++) {
544
					if (!is_int($keys[$i])) {
545
						$numeric = false;
546
						break;
547
					}
548
				}
549
			}
550
			if (!$numeric || $assoc) {
551
				$newList = array();
552
				for ($i = 0; $i < $count; $i++) {
553
					if (is_int($keys[$i])) {
554
						$newList[$list[$keys[$i]]] = null;
555
					} else {
556
						$newList[$keys[$i]] = $list[$keys[$i]];
557
					}
558
				}
559
				$list = $newList;
560
			}
561
		}
562
		return $list;
563
	}
564
}
565
?>
(18-18/19)