EditPage: Show a different label for the button on create vs. modify
[lhc/web/wiklou.git] / includes / EditPage.php
index f2403fe..7f94140 100644 (file)
@@ -335,6 +335,9 @@ class EditPage {
        /** @var string */
        public $edittime = '';
 
+       /** @var integer */
+       private $editRevId = null;
+
        /** @var string */
        public $section = '';
 
@@ -839,6 +842,7 @@ class EditPage {
                        $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' );
@@ -935,6 +939,7 @@ class EditPage {
                        $this->summary = '';
                        $this->sectiontitle = '';
                        $this->edittime = '';
+                       $this->editRevId = null;
                        $this->starttime = wfTimestampNow();
                        $this->edit = false;
                        $this->preview = false;
@@ -1020,6 +1025,7 @@ class EditPage {
        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 ) {
@@ -1862,10 +1868,14 @@ class EditPage {
 
                        $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() &&
@@ -1905,14 +1915,24 @@ class EditPage {
                        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(
@@ -2172,8 +2192,9 @@ class EditPage {
        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;
        }
@@ -2242,10 +2263,6 @@ class EditPage {
                        $wgOut->addModules( 'mediawiki.action.edit.editWarning' );
                }
 
-               if ( $wgAjaxEditStash ) {
-                       $wgOut->addModules( 'mediawiki.action.edit.stash' );
-               }
-
                # Enabled article-related sidebar, toplinks, etc.
                $wgOut->setArticleRelated( true );
 
@@ -2273,7 +2290,10 @@ class EditPage {
                $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,
+               ] );
        }
 
        /**
@@ -2690,6 +2710,18 @@ class EditPage {
                        }
                }
 
+               // 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 ) );
@@ -2745,7 +2777,7 @@ class EditPage {
 
                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
@@ -3052,6 +3084,7 @@ class EditPage {
 <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
@@ -3260,10 +3293,15 @@ 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 ] );
@@ -3475,6 +3513,14 @@ HTML
                if ( Hooks::run( 'EditPageBeforeConflictDiff', [ &$this, &$wgOut ] ) ) {
                        $stats = $wgOut->getContext()->getStats();
                        $stats->increment( 'edit.failures.conflict' );
+                       if ( $this->mTitle->isTalkPage() ) {
+                               $stats->increment( 'edit.failures.conflict.byType.talk' );
+                       } else {
+                               $stats->increment( 'edit.failures.conflict.byType.subject' );
+                       }
+                       if ( $this->mTitle->getNamespace() === NS_PROJECT ) {
+                               $stats->increment( 'edit.failures.conflict.byNamespace.project' );
+                       }
 
                        $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" );
 
@@ -3603,7 +3649,7 @@ HTML
         */
        function getPreviewText() {
                global $wgOut, $wgUser, $wgRawHtml, $wgLang;
-               global $wgAllowUserCss, $wgAllowUserJs, $wgAjaxEditStash;
+               global $wgAllowUserCss, $wgAllowUserJs;
 
                $stats = $wgOut->getContext()->getStats();
 
@@ -3713,15 +3759,6 @@ HTML
                                $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;
@@ -3995,13 +4032,14 @@ HTML
        public function getEditButtons( &$tabindex ) {
                $buttons = [];
 
+               $buttonLabelKey = $this->isNew ? 'savearticle' : 'savechanges';
+               $buttonLabel = wfMessage( $buttonLabelKey )->text();
                $attribs = [
                        'id' => 'wpSave',
                        'name' => 'wpSave',
                        'tabindex' => ++$tabindex,
                ] + Linker::tooltipAndAccesskeyAttribs( 'save' );
-               $buttons['save'] = Html::submitButton( wfMessage( 'savearticle' )->text(),
-                       $attribs, [ 'mw-ui-constructive' ] );
+               $buttons['save'] = Html::submitButton( $buttonLabel, $attribs, [ 'mw-ui-constructive' ] );
 
                ++$tabindex; // use the same for preview and live preview
                $attribs = [