Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 37 |
|
0.00% |
0 / 11 |
CRAP | |
0.00% |
0 / 1 |
AbstractIterator | |
0.00% |
0 / 37 |
|
0.00% |
0 / 11 |
306 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
query | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
setPage | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
setNamespace | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
setFrom | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
setTo | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
current | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
key | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
rewind | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
valid | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
next | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
transform | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace Flow\Search\Iterators; |
4 | |
5 | use Flow\Container; |
6 | use Flow\Data\ManagerGroup; |
7 | use Flow\DbFactory; |
8 | use Flow\Model\AbstractRevision; |
9 | use Flow\Model\UUID; |
10 | use Iterator; |
11 | use MediaWiki\WikiMap\WikiMap; |
12 | use stdClass; |
13 | use Wikimedia\Rdbms\IDatabase; |
14 | use Wikimedia\Rdbms\IResultWrapper; |
15 | |
16 | abstract class AbstractIterator implements Iterator { |
17 | /** |
18 | * @var IDatabase |
19 | */ |
20 | protected $dbr; |
21 | |
22 | /** |
23 | * @var array |
24 | */ |
25 | protected $conditions = []; |
26 | |
27 | /** |
28 | * @var IResultWrapper|null |
29 | */ |
30 | protected $results; |
31 | |
32 | /** |
33 | * Depending on where we are in the iteration, this can be null (object |
34 | * constructed but not yet being iterated over), AbstractRevision (being |
35 | * iterated) or false (end of iteration, no more revisions) |
36 | * |
37 | * @var AbstractRevision|null|false |
38 | */ |
39 | protected $current; |
40 | |
41 | /** |
42 | * Depending on where we are in the iteration, this can be integer (object |
43 | * being iterated over) or null (iteration not yet started, or completed) |
44 | * |
45 | * @var int|null |
46 | */ |
47 | protected $key; |
48 | |
49 | /** |
50 | * @param DbFactory $dbFactory |
51 | */ |
52 | public function __construct( DbFactory $dbFactory ) { |
53 | $this->dbr = $dbFactory->getDB( DB_REPLICA ); |
54 | $this->conditions = [ 'workflow_wiki' => WikiMap::getCurrentWikiId() ]; |
55 | } |
56 | |
57 | /** |
58 | * @return bool|IResultWrapper |
59 | */ |
60 | abstract protected function query(); |
61 | |
62 | /** |
63 | * @param array|int|null $pageId |
64 | */ |
65 | public function setPage( $pageId = null ) { |
66 | $this->results = null; |
67 | |
68 | unset( $this->conditions['workflow_page_id'] ); |
69 | if ( $pageId !== null ) { |
70 | $this->conditions['workflow_page_id'] = $pageId; |
71 | } |
72 | } |
73 | |
74 | /** |
75 | * @param int|null $namespace |
76 | */ |
77 | public function setNamespace( $namespace = null ) { |
78 | $this->results = null; |
79 | |
80 | unset( $this->conditions['workflow_namespace'] ); |
81 | if ( $namespace !== null ) { |
82 | $this->conditions['workflow_namespace'] = $namespace; |
83 | } |
84 | } |
85 | |
86 | /** |
87 | * Define where to start iterating (inclusive) |
88 | * |
89 | * @param UUID|null $revId |
90 | */ |
91 | public function setFrom( UUID $revId = null ) { |
92 | $this->results = null; |
93 | |
94 | unset( $this->conditions[0] ); |
95 | if ( $revId !== null ) { |
96 | $this->conditions[0] = 'rev_id >= ' . $this->dbr->addQuotes( $revId->getBinary() ); |
97 | } |
98 | } |
99 | |
100 | /** |
101 | * Define where to stop iterating (exclusive) |
102 | * |
103 | * @param UUID|null $revId |
104 | */ |
105 | public function setTo( UUID $revId = null ) { |
106 | $this->results = null; |
107 | |
108 | unset( $this->conditions[1] ); |
109 | if ( $revId !== null ) { |
110 | $this->conditions[1] = 'rev_id < ' . $this->dbr->addQuotes( $revId->getBinary() ); |
111 | } |
112 | } |
113 | |
114 | /** |
115 | * @return AbstractRevision|null The most recently fetched revision object |
116 | */ |
117 | public function current() { |
118 | return $this->current; |
119 | } |
120 | |
121 | /** |
122 | * @return int 0-indexed count of the page number fetched |
123 | */ |
124 | public function key() { |
125 | return $this->key; |
126 | } |
127 | |
128 | /** |
129 | * Reset the iterator to the beginning of the table. |
130 | */ |
131 | public function rewind() { |
132 | $this->results = null; |
133 | $this->key = -1; // self::next() will turn this into 0 |
134 | $this->current = null; |
135 | $this->next(); |
136 | } |
137 | |
138 | /** |
139 | * @return bool True when the iterator is in a valid state |
140 | */ |
141 | public function valid() { |
142 | return (bool)$this->current; |
143 | } |
144 | |
145 | /** |
146 | * Fetch the next set of rows from the database. |
147 | */ |
148 | public function next() { |
149 | if ( $this->results === null ) { |
150 | $this->results = $this->query(); |
151 | } |
152 | |
153 | $current = $this->results->fetchObject(); |
154 | if ( $current !== false ) { |
155 | $this->current = $this->transform( $current ); |
156 | $this->key++; |
157 | } else { |
158 | // end of iteration reached |
159 | $this->current = false; |
160 | $this->key = null; |
161 | } |
162 | } |
163 | |
164 | /** |
165 | * Transforms the DB row into a revision object. |
166 | * |
167 | * $row will be one of the results of static::query(). In this method, $row |
168 | * is expected to have at least properties `rev_id` & `rev_type`, which will |
169 | * be used to fetch this specific row's data from storage. |
170 | * |
171 | * This will need to do some DB/cache requests. Ideally, those would be |
172 | * bundled instead of being done on a per-row record. These iterators |
173 | * are only meant to be run in maintenance scripts, however, so it |
174 | * doesn't really matter that much ;) |
175 | * |
176 | * @param stdClass $row |
177 | * @return AbstractRevision |
178 | */ |
179 | protected function transform( stdClass $row ) { |
180 | $uuid = UUID::create( $row->rev_id ); |
181 | |
182 | /** @var ManagerGroup $storage */ |
183 | $storage = Container::get( 'storage' ); |
184 | |
185 | // prevent memory from being filled up |
186 | $storage->clear(); |
187 | |
188 | return $storage->getStorage( $row->rev_type )->get( $uuid ); |
189 | } |
190 | } |