1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of the Cubiche package. |
5
|
|
|
* |
6
|
|
|
* Copyright (c) Cubiche |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
namespace Cubiche\Core\Collections\Tests\Asserters; |
12
|
|
|
|
13
|
|
|
use Cubiche\Core\Collections\CollectionInterface; |
14
|
|
|
use Cubiche\Core\Comparable\Comparator; |
15
|
|
|
use Cubiche\Core\Comparable\ComparatorInterface; |
16
|
|
|
use Cubiche\Core\Specification\Criteria; |
17
|
|
|
use Cubiche\Core\Specification\SpecificationInterface; |
18
|
|
|
use mageekguy\atoum\asserters\object as ObjectAsserter; |
19
|
|
|
use mageekguy\atoum\exceptions\logic as LogicException; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* CollectionAsserter class. |
23
|
|
|
* |
24
|
|
|
* @author Ivannis Suárez Jerez <[email protected]> |
25
|
|
|
*/ |
26
|
|
|
class CollectionAsserter extends ObjectAsserter |
27
|
|
|
{ |
28
|
|
|
/** |
29
|
|
|
* @var bool |
30
|
|
|
*/ |
31
|
|
|
protected $assertAll; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* {@inheritdoc} |
35
|
|
|
*/ |
36
|
|
|
public function __get($asserter) |
37
|
|
|
{ |
38
|
|
|
switch (strtolower($asserter)) { |
39
|
|
|
case 'size': |
40
|
|
|
return $this->size(); |
41
|
|
|
case 'isempty': |
42
|
|
|
return $this->isEmpty(); |
43
|
|
|
case 'isnotempty': |
44
|
|
|
return $this->isNotEmpty(); |
45
|
|
|
case 'hasallelements': |
46
|
|
|
return $this->hasAllElements(); |
47
|
|
|
case 'hasnoelements': |
48
|
|
|
return $this->hasNoElements(); |
49
|
|
|
case 'issorted': |
50
|
|
|
return $this->isSorted(); |
51
|
|
|
case 'isnotsorted': |
52
|
|
|
return $this->isNotSorted(); |
53
|
|
|
default: |
54
|
|
|
return parent::__get($asserter); |
55
|
|
|
} |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @return \mageekguy\atoum\stubs\asserters\integer |
60
|
|
|
*/ |
61
|
|
|
public function size() |
62
|
|
|
{ |
63
|
|
|
return $this->generator->__call( |
64
|
|
|
'integer', |
65
|
|
|
array($this->valueAsCollection()->count()) |
66
|
|
|
); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @param string $failMessage |
71
|
|
|
* |
72
|
|
|
* @return $this |
73
|
|
|
*/ |
74
|
|
View Code Duplication |
public function isEmpty($failMessage = null) |
|
|
|
|
75
|
|
|
{ |
76
|
|
|
if (($actual = $this->valueAsCollection()->count()) === 0) { |
77
|
|
|
$this->pass(); |
78
|
|
|
} else { |
79
|
|
|
$this->fail($failMessage ?: $this->getLocale()->_('%s is not empty', $this, $actual)); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
return $this; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* @param string $failMessage |
87
|
|
|
* |
88
|
|
|
* @return $this |
89
|
|
|
*/ |
90
|
|
View Code Duplication |
public function isNotEmpty($failMessage = null) |
|
|
|
|
91
|
|
|
{ |
92
|
|
|
if ($this->valueAsCollection()->count() > 0) { |
93
|
|
|
$this->pass(); |
94
|
|
|
} else { |
95
|
|
|
$this->fail($failMessage ?: $this->_('%s is empty', $this)); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
return $this; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* @return $this |
103
|
|
|
*/ |
104
|
|
|
public function hasAllElements() |
105
|
|
|
{ |
106
|
|
|
$this->assertAll = true; |
107
|
|
|
|
108
|
|
|
return $this; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* @return $this |
113
|
|
|
*/ |
114
|
|
|
public function hasNoElements() |
115
|
|
|
{ |
116
|
|
|
$this->assertAll = false; |
117
|
|
|
|
118
|
|
|
return $this; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* {@inheritdoc} |
123
|
|
|
*/ |
124
|
|
View Code Duplication |
public function setWith($value, $checkType = true) |
|
|
|
|
125
|
|
|
{ |
126
|
|
|
parent::setWith($value, $checkType); |
127
|
|
|
|
128
|
|
|
if ($checkType === true) { |
129
|
|
|
if ($this->value instanceof CollectionInterface) { |
130
|
|
|
$this->pass(); |
131
|
|
|
} else { |
132
|
|
|
$this->fail($this->getLocale()->_('%s is not a collection', $this)); |
133
|
|
|
} |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
return $this; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* @param SpecificationInterface $criteria |
141
|
|
|
* |
142
|
|
|
* @return $this |
143
|
|
|
*/ |
144
|
|
|
public function thatMatchToCriteria(SpecificationInterface $criteria) |
145
|
|
|
{ |
146
|
|
|
$collection = $this->valueAsCollection(); |
147
|
|
|
foreach ($collection as $item) { |
148
|
|
|
if (!$this->checkMatchResult($criteria->evaluate($item))) { |
149
|
|
|
return $this; |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
$this->pass(); |
154
|
|
|
return $this; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* @param bool $result |
159
|
|
|
* @return bool |
160
|
|
|
*/ |
161
|
|
|
private function checkMatchResult($result) |
162
|
|
|
{ |
163
|
|
View Code Duplication |
if($result === true && $this->assertAll === false) { |
|
|
|
|
164
|
|
|
$this->fail($this->_('At least one items that match with the given criteria')); |
165
|
|
|
return false; |
166
|
|
|
} |
167
|
|
View Code Duplication |
if($result === false && $this->assertAll === true) { |
|
|
|
|
168
|
|
|
$this->fail($this->_('At least one items that not match with the given criteria')); |
169
|
|
|
return false; |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
return true; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* @return $this |
178
|
|
|
*/ |
179
|
|
|
public function isSorted() |
180
|
|
|
{ |
181
|
|
|
return $this->isSortedUsing(new Comparator()); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* @param ComparatorInterface $comparator |
186
|
|
|
* |
187
|
|
|
* @return $this |
188
|
|
|
*/ |
189
|
|
View Code Duplication |
public function isSortedUsing(ComparatorInterface $comparator) |
|
|
|
|
190
|
|
|
{ |
191
|
|
|
list($item1, $item2) = $this->checkIsSorted($comparator); |
192
|
|
|
if($item1 !== null && $item2 !== null) { |
193
|
|
|
$this->fail( |
194
|
|
|
$this->_("There are items [%s, %s] that aren't ordered in the given collection", $item1, $item2) |
195
|
|
|
); |
196
|
|
|
} else { |
197
|
|
|
$this->pass(); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
return $this; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
/** |
204
|
|
|
* @return $this |
205
|
|
|
*/ |
206
|
|
|
public function isNotSorted() |
207
|
|
|
{ |
208
|
|
|
return $this->isNotSortedUsing(new Comparator()); |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* @param ComparatorInterface $comparator |
213
|
|
|
* |
214
|
|
|
* @return $this |
215
|
|
|
*/ |
216
|
|
View Code Duplication |
public function isNotSortedUsing(ComparatorInterface $comparator) |
|
|
|
|
217
|
|
|
{ |
218
|
|
|
list($item1, $item2) = $this->checkIsSorted($comparator); |
219
|
|
|
if($item1 !== null && $item2 !== null) { |
220
|
|
|
$this->fail($this->_('The given collection is sorted')); |
221
|
|
|
} else { |
222
|
|
|
$this->pass(); |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
return $this; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* @param ComparatorInterface $comparator |
230
|
|
|
* @return array |
231
|
|
|
*/ |
232
|
|
|
private function checkIsSorted(ComparatorInterface $comparator) |
233
|
|
|
{ |
234
|
|
|
$collection = $this->valueAsCollection(); |
235
|
|
|
$last = null; |
236
|
|
|
foreach ($collection as $item) { |
237
|
|
|
if ($last !== null && $comparator->compare($last, $item) > 0) { |
238
|
|
|
return array($last, $item); |
239
|
|
|
} |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
return array(null, null); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* @param mixed $value |
247
|
|
|
* |
248
|
|
|
* @return mixed |
249
|
|
|
*/ |
250
|
|
View Code Duplication |
public function contains($value) |
|
|
|
|
251
|
|
|
{ |
252
|
|
|
$collection = $this->valueAsCollection(); |
253
|
|
|
if ($collection->findOne(Criteria::eq($value)) !== null) { |
254
|
|
|
$this->pass(); |
255
|
|
|
} else { |
256
|
|
|
$this->fail($this->getLocale()->_('The collection not contain the value %s', $value)); |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
return $this; |
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
/** |
263
|
|
|
* @param array|\Traversable $values |
264
|
|
|
* |
265
|
|
|
* @return mixed |
266
|
|
|
*/ |
267
|
|
|
public function containsValues($values) |
268
|
|
|
{ |
269
|
|
|
foreach ($values as $value) { |
270
|
|
|
$this->contains($value); |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
return $this; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* @param mixed $value |
278
|
|
|
* |
279
|
|
|
* @return mixed |
280
|
|
|
*/ |
281
|
|
View Code Duplication |
public function notContains($value) |
|
|
|
|
282
|
|
|
{ |
283
|
|
|
$collection = $this->valueAsCollection(); |
284
|
|
|
if ($collection->findOne(Criteria::eq($value)) !== null) { |
285
|
|
|
$this->fail($this->getLocale()->_('The collection contain an element with this value %s', $value)); |
286
|
|
|
} else { |
287
|
|
|
$this->pass(); |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
return $this; |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* {@inheritdoc} |
295
|
|
|
*/ |
296
|
|
|
protected function valueIsSet($message = 'Collection is undefined') |
297
|
|
|
{ |
298
|
|
|
return parent::valueIsSet($message); |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
/** |
302
|
|
|
* @throws LogicException |
303
|
|
|
* |
304
|
|
|
* @return \Cubiche\Core\Collections\CollectionInterface |
305
|
|
|
*/ |
306
|
|
|
protected function valueAsCollection() |
307
|
|
|
{ |
308
|
|
|
$value = $this->valueIsSet()->getValue(); |
309
|
|
|
if ($value instanceof CollectionInterface) { |
310
|
|
|
return $value; |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
throw new LogicException('Collection is undefined'); |
314
|
|
|
} |
315
|
|
|
} |
316
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.