MediaWiki  master
ApiQuerySiteinfoTest.php
Go to the documentation of this file.
1 <?php
2 
4 
13  // We don't try to test every single thing for every category, just a sample
14 
15  protected function doQuery( $siprop = null, $extraParams = [] ) {
16  $params = [ 'action' => 'query', 'meta' => 'siteinfo' ];
17  if ( $siprop !== null ) {
18  $params['siprop'] = $siprop;
19  }
20  $params = array_merge( $params, $extraParams );
21 
22  $res = $this->doApiRequest( $params );
23 
24  $this->assertArrayNotHasKey( 'warnings', $res[0] );
25  $this->assertCount( 1, $res[0]['query'] );
26 
27  return $res[0]['query'][$siprop === null ? 'general' : $siprop];
28  }
29 
30  public function testGeneral() {
31  $this->setMwGlobals( [
32  'wgAllowExternalImagesFrom' => '//localhost/',
33  ] );
34 
35  $data = $this->doQuery();
36 
37  $this->assertSame( Title::newMainPage()->getPrefixedText(), $data['mainpage'] );
38  $this->assertSame( PHP_VERSION, $data['phpversion'] );
39  $this->assertSame( [ '//localhost/' ], $data['externalimages'] );
40  }
41 
42  public function testLinkPrefixCharset() {
43  $contLang = Language::factory( 'ar' );
44  $this->setContentLang( $contLang );
45  $this->assertTrue( $contLang->linkPrefixExtension(), 'Sanity check' );
46 
47  $data = $this->doQuery();
48 
49  $this->assertSame( $contLang->linkPrefixCharset(), $data['linkprefixcharset'] );
50  }
51 
52  public function testVariants() {
53  $contLang = Language::factory( 'zh' );
54  $this->setContentLang( $contLang );
55  $this->assertTrue( $contLang->hasVariants(), 'Sanity check' );
56 
57  $data = $this->doQuery();
58 
59  $expected = array_map(
60  function ( $code ) use ( $contLang ) {
61  return [ 'code' => $code, 'name' => $contLang->getVariantname( $code ) ];
62  },
63  $contLang->getVariants()
64  );
65 
66  $this->assertSame( $expected, $data['variants'] );
67  }
68 
69  public function testReadOnly() {
70  $svc = MediaWikiServices::getInstance()->getReadOnlyMode();
71  $svc->setReason( 'Need more donations' );
72  try {
73  $data = $this->doQuery();
74  } finally {
75  $svc->setReason( false );
76  }
77 
78  $this->assertTrue( $data['readonly'] );
79  $this->assertSame( 'Need more donations', $data['readonlyreason'] );
80  }
81 
82  public function testNamespaces() {
83  $this->setMwGlobals( 'wgExtraNamespaces', [ '138' => 'Testing' ] );
84 
85  $this->assertSame(
86  array_keys( MediaWikiServices::getInstance()->getContentLanguage()->getFormattedNamespaces() ),
87  array_keys( $this->doQuery( 'namespaces' ) )
88  );
89  }
90 
91  public function testNamespaceAliases() {
92  global $wgNamespaceAliases;
93 
94  $expected = array_merge(
95  $wgNamespaceAliases,
96  MediaWikiServices::getInstance()->getContentLanguage()->getNamespaceAliases()
97  );
98  $expected = array_map(
99  function ( $key, $val ) {
100  return [ 'id' => $val, 'alias' => strtr( $key, '_', ' ' ) ];
101  },
102  array_keys( $expected ),
103  $expected
104  );
105 
106  // Test that we don't list duplicates
107  $this->mergeMwGlobalArrayValue( 'wgNamespaceAliases', [ 'Talk' => NS_TALK ] );
108 
109  $this->assertSame( $expected, $this->doQuery( 'namespacealiases' ) );
110  }
111 
112  public function testSpecialPageAliases() {
113  $this->assertCount(
114  count( MediaWikiServices::getInstance()->getSpecialPageFactory()->getNames() ),
115  $this->doQuery( 'specialpagealiases' )
116  );
117  }
118 
119  public function testMagicWords() {
120  $this->assertCount(
121  count( MediaWikiServices::getInstance()->getContentLanguage()->getMagicWords() ),
122  $this->doQuery( 'magicwords' )
123  );
124  }
125 
129  public function testInterwikiMap( $filter ) {
130  global $wgServer, $wgScriptPath;
131 
132  $dbw = wfGetDB( DB_MASTER );
133  $dbw->insert(
134  'interwiki',
135  [
136  [
137  'iw_prefix' => 'self',
138  'iw_url' => "$wgServer$wgScriptPath/index.php?title=$1",
139  'iw_api' => "$wgServer$wgScriptPath/api.php",
140  'iw_wikiid' => 'somedbname',
141  'iw_local' => true,
142  'iw_trans' => true,
143  ],
144  [
145  'iw_prefix' => 'foreign',
146  'iw_url' => '//foreign.example/wiki/$1',
147  'iw_api' => '',
148  'iw_wikiid' => '',
149  'iw_local' => false,
150  'iw_trans' => false,
151  ],
152  ],
153  __METHOD__,
154  'IGNORE'
155  );
156  $this->tablesUsed[] = 'interwiki';
157 
158  $this->setMwGlobals( [
159  'wgLocalInterwikis' => [ 'self' ],
160  'wgExtraInterlanguageLinkPrefixes' => [ 'self' ],
161  'wgExtraLanguageNames' => [ 'self' => 'Recursion' ],
162  ] );
163 
164  MessageCache::singleton()->enable();
165 
166  $this->editPage( 'MediaWiki:Interlanguage-link-self', 'Self!' );
167  $this->editPage( 'MediaWiki:Interlanguage-link-sitename-self', 'Circular logic' );
168 
169  $expected = [];
170 
171  if ( $filter === null || $filter === '!local' ) {
172  $expected[] = [
173  'prefix' => 'foreign',
174  'url' => wfExpandUrl( '//foreign.example/wiki/$1', PROTO_CURRENT ),
175  'protorel' => true,
176  ];
177  }
178  if ( $filter === null || $filter === 'local' ) {
179  $expected[] = [
180  'prefix' => 'self',
181  'local' => true,
182  'trans' => true,
183  'language' => 'Recursion',
184  'localinterwiki' => true,
185  'extralanglink' => true,
186  'linktext' => 'Self!',
187  'sitename' => 'Circular logic',
188  'url' => "$wgServer$wgScriptPath/index.php?title=$1",
189  'protorel' => false,
190  'wikiid' => 'somedbname',
191  'api' => "$wgServer$wgScriptPath/api.php",
192  ];
193  }
194 
195  $data = $this->doQuery( 'interwikimap',
196  $filter === null ? [] : [ 'sifilteriw' => $filter ] );
197 
198  $this->assertSame( $expected, $data );
199  }
200 
201  public function interwikiMapProvider() {
202  return [ [ 'local' ], [ '!local' ], [ null ] ];
203  }
204 
208  public function testDbReplLagInfo( $showHostnames, $includeAll ) {
209  if ( !$showHostnames && $includeAll ) {
210  $this->setExpectedApiException( 'apierror-siteinfo-includealldenied' );
211  }
212 
213  $mockLB = $this->getMockBuilder( LoadBalancer::class )
214  ->disableOriginalConstructor()
215  ->setMethods( [ 'getMaxLag', 'getLagTimes', 'getServerName', '__destruct' ] )
216  ->getMock();
217  $mockLB->method( 'getMaxLag' )->willReturn( [ null, 7, 1 ] );
218  $mockLB->method( 'getLagTimes' )->willReturn( [ 5, 7 ] );
219  $mockLB->method( 'getServerName' )->will( $this->returnValueMap( [
220  [ 0, 'apple' ], [ 1, 'carrot' ]
221  ] ) );
222  $this->setService( 'DBLoadBalancer', $mockLB );
223 
224  $this->setMwGlobals( 'wgShowHostnames', $showHostnames );
225 
226  $expected = [];
227  if ( $includeAll ) {
228  $expected[] = [ 'host' => $showHostnames ? 'apple' : '', 'lag' => 5 ];
229  }
230  $expected[] = [ 'host' => $showHostnames ? 'carrot' : '', 'lag' => 7 ];
231 
232  $data = $this->doQuery( 'dbrepllag', $includeAll ? [ 'sishowalldb' => '' ] : [] );
233 
234  $this->assertSame( $expected, $data );
235  }
236 
237  public function dbReplLagProvider() {
238  return [
239  'no hostnames, no showalldb' => [ false, false ],
240  'no hostnames, showalldb' => [ false, true ],
241  'hostnames, no showalldb' => [ true, false ],
242  'hostnames, showalldb' => [ true, true ]
243  ];
244  }
245 
246  public function testStatistics() {
247  $this->setTemporaryHook( 'APIQuerySiteInfoStatisticsInfo',
248  function ( &$data ) {
249  $data['addedstats'] = 42;
250  }
251  );
252 
253  $expected = [
254  'pages' => intval( SiteStats::pages() ),
255  'articles' => intval( SiteStats::articles() ),
256  'edits' => intval( SiteStats::edits() ),
257  'images' => intval( SiteStats::images() ),
258  'users' => intval( SiteStats::users() ),
259  'activeusers' => intval( SiteStats::activeUsers() ),
260  'admins' => intval( SiteStats::numberingroup( 'sysop' ) ),
261  'jobs' => intval( SiteStats::jobs() ),
262  'addedstats' => 42,
263  ];
264 
265  $this->assertSame( $expected, $this->doQuery( 'statistics' ) );
266  }
267 
271  public function testUserGroups( $numInGroup ) {
273 
274  $this->setGroupPermissions( 'viscount', 'perambulate', 'yes' );
275  $this->setGroupPermissions( 'viscount', 'legislate', '0' );
276  $this->setMwGlobals( [
277  'wgAddGroups' => [ 'viscount' => true, 'bot' => [] ],
278  'wgRemoveGroups' => [ 'viscount' => [ 'sysop' ], 'bot' => [ '*', 'earl' ] ],
279  'wgGroupsAddToSelf' => [ 'bot' => [ 'bureaucrat', 'sysop' ] ],
280  'wgGroupsRemoveFromSelf' => [ 'bot' => [ 'bot' ] ],
281  ] );
282 
283  $data = $this->doQuery( 'usergroups', $numInGroup ? [ 'sinumberingroup' => '' ] : [] );
284 
285  $names = array_map(
286  function ( $val ) {
287  return $val['name'];
288  },
289  $data
290  );
291 
292  $this->assertSame( array_keys( $wgGroupPermissions ), $names );
293 
294  foreach ( $data as $val ) {
295  if ( !$numInGroup ) {
296  $expectedSize = null;
297  } elseif ( $val['name'] === 'user' ) {
298  $expectedSize = SiteStats::users();
299  } elseif ( $val['name'] === '*' || isset( $wgAutopromote[$val['name']] ) ) {
300  $expectedSize = null;
301  } else {
302  $expectedSize = SiteStats::numberingroup( $val['name'] );
303  }
304 
305  if ( $expectedSize === null ) {
306  $this->assertArrayNotHasKey( 'number', $val );
307  } else {
308  $this->assertSame( $expectedSize, $val['number'] );
309  }
310 
311  if ( $val['name'] === 'viscount' ) {
312  $viscountFound = true;
313  $this->assertSame( [ 'perambulate' ], $val['rights'] );
314  $this->assertSame( User::getAllGroups(), $val['add'] );
315  } elseif ( $val['name'] === 'bot' ) {
316  $this->assertArrayNotHasKey( 'add', $val );
317  $this->assertArrayNotHasKey( 'remove', $val );
318  $this->assertSame( [ 'bureaucrat', 'sysop' ], $val['add-self'] );
319  $this->assertSame( [ 'bot' ], $val['remove-self'] );
320  }
321  }
322  }
323 
324  public function testFileExtensions() {
325  global $wgFileExtensions;
326 
327  // Add duplicate
328  $this->setMwGlobals( 'wgFileExtensions', array_merge( $wgFileExtensions, [ 'png' ] ) );
329 
330  $expected = array_map(
331  function ( $val ) {
332  return [ 'ext' => $val ];
333  },
334  array_unique( $wgFileExtensions )
335  );
336 
337  $this->assertSame( $expected, $this->doQuery( 'fileextensions' ) );
338  }
339 
340  public function groupsProvider() {
341  return [
342  'numingroup' => [ true ],
343  'nonumingroup' => [ false ],
344  ];
345  }
346 
347  public function testInstalledLibraries() {
348  // @todo Test no installed.json? Moving installed.json to a different name temporarily
349  // seems a bit scary, but I don't see any other way to do it.
350  //
351  // @todo Install extensions/skins somehow so that we can test they're filtered out
352  global $IP;
353 
354  $path = "$IP/vendor/composer/installed.json";
355  if ( !file_exists( $path ) ) {
356  $this->markTestSkipped( 'No installed libraries' );
357  }
358 
359  $expected = ( new ComposerInstalled( $path ) )->getInstalledDependencies();
360 
361  $expected = array_filter( $expected,
362  function ( $info ) {
363  return strpos( $info['type'], 'mediawiki-' ) !== 0;
364  }
365  );
366 
367  $expected = array_map(
368  function ( $name, $info ) {
369  return [ 'name' => $name, 'version' => $info['version'] ];
370  },
371  array_keys( $expected ),
372  array_values( $expected )
373  );
374 
375  $this->assertSame( $expected, $this->doQuery( 'libraries' ) );
376  }
377 
378  public function testExtensions() {
379  $tmpdir = $this->getNewTempDirectory();
380  touch( "$tmpdir/ErsatzExtension.php" );
381  touch( "$tmpdir/LICENSE" );
382  touch( "$tmpdir/AUTHORS.txt" );
383 
384  $val = [
385  'path' => "$tmpdir/ErsatzExtension.php",
386  'name' => 'Ersatz Extension',
387  'namemsg' => 'ersatz-extension-name',
388  'author' => 'John Smith',
389  'version' => '0.0.2',
390  'url' => 'https://www.example.com/software/ersatz-extension',
391  'description' => 'An extension that is not what it seems.',
392  'descriptionmsg' => 'ersatz-extension-desc',
393  'license-name' => 'PD',
394  ];
395 
396  $this->setMwGlobals( 'wgExtensionCredits', [ 'api' => [
397  $val,
398  [
399  'author' => [ 'John Smith', 'John Smith Jr.', '...' ],
400  'descriptionmsg' => [ 'another-extension-desc', 'param' ] ],
401  ] ] );
402 
403  $data = $this->doQuery( 'extensions' );
404 
405  $this->assertCount( 2, $data );
406 
407  $this->assertSame( 'api', $data[0]['type'] );
408 
409  $sharedKeys = [ 'name', 'namemsg', 'description', 'descriptionmsg', 'author', 'url',
410  'version', 'license-name' ];
411  foreach ( $sharedKeys as $key ) {
412  $this->assertSame( $val[$key], $data[0][$key] );
413  }
414 
415  // @todo Test git info
416 
417  $this->assertSame(
418  Title::newFromText( 'Special:Version/License/Ersatz Extension' )->getLinkURL(),
419  $data[0]['license']
420  );
421 
422  $this->assertSame(
423  Title::newFromText( 'Special:Version/Credits/Ersatz Extension' )->getLinkURL(),
424  $data[0]['credits']
425  );
426 
427  $this->assertSame( 'another-extension-desc', $data[1]['descriptionmsg'] );
428  $this->assertSame( [ 'param' ], $data[1]['descriptionmsgparams'] );
429  $this->assertSame( 'John Smith, John Smith Jr., ...', $data[1]['author'] );
430  }
431 
435  public function testRightsInfo( $page, $url, $text, $expectedUrl, $expectedText ) {
436  $this->setMwGlobals( [
437  'wgRightsPage' => $page,
438  'wgRightsUrl' => $url,
439  'wgRightsText' => $text,
440  ] );
441 
442  $this->assertSame(
443  [ 'url' => $expectedUrl, 'text' => $expectedText ],
444  $this->doQuery( 'rightsinfo' )
445  );
446  }
447 
448  public function rightsInfoProvider() {
449  $textUrl = wfExpandUrl( Title::newFromText( 'License' ), PROTO_CURRENT );
450  $url = 'http://license.example/';
451 
452  return [
453  'No rights info' => [ null, null, null, '', '' ],
454  'Only page' => [ 'License', null, null, $textUrl, 'License' ],
455  'Only URL' => [ null, $url, null, $url, '' ],
456  'Only text' => [ null, null, '!!!', '', '!!!' ],
457  // URL is ignored if page is specified
458  'Page and URL' => [ 'License', $url, null, $textUrl, 'License' ],
459  'URL and text' => [ null, $url, '!!!', $url, '!!!' ],
460  'Page and text' => [ 'License', null, '!!!', $textUrl, '!!!' ],
461  'Page and URL and text' => [ 'License', $url, '!!!', $textUrl, '!!!' ],
462  'Pagename "0"' => [ '0', null, null,
463  wfExpandUrl( Title::newFromText( '0' ), PROTO_CURRENT ), '0' ],
464  'URL "0"' => [ null, '0', null, '0', '' ],
465  'Text "0"' => [ null, null, '0', '', '0' ],
466  ];
467  }
468 
469  public function testRestrictions() {
472 
473  $this->assertSame( [
474  'types' => $wgRestrictionTypes,
475  'levels' => $wgRestrictionLevels,
476  'cascadinglevels' => $wgCascadingRestrictionLevels,
477  'semiprotectedlevels' => $wgSemiprotectedRestrictionLevels,
478  ], $this->doQuery( 'restrictions' ) );
479  }
480 
484  public function testLanguages( $langCode ) {
485  $expected = Language::fetchLanguageNames( (string)$langCode );
486 
487  $expected = array_map(
488  function ( $code, $name ) {
489  return [
490  'code' => $code,
491  'bcp47' => LanguageCode::bcp47( $code ),
492  'name' => $name
493  ];
494  },
495  array_keys( $expected ),
496  array_values( $expected )
497  );
498 
499  $data = $this->doQuery( 'languages',
500  $langCode !== null ? [ 'siinlanguagecode' => $langCode ] : [] );
501 
502  $this->assertSame( $expected, $data );
503  }
504 
505  public function languagesProvider() {
506  return [ [ null ], [ 'fr' ] ];
507  }
508 
509  public function testLanguageVariants() {
510  $expectedKeys = array_filter( LanguageConverter::$languagesWithVariants,
511  function ( $langCode ) {
512  return !Language::factory( $langCode )->getConverter() instanceof FakeConverter;
513  }
514  );
515  sort( $expectedKeys );
516 
517  $this->assertSame( $expectedKeys, array_keys( $this->doQuery( 'languagevariants' ) ) );
518  }
519 
520  public function testLanguageVariantsDisabled() {
521  $this->setMwGlobals( 'wgDisableLangConversion', true );
522 
523  $this->assertSame( [], $this->doQuery( 'languagevariants' ) );
524  }
525 
534  public function testSkins( $code ) {
535  $data = $this->doQuery( 'skins', $code !== null ? [ 'siinlanguagecode' => $code ] : [] );
536 
537  $expectedAllowed = Skin::getAllowedSkins();
538  $expectedDefault = Skin::normalizeKey( 'default' );
539 
540  $i = 0;
541  foreach ( Skin::getSkinNames() as $name => $displayName ) {
542  $this->assertSame( $name, $data[$i]['code'] );
543 
544  $msg = wfMessage( "skinname-$name" );
545  if ( $code && Language::isValidCode( $code ) ) {
546  $msg->inLanguage( $code );
547  } else {
548  $msg->inContentLanguage();
549  }
550  if ( $msg->exists() ) {
551  $displayName = $msg->text();
552  }
553  $this->assertSame( $displayName, $data[$i]['name'] );
554 
555  if ( !isset( $expectedAllowed[$name] ) ) {
556  $this->assertTrue( $data[$i]['unusable'], "$name must be unusable" );
557  }
558  if ( $name === $expectedDefault ) {
559  $this->assertTrue( $data[$i]['default'], "$expectedDefault must be default" );
560  }
561  $i++;
562  }
563  }
564 
565  public function skinsProvider() {
566  return [
567  'No language specified' => [ null ],
568  'Czech' => [ 'cs' ],
569  'Invalid language' => [ '/invalid/' ],
570  ];
571  }
572 
573  public function testExtensionTags() {
574  $expected = array_map(
575  function ( $tag ) {
576  return "<$tag>";
577  },
578  MediaWikiServices::getInstance()->getParser()->getTags()
579  );
580 
581  $this->assertSame( $expected, $this->doQuery( 'extensiontags' ) );
582  }
583 
584  public function testFunctionHooks() {
585  $this->assertSame( MediaWikiServices::getInstance()->getParser()->getFunctionHooks(),
586  $this->doQuery( 'functionhooks' ) );
587  }
588 
589  public function testVariables() {
590  $this->assertSame(
591  MediaWikiServices::getInstance()->getMagicWordFactory()->getVariableIDs(),
592  $this->doQuery( 'variables' )
593  );
594  }
595 
596  public function testProtocols() {
597  global $wgUrlProtocols;
598 
599  $this->assertSame( $wgUrlProtocols, $this->doQuery( 'protocols' ) );
600  }
601 
602  public function testDefaultOptions() {
603  $this->assertSame( User::getDefaultOptions(), $this->doQuery( 'defaultoptions' ) );
604  }
605 
606  public function testUploadDialog() {
607  global $wgUploadDialog;
608 
609  $this->assertSame( $wgUploadDialog, $this->doQuery( 'uploaddialog' ) );
610  }
611 
612  public function testGetHooks() {
613  global $wgHooks;
614 
615  // Make sure there's something to report on
616  $this->setTemporaryHook( 'somehook',
617  function () {
618  return;
619  }
620  );
621 
622  $expectedNames = $wgHooks;
623  ksort( $expectedNames );
624 
625  $actualNames = array_map(
626  function ( $val ) {
627  return $val['name'];
628  },
629  $this->doQuery( 'showhooks' )
630  );
631 
632  $this->assertSame( array_keys( $expectedNames ), $actualNames );
633  }
634 
635  public function testContinuation() {
636  // We make lots and lots of URL protocols that are each 100 bytes
638 
639  $this->setMwGlobals( 'wgUrlProtocols', [] );
640 
641  // Just under the limit
642  $chunks = $wgAPIMaxResultSize / 100 - 1;
643 
644  for ( $i = 0; $i < $chunks; $i++ ) {
645  $wgUrlProtocols[] = substr( str_repeat( "$i ", 50 ), 0, 100 );
646  }
647 
648  $res = $this->doApiRequest( [
649  'action' => 'query',
650  'meta' => 'siteinfo',
651  'siprop' => 'protocols|languages',
652  ] );
653 
654  $this->assertSame(
655  wfMessage( 'apiwarn-truncatedresult', Message::numParam( $wgAPIMaxResultSize ) )
656  ->text(),
657  $res[0]['warnings']['result']['warnings']
658  );
659 
660  $this->assertSame( $wgUrlProtocols, $res[0]['query']['protocols'] );
661  $this->assertArrayNotHasKey( 'languages', $res[0] );
662  $this->assertTrue( $res[0]['batchcomplete'], 'batchcomplete should be true' );
663  $this->assertSame( [ 'siprop' => 'languages', 'continue' => '-||' ], $res[0]['continue'] );
664  }
665 }
editPage( $pageName, $text, $summary='', $defaultNs=NS_MAIN, User $user=null)
Edits or creates a page/revision.
setTemporaryHook( $hookName, $handler)
Create a temporary hook handler which will be reset by tearDown.
static fetchLanguageNames( $inLanguage=self::AS_AUTONYMS, $include='mw')
Get an array of language names, indexed by code.
Definition: Language.php:840
static normalizeKey( $key)
Normalize a skin preference value to a form that can be loaded.
Definition: Skin.php:102
static jobs()
Total number of jobs in the job queue.
Definition: SiteStats.php:179
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:187
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
Definition: Title.php:653
$IP
Definition: WebStart.php:41
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
$wgRestrictionLevels
Rights which can be required for each protection level (via action=protect)
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
static getSkinNames()
Fetch the set of available skins.
Definition: Skin.php:57
doApiRequest(array $params, array $session=null, $appendModule=false, User $user=null, $tokenType=null)
Does the API request and returns the result.
Definition: ApiTestCase.php:62
const PROTO_CURRENT
Definition: Defines.php:218
A fake language variant converter.
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency MediaWikiServices
Definition: injection.txt:23
$wgUrlProtocols
URL schemes that should be recognized as valid by wfParseUrl().
$wgNamespaceAliases
Namespace aliases.
static activeUsers()
Definition: SiteStats.php:130
$wgSemiprotectedRestrictionLevels
Restriction levels that should be considered "semiprotected".
mergeMwGlobalArrayValue( $name, $values)
Merges the given values into a MW global array variable.
testUserGroups( $numInGroup)
groupsProvider
$wgUploadDialog
Configuration for file uploads using the embeddable upload dialog (https://www.mediawiki.org/wiki/Upload_dialog).
static numParam( $num)
Definition: Message.php:1049
testRightsInfo( $page, $url, $text, $expectedUrl, $expectedText)
rightsInfoProvider
This list may contain false positives That usually means there is additional text with links below the first Each row contains links to the first and second as well as the first line of the second redirect text
const DB_MASTER
Definition: defines.php:26
$wgRestrictionTypes
Set of available actions that can be restricted via action=protect You probably shouldn&#39;t change this...
testInterwikiMap( $filter)
interwikiMapProvider
static getAllGroups()
Return the set of defined explicit groups.
Definition: User.php:5007
$wgGroupPermissions
Permission keys given to users in each group.
static numberingroup( $group)
Find the number of users in a given user group.
Definition: SiteStats.php:150
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
Definition: hooks.txt:1982
doQuery( $siprop=null, $extraParams=[])
static edits()
Definition: SiteStats.php:94
either a unescaped string or a HtmlArmor object after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation use $formDescriptor instead default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "&lt
$wgHooks['ArticleShow'][]
Definition: hooks.txt:108
setGroupPermissions( $newPerms, $newKey=null, $newValue=null)
Alters $wgGroupPermissions for the duration of the test.
testDbReplLagInfo( $showHostnames, $includeAll)
dbReplLagProvider
$res
Definition: database.txt:21
$params
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that When $user is not null
Definition: hooks.txt:780
$filter
static factory( $code)
Get a cached or new language object for a given language code.
Definition: Language.php:216
setMwGlobals( $pairs, $value=null)
Sets a global, maintaining a stashed version of the previous global to be restored in tearDown...
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that When $user is not it can be in the form of< username >< more info > e g for bot passwords intended to be added to log contexts Fields it might only if the login was with a bot password it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable & $code
Definition: hooks.txt:780
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
$wgAutopromote
Array containing the conditions of automatic promotion of a user to specific groups.
static images()
Definition: SiteStats.php:139
setService( $name, $object)
Sets a service, maintaining a stashed version of the previous service to be restored in tearDown...
$wgFileExtensions
This is the list of preferred extensions for uploading files.
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
API medium Database.
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
$wgScriptPath
The path we should point to.
static articles()
Definition: SiteStats.php:103
static pages()
Definition: SiteStats.php:112
$wgAPIMaxResultSize
The maximum size (in bytes) of an API result.
getNewTempDirectory()
obtains a new temporary directory
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:271
$wgServer
URL of the server.
const NS_TALK
Definition: Defines.php:61
Reads an installed.json file and provides accessors to get what is installed.
static getDefaultOptions()
Combine the language default options with any site-specific options and add the default language vari...
Definition: User.php:1750
static isValidCode( $code)
Returns true if a language code string is of a valid form, whether or not it exists.
Definition: Language.php:388
testLanguages( $langCode)
languagesProvider
static array $languagesWithVariants
languages supporting variants
$wgCascadingRestrictionLevels
Restriction levels that can be used with cascading protection.
static getAllowedSkins()
Fetch the list of user-selectable skins in regards to $wgSkipSkins.
Definition: Skin.php:81
setExpectedApiException( $msg, $code=null, array $data=null, $httpCode=0)
Expect an ApiUsageException to be thrown with the given parameters, which are the same as ApiUsageExc...
static users()
Definition: SiteStats.php:121
static bcp47( $code)
Get the normalised IETF language tag See unit test for examples.
static singleton()
Get the signleton instance of this class.
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:319