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