149fcd33b25271e9d5f2c8f5d8bf072df89b96cc
[lhc/web/wiklou.git] / tests / phpunit / includes / api / ApiQueryRecentChangesIntegrationTest.php
1 <?php
2
3 use MediaWiki\Linker\LinkTarget;
4 use MediaWiki\MediaWikiServices;
5
6 /**
7 * @group API
8 * @group Database
9 * @group medium
10 *
11 * @covers ApiQueryRecentChanges
12 */
13 class ApiQueryRecentChangesIntegrationTest extends ApiTestCase {
14
15 public function __construct( $name = null, array $data = [], $dataName = '' ) {
16 parent::__construct( $name, $data, $dataName );
17 $this->tablesUsed = array_unique(
18 array_merge( $this->tablesUsed, [ 'recentchanges', 'page' ] )
19 );
20 }
21
22 protected function setUp() {
23 parent::setUp();
24 self::$users['ApiQueryRecentChangesIntegrationTestUser'] = $this->getMutableTestUser();
25 $this->doLogin( 'ApiQueryRecentChangesIntegrationTestUser' );
26 wfGetDB( DB_MASTER )->delete( 'recentchanges', '*', __METHOD__ );
27 }
28
29 private function getLoggedInTestUser() {
30 return self::$users['ApiQueryRecentChangesIntegrationTestUser']->getUser();
31 }
32
33 private function doPageEdit( User $user, LinkTarget $target, $content, $summary ) {
34 $title = Title::newFromLinkTarget( $target );
35 $page = WikiPage::factory( $title );
36 $page->doEditContent(
37 ContentHandler::makeContent( $content, $title ),
38 $summary,
39 0,
40 false,
41 $user
42 );
43 }
44
45 private function doMinorPageEdit( User $user, LinkTarget $target, $content, $summary ) {
46 $title = Title::newFromLinkTarget( $target );
47 $page = WikiPage::factory( $title );
48 $page->doEditContent(
49 ContentHandler::makeContent( $content, $title ),
50 $summary,
51 EDIT_MINOR,
52 false,
53 $user
54 );
55 }
56
57 private function doBotPageEdit( User $user, LinkTarget $target, $content, $summary ) {
58 $title = Title::newFromLinkTarget( $target );
59 $page = WikiPage::factory( $title );
60 $page->doEditContent(
61 ContentHandler::makeContent( $content, $title ),
62 $summary,
63 EDIT_FORCE_BOT,
64 false,
65 $user
66 );
67 }
68
69 private function doAnonPageEdit( LinkTarget $target, $content, $summary ) {
70 $title = Title::newFromLinkTarget( $target );
71 $page = WikiPage::factory( $title );
72 $page->doEditContent(
73 ContentHandler::makeContent( $content, $title ),
74 $summary,
75 0,
76 false,
77 User::newFromId( 0 )
78 );
79 }
80
81 private function deletePage( LinkTarget $target, $reason ) {
82 $title = Title::newFromLinkTarget( $target );
83 $page = WikiPage::factory( $title );
84 $page->doDeleteArticleReal( $reason );
85 }
86
87 /**
88 * Performs a batch of page edits as a specified user
89 * @param User $user
90 * @param array $editData associative array, keys:
91 * - target => LinkTarget page to edit
92 * - content => string new content
93 * - summary => string edit summary
94 * - minorEdit => bool mark as minor edit if true (defaults to false)
95 * - botEdit => bool mark as bot edit if true (defaults to false)
96 */
97 private function doPageEdits( User $user, array $editData ) {
98 foreach ( $editData as $singleEditData ) {
99 if ( array_key_exists( 'minorEdit', $singleEditData ) && $singleEditData['minorEdit'] ) {
100 $this->doMinorPageEdit(
101 $user,
102 $singleEditData['target'],
103 $singleEditData['content'],
104 $singleEditData['summary']
105 );
106 continue;
107 }
108 if ( array_key_exists( 'botEdit', $singleEditData ) && $singleEditData['botEdit'] ) {
109 $this->doBotPageEdit(
110 $user,
111 $singleEditData['target'],
112 $singleEditData['content'],
113 $singleEditData['summary']
114 );
115 continue;
116 }
117 $this->doPageEdit(
118 $user,
119 $singleEditData['target'],
120 $singleEditData['content'],
121 $singleEditData['summary']
122 );
123 }
124 }
125
126 private function doListRecentChangesRequest( array $params = [], $user = null ) {
127 return $this->doApiRequest(
128 array_merge(
129 [ 'action' => 'query', 'list' => 'recentchanges' ],
130 $params
131 ),
132 null,
133 false
134 );
135 }
136
137 private function doGeneratorRecentChangesRequest( array $params = [] ) {
138 return $this->doApiRequest(
139 array_merge(
140 [ 'action' => 'query', 'generator' => 'recentchanges' ],
141 $params
142 )
143 );
144 }
145
146 private function getItemsFromApiResponse( array $response ) {
147 return $response[0]['query']['recentchanges'];
148 }
149
150 /**
151 * Convenience method to assert that actual items array fetched from API is equal to the expected
152 * array, Unlike assertEquals this only checks if values of specified keys are equal in both
153 * arrays. This could be used e.g. not to compare IDs that could change between test run
154 * but only stable keys.
155 * Optionally this also checks that specified keys are present in the actual item without
156 * performing any checks on the related values.
157 *
158 * @param array $actualItems array of actual items (associative arrays)
159 * @param array $expectedItems array of expected items (associative arrays),
160 * those items have less keys than actual items
161 * @param array $keysUsedInValueComparison list of keys of the actual item that will be used
162 * in the comparison of values
163 * @param array $requiredKeys optional, list of keys that must be present in the
164 * actual items. Values of those keys are not checked.
165 */
166 private function assertArraySubsetsEqual(
167 array $actualItems,
168 array $expectedItems,
169 array $keysUsedInValueComparison,
170 array $requiredKeys = []
171 ) {
172 $this->assertCount( count( $expectedItems ), $actualItems );
173
174 // not checking values of all keys of the actual item, so removing unwanted keys from comparison
175 $actualItemsOnlyComparedValues = array_map(
176 function ( array $item ) use ( $keysUsedInValueComparison ) {
177 return array_intersect_key( $item, array_flip( $keysUsedInValueComparison ) );
178 },
179 $actualItems
180 );
181
182 $this->assertEquals(
183 $expectedItems,
184 $actualItemsOnlyComparedValues
185 );
186
187 // Check that each item in $actualItems contains all of keys specified in $requiredKeys
188 $actualItemsKeysOnly = array_map( 'array_keys', $actualItems );
189 foreach ( $actualItemsKeysOnly as $keysOfTheItem ) {
190 $this->assertEmpty( array_diff( $requiredKeys, $keysOfTheItem ) );
191 }
192 }
193
194 private function getTitleFormatter() {
195 return new MediaWikiTitleCodec(
196 Language::factory( 'en' ),
197 MediaWikiServices::getInstance()->getGenderCache()
198 );
199 }
200
201 private function getPrefixedText( LinkTarget $target ) {
202 $formatter = $this->getTitleFormatter();
203 return $formatter->getPrefixedText( $target );
204 }
205
206 public function testListRecentChanges_returnsRCInfo() {
207 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
208 $this->doPageEdit(
209 $this->getLoggedInTestUser(),
210 $target,
211 'Some Content',
212 'Create the page'
213 );
214
215 $result = $this->doListRecentChangesRequest();
216
217 $this->assertArrayHasKey( 'query', $result[0] );
218 $this->assertArrayHasKey( 'recentchanges', $result[0]['query'] );
219
220 $this->assertArraySubsetsEqual(
221 $this->getItemsFromApiResponse( $result ),
222 [
223 [
224 'type' => 'new',
225 'ns' => $target->getNamespace(),
226 'title' => $this->getPrefixedText( $target ),
227 ]
228 ],
229 [ 'type', 'ns', 'title', 'bot', 'new', 'minor' ],
230 [ 'pageid', 'revid', 'old_revid' ]
231 );
232 }
233
234 public function testIdsPropParameter() {
235 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
236 $this->doPageEdit(
237 $this->getLoggedInTestUser(),
238 $target,
239 'Some Content',
240 'Create the page'
241 );
242
243 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'ids', ] );
244 $items = $this->getItemsFromApiResponse( $result );
245
246 $this->assertCount( 1, $items );
247 $this->assertArrayHasKey( 'pageid', $items[0] );
248 $this->assertArrayHasKey( 'revid', $items[0] );
249 $this->assertArrayHasKey( 'old_revid', $items[0] );
250 $this->assertEquals( 'new', $items[0]['type'] );
251 }
252
253 public function testTitlePropParameter() {
254 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
255 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
256 $this->doPageEdits(
257 $this->getLoggedInTestUser(),
258 [
259 [
260 'target' => $subjectTarget,
261 'content' => 'Some Content',
262 'summary' => 'Create the page',
263 ],
264 [
265 'target' => $talkTarget,
266 'content' => 'Some Talk Page Content',
267 'summary' => 'Create Talk page',
268 ],
269 ]
270 );
271
272 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', ] );
273
274 $this->assertEquals(
275 [
276 [
277 'type' => 'new',
278 'ns' => $talkTarget->getNamespace(),
279 'title' => $this->getPrefixedText( $talkTarget ),
280 ],
281 [
282 'type' => 'new',
283 'ns' => $subjectTarget->getNamespace(),
284 'title' => $this->getPrefixedText( $subjectTarget ),
285 ],
286 ],
287 $this->getItemsFromApiResponse( $result )
288 );
289 }
290
291 public function testFlagsPropParameter() {
292 $normalEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
293 $minorEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPageM' );
294 $botEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPageB' );
295 $this->doPageEdits(
296 $this->getLoggedInTestUser(),
297 [
298 [
299 'target' => $normalEditTarget,
300 'content' => 'Some Content',
301 'summary' => 'Create the page',
302 ],
303 [
304 'target' => $minorEditTarget,
305 'content' => 'Some Content',
306 'summary' => 'Create the page',
307 ],
308 [
309 'target' => $minorEditTarget,
310 'content' => 'Slightly Better Content',
311 'summary' => 'Change content',
312 'minorEdit' => true,
313 ],
314 [
315 'target' => $botEditTarget,
316 'content' => 'Some Content',
317 'summary' => 'Create the page with a bot',
318 'botEdit' => true,
319 ],
320 ]
321 );
322
323 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'flags', ] );
324
325 $this->assertEquals(
326 [
327 [
328 'type' => 'new',
329 'new' => true,
330 'minor' => false,
331 'bot' => true,
332 ],
333 [
334 'type' => 'edit',
335 'new' => false,
336 'minor' => true,
337 'bot' => false,
338 ],
339 [
340 'type' => 'new',
341 'new' => true,
342 'minor' => false,
343 'bot' => false,
344 ],
345 [
346 'type' => 'new',
347 'new' => true,
348 'minor' => false,
349 'bot' => false,
350 ],
351 ],
352 $this->getItemsFromApiResponse( $result )
353 );
354 }
355
356 public function testUserPropParameter() {
357 $userEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
358 $anonEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPageA' );
359 $this->doPageEdit(
360 $this->getLoggedInTestUser(),
361 $userEditTarget,
362 'Some Content',
363 'Create the page'
364 );
365 $this->doAnonPageEdit(
366 $anonEditTarget,
367 'Some Content',
368 'Create the page'
369 );
370
371 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'user', ] );
372
373 $this->assertEquals(
374 [
375 [
376 'type' => 'new',
377 'anon' => true,
378 'user' => User::newFromId( 0 )->getName(),
379 ],
380 [
381 'type' => 'new',
382 'user' => $this->getLoggedInTestUser()->getName(),
383 ],
384 ],
385 $this->getItemsFromApiResponse( $result )
386 );
387 }
388
389 public function testUserIdPropParameter() {
390 $user = $this->getLoggedInTestUser();
391 $userEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
392 $anonEditTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPageA' );
393 $this->doPageEdit(
394 $user,
395 $userEditTarget,
396 'Some Content',
397 'Create the page'
398 );
399 $this->doAnonPageEdit(
400 $anonEditTarget,
401 'Some Content',
402 'Create the page'
403 );
404
405 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'userid', ] );
406
407 $this->assertEquals(
408 [
409 [
410 'type' => 'new',
411 'anon' => true,
412 'userid' => 0,
413 ],
414 [
415 'type' => 'new',
416 'userid' => $user->getId(),
417 ],
418 ],
419 $this->getItemsFromApiResponse( $result )
420 );
421 }
422
423 public function testCommentPropParameter() {
424 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
425 $this->doPageEdit(
426 $this->getLoggedInTestUser(),
427 $target,
428 'Some Content',
429 'Create the <b>page</b>'
430 );
431
432 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'comment', ] );
433
434 $this->assertEquals(
435 [
436 [
437 'type' => 'new',
438 'comment' => 'Create the <b>page</b>',
439 ],
440 ],
441 $this->getItemsFromApiResponse( $result )
442 );
443 }
444
445 public function testParsedCommentPropParameter() {
446 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
447 $this->doPageEdit(
448 $this->getLoggedInTestUser(),
449 $target,
450 'Some Content',
451 'Create the <b>page</b>'
452 );
453
454 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'parsedcomment', ] );
455
456 $this->assertEquals(
457 [
458 [
459 'type' => 'new',
460 'parsedcomment' => 'Create the &lt;b&gt;page&lt;/b&gt;',
461 ],
462 ],
463 $this->getItemsFromApiResponse( $result )
464 );
465 }
466
467 public function testTimestampPropParameter() {
468 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
469 $this->doPageEdit(
470 $this->getLoggedInTestUser(),
471 $target,
472 'Some Content',
473 'Create the page'
474 );
475
476 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'timestamp', ] );
477 $items = $this->getItemsFromApiResponse( $result );
478
479 $this->assertCount( 1, $items );
480 $this->assertArrayHasKey( 'timestamp', $items[0] );
481 $this->assertInternalType( 'string', $items[0]['timestamp'] );
482 }
483
484 public function testSizesPropParameter() {
485 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
486 $this->doPageEdit(
487 $this->getLoggedInTestUser(),
488 $target,
489 'Some Content',
490 'Create the page'
491 );
492
493 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'sizes', ] );
494
495 $this->assertEquals(
496 [
497 [
498 'type' => 'new',
499 'oldlen' => 0,
500 'newlen' => 12,
501 ],
502 ],
503 $this->getItemsFromApiResponse( $result )
504 );
505 }
506
507 private function createPageAndDeleteIt( LinkTarget $target ) {
508 $this->doPageEdit(
509 $this->getLoggedInTestUser(),
510 $target,
511 'Some Content',
512 'Create the page that will be deleted'
513 );
514 $this->deletePage( $target, 'Important Reason' );
515 }
516
517 public function testLoginfoPropParameter() {
518 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
519 $this->createPageAndDeleteIt( $target );
520
521 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'loginfo', ] );
522
523 $this->assertArraySubsetsEqual(
524 $this->getItemsFromApiResponse( $result ),
525 [
526 [
527 'type' => 'log',
528 'logtype' => 'delete',
529 'logaction' => 'delete',
530 'logparams' => [],
531 ],
532 ],
533 [ 'type', 'logtype', 'logaction', 'logparams' ],
534 [ 'logid' ]
535 );
536 }
537
538 public function testEmptyPropParameter() {
539 $user = $this->getLoggedInTestUser();
540 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
541 $this->doPageEdit(
542 $user,
543 $target,
544 'Some Content',
545 'Create the page'
546 );
547
548 $result = $this->doListRecentChangesRequest( [ 'rcprop' => '', ] );
549
550 $this->assertEquals(
551 [
552 [
553 'type' => 'new',
554 ]
555 ],
556 $this->getItemsFromApiResponse( $result )
557 );
558 }
559
560 public function testNamespaceParam() {
561 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
562 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
563 $this->doPageEdits(
564 $this->getLoggedInTestUser(),
565 [
566 [
567 'target' => $subjectTarget,
568 'content' => 'Some Content',
569 'summary' => 'Create the page',
570 ],
571 [
572 'target' => $talkTarget,
573 'content' => 'Some Content',
574 'summary' => 'Create the talk page',
575 ],
576 ]
577 );
578
579 $result = $this->doListRecentChangesRequest( [ 'rcnamespace' => '0', ] );
580
581 $this->assertArraySubsetsEqual(
582 $this->getItemsFromApiResponse( $result ),
583 [
584 [
585 'ns' => 0,
586 'title' => $this->getPrefixedText( $subjectTarget ),
587 ],
588 ],
589 [ 'ns', 'title' ]
590 );
591 }
592
593 public function testShowAnonParams() {
594 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
595 $this->doAnonPageEdit(
596 $target,
597 'Some Content',
598 'Create the page'
599 );
600
601 $resultAnon = $this->doListRecentChangesRequest( [
602 'rcprop' => 'user',
603 'rcshow' => WatchedItemQueryService::FILTER_ANON
604 ] );
605 $resultNotAnon = $this->doListRecentChangesRequest( [
606 'rcprop' => 'user',
607 'rcshow' => WatchedItemQueryService::FILTER_NOT_ANON
608 ] );
609
610 $this->assertArraySubsetsEqual(
611 $this->getItemsFromApiResponse( $resultAnon ),
612 [
613 [ 'anon' => true ],
614 ],
615 [ 'anon' ]
616 );
617 $this->assertEmpty( $this->getItemsFromApiResponse( $resultNotAnon ) );
618 }
619
620 public function testNewAndEditTypeParameters() {
621 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
622 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
623 $this->doPageEdits(
624 $this->getLoggedInTestUser(),
625 [
626 [
627 'target' => $subjectTarget,
628 'content' => 'Some Content',
629 'summary' => 'Create the page',
630 ],
631 [
632 'target' => $subjectTarget,
633 'content' => 'Some Other Content',
634 'summary' => 'Change the content',
635 ],
636 [
637 'target' => $talkTarget,
638 'content' => 'Some Talk Page Content',
639 'summary' => 'Create Talk page',
640 ],
641 ]
642 );
643
644 $resultNew = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rctype' => 'new' ] );
645 $resultEdit = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rctype' => 'edit' ] );
646
647 $this->assertEquals(
648 [
649 [
650 'type' => 'new',
651 'ns' => $talkTarget->getNamespace(),
652 'title' => $this->getPrefixedText( $talkTarget ),
653 ],
654 [
655 'type' => 'new',
656 'ns' => $subjectTarget->getNamespace(),
657 'title' => $this->getPrefixedText( $subjectTarget ),
658 ],
659 ],
660 $this->getItemsFromApiResponse( $resultNew )
661 );
662 $this->assertEquals(
663 [
664 [
665 'type' => 'edit',
666 'ns' => $subjectTarget->getNamespace(),
667 'title' => $this->getPrefixedText( $subjectTarget ),
668 ],
669 ],
670 $this->getItemsFromApiResponse( $resultEdit )
671 );
672 }
673
674 public function testLogTypeParameters() {
675 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
676 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
677 $this->createPageAndDeleteIt( $subjectTarget );
678 $this->doPageEdit(
679 $this->getLoggedInTestUser(),
680 $talkTarget,
681 'Some Talk Page Content',
682 'Create Talk page'
683 );
684
685 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rctype' => 'log' ] );
686
687 $this->assertEquals(
688 [
689 [
690 'type' => 'log',
691 'ns' => $subjectTarget->getNamespace(),
692 'title' => $this->getPrefixedText( $subjectTarget ),
693 ],
694 ],
695 $this->getItemsFromApiResponse( $result )
696 );
697 }
698
699 private function getExternalRC( LinkTarget $target ) {
700 $title = Title::newFromLinkTarget( $target );
701
702 $rc = new RecentChange;
703 $rc->mTitle = $title;
704 $rc->mAttribs = [
705 'rc_timestamp' => wfTimestamp( TS_MW ),
706 'rc_namespace' => $title->getNamespace(),
707 'rc_title' => $title->getDBkey(),
708 'rc_type' => RC_EXTERNAL,
709 'rc_source' => 'foo',
710 'rc_minor' => 0,
711 'rc_cur_id' => $title->getArticleID(),
712 'rc_user' => 0,
713 'rc_user_text' => 'External User',
714 'rc_comment' => '',
715 'rc_comment_text' => '',
716 'rc_comment_data' => null,
717 'rc_this_oldid' => $title->getLatestRevID(),
718 'rc_last_oldid' => $title->getLatestRevID(),
719 'rc_bot' => 0,
720 'rc_ip' => '',
721 'rc_patrolled' => 0,
722 'rc_new' => 0,
723 'rc_old_len' => $title->getLength(),
724 'rc_new_len' => $title->getLength(),
725 'rc_deleted' => 0,
726 'rc_logid' => 0,
727 'rc_log_type' => null,
728 'rc_log_action' => '',
729 'rc_params' => '',
730 ];
731 $rc->mExtra = [
732 'prefixedDBkey' => $title->getPrefixedDBkey(),
733 'lastTimestamp' => 0,
734 'oldSize' => $title->getLength(),
735 'newSize' => $title->getLength(),
736 'pageStatus' => 'changed'
737 ];
738
739 return $rc;
740 }
741
742 public function testExternalTypeParameters() {
743 $user = $this->getLoggedInTestUser();
744 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
745 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
746 $this->doPageEdit(
747 $user,
748 $subjectTarget,
749 'Some Content',
750 'Create the page'
751 );
752 $this->doPageEdit(
753 $user,
754 $talkTarget,
755 'Some Talk Page Content',
756 'Create Talk page'
757 );
758
759 $rc = $this->getExternalRC( $subjectTarget );
760 $rc->save();
761
762 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rctype' => 'external' ] );
763
764 $this->assertEquals(
765 [
766 [
767 'type' => 'external',
768 'ns' => $subjectTarget->getNamespace(),
769 'title' => $this->getPrefixedText( $subjectTarget ),
770 ],
771 ],
772 $this->getItemsFromApiResponse( $result )
773 );
774 }
775
776 public function testCategorizeTypeParameter() {
777 $user = $this->getLoggedInTestUser();
778 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
779 $categoryTarget = new TitleValue( NS_CATEGORY, 'ApiQueryRecentChangesIntegrationTestCategory' );
780 $this->doPageEdits(
781 $user,
782 [
783 [
784 'target' => $categoryTarget,
785 'content' => 'Some Content',
786 'summary' => 'Create the category',
787 ],
788 [
789 'target' => $subjectTarget,
790 'content' => 'Some Content [[Category:ApiQueryRecentChangesIntegrationTestCategory]]t',
791 'summary' => 'Create the page and add it to the category',
792 ],
793 ]
794 );
795 $title = Title::newFromLinkTarget( $subjectTarget );
796 $revision = Revision::newFromTitle( $title );
797
798 $rc = RecentChange::newForCategorization(
799 $revision->getTimestamp(),
800 Title::newFromLinkTarget( $categoryTarget ),
801 $user,
802 $revision->getComment(),
803 $title,
804 0,
805 $revision->getId(),
806 null,
807 false
808 );
809 $rc->save();
810
811 $result = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rctype' => 'categorize' ] );
812
813 $this->assertEquals(
814 [
815 [
816 'type' => 'categorize',
817 'ns' => $categoryTarget->getNamespace(),
818 'title' => $this->getPrefixedText( $categoryTarget ),
819 ],
820 ],
821 $this->getItemsFromApiResponse( $result )
822 );
823 }
824
825 public function testLimitParam() {
826 $target1 = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
827 $target2 = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
828 $target3 = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage2' );
829 $this->doPageEdits(
830 $this->getLoggedInTestUser(),
831 [
832 [
833 'target' => $target1,
834 'content' => 'Some Content',
835 'summary' => 'Create the page',
836 ],
837 [
838 'target' => $target2,
839 'content' => 'Some Talk Page Content',
840 'summary' => 'Create Talk page',
841 ],
842 [
843 'target' => $target3,
844 'content' => 'Some Other Content',
845 'summary' => 'Create the page',
846 ],
847 ]
848 );
849
850 $resultWithoutLimit = $this->doListRecentChangesRequest( [ 'rcprop' => 'title' ] );
851 $resultWithLimit = $this->doListRecentChangesRequest( [ 'rclimit' => 2, 'rcprop' => 'title' ] );
852
853 $this->assertEquals(
854 [
855 [
856 'type' => 'new',
857 'ns' => $target3->getNamespace(),
858 'title' => $this->getPrefixedText( $target3 )
859 ],
860 [
861 'type' => 'new',
862 'ns' => $target2->getNamespace(),
863 'title' => $this->getPrefixedText( $target2 )
864 ],
865 [
866 'type' => 'new',
867 'ns' => $target1->getNamespace(),
868 'title' => $this->getPrefixedText( $target1 )
869 ],
870 ],
871 $this->getItemsFromApiResponse( $resultWithoutLimit )
872 );
873 $this->assertEquals(
874 [
875 [
876 'type' => 'new',
877 'ns' => $target3->getNamespace(),
878 'title' => $this->getPrefixedText( $target3 )
879 ],
880 [
881 'type' => 'new',
882 'ns' => $target2->getNamespace(),
883 'title' => $this->getPrefixedText( $target2 )
884 ],
885 ],
886 $this->getItemsFromApiResponse( $resultWithLimit )
887 );
888 $this->assertArrayHasKey( 'continue', $resultWithLimit[0] );
889 $this->assertArrayHasKey( 'rccontinue', $resultWithLimit[0]['continue'] );
890 }
891
892 public function testAllRevParam() {
893 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
894 $this->doPageEdits(
895 $this->getLoggedInTestUser(),
896 [
897 [
898 'target' => $target,
899 'content' => 'Some Content',
900 'summary' => 'Create the page',
901 ],
902 [
903 'target' => $target,
904 'content' => 'Some Other Content',
905 'summary' => 'Change the content',
906 ],
907 ]
908 );
909
910 $resultAllRev = $this->doListRecentChangesRequest( [ 'rcprop' => 'title', 'rcallrev' => '', ] );
911 $resultNoAllRev = $this->doListRecentChangesRequest( [ 'rcprop' => 'title' ] );
912
913 $this->assertEquals(
914 [
915 [
916 'type' => 'edit',
917 'ns' => $target->getNamespace(),
918 'title' => $this->getPrefixedText( $target ),
919 ],
920 [
921 'type' => 'new',
922 'ns' => $target->getNamespace(),
923 'title' => $this->getPrefixedText( $target ),
924 ],
925 ],
926 $this->getItemsFromApiResponse( $resultNoAllRev )
927 );
928 $this->assertEquals(
929 [
930 [
931 'type' => 'edit',
932 'ns' => $target->getNamespace(),
933 'title' => $this->getPrefixedText( $target ),
934 ],
935 [
936 'type' => 'new',
937 'ns' => $target->getNamespace(),
938 'title' => $this->getPrefixedText( $target ),
939 ],
940 ],
941 $this->getItemsFromApiResponse( $resultAllRev )
942 );
943 }
944
945 public function testDirParams() {
946 $subjectTarget = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
947 $talkTarget = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
948 $this->doPageEdits(
949 $this->getLoggedInTestUser(),
950 [
951 [
952 'target' => $subjectTarget,
953 'content' => 'Some Content',
954 'summary' => 'Create the page',
955 ],
956 [
957 'target' => $talkTarget,
958 'content' => 'Some Talk Page Content',
959 'summary' => 'Create Talk page',
960 ],
961 ]
962 );
963
964 $resultDirOlder = $this->doListRecentChangesRequest(
965 [ 'rcdir' => 'older', 'rcprop' => 'title' ]
966 );
967 $resultDirNewer = $this->doListRecentChangesRequest(
968 [ 'rcdir' => 'newer', 'rcprop' => 'title' ]
969 );
970
971 $this->assertEquals(
972 [
973 [
974 'type' => 'new',
975 'ns' => $talkTarget->getNamespace(),
976 'title' => $this->getPrefixedText( $talkTarget )
977 ],
978 [
979 'type' => 'new',
980 'ns' => $subjectTarget->getNamespace(),
981 'title' => $this->getPrefixedText( $subjectTarget )
982 ],
983 ],
984 $this->getItemsFromApiResponse( $resultDirOlder )
985 );
986 $this->assertEquals(
987 [
988 [
989 'type' => 'new',
990 'ns' => $subjectTarget->getNamespace(),
991 'title' => $this->getPrefixedText( $subjectTarget )
992 ],
993 [
994 'type' => 'new',
995 'ns' => $talkTarget->getNamespace(),
996 'title' => $this->getPrefixedText( $talkTarget )
997 ],
998 ],
999 $this->getItemsFromApiResponse( $resultDirNewer )
1000 );
1001 }
1002
1003 public function testStartEndParams() {
1004 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
1005 $this->doPageEdit(
1006 $this->getLoggedInTestUser(),
1007 $target,
1008 'Some Content',
1009 'Create the page'
1010 );
1011
1012 $resultStart = $this->doListRecentChangesRequest( [
1013 'rcstart' => '20010115000000',
1014 'rcdir' => 'newer',
1015 'rcprop' => 'title',
1016 ] );
1017 $resultEnd = $this->doListRecentChangesRequest( [
1018 'rcend' => '20010115000000',
1019 'rcdir' => 'newer',
1020 'rcprop' => 'title',
1021 ] );
1022
1023 $this->assertEquals(
1024 [
1025 [
1026 'type' => 'new',
1027 'ns' => $target->getNamespace(),
1028 'title' => $this->getPrefixedText( $target ),
1029 ]
1030 ],
1031 $this->getItemsFromApiResponse( $resultStart )
1032 );
1033 $this->assertEmpty( $this->getItemsFromApiResponse( $resultEnd ) );
1034 }
1035
1036 public function testContinueParam() {
1037 $target1 = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
1038 $target2 = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage' );
1039 $target3 = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage2' );
1040 $this->doPageEdits(
1041 $this->getLoggedInTestUser(),
1042 [
1043 [
1044 'target' => $target1,
1045 'content' => 'Some Content',
1046 'summary' => 'Create the page',
1047 ],
1048 [
1049 'target' => $target2,
1050 'content' => 'Some Talk Page Content',
1051 'summary' => 'Create Talk page',
1052 ],
1053 [
1054 'target' => $target3,
1055 'content' => 'Some Other Content',
1056 'summary' => 'Create the page',
1057 ],
1058 ]
1059 );
1060
1061 $firstResult = $this->doListRecentChangesRequest( [ 'rclimit' => 2, 'rcprop' => 'title' ] );
1062 $this->assertArrayHasKey( 'continue', $firstResult[0] );
1063 $this->assertArrayHasKey( 'rccontinue', $firstResult[0]['continue'] );
1064
1065 $continuationParam = $firstResult[0]['continue']['rccontinue'];
1066
1067 $continuedResult = $this->doListRecentChangesRequest(
1068 [ 'rccontinue' => $continuationParam, 'rcprop' => 'title' ]
1069 );
1070
1071 $this->assertEquals(
1072 [
1073 [
1074 'type' => 'new',
1075 'ns' => $target3->getNamespace(),
1076 'title' => $this->getPrefixedText( $target3 ),
1077 ],
1078 [
1079 'type' => 'new',
1080 'ns' => $target2->getNamespace(),
1081 'title' => $this->getPrefixedText( $target2 ),
1082 ],
1083 ],
1084 $this->getItemsFromApiResponse( $firstResult )
1085 );
1086 $this->assertEquals(
1087 [
1088 [
1089 'type' => 'new',
1090 'ns' => $target1->getNamespace(),
1091 'title' => $this->getPrefixedText( $target1 )
1092 ]
1093 ],
1094 $this->getItemsFromApiResponse( $continuedResult )
1095 );
1096 }
1097
1098 public function testGeneratorRecentChangesPropInfo_returnsRCPages() {
1099 $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
1100 $this->doPageEdit(
1101 $this->getLoggedInTestUser(),
1102 $target,
1103 'Some Content',
1104 'Create the page'
1105 );
1106
1107 $result = $this->doGeneratorRecentChangesRequest( [ 'prop' => 'info' ] );
1108
1109 $this->assertArrayHasKey( 'query', $result[0] );
1110 $this->assertArrayHasKey( 'pages', $result[0]['query'] );
1111
1112 // $result[0]['query']['pages'] uses page ids as keys. Page ids don't matter here, so drop them
1113 $pages = array_values( $result[0]['query']['pages'] );
1114
1115 $this->assertArraySubsetsEqual(
1116 $pages,
1117 [
1118 [
1119 'ns' => $target->getNamespace(),
1120 'title' => $this->getPrefixedText( $target ),
1121 'new' => true,
1122 ]
1123 ],
1124 [ 'ns', 'title', 'new' ]
1125 );
1126 }
1127
1128 }