]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / tests / phpunit / includes / specialpage / SpecialPageFactoryTest.php
1 <?php
2 use Wikimedia\ScopedCallback;
3
4 /**
5  * Factory for handling the special page list and generating SpecialPage objects.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  * http://www.gnu.org/copyleft/gpl.html
21  *
22  * @covers SpecialPageFactory
23  * @group SpecialPage
24  */
25 class SpecialPageFactoryTest extends MediaWikiTestCase {
26
27         protected function tearDown() {
28                 parent::tearDown();
29
30                 SpecialPageFactory::resetList();
31         }
32
33         public function testResetList() {
34                 SpecialPageFactory::resetList();
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                 ] ] );
46                 SpecialPageFactory::resetList();
47                 SpecialPageFactory::getNames();
48                 SpecialPageFactory::getNames();
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
77         /**
78          * @covers SpecialPageFactory::getPage
79          * @dataProvider specialPageProvider
80          */
81         public function testGetPage( $spec, $shouldReuseInstance ) {
82                 $this->mergeMwGlobalArrayValue( 'wgSpecialPages', [ 'testdummy' => $spec ] );
83                 SpecialPageFactory::resetList();
84
85                 $page = SpecialPageFactory::getPage( 'testdummy' );
86                 $this->assertInstanceOf( 'SpecialPage', $page );
87
88                 $page2 = SpecialPageFactory::getPage( 'testdummy' );
89                 $this->assertEquals( $shouldReuseInstance, $page2 === $page, "Should re-use instance:" );
90         }
91
92         /**
93          * @covers SpecialPageFactory::getNames
94          */
95         public function testGetNames() {
96                 $this->mergeMwGlobalArrayValue( 'wgSpecialPages', [ 'testdummy' => 'SpecialAllPages' ] );
97                 SpecialPageFactory::resetList();
98
99                 $names = SpecialPageFactory::getNames();
100                 $this->assertInternalType( 'array', $names );
101                 $this->assertContains( 'testdummy', $names );
102         }
103
104         /**
105          * @covers SpecialPageFactory::resolveAlias
106          */
107         public function testResolveAlias() {
108                 $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
109                 SpecialPageFactory::resetList();
110
111                 list( $name, $param ) = SpecialPageFactory::resolveAlias( 'Spezialseiten/Foo' );
112                 $this->assertEquals( 'Specialpages', $name );
113                 $this->assertEquals( 'Foo', $param );
114         }
115
116         /**
117          * @covers SpecialPageFactory::getLocalNameFor
118          */
119         public function testGetLocalNameFor() {
120                 $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
121                 SpecialPageFactory::resetList();
122
123                 $name = SpecialPageFactory::getLocalNameFor( 'Specialpages', 'Foo' );
124                 $this->assertEquals( 'Spezialseiten/Foo', $name );
125         }
126
127         /**
128          * @covers SpecialPageFactory::getTitleForAlias
129          */
130         public function testGetTitleForAlias() {
131                 $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
132                 SpecialPageFactory::resetList();
133
134                 $title = SpecialPageFactory::getTitleForAlias( 'Specialpages/Foo' );
135                 $this->assertEquals( 'Spezialseiten/Foo', $title->getText() );
136                 $this->assertEquals( NS_SPECIAL, $title->getNamespace() );
137         }
138
139         /**
140          * @dataProvider provideTestConflictResolution
141          */
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                 );
152                 SpecialPageFactory::resetList();
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
181         /**
182          * @dataProvider provideTestConflictResolution
183          */
184         public function testConflictResolutionReversed(
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
194         public function provideTestConflictResolution() {
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                 ] );
280                 SpecialPageFactory::resetList();
281                 SpecialPageFactory::getLocalNameFor( 'Specialpages' );
282                 $this->assertTrue( $called, 'Recursive call succeeded' );
283         }
284
285 }