MediaWiki
master
|
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 ) $props = array(); 00076 00077 if ( !isset( $props['content'] ) && !isset( $props['text'] ) ) $props['text'] = 'Lorem Ipsum'; 00078 if ( !isset( $props['comment'] ) ) $props['comment'] = 'just a test'; 00079 if ( !isset( $props['page'] ) ) $props['page'] = $this->the_page->getId(); 00080 00081 $rev = new Revision( $props ); 00082 00083 $dbw = wfgetDB( DB_MASTER ); 00084 $rev->insertOn( $dbw ); 00085 00086 return $rev; 00087 } 00088 00089 protected function createPage( $page, $text, $model = null ) { 00090 if ( is_string( $page ) ) { 00091 if ( !preg_match( '/:/', $page ) && 00092 ( $model === null || $model === CONTENT_MODEL_WIKITEXT ) ) { 00093 00094 $ns = $this->getDefaultWikitextNS(); 00095 $page = MWNamespace::getCanonicalName( $ns ) . ':' . $page; 00096 } 00097 00098 $page = Title::newFromText( $page ); 00099 } 00100 00101 if ( $page instanceof Title ) { 00102 $page = new WikiPage( $page ); 00103 } 00104 00105 if ( $page->exists() ) { 00106 $page->doDeleteArticle( "done" ); 00107 } 00108 00109 $content = ContentHandler::makeContent( $text, $page->getTitle(), $model ); 00110 $page->doEditContent( $content, "testing", EDIT_NEW ); 00111 00112 return $page; 00113 } 00114 00115 protected function assertRevEquals( Revision $orig, Revision $rev = null ) { 00116 $this->assertNotNull( $rev, 'missing revision' ); 00117 00118 $this->assertEquals( $orig->getId(), $rev->getId() ); 00119 $this->assertEquals( $orig->getPage(), $rev->getPage() ); 00120 $this->assertEquals( $orig->getTimestamp(), $rev->getTimestamp() ); 00121 $this->assertEquals( $orig->getUser(), $rev->getUser() ); 00122 $this->assertEquals( $orig->getContentModel(), $rev->getContentModel() ); 00123 $this->assertEquals( $orig->getContentFormat(), $rev->getContentFormat() ); 00124 $this->assertEquals( $orig->getSha1(), $rev->getSha1() ); 00125 } 00126 00130 public function testConstructFromRow() 00131 { 00132 $orig = $this->makeRevision(); 00133 00134 $dbr = wfgetDB( DB_SLAVE ); 00135 $res = $dbr->select( 'revision', '*', array( 'rev_id' => $orig->getId() ) ); 00136 $this->assertTrue( is_object( $res ), 'query failed' ); 00137 00138 $row = $res->fetchObject(); 00139 $res->free(); 00140 00141 $rev = new Revision( $row ); 00142 00143 $this->assertRevEquals( $orig, $rev ); 00144 } 00145 00149 public function testNewFromRow() 00150 { 00151 $orig = $this->makeRevision(); 00152 00153 $dbr = wfgetDB( DB_SLAVE ); 00154 $res = $dbr->select( 'revision', '*', array( 'rev_id' => $orig->getId() ) ); 00155 $this->assertTrue( is_object( $res ), 'query failed' ); 00156 00157 $row = $res->fetchObject(); 00158 $res->free(); 00159 00160 $rev = Revision::newFromRow( $row ); 00161 00162 $this->assertRevEquals( $orig, $rev ); 00163 } 00164 00165 00169 public function testNewFromArchiveRow() 00170 { 00171 $page = $this->createPage( 'RevisionStorageTest_testNewFromArchiveRow', 'Lorem Ipsum', CONTENT_MODEL_WIKITEXT ); 00172 $orig = $page->getRevision(); 00173 $page->doDeleteArticle( 'test Revision::newFromArchiveRow' ); 00174 00175 $dbr = wfgetDB( DB_SLAVE ); 00176 $res = $dbr->select( 'archive', '*', array( 'ar_rev_id' => $orig->getId() ) ); 00177 $this->assertTrue( is_object( $res ), 'query failed' ); 00178 00179 $row = $res->fetchObject(); 00180 $res->free(); 00181 00182 $rev = Revision::newFromArchiveRow( $row ); 00183 00184 $this->assertRevEquals( $orig, $rev ); 00185 } 00186 00190 public function testNewFromId() 00191 { 00192 $orig = $this->makeRevision(); 00193 00194 $rev = Revision::newFromId( $orig->getId() ); 00195 00196 $this->assertRevEquals( $orig, $rev ); 00197 } 00198 00202 public function testFetchRevision() 00203 { 00204 $page = $this->createPage( 'RevisionStorageTest_testFetchRevision', 'one', CONTENT_MODEL_WIKITEXT ); 00205 $id1 = $page->getRevision()->getId(); 00206 00207 $page->doEditContent( new WikitextContent( 'two' ), 'second rev' ); 00208 $id2 = $page->getRevision()->getId(); 00209 00210 $res = Revision::fetchRevision( $page->getTitle() ); 00211 00212 #note: order is unspecified 00213 $rows = array(); 00214 while ( ( $row = $res->fetchObject() ) ) { 00215 $rows[ $row->rev_id ]= $row; 00216 } 00217 00218 $row = $res->fetchObject(); 00219 $this->assertEquals( 1, count($rows), 'expected exactly one revision' ); 00220 $this->assertArrayHasKey( $id2, $rows, 'missing revision with id ' . $id2 ); 00221 } 00222 00226 public function testSelectFields() 00227 { 00228 global $wgContentHandlerUseDB; 00229 00230 $fields = Revision::selectFields(); 00231 00232 $this->assertTrue( in_array( 'rev_id', $fields ), 'missing rev_id in list of fields'); 00233 $this->assertTrue( in_array( 'rev_page', $fields ), 'missing rev_page in list of fields'); 00234 $this->assertTrue( in_array( 'rev_timestamp', $fields ), 'missing rev_timestamp in list of fields'); 00235 $this->assertTrue( in_array( 'rev_user', $fields ), 'missing rev_user in list of fields'); 00236 00237 if ( $wgContentHandlerUseDB ) { 00238 $this->assertTrue( in_array( 'rev_content_model', $fields ), 00239 'missing rev_content_model in list of fields'); 00240 $this->assertTrue( in_array( 'rev_content_format', $fields ), 00241 'missing rev_content_format in list of fields'); 00242 } 00243 } 00244 00248 public function testGetPage() 00249 { 00250 $page = $this->the_page; 00251 00252 $orig = $this->makeRevision( array( 'page' => $page->getId() ) ); 00253 $rev = Revision::newFromId( $orig->getId() ); 00254 00255 $this->assertEquals( $page->getId(), $rev->getPage() ); 00256 } 00257 00261 public function testGetText() 00262 { 00263 $this->hideDeprecated( 'Revision::getText' ); 00264 00265 $orig = $this->makeRevision( array( 'text' => 'hello hello.' ) ); 00266 $rev = Revision::newFromId( $orig->getId() ); 00267 00268 $this->assertEquals( 'hello hello.', $rev->getText() ); 00269 } 00270 00274 public function testGetContent() 00275 { 00276 $orig = $this->makeRevision( array( 'text' => 'hello hello.' ) ); 00277 $rev = Revision::newFromId( $orig->getId() ); 00278 00279 $this->assertEquals( 'hello hello.', $rev->getContent()->getNativeData() ); 00280 } 00281 00285 public function testRevText() 00286 { 00287 $this->hideDeprecated( 'Revision::revText' ); 00288 $orig = $this->makeRevision( array( 'text' => 'hello hello rev.' ) ); 00289 $rev = Revision::newFromId( $orig->getId() ); 00290 00291 $this->assertEquals( 'hello hello rev.', $rev->revText() ); 00292 } 00293 00297 public function testGetRawText() 00298 { 00299 $this->hideDeprecated( 'Revision::getRawText' ); 00300 00301 $orig = $this->makeRevision( array( 'text' => 'hello hello raw.' ) ); 00302 $rev = Revision::newFromId( $orig->getId() ); 00303 00304 $this->assertEquals( 'hello hello raw.', $rev->getRawText() ); 00305 } 00306 00310 public function testGetContentModel() 00311 { 00312 global $wgContentHandlerUseDB; 00313 00314 if ( !$wgContentHandlerUseDB ) { 00315 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' ); 00316 } 00317 00318 $orig = $this->makeRevision( array( 'text' => 'hello hello.', 00319 'content_model' => CONTENT_MODEL_JAVASCRIPT ) ); 00320 $rev = Revision::newFromId( $orig->getId() ); 00321 00322 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContentModel() ); 00323 } 00324 00328 public function testGetContentFormat() 00329 { 00330 global $wgContentHandlerUseDB; 00331 00332 if ( !$wgContentHandlerUseDB ) { 00333 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' ); 00334 } 00335 00336 $orig = $this->makeRevision( array( 'text' => 'hello hello.', 00337 'content_model' => CONTENT_MODEL_JAVASCRIPT, 00338 'content_format' => CONTENT_FORMAT_JAVASCRIPT ) ); 00339 $rev = Revision::newFromId( $orig->getId() ); 00340 00341 $this->assertEquals( CONTENT_FORMAT_JAVASCRIPT, $rev->getContentFormat() ); 00342 } 00343 00347 public function testIsCurrent() 00348 { 00349 $page = $this->createPage( 'RevisionStorageTest_testIsCurrent', 'Lorem Ipsum', CONTENT_MODEL_WIKITEXT ); 00350 $rev1 = $page->getRevision(); 00351 00352 # @todo: find out if this should be true 00353 # $this->assertTrue( $rev1->isCurrent() ); 00354 00355 $rev1x = Revision::newFromId( $rev1->getId() ); 00356 $this->assertTrue( $rev1x->isCurrent() ); 00357 00358 $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ), 'second rev' ); 00359 $rev2 = $page->getRevision(); 00360 00361 # @todo: find out if this should be true 00362 # $this->assertTrue( $rev2->isCurrent() ); 00363 00364 $rev1x = Revision::newFromId( $rev1->getId() ); 00365 $this->assertFalse( $rev1x->isCurrent() ); 00366 00367 $rev2x = Revision::newFromId( $rev2->getId() ); 00368 $this->assertTrue( $rev2x->isCurrent() ); 00369 } 00370 00374 public function testGetPrevious() 00375 { 00376 $page = $this->createPage( 'RevisionStorageTest_testGetPrevious', 'Lorem Ipsum testGetPrevious', CONTENT_MODEL_WIKITEXT ); 00377 $rev1 = $page->getRevision(); 00378 00379 $this->assertNull( $rev1->getPrevious() ); 00380 00381 $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ), 00382 'second rev testGetPrevious' ); 00383 $rev2 = $page->getRevision(); 00384 00385 $this->assertNotNull( $rev2->getPrevious() ); 00386 $this->assertEquals( $rev1->getId(), $rev2->getPrevious()->getId() ); 00387 } 00388 00392 public function testGetNext() 00393 { 00394 $page = $this->createPage( 'RevisionStorageTest_testGetNext', 'Lorem Ipsum testGetNext', CONTENT_MODEL_WIKITEXT ); 00395 $rev1 = $page->getRevision(); 00396 00397 $this->assertNull( $rev1->getNext() ); 00398 00399 $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ), 00400 'second rev testGetNext' ); 00401 $rev2 = $page->getRevision(); 00402 00403 $this->assertNotNull( $rev1->getNext() ); 00404 $this->assertEquals( $rev2->getId(), $rev1->getNext()->getId() ); 00405 } 00406 00410 public function testNewNullRevision() 00411 { 00412 $page = $this->createPage( 'RevisionStorageTest_testNewNullRevision', 'some testing text', CONTENT_MODEL_WIKITEXT ); 00413 $orig = $page->getRevision(); 00414 00415 $dbw = wfGetDB( DB_MASTER ); 00416 $rev = Revision::newNullRevision( $dbw, $page->getId(), 'a null revision', false ); 00417 00418 $this->assertNotEquals( $orig->getId(), $rev->getId(), 00419 'new null revision shold have a different id from the original revision' ); 00420 $this->assertEquals( $orig->getTextId(), $rev->getTextId(), 00421 'new null revision shold have the same text id as the original revision' ); 00422 $this->assertEquals( 'some testing text', $rev->getContent()->getNativeData() ); 00423 } 00424 00425 public static function provideUserWasLastToEdit() { 00426 return array( 00427 array( #0 00428 3, true, # actually the last edit 00429 ), 00430 array( #1 00431 2, true, # not the current edit, but still by this user 00432 ), 00433 array( #2 00434 1, false, # edit by another user 00435 ), 00436 array( #3 00437 0, false, # first edit, by this user, but another user edited in the mean time 00438 ), 00439 ); 00440 } 00441 00445 public function testUserWasLastToEdit( $sinceIdx, $expectedLast ) { 00446 $userA = \User::newFromName( "RevisionStorageTest_userA" ); 00447 $userB = \User::newFromName( "RevisionStorageTest_userB" ); 00448 00449 if ( $userA->getId() === 0 ) { 00450 $userA = \User::createNew( $userA->getName() ); 00451 } 00452 00453 if ( $userB->getId() === 0 ) { 00454 $userB = \User::createNew( $userB->getName() ); 00455 } 00456 00457 $ns = $this->getDefaultWikitextNS(); 00458 00459 $dbw = wfGetDB( DB_MASTER ); 00460 $revisions = array(); 00461 00462 // create revisions ----------------------------- 00463 $page = WikiPage::factory( Title::newFromText( 00464 'RevisionStorageTest_testUserWasLastToEdit', $ns ) ); 00465 00466 # zero 00467 $revisions[0] = new Revision( array( 00468 'page' => $page->getId(), 00469 'title' => $page->getTitle(), // we need the title to determine the page's default content model 00470 'timestamp' => '20120101000000', 00471 'user' => $userA->getId(), 00472 'text' => 'zero', 00473 'content_model' => CONTENT_MODEL_WIKITEXT, 00474 'summary' => 'edit zero' 00475 ) ); 00476 $revisions[0]->insertOn( $dbw ); 00477 00478 # one 00479 $revisions[1] = new Revision( array( 00480 'page' => $page->getId(), 00481 'title' => $page->getTitle(), // still need the title, because $page->getId() is 0 (there's no entry in the page table) 00482 'timestamp' => '20120101000100', 00483 'user' => $userA->getId(), 00484 'text' => 'one', 00485 'content_model' => CONTENT_MODEL_WIKITEXT, 00486 'summary' => 'edit one' 00487 ) ); 00488 $revisions[1]->insertOn( $dbw ); 00489 00490 # two 00491 $revisions[2] = new Revision( array( 00492 'page' => $page->getId(), 00493 'title' => $page->getTitle(), 00494 'timestamp' => '20120101000200', 00495 'user' => $userB->getId(), 00496 'text' => 'two', 00497 'content_model' => CONTENT_MODEL_WIKITEXT, 00498 'summary' => 'edit two' 00499 ) ); 00500 $revisions[2]->insertOn( $dbw ); 00501 00502 # three 00503 $revisions[3] = new Revision( array( 00504 'page' => $page->getId(), 00505 'title' => $page->getTitle(), 00506 'timestamp' => '20120101000300', 00507 'user' => $userA->getId(), 00508 'text' => 'three', 00509 'content_model' => CONTENT_MODEL_WIKITEXT, 00510 'summary' => 'edit three' 00511 ) ); 00512 $revisions[3]->insertOn( $dbw ); 00513 00514 # four 00515 $revisions[4] = new Revision( array( 00516 'page' => $page->getId(), 00517 'title' => $page->getTitle(), 00518 'timestamp' => '20120101000200', 00519 'user' => $userA->getId(), 00520 'text' => 'zero', 00521 'content_model' => CONTENT_MODEL_WIKITEXT, 00522 'summary' => 'edit four' 00523 ) ); 00524 $revisions[4]->insertOn( $dbw ); 00525 00526 // test it --------------------------------- 00527 $since = $revisions[ $sinceIdx ]->getTimestamp(); 00528 00529 $wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since ); 00530 00531 $this->assertEquals( $expectedLast, $wasLast ); 00532 } 00533 }