]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/Status.php
MediaWiki 1.17.0
[autoinstalls/mediawiki.git] / includes / Status.php
1 <?php
2
3 /**
4  * Generic operation result class
5  * Has warning/error list, boolean status and arbitrary value
6  *
7  * "Good" means the operation was completed with no warnings or errors.
8  *
9  * "OK" means the operation was partially or wholly completed.
10  *
11  * An operation which is not OK should have errors so that the user can be
12  * informed as to what went wrong. Calling the fatal() function sets an error
13  * message and simultaneously switches off the OK flag.
14  */
15 class Status {
16         var $ok = true;
17         var $value;
18
19         /** Counters for batch operations */
20         var $successCount = 0, $failCount = 0;
21
22         /*semi-private*/ var $errors = array();
23         /*semi-private*/ var $cleanCallback = false;
24
25         /**
26          * Factory function for fatal errors
27          *
28          * @param $message String: message name
29          */
30         static function newFatal( $message /*, parameters...*/ ) {
31                 $params = func_get_args();
32                 $result = new self;
33                 call_user_func_array( array( &$result, 'error' ), $params );
34                 $result->ok = false;
35                 return $result;
36         }
37
38         /**
39          * Factory function for good results
40          *
41          * @param $value Mixed
42          */
43         static function newGood( $value = null ) {
44                 $result = new self;
45                 $result->value = $value;
46                 return $result;
47         }
48
49         /**
50          * Change operation result
51          *
52          * @param $ok Boolean: whether to operation completed
53          * @param $value Mixed
54          */
55         function setResult( $ok, $value = null ) {
56                 $this->ok = $ok;
57                 $this->value = $value;
58         }
59
60         /**
61          * Returns whether the operation completed and didn't have any error or
62          * warnings
63          *
64          * @return Boolean
65          */
66         function isGood() {
67                 return $this->ok && !$this->errors;
68         }
69
70         /**
71          * Returns whether the operation completed
72          *
73          * @return Boolean
74          */
75         function isOK() {
76                 return $this->ok;
77         }
78
79         /**
80          * Add a new warning
81          *
82          * @param $message String: message name
83          */
84         function warning( $message /*, parameters... */ ) {
85                 $params = array_slice( func_get_args(), 1 );
86                 $this->errors[] = array(
87                         'type' => 'warning',
88                         'message' => $message,
89                         'params' => $params );
90         }
91
92         /**
93          * Add an error, do not set fatal flag
94          * This can be used for non-fatal errors
95          *
96          * @param $message String: message name
97          */
98         function error( $message /*, parameters... */ ) {
99                 $params = array_slice( func_get_args(), 1 );
100                 $this->errors[] = array(
101                         'type' => 'error',
102                         'message' => $message,
103                         'params' => $params );
104         }
105
106         /**
107          * Add an error and set OK to false, indicating that the operation
108          * as a whole was fatal
109          *
110          * @param $message String: message name
111          */
112         function fatal( $message /*, parameters... */ ) {
113                 $params = array_slice( func_get_args(), 1 );
114                 $this->errors[] = array(
115                         'type' => 'error',
116                         'message' => $message,
117                         'params' => $params );
118                 $this->ok = false;
119         }
120
121         /**
122          * Sanitize the callback parameter on wakeup, to avoid arbitrary execution.
123          */
124         function __wakeup() {
125                 $this->cleanCallback = false;
126         }
127
128         protected function cleanParams( $params ) {
129                 if ( !$this->cleanCallback ) {
130                         return $params;
131                 }
132                 $cleanParams = array();
133                 foreach ( $params as $i => $param ) {
134                         $cleanParams[$i] = call_user_func( $this->cleanCallback, $param );
135                 }
136                 return $cleanParams;
137         }
138
139         protected function getItemXML( $item ) {
140                 $params = $this->cleanParams( $item['params'] );
141                 $xml = "<{$item['type']}>\n" .
142                         Xml::element( 'message', null, $item['message'] ) . "\n" .
143                         Xml::element( 'text', null, wfMsgReal( $item['message'], $params ) ) ."\n";
144                 foreach ( $params as $param ) {
145                         $xml .= Xml::element( 'param', null, $param );
146                 }
147                 $xml .= "</{$this->type}>\n";
148                 return $xml;
149         }
150
151         /**
152          * Get the error list as XML
153          */
154         function getXML() {
155                 $xml = "<errors>\n";
156                 foreach ( $this->errors as $error ) {
157                         $xml .= $this->getItemXML( $error );
158                 }
159                 $xml .= "</errors>\n";
160                 return $xml;
161         }
162
163         /**
164          * Get the error list as a wikitext formatted list
165          *
166          * @param $shortContext String: a short enclosing context message name, to
167          *        be used when there is a single error
168          * @param $longContext String: a long enclosing context message name, for a list
169          * @return String
170          */
171         function getWikiText( $shortContext = false, $longContext = false ) {
172                 if ( count( $this->errors ) == 0 ) {
173                         if ( $this->ok ) {
174                                 $this->fatal( 'internalerror_info',
175                                         __METHOD__." called for a good result, this is incorrect\n" );
176                         } else {
177                                 $this->fatal( 'internalerror_info',
178                                         __METHOD__.": Invalid result object: no error text but not OK\n" );
179                         }
180                 }
181                 if ( count( $this->errors ) == 1 ) {
182                         $s = $this->getWikiTextForError( $this->errors[0], $this->errors[0]  );
183                         if ( $shortContext ) {
184                                 $s = wfMsgNoTrans( $shortContext, $s );
185                         } elseif ( $longContext ) {
186                                 $s = wfMsgNoTrans( $longContext, "* $s\n" );
187                         }
188                 } else {
189                         $s = '* '. implode("\n* ",
190                                 $this->getWikiTextArray( $this->errors ) ) . "\n";
191                         if ( $longContext ) {
192                                 $s = wfMsgNoTrans( $longContext, $s );
193                         } elseif ( $shortContext ) {
194                                 $s = wfMsgNoTrans( $shortContext, "\n$s\n" );
195                         }
196                 }
197                 return $s;
198         }
199
200         /**
201          * Return the wiki text for a single error.
202          * @param $error Mixed With an array & two values keyed by
203          * 'message' and 'params', use those keys-value pairs.
204          * Otherwise, if its an array, just use the first value as the
205          * message and the remaining items as the params.
206          *
207          * @return String
208          */
209         protected function getWikiTextForError( $error ) {
210                 if ( is_array( $error ) ) {
211                         if ( isset( $error['message'] ) && isset( $error['params'] ) ) {
212                                 return wfMsgReal( $error['message'],
213                                         array_map( 'wfEscapeWikiText', $this->cleanParams( $error['params'] ) ),
214                                         true, false, false );
215                         } else {
216                                 $message = array_shift($error);
217                                 return wfMsgReal( $message,
218                                         array_map( 'wfEscapeWikiText', $this->cleanParams( $error ) ),
219                                         true, false, false );
220                         }
221                 } else {
222                         return wfMsgReal( $error, array(), true, false, false);
223                 }
224         }
225
226         /**
227          * Return an array with the wikitext for each item in the array.
228          * @param $errors Array
229          * @return Array
230          */
231         function getWikiTextArray( $errors ) {
232                 return array_map( array( $this, 'getWikiTextForError' ), $errors );
233         }
234
235         /**
236          * Merge another status object into this one
237          *
238          * @param $other Other Status object
239          * @param $overwriteValue Boolean: whether to override the "value" member
240          */
241         function merge( $other, $overwriteValue = false ) {
242                 $this->errors = array_merge( $this->errors, $other->errors );
243                 $this->ok = $this->ok && $other->ok;
244                 if ( $overwriteValue ) {
245                         $this->value = $other->value;
246                 }
247                 $this->successCount += $other->successCount;
248                 $this->failCount += $other->failCount;
249         }
250
251         /**
252          * Get the list of errors (but not warnings)
253          *
254          * @return Array
255          */
256         function getErrorsArray() {
257                 return $this->getStatusArray( "error" );
258         }
259
260         /**
261          * Get the list of warnings (but not errors)
262          *
263          * @return Array
264          */
265         function getWarningsArray() {
266                 return $this->getStatusArray( "warning" );
267         }
268
269         /**
270          * Returns a list of status messages of the given type
271          * @param $type String
272          *
273          * @return Array
274          */
275         protected function getStatusArray( $type ) {
276                 $result = array();
277                 foreach ( $this->errors as $error ) {
278                         if ( $error['type'] === $type ) {
279                                 if( $error['params'] ) {
280                                         $result[] = array_merge( array( $error['message'] ), $error['params'] );
281                                 } else {
282                                         $result[] = $error['message'];
283                                 }
284                         }
285                 }
286                 return $result;
287         }
288         /**
289          * Returns true if the specified message is present as a warning or error
290          *
291          * @param $msg String: message name
292          * @return Boolean
293          */
294         function hasMessage( $msg ) {
295                 foreach ( $this->errors as $error ) {
296                         if ( $error['message'] === $msg ) {
297                                 return true;
298                         }
299                 }
300                 return false;
301         }
302
303         /**
304          * If the specified source message exists, replace it with the specified 
305          * destination message, but keep the same parameters as in the original error.
306          *
307          * Return true if the replacement was done, false otherwise.
308          */
309         function replaceMessage( $source, $dest ) {
310                 $replaced = false;
311                 foreach ( $this->errors as $index => $error ) {
312                         if ( $error['message'] === $source ) {
313                                 $this->errors[$index]['message'] = $dest;
314                                 $replaced = true;
315                         }
316                 }
317                 return $replaced;
318         }
319
320         /**
321          * Backward compatibility function for WikiError -> Status migration
322          *
323          * @return String
324          */
325         public function getMessage() {
326                 return $this->getWikiText();
327         }
328 }