Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
92.59% |
75 / 81 |
|
75.00% |
6 / 8 |
CRAP | |
0.00% |
0 / 1 |
ZError | |
92.59% |
75 / 81 |
|
75.00% |
6 / 8 |
26.27 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getDefinition | |
100.00% |
16 / 16 |
|
100.00% |
1 / 1 |
1 | |||
isValid | |
78.57% |
11 / 14 |
|
0.00% |
0 / 1 |
7.48 | |||
getZValue | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getZErrorType | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getMessage | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getHtmlMessage | |
92.50% |
37 / 40 |
|
0.00% |
0 / 1 |
13.07 | |||
getErrorData | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | /** |
3 | * WikiLambda ZError |
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\ZErrorTypeRegistry; |
14 | use MediaWiki\Extension\WikiLambda\Registry\ZTypeRegistry; |
15 | use MediaWiki\Extension\WikiLambda\ZObjectUtils; |
16 | use MediaWiki\Html\Html; |
17 | |
18 | class ZError extends ZObject { |
19 | |
20 | /** |
21 | * Construct a new ZError instance. |
22 | * |
23 | * @param ZReference $type ZErrorType Zid |
24 | * @param ZObject $value Value that describes the ZError |
25 | */ |
26 | public function __construct( $type, $value ) { |
27 | $this->data[ ZTypeRegistry::Z_ERROR_TYPE ] = $type; |
28 | $this->data[ ZTypeRegistry::Z_ERROR_VALUE ] = $value; |
29 | } |
30 | |
31 | /** |
32 | * @inheritDoc |
33 | */ |
34 | public static function getDefinition(): array { |
35 | return [ |
36 | 'type' => [ |
37 | 'type' => ZTypeRegistry::Z_REFERENCE, |
38 | 'value' => ZTypeRegistry::Z_ERROR, |
39 | ], |
40 | 'keys' => [ |
41 | ZTypeRegistry::Z_ERROR_TYPE => [ |
42 | 'type' => ZTypeRegistry::Z_ERRORTYPE, |
43 | 'required' => true, |
44 | ], |
45 | ZTypeRegistry::Z_ERROR_VALUE => [ |
46 | 'type' => ZTypeRegistry::Z_OBJECT_TYPE, |
47 | 'required' => true, |
48 | ], |
49 | ], |
50 | ]; |
51 | } |
52 | |
53 | /** |
54 | * @inheritDoc |
55 | */ |
56 | public function isValid(): bool { |
57 | // Type must be a valid Zid that references a ZObject of type Z50 |
58 | if ( !isset( $this->data[ ZTypeRegistry::Z_ERROR_TYPE ] ) ) { |
59 | return false; |
60 | } |
61 | if ( !( $this->data[ ZTypeRegistry::Z_ERROR_TYPE ] instanceof ZReference ) ) { |
62 | return false; |
63 | } |
64 | $errorType = $this->data[ ZTypeRegistry::Z_ERROR_TYPE ]->getZValue(); |
65 | if ( !ZObjectUtils::isValidZObjectReference( $errorType ) ) { |
66 | return false; |
67 | } |
68 | if ( !ZErrorTypeRegistry::singleton()->instanceOfZErrorType( $errorType ) ) { |
69 | return false; |
70 | } |
71 | // Value must be a valid ZObject |
72 | if ( !isset( $this->data[ ZTypeRegistry::Z_ERROR_VALUE ] ) ) { |
73 | return false; |
74 | } |
75 | if ( !( $this->data[ ZTypeRegistry::Z_ERROR_VALUE ] instanceof ZObject ) ) { |
76 | return false; |
77 | } |
78 | return $this->getZValue()->isValid(); |
79 | } |
80 | |
81 | /** |
82 | * Get the content of the ZError value. |
83 | * |
84 | * @return ZObject Value that describes this ZError |
85 | */ |
86 | public function getZValue(): ZObject { |
87 | return $this->data[ ZTypeRegistry::Z_ERROR_VALUE ]; |
88 | } |
89 | |
90 | /** |
91 | * Get the Zid that identifies the ZErrorType that describes this ZError |
92 | * |
93 | * @return string ZErrorType Zid |
94 | */ |
95 | public function getZErrorType(): string { |
96 | return $this->data[ ZTypeRegistry::Z_ERROR_TYPE ]->getZValue(); |
97 | } |
98 | |
99 | /** |
100 | * Get a human-readable one-line string that identifies the ZError information |
101 | * |
102 | * @return string ZError message |
103 | */ |
104 | public function getMessage(): string { |
105 | // TODO (T362236): Add the rendering language as a parameter, don't default to English |
106 | return ZErrorTypeRegistry::singleton()->getZErrorTypeLabel( $this->getZErrorType() ); |
107 | } |
108 | |
109 | /** |
110 | * Get a human-readable one-line string that identifies the ZError information |
111 | * |
112 | * @return string ZError message |
113 | */ |
114 | public function getHtmlMessage(): string { |
115 | // TODO (T362236): Add the rendering language as a parameter, don't default to English |
116 | $message = ZErrorTypeRegistry::singleton()->getZErrorTypeLabel( $this->getZErrorType() ); |
117 | $messages = []; |
118 | |
119 | $errorType = $this->getZErrorType(); |
120 | |
121 | // Errors that have message key: Z500, Z557 |
122 | // Get error message from K1 (if not null) |
123 | if ( |
124 | ( $errorType === ZErrorTypeRegistry::Z_ERROR_UNKNOWN ) || |
125 | ( $errorType === ZErrorTypeRegistry::Z_ERROR_USER_CANNOT_EDIT ) |
126 | ) { |
127 | $errorValue = $this->getZValue(); |
128 | $messageKey = $errorValue->getValueByKey( 'K1' ); |
129 | $message = $messageKey ? $messageKey->getZValue() : $message; |
130 | } |
131 | |
132 | // Errors that can have children: Z509, Z502, Z522, Z526 |
133 | // List of children in K1: |
134 | // * Z509/List of errors |
135 | if ( $errorType === ZErrorTypeRegistry::Z_ERROR_LIST ) { |
136 | $errorValue = $this->getZValue(); |
137 | $subErrors = $errorValue->getValueByKey( 'K1' ); |
138 | |
139 | if ( is_array( $subErrors ) || ( $subErrors instanceof ZTypedList ) ) { |
140 | foreach ( ZObjectUtils::getIterativeList( $subErrors ) as $subError ) { |
141 | $messages[] = Html::rawElement( |
142 | 'li', |
143 | [ 'class' => 'ext-wikilambda-app-suberror-list__item' ], |
144 | $subError->getHtmlMessage() |
145 | ); |
146 | } |
147 | } |
148 | } |
149 | |
150 | // Only child in K2: |
151 | // * Z502/Not wellformed |
152 | // * Z522/Array element not wellformed |
153 | if ( |
154 | ( $errorType === ZErrorTypeRegistry::Z_ERROR_NOT_WELLFORMED ) || |
155 | ( $errorType === ZErrorTypeRegistry::Z_ERROR_KEY_VALUE_NOT_WELLFORMED ) || |
156 | ( $errorType === ZErrorTypeRegistry::Z_ERROR_ARRAY_ELEMENT_NOT_WELLFORMED ) |
157 | ) { |
158 | $errorValue = $this->getZValue(); |
159 | $subError = $errorValue->getValueByKey( 'K2' ); |
160 | '@phan-var ZError $subError'; |
161 | $messages[] = Html::rawElement( |
162 | 'li', |
163 | [ 'class' => 'ext-wikilambda-app-suberror-list__item' ], |
164 | $subError->getHtmlMessage() |
165 | ); |
166 | } |
167 | |
168 | // Add failing key information to message: |
169 | // * Z526/Key value not wellformed |
170 | if ( $errorType === ZErrorTypeRegistry::Z_ERROR_KEY_VALUE_NOT_WELLFORMED ) { |
171 | $errorValue = $this->getZValue(); |
172 | $errorKey = $errorValue->getValueByKey( 'K1' ); |
173 | '@phan-var \MediaWiki\Extension\WikiLambda\ZObjects\ZKey $errorKey'; |
174 | $errorKeyLabel = $errorKey->getKeyLabel(); |
175 | $message .= ': ' . $errorKeyLabel; |
176 | } |
177 | |
178 | if ( count( $messages ) > 0 ) { |
179 | $message .= Html::rawElement( |
180 | 'ul', |
181 | [ 'class' => 'ext-wikilambda-app-suberror-list' ], |
182 | implode( '', $messages ) |
183 | ); |
184 | } |
185 | |
186 | return $message; |
187 | } |
188 | |
189 | /** |
190 | * Get all ZError related information in different forms for API failure response. |
191 | * |
192 | * @return array |
193 | */ |
194 | public function getErrorData() { |
195 | return [ |
196 | 'title' => $this->getMessage(), |
197 | 'message' => $this->getHtmlMessage(), |
198 | 'zerror' => $this->getSerialized(), |
199 | 'labelled' => $this->getHumanReadable(), |
200 | ]; |
201 | } |
202 | } |