MediaWiki REL1_31
SpecialPageFactoryTest.php
Go to the documentation of this file.
1<?php
2use Wikimedia\ScopedCallback;
3
26
27 protected function tearDown() {
28 parent::tearDown();
29
31 }
32
33 public function testResetList() {
35 $this->assertContains( 'Specialpages', SpecialPageFactory::getNames() );
36 }
37
38 public function testHookNotCalledTwice() {
39 $count = 0;
40 $this->mergeMwGlobalArrayValue( 'wgHooks', [
41 'SpecialPage_initList' => [
42 function () use ( &$count ) {
43 $count++;
44 }
45 ] ] );
49 $this->assertEquals( 1, $count );
50 }
51
52 public function newSpecialAllPages() {
53 return new SpecialAllPages();
54 }
55
56 public function specialPageProvider() {
57 $specialPageTestHelper = new SpecialPageTestHelper();
58
59 return [
60 'class name' => [ 'SpecialAllPages', false ],
61 'closure' => [ function () {
62 return new SpecialAllPages();
63 }, false ],
64 'function' => [ [ $this, 'newSpecialAllPages' ], false ],
65 'callback string' => [ 'SpecialPageTestHelper::newSpecialAllPages', false ],
66 'callback with object' => [
67 [ $specialPageTestHelper, 'newSpecialAllPages' ],
68 false
69 ],
70 'callback array' => [
71 [ 'SpecialPageTestHelper', 'newSpecialAllPages' ],
72 false
73 ]
74 ];
75 }
76
81 public function testGetPage( $spec, $shouldReuseInstance ) {
82 $this->mergeMwGlobalArrayValue( 'wgSpecialPages', [ 'testdummy' => $spec ] );
84
85 $page = SpecialPageFactory::getPage( 'testdummy' );
86 $this->assertInstanceOf( SpecialPage::class, $page );
87
88 $page2 = SpecialPageFactory::getPage( 'testdummy' );
89 $this->assertEquals( $shouldReuseInstance, $page2 === $page, "Should re-use instance:" );
90 }
91
95 public function testGetNames() {
96 $this->mergeMwGlobalArrayValue( 'wgSpecialPages', [ 'testdummy' => SpecialAllPages::class ] );
98
100 $this->assertInternalType( 'array', $names );
101 $this->assertContains( 'testdummy', $names );
102 }
103
107 public function testResolveAlias() {
108 $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
110
111 list( $name, $param ) = SpecialPageFactory::resolveAlias( 'Spezialseiten/Foo' );
112 $this->assertEquals( 'Specialpages', $name );
113 $this->assertEquals( 'Foo', $param );
114 }
115
119 public function testGetLocalNameFor() {
120 $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
122
123 $name = SpecialPageFactory::getLocalNameFor( 'Specialpages', 'Foo' );
124 $this->assertEquals( 'Spezialseiten/Foo', $name );
125 }
126
130 public function testGetTitleForAlias() {
131 $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
133
134 $title = SpecialPageFactory::getTitleForAlias( 'Specialpages/Foo' );
135 $this->assertEquals( 'Spezialseiten/Foo', $title->getText() );
136 $this->assertEquals( NS_SPECIAL, $title->getNamespace() );
137 }
138
142 public function testConflictResolution(
143 $test, $aliasesList, $alias, $expectedName, $expectedAlias, $expectWarnings
144 ) {
145 global $wgContLang;
146 $lang = clone $wgContLang;
147 $lang->mExtendedSpecialPageAliases = $aliasesList;
148 $this->setMwGlobals( 'wgContLang', $lang );
149 $this->setMwGlobals( 'wgSpecialPages',
150 array_combine( array_keys( $aliasesList ), array_keys( $aliasesList ) )
151 );
153
154 // Catch the warnings we expect to be raised
155 $warnings = [];
156 $this->setMwGlobals( 'wgDevelopmentWarnings', true );
157 set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
158 if ( preg_match( '/First alias \'[^\']*\' for .*/', $errstr ) ||
159 preg_match( '/Did not find a usable alias for special page .*/', $errstr )
160 ) {
161 $warnings[] = $errstr;
162 return true;
163 }
164 return false;
165 } );
166 $reset = new ScopedCallback( 'restore_error_handler' );
167
168 list( $name, /*...*/ ) = SpecialPageFactory::resolveAlias( $alias );
169 $this->assertEquals( $expectedName, $name, "$test: Alias to name" );
170 $result = SpecialPageFactory::getLocalNameFor( $name );
171 $this->assertEquals( $expectedAlias, $result, "$test: Alias to name to alias" );
172
173 $gotWarnings = count( $warnings );
174 if ( $gotWarnings !== $expectWarnings ) {
175 $this->fail( "Expected $expectWarnings warning(s), but got $gotWarnings:\n" .
176 implode( "\n", $warnings )
177 );
178 }
179 }
180
185 $test, $aliasesList, $alias, $expectedName, $expectedAlias, $expectWarnings
186 ) {
187 // Make sure order doesn't matter by reversing the list
188 $aliasesList = array_reverse( $aliasesList );
189 return $this->testConflictResolution(
190 $test, $aliasesList, $alias, $expectedName, $expectedAlias, $expectWarnings
191 );
192 }
193
195 return [
196 [
197 'Canonical name wins',
198 [ 'Foo' => [ 'Foo', 'Bar' ], 'Baz' => [ 'Foo', 'BazPage', 'Baz2' ] ],
199 'Foo',
200 'Foo',
201 'Foo',
202 1,
203 ],
204
205 [
206 'Doesn\'t redirect to a different special page\'s canonical name',
207 [ 'Foo' => [ 'Foo', 'Bar' ], 'Baz' => [ 'Foo', 'BazPage', 'Baz2' ] ],
208 'Baz',
209 'Baz',
210 'BazPage',
211 1,
212 ],
213
214 [
215 'Canonical name wins even if not aliased',
216 [ 'Foo' => [ 'FooPage' ], 'Baz' => [ 'Foo', 'BazPage', 'Baz2' ] ],
217 'Foo',
218 'Foo',
219 'FooPage',
220 1,
221 ],
222
223 [
224 'Doesn\'t redirect to a different special page\'s canonical name even if not aliased',
225 [ 'Foo' => [ 'FooPage' ], 'Baz' => [ 'Foo', 'BazPage', 'Baz2' ] ],
226 'Baz',
227 'Baz',
228 'BazPage',
229 1,
230 ],
231
232 [
233 'First local name beats non-first',
234 [ 'First' => [ 'Foo' ], 'NonFirst' => [ 'Bar', 'Foo' ] ],
235 'Foo',
236 'First',
237 'Foo',
238 0,
239 ],
240
241 [
242 'Doesn\'t redirect to a different special page\'s first alias',
243 [
244 'Foo' => [ 'Foo' ],
245 'First' => [ 'Bar' ],
246 'Baz' => [ 'Foo', 'Bar', 'BazPage', 'Baz2' ]
247 ],
248 'Baz',
249 'Baz',
250 'BazPage',
251 1,
252 ],
253
254 [
255 'Doesn\'t redirect wrong even if all aliases conflict',
256 [
257 'Foo' => [ 'Foo' ],
258 'First' => [ 'Bar' ],
259 'Baz' => [ 'Foo', 'Bar' ]
260 ],
261 'Baz',
262 'Baz',
263 'Baz',
264 2,
265 ],
266
267 ];
268 }
269
270 public function testGetAliasListRecursion() {
271 $called = false;
272 $this->mergeMwGlobalArrayValue( 'wgHooks', [
273 'SpecialPage_initList' => [
274 function () use ( &$called ) {
275 SpecialPageFactory::getLocalNameFor( 'Specialpages' );
276 $called = true;
277 }
278 ],
279 ] );
281 SpecialPageFactory::getLocalNameFor( 'Specialpages' );
282 $this->assertTrue( $called, 'Recursive call succeeded' );
283 }
284
285}
mergeMwGlobalArrayValue( $name, $values)
Merges the given values into a MW global array variable.
setMwGlobals( $pairs, $value=null)
Sets a global, maintaining a stashed version of the previous global to be restored in tearDown.
$called
$called tracks whether the setUp and tearDown method has been called.
Implements Special:Allpages.
Factory for handling the special page list and generating SpecialPage objects.
testGetNames()
SpecialPageFactory::getNames.
testGetTitleForAlias()
SpecialPageFactory::getTitleForAlias.
testConflictResolutionReversed( $test, $aliasesList, $alias, $expectedName, $expectedAlias, $expectWarnings)
provideTestConflictResolution
testConflictResolution( $test, $aliasesList, $alias, $expectedName, $expectedAlias, $expectWarnings)
provideTestConflictResolution
testResolveAlias()
SpecialPageFactory::resolveAlias.
testGetPage( $spec, $shouldReuseInstance)
SpecialPageFactory::getPage specialPageProvider.
testGetLocalNameFor()
SpecialPageFactory::getLocalNameFor.
static getLocalNameFor( $name, $subpage=false)
Get the local name for a specified canonical name.
static getTitleForAlias( $alias)
Get a title for a given alias.
static getPage( $name)
Find the object with a given name and return it (or NULL)
static resetList()
Reset the internal list of special pages.
static getNames()
Returns a list of canonical special page names.
static resolveAlias( $alias)
Given a special page name with a possible subpage, return an array where the first element is the spe...
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition deferred.txt:11
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the local content language as $wgContLang
Definition design.txt:57
processing should stop and the error should be shown to the user * false
Definition hooks.txt:187
const NS_SPECIAL
Definition Defines.php:63
if(!isset( $args[0])) $lang