1: <?php
2:
3: /**
4: * Jyxo PHP Library
5: *
6: * LICENSE
7: *
8: * This source file is subject to the new BSD license that is bundled
9: * with this package in the file license.txt.
10: * It is also available through the world-wide-web at this URL:
11: * https://github.com/jyxo/php/blob/master/license.txt
12: */
13:
14: /**
15: * LimitIterator which supports Countable for transparent wrapping.
16: *
17: * @category Jyxo
18: * @package Jyxo_Spl
19: * @copyright Copyright (c) 2005-2011 Jyxo, s.r.o.
20: * @license https://github.com/jyxo/php/blob/master/license.txt
21: * @author Jakub Tománek
22: */
23: class Jyxo_Spl_CountableLimitIterator extends LimitIterator implements Countable
24: {
25: /**
26: * Result counting mode - returns all inner iterator data count.
27: *
28: * @var integer
29: */
30: const MODE_PASS = 1;
31:
32: /**
33: * Result counting mode - returns number of data after applying limit
34: * For proper function inner iterator must return exact number of its items.
35: *
36: * @var integer
37: */
38: const MODE_LIMIT = 2;
39:
40: /**
41: * Defined offset.
42: *
43: * @var integer
44: */
45: private $offset;
46:
47: /**
48: * Defined maximum item count.
49: *
50: * @var integer
51: */
52: private $count;
53:
54: /**
55: * Result counting mode - see self::MODE_* constants.
56: *
57: * @var integer
58: */
59: private $mode = self::MODE_PASS;
60:
61: /**
62: * Constructor.
63: *
64: * @param Iterator $iterator Source data
65: * @param integer $offset Offset (Optional)
66: * @param integer $count Maximum item count (Optional)
67: * @param integer $mode Result counting mode
68: * @throws InvalidArgumentException Inner iterator is not countable
69: */
70: public function __construct (Iterator $iterator, $offset = 0, $count = -1, $mode = self::MODE_PASS)
71: {
72: if (!($iterator instanceof Countable)) {
73: throw new InvalidArgumentException('Supplied iterator must be countable');
74: }
75:
76: parent::__construct($iterator, $offset, $count);
77: $this->offset = $offset;
78: $this->count = $count;
79: $this->mode = $mode;
80: }
81:
82: /**
83: * Returns number of items based on result counting mode (all inner or final count after applying limit).
84: *
85: * @return integer
86: */
87: public function count()
88: {
89: $count = count($this->getInnerIterator());
90: if (self::MODE_LIMIT === $this->mode) {
91: // We want real number of results - after applying limit
92:
93: if (0 !== $this->offset) {
94: // Offset from beginning
95: $count -= $this->offset;
96: }
97: if (-1 !== $this->count && $count > $this->count) {
98: // Maximum number of items
99: $count = $this->count;
100: }
101: if ($count < 0) {
102: // We moved after end of inner iterator - offset is higher than count($this->getInnerIterator())
103: $count = 0;
104: }
105: }
106: return $count;
107: }
108: }
109: