28 private bool $mIsHtml;
29 private string $mFormat;
30 private string $mBuffer =
'';
31 private bool $mDisabled =
false;
33 private $mIsWrappedHtml =
false;
35 private $mHttpStatus =
false;
46 parent::__construct( $main, $format );
48 $this->mIsHtml = str_ends_with( $format,
'fm' );
49 if ( $this->mIsHtml ) {
50 $this->mFormat = substr( $format, 0, -2 );
51 $this->mIsWrappedHtml = $this->
getMain()->getCheck(
'wrappedhtml' );
53 $this->mFormat = $format;
55 $this->mFormat = strtoupper( $this->mFormat );
78 return 'api-result-wrapped.json';
82 return 'api-result.html';
86 $ext = $mimeAnalyzer->getExtensionFromMimeTypeOrNull( $this->
getMimeType() )
87 ?? strtolower( $this->mFormat );
88 return "api-result.$ext";
97 return $this->mFormat;
107 return $this->mIsHtml;
117 return $this->mIsWrappedHtml;
126 $this->mDisabled =
true;
135 return $this->mDisabled;
157 $this->mForceDefaultParams =
true;
166 if ( !$this->mForceDefaultParams ) {
167 return parent::getParameterFromSettings( $paramName, $paramSettings, $parseLimit );
170 if ( !is_array( $paramSettings ) ) {
171 return $paramSettings;
174 return $paramSettings[ParamValidator::PARAM_DEFAULT] ??
null;
183 if ( $this->mDisabled ) {
188 $this->mHttpStatus = $code;
190 $this->
getMain()->getRequest()->response()->statusHeader( $code );
199 if ( $this->mDisabled ) {
203 if ( $this->
getIsHtml() && $this->
getMain()->getCacheMode() ===
'public' ) {
205 $this->
getMain()->setCacheMode(
'anon-public-user-private' );
209 ?
'text/mediawiki-api-prettyprint-wrapped'
214 if ( $mime ===
null ) {
218 if ( $mime !==
'text/html' ) {
219 ContentSecurityPolicy::sendRestrictiveHeader();
221 $this->
getMain()->getRequest()->response()->header(
"Content-Type: $mime; charset=utf-8" );
225 if ( $apiFrameOptions ) {
226 $this->
getMain()->getRequest()->response()->header(
"X-Frame-Options: $apiFrameOptions" );
231 $header =
'Content-Disposition: inline';
233 $compatFilename = mb_convert_encoding( $filename,
'ISO-8859-1' );
234 if ( preg_match(
'/^[0-9a-zA-Z!#$%&\'*+\-.^_`|~]+$/', $compatFilename ) ) {
235 $header .=
'; filename=' . $compatFilename;
237 $header .=
'; filename="'
238 . preg_replace(
'/([\0-\x1f"\x5c\x7f])/',
'\\\\$1', $compatFilename ) .
'"';
240 if ( $compatFilename !== $filename ) {
241 $value =
"UTF-8''" . rawurlencode( $filename );
243 $value = strtr( $value, [
244 '%21' =>
'!',
'%23' =>
'#',
'%24' =>
'$',
'%26' =>
'&',
'%2B' =>
'+',
'%5E' =>
'^',
245 '%60' =>
'`',
'%7C' =>
'|',
247 $header .=
'; filename*=' . $value;
249 $this->
getMain()->getRequest()->response()->header( $header );
256 if ( $this->mDisabled ) {
261 if ( $this->
getIsHtml() && $mime !==
null ) {
263 $lcformat = strtolower( $format );
268 $context->setSkin( $skinFactory->makeSkin(
'apioutput' ) );
271 $context->setOutput( $out );
273 $out->setRobotPolicy(
'noindex,nofollow' );
274 $out->addModuleStyles(
'mediawiki.apipretty' );
275 $out->setPageTitleMsg( $context->msg(
'api-format-title' ) );
281 $nonHtmlUrl = strtok( $this->
getRequest()->getFullRequestURL(),
'?' )
282 .
'?' . $this->
getRequest()->appendQueryValue(
'format', $lcformat );
283 $msg = $context->msg(
'api-format-prettyprint-header-hyperlinked' )
284 ->params( $format, $lcformat, $nonHtmlUrl );
286 $msg = $context->msg(
'api-format-prettyprint-header' )->params( $format, $lcformat );
289 $msg = $context->msg(
'api-format-prettyprint-header-only-html' )->params( $format );
292 $header = $msg->parseAsBlock();
294 Html::rawElement(
'div', [
'class' =>
'api-pretty-header' ],
299 if ( $this->mHttpStatus && $this->mHttpStatus !== 200 ) {
301 Html::rawElement(
'div', [
'class' => [
'api-pretty-header',
'api-pretty-status' ] ],
303 'api-format-prettyprint-status',
305 HttpStatus::getMessage( $this->mHttpStatus )
312 if ( $this->
getHookRunner()->onApiFormatHighlight( $context, $result, $mime, $format ) ) {
314 Html::element(
'pre', [
'class' =>
'api-pretty-content' ], $result )
320 $time = $this->
getMain()->getRequest()->getElapsedTime();
321 echo FormatJson::encode(
323 'status' => (
int)( $this->mHttpStatus ?: 200 ),
324 'statustext' => HttpStatus::getMessage( $this->mHttpStatus ?: 200 ),
325 'html' => $out->getHTML(),
326 'modules' => array_values( array_unique( array_merge(
328 $out->getModuleStyles()
330 'continue' => $this->
getResult()->getResultData(
'continue' ),
331 'time' => round( $time * 1000 ),
333 false, FormatJson::ALL_OK
338 $out->getMetadata()->setPreventClickjacking(
false );
356 $this->mBuffer .= $text;
365 return $this->mBuffer;
372 $ret[
'wrappedhtml'] = [
373 ParamValidator::PARAM_DEFAULT =>
false,
383 'action=query&meta=siteinfo&siprop=namespaces&format=' . $this->
getModuleName()
384 => [
'apihelp-format-example-generic', $this->
getFormat() ]
390 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Data_formats';
401class_alias( ApiFormatBase::class,
'ApiFormatBase' );
This is the main API class, used for both external and internal processing.
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
An IContextSource implementation which will inherit context from another source but allow individual ...
A class containing constants representing the names of configuration variables.
const ApiFrameOptions
Name constant for the ApiFrameOptions setting, for use with Config::get()
This is one of the Core classes and should be read at least once by any new developers.
Handle sending Content-Security-Policy headers.
Parent class for all special pages.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...