3use Wikimedia\TestingAccessWrapper;
110 if ( !self::$main ) {
111 self::$main =
new ApiMain( RequestContext::getMain() );
112 self::$main->getContext()->setLanguage(
'en' );
113 self::$main->getContext()->setTitle(
114 Title::makeTitle(
NS_SPECIAL,
'Badtitle/dummy title for ApiStructureTest' )
127 $this->assertInstanceOf( Message::class, $msg,
"$what message" );
128 $this->assertTrue( $msg->exists(),
"$what message {$msg->getKey()} exists" );
142 RequestContext::getMain()->getConfig(),
144 foreach ( $globals as $k => $v ) {
149 $module = TestingAccessWrapper::newFromObject(
$main->getModuleFromPath( $path ) );
152 foreach ( $module->getHelpFlags() as $flag ) {
153 $this->
checkMessage(
"api-help-flag-$flag",
"Flag $flag" );
157 $this->
checkMessage( $module->getSummaryMessage(),
'Module summary' );
158 $this->
checkMessage( $module->getExtendedDescription(),
'Module help top text' );
163 foreach (
$params as $name => $settings ) {
164 if ( !is_array( $settings ) ) {
172 $msg =
"apihelp-{$path}-param-{$name}";
174 $this->
checkMessage( $msg,
"Parameter $name description" );
179 "Parameter $name PARAM_HELP_MSG_PER_VALUE is array" );
181 "Parameter $name PARAM_TYPE is array for msg-per-value mode" );
184 if ( isset( $valueMsgs[
$value] ) ) {
185 $msg = $valueMsgs[
$value];
187 $msg =
"apihelp-{$path}-paramvalue-{$name}-{$value}";
189 $this->
checkMessage( $msg,
"Parameter $name value $value" );
196 "Parameter $name PARAM_HELP_MSG_APPEND is array" );
198 $this->
checkMessage( $msg,
"Parameter $name HELP_MSG_APPEND #$i" );
206 $tags[array_shift( $i )] = 1;
212 foreach ( $tags as $tag => $dummy ) {
213 $this->
checkMessage(
"apihelp-{$path}-paraminfo-{$tag}",
"HELP_MSG_INFO tag $tag" );
217 foreach ( $module->getExamplesMessages() as $qs => $msg ) {
218 $this->assertStringStartsNotWith(
'api.php?', $qs,
219 "Query string must not begin with 'api.php?'" );
227 array_unshift( $paths,
$main->getModulePath() );
230 foreach ( $paths as $path ) {
231 foreach ( self::$testGlobals as $globals ) {
233 foreach ( $globals as $k => $v ) {
234 $g[] =
"$k=" . var_export( $v, 1 );
236 $k =
"Module $path with " . implode(
', ', $g );
249 $module = TestingAccessWrapper::newFromObject(
$main->getModuleFromPath( $path ) );
251 $paramsPlain = $module->getFinalParams();
255 $this->assertTrue(
true );
257 if ( self::$constantNames ===
null ) {
258 self::$constantNames = [];
260 foreach ( (
new ReflectionClass(
'ApiBase' ) )->getConstants() as $key => $val ) {
261 if ( substr( $key, 0, 6 ) ===
'PARAM_' ) {
262 self::$constantNames[$val] = $key;
267 foreach ( [ $paramsPlain, $paramsForHelp ] as
$params ) {
268 foreach (
$params as $param => $config ) {
269 if ( !is_array( $config ) ) {
278 foreach ( self::$paramTypes as $key => $types ) {
279 if ( !isset( $config[$key] ) ) {
282 $keyName = self::$constantNames[$key];
283 $this->
validateType( $types, $config[$key], $param, $keyName );
286 foreach ( self::$paramRequirements as $key => $required ) {
287 if ( !isset( $config[$key] ) ) {
290 foreach ( $required as $requireKey => $requireVal ) {
291 $this->assertArrayHasKey( $requireKey, $config,
292 "$param: When " . self::$constantNames[$key] .
" is set, " .
293 self::$constantNames[$requireKey] .
" must also be set" );
294 if ( $requireVal !==
null ) {
295 $this->assertSame( $requireVal, $config[$requireKey],
296 "$param: When " . self::$constantNames[$key] .
" is set, " .
297 self::$constantNames[$requireKey] .
" must equal " .
298 var_export( $requireVal,
true ) );
303 foreach ( self::$paramAllowedTypes as $key => $allowedTypes ) {
304 if ( !isset( $config[$key] ) ) {
311 $this->assertContains(
313 (
array)$allowedTypes,
314 "$param: " . self::$constantNames[$key] .
315 " can only be used with PARAM_TYPE " .
316 implode(
', ', (
array)$allowedTypes )
320 foreach ( self::$paramProhibitedTypes as $key => $prohibitedTypes ) {
321 if ( !isset( $config[$key] ) ) {
328 $this->assertNotContains(
330 (
array)$prohibitedTypes,
331 "$param: " . self::$constantNames[$key] .
332 " cannot be used with PARAM_TYPE " .
333 implode(
', ', (
array)$prohibitedTypes )
341 "$param: A required parameter cannot have a default" );
350 "$param: PARAM_MAX and PARAM_MAX2 are required for limits"
352 $this->assertGreaterThanOrEqual(
355 "$param: PARAM_MAX cannot be greater than PARAM_MAX2"
363 $this->assertGreaterThanOrEqual(
366 "$param: PARAM_MIN cannot be greater than PARAM_MAX"
374 "$param: PARAM_RANGE_ENFORCE can only be set together with " .
375 "PARAM_MIN or PARAM_MAX"
382 "$param: Deprecated value \"$key\" is not allowed, " .
383 "how can it be deprecated?" );
392 "$param: PARAM_ISMULTI_LIMIT1 cannot be negative" );
396 "$param: PARAM_ISMULTI_LIMIT2 cannot be negative or zero" );
397 $this->assertGreaterThanOrEqual(
400 "$param: PARAM_ISMULTI limit cannot be smaller for users with " .
401 "apihighlimits rights" );
406 "$param: PARAM_MAX_BYTES cannot be negative or zero" );
411 "$param: PARAM_MAX_CHARS cannot be negative or zero" );
420 $this->assertGreaterThanOrEqual(
423 "$param: PARAM_MAX_BYTES cannot be less than PARAM_MAX_CHARS"
429 "$param: PARAM_TEMPLATE_VARS cannot be empty" );
431 $this->assertRegExp(
'/^[^{}]+$/', $key,
432 "$param: PARAM_TEMPLATE_VARS key may not contain '{' or '}'" );
434 $this->assertContains(
'{' . $key .
'}', $param,
435 "$param: Name must contain PARAM_TEMPLATE_VARS key {" . $key .
"}" );
436 $this->assertArrayHasKey( $target,
$params,
437 "$param: PARAM_TEMPLATE_VARS target parameter '$target' does not exist" );
440 "$param: PARAM_TEMPLATE_VARS target parameter '$target' must have PARAM_ISMULTI = true" );
443 $this->assertNotSame( $param, $target,
444 "$param: PARAM_TEMPLATE_VARS cannot target itself" );
446 $this->assertArraySubset(
450 "$param: PARAM_TEMPLATE_VARS target parameter '$target': "
451 .
"the target's PARAM_TEMPLATE_VARS must be a subset of the original."
456 $keys = implode(
'|',
459 return preg_quote( $key,
'/' );
464 $this->assertRegExp(
'/^(?>[^{}]+|\{(?:' .
$keys .
')\})+$/', $param,
465 "$param: Name may not contain '{' or '}' other than as defined by PARAM_TEMPLATE_VARS" );
467 $this->assertRegExp(
'/^[^{}]+$/', $param,
468 "$param: Name may not contain '{' or '}' without PARAM_TEMPLATE_VARS" );
483 if ( count( $types ) === 1 ) {
485 if ( is_string( $types[0] ) ) {
489 $this->assertInternalType(
'array',
$value,
"$param: $desc type" );
490 foreach (
$value as $subvalue ) {
491 $this->
validateType( $types[0], $subvalue, $param,
"$desc value" );
496 foreach ( $types as
$type ) {
497 if ( is_string(
$type ) ) {
498 if ( class_exists(
$type ) || interface_exists(
$type ) ) {
513 }
catch ( Exception $unused ) {
518 $this->fail(
"$param: $desc has incorrect type" );
533 if ( $default ===
'' ) {
537 $defaults = explode(
'|', $default );
539 foreach ( $defaults as $defaultValue ) {
542 if (
$type ===
'integer' && $defaultValue === (
string)(
int)$defaultValue ) {
543 $defaultValue = (int)$defaultValue;
552 $this->assertFalse( $default,
553 "$param: Boolean params may only default to false" );
557 $this->assertInternalType(
'integer', $default,
558 "$param: Default $default is not an integer" );
562 if ( $default ===
'max' ) {
565 $this->assertInternalType(
'integer', $default,
566 "$param: Default $default is neither an integer nor \"max\"" );
570 $validValues = MWNamespace::getValidNamespaces();
575 $validValues = array_merge(
580 $this->assertContains( $default, $validValues,
581 "$param: Default $default is not a valid namespace" );
590 $this->assertInternalType(
'string', $default,
591 "$param: Default $default is not a string" );
595 if ( $default ===
'now' ) {
598 $this->assertNotFalse(
wfTimestamp( TS_MW, $default ),
599 "$param: Default $default is not a valid timestamp" );
606 $wrapper = TestingAccessWrapper::newFromObject(
new ApiMain() );
608 $wrapper->validateUser( $default,
'' );
610 $this->fail(
"$param: Default $default is not a valid username/IP address" );
615 if ( is_array(
$type ) ) {
616 $this->assertContains( $default,
$type,
617 "$param: Default $default is not any of " .
618 implode(
', ',
$type ) );
620 $this->fail(
"Unrecognized type $type" );
631 array_unshift( $paths,
$main->getModulePath() );
634 foreach ( $paths as $path ) {
647 foreach ( $manager->
getNames() as $name ) {
649 $paths[] = $module->getModulePath();
650 $subManager = $module->getModuleManager();
652 $paths = array_merge( $paths, self::getSubModulePaths( $subManager ) );
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
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)?
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'.
const PARAM_DEPRECATED_VALUES
(array) When PARAM_TYPE is an array, this indicates which of the values are deprecated.
const PARAM_ISMULTI_LIMIT1
(integer) Maximum number of values, for normal users.
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below.
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.
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
const PARAM_HELP_MSG_APPEND
((string|array|Message)[]) Specify additional i18n messages to append to the normal message for this ...
const PARAM_ALLOW_DUPLICATES
(boolean) Allow the same value to be set more than once when PARAM_ISMULTI is true?
const PARAM_VALUE_LINKS
(string[]) When PARAM_TYPE is an array, this may be an array mapping those values to page titles whic...
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...
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'.
const PARAM_MAX_BYTES
(integer) Maximum length of a string in bytes (in UTF-8 encoding).
const PARAM_TEMPLATE_VARS
(array) Indicate that this is a templated parameter, and specify replacements.
const PARAM_RANGE_ENFORCE
(boolean) For PARAM_TYPE 'integer', enforce PARAM_MIN and PARAM_MAX?
const PARAM_EXTRA_NAMESPACES
(int[]) When PARAM_TYPE is 'namespace', include these as additional possible values.
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
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 PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
This is the main API class, used for both external and internal processing.
This class holds a list of modules and handles instantiation.
getModule( $moduleName, $group=null, $ignoreCache=false)
Get module instance by name, or instantiate it if it does not exist.
getNames( $group=null)
Get an array of modules in a specific group or all if no group is set.
Checks that all API modules, core and extensions, conform to the conventions:
static provideDocumentationExists()
static $paramAllowedTypes
static array $testGlobals
Sets of globals to test.
static $paramTypes
Values are an array, where each array value is a permitted type.
static provideParameterConsistency()
static getSubModulePaths(ApiModuleManager $manager)
Return paths of all submodules in an ApiModuleManager, recursively.
testDocumentationExists( $path, array $globals)
provideDocumentationExists
static $paramProhibitedTypes
testParameterConsistency( $path)
provideParameterConsistency
validateDefault( $param, $config)
Asserts that $default is a valid default for $type.
checkMessage( $msg, $what)
Test a message.
validateType( $types, $value, $param, $desc)
Throws if $value does not match one of the types specified in $types.
static $paramRequirements
static getMain()
Initialize/fetch the ApiMain instance for testing.
Exception used to abort API execution with an error.
A Config instance which stores all settings as a member variable.
Provides a fallback sequence for Config objects.
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
returning false will NOT prevent logging $e
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))