Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
48.21% |
27 / 56 |
|
43.75% |
7 / 16 |
CRAP | |
0.00% |
0 / 1 |
AbstractCollection | |
48.21% |
27 / 56 |
|
43.75% |
7 / 16 |
119.88 | |
0.00% |
0 / 1 |
getRevisionClass | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getWorkflowId | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getBoardWorkflowId | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
newFromId | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
newFromRevisionId | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
newFromRevision | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getId | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getStorage | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
getAllRevisions | |
69.23% |
9 / 13 |
|
0.00% |
0 / 1 |
4.47 | |||
getRevision | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
getFirstRevision | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getLastRevision | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getPrevRevision | |
75.00% |
3 / 4 |
|
0.00% |
0 / 1 |
2.06 | |||
getNextRevision | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
getTitle | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getWorkflow | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
3.04 | |||
getBoardWorkflow | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace Flow\Collection; |
4 | |
5 | use Flow\Container; |
6 | use Flow\Data\ManagerGroup; |
7 | use Flow\Data\ObjectManager; |
8 | use Flow\Exception\FlowException; |
9 | use Flow\Exception\InvalidDataException; |
10 | use Flow\Model\AbstractRevision; |
11 | use Flow\Model\UUID; |
12 | use Flow\Model\Workflow; |
13 | use MediaWiki\Title\Title; |
14 | |
15 | abstract class AbstractCollection { |
16 | /** |
17 | * Id of the collection object. |
18 | * |
19 | * @var UUID |
20 | */ |
21 | protected $uuid; |
22 | |
23 | /** |
24 | * Array of revisions for this object. |
25 | * |
26 | * @var AbstractRevision[] |
27 | */ |
28 | protected $revisions = []; |
29 | |
30 | /** |
31 | * @var Workflow |
32 | */ |
33 | protected $workflow; |
34 | |
35 | /** |
36 | * Returns the revision class name for this specific object (e.g. Header, |
37 | * PostRevision) |
38 | * |
39 | * @return string |
40 | */ |
41 | public static function getRevisionClass() { |
42 | // Workaround to allow static inheritance without strict standards warning from this being abstract |
43 | throw new FlowException( 'getRevisionClass() must be implemented in the subclass', 'not-implemented' ); |
44 | } |
45 | |
46 | /** |
47 | * Returns the id of the workflow this collection is associated with. |
48 | * |
49 | * @return UUID |
50 | */ |
51 | abstract public function getWorkflowId(); |
52 | |
53 | /** |
54 | * Returns the id of the workflow of the board this collection is on. |
55 | * |
56 | * @return UUID |
57 | */ |
58 | abstract public function getBoardWorkflowId(); |
59 | |
60 | /** |
61 | * Use the static methods to load an object from a given revision. |
62 | * |
63 | * @see AbstractCollection::newFromId |
64 | * @see AbstractCollection::newFromRevision |
65 | * @see AbstractCollection::newFromRevisionId |
66 | * |
67 | * @param UUID $uuid |
68 | */ |
69 | protected function __construct( UUID $uuid ) { |
70 | $this->uuid = $uuid; |
71 | } |
72 | |
73 | /** |
74 | * Instantiate a new object based on its type id |
75 | * (post ID, header ID, etc.) |
76 | * |
77 | * @param UUID $uuid |
78 | * @return static |
79 | * @suppress PhanTypeInstantiateAbstractStatic Phan is right, though |
80 | */ |
81 | public static function newFromId( UUID $uuid ) { |
82 | return new static( $uuid ); |
83 | } |
84 | |
85 | /** |
86 | * Instantiate a new collection based on a revision ID |
87 | * |
88 | * @param UUID $revId Revision ID |
89 | * @return AbstractCollection |
90 | */ |
91 | public static function newFromRevisionId( UUID $revId ) { |
92 | $revision = static::getStorage()->get( $revId ); |
93 | |
94 | if ( $revision === null ) { |
95 | throw new InvalidDataException( |
96 | 'Revisions for ' . $revId->getAlphadecimal() . ' could not be found', |
97 | 'invalid-revision-id' |
98 | ); |
99 | } |
100 | |
101 | return static::newFromRevision( $revision ); |
102 | } |
103 | |
104 | /** |
105 | * Instantiate a new object based off of an AbstractRevision object. |
106 | * |
107 | * @param AbstractRevision $revision |
108 | * @return AbstractCollection |
109 | */ |
110 | public static function newFromRevision( AbstractRevision $revision ) { |
111 | return static::newFromId( $revision->getCollectionId() ); |
112 | } |
113 | |
114 | /** |
115 | * @return UUID |
116 | */ |
117 | public function getId() { |
118 | return $this->uuid; |
119 | } |
120 | |
121 | /** |
122 | * @param string|null $class Storage class - defaults to getRevisionClass() |
123 | * @return ObjectManager |
124 | */ |
125 | public static function getStorage( $class = null ) { |
126 | if ( !$class ) { |
127 | $class = static::getRevisionClass(); |
128 | } |
129 | |
130 | /** @var ManagerGroup $storage */ |
131 | $storage = Container::get( 'storage' ); |
132 | return $storage->getStorage( $class ); |
133 | } |
134 | |
135 | /** |
136 | * @return AbstractRevision[] |
137 | * @throws InvalidDataException When no revisions can be found |
138 | */ |
139 | public function getAllRevisions() { |
140 | if ( !$this->revisions ) { |
141 | /** @var AbstractRevision[] $revisions */ |
142 | $revisions = self::getStorage()->find( |
143 | [ 'rev_type_id' => $this->uuid ], |
144 | [ 'sort' => 'rev_id', 'order' => 'DESC' ] |
145 | ); |
146 | |
147 | if ( !$revisions ) { |
148 | throw new InvalidDataException( |
149 | 'Revisions for ' . $this->uuid->getAlphadecimal() . ' could not be found', |
150 | 'invalid-type-id' |
151 | ); |
152 | } |
153 | |
154 | foreach ( $revisions as $revision ) { |
155 | $this->revisions[$revision->getRevisionId()->getAlphadecimal()] = $revision; |
156 | } |
157 | } |
158 | |
159 | return $this->revisions; |
160 | } |
161 | |
162 | /** |
163 | * Returns the revision with the given id. |
164 | * |
165 | * @param UUID $uuid |
166 | * @return AbstractRevision|null null if there is no such revision in the collection |
167 | */ |
168 | public function getRevision( UUID $uuid ) { |
169 | // make sure all revisions have been loaded |
170 | $this->getAllRevisions(); |
171 | |
172 | if ( !isset( $this->revisions[$uuid->getAlphadecimal()] ) ) { |
173 | return null; |
174 | } |
175 | |
176 | // find requested id, based on given revision |
177 | return $this->revisions[$uuid->getAlphadecimal()]; |
178 | } |
179 | |
180 | /** |
181 | * Returns the oldest revision. |
182 | * |
183 | * @return AbstractRevision |
184 | */ |
185 | public function getFirstRevision() { |
186 | $revisions = $this->getAllRevisions(); |
187 | return array_pop( $revisions ); |
188 | } |
189 | |
190 | /** |
191 | * Returns the most recent revision. |
192 | * |
193 | * @return AbstractRevision |
194 | */ |
195 | public function getLastRevision() { |
196 | $revisions = $this->getAllRevisions(); |
197 | return array_shift( $revisions ); |
198 | } |
199 | |
200 | /** |
201 | * Given a certain revision, returns the previous revision. |
202 | * |
203 | * @param AbstractRevision $revision |
204 | * @return AbstractRevision|null null if there is no previous revision |
205 | */ |
206 | public function getPrevRevision( AbstractRevision $revision ) { |
207 | $previousRevisionId = $revision->getPrevRevisionId(); |
208 | if ( !$previousRevisionId ) { |
209 | return null; |
210 | } |
211 | |
212 | return $this->getRevision( $previousRevisionId ); |
213 | } |
214 | |
215 | /** |
216 | * Given a certain revision, returns the next revision. |
217 | * |
218 | * @param AbstractRevision $revision |
219 | * @return AbstractRevision|null null if there is no next revision |
220 | */ |
221 | public function getNextRevision( AbstractRevision $revision ) { |
222 | // make sure all revisions have been loaded |
223 | $this->getAllRevisions(); |
224 | |
225 | // find requested id, based on given revision |
226 | $ids = array_keys( $this->revisions ); |
227 | $current = array_search( $revision->getRevisionId()->getAlphadecimal(), $ids ); |
228 | $next = $current - 1; |
229 | |
230 | if ( $next < 0 ) { |
231 | return null; |
232 | } |
233 | |
234 | return $this->getRevision( UUID::create( $ids[$next] ) ); |
235 | } |
236 | |
237 | /** |
238 | * Returns the Title object this revision is associated with. |
239 | * |
240 | * @return Title |
241 | */ |
242 | public function getTitle() { |
243 | return $this->getWorkflow()->getArticleTitle(); |
244 | } |
245 | |
246 | /** |
247 | * Returns the workflow object this collection is associated with. |
248 | * |
249 | * @return Workflow |
250 | * @throws InvalidDataException |
251 | */ |
252 | public function getWorkflow() { |
253 | if ( !$this->workflow ) { |
254 | $uuid = $this->getWorkflowId(); |
255 | |
256 | $this->workflow = self::getStorage( Workflow::class )->get( $uuid ); |
257 | if ( !$this->workflow ) { |
258 | throw new InvalidDataException( 'Invalid workflow: ' . $uuid->getAlphadecimal(), 'invalid-workflow' ); |
259 | } |
260 | } |
261 | |
262 | return $this->workflow; |
263 | } |
264 | |
265 | public function getBoardWorkflow() { |
266 | return self::getStorage( Workflow::class )->get( $this->getBoardWorkflowId() ); |
267 | } |
268 | } |