MediaWiki  REL1_21
RevisionStorageTest.php
Go to the documentation of this file.
00001 <?php
00002 
00013 class RevisionStorageTest extends MediaWikiTestCase {
00014 
00018         var $the_page;
00019 
00020         function  __construct( $name = null, array $data = array(), $dataName = '' ) {
00021                 parent::__construct( $name, $data, $dataName );
00022 
00023                 $this->tablesUsed = array_merge( $this->tablesUsed,
00024                         array( 'page',
00025                                 'revision',
00026                                 'text',
00027 
00028                                 'recentchanges',
00029                                 'logging',
00030 
00031                                 'page_props',
00032                                 'pagelinks',
00033                                 'categorylinks',
00034                                 'langlinks',
00035                                 'externallinks',
00036                                 'imagelinks',
00037                                 'templatelinks',
00038                                 'iwlinks' ) );
00039         }
00040 
00041         public function setUp() {
00042                 global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
00043 
00044                 parent::setUp();
00045 
00046                 $wgExtraNamespaces[12312] = 'Dummy';
00047                 $wgExtraNamespaces[12313] = 'Dummy_talk';
00048 
00049                 $wgNamespaceContentModels[12312] = 'DUMMY';
00050                 $wgContentHandlers['DUMMY'] = 'DummyContentHandlerForTesting';
00051 
00052                 MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
00053                 $wgContLang->resetNamespaces(); # reset namespace cache
00054                 if ( !$this->the_page ) {
00055                         $this->the_page = $this->createPage( 'RevisionStorageTest_the_page', "just a dummy page", CONTENT_MODEL_WIKITEXT );
00056                 }
00057         }
00058 
00059         public function tearDown() {
00060                 global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
00061 
00062                 parent::tearDown();
00063 
00064                 unset( $wgExtraNamespaces[12312] );
00065                 unset( $wgExtraNamespaces[12313] );
00066 
00067                 unset( $wgNamespaceContentModels[12312] );
00068                 unset( $wgContentHandlers['DUMMY'] );
00069 
00070                 MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
00071                 $wgContLang->resetNamespaces(); # reset namespace cache
00072         }
00073 
00074         protected function makeRevision( $props = null ) {
00075                 if ( $props === null ) {
00076                         $props = array();
00077                 }
00078 
00079                 if ( !isset( $props['content'] ) && !isset( $props['text'] ) ) {
00080                         $props['text'] = 'Lorem Ipsum';
00081                 }
00082 
00083                 if ( !isset( $props['comment'] ) ) {
00084                         $props['comment'] = 'just a test';
00085                 }
00086 
00087                 if ( !isset( $props['page'] ) ) {
00088                         $props['page'] = $this->the_page->getId();
00089                 }
00090 
00091                 $rev = new Revision( $props );
00092 
00093                 $dbw = wfgetDB( DB_MASTER );
00094                 $rev->insertOn( $dbw );
00095 
00096                 return $rev;
00097         }
00098 
00099         protected function createPage( $page, $text, $model = null ) {
00100                 if ( is_string( $page ) ) {
00101                         if ( !preg_match( '/:/', $page ) &&
00102                                 ( $model === null || $model === CONTENT_MODEL_WIKITEXT )
00103                         ) {
00104                                 $ns = $this->getDefaultWikitextNS();
00105                                 $page = MWNamespace::getCanonicalName( $ns ) . ':' . $page;
00106                         }
00107 
00108                         $page = Title::newFromText( $page );
00109                 }
00110 
00111                 if ( $page instanceof Title ) {
00112                         $page = new WikiPage( $page );
00113                 }
00114 
00115                 if ( $page->exists() ) {
00116                         $page->doDeleteArticle( "done" );
00117                 }
00118 
00119                 $content = ContentHandler::makeContent( $text, $page->getTitle(), $model );
00120                 $page->doEditContent( $content, "testing", EDIT_NEW );
00121 
00122                 return $page;
00123         }
00124 
00125         protected function assertRevEquals( Revision $orig, Revision $rev = null ) {
00126                 $this->assertNotNull( $rev, 'missing revision' );
00127 
00128                 $this->assertEquals( $orig->getId(), $rev->getId() );
00129                 $this->assertEquals( $orig->getPage(), $rev->getPage() );
00130                 $this->assertEquals( $orig->getTimestamp(), $rev->getTimestamp() );
00131                 $this->assertEquals( $orig->getUser(), $rev->getUser() );
00132                 $this->assertEquals( $orig->getContentModel(), $rev->getContentModel() );
00133                 $this->assertEquals( $orig->getContentFormat(), $rev->getContentFormat() );
00134                 $this->assertEquals( $orig->getSha1(), $rev->getSha1() );
00135         }
00136 
00140         public function testConstructFromRow() {
00141                 $orig = $this->makeRevision();
00142 
00143                 $dbr = wfgetDB( DB_SLAVE );
00144                 $res = $dbr->select( 'revision', '*', array( 'rev_id' => $orig->getId() ) );
00145                 $this->assertTrue( is_object( $res ), 'query failed' );
00146 
00147                 $row = $res->fetchObject();
00148                 $res->free();
00149 
00150                 $rev = new Revision( $row );
00151 
00152                 $this->assertRevEquals( $orig, $rev );
00153         }
00154 
00158         public function testNewFromRow() {
00159                 $orig = $this->makeRevision();
00160 
00161                 $dbr = wfgetDB( DB_SLAVE );
00162                 $res = $dbr->select( 'revision', '*', array( 'rev_id' => $orig->getId() ) );
00163                 $this->assertTrue( is_object( $res ), 'query failed' );
00164 
00165                 $row = $res->fetchObject();
00166                 $res->free();
00167 
00168                 $rev = Revision::newFromRow( $row );
00169 
00170                 $this->assertRevEquals( $orig, $rev );
00171         }
00172 
00173 
00177         public function testNewFromArchiveRow() {
00178                 $page = $this->createPage( 'RevisionStorageTest_testNewFromArchiveRow', 'Lorem Ipsum', CONTENT_MODEL_WIKITEXT );
00179                 $orig = $page->getRevision();
00180                 $page->doDeleteArticle( 'test Revision::newFromArchiveRow' );
00181 
00182                 $dbr = wfgetDB( DB_SLAVE );
00183                 $res = $dbr->select( 'archive', '*', array( 'ar_rev_id' => $orig->getId() ) );
00184                 $this->assertTrue( is_object( $res ), 'query failed' );
00185 
00186                 $row = $res->fetchObject();
00187                 $res->free();
00188 
00189                 $rev = Revision::newFromArchiveRow( $row );
00190 
00191                 $this->assertRevEquals( $orig, $rev );
00192         }
00193 
00197         public function testNewFromId() {
00198                 $orig = $this->makeRevision();
00199 
00200                 $rev = Revision::newFromId( $orig->getId() );
00201 
00202                 $this->assertRevEquals( $orig, $rev );
00203         }
00204 
00208         public function testFetchRevision() {
00209                 $page = $this->createPage( 'RevisionStorageTest_testFetchRevision', 'one', CONTENT_MODEL_WIKITEXT );
00210                 $id1 = $page->getRevision()->getId();
00211 
00212                 $page->doEditContent( new WikitextContent( 'two' ), 'second rev' );
00213                 $id2 = $page->getRevision()->getId();
00214 
00215                 $res = Revision::fetchRevision( $page->getTitle() );
00216 
00217                 #note: order is unspecified
00218                 $rows = array();
00219                 while ( ( $row = $res->fetchObject() ) ) {
00220                         $rows[$row->rev_id] = $row;
00221                 }
00222 
00223                 $row = $res->fetchObject();
00224                 $this->assertEquals( 1, count( $rows ), 'expected exactly one revision' );
00225                 $this->assertArrayHasKey( $id2, $rows, 'missing revision with id ' . $id2 );
00226         }
00227 
00231         public function testSelectFields() {
00232                 global $wgContentHandlerUseDB;
00233 
00234                 $fields = Revision::selectFields();
00235 
00236                 $this->assertTrue( in_array( 'rev_id', $fields ), 'missing rev_id in list of fields' );
00237                 $this->assertTrue( in_array( 'rev_page', $fields ), 'missing rev_page in list of fields' );
00238                 $this->assertTrue( in_array( 'rev_timestamp', $fields ), 'missing rev_timestamp in list of fields' );
00239                 $this->assertTrue( in_array( 'rev_user', $fields ), 'missing rev_user in list of fields' );
00240 
00241                 if ( $wgContentHandlerUseDB ) {
00242                         $this->assertTrue( in_array( 'rev_content_model', $fields ),
00243                                 'missing rev_content_model in list of fields' );
00244                         $this->assertTrue( in_array( 'rev_content_format', $fields ),
00245                                 'missing rev_content_format in list of fields' );
00246                 }
00247         }
00248 
00252         public function testGetPage() {
00253                 $page = $this->the_page;
00254 
00255                 $orig = $this->makeRevision( array( 'page' => $page->getId() ) );
00256                 $rev = Revision::newFromId( $orig->getId() );
00257 
00258                 $this->assertEquals( $page->getId(), $rev->getPage() );
00259         }
00260 
00264         public function testGetText() {
00265                 $this->hideDeprecated( 'Revision::getText' );
00266 
00267                 $orig = $this->makeRevision( array( 'text' => 'hello hello.' ) );
00268                 $rev = Revision::newFromId( $orig->getId() );
00269 
00270                 $this->assertEquals( 'hello hello.', $rev->getText() );
00271         }
00272 
00276         public function testGetContent_failure() {
00277                 $rev = new Revision( array(
00278                         'page' => $this->the_page->getId(),
00279                         'content_model' => $this->the_page->getContentModel(),
00280                         'text_id' => 123456789, // not in the test DB
00281                 ) );
00282 
00283                 $this->assertNull( $rev->getContent(),
00284                         "getContent() should return null if the revision's text blob could not be loaded." );
00285 
00286                 //NOTE: check this twice, once for lazy initialization, and once with the cached value.
00287                 $this->assertNull( $rev->getContent(),
00288                         "getContent() should return null if the revision's text blob could not be loaded." );
00289         }
00290 
00294         public function testGetContent() {
00295                 $orig = $this->makeRevision( array( 'text' => 'hello hello.' ) );
00296                 $rev = Revision::newFromId( $orig->getId() );
00297 
00298                 $this->assertEquals( 'hello hello.', $rev->getContent()->getNativeData() );
00299         }
00300 
00304         public function testRevText() {
00305                 $this->hideDeprecated( 'Revision::revText' );
00306                 $orig = $this->makeRevision( array( 'text' => 'hello hello rev.' ) );
00307                 $rev = Revision::newFromId( $orig->getId() );
00308 
00309                 $this->assertEquals( 'hello hello rev.', $rev->revText() );
00310         }
00311 
00315         public function testGetRawText() {
00316                 $this->hideDeprecated( 'Revision::getRawText' );
00317 
00318                 $orig = $this->makeRevision( array( 'text' => 'hello hello raw.' ) );
00319                 $rev = Revision::newFromId( $orig->getId() );
00320 
00321                 $this->assertEquals( 'hello hello raw.', $rev->getRawText() );
00322         }
00323 
00327         public function testGetContentModel() {
00328                 global $wgContentHandlerUseDB;
00329 
00330                 if ( !$wgContentHandlerUseDB ) {
00331                         $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
00332                 }
00333 
00334                 $orig = $this->makeRevision( array( 'text' => 'hello hello.',
00335                         'content_model' => CONTENT_MODEL_JAVASCRIPT ) );
00336                 $rev = Revision::newFromId( $orig->getId() );
00337 
00338                 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContentModel() );
00339         }
00340 
00344         public function testGetContentFormat() {
00345                 global $wgContentHandlerUseDB;
00346 
00347                 if ( !$wgContentHandlerUseDB ) {
00348                         $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
00349                 }
00350 
00351                 $orig = $this->makeRevision( array(
00352                         'text' => 'hello hello.',
00353                         'content_model' => CONTENT_MODEL_JAVASCRIPT,
00354                         'content_format' => CONTENT_FORMAT_JAVASCRIPT
00355                 ) );
00356                 $rev = Revision::newFromId( $orig->getId() );
00357 
00358                 $this->assertEquals( CONTENT_FORMAT_JAVASCRIPT, $rev->getContentFormat() );
00359         }
00360 
00364         public function testIsCurrent() {
00365                 $page = $this->createPage( 'RevisionStorageTest_testIsCurrent', 'Lorem Ipsum', CONTENT_MODEL_WIKITEXT );
00366                 $rev1 = $page->getRevision();
00367 
00368                 # @todo: find out if this should be true
00369                 # $this->assertTrue( $rev1->isCurrent() );
00370 
00371                 $rev1x = Revision::newFromId( $rev1->getId() );
00372                 $this->assertTrue( $rev1x->isCurrent() );
00373 
00374                 $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ), 'second rev' );
00375                 $rev2 = $page->getRevision();
00376 
00377                 # @todo: find out if this should be true
00378                 # $this->assertTrue( $rev2->isCurrent() );
00379 
00380                 $rev1x = Revision::newFromId( $rev1->getId() );
00381                 $this->assertFalse( $rev1x->isCurrent() );
00382 
00383                 $rev2x = Revision::newFromId( $rev2->getId() );
00384                 $this->assertTrue( $rev2x->isCurrent() );
00385         }
00386 
00390         public function testGetPrevious() {
00391                 $page = $this->createPage( 'RevisionStorageTest_testGetPrevious', 'Lorem Ipsum testGetPrevious', CONTENT_MODEL_WIKITEXT );
00392                 $rev1 = $page->getRevision();
00393 
00394                 $this->assertNull( $rev1->getPrevious() );
00395 
00396                 $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
00397                         'second rev testGetPrevious' );
00398                 $rev2 = $page->getRevision();
00399 
00400                 $this->assertNotNull( $rev2->getPrevious() );
00401                 $this->assertEquals( $rev1->getId(), $rev2->getPrevious()->getId() );
00402         }
00403 
00407         public function testGetNext() {
00408                 $page = $this->createPage( 'RevisionStorageTest_testGetNext', 'Lorem Ipsum testGetNext', CONTENT_MODEL_WIKITEXT );
00409                 $rev1 = $page->getRevision();
00410 
00411                 $this->assertNull( $rev1->getNext() );
00412 
00413                 $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
00414                         'second rev testGetNext' );
00415                 $rev2 = $page->getRevision();
00416 
00417                 $this->assertNotNull( $rev1->getNext() );
00418                 $this->assertEquals( $rev2->getId(), $rev1->getNext()->getId() );
00419         }
00420 
00424         public function testNewNullRevision() {
00425                 $page = $this->createPage( 'RevisionStorageTest_testNewNullRevision', 'some testing text', CONTENT_MODEL_WIKITEXT );
00426                 $orig = $page->getRevision();
00427 
00428                 $dbw = wfGetDB( DB_MASTER );
00429                 $rev = Revision::newNullRevision( $dbw, $page->getId(), 'a null revision', false );
00430 
00431                 $this->assertNotEquals( $orig->getId(), $rev->getId(),
00432                         'new null revision shold have a different id from the original revision' );
00433                 $this->assertEquals( $orig->getTextId(), $rev->getTextId(),
00434                         'new null revision shold have the same text id as the original revision' );
00435                 $this->assertEquals( 'some testing text', $rev->getContent()->getNativeData() );
00436         }
00437 
00438         public static function provideUserWasLastToEdit() {
00439                 return array(
00440                         array( #0
00441                                 3, true, # actually the last edit
00442                         ),
00443                         array( #1
00444                                 2, true, # not the current edit, but still by this user
00445                         ),
00446                         array( #2
00447                                 1, false, # edit by another user
00448                         ),
00449                         array( #3
00450                                 0, false, # first edit, by this user, but another user edited in the mean time
00451                         ),
00452                 );
00453         }
00454 
00458         public function testUserWasLastToEdit( $sinceIdx, $expectedLast ) {
00459                 $userA = \User::newFromName( "RevisionStorageTest_userA" );
00460                 $userB = \User::newFromName( "RevisionStorageTest_userB" );
00461 
00462                 if ( $userA->getId() === 0 ) {
00463                         $userA = \User::createNew( $userA->getName() );
00464                 }
00465 
00466                 if ( $userB->getId() === 0 ) {
00467                         $userB = \User::createNew( $userB->getName() );
00468                 }
00469 
00470                 $ns = $this->getDefaultWikitextNS();
00471 
00472                 $dbw = wfGetDB( DB_MASTER );
00473                 $revisions = array();
00474 
00475                 // create revisions -----------------------------
00476                 $page = WikiPage::factory( Title::newFromText(
00477                         'RevisionStorageTest_testUserWasLastToEdit', $ns ) );
00478 
00479                 # zero
00480                 $revisions[0] = new Revision( array(
00481                         'page' => $page->getId(),
00482                         'title' => $page->getTitle(), // we need the title to determine the page's default content model
00483                         'timestamp' => '20120101000000',
00484                         'user' => $userA->getId(),
00485                         'text' => 'zero',
00486                         'content_model' => CONTENT_MODEL_WIKITEXT,
00487                         'summary' => 'edit zero'
00488                 ) );
00489                 $revisions[0]->insertOn( $dbw );
00490 
00491                 # one
00492                 $revisions[1] = new Revision( array(
00493                         'page' => $page->getId(),
00494                         'title' => $page->getTitle(), // still need the title, because $page->getId() is 0 (there's no entry in the page table)
00495                         'timestamp' => '20120101000100',
00496                         'user' => $userA->getId(),
00497                         'text' => 'one',
00498                         'content_model' => CONTENT_MODEL_WIKITEXT,
00499                         'summary' => 'edit one'
00500                 ) );
00501                 $revisions[1]->insertOn( $dbw );
00502 
00503                 # two
00504                 $revisions[2] = new Revision( array(
00505                         'page' => $page->getId(),
00506                         'title' => $page->getTitle(),
00507                         'timestamp' => '20120101000200',
00508                         'user' => $userB->getId(),
00509                         'text' => 'two',
00510                         'content_model' => CONTENT_MODEL_WIKITEXT,
00511                         'summary' => 'edit two'
00512                 ) );
00513                 $revisions[2]->insertOn( $dbw );
00514 
00515                 # three
00516                 $revisions[3] = new Revision( array(
00517                         'page' => $page->getId(),
00518                         'title' => $page->getTitle(),
00519                         'timestamp' => '20120101000300',
00520                         'user' => $userA->getId(),
00521                         'text' => 'three',
00522                         'content_model' => CONTENT_MODEL_WIKITEXT,
00523                         'summary' => 'edit three'
00524                 ) );
00525                 $revisions[3]->insertOn( $dbw );
00526 
00527                 # four
00528                 $revisions[4] = new Revision( array(
00529                         'page' => $page->getId(),
00530                         'title' => $page->getTitle(),
00531                         'timestamp' => '20120101000200',
00532                         'user' => $userA->getId(),
00533                         'text' => 'zero',
00534                         'content_model' => CONTENT_MODEL_WIKITEXT,
00535                         'summary' => 'edit four'
00536                 ) );
00537                 $revisions[4]->insertOn( $dbw );
00538 
00539                 // test it ---------------------------------
00540                 $since = $revisions[$sinceIdx]->getTimestamp();
00541 
00542                 $wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since );
00543 
00544                 $this->assertEquals( $expectedLast, $wasLast );
00545         }
00546 }