MediaWiki REL1_31
RevisionDbTestBase.php
Go to the documentation of this file.
1<?php
6
13abstract class RevisionDbTestBase extends MediaWikiTestCase {
14
18 private $testPage;
19
20 public function __construct( $name = null, array $data = [], $dataName = '' ) {
21 parent::__construct( $name, $data, $dataName );
22
23 $this->tablesUsed = array_merge( $this->tablesUsed,
24 [
25 'page',
26 'revision',
27 'ip_changes',
28 'text',
29 'archive',
30
31 'recentchanges',
32 'logging',
33
34 'page_props',
35 'pagelinks',
36 'categorylinks',
37 'langlinks',
38 'externallinks',
39 'imagelinks',
40 'templatelinks',
41 'iwlinks'
42 ]
43 );
44 }
45
46 protected function setUp() {
47 global $wgContLang;
48
49 parent::setUp();
50
52 'wgExtraNamespaces',
53 [
54 12312 => 'Dummy',
55 12313 => 'Dummy_talk',
56 ]
57 );
58
60 'wgNamespaceContentModels',
61 [
63 ]
64 );
65
67 'wgContentHandlers',
68 [
69 DummyContentForTesting::MODEL_ID => 'DummyContentHandlerForTesting',
70 RevisionTestModifyableContent::MODEL_ID => 'RevisionTestModifyableContentHandler',
71 ]
72 );
73
74 $this->setMwGlobals( 'wgContentHandlerUseDB', $this->getContentHandlerUseDB() );
75
76 MWNamespace::clearCaches();
77 // Reset namespace cache
78 $wgContLang->resetNamespaces();
79
80 if ( !$this->testPage ) {
85 $this->testPage = $this->createPage( __CLASS__, __CLASS__ );
86 }
87 }
88
89 protected function tearDown() {
90 global $wgContLang;
91
92 parent::tearDown();
93
94 MWNamespace::clearCaches();
95 // Reset namespace cache
96 $wgContLang->resetNamespaces();
97 }
98
99 abstract protected function getContentHandlerUseDB();
100
101 private function makeRevisionWithProps( $props = null ) {
102 if ( $props === null ) {
103 $props = [];
104 }
105
106 if ( !isset( $props['content'] ) && !isset( $props['text'] ) ) {
107 $props['text'] = 'Lorem Ipsum';
108 }
109
110 if ( !isset( $props['user_text'] ) ) {
111 $user = $this->getTestUser()->getUser();
112 $props['user_text'] = $user->getName();
113 $props['user'] = $user->getId();
114 }
115
116 if ( !isset( $props['user'] ) ) {
117 $props['user'] = 0;
118 }
119
120 if ( !isset( $props['comment'] ) ) {
121 $props['comment'] = 'just a test';
122 }
123
124 if ( !isset( $props['page'] ) ) {
125 $props['page'] = $this->testPage->getId();
126 }
127
128 if ( !isset( $props['content_model'] ) ) {
129 $props['content_model'] = CONTENT_MODEL_WIKITEXT;
130 }
131
132 $rev = new Revision( $props );
133
134 $dbw = wfGetDB( DB_MASTER );
135 $rev->insertOn( $dbw );
136
137 return $rev;
138 }
139
147 private function createPage( $titleString, $text, $model = null ) {
148 if ( !preg_match( '/:/', $titleString ) &&
149 ( $model === null || $model === CONTENT_MODEL_WIKITEXT )
150 ) {
151 $ns = $this->getDefaultWikitextNS();
152 $titleString = MWNamespace::getCanonicalName( $ns ) . ':' . $titleString;
153 }
154
155 $title = Title::newFromText( $titleString );
156 $wikipage = new WikiPage( $title );
157
158 // Delete the article if it already exists
159 if ( $wikipage->exists() ) {
160 $wikipage->doDeleteArticle( "done" );
161 }
162
163 $content = ContentHandler::makeContent( $text, $title, $model );
164 $wikipage->doEditContent( $content, __METHOD__, EDIT_NEW );
165
166 return $wikipage;
167 }
168
169 private function assertRevEquals( Revision $orig, Revision $rev = null ) {
170 $this->assertNotNull( $rev, 'missing revision' );
171
172 $this->assertEquals( $orig->getId(), $rev->getId() );
173 $this->assertEquals( $orig->getPage(), $rev->getPage() );
174 $this->assertEquals( $orig->getTimestamp(), $rev->getTimestamp() );
175 $this->assertEquals( $orig->getUser(), $rev->getUser() );
176 $this->assertEquals( $orig->getContentModel(), $rev->getContentModel() );
177 $this->assertEquals( $orig->getContentFormat(), $rev->getContentFormat() );
178 $this->assertEquals( $orig->getSha1(), $rev->getSha1() );
179 }
180
184 public function testGetRecentChange() {
185 $rev = $this->testPage->getRevision();
186 $recentChange = $rev->getRecentChange();
187
188 // Make sure various attributes look right / the correct entry has been retrieved.
189 $this->assertEquals( $rev->getTimestamp(), $recentChange->getAttribute( 'rc_timestamp' ) );
190 $this->assertEquals(
191 $rev->getTitle()->getNamespace(),
192 $recentChange->getAttribute( 'rc_namespace' )
193 );
194 $this->assertEquals(
195 $rev->getTitle()->getDBkey(),
196 $recentChange->getAttribute( 'rc_title' )
197 );
198 $this->assertEquals( $rev->getUser(), $recentChange->getAttribute( 'rc_user' ) );
199 $this->assertEquals( $rev->getUserText(), $recentChange->getAttribute( 'rc_user_text' ) );
200 $this->assertEquals( $rev->getComment(), $recentChange->getAttribute( 'rc_comment' ) );
201 $this->assertEquals( $rev->getPage(), $recentChange->getAttribute( 'rc_cur_id' ) );
202 $this->assertEquals( $rev->getId(), $recentChange->getAttribute( 'rc_this_oldid' ) );
203 }
204
208 public function testInsertOn_success() {
209 $parentId = $this->testPage->getLatest();
210
211 // If an ExternalStore is set don't use it.
212 $this->setMwGlobals( 'wgDefaultExternalStore', false );
213
214 $rev = new Revision( [
215 'page' => $this->testPage->getId(),
216 'title' => $this->testPage->getTitle(),
217 'text' => 'Revision Text',
218 'comment' => 'Revision comment',
219 ] );
220
221 $revId = $rev->insertOn( wfGetDB( DB_MASTER ) );
222
223 $this->assertInternalType( 'integer', $revId );
224 $this->assertSame( $revId, $rev->getId() );
225
226 // getTextId() must be an int!
227 $this->assertInternalType( 'integer', $rev->getTextId() );
228
229 $mainSlot = $rev->getRevisionRecord()->getSlot( 'main', RevisionRecord::RAW );
230
231 // we currently only support storage in the text table
232 $textId = MediaWikiServices::getInstance()
233 ->getBlobStore()
234 ->getTextIdFromAddress( $mainSlot->getAddress() );
235
236 $this->assertSelect(
237 'text',
238 [ 'old_id', 'old_text' ],
239 "old_id = $textId",
240 [ [ strval( $textId ), 'Revision Text' ] ]
241 );
242 $this->assertSelect(
243 'revision',
244 [
245 'rev_id',
246 'rev_page',
247 'rev_text_id',
248 'rev_minor_edit',
249 'rev_deleted',
250 'rev_len',
251 'rev_parent_id',
252 'rev_sha1',
253 ],
254 "rev_id = {$rev->getId()}",
255 [ [
256 strval( $rev->getId() ),
257 strval( $this->testPage->getId() ),
258 strval( $textId ),
259 '0',
260 '0',
261 '13',
262 strval( $parentId ),
263 's0ngbdoxagreuf2vjtuxzwdz64n29xm',
264 ] ]
265 );
266 }
267
272 // If an ExternalStore is set don't use it.
273 $this->setMwGlobals( 'wgDefaultExternalStore', false );
274 $this->setExpectedException(
275 IncompleteRevisionException::class,
276 "rev_page field must not be 0!"
277 );
278
279 $title = Title::newFromText( 'Nonexistant-' . __METHOD__ );
280 $rev = new Revision( [], 0, $title );
281
282 $rev->insertOn( wfGetDB( DB_MASTER ) );
283 }
284
288 public function testNewFromTitle_withoutId() {
289 $latestRevId = $this->testPage->getLatest();
290
291 $rev = Revision::newFromTitle( $this->testPage->getTitle() );
292
293 $this->assertTrue( $this->testPage->getTitle()->equals( $rev->getTitle() ) );
294 $this->assertEquals( $latestRevId, $rev->getId() );
295 }
296
300 public function testNewFromTitle_withId() {
301 $latestRevId = $this->testPage->getLatest();
302
303 $rev = Revision::newFromTitle( $this->testPage->getTitle(), $latestRevId );
304
305 $this->assertTrue( $this->testPage->getTitle()->equals( $rev->getTitle() ) );
306 $this->assertEquals( $latestRevId, $rev->getId() );
307 }
308
312 public function testNewFromTitle_withBadId() {
313 $latestRevId = $this->testPage->getLatest();
314
315 $rev = Revision::newFromTitle( $this->testPage->getTitle(), $latestRevId + 1 );
316
317 $this->assertNull( $rev );
318 }
319
323 public function testNewFromRow() {
324 $orig = $this->makeRevisionWithProps();
325
327 $revQuery = Revision::getQueryInfo();
328 $res = $dbr->select( $revQuery['tables'], $revQuery['fields'], [ 'rev_id' => $orig->getId() ],
329 __METHOD__, [], $revQuery['joins'] );
330 $this->assertTrue( is_object( $res ), 'query failed' );
331
332 $row = $res->fetchObject();
333 $res->free();
334
335 $rev = Revision::newFromRow( $row );
336
337 $this->assertRevEquals( $orig, $rev );
338 }
339
340 public function provideNewFromArchiveRow() {
341 yield [
342 function ( $f ) {
343 return $f;
344 },
345 ];
346 yield [
347 function ( $f ) {
348 return $f + [ 'ar_namespace', 'ar_title' ];
349 },
350 ];
351 yield [
352 function ( $f ) {
353 unset( $f['ar_text_id'] );
354 return $f;
355 },
356 ];
357 yield [
358 function ( $f ) {
359 unset( $f['ar_page_id'] );
360 return $f;
361 },
362 ];
363 yield [
364 function ( $f ) {
365 unset( $f['ar_parent_id'] );
366 return $f;
367 },
368 ];
369 yield [
370 function ( $f ) {
371 unset( $f['ar_rev_id'] );
372 return $f;
373 },
374 ];
375 yield [
376 function ( $f ) {
377 unset( $f['ar_sha1'] );
378 return $f;
379 },
380 ];
381 }
382
387 public function testNewFromArchiveRow( $selectModifier ) {
388 $services = MediaWikiServices::getInstance();
389
390 $store = new RevisionStore(
391 $services->getDBLoadBalancer(),
392 $services->getService( '_SqlBlobStore' ),
393 $services->getMainWANObjectCache(),
394 $services->getCommentStore(),
395 $services->getActorMigration()
396 );
397
398 $store->setContentHandlerUseDB( $this->getContentHandlerUseDB() );
399 $this->setService( 'RevisionStore', $store );
400
401 $page = $this->createPage(
402 'RevisionStorageTest_testNewFromArchiveRow',
403 'Lorem Ipsum',
405 );
406 $orig = $page->getRevision();
407 $page->doDeleteArticle( 'test Revision::newFromArchiveRow' );
408
410 $arQuery = Revision::getArchiveQueryInfo();
411 $arQuery['fields'] = $selectModifier( $arQuery['fields'] );
412 $res = $dbr->select(
413 $arQuery['tables'], $arQuery['fields'], [ 'ar_rev_id' => $orig->getId() ],
414 __METHOD__, [], $arQuery['joins']
415 );
416 $this->assertTrue( is_object( $res ), 'query failed' );
417
418 $row = $res->fetchObject();
419 $res->free();
420
421 // MCR migration note: $row is now required to contain ar_title and ar_namespace.
422 // Alternatively, a Title object can be passed to RevisionStore::newRevisionFromArchiveRow
423 $rev = Revision::newFromArchiveRow( $row );
424
425 $this->assertRevEquals( $orig, $rev );
426 }
427
432 $page = $this->createPage(
433 'RevisionStorageTest_testNewFromArchiveRow',
434 'Lorem Ipsum',
436 );
437 $orig = $page->getRevision();
438 $page->doDeleteArticle( 'test Revision::newFromArchiveRow' );
439
441 $arQuery = Revision::getArchiveQueryInfo();
442 $res = $dbr->select(
443 $arQuery['tables'], $arQuery['fields'], [ 'ar_rev_id' => $orig->getId() ],
444 __METHOD__, [], $arQuery['joins']
445 );
446 $this->assertTrue( is_object( $res ), 'query failed' );
447
448 $row = $res->fetchObject();
449 $res->free();
450
451 $rev = Revision::newFromArchiveRow( $row, [ 'comment_text' => 'SOMEOVERRIDE' ] );
452
453 $this->assertNotEquals( $orig->getComment(), $rev->getComment() );
454 $this->assertEquals( 'SOMEOVERRIDE', $rev->getComment() );
455 }
456
460 public function testNewFromId() {
461 $orig = $this->testPage->getRevision();
462 $rev = Revision::newFromId( $orig->getId() );
463 $this->assertRevEquals( $orig, $rev );
464 }
465
469 public function testNewFromPageId() {
470 $rev = Revision::newFromPageId( $this->testPage->getId() );
471 $this->assertRevEquals(
472 $this->testPage->getRevision(),
473 $rev
474 );
475 }
476
481 $rev = Revision::newFromPageId(
482 $this->testPage->getId(),
483 $this->testPage->getLatest()
484 );
485 $this->assertRevEquals(
486 $this->testPage->getRevision(),
487 $rev
488 );
489 }
490
495 $content = new WikitextContent( __METHOD__ );
496 $this->testPage->doEditContent( $content, __METHOD__ );
497 $rev = Revision::newFromPageId(
498 $this->testPage->getId(),
499 $this->testPage->getRevision()->getPrevious()->getId()
500 );
501 $this->assertRevEquals(
502 $this->testPage->getRevision()->getPrevious(),
503 $rev
504 );
505 }
506
510 public function testFetchRevision() {
511 // Hidden process cache assertion below
512 $this->testPage->getRevision()->getId();
513
514 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
515 $id = $this->testPage->getRevision()->getId();
516
517 $this->hideDeprecated( 'Revision::fetchRevision' );
518 $res = Revision::fetchRevision( $this->testPage->getTitle() );
519
520 # note: order is unspecified
521 $rows = [];
522 while ( ( $row = $res->fetchObject() ) ) {
523 $rows[$row->rev_id] = $row;
524 }
525
526 $this->assertEmpty( $rows, 'expected empty set' );
527 }
528
532 public function testGetPage() {
533 $page = $this->testPage;
534
535 $orig = $this->makeRevisionWithProps( [ 'page' => $page->getId() ] );
536 $rev = Revision::newFromId( $orig->getId() );
537
538 $this->assertEquals( $page->getId(), $rev->getPage() );
539 }
540
544 public function testIsCurrent() {
545 $rev1 = $this->testPage->getRevision();
546
547 # @todo find out if this should be true
548 # $this->assertTrue( $rev1->isCurrent() );
549
550 $rev1x = Revision::newFromId( $rev1->getId() );
551 $this->assertTrue( $rev1x->isCurrent() );
552
553 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
554 $rev2 = $this->testPage->getRevision();
555
556 # @todo find out if this should be true
557 # $this->assertTrue( $rev2->isCurrent() );
558
559 $rev1x = Revision::newFromId( $rev1->getId() );
560 $this->assertFalse( $rev1x->isCurrent() );
561
562 $rev2x = Revision::newFromId( $rev2->getId() );
563 $this->assertTrue( $rev2x->isCurrent() );
564 }
565
569 public function testGetPrevious() {
570 $oldestRevision = $this->testPage->getOldestRevision();
571 $latestRevision = $this->testPage->getLatest();
572
573 $this->assertNull( $oldestRevision->getPrevious() );
574
575 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
576 $newRevision = $this->testPage->getRevision();
577
578 $this->assertNotNull( $newRevision->getPrevious() );
579 $this->assertEquals( $latestRevision, $newRevision->getPrevious()->getId() );
580 }
581
585 public function testGetNext() {
586 $rev1 = $this->testPage->getRevision();
587
588 $this->assertNull( $rev1->getNext() );
589
590 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
591 $rev2 = $this->testPage->getRevision();
592
593 $this->assertNotNull( $rev1->getNext() );
594 $this->assertEquals( $rev2->getId(), $rev1->getNext()->getId() );
595 }
596
600 public function testNewNullRevision() {
601 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
602 $orig = $this->testPage->getRevision();
603
604 $dbw = wfGetDB( DB_MASTER );
605 $rev = Revision::newNullRevision( $dbw, $this->testPage->getId(), 'a null revision', false );
606
607 $this->assertNotEquals( $orig->getId(), $rev->getId(),
608 'new null revision should have a different id from the original revision' );
609 $this->assertEquals( $orig->getTextId(), $rev->getTextId(),
610 'new null revision should have the same text id as the original revision' );
611 $this->assertEquals( $orig->getSha1(), $rev->getSha1(),
612 'new null revision should have the same SHA1 as the original revision' );
613 $this->assertTrue( $orig->getRevisionRecord()->hasSameContent( $rev->getRevisionRecord() ),
614 'new null revision should have the same content as the original revision' );
615 $this->assertEquals( __METHOD__, $rev->getContent()->getNativeData() );
616 }
617
621 public function testNewNullRevision_badPage() {
622 $dbw = wfGetDB( DB_MASTER );
623 $rev = Revision::newNullRevision( $dbw, -1, 'a null revision', false );
624
625 $this->assertNull( $rev );
626 }
627
631 public function testInsertOn() {
632 $ip = '2600:387:ed7:947e:8c16:a1ad:dd34:1dd7';
633
634 $orig = $this->makeRevisionWithProps( [
635 'user_text' => $ip
636 ] );
637
638 // Make sure the revision was copied to ip_changes
640 $res = $dbr->select( 'ip_changes', '*', [ 'ipc_rev_id' => $orig->getId() ] );
641 $row = $res->fetchObject();
642
643 $this->assertEquals( IP::toHex( $ip ), $row->ipc_hex );
644 $this->assertEquals(
645 $orig->getTimestamp(),
646 wfTimestamp( TS_MW, $row->ipc_rev_timestamp )
647 );
648 }
649
650 public static function provideUserWasLastToEdit() {
651 yield 'actually the last edit' => [ 3, true ];
652 yield 'not the current edit, but still by this user' => [ 2, true ];
653 yield 'edit by another user' => [ 1, false ];
654 yield 'first edit, by this user, but another user edited in the mean time' => [ 0, false ];
655 }
656
661 public function testUserWasLastToEdit( $sinceIdx, $expectedLast ) {
662 $userA = User::newFromName( "RevisionStorageTest_userA" );
663 $userB = User::newFromName( "RevisionStorageTest_userB" );
664
665 if ( $userA->getId() === 0 ) {
666 $userA = User::createNew( $userA->getName() );
667 }
668
669 if ( $userB->getId() === 0 ) {
670 $userB = User::createNew( $userB->getName() );
671 }
672
673 $ns = $this->getDefaultWikitextNS();
674
675 $dbw = wfGetDB( DB_MASTER );
676 $revisions = [];
677
678 // create revisions -----------------------------
679 $page = WikiPage::factory( Title::newFromText(
680 'RevisionStorageTest_testUserWasLastToEdit', $ns ) );
681 $page->insertOn( $dbw );
682
683 $revisions[0] = new Revision( [
684 'page' => $page->getId(),
685 // we need the title to determine the page's default content model
686 'title' => $page->getTitle(),
687 'timestamp' => '20120101000000',
688 'user' => $userA->getId(),
689 'text' => 'zero',
690 'content_model' => CONTENT_MODEL_WIKITEXT,
691 'comment' => 'edit zero'
692 ] );
693 $revisions[0]->insertOn( $dbw );
694
695 $revisions[1] = new Revision( [
696 'page' => $page->getId(),
697 // still need the title, because $page->getId() is 0 (there's no entry in the page table)
698 'title' => $page->getTitle(),
699 'timestamp' => '20120101000100',
700 'user' => $userA->getId(),
701 'text' => 'one',
702 'content_model' => CONTENT_MODEL_WIKITEXT,
703 'comment' => 'edit one'
704 ] );
705 $revisions[1]->insertOn( $dbw );
706
707 $revisions[2] = new Revision( [
708 'page' => $page->getId(),
709 'title' => $page->getTitle(),
710 'timestamp' => '20120101000200',
711 'user' => $userB->getId(),
712 'text' => 'two',
713 'content_model' => CONTENT_MODEL_WIKITEXT,
714 'comment' => 'edit two'
715 ] );
716 $revisions[2]->insertOn( $dbw );
717
718 $revisions[3] = new Revision( [
719 'page' => $page->getId(),
720 'title' => $page->getTitle(),
721 'timestamp' => '20120101000300',
722 'user' => $userA->getId(),
723 'text' => 'three',
724 'content_model' => CONTENT_MODEL_WIKITEXT,
725 'comment' => 'edit three'
726 ] );
727 $revisions[3]->insertOn( $dbw );
728
729 $revisions[4] = new Revision( [
730 'page' => $page->getId(),
731 'title' => $page->getTitle(),
732 'timestamp' => '20120101000200',
733 'user' => $userA->getId(),
734 'text' => 'zero',
735 'content_model' => CONTENT_MODEL_WIKITEXT,
736 'comment' => 'edit four'
737 ] );
738 $revisions[4]->insertOn( $dbw );
739
740 // test it ---------------------------------
741 $since = $revisions[$sinceIdx]->getTimestamp();
742
743 $revQuery = Revision::getQueryInfo();
744 $allRows = iterator_to_array( $dbw->select(
745 $revQuery['tables'],
746 [ 'rev_id', 'rev_timestamp', 'rev_user' => $revQuery['fields']['rev_user'] ],
747 [
748 'rev_page' => $page->getId(),
749 //'rev_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $since ) )
750 ],
751 __METHOD__,
752 [ 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 50 ],
753 $revQuery['joins']
754 ) );
755
756 $wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since );
757
758 $this->assertEquals( $expectedLast, $wasLast );
759 }
760
769 private function newTestRevision( $text, $title = "Test",
770 $model = CONTENT_MODEL_WIKITEXT, $format = null
771 ) {
772 if ( is_string( $title ) ) {
773 $title = Title::newFromText( $title );
774 }
775
776 $content = ContentHandler::makeContent( $text, $title, $model, $format );
777
778 $rev = new Revision(
779 [
780 'id' => 42,
781 'page' => 23,
782 'title' => $title,
783
784 'content' => $content,
785 'length' => $content->getSize(),
786 'comment' => "testing",
787 'minor_edit' => false,
788
789 'content_format' => $format,
790 ]
791 );
792
793 return $rev;
794 }
795
796 public function provideGetContentModel() {
797 // NOTE: we expect the help namespace to always contain wikitext
798 return [
799 [ 'hello world', 'Help:Hello', null, null, CONTENT_MODEL_WIKITEXT ],
800 [ 'hello world', 'User:hello/there.css', null, null, CONTENT_MODEL_CSS ],
801 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, DummyContentForTesting::MODEL_ID ],
802 ];
803 }
804
809 public function testGetContentModel( $text, $title, $model, $format, $expectedModel ) {
810 $rev = $this->newTestRevision( $text, $title, $model, $format );
811
812 $this->assertEquals( $expectedModel, $rev->getContentModel() );
813 }
814
815 public function provideGetContentFormat() {
816 // NOTE: we expect the help namespace to always contain wikitext
817 return [
818 [ 'hello world', 'Help:Hello', null, null, CONTENT_FORMAT_WIKITEXT ],
819 [ 'hello world', 'Help:Hello', CONTENT_MODEL_CSS, null, CONTENT_FORMAT_CSS ],
820 [ 'hello world', 'User:hello/there.css', null, null, CONTENT_FORMAT_CSS ],
821 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, DummyContentForTesting::MODEL_ID ],
822 ];
823 }
824
829 public function testGetContentFormat( $text, $title, $model, $format, $expectedFormat ) {
830 $rev = $this->newTestRevision( $text, $title, $model, $format );
831
832 $this->assertEquals( $expectedFormat, $rev->getContentFormat() );
833 }
834
835 public function provideGetContentHandler() {
836 // NOTE: we expect the help namespace to always contain wikitext
837 return [
838 [ 'hello world', 'Help:Hello', null, null, WikitextContentHandler::class ],
839 [ 'hello world', 'User:hello/there.css', null, null, CssContentHandler::class ],
840 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, DummyContentHandlerForTesting::class ],
841 ];
842 }
843
848 public function testGetContentHandler( $text, $title, $model, $format, $expectedClass ) {
849 $rev = $this->newTestRevision( $text, $title, $model, $format );
850
851 $this->assertEquals( $expectedClass, get_class( $rev->getContentHandler() ) );
852 }
853
854 public function provideGetContent() {
855 // NOTE: we expect the help namespace to always contain wikitext
856 return [
857 [ 'hello world', 'Help:Hello', null, null, Revision::FOR_PUBLIC, 'hello world' ],
858 [
859 serialize( 'hello world' ),
860 'Hello',
862 null,
863 Revision::FOR_PUBLIC,
864 serialize( 'hello world' )
865 ],
866 [
867 serialize( 'hello world' ),
868 'Dummy:Hello',
869 null,
870 null,
871 Revision::FOR_PUBLIC,
872 serialize( 'hello world' )
873 ],
874 ];
875 }
876
881 public function testGetContent( $text, $title, $model, $format,
882 $audience, $expectedSerialization
883 ) {
884 $rev = $this->newTestRevision( $text, $title, $model, $format );
885 $content = $rev->getContent( $audience );
886
887 $this->assertEquals(
888 $expectedSerialization,
889 is_null( $content ) ? null : $content->serialize( $format )
890 );
891 }
892
896 public function testGetContent_failure() {
897 $rev = new Revision( [
898 'page' => $this->testPage->getId(),
899 'content_model' => $this->testPage->getContentModel(),
900 'text_id' => 123456789, // not in the test DB
901 ] );
902
903 Wikimedia\suppressWarnings(); // bad text_id will trigger a warning.
904
905 $this->assertNull( $rev->getContent(),
906 "getContent() should return null if the revision's text blob could not be loaded." );
907
908 // NOTE: check this twice, once for lazy initialization, and once with the cached value.
909 $this->assertNull( $rev->getContent(),
910 "getContent() should return null if the revision's text blob could not be loaded." );
911
912 Wikimedia\restoreWarnings();
913 }
914
915 public function provideGetSize() {
916 return [
917 [ "hello world.", CONTENT_MODEL_WIKITEXT, 12 ],
918 [ serialize( "hello world." ), DummyContentForTesting::MODEL_ID, 12 ],
919 ];
920 }
921
926 public function testGetSize( $text, $model, $expected_size ) {
927 $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSize', $model );
928 $this->assertEquals( $expected_size, $rev->getSize() );
929 }
930
931 public function provideGetSha1() {
932 return [
933 [ "hello world.", CONTENT_MODEL_WIKITEXT, Revision::base36Sha1( "hello world." ) ],
934 [
935 serialize( "hello world." ),
937 Revision::base36Sha1( serialize( "hello world." ) )
938 ],
939 ];
940 }
941
946 public function testGetSha1( $text, $model, $expected_hash ) {
947 $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSha1', $model );
948 $this->assertEquals( $expected_hash, $rev->getSha1() );
949 }
950
956 public function testGetContentClone() {
957 $content = new RevisionTestModifyableContent( "foo" );
958
959 $rev = new Revision(
960 [
961 'id' => 42,
962 'page' => 23,
963 'title' => Title::newFromText( "testGetContentClone_dummy" ),
964
965 'content' => $content,
966 'length' => $content->getSize(),
967 'comment' => "testing",
968 'minor_edit' => false,
969 ]
970 );
971
973 $content = $rev->getContent( Revision::RAW );
974 $content->setText( "bar" );
975
977 $content2 = $rev->getContent( Revision::RAW );
978 // content is mutable, expect clone
979 $this->assertNotSame( $content, $content2, "expected a clone" );
980 // clone should contain the original text
981 $this->assertEquals( "foo", $content2->getText() );
982
983 $content2->setText( "bla bla" );
984 // clones should be independent
985 $this->assertEquals( "bar", $content->getText() );
986 }
987
992 public function testGetContentUncloned() {
993 $rev = $this->newTestRevision( "hello", "testGetContentUncloned_dummy", CONTENT_MODEL_WIKITEXT );
994 $content = $rev->getContent( Revision::RAW );
995 $content2 = $rev->getContent( Revision::RAW );
996
997 // for immutable content like wikitext, this should be the same object
998 $this->assertSame( $content, $content2 );
999 }
1000
1004 public function testLoadFromId() {
1005 $rev = $this->testPage->getRevision();
1006 $this->hideDeprecated( 'Revision::loadFromId' );
1007 $this->assertRevEquals(
1008 $rev,
1009 Revision::loadFromId( wfGetDB( DB_MASTER ), $rev->getId() )
1010 );
1011 }
1012
1016 public function testLoadFromPageId() {
1017 $this->assertRevEquals(
1018 $this->testPage->getRevision(),
1019 Revision::loadFromPageId( wfGetDB( DB_MASTER ), $this->testPage->getId() )
1020 );
1021 }
1022
1027 $this->assertRevEquals(
1028 $this->testPage->getRevision(),
1029 Revision::loadFromPageId(
1030 wfGetDB( DB_MASTER ),
1031 $this->testPage->getId(),
1032 $this->testPage->getLatest()
1033 )
1034 );
1035 }
1036
1041 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
1042 $this->assertRevEquals(
1043 $this->testPage->getRevision()->getPrevious(),
1044 Revision::loadFromPageId(
1045 wfGetDB( DB_MASTER ),
1046 $this->testPage->getId(),
1047 $this->testPage->getRevision()->getPrevious()->getId()
1048 )
1049 );
1050 }
1051
1055 public function testLoadFromTitle() {
1056 $this->assertRevEquals(
1057 $this->testPage->getRevision(),
1058 Revision::loadFromTitle( wfGetDB( DB_MASTER ), $this->testPage->getTitle() )
1059 );
1060 }
1061
1066 $this->assertRevEquals(
1067 $this->testPage->getRevision(),
1068 Revision::loadFromTitle(
1069 wfGetDB( DB_MASTER ),
1070 $this->testPage->getTitle(),
1071 $this->testPage->getLatest()
1072 )
1073 );
1074 }
1075
1080 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
1081 $this->assertRevEquals(
1082 $this->testPage->getRevision()->getPrevious(),
1083 Revision::loadFromTitle(
1084 wfGetDB( DB_MASTER ),
1085 $this->testPage->getTitle(),
1086 $this->testPage->getRevision()->getPrevious()->getId()
1087 )
1088 );
1089 }
1090
1094 public function testLoadFromTimestamp() {
1095 $this->assertRevEquals(
1096 $this->testPage->getRevision(),
1097 Revision::loadFromTimestamp(
1098 wfGetDB( DB_MASTER ),
1099 $this->testPage->getTitle(),
1100 $this->testPage->getRevision()->getTimestamp()
1101 )
1102 );
1103 }
1104
1109 $this->assertSame(
1110 [],
1111 Revision::getParentLengths(
1112 wfGetDB( DB_MASTER ),
1113 []
1114 )
1115 );
1116 }
1117
1122 $text = '831jr091jr0921kr21kr0921kjr0921j09rj1';
1123 $textLength = strlen( $text );
1124
1125 $this->testPage->doEditContent( new WikitextContent( $text ), __METHOD__ );
1126 $rev[1] = $this->testPage->getLatest();
1127
1128 $this->assertSame(
1129 [ $rev[1] => $textLength ],
1130 Revision::getParentLengths(
1131 wfGetDB( DB_MASTER ),
1132 [ $rev[1] ]
1133 )
1134 );
1135 }
1136
1141 $textOne = '831jr091jr0921kr21kr0921kjr0921j09rj1';
1142 $textOneLength = strlen( $textOne );
1143 $textTwo = '831jr091jr092121j09rj1';
1144 $textTwoLength = strlen( $textTwo );
1145
1146 $this->testPage->doEditContent( new WikitextContent( $textOne ), __METHOD__ );
1147 $rev[1] = $this->testPage->getLatest();
1148 $this->testPage->doEditContent( new WikitextContent( $textTwo ), __METHOD__ );
1149 $rev[2] = $this->testPage->getLatest();
1150
1151 $this->assertSame(
1152 [ $rev[1] => $textOneLength, $rev[2] => $textTwoLength ],
1153 Revision::getParentLengths(
1154 wfGetDB( DB_MASTER ),
1155 [ $rev[1], $rev[2] ]
1156 )
1157 );
1158 }
1159
1164 $this->assertTrue(
1165 $this->testPage->getTitle()->equals(
1166 $this->testPage->getRevision()->getTitle()
1167 )
1168 );
1169 }
1170
1175 $rev = new Revision( [ 'id' => $this->testPage->getLatest() ] );
1176 $this->assertTrue(
1177 $this->testPage->getTitle()->equals(
1178 $rev->getTitle()
1179 )
1180 );
1181 }
1182
1186 public function testIsMinor_true() {
1187 // Use a sysop to ensure we can mark edits as minor
1188 $sysop = $this->getTestSysop()->getUser();
1189
1190 $this->testPage->doEditContent(
1191 new WikitextContent( __METHOD__ ),
1192 __METHOD__,
1193 EDIT_MINOR,
1194 false,
1195 $sysop
1196 );
1197 $rev = $this->testPage->getRevision();
1198
1199 $this->assertSame( true, $rev->isMinor() );
1200 }
1201
1205 public function testIsMinor_false() {
1206 $this->testPage->doEditContent(
1207 new WikitextContent( __METHOD__ ),
1208 __METHOD__,
1209 0
1210 );
1211 $rev = $this->testPage->getRevision();
1212
1213 $this->assertSame( false, $rev->isMinor() );
1214 }
1215
1219 public function testGetTimestamp() {
1220 $testTimestamp = wfTimestampNow();
1221
1222 $this->testPage->doEditContent(
1223 new WikitextContent( __METHOD__ ),
1224 __METHOD__
1225 );
1226 $rev = $this->testPage->getRevision();
1227
1228 $this->assertInternalType( 'string', $rev->getTimestamp() );
1229 $this->assertTrue( strlen( $rev->getTimestamp() ) == strlen( 'YYYYMMDDHHMMSS' ) );
1230 $this->assertContains( substr( $testTimestamp, 0, 10 ), $rev->getTimestamp() );
1231 }
1232
1237 public function testGetUserAndText() {
1238 $sysop = $this->getTestSysop()->getUser();
1239
1240 $this->testPage->doEditContent(
1241 new WikitextContent( __METHOD__ ),
1242 __METHOD__,
1243 0,
1244 false,
1245 $sysop
1246 );
1247 $rev = $this->testPage->getRevision();
1248
1249 $this->assertSame( $sysop->getId(), $rev->getUser() );
1250 $this->assertSame( $sysop->getName(), $rev->getUserText() );
1251 }
1252
1257 $rev = $this->testPage->getRevision();
1258
1259 $this->assertSame( false, $rev->isDeleted( Revision::DELETED_TEXT ) );
1260 $this->assertSame( false, $rev->isDeleted( Revision::DELETED_COMMENT ) );
1261 $this->assertSame( false, $rev->isDeleted( Revision::DELETED_RESTRICTED ) );
1262 $this->assertSame( false, $rev->isDeleted( Revision::DELETED_USER ) );
1263 }
1264
1269 $rev = $this->testPage->getRevision();
1270
1271 $this->assertSame( 0, $rev->getVisibility() );
1272 }
1273
1277 public function testGetComment_notDeleted() {
1278 $expectedSummary = 'goatlicious summary';
1279
1280 $this->testPage->doEditContent(
1281 new WikitextContent( __METHOD__ ),
1282 $expectedSummary
1283 );
1284 $rev = $this->testPage->getRevision();
1285
1286 $this->assertSame( $expectedSummary, $rev->getComment() );
1287 }
1288
1293 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
1294 $rev = $this->testPage->getRevision();
1295
1296 $this->assertGreaterThan( 0, $rev->isUnpatrolled() );
1297 $this->assertSame( $rev->getRecentChange()->getAttribute( 'rc_id' ), $rev->isUnpatrolled() );
1298 }
1299
1304 // This assumes that sysops are auto patrolled
1305 $sysop = $this->getTestSysop()->getUser();
1306 $this->testPage->doEditContent(
1307 new WikitextContent( __METHOD__ ),
1308 __METHOD__,
1309 0,
1310 false,
1311 $sysop
1312 );
1313 $rev = $this->testPage->getRevision();
1314
1315 $this->assertSame( 0, $rev->isUnpatrolled() );
1316 }
1317
1327 public function testSimpleContentGetters() {
1328 $expectedText = 'testSimpleContentGetters in Revision. Goats love MCR...';
1329 $expectedSummary = 'goatlicious testSimpleContentGetters summary';
1330
1331 $this->testPage->doEditContent(
1332 new WikitextContent( $expectedText ),
1333 $expectedSummary
1334 );
1335 $rev = $this->testPage->getRevision();
1336
1337 $this->assertSame( $expectedText, $rev->getContent()->getNativeData() );
1338 $this->assertSame( $expectedText, $rev->getSerializedData() );
1339 $this->assertSame( $this->testPage->getContentModel(), $rev->getContentModel() );
1340 $this->assertSame( $this->testPage->getContent()->getDefaultFormat(), $rev->getContentFormat() );
1341 $this->assertSame( $this->testPage->getContentHandler(), $rev->getContentHandler() );
1342 }
1343
1347 public function testNewKnownCurrent() {
1348 // Setup the services
1349 $cache = new WANObjectCache( [ 'cache' => new HashBagOStuff() ] );
1350 $this->setService( 'MainWANObjectCache', $cache );
1351 $db = wfGetDB( DB_MASTER );
1352
1353 // Get a fresh revision to use during testing
1354 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
1355 $rev = $this->testPage->getRevision();
1356
1357 // Clear any previous cache for the revision during creation
1358 $key = $cache->makeGlobalKey( 'revision-row-1.29',
1359 $db->getDomainID(),
1360 $rev->getPage(),
1361 $rev->getId()
1362 );
1363 $cache->delete( $key, WANObjectCache::HOLDOFF_NONE );
1364 $this->assertFalse( $cache->get( $key ) );
1365
1366 // Get the new revision and make sure it is in the cache and correct
1367 $newRev = Revision::newKnownCurrent( $db, $rev->getPage(), $rev->getId() );
1368 $this->assertRevEquals( $rev, $newRev );
1369
1370 $cachedRow = $cache->get( $key );
1371 $this->assertNotFalse( $cachedRow );
1372 $this->assertEquals( $rev->getId(), $cachedRow->rev_id );
1373 }
1374
1376 $db = wfGetDB( DB_MASTER );
1377
1378 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
1379 $rev = $this->testPage->getRevision();
1380
1381 $pageId = $this->testPage->getId();
1382
1383 $newRev = Revision::newKnownCurrent( $db, $pageId, $rev->getId() );
1384 $this->assertRevEquals( $rev, $newRev );
1385 }
1386
1388 $db = wfGetDB( DB_MASTER );
1389
1390 $this->assertFalse( Revision::newKnownCurrent( $db, 0 ) );
1391 }
1392
1393 public function provideUserCanBitfield() {
1394 yield [ 0, 0, [], null, true ];
1395 // Bitfields match, user has no permissions
1396 yield [ Revision::DELETED_TEXT, Revision::DELETED_TEXT, [], null, false ];
1397 yield [ Revision::DELETED_COMMENT, Revision::DELETED_COMMENT, [], null, false ];
1398 yield [ Revision::DELETED_USER, Revision::DELETED_USER, [], null, false ];
1399 yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [], null, false ];
1400 // Bitfields match, user (admin) does have permissions
1401 yield [ Revision::DELETED_TEXT, Revision::DELETED_TEXT, [ 'sysop' ], null, true ];
1402 yield [ Revision::DELETED_COMMENT, Revision::DELETED_COMMENT, [ 'sysop' ], null, true ];
1403 yield [ Revision::DELETED_USER, Revision::DELETED_USER, [ 'sysop' ], null, true ];
1404 // Bitfields match, user (admin) does not have permissions
1405 yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [ 'sysop' ], null, false ];
1406 // Bitfields match, user (oversight) does have permissions
1407 yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [ 'oversight' ], null, true ];
1408 // Check permissions using the title
1409 yield [
1410 Revision::DELETED_TEXT,
1411 Revision::DELETED_TEXT,
1412 [ 'sysop' ],
1413 Title::newFromText( __METHOD__ ),
1414 true,
1415 ];
1416 yield [
1417 Revision::DELETED_TEXT,
1418 Revision::DELETED_TEXT,
1419 [],
1420 Title::newFromText( __METHOD__ ),
1421 false,
1422 ];
1423 }
1424
1429 public function testUserCanBitfield( $bitField, $field, $userGroups, $title, $expected ) {
1430 $this->setMwGlobals(
1431 'wgGroupPermissions',
1432 [
1433 'sysop' => [
1434 'deletedtext' => true,
1435 'deletedhistory' => true,
1436 ],
1437 'oversight' => [
1438 'viewsuppressed' => true,
1439 'suppressrevision' => true,
1440 ],
1441 ]
1442 );
1443 $user = $this->getTestUser( $userGroups )->getUser();
1444
1445 $this->assertSame(
1446 $expected,
1447 Revision::userCanBitfield( $bitField, $field, $user, $title )
1448 );
1449
1450 // Fallback to $wgUser
1451 $this->setMwGlobals(
1452 'wgUser',
1453 $user
1454 );
1455 $this->assertSame(
1456 $expected,
1457 Revision::userCanBitfield( $bitField, $field, null, $title )
1458 );
1459 }
1460
1461 public function provideUserCan() {
1462 yield [ 0, 0, [], true ];
1463 // Bitfields match, user has no permissions
1464 yield [ Revision::DELETED_TEXT, Revision::DELETED_TEXT, [], false ];
1465 yield [ Revision::DELETED_COMMENT, Revision::DELETED_COMMENT, [], false ];
1466 yield [ Revision::DELETED_USER, Revision::DELETED_USER, [], false ];
1467 yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [], false ];
1468 // Bitfields match, user (admin) does have permissions
1469 yield [ Revision::DELETED_TEXT, Revision::DELETED_TEXT, [ 'sysop' ], true ];
1470 yield [ Revision::DELETED_COMMENT, Revision::DELETED_COMMENT, [ 'sysop' ], true ];
1471 yield [ Revision::DELETED_USER, Revision::DELETED_USER, [ 'sysop' ], true ];
1472 // Bitfields match, user (admin) does not have permissions
1473 yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [ 'sysop' ], false ];
1474 // Bitfields match, user (oversight) does have permissions
1475 yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [ 'oversight' ], true ];
1476 }
1477
1482 public function testUserCan( $bitField, $field, $userGroups, $expected ) {
1483 $this->setMwGlobals(
1484 'wgGroupPermissions',
1485 [
1486 'sysop' => [
1487 'deletedtext' => true,
1488 'deletedhistory' => true,
1489 ],
1490 'oversight' => [
1491 'viewsuppressed' => true,
1492 'suppressrevision' => true,
1493 ],
1494 ]
1495 );
1496 $user = $this->getTestUser( $userGroups )->getUser();
1497 $revision = new Revision( [ 'deleted' => $bitField ], 0, $this->testPage->getTitle() );
1498
1499 $this->assertSame(
1500 $expected,
1501 $revision->userCan( $field, $user )
1502 );
1503 }
1504
1505}
serialize()
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Simple store for keeping values in an associative array for the current process.
getDefaultWikitextNS()
Returns the ID of a namespace that defaults to Wikitext.
Database $db
Primary database.
static getTestSysop()
Convenience method for getting an immutable admin test user.
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.
hideDeprecated( $function)
Don't throw a warning if $function is deprecated and called later.
setService( $name, $object)
Sets a service, maintaining a stashed version of the previous service to be restored in tearDown.
static getTestUser( $groups=[])
Convenience method for getting an immutable test user.
assertSelect( $table, $fields, $condition, array $expectedRows, array $options=[], array $join_conds=[])
Asserts that the given database query yields the rows given by $expectedRows.
MediaWikiServices is the service locator for the application scope of MediaWiki.
Exception throw when trying to access undefined fields on an incomplete RevisionRecord.
Page revision base class.
Service for looking up page revisions.
RevisionDbTestBase contains test cases for the Revision class that have Database interactions.
testLoadFromTitle()
Revision::loadFromTitle.
testNewNullRevision()
Revision::newNullRevision.
testNewKnownCurrent()
Revision::newKnownCurrent.
testLoadFromTitleWithNotLatestRevId()
Revision::loadFromTitle.
testUserCan( $bitField, $field, $userGroups, $expected)
provideUserCan Revision::userCan
testNewFromArchiveRowOverrides()
Revision::newFromArchiveRow.
testLoadFromPageIdWithNotLatestRevId()
Revision::loadFromPageId.
testGetContentHandler( $text, $title, $model, $format, $expectedClass)
provideGetContentHandler Revision::getContentHandler
testGetParentLengths_noRevIds()
Revision::getParentLengths.
testInsertOn_success()
Revision::insertOn.
assertRevEquals(Revision $orig, Revision $rev=null)
testGetComment_notDeleted()
Revision::getComment.
testGetVisibility_nothingDeleted()
Revision::getVisibility.
testGetContent_failure()
Revision::getContent.
testGetParentLengths_multipleRevIds()
Revision::getParentLengths.
testLoadFromId()
Revision::loadFromId.
testLoadFromPageId()
Revision::loadFromPageId.
testInsertOn_exceptionOnNoPage()
Revision::insertOn.
testGetTitle_fromExistingRevision()
Revision::getTitle.
testNewFromTitle_withBadId()
Revision::newFromTitle.
testGetSize( $text, $model, $expected_size)
Revision::getSize provideGetSize.
createPage( $titleString, $text, $model=null)
testGetContentModel( $text, $title, $model, $format, $expectedModel)
provideGetContentModel Revision::getContentModel
testGetContent( $text, $title, $model, $format, $audience, $expectedSerialization)
provideGetContent Revision::getContent
testInsertOn()
Revision::insertOn.
testGetTimestamp()
Revision::getTimestamp.
testNewFromPageId()
Revision::newFromPageId.
testFetchRevision()
Revision::fetchRevision.
testGetUserAndText()
Revision::getUser Revision::getUserText.
testLoadFromTitleWithLatestRevId()
Revision::loadFromTitle.
testGetRecentChange()
Revision::getRecentChange.
testGetSha1( $text, $model, $expected_hash)
Revision::getSha1 provideGetSha1.
testGetTitle_fromRevisionWhichWillLoadTheTitle()
Revision::getTitle.
testNewFromArchiveRow( $selectModifier)
provideNewFromArchiveRow Revision::newFromArchiveRow
testGetContentFormat( $text, $title, $model, $format, $expectedFormat)
provideGetContentFormat Revision::getContentFormat
makeRevisionWithProps( $props=null)
testGetContentClone()
Tests whether $rev->getContent() returns a clone when needed.
testLoadFromTimestamp()
Revision::loadFromTimestamp()
testNewFromRow()
Revision::newFromRow.
testIsUnpatrolled_returnsRecentChangesId()
Revision::isUnpatrolled.
testNewNullRevision_badPage()
Revision::newNullRevision.
testIsDeleted_nothingDeleted()
Revision::isDeleted.
testNewFromTitle_withId()
Revision::newFromTitle.
testIsMinor_false()
Revision::isMinor.
testLoadFromPageIdWithLatestRevId()
Revision::loadFromPageId.
testNewFromId()
Revision::newFromId.
testNewFromTitle_withoutId()
Revision::newFromTitle.
testUserCanBitfield( $bitField, $field, $userGroups, $title, $expected)
provideUserCanBitfield Revision::userCanBitfield
testNewFromPageIdWithLatestId()
Revision::newFromPageId.
testGetContentUncloned()
Tests whether $rev->getContent() returns the same object repeatedly if appropriate.
testIsCurrent()
Revision::isCurrent.
testGetPrevious()
Revision::getPrevious.
testGetParentLengths_oneRevId()
Revision::getParentLengths.
testSimpleContentGetters()
This is a simple blanket test for all simple content getters and is methods to provide some coverage ...
testNewFromPageIdWithNotLatestId()
Revision::newFromPageId.
testIsMinor_true()
Revision::isMinor.
testIsUnpatrolled_returnsZeroIfPatrolled()
Revision::isUnpatrolled.
testGetNext()
Revision::getNext.
__construct( $name=null, array $data=[], $dataName='')
testUserWasLastToEdit( $sinceIdx, $expectedLast)
Revision::userWasLastToEdit provideUserWasLastToEdit.
newTestRevision( $text, $title="Test", $model=CONTENT_MODEL_WIKITEXT, $format=null)
testGetPage()
Revision::getPage.
getId()
Get revision ID.
Definition Revision.php:617
getContentFormat()
Returns the content format for the main slot of this revision.
Definition Revision.php:984
getPage()
Get the page ID.
Definition Revision.php:761
getContentModel()
Returns the content model for the main slot of this revision.
Definition Revision.php:969
getUser( $audience=self::FOR_PUBLIC, User $user=null)
Fetch revision's user id if it's available to the specified audience.
Definition Revision.php:778
getSha1()
Returns the base36 sha1 of the content in this revision, or null if unknown.
Definition Revision.php:718
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition User.php:591
static createNew( $name, $params=[])
Add a user to the database, return the user object.
Definition User.php:4297
Multi-datacenter aware caching interface.
Class representing a MediaWiki article and history.
Definition WikiPage.php:37
Content object for wiki text pages.
$res
Definition database.txt:21
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
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction $rows
Definition hooks.txt:2783
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:2006
static configuration should be added through ResourceLoaderGetConfigVars instead can be used to get the real title after the basic globals have been set but before ordinary actions take place or wrap services the preferred way to define a new service is the $wgServiceWiringFiles array $services
Definition hooks.txt:2273
presenting them properly to the user as errors is done by the caller return true use this to change the list i e etc $rev
Definition hooks.txt:1777
processing should stop and the error should be shown to the user * false
Definition hooks.txt:187
const CONTENT_MODEL_CSS
Definition Defines.php:247
const CONTENT_FORMAT_CSS
Definition Defines.php:264
const CONTENT_MODEL_WIKITEXT
Definition Defines.php:245
const CONTENT_FORMAT_WIKITEXT
Definition Defines.php:260
const EDIT_MINOR
Definition Defines.php:164
const EDIT_NEW
Definition Defines.php:162
$cache
Definition mcc.php:33
const DB_REPLICA
Definition defines.php:25
const DB_MASTER
Definition defines.php:29