Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
80.65% |
25 / 31 |
|
71.43% |
5 / 7 |
CRAP | |
0.00% |
0 / 1 |
ZErrorTypeRegistry | |
80.65% |
25 / 31 |
|
71.43% |
5 / 7 |
16.63 | |
0.00% |
0 / 1 |
initialize | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isZErrorTypeKnown | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
4 | |||
fetchZErrorType | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
instanceOfZErrorType | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
isZErrorTypeCached | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isBuiltinZErrorType | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getZErrorTypeLabel | |
62.50% |
5 / 8 |
|
0.00% |
0 / 1 |
3.47 |
1 | <?php |
2 | /** |
3 | * WikiLambda ZErrorTypeRegistry |
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\Registry; |
12 | |
13 | use MediaWiki\Extension\WikiLambda\WikiLambdaServices; |
14 | use MediaWiki\Extension\WikiLambda\ZErrorException; |
15 | use MediaWiki\Extension\WikiLambda\ZObjectContent; |
16 | use MediaWiki\Title\Title; |
17 | |
18 | /** |
19 | * A registry service for ZErrorType |
20 | */ |
21 | class ZErrorTypeRegistry extends ZObjectRegistry { |
22 | |
23 | // TODO (T300512): Bring all constants (error types ZIDs) to schemata |
24 | public const Z_ERROR_UNKNOWN = 'Z500'; |
25 | public const Z_ERROR_INVALID_SYNTAX = 'Z501'; |
26 | public const Z_ERROR_NOT_WELLFORMED = 'Z502'; |
27 | public const Z_ERROR_ZID_NOT_FOUND = 'Z504'; |
28 | public const Z_ERROR_ARGUMENT_TYPE_MISMATCH = 'Z506'; |
29 | public const Z_ERROR_EVALUATION = 'Z507'; |
30 | public const Z_ERROR_LIST = 'Z509'; |
31 | public const Z_ERROR_MISSING_KEY = 'Z511'; |
32 | public const Z_ERROR_MISSING_PERSISTENT_VALUE = 'Z513'; |
33 | public const Z_ERROR_UNDEFINED_LIST_TYPE = 'Z519'; |
34 | public const Z_ERROR_WRONG_LIST_TYPE = 'Z520'; |
35 | public const Z_ERROR_NOT_NUMBER_BOOLEAN_NULL = 'Z521'; |
36 | public const Z_ERROR_ARRAY_ELEMENT_NOT_WELLFORMED = 'Z522'; |
37 | public const Z_ERROR_MISSING_TYPE = 'Z523'; |
38 | public const Z_ERROR_TYPE_NOT_STRING_ARRAY = 'Z524'; |
39 | public const Z_ERROR_INVALID_KEY = 'Z525'; |
40 | public const Z_ERROR_KEY_VALUE_NOT_WELLFORMED = 'Z526'; |
41 | public const Z_ERROR_STRING_VALUE_MISSING = 'Z532'; |
42 | public const Z_ERROR_STRING_VALUE_WRONG_TYPE = 'Z533'; |
43 | public const Z_ERROR_REFERENCE_VALUE_MISSING = 'Z535'; |
44 | public const Z_ERROR_REFERENCE_VALUE_WRONG_TYPE = 'Z536'; |
45 | public const Z_ERROR_REFERENCE_VALUE_INVALID = 'Z537'; |
46 | public const Z_ERROR_WRONG_NAMESPACE = 'Z538'; |
47 | public const Z_ERROR_WRONG_CONTENT_TYPE = 'Z539'; |
48 | public const Z_ERROR_INVALID_LANG_CODE = 'Z540'; |
49 | public const Z_ERROR_LANG_NOT_FOUND = 'Z541'; |
50 | public const Z_ERROR_UNEXPECTED_ZTYPE = 'Z542'; |
51 | public const Z_ERROR_ZTYPE_NOT_FOUND = 'Z543'; |
52 | public const Z_ERROR_CONFLICTING_TYPE_NAMES = 'Z544'; |
53 | public const Z_ERROR_CONFLICTING_TYPE_ZIDS = 'Z545'; |
54 | public const Z_ERROR_BUILTIN_TYPE_NOT_FOUND = 'Z546'; |
55 | public const Z_ERROR_INVALID_FORMAT = 'Z547'; |
56 | public const Z_ERROR_INVALID_JSON = 'Z548'; |
57 | public const Z_ERROR_INVALID_REFERENCE = 'Z549'; |
58 | public const Z_ERROR_UNKNOWN_REFERENCE = 'Z550'; |
59 | public const Z_ERROR_SCHEMA_TYPE_MISMATCH = 'Z551'; |
60 | public const Z_ERROR_ARRAY_TYPE_MISMATCH = 'Z552'; |
61 | public const Z_ERROR_DISALLOWED_ROOT_ZOBJECT = 'Z553'; |
62 | public const Z_ERROR_LABEL_CLASH = 'Z554'; |
63 | public const Z_ERROR_UNMATCHING_ZID = 'Z555'; |
64 | public const Z_ERROR_INVALID_TITLE = 'Z556'; |
65 | public const Z_ERROR_USER_CANNOT_EDIT = 'Z557'; |
66 | public const Z_ERROR_USER_CANNOT_RUN = 'Z559'; |
67 | public const Z_ERROR_ORCHESTRATOR_RATE_LIMIT = 'Z570'; |
68 | public const Z_ERROR_EVALUATOR_RATE_LIMIT = 'Z571'; |
69 | |
70 | private const BUILT_IN_ERRORS = [ |
71 | 'Z500' => 'Z_ERROR_UNKNOWN', |
72 | 'Z501' => 'Z_ERROR_INVALID_SYNTAX', |
73 | 'Z502' => 'Z_ERROR_NOT_WELLFORMED', |
74 | 'Z504' => 'Z_ERROR_ZID_NOT_FOUND', |
75 | 'Z506' => 'Z_ERROR_ARGUMENT_TYPE_MISMATCH', |
76 | 'Z507' => 'Z_ERROR_EVALUATION', |
77 | 'Z509' => 'Z_ERROR_LIST', |
78 | 'Z511' => 'Z_ERROR_MISSING_KEY', |
79 | 'Z513' => 'Z_ERROR_MISSING_PERSISTENT_VALUE', |
80 | 'Z519' => 'Z_ERROR_UNDEFINED_LIST_TYPE', |
81 | 'Z521' => 'Z_ERROR_NOT_NUMBER_BOOLEAN_NULL', |
82 | 'Z522' => 'Z_ERROR_ARRAY_ELEMENT_NOT_WELLFORMED', |
83 | 'Z523' => 'Z_ERROR_MISSING_TYPE', |
84 | 'Z524' => 'Z_ERROR_TYPE_NOT_STRING_ARRAY', |
85 | 'Z525' => 'Z_ERROR_INVALID_KEY', |
86 | 'Z526' => 'Z_ERROR_KEY_VALUE_NOT_WELLFORMED', |
87 | 'Z532' => 'Z_ERROR_STRING_VALUE_MISSING', |
88 | 'Z533' => 'Z_ERROR_STRING_VALUE_WRONG_TYPE', |
89 | 'Z535' => 'Z_ERROR_REFERENCE_VALUE_MISSING', |
90 | 'Z536' => 'Z_ERROR_REFERENCE_VALUE_WRONG_TYPE', |
91 | 'Z537' => 'Z_ERROR_REFERENCE_VALUE_INVALID', |
92 | 'Z538' => 'Z_ERROR_WRONG_NAMESPACE', |
93 | 'Z539' => 'Z_ERROR_WRONG_CONTENT_TYPE', |
94 | 'Z540' => 'Z_ERROR_INVALID_LANG_CODE', |
95 | 'Z541' => 'Z_ERROR_LANG_NOT_FOUND', |
96 | 'Z542' => 'Z_ERROR_UNEXPECTED_ZTYPE', |
97 | 'Z543' => 'Z_ERROR_ZTYPE_NOT_FOUND', |
98 | 'Z544' => 'Z_ERROR_CONFLICTING_TYPE_NAMES', |
99 | 'Z545' => 'Z_ERROR_CONFLICTING_TYPE_ZIDS', |
100 | 'Z546' => 'Z_ERROR_BUILTIN_TYPE_NOT_FOUND', |
101 | 'Z547' => 'Z_ERROR_INVALID_FORMAT', |
102 | 'Z548' => 'Z_ERROR_INVALID_JSON', |
103 | 'Z549' => 'Z_ERROR_INVALID_REFERENCE', |
104 | 'Z550' => 'Z_ERROR_UNKNOWN_REFERENCE', |
105 | 'Z551' => 'Z_ERROR_SCHEMA_TYPE_MISMATCH', |
106 | 'Z552' => 'Z_ERROR_ARRAY_TYPE_MISMATCH', |
107 | 'Z553' => 'Z_ERROR_DISALLOWED_ROOT_ZOBJECT', |
108 | 'Z554' => 'Z_ERROR_LABEL_CLASH', |
109 | 'Z555' => 'Z_ERROR_UNMATCHING_ZID', |
110 | 'Z556' => 'Z_ERROR_INVALID_TITLE', |
111 | 'Z557' => 'Z_ERROR_USER_CANNOT_EDIT', |
112 | 'Z559' => 'Z_ERROR_USER_CANNOT_RUN', |
113 | 'Z570' => 'Z_ERROR_ORCHESTRATOR_RATE_LIMIT', |
114 | 'Z571' => 'Z_ERROR_EVALUATOR_RATE_LIMIT', |
115 | ]; |
116 | |
117 | /** |
118 | * Initialize ZErrorTypeRegistry |
119 | */ |
120 | protected function initialize(): void { |
121 | // Registry for ZObjects of type ZErrorType/Z500 |
122 | $this->type = ZTypeRegistry::Z_ERRORTYPE; |
123 | } |
124 | |
125 | /** |
126 | * Check if the given ZErrorType Zid is known |
127 | * |
128 | * @param string $errorType |
129 | * @return bool |
130 | */ |
131 | public function isZErrorTypeKnown( string $errorType ): bool { |
132 | if ( $this->isZErrorTypeCached( $errorType ) ) { |
133 | return true; |
134 | } |
135 | |
136 | if ( $this->isBuiltinZErrorType( $errorType ) ) { |
137 | return true; |
138 | } |
139 | |
140 | $zObject = $this->fetchZErrorType( $errorType ); |
141 | if ( $zObject === false ) { |
142 | return false; |
143 | } |
144 | |
145 | $this->register( $errorType, $zObject->getLabels()->getStringForLanguageCode( 'en' ) ); |
146 | return true; |
147 | } |
148 | |
149 | /** |
150 | * Fetches a given error type Zid from the database, throwing error if the ZErrorType does not |
151 | * exist or if the fetched object is not of the wanted type |
152 | * |
153 | * @param string $errorType |
154 | * @return ZObjectContent|bool Found ZObject |
155 | * @throws ZErrorException |
156 | */ |
157 | private function fetchZErrorType( string $errorType ) { |
158 | // TODO (T338253): This is quite expensive. Store this in a metadata DB table, instead of fetching it live? |
159 | $title = Title::newFromText( $errorType, NS_MAIN ); |
160 | $zObjectStore = WikiLambdaServices::getZObjectStore(); |
161 | $zObject = $zObjectStore->fetchZObjectByTitle( $title ); |
162 | |
163 | if ( $zObject === false ) { |
164 | return false; |
165 | // throw new ZErrorException( |
166 | // ZErrorFactory::createZErrorInstance( |
167 | // self::Z_ERROR_ZID_NOT_FOUND, |
168 | // [ "data" => $errorType ] |
169 | // ) |
170 | // ); |
171 | } |
172 | |
173 | if ( $zObject->getZType() !== ZTypeRegistry::Z_ERRORTYPE ) { |
174 | return false; |
175 | // throw new ZErrorException( |
176 | // ZErrorFactory::createZErrorInstance( |
177 | // self::Z_ERROR_UNEXPECTED_ZTYPE, |
178 | // [ |
179 | // "expected" => ZTypeRegistry::Z_ERRORTYPE, |
180 | // "used" => $errorType |
181 | // ] |
182 | // ) |
183 | // ); |
184 | } |
185 | |
186 | return $zObject; |
187 | } |
188 | |
189 | /** |
190 | * Check if the given Zid belongs to a ZErrorType |
191 | * |
192 | * @param string $zid |
193 | * @return bool |
194 | */ |
195 | public function instanceOfZErrorType( string $zid ): bool { |
196 | try { |
197 | return $this->isZErrorTypeKnown( $zid ); |
198 | } catch ( ZErrorException $e ) { |
199 | return false; |
200 | } |
201 | } |
202 | |
203 | /** |
204 | * Check if the given Zid is an already cached ZErrorType (Z50) |
205 | * |
206 | * @param string $errorType |
207 | * @return bool |
208 | */ |
209 | public function isZErrorTypeCached( string $errorType ): bool { |
210 | return array_key_exists( $errorType, $this->registry ); |
211 | } |
212 | |
213 | /** |
214 | * Check if the given Zid belongs to a builtin ZErrorType |
215 | * |
216 | * @param string $errorType |
217 | * @return bool |
218 | */ |
219 | private function isBuiltinZErrorType( string $errorType ): bool { |
220 | return array_key_exists( $errorType, self::BUILT_IN_ERRORS ); |
221 | } |
222 | |
223 | /** |
224 | * Gets the ZErrorType label in English |
225 | * |
226 | * @param string $errorType |
227 | * @return string |
228 | * @throws ZErrorException |
229 | */ |
230 | public function getZErrorTypeLabel( string $errorType ): string { |
231 | if ( $this->isZErrorTypeCached( $errorType ) ) { |
232 | return $this->registry[ $errorType ]; |
233 | } |
234 | |
235 | $zObject = $this->fetchZErrorType( $errorType ); |
236 | if ( $zObject === false ) { |
237 | return "Unknown error $errorType"; |
238 | } |
239 | |
240 | // TODO (T362236): Take the rendering language as a parameter, don't default to English |
241 | $errorLabel = $zObject->getLabels()->getStringForLanguageCode( 'en' ); |
242 | $this->register( $errorType, $errorLabel ); |
243 | |
244 | return $errorLabel; |
245 | } |
246 | } |