Merge "Switch EditForm to using editRevId in place of edittimestamp"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 23 Jun 2016 11:19:35 +0000 (11:19 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 23 Jun 2016 11:19:35 +0000 (11:19 +0000)
1  2 
includes/EditPage.php

diff --combined includes/EditPage.php
@@@ -335,6 -335,9 +335,9 @@@ class EditPage 
        /** @var string */
        public $edittime = '';
  
+       /** @var integer */
+       private $editRevId = null;
        /** @var string */
        public $section = '';
  
                        $this->sectiontitle = preg_replace( '/^\s*=+\s*(.*?)\s*=+\s*$/', '$1', $this->sectiontitle );
  
                        $this->edittime = $request->getVal( 'wpEdittime' );
+                       $this->editRevId = $request->getIntOrNull( 'editRevId' );
                        $this->starttime = $request->getVal( 'wpStarttime' );
  
                        $undidRev = $request->getInt( 'wpUndidRevision' );
                        $this->summary = '';
                        $this->sectiontitle = '';
                        $this->edittime = '';
+                       $this->editRevId = null;
                        $this->starttime = wfTimestampNow();
                        $this->edit = false;
                        $this->preview = false;
        function initialiseForm() {
                global $wgUser;
                $this->edittime = $this->page->getTimestamp();
+               $this->editRevId = $this->page->getLatest();
  
                $content = $this->getContentObject( false ); # TODO: track content object?!
                if ( $content === false ) {
  
                        $this->page->clear(); # Force reload of dates, etc.
                        $timestamp = $this->page->getTimestamp();
+                       $latest = $this->page->getLatest();
  
                        wfDebug( "timestamp: {$timestamp}, edittime: {$this->edittime}\n" );
  
-                       if ( $timestamp != $this->edittime ) {
+                       // Check editRevId if set, which handles same-second timestamp collisions
+                       if ( $timestamp != $this->edittime
+                               || ( $this->editRevId !== null && $this->editRevId != $latest )
+                       ) {
                                $this->isConflict = true;
                                if ( $this->section == 'new' ) {
                                        if ( $this->page->getUserText() == $wgUser->getName() &&
                        if ( $this->isConflict ) {
                                wfDebug( __METHOD__
                                        . ": conflict! getting section '{$this->section}' for time '{$this->edittime}'"
-                                       . " (article time '{$timestamp}')\n" );
-                               $content = $this->page->replaceSectionContent(
-                                       $this->section,
-                                       $textbox_content,
-                                       $sectionTitle,
-                                       $this->edittime
-                               );
+                                       . " (id '{$this->editRevId}') (article time '{$timestamp}')\n" );
+                               // @TODO: replaceSectionAtRev() with base ID (not prior current) for ?oldid=X case
+                               // ...or disable section editing for non-current revisions (not exposed anyway).
+                               if ( $this->editRevId !== null ) {
+                                       $content = $this->page->replaceSectionAtRev(
+                                               $this->section,
+                                               $textbox_content,
+                                               $sectionTitle,
+                                               $this->editRevId
+                                       );
+                               } else {
+                                       $content = $this->page->replaceSectionContent(
+                                               $this->section,
+                                               $textbox_content,
+                                               $sectionTitle,
+                                               $this->edittime
+                                       );
+                               }
                        } else {
                                wfDebug( __METHOD__ . ": getting section '{$this->section}'\n" );
                                $content = $this->page->replaceSectionContent(
        function getBaseRevision() {
                if ( !$this->mBaseRevision ) {
                        $db = wfGetDB( DB_MASTER );
-                       $this->mBaseRevision = Revision::loadFromTimestamp(
-                               $db, $this->mTitle, $this->edittime );
+                       $this->mBaseRevision = $this->editRevId
+                               ? Revision::newFromId( $this->editRevId, Revision::READ_LATEST )
+                               : Revision::loadFromTimestamp( $db, $this->mTitle, $this->edittime );
                }
                return $this->mBaseRevision;
        }
                        $wgOut->addModules( 'mediawiki.action.edit.editWarning' );
                }
  
 -              if ( $wgAjaxEditStash ) {
 -                      $wgOut->addModules( 'mediawiki.action.edit.stash' );
 -              }
 -
                # Enabled article-related sidebar, toplinks, etc.
                $wgOut->setArticleRelated( true );
  
                $wgOut->setPageTitle( wfMessage( $msg, $displayTitle ) );
                # Transmit the name of the message to JavaScript for live preview
                # Keep Resources.php/mediawiki.action.edit.preview in sync with the possible keys
 -              $wgOut->addJsConfigVars( 'wgEditMessage', $msg );
 +              $wgOut->addJsConfigVars( [
 +                      'wgEditMessage' => $msg,
 +                      'wgAjaxEditStash' => $wgAjaxEditStash,
 +              ] );
        }
  
        /**
                        }
                }
  
 +              // Set a hidden field so JS knows what edit form mode we are in
 +              if ( $this->isConflict ) {
 +                      $mode = 'conflict';
 +              } elseif ( $this->preview ) {
 +                      $mode = 'preview';
 +              } elseif ( $this->diff ) {
 +                      $mode = 'diff';
 +              } else {
 +                      $mode = 'text';
 +              }
 +              $wgOut->addHTML( Html::hidden( 'mode', $mode, [ 'id' => 'mw-edit-mode' ] ) );
 +
                // Marker for detecting truncated form data.  This must be the last
                // parameter sent in order to be of use, so do not move me.
                $wgOut->addHTML( Html::hidden( 'wpUltimateParam', true ) );
  
                if ( $this->isConflict ) {
                        $wgOut->wrapWikiMsg( "<div class='mw-explainconflict'>\n$1\n</div>", 'explainconflict' );
-                       $this->edittime = $this->page->getTimestamp();
+                       $this->editRevId = $this->page->getLatest();
                } else {
                        if ( $this->section != '' && !$this->isSectionEditSupported() ) {
                                // We use $this->section to much before this and getVal('wgSection') directly in other places
  <input type='hidden' value="{$section}" name="wpSection"/>
  <input type='hidden' value="{$this->starttime}" name="wpStarttime" />
  <input type='hidden' value="{$this->edittime}" name="wpEdittime" />
+ <input type='hidden' value="{$this->editRevId}" name="editRevId" />
  <input type='hidden' value="{$this->scrolltop}" name="wpScrolltop" id="wpScrolltop" />
  
  HTML
                }
  
                $textboxContent = $this->toEditContent( $this->textbox1 );
-               $newContent = $this->page->replaceSectionContent(
-                                                       $this->section, $textboxContent,
-                                                       $this->summary, $this->edittime );
+               if ( $this->editRevId !== null ) {
+                       $newContent = $this->page->replaceSectionAtRev(
+                               $this->section, $textboxContent, $this->summary, $this->editRevId
+                       );
+               } else {
+                       $newContent = $this->page->replaceSectionContent(
+                               $this->section, $textboxContent, $this->summary, $this->edittime
+                       );
+               }
  
                if ( $newContent ) {
                        ContentHandler::runLegacyHooks( 'EditPageGetDiffText', [ $this, &$newContent ] );
         */
        function getPreviewText() {
                global $wgOut, $wgUser, $wgRawHtml, $wgLang;
 -              global $wgAllowUserCss, $wgAllowUserJs, $wgAjaxEditStash;
 +              global $wgAllowUserCss, $wgAllowUserJs;
  
                $stats = $wgOut->getContext()->getStats();
  
                                $this->mTitle, $pstContent, $wgUser );
                        $parserOutput = $pstContent->getParserOutput( $this->mTitle, null, $parserOptions );
  
 -                      # Try to stash the edit for the final submission step
 -                      # @todo: different date format preferences cause cache misses
 -                      if ( $wgAjaxEditStash ) {
 -                              ApiStashEdit::stashEditFromPreview(
 -                                      $this->getArticle(), $content, $pstContent,
 -                                      $parserOutput, $parserOptions, $parserOptions, wfTimestampNow()
 -                              );
 -                      }
 -
                        $parserOutput->setEditSectionTokens( false ); // no section edit links
                        $previewHTML = $parserOutput->getText();
                        $this->mParserOutput = $parserOutput;