MediaWiki  REL1_31
ApiMoveTest.php
Go to the documentation of this file.
1 <?php
2 
10 class ApiMoveTest extends ApiTestCase {
17  protected function assertMoved( $from, $to, $id, $opts = null ) {
18  $opts = (array)$opts;
19 
20  $fromTitle = Title::newFromText( $from );
21  $toTitle = Title::newFromText( $to );
22 
23  $this->assertTrue( $toTitle->exists(),
24  "Destination {$toTitle->getPrefixedText()} does not exist" );
25 
26  if ( in_array( 'noredirect', $opts ) ) {
27  $this->assertFalse( $fromTitle->exists(),
28  "Source {$fromTitle->getPrefixedText()} exists" );
29  } else {
30  $this->assertTrue( $fromTitle->exists(),
31  "Source {$fromTitle->getPrefixedText()} does not exist" );
32  $this->assertTrue( $fromTitle->isRedirect(),
33  "Source {$fromTitle->getPrefixedText()} is not a redirect" );
34 
35  $target = Revision::newFromTitle( $fromTitle )->getContent()->getRedirectTarget();
36  $this->assertSame( $toTitle->getPrefixedText(), $target->getPrefixedText() );
37  }
38 
39  $this->assertSame( $id, $toTitle->getArticleId() );
40  }
41 
48  protected function createPage( $name ) {
49  return $this->editPage( $name, 'Content' )->value['revision']->getPage();
50  }
51 
52  public function testFromWithFromid() {
53  $this->setExpectedException( ApiUsageException::class,
54  'The parameters "from" and "fromid" can not be used together.' );
55 
56  $this->doApiRequestWithToken( [
57  'action' => 'move',
58  'from' => 'Some page',
59  'fromid' => 123,
60  'to' => 'Some other page',
61  ] );
62  }
63 
64  public function testMove() {
65  $name = ucfirst( __FUNCTION__ );
66 
67  $id = $this->createPage( $name );
68 
69  $res = $this->doApiRequestWithToken( [
70  'action' => 'move',
71  'from' => $name,
72  'to' => "$name 2",
73  ] );
74 
75  $this->assertMoved( $name, "$name 2", $id );
76  $this->assertArrayNotHasKey( 'warnings', $res[0] );
77  }
78 
79  public function testMoveById() {
80  $name = ucfirst( __FUNCTION__ );
81 
82  $id = $this->createPage( $name );
83 
84  $res = $this->doApiRequestWithToken( [
85  'action' => 'move',
86  'fromid' => $id,
87  'to' => "$name 2",
88  ] );
89 
90  $this->assertMoved( $name, "$name 2", $id );
91  $this->assertArrayNotHasKey( 'warnings', $res[0] );
92  }
93 
94  public function testMoveNonexistent() {
95  $this->setExpectedException( ApiUsageException::class,
96  "The page you specified doesn't exist." );
97 
98  $this->doApiRequestWithToken( [
99  'action' => 'move',
100  'from' => 'Nonexistent page',
101  'to' => 'Different page'
102  ] );
103  }
104 
105  public function testMoveNonexistentId() {
106  $this->setExpectedException( ApiUsageException::class,
107  'There is no page with ID 2147483647.' );
108 
109  $this->doApiRequestWithToken( [
110  'action' => 'move',
111  'fromid' => pow( 2, 31 ) - 1,
112  'to' => 'Different page',
113  ] );
114  }
115 
116  public function testMoveToInvalidPageName() {
117  $this->setExpectedException( ApiUsageException::class, 'Bad title "[".' );
118 
119  $name = ucfirst( __FUNCTION__ );
120  $id = $this->createPage( $name );
121 
122  try {
123  $this->doApiRequestWithToken( [
124  'action' => 'move',
125  'from' => $name,
126  'to' => '[',
127  ] );
128  } finally {
129  $this->assertSame( $id, Title::newFromText( $name )->getArticleId() );
130  }
131  }
132 
133  // @todo File moving
134 
135  public function testPingLimiter() {
137 
138  $this->setExpectedException( ApiUsageException::class,
139  "You've exceeded your rate limit. Please wait some time and try again." );
140 
141  $name = ucfirst( __FUNCTION__ );
142 
143  $this->setMwGlobals( 'wgMainCacheType', 'hash' );
144 
145  $this->stashMwGlobals( 'wgRateLimits' );
146  $wgRateLimits['move'] = [ '&can-bypass' => false, 'user' => [ 1, 60 ] ];
147 
148  $id = $this->createPage( $name );
149 
150  $res = $this->doApiRequestWithToken( [
151  'action' => 'move',
152  'from' => $name,
153  'to' => "$name 2",
154  ] );
155 
156  $this->assertMoved( $name, "$name 2", $id );
157  $this->assertArrayNotHasKey( 'warnings', $res[0] );
158 
159  try {
160  $this->doApiRequestWithToken( [
161  'action' => 'move',
162  'from' => "$name 2",
163  'to' => "$name 3",
164  ] );
165  } finally {
166  $this->assertSame( $id, Title::newFromText( "$name 2" )->getArticleId() );
167  $this->assertFalse( Title::newFromText( "$name 3" )->exists(),
168  "\"$name 3\" should not exist" );
169  }
170  }
171 
172  public function testTagsNoPermission() {
173  $this->setExpectedException( ApiUsageException::class,
174  'You do not have permission to apply change tags along with your changes.' );
175 
176  $name = ucfirst( __FUNCTION__ );
177 
178  ChangeTags::defineTag( 'custom tag' );
179 
180  $this->setGroupPermissions( 'user', 'applychangetags', false );
181 
182  $id = $this->createPage( $name );
183 
184  try {
185  $this->doApiRequestWithToken( [
186  'action' => 'move',
187  'from' => $name,
188  'to' => "$name 2",
189  'tags' => 'custom tag',
190  ] );
191  } finally {
192  $this->assertSame( $id, Title::newFromText( $name )->getArticleId() );
193  $this->assertFalse( Title::newFromText( "$name 2" )->exists(),
194  "\"$name 2\" should not exist" );
195  }
196  }
197 
198  public function testSelfMove() {
199  $this->setExpectedException( ApiUsageException::class,
200  'The title is the same; cannot move a page over itself.' );
201 
202  $name = ucfirst( __FUNCTION__ );
203  $this->createPage( $name );
204 
205  $this->doApiRequestWithToken( [
206  'action' => 'move',
207  'from' => $name,
208  'to' => $name,
209  ] );
210  }
211 
212  public function testMoveTalk() {
213  $name = ucfirst( __FUNCTION__ );
214 
215  $id = $this->createPage( $name );
216  $talkId = $this->createPage( "Talk:$name" );
217 
218  $res = $this->doApiRequestWithToken( [
219  'action' => 'move',
220  'from' => $name,
221  'to' => "$name 2",
222  'movetalk' => '',
223  ] );
224 
225  $this->assertMoved( $name, "$name 2", $id );
226  $this->assertMoved( "Talk:$name", "Talk:$name 2", $talkId );
227 
228  $this->assertArrayNotHasKey( 'warnings', $res[0] );
229  }
230 
231  public function testMoveTalkFailed() {
232  $name = ucfirst( __FUNCTION__ );
233 
234  $id = $this->createPage( $name );
235  $talkId = $this->createPage( "Talk:$name" );
236  $talkDestinationId = $this->createPage( "Talk:$name 2" );
237 
238  $res = $this->doApiRequestWithToken( [
239  'action' => 'move',
240  'from' => $name,
241  'to' => "$name 2",
242  'movetalk' => '',
243  ] );
244 
245  $this->assertMoved( $name, "$name 2", $id );
246  $this->assertSame( $talkId, Title::newFromText( "Talk:$name" )->getArticleId() );
247  $this->assertSame( $talkDestinationId,
248  Title::newFromText( "Talk:$name 2" )->getArticleId() );
249  $this->assertSame( [ [
250  'message' => 'articleexists',
251  'params' => [],
252  'code' => 'articleexists',
253  'type' => 'error',
254  ] ], $res[0]['move']['talkmove-errors'] );
255 
256  $this->assertArrayNotHasKey( 'warnings', $res[0] );
257  }
258 
259  public function testMoveSubpages() {
261 
262  $name = ucfirst( __FUNCTION__ );
263 
264  $this->stashMwGlobals( 'wgNamespacesWithSubpages' );
265  $wgNamespacesWithSubpages[NS_MAIN] = true;
266 
267  $pages = [ $name, "$name/1", "$name/2", "Talk:$name", "Talk:$name/1", "Talk:$name/3" ];
268  $ids = [];
269  foreach ( array_merge( $pages, [ "$name/error", "$name 2/error" ] ) as $page ) {
270  $ids[$page] = $this->createPage( $page );
271  }
272 
273  $res = $this->doApiRequestWithToken( [
274  'action' => 'move',
275  'from' => $name,
276  'to' => "$name 2",
277  'movetalk' => '',
278  'movesubpages' => '',
279  ] );
280 
281  foreach ( $pages as $page ) {
282  $this->assertMoved( $page, str_replace( $name, "$name 2", $page ), $ids[$page] );
283  }
284 
285  $this->assertSame( $ids["$name/error"],
286  Title::newFromText( "$name/error" )->getArticleId() );
287  $this->assertSame( $ids["$name 2/error"],
288  Title::newFromText( "$name 2/error" )->getArticleId() );
289 
290  $results = array_merge( $res[0]['move']['subpages'], $res[0]['move']['subpages-talk'] );
291  foreach ( $results as $arr ) {
292  if ( $arr['from'] === "$name/error" ) {
293  $this->assertSame( [ [
294  'message' => 'articleexists',
295  'params' => [],
296  'code' => 'articleexists',
297  'type' => 'error'
298  ] ], $arr['errors'] );
299  } else {
300  $this->assertSame( str_replace( $name, "$name 2", $arr['from'] ), $arr['to'] );
301  }
302  $this->assertCount( 2, $arr );
303  }
304 
305  $this->assertArrayNotHasKey( 'warnings', $res[0] );
306  }
307 
308  public function testMoveNoPermission() {
309  $this->setExpectedException( ApiUsageException::class,
310  'You must be a registered user and [[Special:UserLogin|logged in]] to move a page.' );
311 
312  $name = ucfirst( __FUNCTION__ );
313 
314  $id = $this->createPage( $name );
315 
316  $user = new User();
317 
318  try {
319  $this->doApiRequestWithToken( [
320  'action' => 'move',
321  'from' => $name,
322  'to' => "$name 2",
323  ], null, $user );
324  } finally {
325  $this->assertSame( $id, Title::newFromText( "$name" )->getArticleId() );
326  $this->assertFalse( Title::newFromText( "$name 2" )->exists(),
327  "\"$name 2\" should not exist" );
328  }
329  }
330 
331  public function testSuppressRedirect() {
332  $name = ucfirst( __FUNCTION__ );
333 
334  $id = $this->createPage( $name );
335 
336  $res = $this->doApiRequestWithToken( [
337  'action' => 'move',
338  'from' => $name,
339  'to' => "$name 2",
340  'noredirect' => '',
341  ] );
342 
343  $this->assertMoved( $name, "$name 2", $id, 'noredirect' );
344  $this->assertArrayNotHasKey( 'warnings', $res[0] );
345  }
346 
348  $name = ucfirst( __FUNCTION__ );
349 
350  $this->setGroupPermissions( 'sysop', 'suppressredirect', false );
351 
352  $id = $this->createPage( $name );
353 
354  $res = $this->doApiRequestWithToken( [
355  'action' => 'move',
356  'from' => $name,
357  'to' => "$name 2",
358  'noredirect' => '',
359  ] );
360 
361  $this->assertMoved( $name, "$name 2", $id );
362  $this->assertArrayNotHasKey( 'warnings', $res[0] );
363  }
364 
365  public function testMoveSubpagesError() {
366  $name = ucfirst( __FUNCTION__ );
367 
368  // Subpages are allowed in talk but not main
369  $idBase = $this->createPage( "Talk:$name" );
370  $idSub = $this->createPage( "Talk:$name/1" );
371 
372  $res = $this->doApiRequestWithToken( [
373  'action' => 'move',
374  'from' => "Talk:$name",
375  'to' => $name,
376  'movesubpages' => '',
377  ] );
378 
379  $this->assertMoved( "Talk:$name", $name, $idBase );
380  $this->assertSame( $idSub, Title::newFromText( "Talk:$name/1" )->getArticleId() );
381  $this->assertFalse( Title::newFromText( "$name/1" )->exists(),
382  "\"$name/1\" should not exist" );
383 
384  $this->assertSame( [ 'errors' => [ [
385  'message' => 'namespace-nosubpages',
386  'params' => [ '' ],
387  'code' => 'namespace-nosubpages',
388  'type' => 'error',
389  ] ] ], $res[0]['move']['subpages'] );
390 
391  $this->assertArrayNotHasKey( 'warnings', $res[0] );
392  }
393 }
ApiMoveTest\testMoveSubpagesError
testMoveSubpagesError()
Definition: ApiMoveTest.php:365
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:247
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:273
MediaWikiTestCase\stashMwGlobals
stashMwGlobals( $globalKeys)
Stashes the global, will be restored in tearDown()
Definition: MediaWikiTestCase.php:730
ApiMoveTest\testMoveSubpages
testMoveSubpages()
Definition: ApiMoveTest.php:259
ApiMoveTest\testMoveNoPermission
testMoveNoPermission()
Definition: ApiMoveTest.php:308
array
the array() calling protocol came about after MediaWiki 1.4rc1.
ApiMoveTest\testSuppressRedirectNoPermission
testSuppressRedirectNoPermission()
Definition: ApiMoveTest.php:347
$res
$res
Definition: database.txt:21
User
User
Definition: All_system_messages.txt:425
php
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:37
NS_MAIN
const NS_MAIN
Definition: Defines.php:74
Revision\newFromTitle
static newFromTitle(LinkTarget $linkTarget, $id=0, $flags=0)
Load either the current, or a specified, revision that's attached to a given link target.
Definition: Revision.php:133
ApiMoveTest\testMoveById
testMoveById()
Definition: ApiMoveTest.php:79
ApiMoveTest\testMoveTalkFailed
testMoveTalkFailed()
Definition: ApiMoveTest.php:231
ApiMoveTest\testSuppressRedirect
testSuppressRedirect()
Definition: ApiMoveTest.php:331
MediaWikiTestCase\setMwGlobals
setMwGlobals( $pairs, $value=null)
Sets a global, maintaining a stashed version of the previous global to be restored in tearDown.
Definition: MediaWikiTestCase.php:678
ApiMoveTest\testMoveToInvalidPageName
testMoveToInvalidPageName()
Definition: ApiMoveTest.php:116
ApiTestCase\doApiRequestWithToken
doApiRequestWithToken(array $params, array $session=null, User $user=null, $tokenType='auto')
Convenience function to access the token parameter of doApiRequest() more succinctly.
Definition: ApiTestCase.php:170
ApiMoveTest\testTagsNoPermission
testTagsNoPermission()
Definition: ApiMoveTest.php:172
ChangeTags\defineTag
static defineTag( $tag)
Defines a tag in the valid_tag table, without checking that the tag name is valid.
Definition: ChangeTags.php:825
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:95
ApiMoveTest\assertMoved
assertMoved( $from, $to, $id, $opts=null)
Definition: ApiMoveTest.php:17
ApiMoveTest\testPingLimiter
testPingLimiter()
Definition: ApiMoveTest.php:135
ApiMoveTest\createPage
createPage( $name)
Shortcut function to create a page and return its id.
Definition: ApiMoveTest.php:48
ApiMoveTest\testSelfMove
testSelfMove()
Definition: ApiMoveTest.php:198
ApiTestCase
Definition: ApiTestCase.php:5
ApiTestCase\editPage
editPage( $pageName, $text, $summary='', $defaultNs=NS_MAIN)
Edits or creates a page/revision.
Definition: ApiTestCase.php:52
$wgRateLimits
$wgRateLimits
Simple rate limiter options to brake edit floods.
Definition: DefaultSettings.php:5678
MediaWikiTestCase\setGroupPermissions
setGroupPermissions( $newPerms, $newKey=null, $newValue=null)
Alters $wgGroupPermissions for the duration of the test.
Definition: MediaWikiTestCase.php:920
ApiMoveTest\testFromWithFromid
testFromWithFromid()
Definition: ApiMoveTest.php:52
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:302
ApiMoveTest\testMoveTalk
testMoveTalk()
Definition: ApiMoveTest.php:212
as
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:22
ApiMoveTest\testMove
testMove()
Definition: ApiMoveTest.php:64
ApiMoveTest
API Database medium.
Definition: ApiMoveTest.php:10
class
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:56
ApiMoveTest\testMoveNonexistentId
testMoveNonexistentId()
Definition: ApiMoveTest.php:105
$wgNamespacesWithSubpages
$wgNamespacesWithSubpages
Which namespaces should support subpages? See Language.php for a list of namespaces.
Definition: DefaultSettings.php:4064
ApiMoveTest\testMoveNonexistent
testMoveNonexistent()
Definition: ApiMoveTest.php:94