MediaWiki  REL1_24
ApiEditPageTest.php
Go to the documentation of this file.
00001 <?php
00002 
00014 class ApiEditPageTest extends ApiTestCase {
00015 
00016     protected function setUp() {
00017         global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
00018 
00019         parent::setUp();
00020 
00021         $this->setMwGlobals( array(
00022             'wgExtraNamespaces' => $wgExtraNamespaces,
00023             'wgNamespaceContentModels' => $wgNamespaceContentModels,
00024             'wgContentHandlers' => $wgContentHandlers,
00025             'wgContLang' => $wgContLang,
00026         ) );
00027 
00028         $wgExtraNamespaces[12312] = 'Dummy';
00029         $wgExtraNamespaces[12313] = 'Dummy_talk';
00030 
00031         $wgNamespaceContentModels[12312] = "testing";
00032         $wgContentHandlers["testing"] = 'DummyContentHandlerForTesting';
00033 
00034         MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
00035         $wgContLang->resetNamespaces(); # reset namespace cache
00036 
00037         $this->doLogin();
00038     }
00039 
00040     protected function tearDown() {
00041         MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
00042         parent::tearDown();
00043     }
00044 
00045     public function testEdit() {
00046         $name = 'Help:ApiEditPageTest_testEdit'; // assume Help namespace to default to wikitext
00047 
00048         // -- test new page --------------------------------------------
00049         $apiResult = $this->doApiRequestWithToken( array(
00050             'action' => 'edit',
00051             'title' => $name,
00052             'text' => 'some text',
00053         ) );
00054         $apiResult = $apiResult[0];
00055 
00056         // Validate API result data
00057         $this->assertArrayHasKey( 'edit', $apiResult );
00058         $this->assertArrayHasKey( 'result', $apiResult['edit'] );
00059         $this->assertEquals( 'Success', $apiResult['edit']['result'] );
00060 
00061         $this->assertArrayHasKey( 'new', $apiResult['edit'] );
00062         $this->assertArrayNotHasKey( 'nochange', $apiResult['edit'] );
00063 
00064         $this->assertArrayHasKey( 'pageid', $apiResult['edit'] );
00065 
00066         // -- test existing page, no change ----------------------------
00067         $data = $this->doApiRequestWithToken( array(
00068             'action' => 'edit',
00069             'title' => $name,
00070             'text' => 'some text',
00071         ) );
00072 
00073         $this->assertEquals( 'Success', $data[0]['edit']['result'] );
00074 
00075         $this->assertArrayNotHasKey( 'new', $data[0]['edit'] );
00076         $this->assertArrayHasKey( 'nochange', $data[0]['edit'] );
00077 
00078         // -- test existing page, with change --------------------------
00079         $data = $this->doApiRequestWithToken( array(
00080             'action' => 'edit',
00081             'title' => $name,
00082             'text' => 'different text'
00083         ) );
00084 
00085         $this->assertEquals( 'Success', $data[0]['edit']['result'] );
00086 
00087         $this->assertArrayNotHasKey( 'new', $data[0]['edit'] );
00088         $this->assertArrayNotHasKey( 'nochange', $data[0]['edit'] );
00089 
00090         $this->assertArrayHasKey( 'oldrevid', $data[0]['edit'] );
00091         $this->assertArrayHasKey( 'newrevid', $data[0]['edit'] );
00092         $this->assertNotEquals(
00093             $data[0]['edit']['newrevid'],
00094             $data[0]['edit']['oldrevid'],
00095             "revision id should change after edit"
00096         );
00097     }
00098 
00099     public function testNonTextEdit() {
00100         $name = 'Dummy:ApiEditPageTest_testNonTextEdit';
00101         $data = serialize( 'some bla bla text' );
00102 
00103         // -- test new page --------------------------------------------
00104         $apiResult = $this->doApiRequestWithToken( array(
00105             'action' => 'edit',
00106             'title' => $name,
00107             'text' => $data, ) );
00108         $apiResult = $apiResult[0];
00109 
00110         // Validate API result data
00111         $this->assertArrayHasKey( 'edit', $apiResult );
00112         $this->assertArrayHasKey( 'result', $apiResult['edit'] );
00113         $this->assertEquals( 'Success', $apiResult['edit']['result'] );
00114 
00115         $this->assertArrayHasKey( 'new', $apiResult['edit'] );
00116         $this->assertArrayNotHasKey( 'nochange', $apiResult['edit'] );
00117 
00118         $this->assertArrayHasKey( 'pageid', $apiResult['edit'] );
00119 
00120         // validate resulting revision
00121         $page = WikiPage::factory( Title::newFromText( $name ) );
00122         $this->assertEquals( "testing", $page->getContentModel() );
00123         $this->assertEquals( $data, $page->getContent()->serialize() );
00124     }
00125 
00129     public static function provideEditAppend() {
00130         return array(
00131             array( #0: append
00132                 'foo', 'append', 'bar', "foobar"
00133             ),
00134             array( #1: prepend
00135                 'foo', 'prepend', 'bar', "barfoo"
00136             ),
00137             array( #2: append to empty page
00138                 '', 'append', 'foo', "foo"
00139             ),
00140             array( #3: prepend to empty page
00141                 '', 'prepend', 'foo', "foo"
00142             ),
00143             array( #4: append to non-existing page
00144                 null, 'append', 'foo', "foo"
00145             ),
00146             array( #5: prepend to non-existing page
00147                 null, 'prepend', 'foo', "foo"
00148             ),
00149         );
00150     }
00151 
00155     public function testEditAppend( $text, $op, $append, $expected ) {
00156         static $count = 0;
00157         $count++;
00158 
00159         // assume NS_HELP defaults to wikitext
00160         $name = "Help:ApiEditPageTest_testEditAppend_$count";
00161 
00162         // -- create page (or not) -----------------------------------------
00163         if ( $text !== null ) {
00164             list( $re ) = $this->doApiRequestWithToken( array(
00165                 'action' => 'edit',
00166                 'title' => $name,
00167                 'text' => $text, ) );
00168 
00169             $this->assertEquals( 'Success', $re['edit']['result'] ); // sanity
00170         }
00171 
00172         // -- try append/prepend --------------------------------------------
00173         list( $re ) = $this->doApiRequestWithToken( array(
00174             'action' => 'edit',
00175             'title' => $name,
00176             $op . 'text' => $append, ) );
00177 
00178         $this->assertEquals( 'Success', $re['edit']['result'] );
00179 
00180         // -- validate -----------------------------------------------------
00181         $page = new WikiPage( Title::newFromText( $name ) );
00182         $content = $page->getContent();
00183         $this->assertNotNull( $content, 'Page should have been created' );
00184 
00185         $text = $content->getNativeData();
00186 
00187         $this->assertEquals( $expected, $text );
00188     }
00189 
00193     public function testEditSection() {
00194         $name = 'Help:ApiEditPageTest_testEditSection';
00195         $page = WikiPage::factory( Title::newFromText( $name ) );
00196         $text = "==section 1==\ncontent 1\n==section 2==\ncontent2";
00197         // Preload the page with some text
00198         $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), 'summary' );
00199 
00200         list( $re ) = $this->doApiRequestWithToken( array(
00201             'action' => 'edit',
00202             'title' => $name,
00203             'section' => '1',
00204             'text' => "==section 1==\nnew content 1",
00205         ) );
00206         $this->assertEquals( 'Success', $re['edit']['result'] );
00207         $newtext = WikiPage::factory( Title::newFromText( $name ) )
00208             ->getContent( Revision::RAW )
00209             ->getNativeData();
00210         $this->assertEquals( "==section 1==\nnew content 1\n\n==section 2==\ncontent2", $newtext );
00211 
00212         // Test that we raise a 'nosuchsection' error
00213         try {
00214             $this->doApiRequestWithToken( array(
00215                 'action' => 'edit',
00216                 'title' => $name,
00217                 'section' => '9999',
00218                 'text' => 'text',
00219             ) );
00220             $this->fail( "Should have raised a UsageException" );
00221         } catch ( UsageException $e ) {
00222             $this->assertEquals( 'nosuchsection', $e->getCodeString() );
00223         }
00224     }
00225 
00232     public function testEditNewSection() {
00233         $name = 'Help:ApiEditPageTest_testEditNewSection';
00234 
00235         // Test on a page that does not already exist
00236         $this->assertFalse( Title::newFromText( $name )->exists() );
00237         list( $re ) = $this->doApiRequestWithToken( array(
00238             'action' => 'edit',
00239             'title' => $name,
00240             'section' => 'new',
00241             'text' => 'test',
00242             'summary' => 'header',
00243         ));
00244 
00245         $this->assertEquals( 'Success', $re['edit']['result'] );
00246         // Check the page text is correct
00247         $text = WikiPage::factory( Title::newFromText( $name ) )
00248             ->getContent( Revision::RAW )
00249             ->getNativeData();
00250         $this->assertEquals( "== header ==\n\ntest", $text );
00251 
00252         // Now on one that does
00253         $this->assertTrue( Title::newFromText( $name )->exists() );
00254         list( $re2 ) = $this->doApiRequestWithToken( array(
00255             'action' => 'edit',
00256             'title' => $name,
00257             'section' => 'new',
00258             'text' => 'test',
00259             'summary' => 'header',
00260         ));
00261 
00262         $this->assertEquals( 'Success', $re2['edit']['result'] );
00263         $text = WikiPage::factory( Title::newFromText( $name ) )
00264             ->getContent( Revision::RAW )
00265             ->getNativeData();
00266         $this->assertEquals( "== header ==\n\ntest\n\n== header ==\n\ntest", $text );
00267     }
00268 
00272     public function testEdit_redirect() {
00273         static $count = 0;
00274         $count++;
00275 
00276         // assume NS_HELP defaults to wikitext
00277         $name = "Help:ApiEditPageTest_testEdit_redirect_$count";
00278         $title = Title::newFromText( $name );
00279         $page = WikiPage::factory( $title );
00280 
00281         $rname = "Help:ApiEditPageTest_testEdit_redirect_r$count";
00282         $rtitle = Title::newFromText( $rname );
00283         $rpage = WikiPage::factory( $rtitle );
00284 
00285         // base edit for content
00286         $page->doEditContent( new WikitextContent( "Foo" ),
00287             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00288         $this->forceRevisionDate( $page, '20120101000000' );
00289         $baseTime = $page->getRevision()->getTimestamp();
00290 
00291         // base edit for redirect
00292         $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ),
00293             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00294         $this->forceRevisionDate( $rpage, '20120101000000' );
00295 
00296         // conflicting edit to redirect
00297         $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]\n\n[[Category:Test]]" ),
00298             "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
00299         $this->forceRevisionDate( $rpage, '20120101020202' );
00300 
00301         // try to save edit, following the redirect
00302         list( $re, , ) = $this->doApiRequestWithToken( array(
00303             'action' => 'edit',
00304             'title' => $rname,
00305             'text' => 'nix bar!',
00306             'basetimestamp' => $baseTime,
00307             'section' => 'new',
00308             'redirect' => true,
00309         ), null, self::$users['sysop']->user );
00310 
00311         $this->assertEquals( 'Success', $re['edit']['result'],
00312             "no problems expected when following redirect" );
00313     }
00314 
00318     public function testEdit_redirectText() {
00319         static $count = 0;
00320         $count++;
00321 
00322         // assume NS_HELP defaults to wikitext
00323         $name = "Help:ApiEditPageTest_testEdit_redirectText_$count";
00324         $title = Title::newFromText( $name );
00325         $page = WikiPage::factory( $title );
00326 
00327         $rname = "Help:ApiEditPageTest_testEdit_redirectText_r$count";
00328         $rtitle = Title::newFromText( $rname );
00329         $rpage = WikiPage::factory( $rtitle );
00330 
00331         // base edit for content
00332         $page->doEditContent( new WikitextContent( "Foo" ),
00333             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00334         $this->forceRevisionDate( $page, '20120101000000' );
00335         $baseTime = $page->getRevision()->getTimestamp();
00336 
00337         // base edit for redirect
00338         $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ),
00339             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00340         $this->forceRevisionDate( $rpage, '20120101000000' );
00341 
00342         // conflicting edit to redirect
00343         $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]\n\n[[Category:Test]]" ),
00344             "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
00345         $this->forceRevisionDate( $rpage, '20120101020202' );
00346 
00347         // try to save edit, following the redirect but without creating a section
00348         try {
00349             $this->doApiRequestWithToken( array(
00350                 'action' => 'edit',
00351                 'title' => $rname,
00352                 'text' => 'nix bar!',
00353                 'basetimestamp' => $baseTime,
00354                 'redirect' => true,
00355             ), null, self::$users['sysop']->user );
00356 
00357             $this->fail( 'redirect-appendonly error expected' );
00358         } catch ( UsageException $ex ) {
00359             $this->assertEquals( 'redirect-appendonly', $ex->getCodeString() );
00360         }
00361     }
00362 
00363     public function testEditConflict() {
00364         static $count = 0;
00365         $count++;
00366 
00367         // assume NS_HELP defaults to wikitext
00368         $name = "Help:ApiEditPageTest_testEditConflict_$count";
00369         $title = Title::newFromText( $name );
00370 
00371         $page = WikiPage::factory( $title );
00372 
00373         // base edit
00374         $page->doEditContent( new WikitextContent( "Foo" ),
00375             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00376         $this->forceRevisionDate( $page, '20120101000000' );
00377         $baseTime = $page->getRevision()->getTimestamp();
00378 
00379         // conflicting edit
00380         $page->doEditContent( new WikitextContent( "Foo bar" ),
00381             "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
00382         $this->forceRevisionDate( $page, '20120101020202' );
00383 
00384         // try to save edit, expect conflict
00385         try {
00386             $this->doApiRequestWithToken( array(
00387                 'action' => 'edit',
00388                 'title' => $name,
00389                 'text' => 'nix bar!',
00390                 'basetimestamp' => $baseTime,
00391             ), null, self::$users['sysop']->user );
00392 
00393             $this->fail( 'edit conflict expected' );
00394         } catch ( UsageException $ex ) {
00395             $this->assertEquals( 'editconflict', $ex->getCodeString() );
00396         }
00397     }
00398 
00402     public function testEditConflict_newSection() {
00403         static $count = 0;
00404         $count++;
00405 
00406         // assume NS_HELP defaults to wikitext
00407         $name = "Help:ApiEditPageTest_testEditConflict_newSection_$count";
00408         $title = Title::newFromText( $name );
00409 
00410         $page = WikiPage::factory( $title );
00411 
00412         // base edit
00413         $page->doEditContent( new WikitextContent( "Foo" ),
00414             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00415         $this->forceRevisionDate( $page, '20120101000000' );
00416         $baseTime = $page->getRevision()->getTimestamp();
00417 
00418         // conflicting edit
00419         $page->doEditContent( new WikitextContent( "Foo bar" ),
00420             "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
00421         $this->forceRevisionDate( $page, '20120101020202' );
00422 
00423         // try to save edit, expect no conflict
00424         list( $re, , ) = $this->doApiRequestWithToken( array(
00425             'action' => 'edit',
00426             'title' => $name,
00427             'text' => 'nix bar!',
00428             'basetimestamp' => $baseTime,
00429             'section' => 'new',
00430         ), null, self::$users['sysop']->user );
00431 
00432         $this->assertEquals( 'Success', $re['edit']['result'],
00433             "no edit conflict expected here" );
00434     }
00435 
00436     public function testEditConflict_bug41990() {
00437         static $count = 0;
00438         $count++;
00439 
00440         /*
00441         * bug 41990: if the target page has a newer revision than the redirect, then editing the
00442         * redirect while specifying 'redirect' and *not* specifying 'basetimestamp' erroneously
00443         * caused an edit conflict to be detected.
00444         */
00445 
00446         // assume NS_HELP defaults to wikitext
00447         $name = "Help:ApiEditPageTest_testEditConflict_redirect_bug41990_$count";
00448         $title = Title::newFromText( $name );
00449         $page = WikiPage::factory( $title );
00450 
00451         $rname = "Help:ApiEditPageTest_testEditConflict_redirect_bug41990_r$count";
00452         $rtitle = Title::newFromText( $rname );
00453         $rpage = WikiPage::factory( $rtitle );
00454 
00455         // base edit for content
00456         $page->doEditContent( new WikitextContent( "Foo" ),
00457             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00458         $this->forceRevisionDate( $page, '20120101000000' );
00459 
00460         // base edit for redirect
00461         $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ),
00462             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00463         $this->forceRevisionDate( $rpage, '20120101000000' );
00464 
00465         // new edit to content
00466         $page->doEditContent( new WikitextContent( "Foo bar" ),
00467             "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
00468         $this->forceRevisionDate( $rpage, '20120101020202' );
00469 
00470         // try to save edit; should work, following the redirect.
00471         list( $re, , ) = $this->doApiRequestWithToken( array(
00472             'action' => 'edit',
00473             'title' => $rname,
00474             'text' => 'nix bar!',
00475             'section' => 'new',
00476             'redirect' => true,
00477         ), null, self::$users['sysop']->user );
00478 
00479         $this->assertEquals( 'Success', $re['edit']['result'],
00480             "no edit conflict expected here" );
00481     }
00482 
00487     protected function forceRevisionDate( WikiPage $page, $timestamp ) {
00488         $dbw = wfGetDB( DB_MASTER );
00489 
00490         $dbw->update( 'revision',
00491             array( 'rev_timestamp' => $dbw->timestamp( $timestamp ) ),
00492             array( 'rev_id' => $page->getLatest() ) );
00493 
00494         $page->clear();
00495     }
00496 }