MediaWiki  REL1_23
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             if ( $text === '' ) {
00165                 // can't create an empty page, so create it with some content
00166                 $this->doApiRequestWithToken( array(
00167                     'action' => 'edit',
00168                     'title' => $name,
00169                     'text' => '(dummy)', ) );
00170             }
00171 
00172             list( $re ) = $this->doApiRequestWithToken( array(
00173                 'action' => 'edit',
00174                 'title' => $name,
00175                 'text' => $text, ) );
00176 
00177             $this->assertEquals( 'Success', $re['edit']['result'] ); // sanity
00178         }
00179 
00180         // -- try append/prepend --------------------------------------------
00181         list( $re ) = $this->doApiRequestWithToken( array(
00182             'action' => 'edit',
00183             'title' => $name,
00184             $op . 'text' => $append, ) );
00185 
00186         $this->assertEquals( 'Success', $re['edit']['result'] );
00187 
00188         // -- validate -----------------------------------------------------
00189         $page = new WikiPage( Title::newFromText( $name ) );
00190         $content = $page->getContent();
00191         $this->assertNotNull( $content, 'Page should have been created' );
00192 
00193         $text = $content->getNativeData();
00194 
00195         $this->assertEquals( $expected, $text );
00196     }
00197 
00201     public function testEditSection() {
00202         $name = 'Help:ApiEditPageTest_testEditSection';
00203         $page = WikiPage::factory( Title::newFromText( $name ) );
00204         $text = "==section 1==\ncontent 1\n==section 2==\ncontent2";
00205         // Preload the page with some text
00206         $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), 'summary' );
00207 
00208         list( $re ) = $this->doApiRequestWithToken( array(
00209             'action' => 'edit',
00210             'title' => $name,
00211             'section' => '1',
00212             'text' => "==section 1==\nnew content 1",
00213         ) );
00214         $this->assertEquals( 'Success', $re['edit']['result'] );
00215         $newtext = WikiPage::factory( Title::newFromText( $name ) )
00216             ->getContent( Revision::RAW )
00217             ->getNativeData();
00218         $this->assertEquals( "==section 1==\nnew content 1\n\n==section 2==\ncontent2", $newtext );
00219 
00220         // Test that we raise a 'nosuchsection' error
00221         try {
00222             $this->doApiRequestWithToken( array(
00223                 'action' => 'edit',
00224                 'title' => $name,
00225                 'section' => '9999',
00226                 'text' => 'text',
00227             ) );
00228             $this->fail( "Should have raised a UsageException" );
00229         } catch ( UsageException $e ) {
00230             $this->assertEquals( 'nosuchsection', $e->getCodeString() );
00231         }
00232     }
00233 
00240     public function testEditNewSection() {
00241         $name = 'Help:ApiEditPageTest_testEditNewSection';
00242 
00243         // Test on a page that does not already exist
00244         $this->assertFalse( Title::newFromText( $name )->exists() );
00245         list( $re ) = $this->doApiRequestWithToken( array(
00246             'action' => 'edit',
00247             'title' => $name,
00248             'section' => 'new',
00249             'text' => 'test',
00250             'summary' => 'header',
00251         ));
00252 
00253         $this->assertEquals( 'Success', $re['edit']['result'] );
00254         // Check the page text is correct
00255         $text = WikiPage::factory( Title::newFromText( $name ) )
00256             ->getContent( Revision::RAW )
00257             ->getNativeData();
00258         $this->assertEquals( "== header ==\n\ntest", $text );
00259 
00260         // Now on one that does
00261         $this->assertTrue( Title::newFromText( $name )->exists() );
00262         list( $re2 ) = $this->doApiRequestWithToken( array(
00263             'action' => 'edit',
00264             'title' => $name,
00265             'section' => 'new',
00266             'text' => 'test',
00267             'summary' => 'header',
00268         ));
00269 
00270         $this->assertEquals( 'Success', $re2['edit']['result'] );
00271         $text = WikiPage::factory( Title::newFromText( $name ) )
00272             ->getContent( Revision::RAW )
00273             ->getNativeData();
00274         $this->assertEquals( "== header ==\n\ntest\n\n== header ==\n\ntest", $text );
00275     }
00276 
00277     public function testEditConflict() {
00278         static $count = 0;
00279         $count++;
00280 
00281         // assume NS_HELP defaults to wikitext
00282         $name = "Help:ApiEditPageTest_testEditConflict_$count";
00283         $title = Title::newFromText( $name );
00284 
00285         $page = WikiPage::factory( $title );
00286 
00287         // base edit
00288         $page->doEditContent( new WikitextContent( "Foo" ),
00289             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00290         $this->forceRevisionDate( $page, '20120101000000' );
00291         $baseTime = $page->getRevision()->getTimestamp();
00292 
00293         // conflicting edit
00294         $page->doEditContent( new WikitextContent( "Foo bar" ),
00295             "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
00296         $this->forceRevisionDate( $page, '20120101020202' );
00297 
00298         // try to save edit, expect conflict
00299         try {
00300             $this->doApiRequestWithToken( array(
00301                 'action' => 'edit',
00302                 'title' => $name,
00303                 'text' => 'nix bar!',
00304                 'basetimestamp' => $baseTime,
00305             ), null, self::$users['sysop']->user );
00306 
00307             $this->fail( 'edit conflict expected' );
00308         } catch ( UsageException $ex ) {
00309             $this->assertEquals( 'editconflict', $ex->getCodeString() );
00310         }
00311     }
00312 
00313     public function testEditConflict_redirect() {
00314         static $count = 0;
00315         $count++;
00316 
00317         // assume NS_HELP defaults to wikitext
00318         $name = "Help:ApiEditPageTest_testEditConflict_redirect_$count";
00319         $title = Title::newFromText( $name );
00320         $page = WikiPage::factory( $title );
00321 
00322         $rname = "Help:ApiEditPageTest_testEditConflict_redirect_r$count";
00323         $rtitle = Title::newFromText( $rname );
00324         $rpage = WikiPage::factory( $rtitle );
00325 
00326         // base edit for content
00327         $page->doEditContent( new WikitextContent( "Foo" ),
00328             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00329         $this->forceRevisionDate( $page, '20120101000000' );
00330         $baseTime = $page->getRevision()->getTimestamp();
00331 
00332         // base edit for redirect
00333         $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ),
00334             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00335         $this->forceRevisionDate( $rpage, '20120101000000' );
00336 
00337         // conflicting edit to redirect
00338         $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]\n\n[[Category:Test]]" ),
00339             "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
00340         $this->forceRevisionDate( $rpage, '20120101020202' );
00341 
00342         // try to save edit; should work, because we follow the redirect
00343         list( $re, , ) = $this->doApiRequestWithToken( array(
00344             'action' => 'edit',
00345             'title' => $rname,
00346             'text' => 'nix bar!',
00347             'basetimestamp' => $baseTime,
00348             'redirect' => true,
00349         ), null, self::$users['sysop']->user );
00350 
00351         $this->assertEquals( 'Success', $re['edit']['result'],
00352             "no edit conflict expected when following redirect" );
00353 
00354         // try again, without following the redirect. Should fail.
00355         try {
00356             $this->doApiRequestWithToken( array(
00357                 'action' => 'edit',
00358                 'title' => $rname,
00359                 'text' => 'nix bar!',
00360                 'basetimestamp' => $baseTime,
00361             ), null, self::$users['sysop']->user );
00362 
00363             $this->fail( 'edit conflict expected' );
00364         } catch ( UsageException $ex ) {
00365             $this->assertEquals( 'editconflict', $ex->getCodeString() );
00366         }
00367     }
00368 
00369     public function testEditConflict_bug41990() {
00370         static $count = 0;
00371         $count++;
00372 
00373         /*
00374         * bug 41990: if the target page has a newer revision than the redirect, then editing the
00375         * redirect while specifying 'redirect' and *not* specifying 'basetimestamp' erroneously
00376         * caused an edit conflict to be detected.
00377         */
00378 
00379         // assume NS_HELP defaults to wikitext
00380         $name = "Help:ApiEditPageTest_testEditConflict_redirect_bug41990_$count";
00381         $title = Title::newFromText( $name );
00382         $page = WikiPage::factory( $title );
00383 
00384         $rname = "Help:ApiEditPageTest_testEditConflict_redirect_bug41990_r$count";
00385         $rtitle = Title::newFromText( $rname );
00386         $rpage = WikiPage::factory( $rtitle );
00387 
00388         // base edit for content
00389         $page->doEditContent( new WikitextContent( "Foo" ),
00390             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00391         $this->forceRevisionDate( $page, '20120101000000' );
00392 
00393         // base edit for redirect
00394         $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ),
00395             "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00396         $this->forceRevisionDate( $rpage, '20120101000000' );
00397 
00398         // new edit to content
00399         $page->doEditContent( new WikitextContent( "Foo bar" ),
00400             "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
00401         $this->forceRevisionDate( $rpage, '20120101020202' );
00402 
00403         // try to save edit; should work, following the redirect.
00404         list( $re, , ) = $this->doApiRequestWithToken( array(
00405             'action' => 'edit',
00406             'title' => $rname,
00407             'text' => 'nix bar!',
00408             'redirect' => true,
00409         ), null, self::$users['sysop']->user );
00410 
00411         $this->assertEquals( 'Success', $re['edit']['result'],
00412             "no edit conflict expected here" );
00413     }
00414 
00419     protected function forceRevisionDate( WikiPage $page, $timestamp ) {
00420         $dbw = wfGetDB( DB_MASTER );
00421 
00422         $dbw->update( 'revision',
00423             array( 'rev_timestamp' => $dbw->timestamp( $timestamp ) ),
00424             array( 'rev_id' => $page->getLatest() ) );
00425 
00426         $page->clear();
00427     }
00428 }