/** @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;