Merge "Move section ID fallbacks into headers themselves"
[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 * @defgroup API API
20 */
21
22 /**
23 * This exception will be thrown when dieUsage is called to stop module execution.
24 *
25 * @ingroup API
26 * @deprecated since 1.29, use ApiUsageException instead
27 */
28 class UsageException extends MWException {
29
30 private $mCodestr;
31
32 /**
33 * @var null|array
34 */
35 private $mExtraData;
36
37 /**
38 * @param string $message
39 * @param string $codestr
40 * @param int $code
41 * @param array|null $extradata
42 */
43 public function __construct( $message, $codestr, $code = 0, $extradata = null ) {
44 parent::__construct( $message, $code );
45 $this->mCodestr = $codestr;
46 $this->mExtraData = $extradata;
47
48 if ( !$this instanceof ApiUsageException ) {
49 wfDeprecated( __METHOD__, '1.29' );
50 }
51
52 // This should never happen, so throw an exception about it that will
53 // hopefully get logged with a backtrace (T138585)
54 if ( !is_string( $codestr ) || $codestr === '' ) {
55 throw new InvalidArgumentException( 'Invalid $codestr, was ' .
56 ( $codestr === '' ? 'empty string' : gettype( $codestr ) )
57 );
58 }
59 }
60
61 /**
62 * @return string
63 */
64 public function getCodeString() {
65 wfDeprecated( __METHOD__, '1.29' );
66 return $this->mCodestr;
67 }
68
69 /**
70 * @return array
71 */
72 public function getMessageArray() {
73 wfDeprecated( __METHOD__, '1.29' );
74 $result = [
75 'code' => $this->mCodestr,
76 'info' => $this->getMessage()
77 ];
78 if ( is_array( $this->mExtraData ) ) {
79 $result = array_merge( $result, $this->mExtraData );
80 }
81
82 return $result;
83 }
84
85 /**
86 * @return string
87 */
88 public function __toString() {
89 return "{$this->getCodeString()}: {$this->getMessage()}";
90 }
91 }
92
93 /**
94 * Exception used to abort API execution with an error
95 *
96 * If possible, use ApiBase::dieWithError() instead of throwing this directly.
97 *
98 * @ingroup API
99 * @note This currently extends UsageException for backwards compatibility, so
100 * all the existing code that catches UsageException won't break when stuff
101 * starts throwing ApiUsageException. Eventually UsageException will go away
102 * and this will (probably) extend MWException directly.
103 */
104 class ApiUsageException extends UsageException implements ILocalizedException {
105
106 protected $modulePath;
107 protected $status;
108
109 /**
110 * @param ApiBase|null $module API module responsible for the error, if known
111 * @param StatusValue $status Status holding errors
112 * @param int $httpCode HTTP error code to use
113 */
114 public function __construct(
115 ApiBase $module = null, StatusValue $status, $httpCode = 0
116 ) {
117 if ( $status->isOK() ) {
118 throw new InvalidArgumentException( __METHOD__ . ' requires a fatal Status' );
119 }
120
121 $this->modulePath = $module ? $module->getModulePath() : null;
122 $this->status = $status;
123
124 // Bug T46111: Messages in the log files should be in English and not
125 // customized by the local wiki.
126 $enMsg = clone $this->getApiMessage();
127 $enMsg->inLanguage( 'en' )->useDatabase( false );
128 parent::__construct(
129 ApiErrorFormatter::stripMarkup( $enMsg->text() ),
130 $enMsg->getApiCode(),
131 $httpCode,
132 $enMsg->getApiData()
133 );
134 }
135
136 /**
137 * @param ApiBase|null $module API module responsible for the error, if known
138 * @param string|array|Message $msg See ApiMessage::create()
139 * @param string|null $code See ApiMessage::create()
140 * @param array|null $data See ApiMessage::create()
141 * @param int $httpCode HTTP error code to use
142 * @return static
143 */
144 public static function newWithMessage(
145 ApiBase $module = null, $msg, $code = null, $data = null, $httpCode = 0
146 ) {
147 return new static(
148 $module,
149 StatusValue::newFatal( ApiMessage::create( $msg, $code, $data ) ),
150 $httpCode
151 );
152 }
153
154 /**
155 * @returns ApiMessage
156 */
157 private function getApiMessage() {
158 $errors = $this->status->getErrorsByType( 'error' );
159 if ( !$errors ) {
160 $errors = $this->status->getErrors();
161 }
162 if ( !$errors ) {
163 $msg = new ApiMessage( 'apierror-unknownerror-nocode', 'unknownerror' );
164 } else {
165 $msg = ApiMessage::create( $errors[0] );
166 }
167 return $msg;
168 }
169
170 /**
171 * Fetch the responsible module name
172 * @return string|null
173 */
174 public function getModulePath() {
175 return $this->modulePath;
176 }
177
178 /**
179 * Fetch the error status
180 * @return StatusValue
181 */
182 public function getStatusValue() {
183 return $this->status;
184 }
185
186 /**
187 * @deprecated Do not use. This only exists here because UsageException is in
188 * the inheritance chain for backwards compatibility.
189 * @inheritDoc
190 */
191 public function getCodeString() {
192 wfDeprecated( __METHOD__, '1.29' );
193 return $this->getApiMessage()->getApiCode();
194 }
195
196 /**
197 * @deprecated Do not use. This only exists here because UsageException is in
198 * the inheritance chain for backwards compatibility.
199 * @inheritDoc
200 */
201 public function getMessageArray() {
202 wfDeprecated( __METHOD__, '1.29' );
203 $enMsg = clone $this->getApiMessage();
204 $enMsg->inLanguage( 'en' )->useDatabase( false );
205
206 return [
207 'code' => $enMsg->getApiCode(),
208 'info' => ApiErrorFormatter::stripMarkup( $enMsg->text() ),
209 ] + $enMsg->getApiData();
210 }
211
212 /**
213 * @inheritDoc
214 */
215 public function getMessageObject() {
216 return $this->status->getMessage();
217 }
218
219 /**
220 * @return string
221 */
222 public function __toString() {
223 $enMsg = clone $this->getApiMessage();
224 $enMsg->inLanguage( 'en' )->useDatabase( false );
225 $text = ApiErrorFormatter::stripMarkup( $enMsg->text() );
226
227 return get_class( $this ) . ": {$enMsg->getApiCode()}: {$text} "
228 . "in {$this->getFile()}:{$this->getLine()}\n"
229 . "Stack trace:\n{$this->getTraceAsString()}";
230 }
231
232 }