From df5b122641bf047d8f5834d1f0c219769c3593c2 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Mon, 24 Apr 2017 20:53:50 -0700 Subject: [PATCH] ApiParse: Add 'useskin' param for general OutputPage/Skin support Required for Idc41934eb89. * If 'useskin' is set, run ParserOutput through OutputPage (with proper Skin set up). Specifically call addParserOutputMetadata(). Then use OutputPage isntead of ParserOutput to retrieve that subset of meta data. Such as modules, lang links and config vars. * Deprecate 'effectivelanglinks' in favour of 'useskin'. * Simplify 'headhtml' support and re-use this new code. Change-Id: Iaa85ac49f6e0cbdf7f1bb0f50a8f7730d119f0a2 --- includes/api/ApiParse.php | 114 ++++++++++++++++++++++++++----------- includes/api/i18n/en.json | 1 + includes/api/i18n/qqq.json | 1 + 3 files changed, 82 insertions(+), 34 deletions(-) diff --git a/includes/api/ApiParse.php b/includes/api/ApiParse.php index 7d22d9c470..b36127d7d9 100644 --- a/includes/api/ApiParse.php +++ b/includes/api/ApiParse.php @@ -22,6 +22,8 @@ * @file */ +use MediaWiki\MediaWikiServices; + /** * @ingroup API */ @@ -278,6 +280,40 @@ class ApiParse extends ApiBase { $result_array['title'] = $titleObj->getPrefixedText(); $result_array['pageid'] = $pageid ?: $pageObj->getId(); + if ( $params['disabletoc'] ) { + $p_result->setTOCEnabled( false ); + } + + if ( isset( $params['useskin'] ) ) { + $factory = MediaWikiServices::getInstance()->getSkinFactory(); + $skin = $factory->makeSkin( Skin::normalizeKey( $params['useskin'] ) ); + } else { + $skin = null; + } + + $outputPage = null; + if ( $skin || isset( $prop['headhtml'] ) ) { + // Enabling the skin via 'useskin' or 'headhtml' gets OutputPage and + // Skin involved, which (among others) applies these hooks: + // - ParserOutputHooks + // - Hook: LanguageLinks + // - Hook: OutputPageParserOutput + $context = new DerivativeContext( $this->getContext() ); + $context->setTitle( $titleObj ); + $context->setWikiPage( $pageObj ); + + if ( $skin ) { + // Use the skin specified by 'useskin' + $context->setSkin( $skin ); + // Context clones the skin, refetch to stay in sync. (T166022) + $skin = $context->getSkin(); + } + + $outputPage = new OutputPage( $context ); + $outputPage->addParserOutputMetadata( $p_result ); + $context->setOutput( $outputPage ); + } + if ( !is_null( $oldid ) ) { $result_array['revid'] = intval( $oldid ); } @@ -286,10 +322,6 @@ class ApiParse extends ApiBase { $result_array['redirects'] = $redirValues; } - if ( $params['disabletoc'] ) { - $p_result->setTOCEnabled( false ); - } - if ( isset( $prop['text'] ) ) { $result_array['text'] = $p_result->getText(); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'text'; @@ -303,19 +335,19 @@ class ApiParse extends ApiBase { } if ( isset( $prop['langlinks'] ) ) { - $langlinks = $p_result->getLanguageLinks(); - - if ( $params['effectivelanglinks'] ) { - // Link flags are ignored for now, but may in the future be - // included in the result. - $linkFlags = []; - Hooks::run( 'LanguageLinks', [ $titleObj, &$langlinks, &$linkFlags ] ); + if ( $skin ) { + $langlinks = $outputPage->getLanguageLinks(); + } else { + $langlinks = $p_result->getLanguageLinks(); + // The deprecated 'effectivelanglinks' option depredates OutputPage + // support via 'useskin'. If not already applied, then run just this + // one hook of OutputPage::addParserOutputMetadata here. + if ( $params['effectivelanglinks'] ) { + $linkFlags = []; + Hooks::run( 'LanguageLinks', [ $titleObj, &$langlinks, &$linkFlags ] ); + } } - } else { - $langlinks = false; - } - if ( isset( $prop['langlinks'] ) ) { $result_array['langlinks'] = $this->formatLangLinks( $langlinks ); } if ( isset( $prop['categories'] ) ) { @@ -350,38 +382,42 @@ class ApiParse extends ApiBase { } if ( isset( $prop['headitems'] ) ) { - $result_array['headitems'] = $this->formatHeadItems( $p_result->getHeadItems() ); + if ( $skin ) { + $result_array['headitems'] = $this->formatHeadItems( $outputPage->getHeadItemsArray() ); + } else { + $result_array['headitems'] = $this->formatHeadItems( $p_result->getHeadItems() ); + } $this->addDeprecation( 'apiwarn-deprecation-parse-headitems', 'action=parse&prop=headitems' ); } if ( isset( $prop['headhtml'] ) ) { - $context = new DerivativeContext( $this->getContext() ); - $context->setTitle( $titleObj ); - $context->setWikiPage( $pageObj ); - - // We need an OutputPage tied to $context, not to the - // RequestContext at the root of the stack. - $output = new OutputPage( $context ); - $output->addParserOutputMetadata( $p_result ); - - $result_array['headhtml'] = $output->headElement( $context->getSkin() ); + $result_array['headhtml'] = $outputPage->headElement( $context->getSkin() ); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'headhtml'; } if ( isset( $prop['modules'] ) ) { - $result_array['modules'] = array_values( array_unique( $p_result->getModules() ) ); - $result_array['modulescripts'] = array_values( array_unique( $p_result->getModuleScripts() ) ); - $result_array['modulestyles'] = array_values( array_unique( $p_result->getModuleStyles() ) ); + if ( $skin ) { + $result_array['modules'] = $outputPage->getModules(); + $result_array['modulescripts'] = $outputPage->getModuleScripts(); + $result_array['modulestyles'] = $outputPage->getModuleStyles(); + } else { + $result_array['modules'] = array_values( array_unique( $p_result->getModules() ) ); + $result_array['modulescripts'] = array_values( array_unique( $p_result->getModuleScripts() ) ); + $result_array['modulestyles'] = array_values( array_unique( $p_result->getModuleStyles() ) ); + } } if ( isset( $prop['jsconfigvars'] ) ) { - $result_array['jsconfigvars'] = - ApiResult::addMetadataToResultVars( $p_result->getJsConfigVars() ); + $jsconfigvars = $skin ? $outputPage->getJsConfigVars() : $p_result->getJsConfigVars(); + $result_array['jsconfigvars'] = ApiResult::addMetadataToResultVars( $jsconfigvars ); } if ( isset( $prop['encodedjsconfigvars'] ) ) { + $jsconfigvars = $skin ? $outputPage->getJsConfigVars() : $p_result->getJsConfigVars(); $result_array['encodedjsconfigvars'] = FormatJson::encode( - $p_result->getJsConfigVars(), false, FormatJson::ALL_OK + $jsconfigvars, + false, + FormatJson::ALL_OK ); $result_array[ApiResult::META_SUBELEMENTS][] = 'encodedjsconfigvars'; } @@ -392,7 +428,11 @@ class ApiParse extends ApiBase { } if ( isset( $prop['indicators'] ) ) { - $result_array['indicators'] = (array)$p_result->getIndicators(); + if ( $skin ) { + $result_array['indicators'] = (array)$outputPage->getIndicators(); + } else { + $result_array['indicators'] = (array)$p_result->getIndicators(); + } ApiResult::setArrayType( $result_array['indicators'], 'BCkvp', 'name' ); } @@ -794,7 +834,10 @@ class ApiParse extends ApiBase { 'wrapoutputclass' => 'mw-parser-output', 'pst' => false, 'onlypst' => false, - 'effectivelanglinks' => false, + 'effectivelanglinks' => [ + ApiBase::PARAM_DFLT => false, + ApiBase::PARAM_DEPRECATED => true, + ], 'section' => null, 'sectiontitle' => [ ApiBase::PARAM_TYPE => 'string', @@ -816,6 +859,9 @@ class ApiParse extends ApiBase { 'preview' => false, 'sectionpreview' => false, 'disabletoc' => false, + 'useskin' => [ + ApiBase::PARAM_TYPE => array_keys( Skin::getAllowedSkins() ), + ], 'contentformat' => [ ApiBase::PARAM_TYPE => ContentHandler::getAllContentFormats(), ], diff --git a/includes/api/i18n/en.json b/includes/api/i18n/en.json index 5f52a1e2b2..a3916621f0 100644 --- a/includes/api/i18n/en.json +++ b/includes/api/i18n/en.json @@ -363,6 +363,7 @@ "apihelp-parse-param-preview": "Parse in preview mode.", "apihelp-parse-param-sectionpreview": "Parse in section preview mode (enables preview mode too).", "apihelp-parse-param-disabletoc": "Omit table of contents in output.", + "apihelp-parse-param-useskin": "Apply the selected skin to the parser output. May affect the following properties: langlinks, headitems, modules, jsconfigvars, indicators.", "apihelp-parse-param-contentformat": "Content serialization format used for the input text. Only valid when used with $1text.", "apihelp-parse-param-contentmodel": "Content model of the input text. If omitted, $1title must be specified, and default will be the model of the specified title. Only valid when used with $1text.", "apihelp-parse-example-page": "Parse a page.", diff --git a/includes/api/i18n/qqq.json b/includes/api/i18n/qqq.json index 672b7f0918..ee28dd60d4 100644 --- a/includes/api/i18n/qqq.json +++ b/includes/api/i18n/qqq.json @@ -344,6 +344,7 @@ "apihelp-parse-param-generatexml": "{{doc-apihelp-param|parse|generatexml|params=* $1 - Value of the constant CONTENT_MODEL_WIKITEXT|paramstart=2}}", "apihelp-parse-param-preview": "{{doc-apihelp-param|parse|preview}}", "apihelp-parse-param-sectionpreview": "{{doc-apihelp-param|parse|sectionpreview}}", + "apihelp-parse-param-useskin": "{{doc-apihelp-param|parse|useskin}}", "apihelp-parse-param-disabletoc": "{{doc-apihelp-param|parse|disabletoc}}", "apihelp-parse-param-contentformat": "{{doc-apihelp-param|parse|contentformat}}", "apihelp-parse-param-contentmodel": "{{doc-apihelp-param|parse|contentmodel}}", -- 2.20.1