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