44 use ApiBlockInfoTrait;
282 'blockedtext' => [
'apierror-blocked',
'blocked' ],
283 'blockedtext-partial' => [
'apierror-blocked-partial',
'blocked' ],
284 'autoblockedtext' => [
'apierror-autoblocked',
'autoblocked' ],
285 'systemblockedtext' => [
'apierror-systemblocked',
'blocked' ],
286 'blockedtext-composite' => [
'apierror-blocked',
'blocked' ],
304 $this->mMainModule = $mainModule;
305 $this->mModuleName = $moduleName;
306 $this->mModulePrefix = $modulePrefix;
521 return $this->mModuleName;
529 return $this->mModulePrefix;
537 return $this->mMainModule;
546 return $this === $this->mMainModule;
572 self::dieDebug( __METHOD__,
'base method was called on main module.' );
575 return $this->
getMain()->lacksSameOriginSecurity();
604 if (
$path ===
'main' ) {
608 $parts = explode(
'+',
$path );
609 if ( count( $parts ) === 1 ) {
611 $parts = explode(
' ',
$path );
614 $count = count( $parts );
615 for ( $i = 0; $i < $count; $i++ ) {
617 $manager = $parent->getModuleManager();
618 if ( $manager ===
null ) {
619 $errorPath = implode(
'+', array_slice( $parts, 0, $i ) );
620 $this->
dieWithError( [
'apierror-badmodule-nosubmodules', $errorPath ],
'badmodule' );
622 $module = $manager->getModule( $parts[$i] );
624 if ( $module ===
null ) {
625 $errorPath = $i ? implode(
'+', array_slice( $parts, 0, $i ) ) : $parent->getModuleName();
627 [
'apierror-badmodule-badsubmodule', $errorPath,
wfEscapeWikiText( $parts[$i] ) ],
644 self::dieDebug( __METHOD__,
'base method was called on main module. ' );
647 return $this->
getMain()->getResult();
658 self::dieDebug( __METHOD__,
'base method was called on main module. ' );
661 return $this->
getMain()->getErrorFormatter();
669 if ( !isset( $this->mReplicaDB ) ) {
673 return $this->mReplicaDB;
684 self::dieDebug( __METHOD__,
'base method was called on main module. ' );
687 return $this->
getMain()->getContinuationManager();
698 self::dieDebug( __METHOD__,
'base method was called on main module. ' );
701 $this->
getMain()->setContinuationManager( $manager );
740 if ( is_array( $paramName ) ) {
741 return array_map(
function ( $name ) {
742 return $this->mModulePrefix . $name;
745 return $this->mModulePrefix . $paramName;
762 if ( is_bool( $options ) ) {
763 $options = [
'parseLimit' => $options ];
766 'parseLimit' =>
true,
770 $parseLimit = (bool)$options[
'parseLimit'];
773 if ( !isset( $this->mParamCache[$parseLimit] ) ) {
774 $params = $this->getFinalParams() ?: [];
781 foreach ( $params as $paramName => $paramSettings ) {
782 if ( isset( $paramSettings[self::PARAM_TEMPLATE_VARS] ) ) {
783 $toProcess[] = [ $paramName, $paramSettings[self::PARAM_TEMPLATE_VARS], $paramSettings ];
786 $results[$paramName] = $this->getParameterFromSettings(
787 $paramName, $paramSettings, $parseLimit
790 $results[$paramName] = $ex;
800 while ( $toProcess ) {
801 list( $name, $targets, $settings ) = array_shift( $toProcess );
803 foreach ( $targets as $placeholder => $target ) {
804 if ( !array_key_exists( $target, $results ) ) {
809 if ( !is_array( $results[$target] ) || !$results[$target] ) {
818 unset( $targets[$placeholder] );
819 $placeholder =
'{' . $placeholder .
'}';
821 foreach ( $results[$target] as $value ) {
822 if ( !preg_match(
'/^[^{}]*$/', $value ) ) {
824 $encTargetName = $this->encodeParamName( $target );
825 if ( !isset( $warned[$encTargetName][$value] ) ) {
826 $warned[$encTargetName][$value] =
true;
828 'apiwarn-ignoring-invalid-templated-value',
836 $newName = str_replace( $placeholder, $value, $name );
839 $results[$newName] = $this->getParameterFromSettings( $newName, $settings, $parseLimit );
841 $results[$newName] = $ex;
845 foreach ( $targets as $k => $v ) {
846 $newTargets[$k] = str_replace( $placeholder, $value, $v );
848 $toProcess[] = [ $newName, $newTargets, $settings ];
855 $this->mParamCache[$parseLimit] = $results;
858 $ret = $this->mParamCache[$parseLimit];
859 if ( !$options[
'safeMode'] ) {
860 foreach ( $ret as $v ) {
867 return $this->mParamCache[$parseLimit];
877 $ret = $this->extractRequestParams( [
878 'parseLimit' => $parseLimit,
894 $required = func_get_args();
895 array_shift( $required );
897 $intersection = array_intersect( array_keys( array_filter( $params,
898 [ $this,
'parameterNotEmpty' ] ) ), $required );
900 if ( count( $intersection ) > 1 ) {
901 $this->dieWithError( [
902 'apierror-invalidparammix',
905 return '<var>' . $this->encodeParamName( $p ) .
'</var>';
907 array_values( $intersection )
909 count( $intersection ),
911 } elseif ( count( $intersection ) == 0 ) {
912 $this->dieWithError( [
913 'apierror-missingparam-one-of',
916 return '<var>' . $this->encodeParamName( $p ) .
'</var>';
918 array_values( $required )
932 $required = func_get_args();
933 array_shift( $required );
935 $intersection = array_intersect( array_keys( array_filter( $params,
936 [ $this,
'parameterNotEmpty' ] ) ), $required );
938 if ( count( $intersection ) > 1 ) {
939 $this->dieWithError( [
940 'apierror-invalidparammix',
943 return '<var>' . $this->encodeParamName( $p ) .
'</var>';
945 array_values( $intersection )
947 count( $intersection ),
960 $required = func_get_args();
961 array_shift( $required );
963 $intersection = array_intersect(
964 array_keys( array_filter( $params, [ $this,
'parameterNotEmpty' ] ) ),
968 if ( count( $intersection ) == 0 ) {
969 $this->dieWithError( [
970 'apierror-missingparam-at-least-one-of',
973 return '<var>' . $this->encodeParamName( $p ) .
'</var>';
975 array_values( $required )
991 if ( $this->getConfig()->
get(
'DebugAPI' ) || $this->getMain()->isInternalMode() ) {
995 $queryValues = $this->getRequest()->getQueryValuesOnly();
997 foreach ( $params as $param ) {
998 if ( $prefix !==
'noprefix' ) {
999 $param = $this->encodeParamName( $param );
1001 if ( array_key_exists( $param, $queryValues ) ) {
1002 $badParams[] = $param;
1007 $this->dieWithError(
1008 [
'apierror-mustpostparams', implode(
', ', $badParams ), count( $badParams ) ]
1020 return !is_null( $x ) && $x !==
false;
1035 $this->requireOnlyOneParameter( $params,
'title',
'pageid' );
1038 if ( isset( $params[
'title'] ) ) {
1039 $titleObj = Title::newFromText( $params[
'title'] );
1040 if ( !$titleObj || $titleObj->isExternal() ) {
1041 $this->dieWithError( [
'apierror-invalidtitle',
wfEscapeWikiText( $params[
'title'] ) ] );
1043 if ( !$titleObj->canExist() ) {
1044 $this->dieWithError(
'apierror-pagecannotexist' );
1046 $pageObj = WikiPage::factory( $titleObj );
1047 if ( $load !==
false ) {
1048 $pageObj->loadPageData( $load );
1050 } elseif ( isset( $params[
'pageid'] ) ) {
1051 if ( $load ===
false ) {
1054 $pageObj = WikiPage::newFromID( $params[
'pageid'], $load );
1056 $this->dieWithError( [
'apierror-nosuchpageid', $params[
'pageid'] ] );
1072 $this->requireOnlyOneParameter( $params,
'title',
'pageid' );
1075 if ( isset( $params[
'title'] ) ) {
1076 $titleObj = Title::newFromText( $params[
'title'] );
1077 if ( !$titleObj || $titleObj->isExternal() ) {
1078 $this->dieWithError( [
'apierror-invalidtitle',
wfEscapeWikiText( $params[
'title'] ) ] );
1081 } elseif ( isset( $params[
'pageid'] ) ) {
1082 $titleObj = Title::newFromID( $params[
'pageid'] );
1084 $this->dieWithError( [
'apierror-nosuchpageid', $params[
'pageid'] ] );
1100 $userWatching = $this->
getUser()->isWatched( $titleObj, User::IGNORE_USER_RIGHTS );
1102 switch ( $watchlist ) {
1110 # If the user is already watching, don't bother checking
1111 if ( $userWatching ) {
1114 # If no user option was passed, use watchdefault and watchcreations
1115 if ( is_null( $userOption ) ) {
1116 return $this->
getUser()->getBoolOption(
'watchdefault' ) ||
1117 $this->
getUser()->getBoolOption(
'watchcreations' ) && !$titleObj->exists();
1120 # Watch the article based on the user preference
1121 return $this->
getUser()->getBoolOption( $userOption );
1124 return $userWatching;
1127 return $userWatching;
1142 $encParamName = $this->encodeParamName( $paramName );
1145 if ( !is_array( $paramSettings ) ) {
1147 self::PARAM_DFLT => $paramSettings,
1151 $default = $paramSettings[self::PARAM_DFLT] ??
null;
1152 $multi = $paramSettings[self::PARAM_ISMULTI] ??
false;
1153 $multiLimit1 = $paramSettings[self::PARAM_ISMULTI_LIMIT1] ??
null;
1154 $multiLimit2 = $paramSettings[self::PARAM_ISMULTI_LIMIT2] ??
null;
1155 $type = $paramSettings[self::PARAM_TYPE] ??
null;
1156 $dupes = $paramSettings[self::PARAM_ALLOW_DUPLICATES] ??
false;
1157 $deprecated = $paramSettings[self::PARAM_DEPRECATED] ??
false;
1158 $deprecatedValues = $paramSettings[self::PARAM_DEPRECATED_VALUES] ?? [];
1159 $required = $paramSettings[self::PARAM_REQUIRED] ??
false;
1160 $allowAll = $paramSettings[self::PARAM_ALL] ??
false;
1163 if ( !isset(
$type ) ) {
1164 if ( isset( $default ) ) {
1165 $type = gettype( $default );
1171 if (
$type ==
'password' || !empty( $paramSettings[self::PARAM_SENSITIVE] ) ) {
1172 $this->getMain()->markParamsSensitive( $encParamName );
1175 if (
$type ==
'boolean' ) {
1176 if ( isset( $default ) && $default !==
false ) {
1180 "Boolean param $encParamName's default is set to '$default'. " .
1181 'Boolean parameters must default to false.'
1185 $value = $this->getMain()->getCheck( $encParamName );
1187 } elseif (
$type ==
'upload' ) {
1188 if ( isset( $default ) ) {
1192 "File upload param $encParamName's default is set to " .
1193 "'$default'. File upload parameters may not have a default." );
1196 self::dieDebug( __METHOD__,
"Multi-values not supported for $encParamName" );
1198 $value = $this->getMain()->getUpload( $encParamName );
1199 $provided = $value->exists();
1200 if ( !$value->exists() ) {
1204 $value = $this->getMain()->getRequest()->unsetVal( $encParamName );
1205 if ( $value !==
null ) {
1206 $this->dieWithError(
1207 [
'apierror-badupload', $encParamName ],
1208 "badupload_{$encParamName}"
1213 $value = $this->getMain()->getVal( $encParamName, $default );
1214 $provided = $this->getMain()->getCheck( $encParamName );
1216 if ( isset( $value ) &&
$type ==
'namespace' ) {
1217 $type = MediaWikiServices::getInstance()->getNamespaceInfo()->
1218 getValidNamespaces();
1219 if ( isset( $paramSettings[self::PARAM_EXTRA_NAMESPACES] ) &&
1220 is_array( $paramSettings[self::PARAM_EXTRA_NAMESPACES] )
1222 $type = array_merge(
$type, $paramSettings[self::PARAM_EXTRA_NAMESPACES] );
1228 if ( isset( $value ) &&
$type ==
'submodule' ) {
1229 if ( isset( $paramSettings[self::PARAM_SUBMODULE_MAP] ) ) {
1230 $type = array_keys( $paramSettings[self::PARAM_SUBMODULE_MAP] );
1232 $type = $this->getModuleManager()->getNames( $paramName );
1236 $request = $this->getMain()->getRequest();
1237 $rawValue = $request->getRawVal( $encParamName );
1238 if ( $rawValue ===
null ) {
1239 $rawValue = $default;
1243 if ( isset( $value ) && substr( $rawValue, 0, 1 ) ===
"\x1f" ) {
1247 $value = implode(
"\x1f", $request->normalizeUnicode( explode(
"\x1f", $rawValue ) ) );
1249 $this->dieWithError(
'apierror-badvalue-notmultivalue',
'badvalue_notmultivalue' );
1254 if ( $rawValue !== $value ) {
1255 $this->handleParamNormalization( $paramName, $value, $rawValue );
1259 $allSpecifier = ( is_string( $allowAll ) ? $allowAll : self::ALL_DEFAULT_STRING );
1260 if ( $allowAll && $multi && is_array(
$type ) && in_array( $allSpecifier,
$type,
true ) ) {
1263 "For param $encParamName, PARAM_ALL collides with a possible value" );
1265 if ( isset( $value ) && ( $multi || is_array(
$type ) ) ) {
1266 $value = $this->parseMultiValue(
1271 $allowAll ? $allSpecifier :
null,
1277 if ( isset( $value ) ) {
1280 if ( !is_array(
$type ) ) {
1287 if ( $required && $value ===
'' ) {
1288 $this->dieWithError( [
'apierror-missingparam', $encParamName ] );
1292 $min = $paramSettings[self::PARAM_MIN] ??
null;
1293 $max = $paramSettings[self::PARAM_MAX] ??
null;
1294 $enforceLimits = $paramSettings[self::PARAM_RANGE_ENFORCE] ??
false;
1296 if ( is_array( $value ) ) {
1297 $value = array_map(
'intval', $value );
1298 if ( !is_null( $min ) || !is_null( $max ) ) {
1299 foreach ( $value as &$v ) {
1300 $this->validateLimit( $paramName, $v, $min, $max,
null, $enforceLimits );
1304 $value = (int)$value;
1305 if ( !is_null( $min ) || !is_null( $max ) ) {
1306 $this->validateLimit( $paramName, $value, $min, $max,
null, $enforceLimits );
1312 if ( $value !==
'max' ) {
1313 $value = (int)$value;
1316 self::dieDebug( __METHOD__,
"Multi-values not supported for $encParamName" );
1318 if ( !$parseLimit ) {
1322 if ( !isset( $paramSettings[self::PARAM_MAX] )
1323 || !isset( $paramSettings[self::PARAM_MAX2] )
1327 "MAX1 or MAX2 are not defined for the limit $encParamName"
1330 if ( $value ===
'max' ) {
1331 $value = $this->getMain()->canApiHighLimits()
1332 ? $paramSettings[self::PARAM_MAX2]
1333 : $paramSettings[self::PARAM_MAX];
1334 $this->getResult()->addParsedLimit( $this->getModuleName(), $value );
1336 $this->validateLimit(
1339 $paramSettings[self::PARAM_MIN] ?? 0,
1340 $paramSettings[self::PARAM_MAX],
1341 $paramSettings[self::PARAM_MAX2]
1347 self::dieDebug( __METHOD__,
"Multi-values not supported for $encParamName" );
1351 if ( is_array( $value ) ) {
1352 foreach ( $value as $key => $val ) {
1353 $value[$key] = $this->validateTimestamp( $val, $encParamName );
1356 $value = $this->validateTimestamp( $value, $encParamName );
1360 if ( is_array( $value ) ) {
1361 foreach ( $value as $key => $val ) {
1362 $value[$key] = $this->validateUser( $val, $encParamName );
1365 $value = $this->validateUser( $value, $encParamName );
1372 if ( !is_array( $value ) && !$multi ) {
1373 $value = [ $value ];
1376 if ( !$tagsStatus->isGood() ) {
1377 $this->dieStatus( $tagsStatus );
1381 self::dieDebug( __METHOD__,
"Param $encParamName's type is unknown - $type" );
1386 if ( !$dupes && is_array( $value ) ) {
1387 $value = array_unique( $value );
1390 if ( in_array(
$type, [
'NULL',
'string',
'text',
'password' ],
true ) ) {
1391 foreach ( (array)$value as $val ) {
1392 if ( isset( $paramSettings[self::PARAM_MAX_BYTES] )
1393 && strlen( $val ) > $paramSettings[self::PARAM_MAX_BYTES]
1395 $this->dieWithError( [
'apierror-maxbytes', $encParamName,
1396 $paramSettings[self::PARAM_MAX_BYTES] ] );
1398 if ( isset( $paramSettings[self::PARAM_MAX_CHARS] )
1399 && mb_strlen( $val,
'UTF-8' ) > $paramSettings[self::PARAM_MAX_CHARS]
1401 $this->dieWithError( [
'apierror-maxchars', $encParamName,
1402 $paramSettings[self::PARAM_MAX_CHARS] ] );
1408 if ( $deprecated && $provided ) {
1409 $feature = $encParamName;
1411 while ( !$m->isMain() ) {
1412 $p = $m->getParent();
1413 $name = $m->getModuleName();
1414 $param = $p->encodeParamName( $p->getModuleManager()->getModuleGroup( $name ) );
1415 $feature =
"{$param}={$name}&{$feature}";
1418 $this->addDeprecation( [
'apiwarn-deprecation-parameter', $encParamName ], $feature );
1422 $usedDeprecatedValues = $deprecatedValues && $provided
1423 ? array_intersect( array_keys( $deprecatedValues ), (array)$value )
1425 if ( $usedDeprecatedValues ) {
1426 $feature =
"$encParamName=";
1428 while ( !$m->isMain() ) {
1429 $p = $m->getParent();
1430 $name = $m->getModuleName();
1431 $param = $p->encodeParamName( $p->getModuleManager()->getModuleGroup( $name ) );
1432 $feature =
"{$param}={$name}&{$feature}";
1435 foreach ( $usedDeprecatedValues as $v ) {
1436 $msg = $deprecatedValues[$v];
1437 if ( $msg ===
true ) {
1438 $msg = [
'apiwarn-deprecation-parameter',
"$encParamName=$v" ];
1440 $this->addDeprecation( $msg,
"$feature$v" );
1443 } elseif ( $required ) {
1444 $this->dieWithError( [
'apierror-missingparam', $encParamName ] );
1458 $encParamName = $this->encodeParamName( $paramName );
1459 $this->addWarning( [
'apiwarn-badutf8', $encParamName ] );
1470 if ( substr( $value, 0, 1 ) ===
"\x1f" ) {
1472 $value = substr( $value, 1 );
1477 return explode( $sep, $value, $limit );
1498 $allSpecifier =
null, $limit1 =
null, $limit2 =
null
1500 if ( ( $value ===
'' || $value ===
"\x1f" ) && $allowMultiple ) {
1503 $limit1 = $limit1 ?: self::LIMIT_SML1;
1504 $limit2 = $limit2 ?: self::LIMIT_SML2;
1508 $valuesList = $this->explodeMultiValue( $value, $limit2 + 1 );
1509 $sizeLimit = count( $valuesList ) > $limit1 && $this->mMainModule->canApiHighLimits()
1513 if ( $allowMultiple && is_array( $allowedValues ) && $allSpecifier &&
1514 count( $valuesList ) === 1 && $valuesList[0] === $allSpecifier
1516 return $allowedValues;
1519 if ( count( $valuesList ) > $sizeLimit ) {
1520 $this->dieWithError(
1521 [
'apierror-toomanyvalues', $valueName, $sizeLimit ],
1522 "too-many-$valueName"
1526 if ( !$allowMultiple && count( $valuesList ) != 1 ) {
1528 if ( in_array( $value, $allowedValues,
true ) ) {
1532 $values = array_map(
function ( $v ) {
1534 }, $allowedValues );
1535 $this->dieWithError( [
1536 'apierror-multival-only-one-of',
1540 ],
"multival_$valueName" );
1543 if ( is_array( $allowedValues ) ) {
1545 $unknown = array_map(
'wfEscapeWikiText', array_diff( $valuesList, $allowedValues ) );
1546 if ( count( $unknown ) ) {
1547 if ( $allowMultiple ) {
1548 $this->addWarning( [
1549 'apiwarn-unrecognizedvalues',
1555 $this->dieWithError(
1556 [
'apierror-unrecognizedvalue', $valueName,
wfEscapeWikiText( $valuesList[0] ) ],
1557 "unknown_$valueName"
1562 $valuesList = array_intersect( $valuesList, $allowedValues );
1565 return $allowMultiple ? $valuesList : $valuesList[0];
1578 protected function validateLimit( $paramName, &$value, $min, $max, $botMax =
null,
1579 $enforceLimits =
false
1581 if ( !is_null( $min ) && $value < $min ) {
1583 [
'apierror-integeroutofrange-belowminimum',
1584 $this->encodeParamName( $paramName ), $min, $value ],
1585 'integeroutofrange',
1586 [
'min' => $min,
'max' => $max,
'botMax' => $botMax ?: $max ]
1589 $this->warnOrDie( $msg, $enforceLimits );
1595 if ( $this->getMain()->isInternalMode() ) {
1601 if ( !is_null( $max ) && $value > $max ) {
1602 if ( !is_null( $botMax ) && $this->getMain()->canApiHighLimits() ) {
1603 if ( $value > $botMax ) {
1605 [
'apierror-integeroutofrange-abovebotmax',
1606 $this->encodeParamName( $paramName ), $botMax, $value ],
1607 'integeroutofrange',
1608 [
'min' => $min,
'max' => $max,
'botMax' => $botMax ?: $max ]
1611 $this->warnOrDie( $msg, $enforceLimits );
1616 [
'apierror-integeroutofrange-abovemax',
1617 $this->encodeParamName( $paramName ), $max, $value ],
1618 'integeroutofrange',
1619 [
'min' => $min,
'max' => $max,
'botMax' => $botMax ?: $max ]
1622 $this->warnOrDie( $msg, $enforceLimits );
1639 $this->addDeprecation(
1640 [
'apiwarn-unclearnowtimestamp', $encParamName,
wfEscapeWikiText( $value ) ],
1641 'unclear-"now"-timestamp'
1647 if ( $value ===
'now' ) {
1652 if ( $timestamp ===
false ) {
1653 $this->dieWithError(
1655 "badtimestamp_{$encParamName}"
1672 $tokenType = $this->needsToken();
1674 if ( !isset( $salts[$tokenType] ) ) {
1676 "Module '{$this->getModuleName()}' tried to use token type '$tokenType' " .
1677 'without registering it'
1682 $this->
getUser(), $this->getRequest()->getSession(), $salts[$tokenType]
1684 if ( $tokenObj->match( $token ) ) {
1688 $webUiSalt = $this->getWebUITokenSalt( $params );
1689 if ( $webUiSalt !==
null && $this->
getUser()->matchEditToken(
1711 $name = User::getCanonicalName( $value,
'valid' );
1712 if ( $name !==
false ) {
1718 IP::isIPAddress( $value ) ||
1728 return IP::sanitizeIP( $value );
1731 $this->dieWithError(
1733 "baduser_{$encParamName}"
1750 protected function setWatch( $watch, $titleObj, $userOption =
null ) {
1751 $value = $this->getWatchlistValue( $watch, $titleObj, $userOption );
1752 if ( $value ===
null ) {
1766 if ( !is_null( $params[
'owner'] ) && !is_null( $params[
'token'] ) ) {
1767 $user = User::newFromName( $params[
'owner'],
false );
1768 if ( !( $user && $user->getId() ) ) {
1769 $this->dieWithError(
1773 $token = $user->getOption(
'watchlisttoken' );
1774 if ( $token ==
'' || !hash_equals( $token, $params[
'token'] ) ) {
1775 $this->dieWithError(
'apierror-bad-watchlist-token',
'bad_wltoken' );
1778 if ( !$this->
getUser()->isLoggedIn() ) {
1779 $this->dieWithError(
'watchlistanontext',
'notloggedin' );
1781 $this->checkUserRightsAny(
'viewmywatchlist' );
1801 if ( is_string( $msg ) ) {
1803 } elseif ( is_array( $msg ) ) {
1806 if ( !$msg instanceof
Message ) {
1812 $msg->params( $params );
1826 if ( $user ===
null ) {
1830 $status = Status::newGood();
1831 foreach ( $errors as $error ) {
1832 if ( !is_array( $error ) ) {
1833 $error = [ $error ];
1835 if ( is_string( $error[0] ) && isset( self::$blockMsgMap[$error[0]] ) && $user->getBlock() ) {
1836 list( $msg, $code ) = self::$blockMsgMap[$error[0]];
1838 [
'blockinfo' => $this->getBlockDetails( $user->getBlock() ) ]
1841 $status->fatal( ...$error );
1854 if ( $user ===
null ) {
1858 foreach ( self::$blockMsgMap as $msg => list( $apiMsg, $code ) ) {
1859 if ( $status->
hasMessage( $msg ) && $user->getBlock() ) {
1861 [
'blockinfo' => $this->getBlockDetails( $user->getBlock() ) ]
1872 if ( $this->getRequest()->wasPosted() ) {
1888 foreach ( $fields as list( $table, $field ) ) {
1889 if ( isset( self::$filterIDsCache[$table][$field] ) ) {
1890 $row = self::$filterIDsCache[$table][$field];
1892 $row = $this->
getDB()->selectRow(
1895 'min_id' =>
"MIN($field)",
1896 'max_id' =>
"MAX($field)",
1901 self::$filterIDsCache[$table][$field] = $row;
1903 $min = min( $min, $row->min_id );
1904 $max = max( $max, $row->max_id );
1906 return array_filter( $ids,
function ( $id ) use ( $min, $max ) {
1907 return ( is_int( $id ) && $id >= 0 || ctype_digit( $id ) )
1908 && $id >= $min && $id <= $max;
1934 $this->getErrorFormatter()->addWarning( $this->getModulePath(), $msg, $code, $data );
1948 $data = (array)$data;
1949 if ( $feature !==
null ) {
1950 $data[
'feature'] = $feature;
1951 $this->logFeatureUsage( $feature );
1953 $this->addWarning( $msg,
'deprecation', $data );
1957 $msgs = [ $this->msg(
'api-usage-mailinglist-ref' ) ];
1958 Hooks::run(
'ApiDeprecationHelp', [ &$msgs ] );
1959 if ( count( $msgs ) > 1 ) {
1960 $key =
'$' . implode(
' $', range( 1, count( $msgs ) ) );
1961 $msg = (
new RawMessage( $key ) )->params( $msgs );
1963 $msg = reset( $msgs );
1965 $this->getMain()->addWarning( $msg,
'deprecation-help' );
1980 public function addError( $msg, $code =
null, $data =
null ) {
1981 $this->getErrorFormatter()->addError( $this->getModulePath(), $msg, $code, $data );
1996 $this->getErrorFormatter()->addMessagesFromStatus(
1997 $this->getModulePath(), $status, $types,
$filter
2014 public function dieWithError( $msg, $code =
null, $data =
null, $httpCode =
null ) {
2015 throw ApiUsageException::newWithMessage( $this, $msg, $code, $data, $httpCode );
2027 $this->dieWithError(
2029 $this->getErrorFormatter()->getMessageFromException( $exception, $options )
2040 if ( $enforceLimits ) {
2041 $this->dieWithError( $msg );
2043 $this->addWarning( $msg );
2057 if ( $block->
getType() == DatabaseBlock::TYPE_AUTO ) {
2058 $this->dieWithError(
2059 'apierror-autoblocked',
2061 [
'blockinfo' => $this->getBlockDetails( $block ) ]
2064 $this->dieWithError(
2065 'apierror-blocked-partial',
2067 [
'blockinfo' => $this->getBlockDetails( $block ) ]
2070 $this->dieWithError(
2073 [
'blockinfo' => $this->getBlockDetails( $block ) ]
2087 if ( $status->
isGood() ) {
2088 throw new MWException(
'Successful status passed to ApiBase::dieStatus' );
2093 $status->
setOK(
false );
2095 $newStatus = Status::newGood();
2097 $newStatus->fatal( $err[
'message'], ...$err[
'params'] );
2099 if ( !$newStatus->getErrorsByType(
'error' ) ) {
2100 $newStatus->fatal(
'unknownerror-nocode' );
2102 $status = $newStatus;
2105 $this->addBlockInfoToStatus( $status );
2115 $this->dieWithError(
2116 'apierror-readonly',
2134 $rights = (array)$rights;
2136 ->userHasAnyRight( $user, ...$rights )
2138 $this->dieWithError( [
'apierror-permissiondenied', $this->msg(
"action-{$rights[0]}" ) ] );
2157 if ( !is_array( $options ) ) {
2158 wfDeprecated(
'$user as the third parameter to ' . __METHOD__,
'1.33' );
2159 $options = [
'user' => $options ];
2161 $user = $options[
'user'] ?? $this->
getUser();
2164 foreach ( (array)$actions as $action ) {
2165 $errors = array_merge(
2172 if ( !empty( $options[
'autoblock'] ) ) {
2173 $user->spreadAnyEditBlock();
2176 $this->dieStatus( $this->errorArrayToStatus( $errors, $user ) );
2192 if ( $this->getConfig()->
get(
'DebugAPI' ) !==
true ) {
2193 $this->dieWithError( $msg, $code, $data, $httpCode );
2195 $this->addWarning( $msg, $code, $data );
2210 $this->dieWithError(
'apierror-badcontinue' );
2220 protected static function dieDebug( $method, $message ) {
2221 throw new MWException(
"Internal error in $method: $message" );
2231 static $loggedFeatures = [];
2235 if ( isset( $loggedFeatures[$feature] ) ) {
2238 $loggedFeatures[$feature] =
true;
2240 $request = $this->getRequest();
2242 'feature' => $feature,
2244 'username' => str_replace(
' ',
'_', $this->
getUser()->getName() ),
2245 'ip' => $request->getIP(),
2246 'referer' => (string)$request->getHeader(
'Referer' ),
2247 'agent' => $this->getMain()->getUserAgent(),
2251 $s =
'"' . addslashes( $ctx[
'feature'] ) .
'"' .
2253 ' "' . $ctx[
'ip'] .
'"' .
2254 ' "' . addslashes( $ctx[
'referer'] ) .
'"' .
2255 ' "' . addslashes( $ctx[
'agent'] ) .
'"';
2257 wfDebugLog(
'api-feature-usage',
$s,
'private', $ctx );
2277 return "apihelp-{$this->getModulePath()}-summary";
2291 "apihelp-{$this->getModulePath()}-extended-description",
2292 'api-help-no-extended-description',
2303 $msg = self::makeMessage( $this->getSummaryMessage(), $this->
getContext(), [
2304 $this->getModulePrefix(),
2305 $this->getModuleName(),
2306 $this->getModulePath(),
2319 $summary = self::makeMessage( $this->getSummaryMessage(), $this->
getContext(), [
2320 $this->getModulePrefix(),
2321 $this->getModuleName(),
2322 $this->getModulePath(),
2324 $extendedDescription = self::makeMessage(
2325 $this->getExtendedDescription(), $this->
getContext(), [
2326 $this->getModulePrefix(),
2327 $this->getModuleName(),
2328 $this->getModulePath(),
2332 $msgs = [ $summary, $extendedDescription ];
2334 Hooks::run(
'APIGetDescriptionMessages', [ $this, &$msgs ] );
2348 $params = $this->getAllowedParams( $flags );
2353 if ( $this->needsToken() ) {
2354 $params[
'token'] = [
2355 self::PARAM_TYPE =>
'string',
2356 self::PARAM_REQUIRED =>
true,
2357 self::PARAM_SENSITIVE =>
true,
2358 self::PARAM_HELP_MSG => [
2359 'api-help-param-token',
2360 $this->needsToken(),
2362 ] + ( $params[
'token'] ?? [] );
2367 Hooks::run(
'APIGetAllowedParams', [ &$apiModule, &$params, $flags ] );
2380 $prefix = $this->getModulePrefix();
2381 $name = $this->getModuleName();
2382 $path = $this->getModulePath();
2384 $params = $this->getFinalParams( self::GET_VALUES_FOR_HELP );
2386 foreach ( $params as $param => $settings ) {
2387 if ( !is_array( $settings ) ) {
2391 if ( isset( $settings[self::PARAM_HELP_MSG] ) ) {
2392 $msg = $settings[self::PARAM_HELP_MSG];
2394 $msg = $this->msg(
"apihelp-{$path}-param-{$param}" );
2396 $msg = self::makeMessage( $msg, $this->
getContext(),
2397 [ $prefix, $param, $name,
$path ] );
2399 self::dieDebug( __METHOD__,
2400 'Value in ApiBase::PARAM_HELP_MSG is not valid' );
2402 $msgs[$param] = [ $msg ];
2404 if ( isset( $settings[self::PARAM_TYPE] ) &&
2405 $settings[self::PARAM_TYPE] ===
'submodule'
2407 if ( isset( $settings[self::PARAM_SUBMODULE_MAP] ) ) {
2408 $map = $settings[self::PARAM_SUBMODULE_MAP];
2410 $prefix = $this->isMain() ?
'' : ( $this->getModulePath() .
'+' );
2412 foreach ( $this->getModuleManager()->getNames( $param ) as $submoduleName ) {
2413 $map[$submoduleName] = $prefix . $submoduleName;
2418 $deprecatedSubmodules = [];
2419 foreach ( $map as $v => $m ) {
2420 $arr = &$submodules;
2421 $isDeprecated =
false;
2424 $submod = $this->getModuleFromPath( $m );
2426 $summary = $submod->getFinalSummary();
2427 $isDeprecated = $submod->isDeprecated();
2428 if ( $isDeprecated ) {
2429 $arr = &$deprecatedSubmodules;
2436 $key = $summary->getKey();
2437 $params = $summary->getParams();
2439 $key =
'api-help-undocumented-module';
2443 $arr[] = $m->setContext( $this->
getContext() );
2445 $msgs[$param] = array_merge( $msgs[$param], $submodules, $deprecatedSubmodules );
2446 } elseif ( isset( $settings[self::PARAM_HELP_MSG_PER_VALUE] ) ) {
2447 if ( !is_array( $settings[self::PARAM_HELP_MSG_PER_VALUE] ) ) {
2448 self::dieDebug( __METHOD__,
2449 'ApiBase::PARAM_HELP_MSG_PER_VALUE is not valid' );
2451 if ( !is_array( $settings[self::PARAM_TYPE] ) ) {
2452 self::dieDebug( __METHOD__,
2453 'ApiBase::PARAM_HELP_MSG_PER_VALUE may only be used when ' .
2454 'ApiBase::PARAM_TYPE is an array' );
2457 $valueMsgs = $settings[self::PARAM_HELP_MSG_PER_VALUE];
2458 $deprecatedValues = $settings[self::PARAM_DEPRECATED_VALUES] ?? [];
2460 foreach ( $settings[self::PARAM_TYPE] as $value ) {
2461 if ( isset( $valueMsgs[$value] ) ) {
2462 $msg = $valueMsgs[$value];
2464 $msg =
"apihelp-{$path}-paramvalue-{$param}-{$value}";
2466 $m = self::makeMessage( $msg, $this->
getContext(),
2467 [ $prefix, $param, $name,
$path, $value ] );
2472 [ $m->getKey(),
'api-help-param-no-description' ],
2474 isset( $deprecatedValues[$value] )
2476 $msgs[$param][] = $m->setContext( $this->
getContext() );
2478 self::dieDebug( __METHOD__,
2479 "Value in ApiBase::PARAM_HELP_MSG_PER_VALUE for $value is not valid" );
2484 if ( isset( $settings[self::PARAM_HELP_MSG_APPEND] ) ) {
2485 if ( !is_array( $settings[self::PARAM_HELP_MSG_APPEND] ) ) {
2486 self::dieDebug( __METHOD__,
2487 'Value for ApiBase::PARAM_HELP_MSG_APPEND is not an array' );
2489 foreach ( $settings[self::PARAM_HELP_MSG_APPEND] as $m ) {
2490 $m = self::makeMessage( $m, $this->
getContext(),
2491 [ $prefix, $param, $name,
$path ] );
2493 $msgs[$param][] = $m;
2495 self::dieDebug( __METHOD__,
2496 'Value in ApiBase::PARAM_HELP_MSG_APPEND is not valid' );
2502 Hooks::run(
'APIGetParamDescriptionMessages', [ $this, &$msgs ] );
2519 if ( $this->isDeprecated() ) {
2520 $flags[] =
'deprecated';
2522 if ( $this->isInternal() ) {
2523 $flags[] =
'internal';
2525 if ( $this->isReadMode() ) {
2526 $flags[] =
'readrights';
2528 if ( $this->isWriteMode() ) {
2529 $flags[] =
'writerights';
2531 if ( $this->mustBePosted() ) {
2532 $flags[] =
'mustbeposted';
2552 if ( $this->mModuleSource !==
false ) {
2553 return $this->mModuleSource;
2557 $rClass =
new ReflectionClass( $this );
2558 $path = $rClass->getFileName();
2561 $this->mModuleSource =
null;
2567 if ( self::$extensionInfo ===
null ) {
2568 $extDir = $this->getConfig()->get(
'ExtensionDirectory' );
2569 self::$extensionInfo = [
2570 realpath( __DIR__ ) ?: __DIR__ => [
2572 'name' =>
'MediaWiki',
2573 'license-name' =>
'GPL-2.0-or-later',
2575 realpath(
"$IP/extensions" ) ?:
"$IP/extensions" =>
null,
2576 realpath( $extDir ) ?: $extDir =>
null,
2582 'license-name' =>
null,
2584 foreach ( $this->getConfig()->
get(
'ExtensionCredits' ) as $group ) {
2585 foreach ( $group as
$ext ) {
2586 if ( !isset(
$ext[
'path'] ) || !isset(
$ext[
'name'] ) ) {
2591 $extpath =
$ext[
'path'];
2592 if ( !is_dir( $extpath ) ) {
2593 $extpath = dirname( $extpath );
2595 self::$extensionInfo[realpath( $extpath ) ?: $extpath] =
2596 array_intersect_key(
$ext, $keep );
2599 foreach ( ExtensionRegistry::getInstance()->getAllThings() as
$ext ) {
2600 $extpath =
$ext[
'path'];
2601 if ( !is_dir( $extpath ) ) {
2602 $extpath = dirname( $extpath );
2604 self::$extensionInfo[realpath( $extpath ) ?: $extpath] =
2605 array_intersect_key(
$ext, $keep );
2612 if ( array_key_exists(
$path, self::$extensionInfo ) ) {
2614 $this->mModuleSource = self::$extensionInfo[
$path];
2615 return $this->mModuleSource;
2620 }
while (
$path !== $oldpath );
2623 $this->mModuleSource =
null;
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfReadOnlyReason()
Check if the site is in read-only mode and return the message if so.
wfTransactionalTimeLimit()
Set PHP's time limit to the larger of php.ini or $wgTransactionalTimeLimit.
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
This abstract class implements many basic API functions, and is the base of all API classes.
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
const PARAM_REQUIRED
(boolean) Is the parameter required?
const PARAM_MAX2
(integer) Max value allowed for the parameter for users with the apihighlimits right,...
const PARAM_SUBMODULE_MAP
(string[]) When PARAM_TYPE is 'submodule', map parameter values to submodule paths.
const PARAM_DEPRECATED
(boolean) Is the parameter deprecated (will show a warning)?
checkUserRightsAny( $rights, $user=null)
Helper function for permission-denied errors.
getParameter( $paramName, $parseLimit=true)
Get a value for the given parameter.
getModuleFromPath( $path)
Get a module from its module path.
getDB()
Gets a default replica DB connection object.
filterIDs( $fields, array $ids)
Filter out-of-range values from a list of positive integer IDs.
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
parameterNotEmpty( $x)
Callback function used in requireOnlyOneParameter to check whether required parameters are set.
static makeMessage( $msg, IContextSource $context, array $params=null)
Create a Message from a string or array.
const PARAM_MAX
(integer) Max value allowed for the parameter, for PARAM_TYPE 'integer' and 'limit'.
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
getWatchlistUser( $params)
Gets the user for whom to get the watchlist.
isDeprecated()
Indicates whether this module is deprecated.
checkTitleUserPermissions(LinkTarget $linkTarget, $actions, $options=[])
Helper function for permission-denied errors.
dieContinueUsageIf( $condition)
Die with the 'badcontinue' error.
dieWithErrorOrDebug( $msg, $code=null, $data=null, $httpCode=null)
Will only set a warning instead of failing if the global $wgDebugAPI is set to true.
const PARAM_DEPRECATED_VALUES
(array) When PARAM_TYPE is an array, this indicates which of the values are deprecated.
array null bool $mModuleSource
getParent()
Get the parent of this module.
validateUser( $value, $encParamName)
Validate and normalize parameters of type 'user'.
static dieDebug( $method, $message)
Internal code errors should be reported with this method.
getHelpUrls()
Return links to more detailed help pages about the module.
const PARAM_ISMULTI_LIMIT1
(integer) Maximum number of values, for normal users.
getModuleManager()
Get the module manager, or null if this module has no sub-modules.
parseMultiValue( $valueName, $value, $allowMultiple, $allowedValues, $allSpecifier=null, $limit1=null, $limit2=null)
Return an array of values that were given in a 'a|b|c' notation, after it optionally validates them a...
addMessagesFromStatus(StatusValue $status, $types=[ 'warning', 'error'], array $filter=[])
Add warnings and/or errors from a Status.
getMain()
Get the main module.
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below.
getCustomPrinter()
If the module may only be used with a certain format module, it should override this method to return...
setWatch( $watch, $titleObj, $userOption=null)
Set a watch (or unwatch) based the based on a watchlist parameter.
const PARAM_SENSITIVE
(boolean) Is the parameter sensitive? Note 'password'-type fields are always sensitive regardless of ...
const PARAM_HELP_MSG_INFO
(array) Specify additional information tags for the parameter.
getErrorFormatter()
Get the error formatter.
isWriteMode()
Indicates whether this module requires write mode.
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
isInternal()
Indicates whether this module is "internal" Internal API modules are not (yet) intended for 3rd party...
getFinalSummary()
Get final module summary.
requirePostedParameters( $params, $prefix='prefix')
Die if any of the specified parameters were found in the query part of the URL rather than the post b...
const PARAM_HELP_MSG_APPEND
((string|array|Message)[]) Specify additional i18n messages to append to the normal message for this ...
dieReadOnly()
Helper function for readonly errors.
const PARAM_ALLOW_DUPLICATES
(boolean) Allow the same value to be set more than once when PARAM_ISMULTI is true?
getSummaryMessage()
Return the summary message.
modifyHelp(array &$help, array $options, array &$tocData)
Called from ApiHelp before the pieces are joined together and returned.
static $blockMsgMap
$var array Map of web UI block messages to corresponding API messages and codes
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
errorArrayToStatus(array $errors, User $user=null)
Turn an array of message keys or key+param arrays into a Status.
const PARAM_VALUE_LINKS
(string[]) When PARAM_TYPE is an array, this may be an array mapping those values to page titles whic...
__construct(ApiMain $mainModule, $moduleName, $modulePrefix='')
addError( $msg, $code=null, $data=null)
Add an error for this module without aborting.
getExamplesMessages()
Returns usage examples for this module.
const PARAM_ISMULTI_LIMIT2
(integer) Maximum number of values, for users with the apihighimits right.
const PARAM_MAX_CHARS
(integer) Maximum length of a string in characters (unicode codepoints).
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, this is an array mapping those values to $msg...
addDeprecation( $msg, $feature, $data=[])
Add a deprecation warning for this module.
addBlockInfoToStatus(StatusValue $status, User $user=null)
Add block info to block messages in a Status.
getExtendedDescription()
Return the extended help text message.
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
getModuleSourceInfo()
Returns information about the source of this module, if known.
const PARAM_SUBMODULE_PARAM_PREFIX
(string) When PARAM_TYPE is 'submodule', used to indicate the 'g' prefix added by ApiQueryGeneratorBa...
const PARAM_MIN
(integer) Lowest value allowed for the parameter, for PARAM_TYPE 'integer' and 'limit'.
mustBePosted()
Indicates whether this module must be called with a POST request.
getWebUITokenSalt(array $params)
Fetch the salt used in the Web UI corresponding to this module.
static array $extensionInfo
Maps extension paths to info arrays.
const LIMIT_BIG1
Fast query, standard limit.
isMain()
Returns true if this module is the main module ($this === $this->mMainModule), false otherwise.
const LIMIT_SML2
Slow query, apihighlimits limit.
handleParamNormalization( $paramName, $value, $rawValue)
Handle when a parameter was Unicode-normalized.
validateLimit( $paramName, &$value, $min, $max, $botMax=null, $enforceLimits=false)
Validate the value against the minimum and user/bot maximum limits.
getFinalDescription()
Get final module description, after hooks have had a chance to tweak it as needed.
dieBlocked(AbstractBlock $block)
Throw an ApiUsageException, which will (if uncaught) call the main module's error handler and die wit...
const PARAM_MAX_BYTES
(integer) Maximum length of a string in bytes (in UTF-8 encoding).
warnOrDie(ApiMessage $msg, $enforceLimits=false)
Adds a warning to the output, else dies.
const PARAM_TEMPLATE_VARS
(array) Indicate that this is a templated parameter, and specify replacements.
setContinuationManager(ApiContinuationManager $manager=null)
Set the continuation manager.
getResult()
Get the result object.
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
requireMaxOneParameter( $params, $required)
Die if more than one of a certain set of parameters is set and not false.
needsToken()
Returns the token type this module requires in order to execute.
getParameterFromSettings( $paramName, $paramSettings, $parseLimit)
Using the settings determine the value for the given parameter.
getModulePath()
Get the path to this module.
const PARAM_RANGE_ENFORCE
(boolean) For PARAM_TYPE 'integer', enforce PARAM_MIN and PARAM_MAX?
logFeatureUsage( $feature)
Write logging information for API features to a debug log, for usage analysis.
const PARAM_EXTRA_NAMESPACES
(int[]) When PARAM_TYPE is 'namespace', include these as additional possible values.
shouldCheckMaxlag()
Indicates if this module needs maxlag to be checked.
getHelpFlags()
Generates the list of flags for the help screen and for action=paraminfo.
const LIMIT_SML1
Slow query, standard limit.
getFinalParams( $flags=0)
Get final list of parameters, after hooks have had a chance to tweak it as needed.
getWatchlistValue( $watchlist, $titleObj, $userOption=null)
Return true if we're to watch the page, false if not, null if no change.
isReadMode()
Indicates whether this module requires read rights.
static stdClass[][] $filterIDsCache
Cache for self::filterIDs()
dieWithException( $exception, array $options=[])
Abort execution with an error derived from an exception.
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
requireAtLeastOneParameter( $params, $required)
Die if none of a certain set of parameters is set and not false.
getTitleFromTitleOrPageId( $params)
Get a Title object from a title or pageid param, if possible.
const PARAM_ALL
(boolean|string) When PARAM_TYPE has a defined set of values and PARAM_ISMULTI is true,...
const GET_VALUES_FOR_HELP
getAllowedParams() flag: When set, the result could take longer to generate, but should be more thoro...
const LIMIT_BIG2
Fast query, apihighlimits limit.
getModuleName()
Get the name of the module being executed by this instance.
getTitleOrPageId( $params, $load=false)
Get a WikiPage object from a title or pageid param, if possible.
validateTimestamp( $value, $encParamName)
Validate and normalize parameters of type 'timestamp'.
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
getFinalParamDescription()
Get final parameter descriptions, after hooks have had a chance to tweak it as needed.
dynamicParameterDocumentation()
Indicate if the module supports dynamically-determined parameters that cannot be included in self::ge...
getContinuationManager()
Get the continuation manager.
explodeMultiValue( $value, $limit)
Split a multi-valued parameter string, like explode()
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
validateToken( $token, array $params)
Validate the supplied token.
getConditionalRequestData( $condition)
Returns data for HTTP conditional request mechanisms.
requireOnlyOneParameter( $params, $required)
Die if none or more than one of a certain set of parameters is set and not false.
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
lacksSameOriginSecurity()
Returns true if the current request breaks the same-origin policy.
This manages continuation state.
Message subclass that prepends wikitext for API help.
This is the main API class, used for both external and internal processing.
Extension of Message implementing IApiMessage.
static create( $msg, $code=null, array $data=null)
Create an IApiMessage for the message.
static getTokenTypeSalts()
Get the salts for known token types.
static getToken(User $user, MediaWiki\Session\Session $session, $salt)
Get a token from a salt.
Exception used to abort API execution with an error.
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
getContext()
Get the base IContextSource object.
setContext(IContextSource $context)
static isExternal( $username)
Tells whether the username is external or not.
The Message class provides methods which fulfil two basic services:
static listParam(array $list, $type='text')
Variant of the Message class.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
hasMessage( $message)
Returns true if the specified message is present as a warning or error.
replaceMessage( $source, $dest)
If the specified source message exists, replace it with the specified destination message,...
setOK( $ok)
Change operation status.
getErrorsByType( $type)
Returns a list of status messages of the given type.
isGood()
Returns whether the operation completed and didn't have any error or warnings.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
static doWatchOrUnwatch( $watch, Title $title, User $user)
Watch or unwatch a page.
return[ 'OATHAuth'=> function(MediaWikiServices $services) { return new OATHAuth($services->getMainConfig(), $services->getDBLoadBalancerFactory());}, 'OATHUserRepository'=> function(MediaWikiServices $services) { global $wgOATHAuthDatabase;$auth=$services->getService( 'OATHAuth');return new OATHUserRepository($services->getDBLoadBalancerFactory() ->getMainLB( $wgOATHAuthDatabase), new \HashBagOStuff(['maxKey'=> 5]), $auth);}]
Interface for objects which can provide a MediaWiki context on request.
if(!is_readable( $file)) $ext