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