// $msg for ApiBase::makeMessage(). Any value not having a mapping will use
// apihelp-{$path}-paramvalue-{$param}-{$value} is used.
const PARAM_HELP_MSG_PER_VALUE = 14;
+ /// @since 1.26
+ // When PARAM_TYPE is 'submodule', map parameter values to submodule paths.
+ // Default is to use all modules in $this->getModuleManager() in the group
+ // matching the parameter name.
+ const PARAM_SUBMODULE_MAP = 15;
+ /// @since 1.26
+ // When PARAM_TYPE is 'submodule', used to indicate the 'g' prefix added by
+ // ApiQueryGeneratorBase (and similar if anything else ever does that).
+ const PARAM_SUBMODULE_PARAM_PREFIX = 16;
const LIMIT_BIG1 = 500; // Fast query, std user limit
const LIMIT_BIG2 = 5000; // Fast query, bot/sysop limit
$type = MWNamespace::getValidNamespaces();
}
if ( isset( $value ) && $type == 'submodule' ) {
- $type = $this->getModuleManager()->getNames( $paramName );
+ if ( isset( $paramSettings[self::PARAM_SUBMODULE_MAP] ) ) {
+ $type = array_keys( $paramSettings[self::PARAM_SUBMODULE_MAP] );
+ } else {
+ $type = $this->getModuleManager()->getNames( $paramName );
+ }
}
}
case 'NULL': // nothing to do
break;
case 'string':
+ case 'text':
+ case 'password':
if ( $required && $value === '' ) {
$this->dieUsageMsg( array( 'missingparam', $paramName ) );
}
* @return string Validated and normalized parameter
*/
protected function validateTimestamp( $value, $encParamName ) {
+ // Confusing synonyms for the current time accepted by wfTimestamp()
+ // (wfTimestamp() also accepts various non-strings and the string of 14
+ // ASCII NUL bytes, but those can't get here)
+ if ( !$value ) {
+ $this->logFeatureUsage( 'unclear-"now"-timestamp' );
+ $this->setWarning(
+ "Passing '$value' for timestamp parameter $encParamName has been deprecated." .
+ ' If for some reason you need to explicitly specify the current time without' .
+ ' calculating it client-side, use "now".'
+ );
+ return wfTimestamp( TS_MW );
+ }
+
+ // Explicit synonym for the current time
+ if ( $value === 'now' ) {
+ return wfTimestamp( TS_MW );
+ }
+
$unixTimestamp = wfTimestamp( TS_UNIX, $value );
if ( $unixTimestamp === false ) {
$this->dieUsage(
}
if ( $type === 'submodule' ) {
- $type = $this->getModuleManager()->getNames( $paramName );
+ if ( isset( $paramSettings[self::PARAM_SUBMODULE_MAP] ) ) {
+ $type = array_keys( $paramSettings[self::PARAM_SUBMODULE_MAP] );
+ } else {
+ $type = $this->getModuleManager()->getNames( $paramName );
+ }
sort( $type );
}
if ( is_array( $type ) ) {
ApiBase::PARAM_TYPE => 'user',
ApiBase::PARAM_REQUIRED => true
),
- 'password' => null,
+ 'password' => array(
+ ApiBase::PARAM_TYPE => 'password',
+ ),
'domain' => null,
'token' => null,
'email' => array(
$requestArray['wpUndidRevision'] = $params['undo'];
}
- // Watch out for basetimestamp == ''
- // wfTimestamp() treats it as NOW, almost certainly causing an edit conflict
- if ( !is_null( $params['basetimestamp'] ) && $params['basetimestamp'] != '' ) {
- $requestArray['wpEdittime'] = wfTimestamp( TS_MW, $params['basetimestamp'] );
+ // Watch out for basetimestamp == '' or '0'
+ // It gets treated as NOW, almost certainly causing an edit conflict
+ if ( $params['basetimestamp'] !== null && (bool)$this->getMain()->getVal( 'basetimestamp' ) ) {
+ $requestArray['wpEdittime'] = $params['basetimestamp'];
} else {
$requestArray['wpEdittime'] = $pageObj->getTimestamp();
}
- if ( !is_null( $params['starttimestamp'] ) && $params['starttimestamp'] != '' ) {
- $requestArray['wpStarttime'] = wfTimestamp( TS_MW, $params['starttimestamp'] );
+ if ( $params['starttimestamp'] !== null ) {
+ $requestArray['wpStarttime'] = $params['starttimestamp'];
} else {
$requestArray['wpStarttime'] = wfTimestampNow(); // Fake wpStartime
}
'sectiontitle' => array(
ApiBase::PARAM_TYPE => 'string',
),
- 'text' => null,
+ 'text' => array(
+ ApiBase::PARAM_TYPE => 'text',
+ ),
'summary' => null,
'tags' => array(
ApiBase::PARAM_TYPE => ChangeTags::listExplicitlyDefinedTags(),
'minor' => false,
'notminor' => false,
'bot' => false,
- 'basetimestamp' => null,
- 'starttimestamp' => null,
+ 'basetimestamp' => array(
+ ApiBase::PARAM_TYPE => 'timestamp',
+ ),
+ 'starttimestamp' => array(
+ ApiBase::PARAM_TYPE => 'timestamp',
+ ),
'recreate' => false,
'createonly' => false,
'nocreate' => false,
),
),
'md5' => null,
- 'prependtext' => null,
- 'appendtext' => null,
+ 'prependtext' => array(
+ ApiBase::PARAM_TYPE => 'text',
+ ),
+ 'appendtext' => array(
+ ApiBase::PARAM_TYPE => 'text',
+ ),
'undo' => array(
ApiBase::PARAM_TYPE => 'integer'
),
),
'subject' => null,
'text' => array(
- ApiBase::PARAM_TYPE => 'string',
+ ApiBase::PARAM_TYPE => 'text',
ApiBase::PARAM_REQUIRED => true
),
'ccme' => false,
ApiBase::PARAM_DFLT => 'API',
),
'text' => array(
- ApiBase::PARAM_TYPE => 'string',
+ ApiBase::PARAM_TYPE => 'text',
ApiBase::PARAM_REQUIRED => true,
),
'revid' => array(
switch ( $type ) {
case 'submodule':
$groups[] = $name;
- $submodules = $module->getModuleManager()->getNames( $name );
+ if ( isset( $settings[ApiBase::PARAM_SUBMODULE_MAP] ) ) {
+ $map = $settings[ApiBase::PARAM_SUBMODULE_MAP];
+ ksort( $map );
+ $submodules = array();
+ foreach ( $map as $v => $m ) {
+ $submodules[] = "[[Special:ApiHelp/{$m}|{$v}]]";
+ }
+ } else {
+ $submodules = $module->getModuleManager()->getNames( $name );
+ sort( $submodules );
+ $prefix = $module->isMain()
+ ? '' : ( $module->getModulePath() . '+' );
+ $submodules = array_map( function ( $name ) use ( $prefix ) {
+ return "[[Special:ApiHelp/{$prefix}{$name}|{$name}]]";
+ }, $submodules );
+ }
$count = count( $submodules );
- sort( $submodules );
- $prefix = $module->isMain()
- ? '' : ( $module->getModulePath() . '+' );
- $submodules = array_map( function ( $name ) use ( $prefix ) {
- return "[[Special:ApiHelp/{$prefix}{$name}|{$name}]]";
- }, $submodules );
$info[] = $context->msg( 'api-help-param-list' )
->params( $multi ? 2 : 1 )
->params( $context->getLanguage()->commaList( $submodules ) )
break;
case 'string':
+ case 'text':
// Displaying a type message here would be useless.
$type = null;
break;
// Add type. Messages for grep: api-help-param-type-limit
// api-help-param-type-integer api-help-param-type-boolean
// api-help-param-type-timestamp api-help-param-type-user
+ // api-help-param-type-password
if ( is_string( $type ) ) {
$msg = $context->msg( "api-help-param-type-$type" );
if ( !$msg->isDisabled() ) {
public function getAllowedParams() {
return array(
'name' => null,
- 'password' => null,
+ 'password' => array(
+ ApiBase::PARAM_TYPE => 'password',
+ ),
'domain' => null,
'token' => null,
);
),
'generator' => array(
ApiBase::PARAM_TYPE => null,
- ApiBase::PARAM_VALUE_LINKS => array(),
ApiBase::PARAM_HELP_MSG => 'api-pageset-param-generator',
+ ApiBase::PARAM_SUBMODULE_PARAM_PREFIX => 'g',
),
'redirects' => array(
ApiBase::PARAM_DFLT => false,
if ( !$this->mAllowGenerator ) {
unset( $result['generator'] );
} elseif ( $flags & ApiBase::GET_VALUES_FOR_HELP ) {
- foreach ( $this->getGenerators() as $g ) {
- $result['generator'][ApiBase::PARAM_TYPE][] = $g;
- $result['generator'][ApiBase::PARAM_VALUE_LINKS][$g] = "Special:ApiHelp/query+$g";
- }
+ $result['generator'][ApiBase::PARAM_TYPE] = 'submodule';
+ $result['generator'][ApiBase::PARAM_SUBMODULE_MAP] = $this->getGenerators();
}
return $result;
$query = $this->getMain()->getModuleManager()->getModule( 'query' );
}
$gens = array();
+ $prefix = $query->getModulePath() . '+';
$mgr = $query->getModuleManager();
foreach ( $mgr->getNamesWithClasses() as $name => $class ) {
if ( is_subclass_of( $class, 'ApiQueryGeneratorBase' ) ) {
- $gens[] = $name;
+ $gens[$name] = $prefix . $name;
}
}
- sort( $gens );
+ ksort( $gens );
self::$generators = $gens;
}
if ( isset( $settings[ApiBase::PARAM_DFLT] ) ) {
switch ( $settings[ApiBase::PARAM_TYPE] ) {
case 'boolean':
- $item['default'] = ( $settings[ApiBase::PARAM_DFLT] ? 'true' : 'false' );
+ $item['default'] = (bool)$settings[ApiBase::PARAM_DFLT];
break;
case 'string':
+ case 'text':
+ case 'password':
$item['default'] = strval( $settings[ApiBase::PARAM_DFLT] );
break;
case 'integer':
+ case 'limit':
$item['default'] = intval( $settings[ApiBase::PARAM_DFLT] );
break;
+ case 'timestamp':
+ $item['default'] = wfTimestamp( TS_ISO_8601, $settings[ApiBase::PARAM_DFLT] );
+ break;
default:
$item['default'] = $settings[ApiBase::PARAM_DFLT];
break;
if ( isset( $settings[ApiBase::PARAM_TYPE] ) ) {
if ( $settings[ApiBase::PARAM_TYPE] === 'submodule' ) {
- $item['type'] = $module->getModuleManager()->getNames( $name );
- sort( $item['type'] );
- $item['submodules'] = true;
+ if ( isset( $settings[ApiBase::PARAM_SUBMODULE_MAP] ) ) {
+ ksort( $settings[ApiBase::PARAM_SUBMODULE_MAP] );
+ $item['type'] = array_keys( $settings[ApiBase::PARAM_SUBMODULE_MAP] );
+ $item['submodules'] = $settings[ApiBase::PARAM_SUBMODULE_MAP];
+ } else {
+ $item['type'] = $module->getModuleManager()->getNames( $name );
+ sort( $item['type'] );
+ $prefix = $module->isMain()
+ ? '' : ( $module->getModulePath() . '+' );
+ $item['submodules'] = array();
+ foreach ( $item['type'] as $v ) {
+ $item['submodules'][$v] = $prefix.$v;
+ }
+ }
+ if ( isset( $settings[ApiBase::PARAM_SUBMODULE_PARAM_PREFIX] ) ) {
+ $item['submoduleparamprefix'] = $settings[ApiBase::PARAM_SUBMODULE_PARAM_PREFIX];
+ }
} else {
$item['type'] = $settings[ApiBase::PARAM_TYPE];
}
if ( isset( $settings[ApiBase::PARAM_MIN] ) ) {
$item['min'] = $settings[ApiBase::PARAM_MIN];
}
+ if ( !empty( $settings[ApiBase::PARAM_RANGE_ENFORCE] ) ) {
+ $item['enforcerange'] = true;
+ }
if ( !empty( $settings[ApiBase::PARAM_HELP_MSG_INFO] ) ) {
$item['info'] = array();
public function getAllowedParams() {
return array(
'title' => null,
- 'text' => null,
+ 'text' => array(
+ ApiBase::PARAM_TYPE => 'text',
+ ),
'summary' => null,
'page' => null,
'pageid' => array(
ApiBase::PARAM_TYPE => 'string'
),
'text' => array(
- ApiBase::PARAM_TYPE => 'string',
+ ApiBase::PARAM_TYPE => 'text',
ApiBase::PARAM_REQUIRED => true
),
'contentmodel' => array(
'comment' => array(
ApiBase::PARAM_DFLT => ''
),
- 'text' => null,
+ 'text' => array(
+ ApiBase::PARAM_TYPE => 'text',
+ ),
'watch' => array(
ApiBase::PARAM_DFLT => false,
ApiBase::PARAM_DEPRECATED => true,
"api-help-param-deprecated": "Deprecated.",
"api-help-param-required": "This parameter is required.",
"api-help-datatypes-header": "Data types",
- "api-help-datatypes": "Some parameter types in API requests need further explanation:\n;boolean\n:Boolean parameters work like HTML checkboxes: if the parameter is specified, regardless of value, it is considered true. For a false value, omit the parameter entirely.\n;timestamp\n:Timestamps may be specified in several formats. ISO 8601 date and time is recommended. All times are in UTC, any included timezone is ignored.\n:* ISO 8601 date and time, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd> (punctuation and <kbd>Z</kbd> are optional)\n:* ISO 8601 date and time with (ignored) fractional seconds, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd> (dashes, colons, and <kbd>Z</kbd> are optional)\n:* MediaWiki format, <kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* Generic numeric format, <kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd> (optional timezone of <kbd>GMT</kbd>, <kbd>+<var>##</var></kbd>, or <kbd>-<var>##</var></kbd> is ignored)\n:* EXIF format, <kbd><var>2001</var>:<var>01</var>:<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:*RFC 2822 format (timezone may be omitted), <kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* RFC 850 format (timezone may be omitted), <kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* C ctime format, <kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* Seconds since 1970-01-01T00:00:00Z as a 1 to 13 digit integer",
+ "api-help-datatypes": "Some parameter types in API requests need further explanation:\n;boolean\n:Boolean parameters work like HTML checkboxes: if the parameter is specified, regardless of value, it is considered true. For a false value, omit the parameter entirely.\n;timestamp\n:Timestamps may be specified in several formats. ISO 8601 date and time is recommended. All times are in UTC, any included timezone is ignored.\n:* ISO 8601 date and time, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd> (punctuation and <kbd>Z</kbd> are optional)\n:* ISO 8601 date and time with (ignored) fractional seconds, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd> (dashes, colons, and <kbd>Z</kbd> are optional)\n:* MediaWiki format, <kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* Generic numeric format, <kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd> (optional timezone of <kbd>GMT</kbd>, <kbd>+<var>##</var></kbd>, or <kbd>-<var>##</var></kbd> is ignored)\n:* EXIF format, <kbd><var>2001</var>:<var>01</var>:<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:*RFC 2822 format (timezone may be omitted), <kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* RFC 850 format (timezone may be omitted), <kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* C ctime format, <kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* Seconds since 1970-01-01T00:00:00Z as a 1 to 13 digit integer (excluding <kbd>0</kbd>)\n:* The string <kbd>now</kbd>",
"api-help-param-type-limit": "Type: integer or <kbd>max</kbd>",
"api-help-param-type-integer": "Type: {{PLURAL:$1|1=integer|2=list of integers}}",
"api-help-param-type-boolean": "Type: boolean ([[Special:ApiHelp/main#main/datatypes|details]])",
+ "api-help-param-type-password": "",
"api-help-param-type-timestamp": "Type: {{PLURAL:$1|1=timestamp|2=list of timestamps}} ([[Special:ApiHelp/main#main/datatypes|allowed formats]])",
"api-help-param-type-user": "Type: {{PLURAL:$1|1=user name|2=list of user names}}",
"api-help-param-list": "{{PLURAL:$1|1=One value|2=Values (separate with <kbd>{{!}}</kbd>)}}: $2",
"api-help-param-type-limit": "{{technical}} {{doc-important|Do not translate text inside <kbd%gt; tags}} Used to indicate that a parameter is a \"limit\" type. Parameters:\n* $1 - Always 1.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
"api-help-param-type-integer": "{{technical}} Used to indicate that a parameter is an integer or list of integers. Parameters:\n* $1 - 1 if the parameter takes one value, 2 if the parameter takes a list of values.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
"api-help-param-type-boolean": "{{technical}} {{doc-important|Do not translate <code>Special:ApiHelp</code> in this message.}} Used to indicate that a parameter is a boolean. Parameters:\n* $1 - Always 1.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
+ "api-help-param-type-password": "{{optional}}{{technical}} Used to indicate that a parameter is a password or list of passwords. Parameters:\n* $1 - 1 if the parameter takes one value, 2 if the parameter takes a list of values.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
"api-help-param-type-timestamp": "{{technical}} {{doc-important|Do not translate <code>Special:ApiHelp</code> in this message.}} Used to indicate that a parameter is a timestamp or list of timestamps. Parameters:\n* $1 - 1 if the parameter takes one value, 2 if the parameter takes a list of values.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
"api-help-param-type-user": "{{technical}} Used to indicate that a parameter is a username or list of usernames. Parameters:\n* $1 - 1 if the parameter takes one value, 2 if the parameter takes a list of values.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
"api-help-param-list": "Used to display the possible values for a parameter taking a list of values\n\nParameters:\n* $1 - 1 if the parameter takes one value, 2 if the parameter takes any number of values\n* $2 - Comma-separated list of values, possibly formatted using {{msg-mw|api-help-param-list-can-be-empty}}\n{{Identical|Value}}",