"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "includes/api/ApiBase.php" between
mediawiki-1.31.1.tar.gz and mediawiki-1.32.0.tar.gz

About: MediaWiki is a wiki engine (the collaborative editing software that runs for e.g. Wikipedia, the free encyclopedia).

ApiBase.php  (mediawiki-1.31.1):ApiBase.php  (mediawiki-1.32.0)
skipping to change at line 229 skipping to change at line 229
* @since 1.31 * @since 1.31
*/ */
const PARAM_MAX_BYTES = 23; const PARAM_MAX_BYTES = 23;
/** /**
* (integer) Maximum length of a string in characters (unicode codepoints ). * (integer) Maximum length of a string in characters (unicode codepoints ).
* @since 1.31 * @since 1.31
*/ */
const PARAM_MAX_CHARS = 24; const PARAM_MAX_CHARS = 24;
/**
* (array) Indicate that this is a templated parameter, and specify repla
cements. Keys are the
* placeholders in the parameter name and values are the names of (unpref
ixed) parameters from
* which the replacement values are taken.
*
* For example, a parameter "foo-{ns}-{title}" could be defined with
* PARAM_TEMPLATE_VARS => [ 'ns' => 'namespaces', 'title' => 'titles' ].
Then a query for
* namespaces=0|1&titles=X|Y would support parameters foo-0-X, foo-0-Y, f
oo-1-X, and foo-1-Y.
*
* All placeholders must be present in the parameter's name. Each target
parameter must have
* PARAM_ISMULTI true. If a target is itself a templated parameter, its P
ARAM_TEMPLATE_VARS must
* be a subset of the referring parameter's, mapping the same placeholder
s to the same targets.
* A parameter cannot target itself.
*
* @since 1.32
*/
const PARAM_TEMPLATE_VARS = 25;
/**@}*/ /**@}*/
const ALL_DEFAULT_STRING = '*'; const ALL_DEFAULT_STRING = '*';
/** Fast query, standard limit. */ /** Fast query, standard limit. */
const LIMIT_BIG1 = 500; const LIMIT_BIG1 = 500;
/** Fast query, apihighlimits limit. */ /** Fast query, apihighlimits limit. */
const LIMIT_BIG2 = 5000; const LIMIT_BIG2 = 5000;
/** Slow query, standard limit. */ /** Slow query, standard limit. */
const LIMIT_SML1 = 50; const LIMIT_SML1 = 50;
skipping to change at line 746 skipping to change at line 764
return $this->mModulePrefix . $paramName; return $this->mModulePrefix . $paramName;
} }
} }
/** /**
* Using getAllowedParams(), this function makes an array of the values * Using getAllowedParams(), this function makes an array of the values
* provided by the user, with key being the name of the variable, and * provided by the user, with key being the name of the variable, and
* value - validated value from user or default. limits will not be * value - validated value from user or default. limits will not be
* parsed if $parseLimit is set to false; use this when the max * parsed if $parseLimit is set to false; use this when the max
* limit is not definitive yet, e.g. when getting revisions. * limit is not definitive yet, e.g. when getting revisions.
* @param bool $parseLimit True by default * @param bool|array $options If a boolean, uses that as the value for 'p
arseLimit'
* - parseLimit: (bool, default true) Whether to parse the 'max' value f
or limit types
* - safeMode: (bool, default false) If true, avoid throwing for paramet
er validation errors.
* Returned parameter values might be ApiUsageException instances.
* @return array * @return array
*/ */
public function extractRequestParams( $parseLimit = true ) { public function extractRequestParams( $options = [] ) {
if ( is_bool( $options ) ) {
$options = [ 'parseLimit' => $options ];
}
$options += [
'parseLimit' => true,
'safeMode' => false,
];
$parseLimit = (bool)$options['parseLimit'];
// Cache parameters, for performance and to avoid T26564. // Cache parameters, for performance and to avoid T26564.
if ( !isset( $this->mParamCache[$parseLimit] ) ) { if ( !isset( $this->mParamCache[$parseLimit] ) ) {
$params = $this->getFinalParams(); $params = $this->getFinalParams() ?: [];
$results = []; $results = [];
$warned = [];
// Process all non-templates and save templates for secon
dary
// processing.
$toProcess = [];
foreach ( $params as $paramName => $paramSettings ) {
if ( isset( $paramSettings[self::PARAM_TEMPLATE_V
ARS] ) ) {
$toProcess[] = [ $paramName, $paramSettin
gs[self::PARAM_TEMPLATE_VARS], $paramSettings ];
} else {
try {
$results[$paramName] = $this->get
ParameterFromSettings(
$paramName, $paramSetting
s, $parseLimit
);
} catch ( ApiUsageException $ex ) {
$results[$paramName] = $ex;
}
}
}
// Now process all the templates by successively replacin
g the
// placeholders with all client-supplied values.
// This bit duplicates JavaScript logic in
// ApiSandbox.PageLayout.prototype.updateTemplatedParams(
).
// If you update this, see if that needs updating too.
while ( $toProcess ) {
list( $name, $targets, $settings ) = array_shift(
$toProcess );
foreach ( $targets as $placeholder => $target ) {
if ( !array_key_exists( $target, $results
) ) {
// The target wasn't processed ye
t, try the next one.
// If all hit this case, the para
meter has no expansions.
continue;
}
if ( !is_array( $results[$target] ) || !$
results[$target] ) {
// The target was processed but h
as no (valid) values.
// That means it has no expansion
s.
break;
}
// Expand this target in the name and all
other targets,
// then requeue if there are more targets
left or put in
// $results if all are done.
unset( $targets[$placeholder] );
$placeholder = '{' . $placeholder . '}';
foreach ( $results[$target] as $value ) {
if ( !preg_match( '/^[^{}]*$/', $
value ) ) {
// Skip values that make
invalid parameter names.
$encTargetName = $this->e
ncodeParamName( $target );
if ( !isset( $warned[$enc
TargetName][$value] ) ) {
$warned[$encTarge
tName][$value] = true;
$this->addWarning
( [
'apiwarn-
ignoring-invalid-templated-value',
wfEscapeW
ikiText( $encTargetName ),
wfEscapeW
ikiText( $value ),
] );
}
continue;
}
if ( $params ) { // getFinalParams() can return false $newName = str_replace( $placehol
foreach ( $params as $paramName => $paramSettings der, $value, $name );
) { if ( !$targets ) {
$results[$paramName] = $this->getParamete try {
rFromSettings( $results[$newName
$paramName, $paramSettings, $pars ] = $this->getParameterFromSettings( $newName, $settings, $parseLimit );
eLimit ); } catch ( ApiUsageExcepti
on $ex ) {
$results[$newName
] = $ex;
}
} else {
$newTargets = [];
foreach ( $targets as $k
=> $v ) {
$newTargets[$k] =
str_replace( $placeholder, $value, $v );
}
$toProcess[] = [ $newName
, $newTargets, $settings ];
}
}
break;
} }
} }
$this->mParamCache[$parseLimit] = $results; $this->mParamCache[$parseLimit] = $results;
} }
$ret = $this->mParamCache[$parseLimit];
if ( !$options['safeMode'] ) {
foreach ( $ret as $v ) {
if ( $v instanceof ApiUsageException ) {
throw $v;
}
}
}
return $this->mParamCache[$parseLimit]; return $this->mParamCache[$parseLimit];
} }
/** /**
* Get a value for the given parameter * Get a value for the given parameter
* @param string $paramName Parameter name * @param string $paramName Parameter name
* @param bool $parseLimit See extractRequestParams() * @param bool $parseLimit See extractRequestParams()
* @return mixed Parameter value * @return mixed Parameter value
*/ */
protected function getParameter( $paramName, $parseLimit = true ) { protected function getParameter( $paramName, $parseLimit = true ) {
$paramSettings = $this->getFinalParams()[$paramName]; $ret = $this->extractRequestParams( [
'parseLimit' => $parseLimit,
return $this->getParameterFromSettings( $paramName, $paramSetting 'safeMode' => true,
s, $parseLimit ); ] )[$paramName];
if ( $ret instanceof ApiUsageException ) {
throw $ret;
}
return $ret;
} }
/** /**
* Die if none or more than one of a certain set of parameters is set and not false. * Die if none or more than one of a certain set of parameters is set and not false.
* *
* @param array $params User provided set of parameters, as from $this->e xtractRequestParams() * @param array $params User provided set of parameters, as from $this->e xtractRequestParams()
* @param string $required,... Names of parameters of which exactly one m ust be set * @param string $required,... Names of parameters of which exactly one m ust be set
*/ */
public function requireOnlyOneParameter( $params, $required /*...*/ ) { public function requireOnlyOneParameter( $params, $required /*...*/ ) {
$required = func_get_args(); $required = func_get_args();
skipping to change at line 987 skipping to change at line 1103
} }
} }
return $titleObj; return $titleObj;
} }
/** /**
* Return true if we're to watch the page, false if not, null if no chang e. * Return true if we're to watch the page, false if not, null if no chang e.
* @param string $watchlist Valid values: 'watch', 'unwatch', 'preference s', 'nochange' * @param string $watchlist Valid values: 'watch', 'unwatch', 'preference s', 'nochange'
* @param Title $titleObj The page under consideration * @param Title $titleObj The page under consideration
* @param string $userOption The user option to consider when $watchlist= preferences. * @param string|null $userOption The user option to consider when $watch list=preferences.
* If not set will use watchdefault always and watchcreations if $titl eObj doesn't exist. * If not set will use watchdefault always and watchcreations if $titl eObj doesn't exist.
* @return bool * @return bool
*/ */
protected function getWatchlistValue( $watchlist, $titleObj, $userOption = null ) { protected function getWatchlistValue( $watchlist, $titleObj, $userOption = null ) {
$userWatching = $this->getUser()->isWatched( $titleObj, User::IGN ORE_USER_RIGHTS ); $userWatching = $this->getUser()->isWatched( $titleObj, User::IGN ORE_USER_RIGHTS );
switch ( $watchlist ) { switch ( $watchlist ) {
case 'watch': case 'watch':
return true; return true;
skipping to change at line 1043 skipping to change at line 1159
// Some classes may decide to change parameter names // Some classes may decide to change parameter names
$encParamName = $this->encodeParamName( $paramName ); $encParamName = $this->encodeParamName( $paramName );
// Shorthand // Shorthand
if ( !is_array( $paramSettings ) ) { if ( !is_array( $paramSettings ) ) {
$paramSettings = [ $paramSettings = [
self::PARAM_DFLT => $paramSettings, self::PARAM_DFLT => $paramSettings,
]; ];
} }
$default = isset( $paramSettings[self::PARAM_DFLT] ) $default = $paramSettings[self::PARAM_DFLT] ?? null;
? $paramSettings[self::PARAM_DFLT] $multi = $paramSettings[self::PARAM_ISMULTI] ?? false;
: null; $multiLimit1 = $paramSettings[self::PARAM_ISMULTI_LIMIT1] ?? null
$multi = isset( $paramSettings[self::PARAM_ISMULTI] ) ;
? $paramSettings[self::PARAM_ISMULTI] $multiLimit2 = $paramSettings[self::PARAM_ISMULTI_LIMIT2] ?? null
: false; ;
$multiLimit1 = isset( $paramSettings[self::PARAM_ISMULTI_LIMIT1] $type = $paramSettings[self::PARAM_TYPE] ?? null;
) $dupes = $paramSettings[self::PARAM_ALLOW_DUPLICATES] ?? false;
? $paramSettings[self::PARAM_ISMULTI_LIMIT1] $deprecated = $paramSettings[self::PARAM_DEPRECATED] ?? false;
: null; $deprecatedValues = $paramSettings[self::PARAM_DEPRECATED_VALUES]
$multiLimit2 = isset( $paramSettings[self::PARAM_ISMULTI_LIMIT2] ?? [];
) $required = $paramSettings[self::PARAM_REQUIRED] ?? false;
? $paramSettings[self::PARAM_ISMULTI_LIMIT2] $allowAll = $paramSettings[self::PARAM_ALL] ?? false;
: null;
$type = isset( $paramSettings[self::PARAM_TYPE] )
? $paramSettings[self::PARAM_TYPE]
: null;
$dupes = isset( $paramSettings[self::PARAM_ALLOW_DUPLICATES] )
? $paramSettings[self::PARAM_ALLOW_DUPLICATES]
: false;
$deprecated = isset( $paramSettings[self::PARAM_DEPRECATED] )
? $paramSettings[self::PARAM_DEPRECATED]
: false;
$deprecatedValues = isset( $paramSettings[self::PARAM_DEPRECATED_
VALUES] )
? $paramSettings[self::PARAM_DEPRECATED_VALUES]
: [];
$required = isset( $paramSettings[self::PARAM_REQUIRED] )
? $paramSettings[self::PARAM_REQUIRED]
: false;
$allowAll = isset( $paramSettings[self::PARAM_ALL] )
? $paramSettings[self::PARAM_ALL]
: false;
// When type is not given, and no choices, the type is the same a s $default // When type is not given, and no choices, the type is the same a s $default
if ( !isset( $type ) ) { if ( !isset( $type ) ) {
if ( isset( $default ) ) { if ( isset( $default ) ) {
$type = gettype( $default ); $type = gettype( $default );
} else { } else {
$type = 'NULL'; // allow everything $type = 'NULL'; // allow everything
} }
} }
skipping to change at line 1153 skipping to change at line 1249
$request = $this->getMain()->getRequest(); $request = $this->getMain()->getRequest();
$rawValue = $request->getRawVal( $encParamName ); $rawValue = $request->getRawVal( $encParamName );
if ( $rawValue === null ) { if ( $rawValue === null ) {
$rawValue = $default; $rawValue = $default;
} }
// Preserve U+001F for self::parseMultiValue(), or error out if that won't be called // Preserve U+001F for self::parseMultiValue(), or error out if that won't be called
if ( isset( $value ) && substr( $rawValue, 0, 1 ) === "\x 1f" ) { if ( isset( $value ) && substr( $rawValue, 0, 1 ) === "\x 1f" ) {
if ( $multi ) { if ( $multi ) {
// This loses the potential $wgContLang-> // This loses the potential checkTitleEnc
checkTitleEncoding() transformation oding() transformation done by
// done by WebRequest for $_GET. Let's ca // WebRequest for $_GET. Let's call that
ll that a feature. a feature.
$value = implode( "\x1f", $request->norma lizeUnicode( explode( "\x1f", $rawValue ) ) ); $value = implode( "\x1f", $request->norma lizeUnicode( explode( "\x1f", $rawValue ) ) );
} else { } else {
$this->dieWithError( 'apierror-badvalue-n otmultivalue', 'badvalue_notmultivalue' ); $this->dieWithError( 'apierror-badvalue-n otmultivalue', 'badvalue_notmultivalue' );
} }
} }
// Check for NFC normalization, and warn // Check for NFC normalization, and warn
if ( $rawValue !== $value ) { if ( $rawValue !== $value ) {
$this->handleParamNormalization( $paramName, $val ue, $rawValue ); $this->handleParamNormalization( $paramName, $val ue, $rawValue );
} }
skipping to change at line 1196 skipping to change at line 1292
// More validation only when choices were not given // More validation only when choices were not given
// choices were validated in parseMultiValue() // choices were validated in parseMultiValue()
if ( !is_array( $type ) ) { if ( !is_array( $type ) ) {
switch ( $type ) { switch ( $type ) {
case 'NULL': // nothing to do case 'NULL': // nothing to do
break; break;
case 'string': case 'string':
case 'text': case 'text':
case 'password': case 'password':
if ( $required && $value === '' ) { if ( $required && $value === '' ) {
$this->dieWithError( [ 'a pierror-missingparam', $paramName ] ); $this->dieWithError( [ 'a pierror-missingparam', $encParamName ] );
} }
break; break;
case 'integer': // Force everything using intval() and optionally validate limits case 'integer': // Force everything using intval() and optionally validate limits
$min = isset( $paramSettings[self $min = $paramSettings[self::PARAM
::PARAM_MIN] ) ? $paramSettings[self::PARAM_MIN] : null; _MIN] ?? null;
$max = isset( $paramSettings[self $max = $paramSettings[self::PARAM
::PARAM_MAX] ) ? $paramSettings[self::PARAM_MAX] : null; _MAX] ?? null;
$enforceLimits = isset( $paramSet $enforceLimits = $paramSettings[s
tings[self::PARAM_RANGE_ENFORCE] ) elf::PARAM_RANGE_ENFORCE] ?? false;
? $paramSettings[self::PA
RAM_RANGE_ENFORCE] : false;
if ( is_array( $value ) ) { if ( is_array( $value ) ) {
$value = array_map( 'intv al', $value ); $value = array_map( 'intv al', $value );
if ( !is_null( $min ) || !is_null( $max ) ) { if ( !is_null( $min ) || !is_null( $max ) ) {
foreach ( $value as &$v ) { foreach ( $value as &$v ) {
$this->va lidateLimit( $paramName, $v, $min, $max, null, $enforceLimits ); $this->va lidateLimit( $paramName, $v, $min, $max, null, $enforceLimits );
} }
} }
} else { } else {
$value = intval( $value ) ; $value = intval( $value ) ;
skipping to change at line 1235 skipping to change at line 1330
|| !isset( $paramSettings [self::PARAM_MAX2] ) || !isset( $paramSettings [self::PARAM_MAX2] )
) { ) {
self::dieDebug( self::dieDebug(
__METHOD__, __METHOD__,
"MAX1 or MAX2 are not defined for the limit $encParamName" "MAX1 or MAX2 are not defined for the limit $encParamName"
); );
} }
if ( $multi ) { if ( $multi ) {
self::dieDebug( __METHOD_ _, "Multi-values not supported for $encParamName" ); self::dieDebug( __METHOD_ _, "Multi-values not supported for $encParamName" );
} }
$min = isset( $paramSettings[self ::PARAM_MIN] ) ? $paramSettings[self::PARAM_MIN] : 0; $min = $paramSettings[self::PARAM _MIN] ?? 0;
if ( $value == 'max' ) { if ( $value == 'max' ) {
$value = $this->getMain() ->canApiHighLimits() $value = $this->getMain() ->canApiHighLimits()
? $paramSettings[ self::PARAM_MAX2] ? $paramSettings[ self::PARAM_MAX2]
: $paramSettings[ self::PARAM_MAX]; : $paramSettings[ self::PARAM_MAX];
$this->getResult()->addPa rsedLimit( $this->getModuleName(), $value ); $this->getResult()->addPa rsedLimit( $this->getModuleName(), $value );
} else { } else {
$value = intval( $value ) ; $value = intval( $value ) ;
$this->validateLimit( $this->validateLimit(
$paramName, $paramName,
$value, $value,
skipping to change at line 1351 skipping to change at line 1446
} }
foreach ( $usedDeprecatedValues as $v ) { foreach ( $usedDeprecatedValues as $v ) {
$msg = $deprecatedValues[$v]; $msg = $deprecatedValues[$v];
if ( $msg === true ) { if ( $msg === true ) {
$msg = [ 'apiwarn-deprecation-par ameter', "$encParamName=$v" ]; $msg = [ 'apiwarn-deprecation-par ameter', "$encParamName=$v" ];
} }
$this->addDeprecation( $msg, "$feature$v" ); $this->addDeprecation( $msg, "$feature$v" );
} }
} }
} elseif ( $required ) { } elseif ( $required ) {
$this->dieWithError( [ 'apierror-missingparam', $paramNam e ] ); $this->dieWithError( [ 'apierror-missingparam', $encParam Name ] );
} }
return $value; return $value;
} }
/** /**
* Handle when a parameter was Unicode-normalized * Handle when a parameter was Unicode-normalized
* @since 1.28 * @since 1.28
* @param string $paramName Unprefixed parameter name * @param string $paramName Unprefixed parameter name
* @param string $value Input that will be used. * @param string $value Input that will be used.
skipping to change at line 1426 skipping to change at line 1521
$sizeLimit = count( $valuesList ) > $limit1 && $this->mMainModule ->canApiHighLimits() $sizeLimit = count( $valuesList ) > $limit1 && $this->mMainModule ->canApiHighLimits()
? $limit2 ? $limit2
: $limit1; : $limit1;
if ( $allowMultiple && is_array( $allowedValues ) && $allSpecifie r && if ( $allowMultiple && is_array( $allowedValues ) && $allSpecifie r &&
count( $valuesList ) === 1 && $valuesList[0] === $allSpec ifier count( $valuesList ) === 1 && $valuesList[0] === $allSpec ifier
) { ) {
return $allowedValues; return $allowedValues;
} }
if ( self::truncateArray( $valuesList, $sizeLimit ) ) { if ( count( $valuesList ) > $sizeLimit ) {
$this->addDeprecation( $this->dieWithError(
[ 'apiwarn-toomanyvalues', $valueName, $sizeLimit [ 'apierror-toomanyvalues', $valueName, $sizeLimi
], t ],
"too-many-$valueName-for-{$this->getModulePath()} "too-many-$valueName"
"
); );
} }
if ( !$allowMultiple && count( $valuesList ) != 1 ) { if ( !$allowMultiple && count( $valuesList ) != 1 ) {
// T35482 - Allow entries with | in them for non-multiple values // T35482 - Allow entries with | in them for non-multiple values
if ( in_array( $value, $allowedValues, true ) ) { if ( in_array( $value, $allowedValues, true ) ) {
return $value; return $value;
} }
$values = array_map( function ( $v ) { $values = array_map( function ( $v ) {
skipping to change at line 1482 skipping to change at line 1577
return $allowMultiple ? $valuesList : $valuesList[0]; return $allowMultiple ? $valuesList : $valuesList[0];
} }
/** /**
* Validate the value against the minimum and user/bot maximum limits. * Validate the value against the minimum and user/bot maximum limits.
* Prints usage info on failure. * Prints usage info on failure.
* @param string $paramName Parameter name * @param string $paramName Parameter name
* @param int &$value Parameter value * @param int &$value Parameter value
* @param int|null $min Minimum value * @param int|null $min Minimum value
* @param int|null $max Maximum value for users * @param int|null $max Maximum value for users
* @param int $botMax Maximum value for sysops/bots * @param int|null $botMax Maximum value for sysops/bots
* @param bool $enforceLimits Whether to enforce (die) if value is outsid e limits * @param bool $enforceLimits Whether to enforce (die) if value is outsid e limits
*/ */
protected function validateLimit( $paramName, &$value, $min, $max, $botMa x = null, protected function validateLimit( $paramName, &$value, $min, $max, $botMa x = null,
$enforceLimits = false $enforceLimits = false
) { ) {
if ( !is_null( $min ) && $value < $min ) { if ( !is_null( $min ) && $value < $min ) {
$msg = ApiMessage::create( $msg = ApiMessage::create(
[ 'apierror-integeroutofrange-belowminimum', [ 'apierror-integeroutofrange-belowminimum',
$this->encodeParamName( $paramName ), $mi n, $value ], $this->encodeParamName( $paramName ), $mi n, $value ],
'integeroutofrange', 'integeroutofrange',
skipping to change at line 1615 skipping to change at line 1710
* Validate and normalize parameters of type 'user' * Validate and normalize parameters of type 'user'
* @param string $value Parameter value * @param string $value Parameter value
* @param string $encParamName Parameter name * @param string $encParamName Parameter name
* @return string Validated and normalized parameter * @return string Validated and normalized parameter
*/ */
private function validateUser( $value, $encParamName ) { private function validateUser( $value, $encParamName ) {
if ( ExternalUserNames::isExternal( $value ) && User::newFromName ( $value, false ) ) { if ( ExternalUserNames::isExternal( $value ) && User::newFromName ( $value, false ) ) {
return $value; return $value;
} }
$titleObj = Title::makeTitleSafe( NS_USER, $value ); $name = User::getCanonicalName( $value, 'valid' );
if ( $name !== false ) {
if ( $titleObj ) { return $name;
$value = $titleObj->getText();
} }
if ( if (
!User::isValidUserName( $value ) &&
// We allow ranges as well, for blocks. // We allow ranges as well, for blocks.
!IP::isIPAddress( $value ) && IP::isIPAddress( $value ) ||
// See comment for User::isIP. We don't just call that f unction // See comment for User::isIP. We don't just call that f unction
// here because it also returns true for things like // here because it also returns true for things like
// 300.300.300.300 that are neither valid usernames nor v alid IP // 300.300.300.300 that are neither valid usernames nor v alid IP
// addresses. // addresses.
!preg_match( preg_match(
'/^' . RE_IP_BYTE . '\.' . RE_IP_BYTE . '\.' . RE _IP_BYTE . '\.xxx$/', '/^' . RE_IP_BYTE . '\.' . RE_IP_BYTE . '\.' . RE _IP_BYTE . '\.xxx$/',
$value $value
) )
) { ) {
$this->dieWithError( return IP::sanitizeIP( $value );
[ 'apierror-baduser', $encParamName, wfEscapeWiki
Text( $value ) ],
"baduser_{$encParamName}"
);
} }
return $value; $this->dieWithError(
[ 'apierror-baduser', $encParamName, wfEscapeWikiText( $v
alue ) ],
"baduser_{$encParamName}"
);
} }
/**@}*/ /**@}*/
/************************************************************************ //** /************************************************************************ //**
* @name Utility methods * @name Utility methods
* @{ * @{
*/ */
/** /**
* Set a watch (or unwatch) based the based on a watchlist parameter. * Set a watch (or unwatch) based the based on a watchlist parameter.
* @param string $watch Valid values: 'watch', 'unwatch', 'preferences', 'nochange' * @param string $watch Valid values: 'watch', 'unwatch', 'preferences', 'nochange'
* @param Title $titleObj The article's title to change * @param Title $titleObj The article's title to change
* @param string $userOption The user option to consider when $watch=pref erences * @param string|null $userOption The user option to consider when $watch =preferences
*/ */
protected function setWatch( $watch, $titleObj, $userOption = null ) { protected function setWatch( $watch, $titleObj, $userOption = null ) {
$value = $this->getWatchlistValue( $watch, $titleObj, $userOption ); $value = $this->getWatchlistValue( $watch, $titleObj, $userOption );
if ( $value === null ) { if ( $value === null ) {
return; return;
} }
WatchAction::doWatchOrUnwatch( $value, $titleObj, $this->getUser( ) ); WatchAction::doWatchOrUnwatch( $value, $titleObj, $this->getUser( ) );
} }
/** /**
* Truncate an array to a certain length.
* @param array &$arr Array to truncate
* @param int $limit Maximum length
* @return bool True if the array was truncated, false otherwise
*/
public static function truncateArray( &$arr, $limit ) {
$modified = false;
while ( count( $arr ) > $limit ) {
array_pop( $arr );
$modified = true;
}
return $modified;
}
/**
* Gets the user for whom to get the watchlist * Gets the user for whom to get the watchlist
* *
* @param array $params * @param array $params
* @return User * @return User
*/ */
public function getWatchlistUser( $params ) { public function getWatchlistUser( $params ) {
if ( !is_null( $params['owner'] ) && !is_null( $params['token'] ) ) { if ( !is_null( $params['owner'] ) && !is_null( $params['token'] ) ) {
$user = User::newFromName( $params['owner'], false ); $user = User::newFromName( $params['owner'], false );
if ( !( $user && $user->getId() ) ) { if ( !( $user && $user->getId() ) ) {
$this->dieWithError( $this->dieWithError(
skipping to change at line 1738 skipping to change at line 1815
/** /**
* Create a Message from a string or array * Create a Message from a string or array
* *
* A string is used as a message key. An array has the message key as the * A string is used as a message key. An array has the message key as the
* first value and message parameters as subsequent values. * first value and message parameters as subsequent values.
* *
* @since 1.25 * @since 1.25
* @param string|array|Message $msg * @param string|array|Message $msg
* @param IContextSource $context * @param IContextSource $context
* @param array $params * @param array|null $params
* @return Message|null * @return Message|null
*/ */
public static function makeMessage( $msg, IContextSource $context, array $params = null ) { public static function makeMessage( $msg, IContextSource $context, array $params = null ) {
if ( is_string( $msg ) ) { if ( is_string( $msg ) ) {
$msg = wfMessage( $msg ); $msg = wfMessage( $msg );
} elseif ( is_array( $msg ) ) { } elseif ( is_array( $msg ) ) {
$msg = call_user_func_array( 'wfMessage', $msg ); $msg = wfMessage( ...$msg );
} }
if ( !$msg instanceof Message ) { if ( !$msg instanceof Message ) {
return null; return null;
} }
$msg->setContext( $context ); $msg->setContext( $context );
if ( $params ) { if ( $params ) {
$msg->params( $params ); $msg->params( $params );
} }
skipping to change at line 1792 skipping to change at line 1869
'autoblocked', 'autoblocked',
[ 'blockinfo' => ApiQueryUserInfo::getBlo ckInfo( $user->getBlock() ) ] [ 'blockinfo' => ApiQueryUserInfo::getBlo ckInfo( $user->getBlock() ) ]
) ); ) );
} elseif ( is_array( $error ) && $error[0] === 'systemblo ckedtext' && $user->getBlock() ) { } elseif ( is_array( $error ) && $error[0] === 'systemblo ckedtext' && $user->getBlock() ) {
$status->fatal( ApiMessage::create( $status->fatal( ApiMessage::create(
'apierror-systemblocked', 'apierror-systemblocked',
'blocked', 'blocked',
[ 'blockinfo' => ApiQueryUserInfo::getBlo ckInfo( $user->getBlock() ) ] [ 'blockinfo' => ApiQueryUserInfo::getBlo ckInfo( $user->getBlock() ) ]
) ); ) );
} else { } else {
call_user_func_array( [ $status, 'fatal' ], (arra y)$error ); $status->fatal( ...(array)$error );
} }
} }
return $status; return $status;
} }
/**
* Call wfTransactionalTimeLimit() if this request was POSTed
* @since 1.26
*/
protected function useTransactionalTimeLimit() {
if ( $this->getRequest()->wasPosted() ) {
wfTransactionalTimeLimit();
}
}
/**@}*/ /**@}*/
/************************************************************************ //** /************************************************************************ //**
* @name Warning and error reporting * @name Warning and error reporting
* @{ * @{
*/ */
/** /**
* Add a warning for this module. * Add a warning for this module.
* *
skipping to change at line 1877 skipping to change at line 1964
$this->getErrorFormatter()->addError( $this->getModulePath(), $ms g, $code, $data ); $this->getErrorFormatter()->addError( $this->getModulePath(), $ms g, $code, $data );
} }
/** /**
* Add warnings and/or errors from a Status * Add warnings and/or errors from a Status
* *
* @note If you want to abort processing, use self::dieStatus() instead. * @note If you want to abort processing, use self::dieStatus() instead.
* @since 1.29 * @since 1.29
* @param StatusValue $status * @param StatusValue $status
* @param string[] $types 'warning' and/or 'error' * @param string[] $types 'warning' and/or 'error'
* @param string[] $filter Message keys to filter out (since 1.32)
*/ */
public function addMessagesFromStatus( StatusValue $status, $types = [ 'w public function addMessagesFromStatus(
arning', 'error' ] ) { StatusValue $status, $types = [ 'warning', 'error' ], array $filt
$this->getErrorFormatter()->addMessagesFromStatus( $this->getModu er = []
lePath(), $status, $types ); ) {
$this->getErrorFormatter()->addMessagesFromStatus(
$this->getModulePath(), $status, $types, $filter
);
} }
/** /**
* Abort execution with an error * Abort execution with an error
* *
* If $msg is not an ApiMessage, the message code will be derived from th e * If $msg is not an ApiMessage, the message code will be derived from th e
* message key by stripping any "apiwarn-" or "apierror-" prefix. * message key by stripping any "apiwarn-" or "apierror-" prefix.
* *
* @since 1.29 * @since 1.29
* @param string|array|Message $msg See ApiErrorFormatter::addError() * @param string|array|Message $msg See ApiErrorFormatter::addError()
skipping to change at line 1971 skipping to change at line 2063
if ( $status->isGood() ) { if ( $status->isGood() ) {
throw new MWException( 'Successful status passed to ApiBa se::dieStatus' ); throw new MWException( 'Successful status passed to ApiBa se::dieStatus' );
} }
// ApiUsageException needs a fatal status, but this method has // ApiUsageException needs a fatal status, but this method has
// historically accepted any non-good status. Convert it if neces sary. // historically accepted any non-good status. Convert it if neces sary.
$status->setOK( false ); $status->setOK( false );
if ( !$status->getErrorsByType( 'error' ) ) { if ( !$status->getErrorsByType( 'error' ) ) {
$newStatus = Status::newGood(); $newStatus = Status::newGood();
foreach ( $status->getErrorsByType( 'warning' ) as $err ) { foreach ( $status->getErrorsByType( 'warning' ) as $err ) {
call_user_func_array( $newStatus->fatal( $err['message'], ...$err['para
[ $newStatus, 'fatal' ], ms'] );
array_merge( [ $err['message'] ], $err['p
arams'] )
);
} }
if ( !$newStatus->getErrorsByType( 'error' ) ) { if ( !$newStatus->getErrorsByType( 'error' ) ) {
$newStatus->fatal( 'unknownerror-nocode' ); $newStatus->fatal( 'unknownerror-nocode' );
} }
$status = $newStatus; $status = $newStatus;
} }
throw new ApiUsageException( $this, $status ); throw new ApiUsageException( $this, $status );
} }
skipping to change at line 2011 skipping to change at line 2100
* @param string|string[] $rights * @param string|string[] $rights
* @param User|null $user * @param User|null $user
* @throws ApiUsageException if the user doesn't have any of the rights. * @throws ApiUsageException if the user doesn't have any of the rights.
* The error message is based on $rights[0]. * The error message is based on $rights[0].
*/ */
public function checkUserRightsAny( $rights, $user = null ) { public function checkUserRightsAny( $rights, $user = null ) {
if ( !$user ) { if ( !$user ) {
$user = $this->getUser(); $user = $this->getUser();
} }
$rights = (array)$rights; $rights = (array)$rights;
if ( !call_user_func_array( [ $user, 'isAllowedAny' ], $rights ) ) { if ( !$user->isAllowedAny( ...$rights ) ) {
$this->dieWithError( [ 'apierror-permissiondenied', $this ->msg( "action-{$rights[0]}" ) ] ); $this->dieWithError( [ 'apierror-permissiondenied', $this ->msg( "action-{$rights[0]}" ) ] );
} }
} }
/** /**
* Helper function for permission-denied errors * Helper function for permission-denied errors
* @since 1.29 * @since 1.29
* @param Title $title * @param Title $title
* @param string|string[] $actions * @param string|string[] $actions
* @param User|null $user * @param User|null $user
skipping to change at line 2176 skipping to change at line 2265
* needed. * needed.
* *
* @since 1.25, returns Message[] rather than string[] * @since 1.25, returns Message[] rather than string[]
* @return Message[] * @return Message[]
*/ */
public function getFinalDescription() { public function getFinalDescription() {
$desc = $this->getDescription(); $desc = $this->getDescription();
// Avoid PHP 7.1 warning of passing $this by reference // Avoid PHP 7.1 warning of passing $this by reference
$apiModule = $this; $apiModule = $this;
Hooks::run( 'APIGetDescription', [ &$apiModule, &$desc ] ); Hooks::run( 'APIGetDescription', [ &$apiModule, &$desc ], '1.25' );
$desc = self::escapeWikiText( $desc ); $desc = self::escapeWikiText( $desc );
if ( is_array( $desc ) ) { if ( is_array( $desc ) ) {
$desc = implode( "\n", $desc ); $desc = implode( "\n", $desc );
} else { } else {
$desc = (string)$desc; $desc = (string)$desc;
} }
$summary = self::makeMessage( $this->getSummaryMessage(), $this-> getContext(), [ $summary = self::makeMessage( $this->getSummaryMessage(), $this-> getContext(), [
$this->getModulePrefix(), $this->getModulePrefix(),
$this->getModuleName(), $this->getModuleName(),
skipping to change at line 2240 skipping to change at line 2329
if ( $this->needsToken() ) { if ( $this->needsToken() ) {
$params['token'] = [ $params['token'] = [
self::PARAM_TYPE => 'string', self::PARAM_TYPE => 'string',
self::PARAM_REQUIRED => true, self::PARAM_REQUIRED => true,
self::PARAM_SENSITIVE => true, self::PARAM_SENSITIVE => true,
self::PARAM_HELP_MSG => [ self::PARAM_HELP_MSG => [
'api-help-param-token', 'api-help-param-token',
$this->needsToken(), $this->needsToken(),
], ],
] + ( isset( $params['token'] ) ? $params['token'] : [] ) ; ] + ( $params['token'] ?? [] );
} }
// Avoid PHP 7.1 warning of passing $this by reference // Avoid PHP 7.1 warning of passing $this by reference
$apiModule = $this; $apiModule = $this;
Hooks::run( 'APIGetAllowedParams', [ &$apiModule, &$params, $flag s ] ); Hooks::run( 'APIGetAllowedParams', [ &$apiModule, &$params, $flag s ] );
return $params; return $params;
} }
/** /**
skipping to change at line 2266 skipping to change at line 2355
*/ */
public function getFinalParamDescription() { public function getFinalParamDescription() {
$prefix = $this->getModulePrefix(); $prefix = $this->getModulePrefix();
$name = $this->getModuleName(); $name = $this->getModuleName();
$path = $this->getModulePath(); $path = $this->getModulePath();
$desc = $this->getParamDescription(); $desc = $this->getParamDescription();
// Avoid PHP 7.1 warning of passing $this by reference // Avoid PHP 7.1 warning of passing $this by reference
$apiModule = $this; $apiModule = $this;
Hooks::run( 'APIGetParamDescription', [ &$apiModule, &$desc ] ); Hooks::run( 'APIGetParamDescription', [ &$apiModule, &$desc ], '1 .25' );
if ( !$desc ) { if ( !$desc ) {
$desc = []; $desc = [];
} }
$desc = self::escapeWikiText( $desc ); $desc = self::escapeWikiText( $desc );
$params = $this->getFinalParams( self::GET_VALUES_FOR_HELP ); $params = $this->getFinalParams( self::GET_VALUES_FOR_HELP );
$msgs = []; $msgs = [];
foreach ( $params as $param => $settings ) { foreach ( $params as $param => $settings ) {
if ( !is_array( $settings ) ) { if ( !is_array( $settings ) ) {
$settings = []; $settings = [];
} }
$d = isset( $desc[$param] ) ? $desc[$param] : ''; $d = $desc[$param] ?? '';
if ( is_array( $d ) ) { if ( is_array( $d ) ) {
// Special handling for prop parameters // Special handling for prop parameters
$d = array_map( function ( $line ) { $d = array_map( function ( $line ) {
if ( preg_match( '/^\s+(\S+)\s+-\s+(.+)$/ ', $line, $m ) ) { if ( preg_match( '/^\s+(\S+)\s+-\s+(.+)$/ ', $line, $m ) ) {
$line = "\n;{$m[1]}:{$m[2]}"; $line = "\n;{$m[1]}:{$m[2]}";
} }
return $line; return $line;
}, $d ); }, $d );
$d = implode( ' ', $d ); $d = implode( ' ', $d );
} }
skipping to change at line 2362 skipping to change at line 2451
self::dieDebug( __METHOD__, self::dieDebug( __METHOD__,
'ApiBase::PARAM_HELP_MSG_PER_VALU E is not valid' ); 'ApiBase::PARAM_HELP_MSG_PER_VALU E is not valid' );
} }
if ( !is_array( $settings[self::PARAM_TYPE] ) ) { if ( !is_array( $settings[self::PARAM_TYPE] ) ) {
self::dieDebug( __METHOD__, self::dieDebug( __METHOD__,
'ApiBase::PARAM_HELP_MSG_PER_VALU E may only be used when ' . 'ApiBase::PARAM_HELP_MSG_PER_VALU E may only be used when ' .
'ApiBase::PARAM_TYPE is an array' ); 'ApiBase::PARAM_TYPE is an array' );
} }
$valueMsgs = $settings[self::PARAM_HELP_MSG_PER_V ALUE]; $valueMsgs = $settings[self::PARAM_HELP_MSG_PER_V ALUE];
$deprecatedValues = isset( $settings[self::PARAM_ $deprecatedValues = $settings[self::PARAM_DEPRECA
DEPRECATED_VALUES] ) TED_VALUES] ?? [];
? $settings[self::PARAM_DEPRECATED_VALUES
]
: [];
foreach ( $settings[self::PARAM_TYPE] as $value ) { foreach ( $settings[self::PARAM_TYPE] as $value ) {
if ( isset( $valueMsgs[$value] ) ) { if ( isset( $valueMsgs[$value] ) ) {
$msg = $valueMsgs[$value]; $msg = $valueMsgs[$value];
} else { } else {
$msg = "apihelp-{$path}-paramvalu e-{$param}-{$value}"; $msg = "apihelp-{$path}-paramvalu e-{$param}-{$value}";
} }
$m = self::makeMessage( $msg, $this->getC ontext(), $m = self::makeMessage( $msg, $this->getC ontext(),
[ $prefix, $param, $name, $path, $value ] ); [ $prefix, $param, $name, $path, $value ] );
if ( $m ) { if ( $m ) {
skipping to change at line 2603 skipping to change at line 2690
* that value, and boolean false means "no examples". * that value, and boolean false means "no examples".
* *
* @deprecated since 1.25, use getExamplesMessages() instead * @deprecated since 1.25, use getExamplesMessages() instead
* @return bool|string|array * @return bool|string|array
*/ */
protected function getExamples() { protected function getExamples() {
return false; return false;
} }
/** /**
* @deprecated since 1.25
*/
public function profileIn() {
// No wfDeprecated() yet because extensions call this and might n
eed to
// keep doing so for BC.
}
/**
* @deprecated since 1.25
*/
public function profileOut() {
// No wfDeprecated() yet because extensions call this and might n
eed to
// keep doing so for BC.
}
/**
* @deprecated since 1.25
*/
public function safeProfileOut() {
wfDeprecated( __METHOD__, '1.25' );
}
/**
* @deprecated since 1.25
*/
public function profileDBIn() {
wfDeprecated( __METHOD__, '1.25' );
}
/**
* @deprecated since 1.25
*/
public function profileDBOut() {
wfDeprecated( __METHOD__, '1.25' );
}
/**
* Call wfTransactionalTimeLimit() if this request was POSTed
* @since 1.26
*/
protected function useTransactionalTimeLimit() {
if ( $this->getRequest()->wasPosted() ) {
wfTransactionalTimeLimit();
}
}
/**
* @deprecated since 1.29, use ApiBase::addWarning() instead
* @param string $warning Warning message
*/
public function setWarning( $warning ) {
wfDeprecated( __METHOD__, '1.29' );
$msg = new ApiRawMessage( $warning, 'warning' );
$this->getErrorFormatter()->addWarning( $this->getModulePath(), $
msg );
}
/**
* Throw an ApiUsageException, which will (if uncaught) call the main mod
ule's
* error handler and die with an error message.
*
* @deprecated since 1.29, use self::dieWithError() instead
* @param string $description One-line human-readable description of the
* error condition, e.g., "The API requires a valid action parameter"
* @param string $errorCode Brief, arbitrary, stable string to allow easy
* automated identification of the error, e.g., 'unknown_action'
* @param int $httpRespCode HTTP response code
* @param array|null $extradata Data to add to the "<error>" element; arr
ay in ApiResult format
* @throws ApiUsageException always
*/
public function dieUsage( $description, $errorCode, $httpRespCode = 0, $e
xtradata = null ) {
wfDeprecated( __METHOD__, '1.29' );
$this->dieWithError(
new RawMessage( '$1', [ $description ] ),
$errorCode,
$extradata,
$httpRespCode
);
}
/**
* Get error (as code, string) from a Status object.
*
* @since 1.23
* @deprecated since 1.29, use ApiErrorFormatter::arrayFromStatus instead
* @param Status $status
* @param array|null &$extraData Set if extra data from IApiMessage is av
ailable (since 1.27)
* @return array Array of code and error string
* @throws MWException
*/
public function getErrorFromStatus( $status, &$extraData = null ) {
wfDeprecated( __METHOD__, '1.29' );
if ( $status->isGood() ) {
throw new MWException( 'Successful status passed to ApiBa
se::dieStatus' );
}
$errors = $status->getErrorsByType( 'error' );
if ( !$errors ) {
// No errors? Assume the warnings should be treated as er
rors
$errors = $status->getErrorsByType( 'warning' );
}
if ( !$errors ) {
// Still no errors? Punt
$errors = [ [ 'message' => 'unknownerror-nocode', 'params
' => [] ] ];
}
if ( $errors[0]['message'] instanceof MessageSpecifier ) {
$msg = $errors[0]['message'];
} else {
$msg = new Message( $errors[0]['message'], $errors[0]['pa
rams'] );
}
if ( !$msg instanceof IApiMessage ) {
$key = $msg->getKey();
$params = $msg->getParams();
array_unshift( $params, isset( self::$messageMap[$key] )
? self::$messageMap[$key] : $key );
$msg = ApiMessage::create( $params );
}
return [
$msg->getApiCode(),
ApiErrorFormatter::stripMarkup( $msg->inLanguage( 'en' )-
>useDatabase( false )->text() )
];
}
/**
* @deprecated since 1.29. Prior to 1.29, this was a public mapping from
* arbitrary strings (often message keys used elsewhere in MediaWiki) to
* API codes and message texts, and a few interfaces required poking
* something in here. Now we're repurposing it to map those same strings
* to i18n messages, and declaring that any interface that requires poki
ng
* at this is broken and needs replacing ASAP.
*/
private static $messageMap = [
'unknownerror' => 'apierror-unknownerror',
'unknownerror-nocode' => 'apierror-unknownerror-nocode',
'ns-specialprotected' => 'ns-specialprotected',
'protectedinterface' => 'protectedinterface',
'namespaceprotected' => 'namespaceprotected',
'customcssprotected' => 'customcssprotected',
'customjsprotected' => 'customjsprotected',
'cascadeprotected' => 'cascadeprotected',
'protectedpagetext' => 'protectedpagetext',
'protect-cantedit' => 'protect-cantedit',
'deleteprotected' => 'deleteprotected',
'badaccess-group0' => 'badaccess-group0',
'badaccess-groups' => 'badaccess-groups',
'titleprotected' => 'titleprotected',
'nocreate-loggedin' => 'nocreate-loggedin',
'nocreatetext' => 'nocreatetext',
'movenologintext' => 'movenologintext',
'movenotallowed' => 'movenotallowed',
'confirmedittext' => 'confirmedittext',
'blockedtext' => 'apierror-blocked',
'autoblockedtext' => 'apierror-autoblocked',
'systemblockedtext' => 'apierror-systemblocked',
'actionthrottledtext' => 'apierror-ratelimited',
'alreadyrolled' => 'alreadyrolled',
'cantrollback' => 'cantrollback',
'readonlytext' => 'readonlytext',
'sessionfailure' => 'sessionfailure',
'cannotdelete' => 'cannotdelete',
'notanarticle' => 'apierror-missingtitle',
'selfmove' => 'selfmove',
'immobile_namespace' => 'apierror-immobilenamespace',
'articleexists' => 'articleexists',
'hookaborted' => 'hookaborted',
'cantmove-titleprotected' => 'cantmove-titleprotected',
'imagenocrossnamespace' => 'imagenocrossnamespace',
'imagetypemismatch' => 'imagetypemismatch',
'ip_range_invalid' => 'ip_range_invalid',
'range_block_disabled' => 'range_block_disabled',
'nosuchusershort' => 'nosuchusershort',
'badipaddress' => 'badipaddress',
'ipb_expiry_invalid' => 'ipb_expiry_invalid',
'ipb_already_blocked' => 'ipb_already_blocked',
'ipb_blocked_as_range' => 'ipb_blocked_as_range',
'ipb_cant_unblock' => 'ipb_cant_unblock',
'mailnologin' => 'apierror-cantsend',
'ipbblocked' => 'ipbblocked',
'ipbnounblockself' => 'ipbnounblockself',
'usermaildisabled' => 'usermaildisabled',
'blockedemailuser' => 'apierror-blockedfrommail',
'notarget' => 'apierror-notarget',
'noemail' => 'noemail',
'rcpatroldisabled' => 'rcpatroldisabled',
'markedaspatrollederror-noautopatrol' => 'markedaspatrollederror-
noautopatrol',
'delete-toobig' => 'delete-toobig',
'movenotallowedfile' => 'movenotallowedfile',
'userrights-no-interwiki' => 'userrights-no-interwiki',
'userrights-nodatabase' => 'userrights-nodatabase',
'nouserspecified' => 'nouserspecified',
'noname' => 'noname',
'summaryrequired' => 'apierror-summaryrequired',
'import-rootpage-invalid' => 'import-rootpage-invalid',
'import-rootpage-nosubpage' => 'import-rootpage-nosubpage',
'readrequired' => 'apierror-readapidenied',
'writedisabled' => 'apierror-noapiwrite',
'writerequired' => 'apierror-writeapidenied',
'missingparam' => 'apierror-missingparam',
'invalidtitle' => 'apierror-invalidtitle',
'nosuchpageid' => 'apierror-nosuchpageid',
'nosuchrevid' => 'apierror-nosuchrevid',
'nosuchuser' => 'nosuchusershort',
'invaliduser' => 'apierror-invaliduser',
'invalidexpiry' => 'apierror-invalidexpiry',
'pastexpiry' => 'apierror-pastexpiry',
'create-titleexists' => 'apierror-create-titleexists',
'missingtitle-createonly' => 'apierror-missingtitle-createonly',
'cantblock' => 'apierror-cantblock',
'canthide' => 'apierror-canthide',
'cantblock-email' => 'apierror-cantblock-email',
'cantunblock' => 'apierror-permissiondenied-generic',
'cannotundelete' => 'cannotundelete',
'permdenied-undelete' => 'apierror-permissiondenied-generic',
'createonly-exists' => 'apierror-articleexists',
'nocreate-missing' => 'apierror-missingtitle',
'cantchangecontentmodel' => 'apierror-cantchangecontentmodel',
'nosuchrcid' => 'apierror-nosuchrcid',
'nosuchlogid' => 'apierror-nosuchlogid',
'protect-invalidaction' => 'apierror-protect-invalidaction',
'protect-invalidlevel' => 'apierror-protect-invalidlevel',
'toofewexpiries' => 'apierror-toofewexpiries',
'cantimport' => 'apierror-cantimport',
'cantimport-upload' => 'apierror-cantimport-upload',
'importnofile' => 'importnofile',
'importuploaderrorsize' => 'importuploaderrorsize',
'importuploaderrorpartial' => 'importuploaderrorpartial',
'importuploaderrortemp' => 'importuploaderrortemp',
'importcantopen' => 'importcantopen',
'import-noarticle' => 'import-noarticle',
'importbadinterwiki' => 'importbadinterwiki',
'import-unknownerror' => 'apierror-import-unknownerror',
'cantoverwrite-sharedfile' => 'apierror-cantoverwrite-sharedfile'
,
'sharedfile-exists' => 'apierror-fileexists-sharedrepo-perm',
'mustbeposted' => 'apierror-mustbeposted',
'show' => 'apierror-show',
'specialpage-cantexecute' => 'apierror-specialpage-cantexecute',
'invalidoldimage' => 'apierror-invalidoldimage',
'nodeleteablefile' => 'apierror-nodeleteablefile',
'fileexists-forbidden' => 'fileexists-forbidden',
'fileexists-shared-forbidden' => 'fileexists-shared-forbidden',
'filerevert-badversion' => 'filerevert-badversion',
'noimageredirect-anon' => 'apierror-noimageredirect-anon',
'noimageredirect-logged' => 'apierror-noimageredirect',
'spamdetected' => 'apierror-spamdetected',
'contenttoobig' => 'apierror-contenttoobig',
'noedit-anon' => 'apierror-noedit-anon',
'noedit' => 'apierror-noedit',
'wasdeleted' => 'apierror-pagedeleted',
'blankpage' => 'apierror-emptypage',
'editconflict' => 'editconflict',
'hashcheckfailed' => 'apierror-badmd5',
'missingtext' => 'apierror-notext',
'emptynewsection' => 'apierror-emptynewsection',
'revwrongpage' => 'apierror-revwrongpage',
'undo-failure' => 'undo-failure',
'content-not-allowed-here' => 'content-not-allowed-here',
'edit-hook-aborted' => 'edit-hook-aborted',
'edit-gone-missing' => 'edit-gone-missing',
'edit-conflict' => 'edit-conflict',
'edit-already-exists' => 'edit-already-exists',
'invalid-file-key' => 'apierror-invalid-file-key',
'nouploadmodule' => 'apierror-nouploadmodule',
'uploaddisabled' => 'uploaddisabled',
'copyuploaddisabled' => 'copyuploaddisabled',
'copyuploadbaddomain' => 'apierror-copyuploadbaddomain',
'copyuploadbadurl' => 'apierror-copyuploadbadurl',
'filename-tooshort' => 'filename-tooshort',
'filename-toolong' => 'filename-toolong',
'illegal-filename' => 'illegal-filename',
'filetype-missing' => 'filetype-missing',
'mustbeloggedin' => 'apierror-mustbeloggedin',
];
/**
* @deprecated do not use
* @param array|string|MessageSpecifier $error Element of a getUserPermis
sionsErrors()-style array
* @return ApiMessage
*/
private function parseMsgInternal( $error ) {
$msg = Message::newFromSpecifier( $error );
if ( !$msg instanceof IApiMessage ) {
$key = $msg->getKey();
if ( isset( self::$messageMap[$key] ) ) {
$params = $msg->getParams();
array_unshift( $params, self::$messageMap[$key] )
;
} else {
$params = [ 'apierror-unknownerror', wfEscapeWiki
Text( $key ) ];
}
$msg = ApiMessage::create( $params );
}
return $msg;
}
/**
* Return the error message related to a certain array
* @deprecated since 1.29
* @param array|string|MessageSpecifier $error Element of a getUserPermis
sionsErrors()-style array
* @return array [ 'code' => code, 'info' => info ]
*/
public function parseMsg( $error ) {
wfDeprecated( __METHOD__, '1.29' );
// Check whether someone passed the whole array, instead of one e
lement as
// documented. This breaks if it's actually an array of fallback
keys, but
// that's long-standing misbehavior introduced in r87627 to incor
rectly
// fix T30797.
if ( is_array( $error ) ) {
$first = reset( $error );
if ( is_array( $first ) ) {
wfDebug( __METHOD__ . ' was passed an array of ar
rays. ' . wfGetAllCallers( 5 ) );
$error = $first;
}
}
$msg = $this->parseMsgInternal( $error );
return [
'code' => $msg->getApiCode(),
'info' => ApiErrorFormatter::stripMarkup(
$msg->inLanguage( 'en' )->useDatabase( false )->t
ext()
),
'data' => $msg->getApiData()
];
}
/**
* Output the error message related to a certain array
* @deprecated since 1.29, use ApiBase::dieWithError() instead
* @param array|string|MessageSpecifier $error Element of a getUserPermis
sionsErrors()-style array
* @throws ApiUsageException always
*/
public function dieUsageMsg( $error ) {
wfDeprecated( __METHOD__, '1.29' );
$this->dieWithError( $this->parseMsgInternal( $error ) );
}
/**
* Will only set a warning instead of failing if the global $wgDebugAPI
* is set to true. Otherwise behaves exactly as dieUsageMsg().
* @deprecated since 1.29, use ApiBase::dieWithErrorOrDebug() instead
* @param array|string|MessageSpecifier $error Element of a getUserPermis
sionsErrors()-style array
* @throws ApiUsageException
* @since 1.21
*/
public function dieUsageMsgOrDebug( $error ) {
wfDeprecated( __METHOD__, '1.29' );
$this->dieWithErrorOrDebug( $this->parseMsgInternal( $error ) );
}
/**
* Return the description message. * Return the description message.
* *
* This is additional text to display on the help page after the summary. * This is additional text to display on the help page after the summary.
* *
* @deprecated since 1.30 * @deprecated since 1.30
* @return string|array|Message * @return string|array|Message
*/ */
protected function getDescriptionMessage() { protected function getDescriptionMessage() {
return [ [ return [ [
"apihelp-{$this->getModulePath()}-description", "apihelp-{$this->getModulePath()}-description",
"apihelp-{$this->getModulePath()}-summary", "apihelp-{$this->getModulePath()}-summary",
] ]; ] ];
} }
/**
* Truncate an array to a certain length.
* @deprecated since 1.32, no replacement
* @param array &$arr Array to truncate
* @param int $limit Maximum length
* @return bool True if the array was truncated, false otherwise
*/
public static function truncateArray( &$arr, $limit ) {
wfDeprecated( __METHOD__, '1.32' );
$modified = false;
while ( count( $arr ) > $limit ) {
array_pop( $arr );
$modified = true;
}
return $modified;
}
/**@}*/ /**@}*/
} }
/** /**
* For really cool vim folding this needs to be at the end: * For really cool vim folding this needs to be at the end:
* vim: foldmarker=@{,@} foldmethod=marker * vim: foldmarker=@{,@} foldmethod=marker
*/ */
 End of changes. 41 change blocks. 
497 lines changed or deleted 261 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)