Merge "Expose RL modules and js config vars in action=expandtemplates"

This commit is contained in:
jenkins-bot 2015-06-05 16:16:46 +00:00 committed by Gerrit Code Review
commit 7de7f9fc8e
6 changed files with 205 additions and 62 deletions

View file

@ -111,8 +111,9 @@ class ApiExpandTemplates extends ApiBase {
// the old way
ApiResult::setContentValue( $retval, 'wikitext', $wikitext );
} else {
$p_output = $wgParser->getOutput();
if ( isset( $prop['categories'] ) ) {
$categories = $wgParser->getOutput()->getCategories();
$categories = $p_output->getCategories();
if ( $categories ) {
$categories_result = array();
foreach ( $categories as $category => $sortkey ) {
@ -126,7 +127,7 @@ class ApiExpandTemplates extends ApiBase {
}
}
if ( isset( $prop['properties'] ) ) {
$properties = $wgParser->getOutput()->getProperties();
$properties = $p_output->getProperties();
if ( $properties ) {
ApiResult::setArrayType( $properties, 'BCkvp', 'name' );
ApiResult::setIndexedTagName( $properties, 'property' );
@ -142,6 +143,27 @@ class ApiExpandTemplates extends ApiBase {
if ( isset( $prop['wikitext'] ) ) {
$retval['wikitext'] = $wikitext;
}
if ( isset( $prop['modules'] ) ) {
$retval['modules'] = array_values( array_unique( $p_output->getModules() ) );
$retval['modulescripts'] = array_values( array_unique( $p_output->getModuleScripts() ) );
$retval['modulestyles'] = array_values( array_unique( $p_output->getModuleStyles() ) );
}
if ( isset( $prop['jsconfigvars'] ) ) {
$retval['jsconfigvars'] =
ApiResult::addMetadataToResultVars( $p_output->getJsConfigVars() );
}
if ( isset( $prop['encodedjsconfigvars'] ) ) {
$retval['encodedjsconfigvars'] = FormatJson::encode(
$p_output->getJsConfigVars(), false, FormatJson::ALL_OK
);
$retval[ApiResult::META_SUBELEMENTS][] = 'encodedjsconfigvars';
}
if ( isset( $prop['modules'] ) &&
!isset( $prop['jsconfigvars'] ) && !isset( $prop['encodedjsconfigvars'] ) ) {
$this->setWarning( "Property 'modules' was set but not 'jsconfigvars' " .
"or 'encodedjsconfigvars'. Configuration variables are necessary " .
"for proper module usage.");
}
}
}
ApiResult::setSubelementsList( $retval, array( 'wikitext', 'parsetree' ) );
@ -167,9 +189,13 @@ class ApiExpandTemplates extends ApiBase {
'properties',
'volatile',
'ttl',
'modules',
'jsconfigvars',
'encodedjsconfigvars',
'parsetree',
),
ApiBase::PARAM_ISMULTI => true,
ApiBase::PARAM_HELP_MSG_PER_VALUE => array(),
),
'includecomments' => false,
'generatexml' => array(

View file

@ -71,7 +71,9 @@ class ApiParse extends ApiBase {
if ( isset( $params['section'] ) ) {
$this->section = $params['section'];
if ( !preg_match( '/^((T-)?\d+|new)$/', $this->section ) ) {
$this->dieUsage( "The section parameter must be a valid section id or 'new'", "invalidsection" );
$this->dieUsage(
"The section parameter must be a valid section id or 'new'", "invalidsection"
);
}
} else {
$this->section = false;
@ -89,7 +91,10 @@ class ApiParse extends ApiBase {
if ( !is_null( $oldid ) || !is_null( $pageid ) || !is_null( $page ) ) {
if ( $this->section === 'new' ) {
$this->dieUsage( 'section=new cannot be combined with oldid, pageid or page parameters. Please use text', 'params' );
$this->dieUsage(
'section=new cannot be combined with oldid, pageid or page parameters. ' .
'Please use text', 'params'
);
}
if ( !is_null( $oldid ) ) {
// Don't use the parser cache
@ -356,7 +361,8 @@ class ApiParse extends ApiBase {
}
if ( isset( $prop['jsconfigvars'] ) ) {
$result_array['jsconfigvars'] = $this->formatJsConfigVars( $p_result->getJsConfigVars() );
$result_array['jsconfigvars'] =
ApiResult::addMetadataToResultVars( $p_result->getJsConfigVars() );
}
if ( isset( $prop['encodedjsconfigvars'] ) ) {
@ -366,6 +372,13 @@ class ApiParse extends ApiBase {
$result_array[ApiResult::META_SUBELEMENTS][] = 'encodedjsconfigvars';
}
if ( isset( $prop['modules'] ) &&
!isset( $prop['jsconfigvars'] ) && !isset( $prop['encodedjsconfigvars'] ) ) {
$this->setWarning( "Property 'modules' was set but not 'jsconfigvars' " .
"or 'encodedjsconfigvars'. Configuration variables are necessary " .
"for proper module usage.");
}
if ( isset( $prop['indicators'] ) ) {
$result_array['indicators'] = (array)$p_result->getIndicators();
ApiResult::setArrayType( $result_array['indicators'], 'BCkvp', 'name' );
@ -520,12 +533,13 @@ class ApiParse extends ApiBase {
$sectionTitle = !is_null( $params['sectiontitle'] ) ? $params['sectiontitle'] : '';
if ( $this->section === 'new' && ( $sectionTitle === '' || $summary === '' ) ) {
if( $sectionTitle !== '' ) {
if ( $sectionTitle !== '' ) {
$summary = $params['sectiontitle'];
}
if ( $summary !== '' ) {
$summary = wfMessage( 'newsectionsummary' )->rawParams( $wgParser->stripSectionName( $summary ) )
->inContentLanguage()->text();
$summary = wfMessage( 'newsectionsummary' )
->rawParams( $wgParser->stripSectionName( $summary ) )
->inContentLanguage()->text();
}
}
return Linker::formatComment( $summary, $title, $this->section === 'new' );
@ -681,53 +695,6 @@ class ApiParse extends ApiBase {
return $result;
}
private function formatJsConfigVars( $vars, $forceHash = true ) {
// Process subarrays and determine if this is a JS [] or {}
$hash = $forceHash;
$maxKey = -1;
$bools = array();
foreach ( $vars as $k => $v ) {
if ( is_array( $v ) || is_object( $v ) ) {
$vars[$k] = $this->formatJsConfigVars( (array)$v, false );
} elseif ( is_bool( $v ) ) {
// Better here to use real bools even in BC formats
$bools[] = $k;
}
if ( is_string( $k ) ) {
$hash = true;
} elseif ( $k > $maxKey ) {
$maxKey = $k;
}
}
if ( !$hash && $maxKey !== count( $vars ) - 1 ) {
$hash = true;
}
// Get the list of keys we actually care about. Unfortunately, we can't support
// certain keys that conflict with ApiResult metadata.
$keys = array_diff( array_keys( $vars ), array(
ApiResult::META_TYPE, ApiResult::META_PRESERVE_KEYS, ApiResult::META_KVP_KEY_NAME,
ApiResult::META_INDEXED_TAG_NAME, ApiResult::META_BC_BOOLS
) );
// Set metadata appropriately
if ( $hash ) {
return array(
ApiResult::META_TYPE => 'kvp',
ApiResult::META_KVP_KEY_NAME => 'key',
ApiResult::META_PRESERVE_KEYS => $keys,
ApiResult::META_BC_BOOLS => $bools,
ApiResult::META_INDEXED_TAG_NAME => 'var',
) + $vars;
} else {
return array(
ApiResult::META_TYPE => 'array',
ApiResult::META_BC_BOOLS => $bools,
ApiResult::META_INDEXED_TAG_NAME => 'value',
) + $vars;
}
}
private function setIndexedTagNames( &$array, $mapping ) {
foreach ( $mapping as $key => $name ) {
if ( isset( $array[$key] ) ) {

View file

@ -302,10 +302,14 @@ class ApiResult implements ApiSerializable {
$arr[$name] += $value;
} else {
$keys = join( ', ', array_keys( $conflicts ) );
throw new RuntimeException( "Conflicting keys ($keys) when attempting to merge element $name" );
throw new RuntimeException(
"Conflicting keys ($keys) when attempting to merge element $name"
);
}
} else {
throw new RuntimeException( "Attempting to add element $name=$value, existing value is {$arr[$name]}" );
throw new RuntimeException(
"Attempting to add element $name=$value, existing value is {$arr[$name]}"
);
}
}
@ -703,7 +707,9 @@ class ApiResult implements ApiSerializable {
* @param string $kvpKeyName See ApiResult::META_KVP_KEY_NAME
*/
public static function setArrayType( array &$arr, $type, $kvpKeyName = null ) {
if ( !in_array( $type, array( 'default', 'array', 'assoc', 'kvp', 'BCarray', 'BCassoc', 'BCkvp' ), true ) ) {
if ( !in_array( $type, array(
'default', 'array', 'assoc', 'kvp', 'BCarray', 'BCassoc', 'BCkvp'
), true ) ) {
throw new InvalidArgumentException( 'Bad type' );
}
$arr[self::META_TYPE] = $type;
@ -1035,7 +1041,8 @@ class ApiResult implements ApiSerializable {
/**
* Get the 'real' size of a result item. This means the strlen() of the item,
* or the sum of the strlen()s of the elements if the item is an array.
* @note Once the deprecated public self::size is removed, we can rename this back to a less awkward name.
* @note Once the deprecated public self::size is removed, we can rename
* this back to a less awkward name.
* @param mixed $value
* @return int
*/
@ -1096,6 +1103,61 @@ class ApiResult implements ApiSerializable {
return $ret;
}
/**
* Add the correct metadata to an array of vars we want to export through
* the API.
*
* @param array $vars
* @param boolean $forceHash
* @return array
*/
public static function addMetadataToResultVars( $vars, $forceHash = true ) {
// Process subarrays and determine if this is a JS [] or {}
$hash = $forceHash;
$maxKey = -1;
$bools = array();
foreach ( $vars as $k => $v ) {
if ( is_array( $v ) || is_object( $v ) ) {
$vars[$k] = ApiResult::addMetadataToResultVars( (array)$v, is_object( $v ) );
} elseif ( is_bool( $v ) ) {
// Better here to use real bools even in BC formats
$bools[] = $k;
}
if ( is_string( $k ) ) {
$hash = true;
} elseif ( $k > $maxKey ) {
$maxKey = $k;
}
}
if ( !$hash && $maxKey !== count( $vars ) - 1 ) {
$hash = true;
}
// Set metadata appropriately
if ( $hash ) {
// Get the list of keys we actually care about. Unfortunately, we can't support
// certain keys that conflict with ApiResult metadata.
$keys = array_diff( array_keys( $vars ), array(
ApiResult::META_TYPE, ApiResult::META_PRESERVE_KEYS, ApiResult::META_KVP_KEY_NAME,
ApiResult::META_INDEXED_TAG_NAME, ApiResult::META_BC_BOOLS
) );
return array(
ApiResult::META_TYPE => 'kvp',
ApiResult::META_KVP_KEY_NAME => 'key',
ApiResult::META_PRESERVE_KEYS => $keys,
ApiResult::META_BC_BOOLS => $bools,
ApiResult::META_INDEXED_TAG_NAME => 'var',
) + $vars;
} else {
return array(
ApiResult::META_TYPE => 'array',
ApiResult::META_BC_BOOLS => $bools,
ApiResult::META_INDEXED_TAG_NAME => 'value',
) + $vars;
}
}
/**@}*/
/************************************************************************//**

View file

@ -121,7 +121,16 @@
"apihelp-expandtemplates-param-title": "Title of page.",
"apihelp-expandtemplates-param-text": "Wikitext to convert.",
"apihelp-expandtemplates-param-revid": "Revision ID, for <nowiki>{{REVISIONID}}</nowiki> and similar variables.",
"apihelp-expandtemplates-param-prop": "Which pieces of information to get:\n;wikitext:The expanded wikitext.\n;categories:Any categories present in the input that are not represented in the wikitext output.\n;properties:Page properties defined by expanded magic words in the wikitext.\n;volatile:Whether the output is volatile and should not be reused elsewhere within the page.\n;ttl:The maximum time after which caches of the result should be invalidated.\n;parsetree:The XML parse tree of the input.\nNote that if no values are selected, the result will contain the wikitext, but the output will be in a deprecated format.",
"apihelp-expandtemplates-param-prop": "Which pieces of information to get.\n\nNote that if no values are selected, the result will contain the wikitext, but the output will be in a deprecated format.",
"apihelp-expandtemplates-paramvalue-prop-wikitext": "The expanded wikitext.",
"apihelp-expandtemplates-paramvalue-prop-categories": "Any categories present in the input that are not represented in the wikitext output.",
"apihelp-expandtemplates-paramvalue-prop-properties": "Page properties defined by expanded magic words in the wikitext.",
"apihelp-expandtemplates-paramvalue-prop-volatile": "Whether the output is volatile and should not be reused elsewhere within the page.",
"apihelp-expandtemplates-paramvalue-prop-ttl": "The maximum time after which caches of the result should be invalidated.",
"apihelp-expandtemplates-paramvalue-prop-modules": "Any ResourceLoader modules that parser functions have requested be added to the output. Either <kbd>jsconfigvars</kbd> or <kbd>encodedjsconfigvars</kbd> must be requested jointly with <kbd>modules</kbd>.",
"apihelp-expandtemplates-paramvalue-prop-jsconfigvars": "Gives the JavaScript configuration variables specific to the page.",
"apihelp-expandtemplates-paramvalue-prop-encodedjsconfigvars": "Gives the JavaScript configuration variables specific to the page as a JSON string.",
"apihelp-expandtemplates-paramvalue-prop-parsetree": "The XML parse tree of the input.",
"apihelp-expandtemplates-param-includecomments": "Whether to include HTML comments in the output.",
"apihelp-expandtemplates-param-generatexml": "Generate XML parse tree (replaced by $1prop=parsetree).",
"apihelp-expandtemplates-example-simple": "Expand the wikitext <kbd><nowiki>{{Project:Sandbox}}</nowiki></kbd>.",
@ -286,7 +295,7 @@
"apihelp-parse-paramvalue-prop-displaytitle": "Adds the title of the parsed wikitext.",
"apihelp-parse-paramvalue-prop-headitems": "Gives items to put in the <code>&lt;head&gt;</code> of the page.",
"apihelp-parse-paramvalue-prop-headhtml": "Gives parsed <code>&lt;head&gt;</code> of the page.",
"apihelp-parse-paramvalue-prop-modules": "Gives the ResourceLoader modules used on the page.",
"apihelp-parse-paramvalue-prop-modules": "Gives the ResourceLoader modules used on the page. Either <kbd>jsconfigvars</kbd> or <kbd>encodedjsconfigvars</kbd> must be requested jointly with <kbd>modules</kbd>.",
"apihelp-parse-paramvalue-prop-jsconfigvars": "Gives the JavaScript configuration variables specific to the page.",
"apihelp-parse-paramvalue-prop-encodedjsconfigvars": "Gives the JavaScript configuration variables specific to the page as a JSON string.",
"apihelp-parse-paramvalue-prop-indicators": "Gives the HTML of page status indicators used on the page.",

View file

@ -116,7 +116,16 @@
"apihelp-expandtemplates-param-title": "{{doc-apihelp-param|expandtemplates|title}}",
"apihelp-expandtemplates-param-text": "{{doc-apihelp-param|expandtemplates|text}}",
"apihelp-expandtemplates-param-revid": "{{doc-apihelp-param|expandtemplates|revid}}\n{{doc-important|Do not translate <code><<nowiki />nowiki>{{<nowiki />REVISIONID}}<<nowiki />/nowiki></code>}}",
"apihelp-expandtemplates-param-prop": "{{doc-apihelp-param|expandtemplates|prop}}",
"apihelp-expandtemplates-param-prop": "{{doc-apihelp-param|expandtemplates|prop|paramvalues=1}}",
"apihelp-expandtemplates-paramvalue-prop-wikitext": "{{doc-apihelp-paramvalue|expandtemplates|prop|wikitext}}",
"apihelp-expandtemplates-paramvalue-prop-categories": "{{doc-apihelp-paramvalue|expandtemplates|prop|categories}}",
"apihelp-expandtemplates-paramvalue-prop-properties": "{{doc-apihelp-paramvalue|expandtemplates|prop|properties}}",
"apihelp-expandtemplates-paramvalue-prop-volatile": "{{doc-apihelp-paramvalue|expandtemplates|prop|volatile}}",
"apihelp-expandtemplates-paramvalue-prop-ttl": "{{doc-apihelp-paramvalue|expandtemplates|prop|ttl}}",
"apihelp-expandtemplates-paramvalue-prop-modules": "{{doc-apihelp-paramvalue|expandtemplates|prop|modules}}",
"apihelp-expandtemplates-paramvalue-prop-jsconfigvars": "{{doc-apihelp-paramvalue|expandtemplates|prop|jsconfigvars}}",
"apihelp-expandtemplates-paramvalue-prop-encodedjsconfigvars": "{{doc-apihelp-paramvalue|expandtemplates|prop|encodedjsconfigvars}}",
"apihelp-expandtemplates-paramvalue-prop-parsetree": "{{doc-apihelp-paramvalue|expandtemplates|prop|parsetree}}",
"apihelp-expandtemplates-param-includecomments": "{{doc-apihelp-param|expandtemplates|includecomments}}",
"apihelp-expandtemplates-param-generatexml": "{{doc-apihelp-param|expandtemplates|generatexml}}",
"apihelp-expandtemplates-example-simple": "{{doc-apihelp-example|expandtemplates}}",

View file

@ -1124,6 +1124,76 @@ class ApiResultTest extends MediaWikiTestCase {
$data[ApiResult::META_CONTENT] = 'bar';
}
/**
* @covers ApiResult
*/
public function testAddMetadataToResultVars() {
$arr = array(
'a' => "foo",
'b' => false,
'c' => 10,
'sequential_numeric_keys' => array( 'a', 'b', 'c' ),
'non_sequential_numeric_keys' => array( 'a', 'b', 4 => 'c' ),
'string_keys' => array(
'one' => 1,
'two' => 2
),
'object_sequential_keys' => (object)array( 'a', 'b', 'c' ),
'_type' => "should be overwritten in result",
);
$this->assertSame( array(
ApiResult::META_TYPE => 'kvp',
ApiResult::META_KVP_KEY_NAME => 'key',
ApiResult::META_PRESERVE_KEYS => array(
'a', 'b', 'c',
'sequential_numeric_keys', 'non_sequential_numeric_keys',
'string_keys', 'object_sequential_keys'
),
ApiResult::META_BC_BOOLS => array( 'b' ),
ApiResult::META_INDEXED_TAG_NAME => 'var',
'a' => "foo",
'b' => false,
'c' => 10,
'sequential_numeric_keys' => array(
ApiResult::META_TYPE => 'array',
ApiResult::META_BC_BOOLS => array(),
ApiResult::META_INDEXED_TAG_NAME => 'value',
0 => 'a',
1 => 'b',
2 => 'c',
),
'non_sequential_numeric_keys' => array(
ApiResult::META_TYPE => 'kvp',
ApiResult::META_KVP_KEY_NAME => 'key',
ApiResult::META_PRESERVE_KEYS => array( 0, 1, 4 ),
ApiResult::META_BC_BOOLS => array(),
ApiResult::META_INDEXED_TAG_NAME => 'var',
0 => 'a',
1 => 'b',
4 => 'c',
),
'string_keys' => array(
ApiResult::META_TYPE => 'kvp',
ApiResult::META_KVP_KEY_NAME => 'key',
ApiResult::META_PRESERVE_KEYS => array( 'one', 'two' ),
ApiResult::META_BC_BOOLS => array(),
ApiResult::META_INDEXED_TAG_NAME => 'var',
'one' => 1,
'two' => 2,
),
'object_sequential_keys' => array(
ApiResult::META_TYPE => 'kvp',
ApiResult::META_KVP_KEY_NAME => 'key',
ApiResult::META_PRESERVE_KEYS => array( 0, 1, 2 ),
ApiResult::META_BC_BOOLS => array(),
ApiResult::META_INDEXED_TAG_NAME => 'var',
0 => 'a',
1 => 'b',
2 => 'c',
),
), ApiResult::addMetadataToResultVars( $arr ) );
}
/**
* @covers ApiResult
*/