MediaWiki  REL1_21
ApiEditPageTest.php
Go to the documentation of this file.
00001 <?php
00002 
00012 class ApiEditPageTest extends ApiTestCase {
00013 
00014         public function setup() {
00015                 global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
00016 
00017                 parent::setup();
00018 
00019                 $wgExtraNamespaces[12312] = 'Dummy';
00020                 $wgExtraNamespaces[12313] = 'Dummy_talk';
00021 
00022                 $wgNamespaceContentModels[12312] = "testing";
00023                 $wgContentHandlers["testing"] = 'DummyContentHandlerForTesting';
00024 
00025                 MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
00026                 $wgContLang->resetNamespaces(); # reset namespace cache
00027 
00028                 $this->doLogin();
00029         }
00030 
00031         public function teardown() {
00032                 global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
00033 
00034                 unset( $wgExtraNamespaces[12312] );
00035                 unset( $wgExtraNamespaces[12313] );
00036 
00037                 unset( $wgNamespaceContentModels[12312] );
00038                 unset( $wgContentHandlers["testing"] );
00039 
00040                 MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
00041                 $wgContLang->resetNamespaces(); # reset namespace cache
00042 
00043                 parent::teardown();
00044         }
00045 
00046         function testEdit() {
00047                 $name = 'Help:ApiEditPageTest_testEdit'; // assume Help namespace to default to wikitext
00048 
00049                 // -- test new page --------------------------------------------
00050                 $apiResult = $this->doApiRequestWithToken( array(
00051                         'action' => 'edit',
00052                         'title' => $name,
00053                         'text' => 'some text',
00054                 ) );
00055                 $apiResult = $apiResult[0];
00056 
00057                 // Validate API result data
00058                 $this->assertArrayHasKey( 'edit', $apiResult );
00059                 $this->assertArrayHasKey( 'result', $apiResult['edit'] );
00060                 $this->assertEquals( 'Success', $apiResult['edit']['result'] );
00061 
00062                 $this->assertArrayHasKey( 'new', $apiResult['edit'] );
00063                 $this->assertArrayNotHasKey( 'nochange', $apiResult['edit'] );
00064 
00065                 $this->assertArrayHasKey( 'pageid', $apiResult['edit'] );
00066 
00067                 // -- test existing page, no change ----------------------------
00068                 $data = $this->doApiRequestWithToken( array(
00069                         'action' => 'edit',
00070                         'title' => $name,
00071                         'text' => 'some text',
00072                 ) );
00073 
00074                 $this->assertEquals( 'Success', $data[0]['edit']['result'] );
00075 
00076                 $this->assertArrayNotHasKey( 'new', $data[0]['edit'] );
00077                 $this->assertArrayHasKey( 'nochange', $data[0]['edit'] );
00078 
00079                 // -- test existing page, with change --------------------------
00080                 $data = $this->doApiRequestWithToken( array(
00081                         'action' => 'edit',
00082                         'title' => $name,
00083                         'text' => 'different text'
00084                 ) );
00085 
00086                 $this->assertEquals( 'Success', $data[0]['edit']['result'] );
00087 
00088                 $this->assertArrayNotHasKey( 'new', $data[0]['edit'] );
00089                 $this->assertArrayNotHasKey( 'nochange', $data[0]['edit'] );
00090 
00091                 $this->assertArrayHasKey( 'oldrevid', $data[0]['edit'] );
00092                 $this->assertArrayHasKey( 'newrevid', $data[0]['edit'] );
00093                 $this->assertNotEquals(
00094                         $data[0]['edit']['newrevid'],
00095                         $data[0]['edit']['oldrevid'],
00096                         "revision id should change after edit"
00097                 );
00098         }
00099 
00100         function testNonTextEdit() {
00101                 $name = 'Dummy:ApiEditPageTest_testNonTextEdit';
00102                 $data = serialize( 'some bla bla text' );
00103 
00104                 // -- test new page --------------------------------------------
00105                 $apiResult = $this->doApiRequestWithToken( array(
00106                         'action' => 'edit',
00107                         'title' => $name,
00108                         'text' => $data, ) );
00109                 $apiResult = $apiResult[0];
00110 
00111                 // Validate API result data
00112                 $this->assertArrayHasKey( 'edit', $apiResult );
00113                 $this->assertArrayHasKey( 'result', $apiResult['edit'] );
00114                 $this->assertEquals( 'Success', $apiResult['edit']['result'] );
00115 
00116                 $this->assertArrayHasKey( 'new', $apiResult['edit'] );
00117                 $this->assertArrayNotHasKey( 'nochange', $apiResult['edit'] );
00118 
00119                 $this->assertArrayHasKey( 'pageid', $apiResult['edit'] );
00120 
00121                 // validate resulting revision
00122                 $page = WikiPage::factory( Title::newFromText( $name ) );
00123                 $this->assertEquals( "testing", $page->getContentModel() );
00124                 $this->assertEquals( $data, $page->getContent()->serialize() );
00125         }
00126 
00127         static function provideEditAppend() {
00128                 return array(
00129                         array( #0: append
00130                                 'foo', 'append', 'bar', "foobar"
00131                         ),
00132                         array( #1: prepend
00133                                 'foo', 'prepend', 'bar', "barfoo"
00134                         ),
00135                         array( #2: append to empty page
00136                                 '', 'append', 'foo', "foo"
00137                         ),
00138                         array( #3: prepend to empty page
00139                                 '', 'prepend', 'foo', "foo"
00140                         ),
00141                         array( #4: append to non-existing page
00142                                 null, 'append', 'foo', "foo"
00143                         ),
00144                         array( #5: prepend to non-existing page
00145                                 null, 'prepend', 'foo', "foo"
00146                         ),
00147                 );
00148         }
00149 
00153         function testEditAppend( $text, $op, $append, $expected ) {
00154                 static $count = 0;
00155                 $count++;
00156 
00157                 // assume NS_HELP defaults to wikitext
00158                 $name = "Help:ApiEditPageTest_testEditAppend_$count";
00159 
00160                 // -- create page (or not) -----------------------------------------
00161                 if ( $text !== null ) {
00162                         if ( $text === '' ) {
00163                                 // can't create an empty page, so create it with some content
00164                                 list( $re, , ) = $this->doApiRequestWithToken( array(
00165                                         'action' => 'edit',
00166                                         'title' => $name,
00167                                         'text' => '(dummy)', ) );
00168                         }
00169 
00170                         list( $re, , ) = $this->doApiRequestWithToken( array(
00171                                 'action' => 'edit',
00172                                 'title' => $name,
00173                                 'text' => $text, ) );
00174 
00175                         $this->assertEquals( 'Success', $re['edit']['result'] ); // sanity
00176                 }
00177 
00178                 // -- try append/prepend --------------------------------------------
00179                 list( $re, , ) = $this->doApiRequestWithToken( array(
00180                         'action' => 'edit',
00181                         'title' => $name,
00182                         $op . 'text' => $append, ) );
00183 
00184                 $this->assertEquals( 'Success', $re['edit']['result'] );
00185 
00186                 // -- validate -----------------------------------------------------
00187                 $page = new WikiPage( Title::newFromText( $name ) );
00188                 $content = $page->getContent();
00189                 $this->assertNotNull( $content, 'Page should have been created' );
00190 
00191                 $text = $content->getNativeData();
00192 
00193                 $this->assertEquals( $expected, $text );
00194         }
00195 
00196         function testEditSection() {
00197                 $this->markTestIncomplete( "not yet implemented" );
00198         }
00199 
00200         function testUndo() {
00201                 $this->markTestIncomplete( "not yet implemented" );
00202         }
00203 
00204         function testEditConflict() {
00205                 static $count = 0;
00206                 $count++;
00207 
00208                 // assume NS_HELP defaults to wikitext
00209                 $name = "Help:ApiEditPageTest_testEditConflict_$count";
00210                 $title = Title::newFromText( $name );
00211 
00212                 $page = WikiPage::factory( $title );
00213 
00214                 // base edit
00215                 $page->doEditContent( new WikitextContent( "Foo" ),
00216                         "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00217                 $this->forceRevisionDate( $page, '20120101000000' );
00218                 $baseTime = $page->getRevision()->getTimestamp();
00219 
00220                 // conflicting edit
00221                 $page->doEditContent( new WikitextContent( "Foo bar" ),
00222                         "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
00223                 $this->forceRevisionDate( $page, '20120101020202' );
00224 
00225                 // try to save edit, expect conflict
00226                 try {
00227                         list( $re, , ) = $this->doApiRequestWithToken( array(
00228                                 'action' => 'edit',
00229                                 'title' => $name,
00230                                 'text' => 'nix bar!',
00231                                 'basetimestamp' => $baseTime,
00232                         ), null, self::$users['sysop']->user );
00233 
00234                         $this->fail( 'edit conflict expected' );
00235                 } catch ( UsageException $ex ) {
00236                         $this->assertEquals( 'editconflict', $ex->getCodeString() );
00237                 }
00238         }
00239 
00240         function testEditConflict_redirect() {
00241                 static $count = 0;
00242                 $count++;
00243 
00244                 // assume NS_HELP defaults to wikitext
00245                 $name = "Help:ApiEditPageTest_testEditConflict_redirect_$count";
00246                 $title = Title::newFromText( $name );
00247                 $page = WikiPage::factory( $title );
00248 
00249                 $rname = "Help:ApiEditPageTest_testEditConflict_redirect_r$count";
00250                 $rtitle = Title::newFromText( $rname );
00251                 $rpage = WikiPage::factory( $rtitle );
00252 
00253                 // base edit for content
00254                 $page->doEditContent( new WikitextContent( "Foo" ),
00255                         "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00256                 $this->forceRevisionDate( $page, '20120101000000' );
00257                 $baseTime = $page->getRevision()->getTimestamp();
00258 
00259                 // base edit for redirect
00260                 $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ),
00261                         "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00262                 $this->forceRevisionDate( $rpage, '20120101000000' );
00263 
00264                 // conflicting edit to redirect
00265                 $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]\n\n[[Category:Test]]" ),
00266                         "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
00267                 $this->forceRevisionDate( $rpage, '20120101020202' );
00268 
00269                 // try to save edit; should work, because we follow the redirect
00270                 list( $re, , ) = $this->doApiRequestWithToken( array(
00271                         'action' => 'edit',
00272                         'title' => $rname,
00273                         'text' => 'nix bar!',
00274                         'basetimestamp' => $baseTime,
00275                         'redirect' => true,
00276                 ), null, self::$users['sysop']->user );
00277 
00278                 $this->assertEquals( 'Success', $re['edit']['result'],
00279                         "no edit conflict expected when following redirect" );
00280 
00281                 // try again, without following the redirect. Should fail.
00282                 try {
00283                         list( $re, , ) = $this->doApiRequestWithToken( array(
00284                                 'action' => 'edit',
00285                                 'title' => $rname,
00286                                 'text' => 'nix bar!',
00287                                 'basetimestamp' => $baseTime,
00288                         ), null, self::$users['sysop']->user );
00289 
00290                         $this->fail( 'edit conflict expected' );
00291                 } catch ( UsageException $ex ) {
00292                         $this->assertEquals( 'editconflict', $ex->getCodeString() );
00293                 }
00294         }
00295 
00296         function testEditConflict_bug41990() {
00297                 static $count = 0;
00298                 $count++;
00299 
00300                 /*
00301                 * bug 41990: if the target page has a newer revision than the redirect, then editing the
00302                 * redirect while specifying 'redirect' and *not* specifying 'basetimestamp' erronously
00303                 * caused an edit conflict to be detected.
00304                 */
00305 
00306                 // assume NS_HELP defaults to wikitext
00307                 $name = "Help:ApiEditPageTest_testEditConflict_redirect_bug41990_$count";
00308                 $title = Title::newFromText( $name );
00309                 $page = WikiPage::factory( $title );
00310 
00311                 $rname = "Help:ApiEditPageTest_testEditConflict_redirect_bug41990_r$count";
00312                 $rtitle = Title::newFromText( $rname );
00313                 $rpage = WikiPage::factory( $rtitle );
00314 
00315                 // base edit for content
00316                 $page->doEditContent( new WikitextContent( "Foo" ),
00317                         "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00318                 $this->forceRevisionDate( $page, '20120101000000' );
00319 
00320                 // base edit for redirect
00321                 $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ),
00322                         "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
00323                 $this->forceRevisionDate( $rpage, '20120101000000' );
00324                 $baseTime = $rpage->getRevision()->getTimestamp();
00325 
00326                 // new edit to content
00327                 $page->doEditContent( new WikitextContent( "Foo bar" ),
00328                         "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
00329                 $this->forceRevisionDate( $rpage, '20120101020202' );
00330 
00331                 // try to save edit; should work, following the redirect.
00332                 list( $re, , ) = $this->doApiRequestWithToken( array(
00333                         'action' => 'edit',
00334                         'title' => $rname,
00335                         'text' => 'nix bar!',
00336                         'redirect' => true,
00337                 ), null, self::$users['sysop']->user );
00338 
00339                 $this->assertEquals( 'Success', $re['edit']['result'],
00340                         "no edit conflict expected here" );
00341         }
00342 
00343         protected function forceRevisionDate( WikiPage $page, $timestamp ) {
00344                 $dbw = wfGetDB( DB_MASTER );
00345 
00346                 $dbw->update( 'revision',
00347                         array( 'rev_timestamp' => $dbw->timestamp( $timestamp ) ),
00348                         array( 'rev_id' => $page->getLatest() ) );
00349 
00350                 $page->clear();
00351         }
00352 }