MediaWiki  master
TitleTest.php
Go to the documentation of this file.
1 <?php
2 
6 
12  protected function setUp() {
13  parent::setUp();
14 
15  $this->setMwGlobals( [
16  'wgAllowUserJs' => false,
17  'wgDefaultLanguageVariant' => false,
18  'wgMetaNamespace' => 'Project',
19  ] );
20  $this->setUserLang( 'en' );
21  $this->setContentLang( 'en' );
22  }
23 
27  public function testLegalChars() {
28  $titlechars = Title::legalChars();
29 
30  foreach ( range( 1, 255 ) as $num ) {
31  $chr = chr( $num );
32  if ( strpos( "#[]{}<>|", $chr ) !== false || preg_match( "/[\\x00-\\x1f\\x7f]/", $chr ) ) {
33  $this->assertFalse(
34  (bool)preg_match( "/[$titlechars]/", $chr ),
35  "chr($num) = $chr is not a valid titlechar"
36  );
37  } else {
38  $this->assertTrue(
39  (bool)preg_match( "/[$titlechars]/", $chr ),
40  "chr($num) = $chr is a valid titlechar"
41  );
42  }
43  }
44  }
45 
46  public static function provideValidSecureAndSplit() {
47  return [
48  [ 'Sandbox' ],
49  [ 'A "B"' ],
50  [ 'A \'B\'' ],
51  [ '.com' ],
52  [ '~' ],
53  [ '#' ],
54  [ '"' ],
55  [ '\'' ],
56  [ 'Talk:Sandbox' ],
57  [ 'Talk:Foo:Sandbox' ],
58  [ 'File:Example.svg' ],
59  [ 'File_talk:Example.svg' ],
60  [ 'Foo/.../Sandbox' ],
61  [ 'Sandbox/...' ],
62  [ 'A~~' ],
63  [ ':A' ],
64  // Length is 256 total, but only title part matters
65  [ 'Category:' . str_repeat( 'x', 248 ) ],
66  [ str_repeat( 'x', 252 ) ],
67  // interwiki prefix
68  [ 'localtestiw: #anchor' ],
69  [ 'localtestiw:' ],
70  [ 'localtestiw:foo' ],
71  [ 'localtestiw: foo # anchor' ],
72  [ 'localtestiw: Talk: Sandbox # anchor' ],
73  [ 'remotetestiw:' ],
74  [ 'remotetestiw: Talk: # anchor' ],
75  [ 'remotetestiw: #bar' ],
76  [ 'remotetestiw: Talk:' ],
77  [ 'remotetestiw: Talk: Foo' ],
78  [ 'localtestiw:remotetestiw:' ],
79  [ 'localtestiw:remotetestiw:foo' ]
80  ];
81  }
82 
83  public static function provideInvalidSecureAndSplit() {
84  return [
85  [ '', 'title-invalid-empty' ],
86  [ ':', 'title-invalid-empty' ],
87  [ '__ __', 'title-invalid-empty' ],
88  [ ' __ ', 'title-invalid-empty' ],
89  // Bad characters forbidden regardless of wgLegalTitleChars
90  [ 'A [ B', 'title-invalid-characters' ],
91  [ 'A ] B', 'title-invalid-characters' ],
92  [ 'A { B', 'title-invalid-characters' ],
93  [ 'A } B', 'title-invalid-characters' ],
94  [ 'A < B', 'title-invalid-characters' ],
95  [ 'A > B', 'title-invalid-characters' ],
96  [ 'A | B', 'title-invalid-characters' ],
97  [ "A \t B", 'title-invalid-characters' ],
98  [ "A \n B", 'title-invalid-characters' ],
99  // URL encoding
100  [ 'A%20B', 'title-invalid-characters' ],
101  [ 'A%23B', 'title-invalid-characters' ],
102  [ 'A%2523B', 'title-invalid-characters' ],
103  // XML/HTML character entity references
104  // Note: Commented out because they are not marked invalid by the PHP test as
105  // Title::newFromText runs Sanitizer::decodeCharReferencesAndNormalize first.
106  // 'A &eacute; B',
107  // 'A &#233; B',
108  // 'A &#x00E9; B',
109  // Subject of NS_TALK does not roundtrip to NS_MAIN
110  [ 'Talk:File:Example.svg', 'title-invalid-talk-namespace' ],
111  // Directory navigation
112  [ '.', 'title-invalid-relative' ],
113  [ '..', 'title-invalid-relative' ],
114  [ './Sandbox', 'title-invalid-relative' ],
115  [ '../Sandbox', 'title-invalid-relative' ],
116  [ 'Foo/./Sandbox', 'title-invalid-relative' ],
117  [ 'Foo/../Sandbox', 'title-invalid-relative' ],
118  [ 'Sandbox/.', 'title-invalid-relative' ],
119  [ 'Sandbox/..', 'title-invalid-relative' ],
120  // Tilde
121  [ 'A ~~~ Name', 'title-invalid-magic-tilde' ],
122  [ 'A ~~~~ Signature', 'title-invalid-magic-tilde' ],
123  [ 'A ~~~~~ Timestamp', 'title-invalid-magic-tilde' ],
124  // Length
125  [ str_repeat( 'x', 256 ), 'title-invalid-too-long' ],
126  // Namespace prefix without actual title
127  [ 'Talk:', 'title-invalid-empty' ],
128  [ 'Talk:#', 'title-invalid-empty' ],
129  [ 'Category: ', 'title-invalid-empty' ],
130  [ 'Category: #bar', 'title-invalid-empty' ],
131  // interwiki prefix
132  [ 'localtestiw: Talk: # anchor', 'title-invalid-empty' ],
133  [ 'localtestiw: Talk:', 'title-invalid-empty' ]
134  ];
135  }
136 
137  private function secureAndSplitGlobals() {
138  $this->setMwGlobals( [
139  'wgLocalInterwikis' => [ 'localtestiw' ],
140  'wgHooks' => [
141  'InterwikiLoadPrefix' => [
142  function ( $prefix, &$data ) {
143  if ( $prefix === 'localtestiw' ) {
144  $data = [ 'iw_url' => 'localtestiw' ];
145  } elseif ( $prefix === 'remotetestiw' ) {
146  $data = [ 'iw_url' => 'remotetestiw' ];
147  }
148  return false;
149  }
150  ]
151  ]
152  ] );
153 
154  // Reset services since we modified $wgLocalInterwikis
155  $this->overrideMwServices();
156  }
157 
164  public function testSecureAndSplitValid( $text ) {
165  $this->secureAndSplitGlobals();
166  $this->assertInstanceOf( Title::class, Title::newFromText( $text ), "Valid: $text" );
167  }
168 
175  public function testSecureAndSplitInvalid( $text, $expectedErrorMessage ) {
176  $this->secureAndSplitGlobals();
177  try {
178  Title::newFromTextThrow( $text ); // should throw
179  $this->assertTrue( false, "Invalid: $text" );
180  } catch ( MalformedTitleException $ex ) {
181  $this->assertEquals( $expectedErrorMessage, $ex->getErrorMessage(), "Invalid: $text" );
182  }
183  }
184 
185  public static function provideConvertByteClassToUnicodeClass() {
186  return [
187  [
188  ' %!"$&\'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+',
189  ' %!"$&\'()*,\\-./0-9:;=?@A-Z\\\\\\^_`a-z~+\\u0080-\\uFFFF',
190  ],
191  [
192  'QWERTYf-\\xFF+',
193  'QWERTYf-\\x7F+\\u0080-\\uFFFF',
194  ],
195  [
196  'QWERTY\\x66-\\xFD+',
197  'QWERTYf-\\x7F+\\u0080-\\uFFFF',
198  ],
199  [
200  'QWERTYf-y+',
201  'QWERTYf-y+',
202  ],
203  [
204  'QWERTYf-\\x80+',
205  'QWERTYf-\\x7F+\\u0080-\\uFFFF',
206  ],
207  [
208  'QWERTY\\x66-\\x80+\\x23',
209  'QWERTYf-\\x7F+#\\u0080-\\uFFFF',
210  ],
211  [
212  'QWERTY\\x66-\\x80+\\xD3',
213  'QWERTYf-\\x7F+\\u0080-\\uFFFF',
214  ],
215  [
216  '\\\\\\x99',
217  '\\\\\\u0080-\\uFFFF',
218  ],
219  [
220  '-\\x99',
221  '\\-\\u0080-\\uFFFF',
222  ],
223  [
224  'QWERTY\\-\\x99',
225  'QWERTY\\-\\u0080-\\uFFFF',
226  ],
227  [
228  '\\\\x99',
229  '\\\\x99',
230  ],
231  [
232  'A-\\x9F',
233  'A-\\x7F\\u0080-\\uFFFF',
234  ],
235  [
236  '\\x66-\\x77QWERTY\\x88-\\x91FXZ',
237  'f-wQWERTYFXZ\\u0080-\\uFFFF',
238  ],
239  [
240  '\\x66-\\x99QWERTY\\xAA-\\xEEFXZ',
241  'f-\\x7FQWERTYFXZ\\u0080-\\uFFFF',
242  ],
243  ];
244  }
245 
250  public function testConvertByteClassToUnicodeClass( $byteClass, $unicodeClass ) {
251  $this->assertEquals( $unicodeClass, Title::convertByteClassToUnicodeClass( $byteClass ) );
252  }
253 
258  public function testFixSpecialNameRetainsParameter( $text, $expectedParam ) {
259  $title = Title::newFromText( $text );
260  $fixed = $title->fixSpecialName();
261  $stuff = explode( '/', $fixed->getDBkey(), 2 );
262  if ( count( $stuff ) == 2 ) {
263  $par = $stuff[1];
264  } else {
265  $par = null;
266  }
267  $this->assertEquals(
268  $expectedParam,
269  $par,
270  "T33100 regression check: Title->fixSpecialName() should preserve parameter"
271  );
272  }
273 
275  return [
276  [ 'Special:Version', null ],
277  [ 'Special:Version/', '' ],
278  [ 'Special:Version/param', 'param' ],
279  ];
280  }
281 
293  public function testWgWhitelistReadRegexp( $whitelistRegexp, $source, $action, $expected ) {
294  // $wgWhitelistReadRegexp must be an array. Since the provided test cases
295  // usually have only one regex, it is more concise to write the lonely regex
296  // as a string. Thus we cast to a [] to honor $wgWhitelistReadRegexp
297  // type requisite.
298  if ( is_string( $whitelistRegexp ) ) {
299  $whitelistRegexp = [ $whitelistRegexp ];
300  }
301 
302  $this->setMwGlobals( [
303  // So User::isEveryoneAllowed( 'read' ) === false
304  'wgGroupPermissions' => [ '*' => [ 'read' => false ] ],
305  'wgWhitelistRead' => [ 'some random non sense title' ],
306  'wgWhitelistReadRegexp' => $whitelistRegexp,
307  ] );
308 
310 
311  // New anonymous user with no rights
312  $user = new User;
313  $this->overrideUserPermissions( $user, [] );
314  $errors = $title->userCan( $action, $user );
315 
316  if ( is_bool( $expected ) ) {
317  # Forge the assertion message depending on the assertion expectation
318  $allowableness = $expected
319  ? " should be allowed"
320  : " should NOT be allowed";
321  $this->assertEquals(
322  $expected,
323  $errors,
324  "User action '$action' on [[$source]] $allowableness."
325  );
326  } else {
327  $errors = $this->flattenErrorsArray( $errors );
328  foreach ( (array)$expected as $error ) {
329  $this->assertContains( $error, $errors );
330  }
331  }
332  }
333 
337  public function dataWgWhitelistReadRegexp() {
338  $ALLOWED = true;
339  $DISALLOWED = false;
340 
341  return [
342  // Everything, if this doesn't work, we're really in trouble
343  [ '/.*/', 'Main_Page', 'read', $ALLOWED ],
344  [ '/.*/', 'Main_Page', 'edit', $DISALLOWED ],
345 
346  // We validate against the title name, not the db key
347  [ '/^Main_Page$/', 'Main_Page', 'read', $DISALLOWED ],
348  // Main page
349  [ '/^Main/', 'Main_Page', 'read', $ALLOWED ],
350  [ '/^Main.*/', 'Main_Page', 'read', $ALLOWED ],
351  // With spaces
352  [ '/Mic\sCheck/', 'Mic Check', 'read', $ALLOWED ],
353  // Unicode multibyte
354  // ...without unicode modifier
355  [ '/Unicode Test . Yes/', 'Unicode Test Ñ Yes', 'read', $DISALLOWED ],
356  // ...with unicode modifier
357  [ '/Unicode Test . Yes/u', 'Unicode Test Ñ Yes', 'read', $ALLOWED ],
358  // Case insensitive
359  [ '/MiC ChEcK/', 'mic check', 'read', $DISALLOWED ],
360  [ '/MiC ChEcK/i', 'mic check', 'read', $ALLOWED ],
361 
362  // From DefaultSettings.php:
363  [ "@^UsEr.*@i", 'User is banned', 'read', $ALLOWED ],
364  [ "@^UsEr.*@i", 'User:John Doe', 'read', $ALLOWED ],
365 
366  // With namespaces:
367  [ '/^Special:NewPages$/', 'Special:NewPages', 'read', $ALLOWED ],
368  [ null, 'Special:Newpages', 'read', $DISALLOWED ],
369 
370  ];
371  }
372 
373  public function flattenErrorsArray( $errors ) {
374  $result = [];
375  foreach ( $errors as $error ) {
376  $result[] = $error[0];
377  }
378 
379  return $result;
380  }
381 
386  public function testGetPageViewLanguage( $expected, $titleText, $contLang,
387  $lang, $variant, $msg = ''
388  ) {
389  // Setup environnement for this test
390  $this->setMwGlobals( [
391  'wgDefaultLanguageVariant' => $variant,
392  'wgAllowUserJs' => true,
393  ] );
394  $this->setUserLang( $lang );
395  $this->setContentLang( $contLang );
396 
397  $title = Title::newFromText( $titleText );
398  $this->assertInstanceOf( Title::class, $title,
399  "Test must be passed a valid title text, you gave '$titleText'"
400  );
401  $this->assertEquals( $expected,
402  $title->getPageViewLanguage()->getCode(),
403  $msg
404  );
405  }
406 
407  public static function provideGetPageViewLanguage() {
408  # Format:
409  # - expected
410  # - Title name
411  # - content language (expected in most cases)
412  # - wgLang (on some specific pages)
413  # - wgDefaultLanguageVariant
414  # - Optional message
415  return [
416  [ 'fr', 'Help:I_need_somebody', 'fr', 'fr', false ],
417  [ 'es', 'Help:I_need_somebody', 'es', 'zh-tw', false ],
418  [ 'zh', 'Help:I_need_somebody', 'zh', 'zh-tw', false ],
419 
420  [ 'es', 'Help:I_need_somebody', 'es', 'zh-tw', 'zh-cn' ],
421  [ 'es', 'MediaWiki:About', 'es', 'zh-tw', 'zh-cn' ],
422  [ 'es', 'MediaWiki:About/', 'es', 'zh-tw', 'zh-cn' ],
423  [ 'de', 'MediaWiki:About/de', 'es', 'zh-tw', 'zh-cn' ],
424  [ 'en', 'MediaWiki:Common.js', 'es', 'zh-tw', 'zh-cn' ],
425  [ 'en', 'MediaWiki:Common.css', 'es', 'zh-tw', 'zh-cn' ],
426  [ 'en', 'User:JohnDoe/Common.js', 'es', 'zh-tw', 'zh-cn' ],
427  [ 'en', 'User:JohnDoe/Monobook.css', 'es', 'zh-tw', 'zh-cn' ],
428 
429  [ 'zh-cn', 'Help:I_need_somebody', 'zh', 'zh-tw', 'zh-cn' ],
430  [ 'zh', 'MediaWiki:About', 'zh', 'zh-tw', 'zh-cn' ],
431  [ 'zh', 'MediaWiki:About/', 'zh', 'zh-tw', 'zh-cn' ],
432  [ 'de', 'MediaWiki:About/de', 'zh', 'zh-tw', 'zh-cn' ],
433  [ 'zh-cn', 'MediaWiki:About/zh-cn', 'zh', 'zh-tw', 'zh-cn' ],
434  [ 'zh-tw', 'MediaWiki:About/zh-tw', 'zh', 'zh-tw', 'zh-cn' ],
435  [ 'en', 'MediaWiki:Common.js', 'zh', 'zh-tw', 'zh-cn' ],
436  [ 'en', 'MediaWiki:Common.css', 'zh', 'zh-tw', 'zh-cn' ],
437  [ 'en', 'User:JohnDoe/Common.js', 'zh', 'zh-tw', 'zh-cn' ],
438  [ 'en', 'User:JohnDoe/Monobook.css', 'zh', 'zh-tw', 'zh-cn' ],
439 
440  [ 'zh-tw', 'Special:NewPages', 'es', 'zh-tw', 'zh-cn' ],
441  [ 'zh-tw', 'Special:NewPages', 'zh', 'zh-tw', 'zh-cn' ],
442 
443  ];
444  }
445 
450  public function testGetBaseText( $title, $expected, $msg = '' ) {
452  $this->assertSame( $expected,
453  $title->getBaseText(),
454  $msg
455  );
456  }
457 
462  public function testGetBaseTitle( $title, $expected, $msg = '' ) {
464  $base = $title->getBaseTitle();
465  $this->assertTrue( $base->isValid(), $msg );
466  $this->assertTrue(
467  $base->equals( Title::makeTitleSafe( $title->getNamespace(), $expected ) ),
468  $msg
469  );
470  }
471 
472  public static function provideBaseTitleCases() {
473  return [
474  # Title, expected base, optional message
475  [ 'User:John_Doe/subOne/subTwo', 'John Doe/subOne' ],
476  [ 'User:Foo / Bar / Baz', 'Foo / Bar ' ],
477  ];
478  }
479 
484  public function testGetRootText( $title, $expected, $msg = '' ) {
486  $this->assertEquals( $expected,
487  $title->getRootText(),
488  $msg
489  );
490  }
491 
496  public function testGetRootTitle( $title, $expected, $msg = '' ) {
498  $root = $title->getRootTitle();
499  $this->assertTrue( $root->isValid(), $msg );
500  $this->assertTrue(
501  $root->equals( Title::makeTitleSafe( $title->getNamespace(), $expected ) ),
502  $msg
503  );
504  }
505 
506  public static function provideRootTitleCases() {
507  return [
508  # Title, expected base, optional message
509  [ 'User:John_Doe/subOne/subTwo', 'John Doe' ],
510  [ 'User:Foo / Bar / Baz', 'Foo ' ],
511  [ 'Talk:////', '
512  [ 'Template:
513  [ 'Template:Foo////', 'Foo' ],
514  [ 'Template:Foo////Bar', 'Foo' ],
515  ];
516  }
517 
523  public function testGetSubpageText( $title, $expected, $msg = '' ) {
525  $this->assertEquals( $expected,
526  $title->getSubpageText(),
527  $msg
528  );
529  }
530 
531  public static function provideSubpageTitleCases() {
532  return [
533  # Title, expected base, optional message
534  [ 'User:John_Doe/subOne/subTwo', 'subTwo' ],
535  [ 'User:John_Doe/subOne', 'subOne' ],
536  ];
537  }
538 
539  public function provideSubpage() {
540  // NOTE: avoid constructing Title objects in the provider, since it may access the database.
541  return [
542  [ 'Foo', 'x', new TitleValue( NS_MAIN, 'Foo/x' ) ],
543  [ 'Foo#bar', 'x', new TitleValue( NS_MAIN, 'Foo/x' ) ],
544  [ 'User:Foo', 'x', new TitleValue( NS_USER, 'Foo/x' ) ],
545  [ 'wiki:User:Foo', 'x', new TitleValue( NS_MAIN, 'User:Foo/x', '', 'wiki' ) ],
546  ];
547  }
548 
553  public function testSubpage( $title, $sub, LinkTarget $expected ) {
554  $interwikiLookup = $this->getMock( InterwikiLookup::class );
555  $interwikiLookup->expects( $this->any() )
556  ->method( 'isValidInterwiki' )
557  ->willReturnCallback(
558  function ( $prefix ) {
559  return $prefix == 'wiki';
560  }
561  );
562 
563  $this->setService( 'InterwikiLookup', $interwikiLookup );
564 
566  $expected = Title::newFromLinkTarget( $expected );
567  $actual = $title->getSubpage( $sub );
568 
569  // NOTE: convert to string for comparison
570  $this->assertSame( $expected->getPrefixedText(), $actual->getPrefixedText(), 'text form' );
571  $this->assertTrue( $expected->equals( $actual ), 'Title equality' );
572  }
573 
574  public static function provideNewFromTitleValue() {
575  return [
576  [ new TitleValue( NS_MAIN, 'Foo' ) ],
577  [ new TitleValue( NS_MAIN, 'Foo', 'bar' ) ],
578  [ new TitleValue( NS_USER, 'Hansi_Maier' ) ],
579  ];
580  }
581 
587  $title = Title::newFromTitleValue( $value );
588 
589  $dbkey = str_replace( ' ', '_', $value->getText() );
590  $this->assertEquals( $dbkey, $title->getDBkey() );
591  $this->assertEquals( $value->getNamespace(), $title->getNamespace() );
592  $this->assertEquals( $value->getFragment(), $title->getFragment() );
593  }
594 
600  $title = Title::newFromLinkTarget( $value );
601 
602  $dbkey = str_replace( ' ', '_', $value->getText() );
603  $this->assertEquals( $dbkey, $title->getDBkey() );
604  $this->assertEquals( $value->getNamespace(), $title->getNamespace() );
605  $this->assertEquals( $value->getFragment(), $title->getFragment() );
606  }
607 
611  public function testNewFromLinkTarget_clone() {
612  $title = Title::newFromText( __METHOD__ );
613  $this->assertSame( $title, Title::newFromLinkTarget( $title ) );
614 
615  // The Title::NEW_CLONE flag should ensure that a fresh instance is returned.
617  $this->assertNotSame( $title, $clone );
618  $this->assertTrue( $clone->equals( $title ) );
619  }
620 
621  public function provideCastFromLinkTarget() {
622  return array_merge( [ [ null ] ], self::provideNewFromTitleValue() );
623  }
624 
629  public function testCastFromLinkTarget( $value ) {
631 
632  if ( $value === null ) {
633  $this->assertNull( $title );
634  } else {
635  $dbkey = str_replace( ' ', '_', $value->getText() );
636  $this->assertSame( $dbkey, $title->getDBkey() );
637  $this->assertSame( $value->getNamespace(), $title->getNamespace() );
638  $this->assertSame( $value->getFragment(), $title->getFragment() );
639  }
640  }
641 
642  public static function provideGetTitleValue() {
643  return [
644  [ 'Foo' ],
645  [ 'Foo#bar' ],
646  [ 'User:Hansi_Maier' ],
647  ];
648  }
649 
654  public function testGetTitleValue( $text ) {
655  $title = Title::newFromText( $text );
656  $value = $title->getTitleValue();
657 
658  $dbkey = str_replace( ' ', '_', $value->getText() );
659  $this->assertEquals( $title->getDBkey(), $dbkey );
660  $this->assertEquals( $title->getNamespace(), $value->getNamespace() );
661  $this->assertEquals( $title->getFragment(), $value->getFragment() );
662  }
663 
664  public static function provideGetFragment() {
665  return [
666  [ 'Foo', '' ],
667  [ 'Foo#bar', 'bar' ],
668  [ 'Foo#bär', 'bär' ],
669 
670  // Inner whitespace is normalized
671  [ 'Foo#bar_bar', 'bar bar' ],
672  [ 'Foo#bar bar', 'bar bar' ],
673  [ 'Foo#bar bar', 'bar bar' ],
674 
675  // Leading whitespace is kept, trailing whitespace is trimmed.
676  // XXX: Is this really want we want?
677  [ 'Foo#_bar_bar_', ' bar bar' ],
678  [ 'Foo# bar bar ', ' bar bar' ],
679  ];
680  }
681 
689  public function testGetFragment( $full, $fragment ) {
690  $title = Title::newFromText( $full );
691  $this->assertEquals( $fragment, $title->getFragment() );
692  }
693 
700  public function testIsAlwaysKnown( $page, $isKnown ) {
701  $title = Title::newFromText( $page );
702  $this->assertEquals( $isKnown, $title->isAlwaysKnown() );
703  }
704 
705  public static function provideIsAlwaysKnown() {
706  return [
707  [ 'Some nonexistent page', false ],
708  [ 'UTPage', false ],
709  [ '#test', true ],
710  [ 'Special:BlankPage', true ],
711  [ 'Special:SomeNonexistentSpecialPage', false ],
712  [ 'MediaWiki:Parentheses', true ],
713  [ 'MediaWiki:Some nonexistent message', false ],
714  ];
715  }
716 
723  public function testIsValid( Title $title, $isValid ) {
724  $this->assertEquals( $isValid, $title->isValid(), $title->getPrefixedText() );
725  }
726 
727  public static function provideIsValid() {
728  return [
729  [ Title::makeTitle( NS_MAIN, '' ), false ],
730  [ Title::makeTitle( NS_MAIN, '<>' ), false ],
731  [ Title::makeTitle( NS_MAIN, '|' ), false ],
732  [ Title::makeTitle( NS_MAIN, '#' ), false ],
733  [ Title::makeTitle( NS_MAIN, 'Test' ), true ],
734  [ Title::makeTitle( NS_MAIN, ' Test' ), false ],
735  [ Title::makeTitle( NS_MAIN, '_Test' ), false ],
736  [ Title::makeTitle( NS_MAIN, 'Test ' ), false ],
737  [ Title::makeTitle( NS_MAIN, 'Test_' ), false ],
738  [ Title::makeTitle( NS_MAIN, "Test\nthis" ), false ],
739  [ Title::makeTitle( NS_MAIN, "Test\tthis" ), false ],
740  [ Title::makeTitle( -33, 'Test' ), false ],
741  [ Title::makeTitle( 77663399, 'Test' ), false ],
742  ];
743  }
744 
748  public function testIsAlwaysKnownOnInterwiki() {
749  $title = Title::makeTitle( NS_MAIN, 'Interwiki link', '', 'externalwiki' );
750  $this->assertTrue( $title->isAlwaysKnown() );
751  }
752 
756  public function testExists() {
757  $title = Title::makeTitle( NS_PROJECT, 'New page' );
758  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
759 
760  $article = new Article( $title );
761  $page = $article->getPage();
762  $page->doEditContent( new WikitextContent( 'Some [[link]]' ), 'summary' );
763 
764  // Tell Title it doesn't know whether it exists
765  $title->mArticleID = -1;
766 
767  // Tell the link cache it doesn't exist when it really does
768  $linkCache->clearLink( $title );
769  $linkCache->addBadLinkObj( $title );
770 
771  $this->assertEquals(
772  false,
773  $title->exists(),
774  'exists() should rely on link cache unless GAID_FOR_UPDATE is used'
775  );
776  $this->assertEquals(
777  true,
778  $title->exists( Title::GAID_FOR_UPDATE ),
779  'exists() should re-query database when GAID_FOR_UPDATE is used'
780  );
781  }
782 
783  public function provideCanHaveTalkPage() {
784  return [
785  'User page has talk page' => [
786  Title::makeTitle( NS_USER, 'Jane' ), true
787  ],
788  'Talke page has talk page' => [
789  Title::makeTitle( NS_TALK, 'Foo' ), true
790  ],
791  'Special page cannot have talk page' => [
792  Title::makeTitle( NS_SPECIAL, 'Thing' ), false
793  ],
794  'Virtual namespace cannot have talk page' => [
795  Title::makeTitle( NS_MEDIA, 'Kitten.jpg' ), false
796  ],
797  'Relative link has no talk page' => [
798  Title::makeTitle( NS_MAIN, '', 'Kittens' ), false
799  ],
800  'Interwiki link has no talk page' => [
801  Title::makeTitle( NS_MAIN, 'Kittens', '', 'acme' ), false
802  ],
803  ];
804  }
805 
806  public function provideIsWatchable() {
807  return [
808  'User page is watchable' => [
809  Title::makeTitle( NS_USER, 'Jane' ), true
810  ],
811  'Talke page is watchable' => [
812  Title::makeTitle( NS_TALK, 'Foo' ), true
813  ],
814  'Special page is not watchable' => [
815  Title::makeTitle( NS_SPECIAL, 'Thing' ), false
816  ],
817  'Virtual namespace is not watchable' => [
818  Title::makeTitle( NS_MEDIA, 'Kitten.jpg' ), false
819  ],
820  'Relative link is not watchable' => [
821  Title::makeTitle( NS_MAIN, '', 'Kittens' ), false
822  ],
823  'Interwiki link is not watchable' => [
824  Title::makeTitle( NS_MAIN, 'Kittens', '', 'acme' ), false
825  ],
826  ];
827  }
828 
829  public static function provideGetTalkPage_good() {
830  return [
831  [ Title::makeTitle( NS_MAIN, 'Test' ), Title::makeTitle( NS_TALK, 'Test' ) ],
832  [ Title::makeTitle( NS_TALK, 'Test' ), Title::makeTitle( NS_TALK, 'Test' ) ],
833  ];
834  }
835 
836  public static function provideGetTalkPage_bad() {
837  return [
838  [ Title::makeTitle( NS_SPECIAL, 'Test' ) ],
839  [ Title::makeTitle( NS_MEDIA, 'Test' ) ],
840  [ Title::makeTitle( NS_MAIN, '', 'Kittens' ) ],
841  [ Title::makeTitle( NS_MAIN, 'Kittens', '', 'acme' ) ],
842  ];
843  }
844 
845  public static function provideGetSubjectPage_good() {
846  return [
847  [ Title::makeTitle( NS_TALK, 'Test' ), Title::makeTitle( NS_MAIN, 'Test' ) ],
848  [ Title::makeTitle( NS_MAIN, 'Test' ), Title::makeTitle( NS_MAIN, 'Test' ) ],
849  ];
850  }
851 
852  public static function provideGetOtherPage_good() {
853  return [
854  [ Title::makeTitle( NS_MAIN, 'Test' ), Title::makeTitle( NS_TALK, 'Test' ) ],
855  [ Title::makeTitle( NS_TALK, 'Test' ), Title::makeTitle( NS_MAIN, 'Test' ) ],
856  ];
857  }
858 
866  public function testCanHaveTalkPage( Title $title, $expected ) {
867  $actual = $title->canHaveTalkPage();
868  $this->assertSame( $expected, $actual, $title->getPrefixedDBkey() );
869  }
870 
878  public function testIsWatchable( Title $title, $expected ) {
879  $actual = $title->canHaveTalkPage();
880  $this->assertSame( $expected, $actual, $title->getPrefixedDBkey() );
881  }
882 
887  public function testGetTalkPage_good( Title $title, Title $expected ) {
888  $actual = $title->getTalkPage();
889  $this->assertTrue( $expected->equals( $actual ), $title->getPrefixedDBkey() );
890  }
891 
896  public function testGetTalkPage_bad( Title $title ) {
897  $this->setExpectedException( MWException::class );
898  $title->getTalkPage();
899  }
900 
905  public function testGetTalkPageIfDefined_good( Title $title, Title $expected ) {
906  $actual = $title->getTalkPageIfDefined();
907  $this->assertNotNull( $actual, $title->getPrefixedDBkey() );
908  $this->assertTrue( $expected->equals( $actual ), $title->getPrefixedDBkey() );
909  }
910 
916  $talk = $title->getTalkPageIfDefined();
917  $this->assertNull(
918  $talk,
919  $title->getPrefixedDBkey()
920  );
921  }
922 
927  public function testGetSubjectPage_good( Title $title, Title $expected ) {
928  $actual = $title->getSubjectPage();
929  $this->assertTrue( $expected->equals( $actual ), $title->getPrefixedDBkey() );
930  }
931 
936  public function testGetOtherPage_good( Title $title, Title $expected ) {
937  $actual = $title->getOtherPage();
938  $this->assertTrue( $expected->equals( $actual ), $title->getPrefixedDBkey() );
939  }
940 
945  public function testGetOtherPage_bad( Title $title ) {
946  $this->setExpectedException( MWException::class );
947  $title->getOtherPage();
948  }
949 
958  public function testIsMovable( $title, $expected, $hookCallback = null ) {
959  if ( $hookCallback ) {
960  $this->setTemporaryHook( 'TitleIsMovable', $hookCallback );
961  }
962  if ( is_string( $title ) ) {
964  }
965 
966  $this->assertSame( $expected, $title->isMovable() );
967  }
968 
969  public static function provideIsMovable() {
970  return [
971  'Simple title' => [ 'Foo', true ],
972  // @todo Should these next two really be true?
973  'Empty name' => [ Title::makeTitle( NS_MAIN, '' ), true ],
974  'Invalid name' => [ Title::makeTitle( NS_MAIN, '<' ), true ],
975  'Interwiki' => [ Title::makeTitle( NS_MAIN, 'Test', '', 'otherwiki' ), false ],
976  'Special page' => [ 'Special:FooBar', false ],
977  'Aborted by hook' => [ 'Hooked in place', false,
978  function ( Title $title, &$result ) {
979  $result = false;
980  }
981  ],
982  ];
983  }
984 
985  public function provideCreateFragmentTitle() {
986  return [
987  [ Title::makeTitle( NS_MAIN, 'Test' ), 'foo' ],
988  [ Title::makeTitle( NS_TALK, 'Test', 'foo' ), '' ],
989  [ Title::makeTitle( NS_CATEGORY, 'Test', 'foo' ), 'bar' ],
990  [ Title::makeTitle( NS_MAIN, 'Test1', '', 'interwiki' ), 'baz' ]
991  ];
992  }
993 
998  public function testCreateFragmentTitle( Title $title, $fragment ) {
999  $this->mergeMwGlobalArrayValue( 'wgHooks', [
1000  'InterwikiLoadPrefix' => [
1001  function ( $prefix, &$iwdata ) {
1002  if ( $prefix === 'interwiki' ) {
1003  $iwdata = [
1004  'iw_url' => 'http://example.com/',
1005  'iw_local' => 0,
1006  'iw_trans' => 0,
1007  ];
1008  return false;
1009  }
1010  },
1011  ],
1012  ] );
1013 
1014  $fragmentTitle = $title->createFragmentTarget( $fragment );
1015 
1016  $this->assertEquals( $title->getNamespace(), $fragmentTitle->getNamespace() );
1017  $this->assertEquals( $title->getText(), $fragmentTitle->getText() );
1018  $this->assertEquals( $title->getInterwiki(), $fragmentTitle->getInterwiki() );
1019  $this->assertEquals( $fragment, $fragmentTitle->getFragment() );
1020  }
1021 
1022  public function provideGetPrefixedText() {
1023  return [
1024  // ns = 0
1025  [
1026  Title::makeTitle( NS_MAIN, 'Foo bar' ),
1027  'Foo bar'
1028  ],
1029  // ns = 2
1030  [
1031  Title::makeTitle( NS_USER, 'Foo bar' ),
1032  'User:Foo bar'
1033  ],
1034  // ns = 3
1035  [
1036  Title::makeTitle( NS_USER_TALK, 'Foo bar' ),
1037  'User talk:Foo bar'
1038  ],
1039  // fragment not included
1040  [
1041  Title::makeTitle( NS_MAIN, 'Foo bar', 'fragment' ),
1042  'Foo bar'
1043  ],
1044  // ns = -2
1045  [
1046  Title::makeTitle( NS_MEDIA, 'Foo bar' ),
1047  'Media:Foo bar'
1048  ],
1049  // non-existent namespace
1050  [
1051  Title::makeTitle( 100777, 'Foo bar' ),
1052  'Special:Badtitle/NS100777:Foo bar'
1053  ],
1054  ];
1055  }
1056 
1061  public function testGetPrefixedText( Title $title, $expected ) {
1062  $this->assertEquals( $expected, $title->getPrefixedText() );
1063  }
1064 
1065  public function provideGetPrefixedDBKey() {
1066  return [
1067  // ns = 0
1068  [
1069  Title::makeTitle( NS_MAIN, 'Foo_bar' ),
1070  'Foo_bar'
1071  ],
1072  // ns = 2
1073  [
1074  Title::makeTitle( NS_USER, 'Foo_bar' ),
1075  'User:Foo_bar'
1076  ],
1077  // ns = 3
1078  [
1079  Title::makeTitle( NS_USER_TALK, 'Foo_bar' ),
1080  'User_talk:Foo_bar'
1081  ],
1082  // fragment not included
1083  [
1084  Title::makeTitle( NS_MAIN, 'Foo_bar', 'fragment' ),
1085  'Foo_bar'
1086  ],
1087  // ns = -2
1088  [
1089  Title::makeTitle( NS_MEDIA, 'Foo_bar' ),
1090  'Media:Foo_bar'
1091  ],
1092  // non-existent namespace
1093  [
1094  Title::makeTitle( 100777, 'Foo_bar' ),
1095  'Special:Badtitle/NS100777:Foo_bar'
1096  ],
1097  ];
1098  }
1099 
1104  public function testGetPrefixedDBKey( Title $title, $expected ) {
1105  $this->assertEquals( $expected, $title->getPrefixedDBkey() );
1106  }
1107 
1115  public function testGetFragmentForURL( $titleStr, $expected ) {
1116  $this->setMwGlobals( [
1117  'wgFragmentMode' => [ 'html5' ],
1118  'wgExternalInterwikiFragmentMode' => 'legacy',
1119  ] );
1120  $dbw = wfGetDB( DB_MASTER );
1121  $dbw->insert( 'interwiki',
1122  [
1123  [
1124  'iw_prefix' => 'de',
1125  'iw_url' => 'http://de.wikipedia.org/wiki/',
1126  'iw_api' => 'http://de.wikipedia.org/w/api.php',
1127  'iw_wikiid' => 'dewiki',
1128  'iw_local' => 1,
1129  'iw_trans' => 0,
1130  ],
1131  [
1132  'iw_prefix' => 'zz',
1133  'iw_url' => 'http://zzwiki.org/wiki/',
1134  'iw_api' => 'http://zzwiki.org/w/api.php',
1135  'iw_wikiid' => 'zzwiki',
1136  'iw_local' => 0,
1137  'iw_trans' => 0,
1138  ],
1139  ],
1140  __METHOD__,
1141  [ 'IGNORE' ]
1142  );
1143 
1144  $title = Title::newFromText( $titleStr );
1145  self::assertEquals( $expected, $title->getFragmentForURL() );
1146 
1147  $dbw->delete( 'interwiki', '*', __METHOD__ );
1148  }
1149 
1150  public function provideGetFragmentForURL() {
1151  return [
1152  [ 'Foo', '' ],
1153  [ 'Foo#ümlåût', '#ümlåût' ],
1154  [ 'de:Foo#Bå®', '#Bå®' ],
1155  [ 'zz:Foo#тест', '#.D1.82.D0.B5.D1.81.D1.82' ],
1156  ];
1157  }
1158 
1163  public function testIsRawHtmlMessage( $textForm, $expected ) {
1164  $this->setMwGlobals( 'wgRawHtmlMessages', [
1165  'foobar',
1166  'foo_bar',
1167  'foo-bar',
1168  ] );
1169 
1170  $title = Title::newFromText( $textForm );
1171  $this->assertSame( $expected, $title->isRawHtmlMessage() );
1172  }
1173 
1174  public function provideIsRawHtmlMessage() {
1175  return [
1176  [ 'MediaWiki:Foobar', true ],
1177  [ 'MediaWiki:Foo bar', true ],
1178  [ 'MediaWiki:Foo-bar', true ],
1179  [ 'MediaWiki:foo bar', true ],
1180  [ 'MediaWiki:foo-bar', true ],
1181  [ 'MediaWiki:foobar', true ],
1182  [ 'MediaWiki:some-other-message', false ],
1183  [ 'Main Page', false ],
1184  ];
1185  }
1186 
1187  public function provideEquals() {
1188  yield [
1189  Title::newFromText( 'Main Page' ),
1190  Title::newFromText( 'Main Page' ),
1191  true
1192  ];
1193  yield [
1194  Title::newFromText( 'Main Page' ),
1195  Title::newFromText( 'Not The Main Page' ),
1196  false
1197  ];
1198  yield [
1199  Title::newFromText( 'Main Page' ),
1200  Title::newFromText( 'Project:Main Page' ),
1201  false
1202  ];
1203  yield [
1204  Title::newFromText( 'File:Example.png' ),
1205  Title::newFromText( 'Image:Example.png' ),
1206  true
1207  ];
1208  yield [
1209  Title::newFromText( 'Special:Version' ),
1210  Title::newFromText( 'Special:Version' ),
1211  true
1212  ];
1213  yield [
1214  Title::newFromText( 'Special:Version' ),
1215  Title::newFromText( 'Special:Recentchanges' ),
1216  false
1217  ];
1218  yield [
1219  Title::newFromText( 'Special:Version' ),
1220  Title::newFromText( 'Main Page' ),
1221  false
1222  ];
1223  yield [
1224  Title::makeTitle( NS_MAIN, 'Foo', '', '' ),
1225  Title::makeTitle( NS_MAIN, 'Foo', '', '' ),
1226  true
1227  ];
1228  yield [
1229  Title::makeTitle( NS_MAIN, 'Foo', '', '' ),
1230  Title::makeTitle( NS_MAIN, 'Bar', '', '' ),
1231  false
1232  ];
1233  yield [
1234  Title::makeTitle( NS_MAIN, 'Foo', '', '' ),
1235  Title::makeTitle( NS_TALK, 'Foo', '', '' ),
1236  false
1237  ];
1238  yield [
1239  Title::makeTitle( NS_MAIN, 'Foo', 'Bar', '' ),
1240  Title::makeTitle( NS_MAIN, 'Foo', 'Bar', '' ),
1241  true
1242  ];
1243  yield [
1244  Title::makeTitle( NS_MAIN, 'Foo', 'Bar', '' ),
1245  Title::makeTitle( NS_MAIN, 'Foo', 'Baz', '' ),
1246  true
1247  ];
1248  yield [
1249  Title::makeTitle( NS_MAIN, 'Foo', 'Bar', '' ),
1250  Title::makeTitle( NS_MAIN, 'Foo', '', '' ),
1251  true
1252  ];
1253  yield [
1254  Title::makeTitle( NS_MAIN, 'Foo', '', 'baz' ),
1255  Title::makeTitle( NS_MAIN, 'Foo', '', 'baz' ),
1256  true
1257  ];
1258  yield [
1259  Title::makeTitle( NS_MAIN, 'Foo', '', '' ),
1260  Title::makeTitle( NS_MAIN, 'Foo', '', 'baz' ),
1261  false
1262  ];
1263  }
1264 
1269  public function testEquals( Title $firstValue, /* LinkTarget */ $secondValue, $expectedSame ) {
1270  $this->assertSame(
1271  $expectedSame,
1272  $firstValue->equals( $secondValue )
1273  );
1274  }
1275 
1279  public function testNewMainPage() {
1280  $mock = $this->createMock( MessageCache::class );
1281  $mock->method( 'get' )->willReturn( 'Foresheet' );
1282  $mock->method( 'transform' )->willReturn( 'Foresheet' );
1283 
1284  $this->setService( 'MessageCache', $mock );
1285 
1286  $this->assertSame(
1287  'Foresheet',
1288  Title::newMainPage()->getText()
1289  );
1290  }
1291 
1295  public function testNewMainPageWithLocal() {
1296  $local = $this->createMock( MessageLocalizer::class );
1297  $local->method( 'msg' )->willReturn( new RawMessage( 'Prime Article' ) );
1298 
1299  $this->assertSame(
1300  'Prime Article',
1301  Title::newMainPage( $local )->getText()
1302  );
1303  }
1304 }
getText()
Returns the title in text form, without namespace prefix or fragment.
Definition: TitleValue.php:174
! article Main Page ! text blah blah ! endarticle !article Foo !text FOO !endarticle !article Foo s bar s !text Article titles can contain single quotes !endarticle !article Template
static castFromLinkTarget( $linkTarget)
Same as newFromLinkTarget, but if passed null, returns null.
Definition: Title.php:298
static provideGetOtherPage_good()
Definition: TitleTest.php:852
testSecureAndSplitValid( $text)
See also mediawiki.Title.test.js Title::secureAndSplit provideValidSecureAndSplit.
Definition: TitleTest.php:164
testIsAlwaysKnownOnInterwiki()
Title::isAlwaysKnown.
Definition: TitleTest.php:748
canHaveTalkPage()
Can this title have a corresponding talk page?
Definition: Title.php:1158
static provideGetPageViewLanguage()
Definition: TitleTest.php:407
static provideValidSecureAndSplit()
Definition: TitleTest.php:46
testFixSpecialNameRetainsParameter( $text, $expectedParam)
provideSpecialNamesWithAndWithoutParameter Title::fixSpecialName
Definition: TitleTest.php:258
testEquals(Title $firstValue, $secondValue, $expectedSame)
Title::equals provideEquals.
Definition: TitleTest.php:1269
const NS_MAIN
Definition: Defines.php:60
getText()
Get the text form (spaces not underscores) of the main part.
Definition: Title.php:1003
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:193
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
Definition: Title.php:656
static provideSpecialNamesWithAndWithoutParameter()
Definition: TitleTest.php:274
testIsAlwaysKnown( $page, $isKnown)
Title::isAlwaysKnown provideIsAlwaysKnown.
Definition: TitleTest.php:700
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
static provideGetFragment()
Definition: TitleTest.php:664
equals(LinkTarget $title)
Compare with another title.
Definition: Title.php:4009
getTalkPageIfDefined()
Get a Title object associated with the talk page of this article, if such a talk page can exist...
Definition: Title.php:1563
if(!isset( $args[0])) $lang
static provideIsMovable()
Definition: TitleTest.php:969
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
testWgWhitelistReadRegexp( $whitelistRegexp, $source, $action, $expected)
Auth-less test of Title::userCan.
Definition: TitleTest.php:293
Class for viewing MediaWiki article and history.
Definition: Article.php:38
$source
$value
static provideIsValid()
Definition: TitleTest.php:727
const NS_SPECIAL
Definition: Defines.php:49
static provideConvertByteClassToUnicodeClass()
Definition: TitleTest.php:185
testGetBaseTitle( $title, $expected, $msg='')
provideBaseTitleCases Title::getBaseTitle
Definition: TitleTest.php:462
getOtherPage()
Get the other title for this page, if this is a subject page get the talk page, if it is a subject pa...
Definition: Title.php:1592
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
getPrefixedText()
Get the prefixed title with spaces.
Definition: Title.php:1724
secureAndSplitGlobals()
Definition: TitleTest.php:137
testConvertByteClassToUnicodeClass( $byteClass, $unicodeClass)
provideConvertByteClassToUnicodeClass Title::convertByteClassToUnicodeClass
Definition: TitleTest.php:250
testIsWatchable(Title $title, $expected)
provideIsWatchable Title::isWatchable
Definition: TitleTest.php:878
static provideRootTitleCases()
Definition: TitleTest.php:506
testGetTalkPage_good(Title $title, Title $expected)
provideGetTalkPage_good Title::getTalkPageIfDefined
Definition: TitleTest.php:887
testIsValid(Title $title, $isValid)
Title::isValid provideIsValid.
Definition: TitleTest.php:723
testGetTalkPageIfDefined_good(Title $title, Title $expected)
provideGetTalkPage_good Title::getTalkPageIfDefined
Definition: TitleTest.php:905
const DB_MASTER
Definition: defines.php:26
static provideSubpageTitleCases()
Definition: TitleTest.php:531
static provideNewFromTitleValue()
Definition: TitleTest.php:574
testIsMovable( $title, $expected, $hookCallback=null)
provideIsMovable Title::isMovable
Definition: TitleTest.php:958
getTalkPage()
Get a Title object associated with the talk page of this article.
Definition: Title.php:1549
testGetRootText( $title, $expected, $msg='')
provideRootTitleCases Title::getRootText
Definition: TitleTest.php:484
getNamespace()
Get the namespace index.
static provideBaseTitleCases()
Definition: TitleTest.php:472
const NEW_CLONE
Flag for use with factory methods like newFromLinkTarget() that have a $forceClone parameter...
Definition: Title.php:66
provideGetPrefixedText()
Definition: TitleTest.php:1022
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message. Please note the header message cannot receive/use parameters. 'ImgAuthModifyHeaders':Executed just before a file is streamed to a user via img_auth.php, allowing headers to be modified beforehand. $title:LinkTarget object & $headers:HTTP headers(name=> value, names are case insensitive). Two headers get special handling:If-Modified-Since(value must be a valid HTTP date) and Range(must be of the form "bytes=(\*-\*)") will be honored when streaming the file. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item. Return false to stop further processing of the tag $reader:XMLReader object $logInfo:Array of information 'ImportHandlePageXMLTag':When parsing a XML tag in a page. Return false to stop further processing of the tag $reader:XMLReader object & $pageInfo:Array of information 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. Return false to stop further processing of the tag $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. Return false to stop further processing of the tag $reader:XMLReader object 'ImportHandleUnknownUser':When a user doesn 't exist locally, this hook is called to give extensions an opportunity to auto-create it. If the auto-creation is successful, return false. $name:User name 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. Return false to stop further processing of the tag $reader:XMLReader object $revisionInfo:Array of information 'ImportLogInterwikiLink':Hook to change the interwiki link used in log entries and edit summaries for transwiki imports. & $fullInterwikiPrefix:Interwiki prefix, may contain colons. & $pageTitle:String that contains page title. 'ImportSources':Called when reading from the $wgImportSources configuration variable. Can be used to lazy-load the import sources list. & $importSources:The value of $wgImportSources. Modify as necessary. See the comment in DefaultSettings.php for the detail of how to structure this array. 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. & $title:Title object for the current page & $request:WebRequest & $ignoreRedirect:boolean to skip redirect check & $target:Title/string of redirect target & $article:Article object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) & $article:article(object) being checked 'IsTrustedProxy':Override the result of IP::isTrustedProxy() & $ip:IP being check & $result:Change this value to override the result of IP::isTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of Sanitizer::validateEmail(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code:language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Array with elements of the form "language:title" in the order that they will be output. & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LanguageSelector':Hook to change the language selector available on a page. $out:The output page. $cssClassName:CSS class name of the language selector. 'LinkBegin':DEPRECATED since 1.28! Use HtmlPageLinkRendererBegin instead. Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition: hooks.txt:1981
static convertByteClassToUnicodeClass( $byteClass)
Utility method for converting a character sequence from bytes to Unicode.
Definition: Title.php:717
getFragment()
Get the link fragment (i.e.
testGetPrefixedDBKey(Title $title, $expected)
Title::getPrefixedDBKey provideGetPrefixedDBKey.
Definition: TitleTest.php:1104
testGetBaseText( $title, $expected, $msg='')
provideBaseTitleCases Title::getBaseText
Definition: TitleTest.php:450
static provideGetSubjectPage_good()
Definition: TitleTest.php:845
testExists()
Title::exists.
Definition: TitleTest.php:756
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:1983
testGetFragmentForURL( $titleStr, $expected)
Title::getFragmentForURL provideGetFragmentForURL.
Definition: TitleTest.php:1115
Database Title.
Definition: TitleTest.php:11
const NS_PROJECT
Definition: Defines.php:64
testNewMainPageWithLocal()
Title::newMainPage.
Definition: TitleTest.php:1295
testGetTalkPageIfDefined_bad(Title $title)
provideGetTalkPage_bad Title::getTalkPageIfDefined
Definition: TitleTest.php:915
const NS_MEDIA
Definition: Defines.php:48
testGetTalkPage_bad(Title $title)
provideGetTalkPage_bad Title::getTalkPageIfDefined
Definition: TitleTest.php:896
const GAID_FOR_UPDATE
Used to be GAID_FOR_UPDATE define.
Definition: Title.php:57
flattenErrorsArray( $errors)
Definition: TitleTest.php:373
const NS_CATEGORY
Definition: Defines.php:74
testGetSubjectPage_good(Title $title, Title $expected)
provideGetSubjectPage_good Title::getSubjectPage
Definition: TitleTest.php:927
dataWgWhitelistReadRegexp()
Provides test parameter values for testWgWhitelistReadRegexp()
Definition: TitleTest.php:337
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:773
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:918
getNamespace()
Get the namespace index, i.e.
Definition: Title.php:1045
provideCreateFragmentTitle()
Definition: TitleTest.php:985
testLegalChars()
Title::legalChars.
Definition: TitleTest.php:27
getInterwiki()
Get the interwiki prefix.
Definition: Title.php:931
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
static provideInvalidSecureAndSplit()
Definition: TitleTest.php:83
testGetOtherPage_bad(Title $title)
provideGetTalkPage_bad Title::getOtherPage
Definition: TitleTest.php:945
provideIsRawHtmlMessage()
Definition: TitleTest.php:1174
testSecureAndSplitInvalid( $text, $expectedErrorMessage)
See also mediawiki.Title.test.js Title::secureAndSplit provideInvalidSecureAndSplit.
Definition: TitleTest.php:175
static newFromTextThrow( $text, $defaultNamespace=NS_MAIN)
Like Title::newFromText(), but throws MalformedTitleException when the title is invalid, rather than returning null.
Definition: Title.php:359
isValid()
Returns true if the title is valid, false if it is invalid.
Definition: Title.php:871
getSubjectPage()
Get a title object associated with the subject page of this talk page.
Definition: Title.php:1578
static provideIsAlwaysKnown()
Definition: TitleTest.php:705
testGetPrefixedText(Title $title, $expected)
Title::getPrefixedText provideGetPrefixedText.
Definition: TitleTest.php:1061
testCreateFragmentTitle(Title $title, $fragment)
Title::createFragmentTarget provideCreateFragmentTitle.
Definition: TitleTest.php:998
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:620
static newFromLinkTarget(LinkTarget $linkTarget, $forceClone='')
Returns a Title given a LinkTarget.
Definition: Title.php:274
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:592
testGetOtherPage_good(Title $title, Title $expected)
provideGetOtherPage_good Title::getOtherPage
Definition: TitleTest.php:936
provideGetFragmentForURL()
Definition: TitleTest.php:1150
testCanHaveTalkPage(Title $title, $expected)
provideCanHaveTalkPage Title::canHaveTalkPage
Definition: TitleTest.php:866
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
provideGetPrefixedDBKey()
Definition: TitleTest.php:1065
testSubpage( $title, $sub, LinkTarget $expected)
provideSubpage Title::getSubpage
Definition: TitleTest.php:553
static newFromDBkey( $key)
Create a new Title from a prefixed DB key.
Definition: Title.php:234
static provideGetTalkPage_bad()
Definition: TitleTest.php:836
createFragmentTarget( $fragment)
Creates a new Title for a different fragment of the same page.
Definition: Title.php:1670
provideCastFromLinkTarget()
Definition: TitleTest.php:621
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
Variant of the Message class.
Definition: RawMessage.php:34
provideIsWatchable()
Definition: TitleTest.php:806
testIsRawHtmlMessage( $textForm, $expected)
Title::isRawHtmlMessage provideIsRawHtmlMessage.
Definition: TitleTest.php:1163
provideCanHaveTalkPage()
Definition: TitleTest.php:783
static provideGetTitleValue()
Definition: TitleTest.php:642
testGetSubpageText( $title, $expected, $msg='')
Definition: TitleTest.php:523
testGetTitleValue( $text)
Title::getTitleValue provideGetTitleValue.
Definition: TitleTest.php:654
getText()
Returns the link in text form, without namespace prefix or fragment.
static provideGetTalkPage_good()
Definition: TitleTest.php:829
static legalChars()
Get a regex character class describing the legal characters in a link.
Definition: Title.php:703
const NS_TALK
Definition: Defines.php:61
testGetFragment( $full, $fragment)
Title::getFragment provideGetFragment.
Definition: TitleTest.php:689
testGetPageViewLanguage( $expected, $titleText, $contLang, $lang, $variant, $msg='')
provideGetPageViewLanguage Title::getPageViewLanguage
Definition: TitleTest.php:386
testNewFromLinkTarget_clone()
Title::newFromLinkTarget.
Definition: TitleTest.php:611
testNewMainPage()
Title::newMainPage.
Definition: TitleTest.php:1279
provideSubpage()
Definition: TitleTest.php:539
const NS_USER_TALK
Definition: Defines.php:63
static newFromTitleValue(TitleValue $titleValue, $forceClone='')
Returns a Title given a TitleValue.
Definition: Title.php:259
testNewFromLinkTarget(LinkTarget $value)
Title::newFromLinkTarget provideNewFromTitleValue.
Definition: TitleTest.php:599
testCastFromLinkTarget( $value)
Title::castFromLinkTarget provideCastFromLinkTarget.
Definition: TitleTest.php:629
return true to allow those checks to and false if checking is done & $user
Definition: hooks.txt:1460
getPrefixedDBkey()
Get the prefixed database key form.
Definition: Title.php:1712
testNewFromTitleValue(TitleValue $value)
Title::newFromTitleValue provideNewFromTitleValue.
Definition: TitleTest.php:586
testGetRootTitle( $title, $expected, $msg='')
provideRootTitleCases Title::getRootTitle
Definition: TitleTest.php:496
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:322