X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FEditPage.php;h=47912cb8c2c3f09b07184b777dcdcf0e3b998e62;hb=a45caa8469bc6091d2161fde212c454cc0f0b970;hp=8571cd79a980e98ceb0b5bbc08d4e4cef3de71a2;hpb=e4d382142c12c749a36c17431dd987d91aa8c5ff;p=lhc%2Fweb%2Fwiklou.git
diff --git a/includes/EditPage.php b/includes/EditPage.php
index 8571cd79a9..47912cb8c2 100644
--- a/includes/EditPage.php
+++ b/includes/EditPage.php
@@ -201,6 +201,8 @@ class EditPage {
/** @var Article */
public $mArticle;
+ /** @var WikiPage */
+ private $page;
/** @var Title */
public $mTitle;
@@ -399,6 +401,7 @@ class EditPage {
*/
public function __construct( Article $article ) {
$this->mArticle = $article;
+ $this->page = $article->getPage(); // model object
$this->mTitle = $article->getTitle();
$this->contentModel = $this->mTitle->getContentModel();
@@ -537,6 +540,20 @@ class EditPage {
return;
}
+ $revision = $this->mArticle->getRevisionFetched();
+ // Disallow editing revisions with content models different from the current one
+ if ( $revision && $revision->getContentModel() !== $this->contentModel ) {
+ $this->displayViewSourcePage(
+ $this->getContentObject(),
+ wfMessage(
+ 'contentmodelediterror',
+ $revision->getContentModel(),
+ $this->contentModel
+ )->plain()
+ );
+ return;
+ }
+
$this->isConflict = false;
// css / js subpages of user pages get a special treatment
$this->isCssJsSubpage = $this->mTitle->isCssJsSubpage();
@@ -647,6 +664,20 @@ class EditPage {
throw new PermissionsError( $action, $permErrors );
}
+ $this->displayViewSourcePage(
+ $content,
+ $wgOut->formatPermissionsErrorMessage( $permErrors, 'edit' )
+ );
+ }
+
+ /**
+ * Display a read-only View Source page
+ * @param Content $content content object
+ * @param string $errorMessage additional wikitext error message to display
+ */
+ protected function displayViewSourcePage( Content $content, $errorMessage = '' ) {
+ global $wgOut;
+
Hooks::run( 'EditPage::showReadOnlyForm:initial', array( $this, &$wgOut ) );
$wgOut->setRobotPolicy( 'noindex,nofollow' );
@@ -658,8 +689,10 @@ class EditPage {
$wgOut->addHTML( $this->editFormPageTop );
$wgOut->addHTML( $this->editFormTextTop );
- $wgOut->addWikiText( $wgOut->formatPermissionsErrorMessage( $permErrors, 'edit' ) );
- $wgOut->addHTML( "
\n" );
+ if ( $errorMessage !== '' ) {
+ $wgOut->addWikiText( $errorMessage );
+ $wgOut->addHTML( "
\n" );
+ }
# If the user made changes, preserve them when showing the markup
# (This happens when a user is blocked during edit, for instance)
@@ -667,7 +700,13 @@ class EditPage {
$text = $this->textbox1;
$wgOut->addWikiMsg( 'viewyourtext' );
} else {
- $text = $this->toEditText( $content );
+ try {
+ $text = $this->toEditText( $content );
+ } catch ( MWException $e ) {
+ # Serialize using the default format if the content model is not supported
+ # (e.g. for an old revision with a different model)
+ $text = $content->serialize();
+ }
$wgOut->addWikiMsg( 'viewsourcetext' );
}
@@ -966,6 +1005,7 @@ class EditPage {
* for saving, preview parsing and so on...
*
* @param WebRequest $request
+ * @return string|null
*/
protected function importContentFormData( &$request ) {
return; // Don't do anything, EditPage already extracted wpTextbox1
@@ -978,7 +1018,7 @@ class EditPage {
*/
function initialiseForm() {
global $wgUser;
- $this->edittime = $this->mArticle->getTimestamp();
+ $this->edittime = $this->page->getTimestamp();
$content = $this->getContentObject( false ); # TODO: track content object?!
if ( $content === false ) {
@@ -1062,13 +1102,13 @@ class EditPage {
!$undorev->isDeleted( Revision::DELETED_TEXT ) &&
!$oldrev->isDeleted( Revision::DELETED_TEXT )
) {
- $content = $this->mArticle->getUndoContent( $undorev, $oldrev );
+ $content = $this->page->getUndoContent( $undorev, $oldrev );
if ( $content === false ) {
# Warn the user that something went wrong
$undoMsg = 'failure';
} else {
- $oldContent = $this->mArticle->getPage()->getContent( Revision::RAW );
+ $oldContent = $this->page->getContent( Revision::RAW );
$popts = ParserOptions::newFromUserAndLang( $wgUser, $wgContLang );
$newContent = $content->preSaveTransform( $this->mTitle, $wgUser, $popts );
@@ -1162,6 +1202,26 @@ class EditPage {
return $content;
}
+ /**
+ * Get the edit's parent revision ID
+ *
+ * The "parent" revision is the ancestor that should be recorded in this
+ * page's revision history. It is either the revision ID of the in-memory
+ * article content, or in the case of a 3-way merge in order to rebase
+ * across a recoverable edit conflict, the ID of the newer revision to
+ * which we have rebased this page.
+ *
+ * @since 1.27
+ * @return int Revision ID
+ */
+ public function getParentRevId() {
+ if ( $this->parentRevId ) {
+ return $this->parentRevId;
+ } else {
+ return $this->mArticle->getRevIdFetched();
+ }
+ }
+
/**
* Get the current content of the page. This is basically similar to
* WikiPage::getContent( Revision::RAW ) except that when the page doesn't exist an empty
@@ -1171,7 +1231,7 @@ class EditPage {
* @return Content
*/
protected function getCurrentContent() {
- $rev = $this->mArticle->getRevision();
+ $rev = $this->page->getRevision();
$content = $rev ? $rev->getContent( Revision::RAW ) : null;
if ( $content === false || $content === null ) {
@@ -1301,7 +1361,7 @@ class EditPage {
* @param int $statusValue The status value (to check for new article status)
*/
protected function setPostEditCookie( $statusValue ) {
- $revisionId = $this->mArticle->getLatest();
+ $revisionId = $this->page->getLatest();
$postEditKey = self::POST_EDIT_COOKIE_KEY_PREFIX . $revisionId;
$val = 'saved';
@@ -1724,8 +1784,8 @@ class EditPage {
# Load the page data from the master. If anything changes in the meantime,
# we detect it by using page_latest like a token in a 1 try compare-and-swap.
- $this->mArticle->loadPageData( 'fromdbmaster' );
- $new = !$this->mArticle->exists();
+ $this->page->loadPageData( 'fromdbmaster' );
+ $new = !$this->page->exists();
if ( $new ) {
// Late check for create permission, just in case *PARANOIA*
@@ -1777,19 +1837,19 @@ class EditPage {
# Article exists. Check for edit conflict.
- $this->mArticle->clear(); # Force reload of dates, etc.
- $timestamp = $this->mArticle->getTimestamp();
+ $this->page->clear(); # Force reload of dates, etc.
+ $timestamp = $this->page->getTimestamp();
wfDebug( "timestamp: {$timestamp}, edittime: {$this->edittime}\n" );
if ( $timestamp != $this->edittime ) {
$this->isConflict = true;
if ( $this->section == 'new' ) {
- if ( $this->mArticle->getUserText() == $wgUser->getName() &&
- $this->mArticle->getComment() == $this->newSectionSummary()
+ if ( $this->page->getUserText() == $wgUser->getName() &&
+ $this->page->getComment() == $this->newSectionSummary()
) {
// Probably a duplicate submission of a new comment.
- // This can happen when squid resends a request after
+ // This can happen when CDN resends a request after
// a timeout but the first one actually went through.
wfDebug( __METHOD__
. ": duplicate new section submission; trigger edit conflict!\n" );
@@ -1824,7 +1884,7 @@ class EditPage {
. ": conflict! getting section '{$this->section}' for time '{$this->edittime}'"
. " (article time '{$timestamp}')\n" );
- $content = $this->mArticle->replaceSectionContent(
+ $content = $this->page->replaceSectionContent(
$this->section,
$textbox_content,
$sectionTitle,
@@ -1832,7 +1892,7 @@ class EditPage {
);
} else {
wfDebug( __METHOD__ . ": getting section '{$this->section}'\n" );
- $content = $this->mArticle->replaceSectionContent(
+ $content = $this->page->replaceSectionContent(
$this->section,
$textbox_content,
$sectionTitle
@@ -1947,7 +2007,7 @@ class EditPage {
( ( $this->minoredit && !$this->isNew ) ? EDIT_MINOR : 0 ) |
( $bot ? EDIT_FORCE_BOT : 0 );
- $doEditStatus = $this->mArticle->doEditContent(
+ $doEditStatus = $this->page->doEditContent(
$content,
$this->summary,
$flags,
@@ -2005,7 +2065,7 @@ class EditPage {
}
/**
- * @param Title $title
+ * @param User $user
* @param string $oldModel
* @param string $newModel
* @param string $reason
@@ -2023,26 +2083,26 @@ class EditPage {
$log->publish( $logid );
}
-
/**
* Register the change of watch status
*/
protected function updateWatchlist() {
global $wgUser;
- if ( $wgUser->isLoggedIn()
- && $this->watchthis != $wgUser->isWatched( $this->mTitle, WatchedItem::IGNORE_USER_RIGHTS )
- ) {
- $fname = __METHOD__;
- $title = $this->mTitle;
- $watch = $this->watchthis;
-
- // Do this in its own transaction to reduce contention...
- $dbw = wfGetDB( DB_MASTER );
- $dbw->onTransactionIdle( function () use ( $dbw, $title, $watch, $wgUser, $fname ) {
- WatchAction::doWatchOrUnwatch( $watch, $title, $wgUser );
- } );
+ if ( !$wgUser->isLoggedIn() ) {
+ return;
}
+
+ $user = $wgUser;
+ $title = $this->mTitle;
+ $watch = $this->watchthis;
+ // Do this in its own transaction to reduce contention...
+ DeferredUpdates::addCallableUpdate( function () use ( $user, $title, $watch ) {
+ if ( $watch == $user->isWatched( $title, WatchedItem::IGNORE_USER_RIGHTS ) ) {
+ return; // nothing to change
+ }
+ WatchAction::doWatchOrUnwatch( $watch, $title, $user );
+ } );
}
/**
@@ -2082,6 +2142,8 @@ class EditPage {
if ( $result ) {
$editContent = $result;
+ // Update parentRevId to what we just merged.
+ $this->parentRevId = $currentRevision->getId();
return true;
}
@@ -2089,7 +2151,9 @@ class EditPage {
}
/**
- * @return Revision
+ * @note: this method is very poorly named. If the user opened the form with ?oldid=X,
+ * one might think of X as the "base revision", which is NOT what this returns.
+ * @return Revision Current version when the edit was started
*/
function getBaseRevision() {
if ( !$this->mBaseRevision ) {
@@ -2542,8 +2606,7 @@ class EditPage {
$wgOut->addHTML( Html::hidden( 'wpAutoSummary', $autosumm ) );
$wgOut->addHTML( Html::hidden( 'oldid', $this->oldid ) );
- $wgOut->addHTML( Html::hidden( 'parentRevId',
- $this->parentRevId ?: $this->mArticle->getRevIdFetched() ) );
+ $wgOut->addHTML( Html::hidden( 'parentRevId', $this->getParentRevId() ) );
$wgOut->addHTML( Html::hidden( 'format', $this->contentFormat ) );
$wgOut->addHTML( Html::hidden( 'model', $this->contentModel ) );
@@ -2594,7 +2657,7 @@ class EditPage {
Linker::formatTemplates( $this->getTemplates(), $this->preview, $this->section != '' ) ) );
$wgOut->addHTML( Html::rawElement( 'div', array( 'class' => 'hiddencats' ),
- Linker::formatHiddenCategories( $this->mArticle->getHiddenCategories() ) ) );
+ Linker::formatHiddenCategories( $this->page->getHiddenCategories() ) ) );
$wgOut->addHTML( Html::rawElement( 'div', array( 'class' => 'limitreport' ),
self::getPreviewLimitReport( $this->mParserOutput ) ) );
@@ -2671,7 +2734,7 @@ class EditPage {
if ( $this->isConflict ) {
$wgOut->wrapWikiMsg( "\n$1\n
", 'explainconflict' );
- $this->edittime = $this->mArticle->getTimestamp();
+ $this->edittime = $this->page->getTimestamp();
} else {
if ( $this->section != '' && !$this->isSectionEditSupported() ) {
// We use $this->section to much before this and getVal('wgSection') directly in other places
@@ -2812,6 +2875,7 @@ class EditPage {
}
if ( $this->mTitle->isCascadeProtected() ) {
# Is this page under cascading protection from some source pages?
+ /** @var Title[] $cascadeSources */
list( $cascadeSources, /* $restrictions */ ) = $this->mTitle->getCascadeProtectionSources();
$notice = "\n$1\n";
$cascadeSourcesCount = count( $cascadeSources );
@@ -3181,7 +3245,7 @@ HTML
$textboxContent = $this->toEditContent( $this->textbox1 );
- $newContent = $this->mArticle->replaceSectionContent(
+ $newContent = $this->page->replaceSectionContent(
$this->section, $textboxContent,
$this->summary, $this->edittime );
@@ -3571,7 +3635,7 @@ HTML
$note = wfMessage( 'previewnote' )->plain() . ' ' . $continueEditing;
}
- $parserOptions = $this->mArticle->makeParserOptions( $this->mArticle->getContext() );
+ $parserOptions = $this->page->makeParserOptions( $this->mArticle->getContext() );
$parserOptions->setIsPreview( true );
$parserOptions->setIsSectionPreview( !is_null( $this->section ) && $this->section !== '' );
@@ -3643,6 +3707,8 @@ HTML
if ( count( $parserOutput->getWarnings() ) ) {
$note .= "\n\n" . implode( "\n\n", $parserOutput->getWarnings() );
}
+
+ ScopedCallback::consume( $scopedCallback );
} catch ( MWContentSerializationException $ex ) {
$m = wfMessage(
'content-failed-to-parse',