1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16:
17: 18: 19: 20: 21:
22: class Pinoco_List implements IteratorAggregate, ArrayAccess, Countable, Pinoco_ArrayConvertible
23: {
24: private $_arr;
25: private $_default_val;
26:
27: 28: 29:
30: public function __construct()
31: {
32: $this->_arr = array();
33: $this->_default_val = null;
34: }
35:
36: 37: 38: 39: 40: 41:
42: public static function fromArray($src)
43: {
44: $self = new Pinoco_List();
45: $self->concat($src);
46: return $self;
47: }
48:
49: 50: 51: 52: 53: 54: 55:
56: public static function wrap(&$srcref)
57: {
58: if (!is_array($srcref)) {
59: throw new InvalidArgumentException("Non array variable was given.");
60: }
61: $self = new Pinoco_List();
62: $self->_arr = &$srcref;
63: return $self;
64: }
65:
66: 67: 68: 69: 70: 71:
72: public function push($value)
73: {
74: $args = func_get_args();
75: foreach ($args as $a) {
76: array_push($this->_arr, $a);
77: }
78: }
79:
80: 81: 82: 83: 84:
85: public function pop()
86: {
87: return array_pop($this->_arr);
88: }
89:
90: 91: 92: 93: 94: 95:
96: public function unshift($value)
97: {
98: $args = func_get_args();
99: foreach ($args as $a) {
100: array_unshift($this->_arr, $a);
101: }
102: }
103:
104: 105: 106: 107: 108:
109: public function shift()
110: {
111: return array_shift($this->_arr);
112: }
113:
114: 115: 116: 117: 118: 119:
120: public function concat($source)
121: {
122: $args = func_get_args();
123: foreach ($args as $a) {
124: foreach ($a as $e) {
125: array_push($this->_arr, $e);
126: }
127: }
128: }
129:
130: 131: 132: 133: 134: 135:
136: public function sort($callable=null)
137: {
138: if (!$callable) {
139: sort($this->_arr);
140: }
141: else {
142: usort($this->_arr, $callable);
143: }
144: }
145:
146: 147: 148: 149: 150: 151:
152: public function sorted($callable=null)
153: {
154: $tmp = clone($this);
155: $tmp->sort($callable);
156: return $tmp;
157: }
158:
159: 160: 161: 162: 163:
164: public function count()
165: {
166: return count($this->_arr);
167: }
168:
169: 170: 171: 172: 173: 174:
175: public function join($sep=",")
176: {
177: return implode($sep, $this->_arr);
178: }
179:
180: 181: 182: 183: 184:
185: public function reverse()
186: {
187: return self::fromArray(array_reverse($this->_arr));
188: }
189:
190: 191: 192: 193: 194: 195: 196:
197: public function slice($offset, $length=null)
198: {
199: if (!is_null($length)) {
200: return self::fromArray(array_slice($this->_arr, $offset, $length));
201: }
202: else {
203: return self::fromArray(array_slice($this->_arr, $offset));
204: }
205: }
206:
207: 208: 209: 210: 211: 212: 213: 214:
215: public function splice($offset, $length=null, $replacement=null)
216: {
217: return self::fromArray(array_splice($this->_arr, $offset, $length, $replacement));
218: }
219:
220: 221: 222: 223: 224: 225: 226:
227: public function insert($offset, $value)
228: {
229: $args = func_get_args();
230: array_shift($args);
231: array_splice($this->_arr, $offset, 0, $args);
232: }
233:
234: 235: 236: 237: 238: 239: 240:
241: public function remove($offset, $length=1)
242: {
243: array_splice($this->_arr, $offset, $length);
244: }
245:
246: 247: 248: 249: 250: 251:
252: public function index($value)
253: {
254: $r = array_search($value, $this->_arr);
255: return $r===false ? -1 : $r;
256: }
257:
258: 259: 260: 261: 262: 263: 264:
265: public function get($idx, $default=Pinoco_OptionalParam::UNSPECIFIED)
266: {
267: if (isset($this->_arr[$idx])) {
268: return $this->_arr[$idx];
269: }
270: else {
271: return Pinoco_OptionalParam::isSpecifiedBy($default) ? $default : $this->_default_val;
272: }
273: }
274:
275: 276: 277: 278: 279: 280: 281:
282: public function rget($expression, $default=Pinoco_OptionalParam::UNSPECIFIED)
283: {
284: $default = Pinoco_OptionalParam::isSpecifiedBy($default) ? $default : $this->_default_val;
285: $es = explode('/', $expression);
286: $v = $this;
287: while (count($es) > 0) {
288: $name = trim(array_shift($es));
289: if ($name === "") {
290: continue;
291: }
292: if ($v instanceof Pinoco_ArrayConvertible) {
293: $v = $v->get($name, $default);
294: }
295: elseif (is_object($v)) {
296: if (property_exists($v, $name)) {
297: $v = $v->$name;
298: }
299: else {
300: return $default;
301: }
302: }
303: elseif (is_array($v)) {
304: if (array_key_exists($name, $v)) {
305: $v = $v[$name];
306: }
307: else {
308: return $default;
309: }
310: }
311: else {
312: return $default;
313: }
314: }
315: return $v;
316: }
317:
318: 319: 320: 321: 322: 323: 324: 325:
326: public function set($idx, $value, $default=Pinoco_OptionalParam::UNSPECIFIED)
327: {
328: $default = Pinoco_OptionalParam::isSpecifiedBy($default) ? $default : $this->_default_val;
329: for ($i = count($this->_arr); $i < $idx; $i++) {
330: $this->_arr[$i] = $default;
331: }
332: $this->_arr[$idx] = $value;
333: }
334:
335: 336: 337: 338: 339: 340:
341: public function setDefault($value)
342: {
343: $this->_default_val = $value;
344: }
345:
346: 347: 348: 349: 350: 351:
352: public function toArray($modifier=null)
353: {
354: $arr = array();
355: if ($modifier) {
356: foreach ($this->_arr as $i=>$v) {
357: $name = (strpos($modifier, "%") !== false) ? sprintf($modifier, $i) : (
358: is_callable($modifier) ? call_user_func($modifier, $i) : ($modifier . $i)
359: );
360: $arr[$name] = $v;
361: }
362: }
363: else {
364: foreach ($this->_arr as $i=>$v) {
365: $arr[$i] = $v;
366: }
367: }
368: return $arr;
369: }
370:
371: 372: 373: 374: 375: 376:
377: public function toArrayRecurse($depth=null)
378: {
379: if ($depth !== null && $depth == 0) { return $this; }
380: $arr = array();
381: foreach ($this->_arr as $i=>$v) {
382: if ($v instanceof Pinoco_ArrayConvertible) {
383: $v = $v->toArrayRecurse($depth !== null ? $depth - 1 : null);
384: }
385: $arr[$i] = $v;
386: }
387: return $arr;
388: }
389:
390: 391: 392: 393: 394: 395: 396:
397: public function reduce($callable, $initial=null)
398: {
399: return array_reduce($this->_arr, $callable, $initial);
400: }
401:
402: 403: 404: 405: 406: 407:
408: public function each($callable)
409: {
410: foreach ($this->_arr as $e) {
411: call_user_func($callable, $e);
412: }
413: }
414:
415: 416: 417: 418: 419: 420:
421: public function map($callable)
422: {
423: return self::fromArray(array_map($callable, $this->_arr));
424: }
425:
426: 427: 428: 429: 430: 431:
432: public function filter($callable)
433: {
434: return self::fromArray(array_filter($this->_arr, $callable));
435: }
436:
437: 438: 439: 440: 441: 442: 443: 444:
445:
446: public function offsetSet($offset, $value)
447: {
448: $this->set($offset, $value);
449: }
450: public function offsetExists($offset)
451: {
452: return $offset < count($this->_arr);
453: }
454: public function offsetUnset($offset)
455: {
456: array_splice($this->_arr, $offset, 1);
457: }
458: public function offsetGet($offset)
459: {
460: return $this->get($offset);
461: }
462:
463: public function getIterator()
464: {
465: return new Pinoco_ArrayConvertiblesIterator($this->_arr);
466: }
467:
468: public function __toString() { return __CLASS__; }
469: }
470:
471: