Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
94.00% |
47 / 50 |
|
81.25% |
13 / 16 |
CRAP | |
0.00% |
0 / 1 |
SenseSet | |
94.00% |
47 / 50 |
|
81.25% |
13 / 16 |
28.17 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
toArray | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
toArrayUnordered | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
sortSenses | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
count | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
maxSenseIdNumber | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
add | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
2 | |||
remove | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
put | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getById | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
copy | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__clone | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
isEmpty | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
equals | |
80.00% |
4 / 5 |
|
0.00% |
0 / 1 |
3.07 | |||
hasSenseWithId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
sameSenses | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
4.07 |
1 | <?php |
2 | |
3 | namespace Wikibase\Lexeme\Domain\Model; |
4 | |
5 | use Countable; |
6 | use InvalidArgumentException; |
7 | use Wikibase\Lexeme\Domain\Model\Exceptions\ConflictException; |
8 | |
9 | /** |
10 | * Set of Senses in which uniqueness of a Sense is controlled by its ID. |
11 | * Supposed to be used only inside the Lexeme class. |
12 | * |
13 | * @license GPL-2.0-or-later |
14 | */ |
15 | class SenseSet implements Countable { |
16 | |
17 | /** |
18 | * @var Sense[] indexed by serialization of SenseId |
19 | */ |
20 | private $senses = []; |
21 | |
22 | /** |
23 | * @param Sense[] $senses |
24 | */ |
25 | public function __construct( array $senses = [] ) { |
26 | foreach ( $senses as $sense ) { |
27 | if ( !$sense instanceof Sense ) { |
28 | throw new InvalidArgumentException( '$senses must be an array of Senses' ); |
29 | } |
30 | |
31 | $this->add( $sense ); |
32 | } |
33 | } |
34 | |
35 | /** |
36 | * @return Sense[] |
37 | */ |
38 | public function toArray() { |
39 | $senses = $this->sortSenses( $this->senses ); |
40 | return array_values( $senses ); |
41 | } |
42 | |
43 | /** |
44 | * Return the individual Senses in arbitrary order. |
45 | * |
46 | * Only use this method if the order is certainly insignificant, |
47 | * e.g. because the Senses will be summarized or reduced in some way. |
48 | * Otherwise, use {@link toArray()}. |
49 | * |
50 | * @return Sense[] |
51 | */ |
52 | public function toArrayUnordered(): array { |
53 | return array_values( $this->senses ); |
54 | } |
55 | |
56 | /** |
57 | * @param Sense[] $senses |
58 | * @return array sorted array mapping numeric id to the sense |
59 | */ |
60 | private function sortSenses( array $senses ) { |
61 | $sortedSenses = []; |
62 | foreach ( $senses as $sense ) { |
63 | $senseIdPart = explode( '-', $sense->getId()->getSerialization(), 2 )[1]; |
64 | $senseIdNumber = (int)substr( $senseIdPart, 1 ); |
65 | $sortedSenses[$senseIdNumber] = $sense; |
66 | } |
67 | ksort( $sortedSenses ); |
68 | |
69 | return $sortedSenses; |
70 | } |
71 | |
72 | /** |
73 | * @return int |
74 | */ |
75 | public function count(): int { |
76 | return count( $this->senses ); |
77 | } |
78 | |
79 | /** |
80 | * @return int |
81 | */ |
82 | public function maxSenseIdNumber() { |
83 | $max = 0; |
84 | |
85 | foreach ( $this->senses as $senseId => $sense ) { |
86 | $senseIdPart = explode( '-', $senseId, 2 )[1]; |
87 | $senseIdNumber = (int)substr( $senseIdPart, 1 ); |
88 | if ( $senseIdNumber > $max ) { |
89 | $max = $senseIdNumber; |
90 | } |
91 | } |
92 | |
93 | return $max; |
94 | } |
95 | |
96 | public function add( Sense $sense ) { |
97 | $senseId = $sense->getId()->getSerialization(); |
98 | if ( array_key_exists( $senseId, $this->senses ) ) { |
99 | throw new ConflictException( |
100 | 'At least two senses with the same ID were provided: `' . $senseId . '`' |
101 | ); |
102 | } |
103 | |
104 | $this->senses[$senseId] = $sense; |
105 | } |
106 | |
107 | public function remove( SenseId $senseId ) { |
108 | unset( $this->senses[$senseId->getSerialization()] ); |
109 | } |
110 | |
111 | /** |
112 | * Replace the sense identified by $sense->getId() with the given one or add it. |
113 | * |
114 | * @param Sense $sense |
115 | */ |
116 | public function put( Sense $sense ) { |
117 | $this->remove( $sense->getId() ); |
118 | $this->add( $sense ); |
119 | } |
120 | |
121 | /** |
122 | * @param SenseId $senseId |
123 | * |
124 | * @return Sense|null |
125 | */ |
126 | public function getById( SenseId $senseId ) { |
127 | return $this->senses[$senseId->getSerialization()] ?? null; |
128 | } |
129 | |
130 | /** |
131 | * @return self |
132 | */ |
133 | public function copy() { |
134 | return clone $this; |
135 | } |
136 | |
137 | /** |
138 | * @see http://php.net/manual/en/language.oop5.cloning.php |
139 | */ |
140 | public function __clone() { |
141 | $clonedSenses = []; |
142 | foreach ( $this->senses as $key => $sense ) { |
143 | $clonedSenses[$key] = clone $sense; |
144 | } |
145 | $this->senses = $clonedSenses; |
146 | } |
147 | |
148 | /** |
149 | * @return bool |
150 | */ |
151 | public function isEmpty() { |
152 | return $this->senses === []; |
153 | } |
154 | |
155 | public function equals( $other ) { |
156 | if ( $this === $other ) { |
157 | return true; |
158 | } |
159 | |
160 | if ( !( $other instanceof self ) ) { |
161 | return false; |
162 | } |
163 | |
164 | return $this->sameSenses( $other ); |
165 | } |
166 | |
167 | public function hasSenseWithId( SenseId $id ): bool { |
168 | return $this->getById( $id ) !== null; |
169 | } |
170 | |
171 | /** |
172 | * @return bool |
173 | */ |
174 | private function sameSenses( SenseSet $other ) { |
175 | if ( $this->count() !== $other->count() ) { |
176 | return false; |
177 | } |
178 | |
179 | foreach ( $this->senses as $sense ) { |
180 | if ( !$sense->equals( $other->getById( $sense->getId() ) ) ) { |
181 | return false; |
182 | } |
183 | } |
184 | |
185 | return true; |
186 | } |
187 | |
188 | } |