Split ApiMessage to class per file
[lhc/web/wiklou.git] / includes / api / ApiUsageException.php
1 <?php
2 /**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21 /**
22 * This exception will be thrown when dieUsage is called to stop module execution.
23 *
24 * @ingroup API
25 * @deprecated since 1.29, use ApiUsageException instead
26 */
27 class UsageException extends MWException {
28
29 private $mCodestr;
30
31 /**
32 * @var null|array
33 */
34 private $mExtraData;
35
36 /**
37 * @param string $message
38 * @param string $codestr
39 * @param int $code
40 * @param array|null $extradata
41 */
42 public function __construct( $message, $codestr, $code = 0, $extradata = null ) {
43 parent::__construct( $message, $code );
44 $this->mCodestr = $codestr;
45 $this->mExtraData = $extradata;
46
47 if ( !$this instanceof ApiUsageException ) {
48 wfDeprecated( __METHOD__, '1.29' );
49 }
50
51 // This should never happen, so throw an exception about it that will
52 // hopefully get logged with a backtrace (T138585)
53 if ( !is_string( $codestr ) || $codestr === '' ) {
54 throw new InvalidArgumentException( 'Invalid $codestr, was ' .
55 ( $codestr === '' ? 'empty string' : gettype( $codestr ) )
56 );
57 }
58 }
59
60 /**
61 * @return string
62 */
63 public function getCodeString() {
64 wfDeprecated( __METHOD__, '1.29' );
65 return $this->mCodestr;
66 }
67
68 /**
69 * @return array
70 */
71 public function getMessageArray() {
72 wfDeprecated( __METHOD__, '1.29' );
73 $result = [
74 'code' => $this->mCodestr,
75 'info' => $this->getMessage()
76 ];
77 if ( is_array( $this->mExtraData ) ) {
78 $result = array_merge( $result, $this->mExtraData );
79 }
80
81 return $result;
82 }
83
84 /**
85 * @return string
86 */
87 public function __toString() {
88 return "{$this->getCodeString()}: {$this->getMessage()}";
89 }
90 }
91
92 /**
93 * Exception used to abort API execution with an error
94 *
95 * If possible, use ApiBase::dieWithError() instead of throwing this directly.
96 *
97 * @ingroup API
98 * @note This currently extends UsageException for backwards compatibility, so
99 * all the existing code that catches UsageException won't break when stuff
100 * starts throwing ApiUsageException. Eventually UsageException will go away
101 * and this will (probably) extend MWException directly.
102 */
103 class ApiUsageException extends UsageException implements ILocalizedException {
104
105 protected $modulePath;
106 protected $status;
107
108 /**
109 * @param ApiBase|null $module API module responsible for the error, if known
110 * @param StatusValue $status Status holding errors
111 * @param int $httpCode HTTP error code to use
112 */
113 public function __construct(
114 ApiBase $module = null, StatusValue $status, $httpCode = 0
115 ) {
116 if ( $status->isOK() ) {
117 throw new InvalidArgumentException( __METHOD__ . ' requires a fatal Status' );
118 }
119
120 $this->modulePath = $module ? $module->getModulePath() : null;
121 $this->status = $status;
122
123 // Bug T46111: Messages in the log files should be in English and not
124 // customized by the local wiki.
125 $enMsg = clone $this->getApiMessage();
126 $enMsg->inLanguage( 'en' )->useDatabase( false );
127 parent::__construct(
128 ApiErrorFormatter::stripMarkup( $enMsg->text() ),
129 $enMsg->getApiCode(),
130 $httpCode,
131 $enMsg->getApiData()
132 );
133 }
134
135 /**
136 * @param ApiBase|null $module API module responsible for the error, if known
137 * @param string|array|Message $msg See ApiMessage::create()
138 * @param string|null $code See ApiMessage::create()
139 * @param array|null $data See ApiMessage::create()
140 * @param int $httpCode HTTP error code to use
141 * @return static
142 */
143 public static function newWithMessage(
144 ApiBase $module = null, $msg, $code = null, $data = null, $httpCode = 0
145 ) {
146 return new static(
147 $module,
148 StatusValue::newFatal( ApiMessage::create( $msg, $code, $data ) ),
149 $httpCode
150 );
151 }
152
153 /**
154 * @return ApiMessage
155 */
156 private function getApiMessage() {
157 $errors = $this->status->getErrorsByType( 'error' );
158 if ( !$errors ) {
159 $errors = $this->status->getErrors();
160 }
161 if ( !$errors ) {
162 $msg = new ApiMessage( 'apierror-unknownerror-nocode', 'unknownerror' );
163 } else {
164 $msg = ApiMessage::create( $errors[0] );
165 }
166 return $msg;
167 }
168
169 /**
170 * Fetch the responsible module name
171 * @return string|null
172 */
173 public function getModulePath() {
174 return $this->modulePath;
175 }
176
177 /**
178 * Fetch the error status
179 * @return StatusValue
180 */
181 public function getStatusValue() {
182 return $this->status;
183 }
184
185 /**
186 * @deprecated Do not use. This only exists here because UsageException is in
187 * the inheritance chain for backwards compatibility.
188 * @inheritDoc
189 */
190 public function getCodeString() {
191 wfDeprecated( __METHOD__, '1.29' );
192 return $this->getApiMessage()->getApiCode();
193 }
194
195 /**
196 * @deprecated Do not use. This only exists here because UsageException is in
197 * the inheritance chain for backwards compatibility.
198 * @inheritDoc
199 */
200 public function getMessageArray() {
201 wfDeprecated( __METHOD__, '1.29' );
202 $enMsg = clone $this->getApiMessage();
203 $enMsg->inLanguage( 'en' )->useDatabase( false );
204
205 return [
206 'code' => $enMsg->getApiCode(),
207 'info' => ApiErrorFormatter::stripMarkup( $enMsg->text() ),
208 ] + $enMsg->getApiData();
209 }
210
211 /**
212 * @inheritDoc
213 */
214 public function getMessageObject() {
215 return Status::wrap( $this->status )->getMessage();
216 }
217
218 /**
219 * @return string
220 */
221 public function __toString() {
222 $enMsg = clone $this->getApiMessage();
223 $enMsg->inLanguage( 'en' )->useDatabase( false );
224 $text = ApiErrorFormatter::stripMarkup( $enMsg->text() );
225
226 return get_class( $this ) . ": {$enMsg->getApiCode()}: {$text} "
227 . "in {$this->getFile()}:{$this->getLine()}\n"
228 . "Stack trace:\n{$this->getTraceAsString()}";
229 }
230
231 }