36 private $mIsHtml, $mFormat;
37 private $mBuffer, $mDisabled =
false;
38 private $mIsWrappedHtml =
false;
39 private $mHttpStatus =
false;
49 parent::__construct( $main, $format );
51 $this->mIsHtml = str_ends_with( $format,
'fm' );
52 if ( $this->mIsHtml ) {
53 $this->mFormat = substr( $format, 0, -2 );
54 $this->mIsWrappedHtml = $this->
getMain()->getCheck(
'wrappedhtml' );
56 $this->mFormat = $format;
58 $this->mFormat = strtoupper( $this->mFormat );
81 return 'api-result-wrapped.json';
85 return 'api-result.html';
88 $mimeAnalyzer = MediaWikiServices::getInstance()->getMimeAnalyzer();
89 $ext = $mimeAnalyzer->getExtensionFromMimeTypeOrNull( $this->
getMimeType() )
90 ?? strtolower( $this->mFormat );
91 return "api-result.$ext";
100 return $this->mFormat;
110 return $this->mIsHtml;
120 return $this->mIsWrappedHtml;
129 $this->mDisabled =
true;
138 return $this->mDisabled;
160 $this->mForceDefaultParams =
true;
169 if ( !$this->mForceDefaultParams ) {
170 return parent::getParameterFromSettings( $paramName, $paramSettings, $parseLimit );
173 if ( !is_array( $paramSettings ) ) {
174 return $paramSettings;
177 return $paramSettings[ParamValidator::PARAM_DEFAULT] ??
null;
186 if ( $this->mDisabled ) {
191 $this->mHttpStatus = $code;
193 $this->
getMain()->getRequest()->response()->statusHeader( $code );
202 if ( $this->mDisabled ) {
206 if ( $this->
getIsHtml() && $this->
getMain()->getCacheMode() ===
'public' ) {
208 $this->
getMain()->setCacheMode(
'anon-public-user-private' );
212 ?
'text/mediawiki-api-prettyprint-wrapped'
217 if ( $mime ===
null ) {
221 $this->
getMain()->getRequest()->response()->header(
"Content-Type: $mime; charset=utf-8" );
224 $apiFrameOptions = $this->
getConfig()->get( MainConfigNames::ApiFrameOptions );
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;
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;
256 if ( $this->mDisabled ) {
261 if ( $this->
getIsHtml() && $mime !==
null ) {
263 $lcformat = strtolower( $format );
266 $context =
new DerivativeContext( $this->
getMain() );
267 $skinFactory = MediaWikiServices::getInstance()->getSkinFactory();
268 $context->setSkin( $skinFactory->makeSkin(
'apioutput' ) );
269 $context->setTitle( SpecialPage::getTitleFor(
'ApiHelp' ) );
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' ],
295 ApiHelp::fixHelpLinks(
$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->setPreventClickjacking(
false );
356 $this->mBuffer .= $text;
365 return $this->mBuffer;
371 $ret[
'wrappedhtml'] = [
372 ParamValidator::PARAM_DEFAULT =>
false,
381 'action=query&meta=siteinfo&siprop=namespaces&format=' . $this->
getModuleName()
382 => [
'apihelp-format-example-generic', $this->
getFormat() ]
387 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Data_formats';
This abstract class implements many basic API functions, and is the base of all API classes.
getModuleManager()
Get the module manager, or null if this module has no submodules.
getMain()
Get the main module.
getResult()
Get the result object.
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
getModuleName()
Get the name of the module being executed by this instance.
getHookRunner()
Get an ApiHookRunner for running core API hooks.
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()
A class containing constants representing the names of configuration variables.
This is one of the Core classes and should be read at least once by any new developers.
Parent class for all special pages.