abstract class ApiFormatBase extends ApiBase {
private $mIsHtml, $mFormat, $mUnescapeAmps, $mHelp;
private $mBuffer, $mDisabled = false;
+ private $mIsWrappedHtml = false;
protected $mForceDefaultParams = false;
/**
$this->mIsHtml = ( substr( $format, -2, 2 ) === 'fm' ); // ends with 'fm'
if ( $this->mIsHtml ) {
$this->mFormat = substr( $format, 0, -2 ); // remove ending 'fm'
+ $this->mIsWrappedHtml = $this->getMain()->getCheck( 'wrappedhtml' );
} else {
$this->mFormat = $format;
}
return $this->mIsHtml;
}
+ /**
+ * Returns true when the special wrapped mode is enabled.
+ * @since 1.27
+ * @return bool
+ */
+ protected function getIsWrappedHtml() {
+ return $this->mIsWrappedHtml;
+ }
+
/**
* Disable the formatter.
*
* Initialize the printer function and prepare the output headers.
* @param bool $unused Always false since 1.25
*/
- function initPrinter( $unused = false ) {
+ public function initPrinter( $unused = false ) {
if ( $this->mDisabled ) {
return;
}
- $mime = $this->getIsHtml() ? 'text/html' : $this->getMimeType();
+ $mime = $this->getIsWrappedHtml()
+ ? 'text/mediawiki-api-prettyprint-wrapped'
+ : ( $this->getIsHtml() ? 'text/html' : $this->getMimeType() );
// Some printers (ex. Feed) do their own header settings,
// in which case $mime will be set to null
$out->addModuleStyles( 'mediawiki.apipretty' );
$out->setPageTitle( $context->msg( 'api-format-title' ) );
- // When the format without suffix 'fm' is defined, there is a non-html version
- if ( $this->getMain()->getModuleManager()->isDefined( $lcformat, 'format' ) ) {
- $msg = $context->msg( 'api-format-prettyprint-header' )->params( $format, $lcformat );
- } else {
- $msg = $context->msg( 'api-format-prettyprint-header-only-html' )->params( $format );
- }
+ if ( !$this->getIsWrappedHtml() ) {
+ // When the format without suffix 'fm' is defined, there is a non-html version
+ if ( $this->getMain()->getModuleManager()->isDefined( $lcformat, 'format' ) ) {
+ $msg = $context->msg( 'api-format-prettyprint-header' )->params( $format, $lcformat );
+ } else {
+ $msg = $context->msg( 'api-format-prettyprint-header-only-html' )->params( $format );
+ }
- $header = $msg->parseAsBlock();
- $out->addHTML(
- Html::rawElement( 'div', array( 'class' => 'api-pretty-header' ),
- ApiHelp::fixHelpLinks( $header )
- )
- );
+ $header = $msg->parseAsBlock();
+ $out->addHTML(
+ Html::rawElement( 'div', [ 'class' => 'api-pretty-header' ],
+ ApiHelp::fixHelpLinks( $header )
+ )
+ );
+ }
- if ( Hooks::run( 'ApiFormatHighlight', array( $context, $result, $mime, $format ) ) ) {
+ if ( Hooks::run( 'ApiFormatHighlight', [ $context, $result, $mime, $format ] ) ) {
$out->addHTML(
- Html::element( 'pre', array( 'class' => 'api-pretty-content' ), $result )
+ Html::element( 'pre', [ 'class' => 'api-pretty-content' ], $result )
);
}
- // API handles its own clickjacking protection.
- // Note, that $wgBreakFrames will still override $wgApiFrameOptions for format mode.
- $out->allowClickjacking();
- $out->output();
+ if ( $this->getIsWrappedHtml() ) {
+ // This is a special output mode mainly intended for ApiSandbox use
+ $time = microtime( true ) - $this->getConfig()->get( 'RequestTime' );
+ $json = FormatJson::encode(
+ [
+ 'html' => $out->getHTML(),
+ 'modules' => array_values( array_unique( array_merge(
+ $out->getModules(),
+ $out->getModuleScripts(),
+ $out->getModuleStyles()
+ ) ) ),
+ 'time' => round( $time * 1000 ),
+ ],
+ false, FormatJson::ALL_OK
+ );
+
+ // Bug 66776: wfMangleFlashPolicy() is needed to avoid a nasty bug in
+ // Flash, but what it does isn't friendly for the API, so we need to
+ // work around it.
+ if ( preg_match( '/\<\s*cross-domain-policy\s*\>/i', $json ) ) {
+ $json = preg_replace(
+ '/\<(\s*cross-domain-policy\s*)\>/i', '\\u003C$1\\u003E', $json
+ );
+ }
+
+ echo $json;
+ } else {
+ // API handles its own clickjacking protection.
+ // Note, that $wgBreakFrames will still override $wgApiFrameOptions for format mode.
+ $out->allowClickjacking();
+ $out->output();
+ }
} else {
// For non-HTML output, clear all errors that might have been
// displayed if display_errors=On
return $this->mBuffer;
}
- protected function getExamplesMessages() {
- return array(
- 'action=query&meta=siteinfo&siprop=namespaces&format=' . $this->getModuleName()
- => array( 'apihelp-format-example-generic', $this->getFormat() )
- );
- }
-
- public function getHelpUrls() {
- return 'https://www.mediawiki.org/wiki/API:Data_formats';
- }
-
- /************************************************************************//**
- * @name Deprecated
- * @{
- */
-
- /**
- * Specify whether or not sequences like &quot; should be unescaped
- * to " . This should only be set to true for the help message
- * when rendered in the default (xmlfm) format. This is a temporary
- * special-case fix that should be removed once the help has been
- * reworked to use a fully HTML interface.
- *
- * @deprecated since 1.25
- * @param bool $b Whether or not ampersands should be escaped.
- */
- public function setUnescapeAmps( $b ) {
- wfDeprecated( __METHOD__, '1.25' );
- $this->mUnescapeAmps = $b;
- }
-
- /**
- * Whether this formatter can format the help message in a nice way.
- * By default, this returns the same as getIsHtml().
- * When action=help is set explicitly, the help will always be shown
- * @deprecated since 1.25
- * @return bool
- */
- public function getWantsHelp() {
- wfDeprecated( __METHOD__, '1.25' );
- return $this->getIsHtml();
- }
-
- /**
- * Sets whether the pretty-printer should format *bold*
- * @deprecated since 1.25
- * @param bool $help
- */
- public function setHelp( $help = true ) {
- wfDeprecated( __METHOD__, '1.25' );
- $this->mHelp = $help;
- }
-
- /**
- * Pretty-print various elements in HTML format, such as xml tags and
- * URLs. This method also escapes characters like <
- * @deprecated since 1.25
- * @param string $text
- * @return string
- */
- protected function formatHTML( $text ) {
- wfDeprecated( __METHOD__, '1.25' );
-
- // Escape everything first for full coverage
- $text = htmlspecialchars( $text );
-
- if ( $this->mFormat === 'XML' ) {
- // encode all comments or tags as safe blue strings
- $text = str_replace( '<', '<span style="color:blue;"><', $text );
- $text = str_replace( '>', '></span>', $text );
- }
-
- // identify requests to api.php
- $text = preg_replace( '#^(\s*)(api\.php\?[^ <\n\t]+)$#m', '\1<a href="\2">\2</a>', $text );
- if ( $this->mHelp ) {
- // make lines inside * bold
- $text = preg_replace( '#^(\s*)(\*[^<>\n]+\*)(\s*)$#m', '$1<b>$2</b>$3', $text );
- }
+ public function getAllowedParams() {
+ $ret = [];
+ if ( $this->getIsHtml() ) {
+ $ret['wrappedhtml'] = [
+ ApiBase::PARAM_DFLT => false,
+ ApiBase::PARAM_HELP_MSG => 'apihelp-format-param-wrappedhtml',
- // Armor links (bug 61362)
- $masked = array();
- $text = preg_replace_callback( '#<a .*?</a>#', function ( $matches ) use ( &$masked ) {
- $sha = sha1( $matches[0] );
- $masked[$sha] = $matches[0];
- return "<$sha>";
- }, $text );
-
- // identify URLs
- $protos = wfUrlProtocolsWithoutProtRel();
- // This regex hacks around bug 13218 (" included in the URL)
- $text = preg_replace(
- "#(((?i)$protos).*?)(")?([ \\'\"<>\n]|<|>|")#",
- '<a href="\\1">\\1</a>\\3\\4',
- $text
- );
-
- // Unarmor links
- $text = preg_replace_callback( '#<([0-9a-f]{40})>#', function ( $matches ) use ( &$masked ) {
- $sha = $matches[1];
- return isset( $masked[$sha] ) ? $masked[$sha] : $matches[0];
- }, $text );
-
- /**
- * Temporary fix for bad links in help messages. As a special case,
- * XML-escaped metachars are de-escaped one level in the help message
- * for legibility. Should be removed once we have completed a fully-HTML
- * version of the help message.
- */
- if ( $this->mUnescapeAmps ) {
- $text = preg_replace( '/&(amp|quot|lt|gt);/', '&\1;', $text );
+ ];
}
-
- return $text;
- }
-
- /**
- * @see ApiBase::getDescription
- * @deprecated since 1.25
- */
- public function getDescription() {
- return $this->getIsHtml() ? ' (pretty-print in HTML)' : '';
+ return $ret;
}
- /**
- * Set the flag to buffer the result instead of printing it.
- * @deprecated since 1.25, output is always buffered
- * @param bool $value
- */
- public function setBufferResult( $value ) {
+ protected function getExamplesMessages() {
+ return [
+ 'action=query&meta=siteinfo&siprop=namespaces&format=' . $this->getModuleName()
+ => [ 'apihelp-format-example-generic', $this->getFormat() ]
+ ];
}
- /**
- * Formerly indicated whether the formatter needed metadata from ApiResult.
- *
- * ApiResult previously (indirectly) used this to decide whether to add
- * metadata or to ignore calls to metadata-setting methods, which
- * unfortunately made several methods that should have been static have to
- * be dynamic instead. Now ApiResult always stores metadata and formatters
- * are required to ignore it or filter it out.
- *
- * @deprecated since 1.25
- * @return bool Always true
- */
- public function getNeedsRawData() {
- wfDeprecated( __METHOD__, '1.25' );
- return true;
+ public function getHelpUrls() {
+ return 'https://www.mediawiki.org/wiki/API:Data_formats';
}
- /**@}*/
}
/**