Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
92.16% |
94 / 102 |
|
84.62% |
11 / 13 |
CRAP | |
0.00% |
0 / 1 |
ZType | |
92.16% |
94 / 102 |
|
84.62% |
11 / 13 |
34.56 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
1 | |||
getDefinition | |
100.00% |
38 / 38 |
|
100.00% |
1 / 1 |
1 | |||
isValid | |
74.07% |
20 / 27 |
|
0.00% |
0 / 1 |
17.42 | |||
getTypeId | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getTypeKeys | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getTypeValidator | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getEqualityFunction | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getRendererFunction | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getParserFunction | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getDeserialisers | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getSerialisers | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isEnumType | |
87.50% |
7 / 8 |
|
0.00% |
0 / 1 |
4.03 | |||
getZKey | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 |
1 | <?php |
2 | /** |
3 | * WikiLambda ZType |
4 | * |
5 | * @file |
6 | * @ingroup Extensions |
7 | * @copyright 2020– Abstract Wikipedia team; see AUTHORS.txt |
8 | * @license MIT |
9 | */ |
10 | |
11 | namespace MediaWiki\Extension\WikiLambda\ZObjects; |
12 | |
13 | use MediaWiki\Extension\WikiLambda\Registry\ZTypeRegistry; |
14 | |
15 | class ZType extends ZObject { |
16 | |
17 | /** |
18 | * Construct a ZType instance given the identity ZReference, a ZTypedList of ZKeys, |
19 | * and a ZReference to the type validator |
20 | * |
21 | * @param ZObject $identity |
22 | * @param ZObject $keys |
23 | * @param ZObject $validator |
24 | * @param ?ZObject $equality |
25 | * @param ?ZObject $renderer |
26 | * @param ?ZObject $parser |
27 | * @param ?ZTypedList $deserialisers |
28 | * @param ?ZTypedList $serialisers |
29 | */ |
30 | public function __construct( |
31 | $identity, $keys, $validator, |
32 | ?ZObject $equality = null, |
33 | ?ZObject $renderer = null, ?ZObject $parser = null, |
34 | ?ZTypedList $deserialisers = null, ?ZTypedList $serialisers = null |
35 | ) { |
36 | $this->data[ ZTypeRegistry::Z_TYPE_IDENTITY ] = $identity; |
37 | $this->data[ ZTypeRegistry::Z_TYPE_KEYS ] = $keys; |
38 | $this->data[ ZTypeRegistry::Z_TYPE_VALIDATOR ] = $validator; |
39 | $this->data[ ZTypeRegistry::Z_TYPE_EQUALITY ] = $equality ?? false; |
40 | $this->data[ ZTypeRegistry::Z_TYPE_RENDERER ] = $renderer ?? false; |
41 | $this->data[ ZTypeRegistry::Z_TYPE_PARSER ] = $parser ?? false; |
42 | $this->data[ ZTypeRegistry::Z_TYPE_DESERIALISERS ] = $deserialisers ?? |
43 | new ZTypedList( ZTypedList::buildType( new ZReference( ZTypeRegistry::Z_DESERIALISER ) ) ); |
44 | $this->data[ ZTypeRegistry::Z_TYPE_SERIALISERS ] = $serialisers ?? |
45 | new ZTypedList( ZTypedList::buildType( new ZReference( ZTypeRegistry::Z_SERIALISER ) ) ); |
46 | } |
47 | |
48 | /** |
49 | * @inheritDoc |
50 | */ |
51 | public static function getDefinition(): array { |
52 | return [ |
53 | 'type' => [ |
54 | 'type' => ZTypeRegistry::Z_REFERENCE, |
55 | 'value' => ZTypeRegistry::Z_TYPE, |
56 | ], |
57 | 'keys' => [ |
58 | ZTypeRegistry::Z_TYPE_IDENTITY => [ |
59 | // NOTE: Allows Z0. |
60 | 'type' => ZTypeRegistry::BUILTIN_REFERENCE_NULLABLE, |
61 | ], |
62 | ZTypeRegistry::Z_TYPE_KEYS => [ |
63 | // TODO (T362257): Walk the array of ZKeys. |
64 | 'type' => ZTypeRegistry::HACK_ARRAY_Z_KEY, |
65 | 'required' => true, |
66 | ], |
67 | ZTypeRegistry::Z_TYPE_VALIDATOR => [ |
68 | // NOTE: Allows Z0 until we support ZFunctions. |
69 | 'type' => ZTypeRegistry::BUILTIN_REFERENCE_NULLABLE, |
70 | ], |
71 | ZTypeRegistry::Z_TYPE_EQUALITY => [ |
72 | 'type' => ZTypeRegistry::Z_FUNCTION, |
73 | 'required' => false, |
74 | ], |
75 | ZTypeRegistry::Z_TYPE_RENDERER => [ |
76 | 'type' => ZTypeRegistry::Z_FUNCTION, |
77 | 'required' => false, |
78 | ], |
79 | ZTypeRegistry::Z_TYPE_PARSER => [ |
80 | 'type' => ZTypeRegistry::Z_FUNCTION, |
81 | 'required' => false, |
82 | ], |
83 | ZTypeRegistry::Z_TYPE_DESERIALISERS => [ |
84 | 'type' => ZTypeRegistry::Z_FUNCTION_TYPED_LIST, |
85 | 'required' => false, |
86 | ], |
87 | ZTypeRegistry::Z_TYPE_SERIALISERS => [ |
88 | 'type' => ZTypeRegistry::Z_FUNCTION_TYPED_LIST, |
89 | 'required' => false, |
90 | ], |
91 | ], |
92 | ]; |
93 | } |
94 | |
95 | /** |
96 | * @inheritDoc |
97 | */ |
98 | public function isValid(): bool { |
99 | // Identity must be set to a valid ZReference (or special case of 'Z0') |
100 | if ( !isset( $this->data[ ZTypeRegistry::Z_TYPE_IDENTITY ] ) ) { |
101 | return false; |
102 | } |
103 | if ( !( $this->data[ ZTypeRegistry::Z_TYPE_IDENTITY ] instanceof ZReference ) ) { |
104 | return false; |
105 | } |
106 | if ( !( $this->data[ ZTypeRegistry::Z_TYPE_IDENTITY ]->isValid() ) ) { |
107 | return false; |
108 | } |
109 | |
110 | // Key map must be set to an array or ZTypedList of zero or more ZKeys, all valid |
111 | if ( !isset( $this->data[ ZTypeRegistry::Z_TYPE_KEYS ] ) ) { |
112 | return false; |
113 | } |
114 | $keys = $this->data[ ZTypeRegistry::Z_TYPE_KEYS ]; |
115 | if ( !is_array( $keys ) ) { |
116 | if ( $keys instanceof ZTypedList ) { |
117 | if ( $keys->getElementType()->getZValue() !== ZTypeRegistry::Z_KEY ) { |
118 | return false; |
119 | } |
120 | $keys = $keys->getAsArray(); |
121 | } else { |
122 | return false; |
123 | } |
124 | } |
125 | foreach ( $keys as $key ) { |
126 | if ( !( $key instanceof ZKey ) ) { |
127 | return false; |
128 | } |
129 | if ( !$key->isValid() ) { |
130 | return false; |
131 | } |
132 | } |
133 | |
134 | // Validator must be set to a valid ZKey reference |
135 | if ( !isset( $this->data[ ZTypeRegistry::Z_TYPE_VALIDATOR ] ) ) { |
136 | return false; |
137 | } |
138 | if ( !( $this->data[ ZTypeRegistry::Z_TYPE_VALIDATOR ] instanceof ZReference ) ) { |
139 | return false; |
140 | } |
141 | if ( !( $this->data[ ZTypeRegistry::Z_TYPE_VALIDATOR ]->isValid() ) ) { |
142 | return false; |
143 | } |
144 | // TODO (T362242): Actually check that the validator is a ZFunction that applies to us. |
145 | |
146 | // TODO (T362243): Check the equality, renderer, parser, and type converter keys. |
147 | |
148 | return true; |
149 | } |
150 | |
151 | /** |
152 | * Get the representation of th ZType Zid |
153 | * |
154 | * @return ZReference|ZFunctionCall |
155 | */ |
156 | public function getTypeId() { |
157 | return $this->data[ ZTypeRegistry::Z_TYPE_IDENTITY ]; |
158 | } |
159 | |
160 | /** |
161 | * Get a list with the set of ZKeys for this ZType |
162 | * |
163 | * @return ZTypedList |
164 | */ |
165 | public function getTypeKeys() { |
166 | return $this->data[ ZTypeRegistry::Z_TYPE_KEYS ]; |
167 | } |
168 | |
169 | /** |
170 | * Get the string representation of the ZReference to this ZType's validator function |
171 | * |
172 | * @return string |
173 | */ |
174 | public function getTypeValidator() { |
175 | return $this->data[ ZTypeRegistry::Z_TYPE_VALIDATOR ]->getZValue(); |
176 | } |
177 | |
178 | /** |
179 | * Get the string representation of the ZReference to this ZType's equality function, |
180 | * or false if there is none. |
181 | * |
182 | * @return string|false |
183 | */ |
184 | public function getEqualityFunction() { |
185 | return $this->data[ ZTypeRegistry::Z_TYPE_EQUALITY ] ? |
186 | $this->data[ ZTypeRegistry::Z_TYPE_EQUALITY ]->getZValue() : |
187 | false; |
188 | } |
189 | |
190 | /** |
191 | * Get the string representation of the ZReference to this ZType's rendering function, |
192 | * or false if there is none. |
193 | * |
194 | * @return string|false |
195 | */ |
196 | public function getRendererFunction() { |
197 | return $this->data[ ZTypeRegistry::Z_TYPE_RENDERER ] ? |
198 | $this->data[ ZTypeRegistry::Z_TYPE_RENDERER ]->getZValue() : |
199 | false; |
200 | } |
201 | |
202 | /** |
203 | * Get the string representation of the ZReference to this ZType's parsing function, |
204 | * or false if there is none. |
205 | * |
206 | * @return string|false |
207 | */ |
208 | public function getParserFunction() { |
209 | return $this->data[ ZTypeRegistry::Z_TYPE_PARSER ] ? |
210 | $this->data[ ZTypeRegistry::Z_TYPE_PARSER ]->getZValue() : |
211 | false; |
212 | } |
213 | |
214 | /** |
215 | * Get the ZList of this ZType's deserialisers |
216 | * |
217 | * @return ZTypedList |
218 | */ |
219 | public function getDeserialisers() { |
220 | return $this->data[ ZTypeRegistry::Z_TYPE_DESERIALISERS ]; |
221 | } |
222 | |
223 | /** |
224 | * Get the ZList of this ZType's serialisers |
225 | * |
226 | * @return ZTypedList |
227 | */ |
228 | public function getSerialisers() { |
229 | return $this->data[ ZTypeRegistry::Z_TYPE_SERIALISERS ]; |
230 | } |
231 | |
232 | /** |
233 | * Return whether the type has an identity key but is not |
234 | * one of the non-enum reserved types with identity key: |
235 | * * Type/Z4 |
236 | * * Function/Z8 |
237 | * * Deserialiser/Z46 |
238 | * * Serialiser/Z64 |
239 | * |
240 | * @return bool |
241 | */ |
242 | public function isEnumType() { |
243 | $typeId = $this->getTypeId()->getZValue(); |
244 | |
245 | if ( in_array( $typeId, ZTypeRegistry::EXCLUDE_TYPES_FROM_ENUMS ) ) { |
246 | // Type has identity key but excluded from enum; return false |
247 | return false; |
248 | } |
249 | |
250 | $keys = $this->getTypeKeys()->getAsArray(); |
251 | foreach ( $keys as $key ) { |
252 | if ( $key->getIsIdentity() ) { |
253 | return true; |
254 | } |
255 | } |
256 | return false; |
257 | } |
258 | |
259 | /** |
260 | * Get the ZKey of a given key reference from the set of ZKeys of this ZType or |
261 | * null if the ZKey is not available. |
262 | * |
263 | * @param string $key |
264 | * @return ZKey|null |
265 | */ |
266 | public function getZKey( $key ) { |
267 | $keys = $this->getTypeKeys()->getAsArray(); |
268 | foreach ( $keys as $zkey ) { |
269 | if ( $zkey->getKeyId() === $key ) { |
270 | return $zkey; |
271 | } |
272 | } |
273 | return null; |
274 | } |
275 | } |