EditPage cleanup - parser errors, etc
Cleaned up EditPage, removing and fixing comments etc. The most prominent changes are: * improved handing for parse errors * improved handling for image redirects * better readability because one huge try/catch block was removed Change-Id: Ie33720922eb05dda89a22ca1f5f0cba4b1d31129
This commit is contained in:
parent
96f7db3f7b
commit
a1f145591b
2 changed files with 290 additions and 281 deletions
|
|
@ -691,7 +691,7 @@ class EditPage {
|
|||
} else {
|
||||
# Not a posted form? Start with nothing.
|
||||
wfDebug( __METHOD__ . ": Not a posted form.\n" );
|
||||
$this->textbox1 = ''; #FIXME: track content object
|
||||
$this->textbox1 = '';
|
||||
$this->summary = '';
|
||||
$this->sectiontitle = '';
|
||||
$this->edittime = '';
|
||||
|
|
@ -799,8 +799,9 @@ class EditPage {
|
|||
* @return mixed string on success, $def_text for invalid sections
|
||||
* @private
|
||||
* @deprecated since 1.WD
|
||||
* @todo: deprecated, replace usage everywhere
|
||||
*/
|
||||
function getContent( $def_text = false ) { #FIXME: deprecated, replace usage!
|
||||
function getContent( $def_text = false ) {
|
||||
wfDeprecated( __METHOD__, '1.WD' );
|
||||
|
||||
if ( $def_text !== null && $def_text !== false && $def_text !== '' ) {
|
||||
|
|
@ -811,10 +812,11 @@ class EditPage {
|
|||
|
||||
$content = $this->getContentObject( $def_content );
|
||||
|
||||
return $content->serialize( $this->content_format ); #XXX: really use serialized form? use ContentHandler::getContentText() instead?
|
||||
// Note: EditPage should only be used with text based content anyway.
|
||||
return $content->serialize( $this->content_format );
|
||||
}
|
||||
|
||||
private function getContentObject( $def_content = null ) { #FIXME: use this!
|
||||
private function getContentObject( $def_content = null ) {
|
||||
global $wgOut, $wgRequest;
|
||||
|
||||
wfProfileIn( __METHOD__ );
|
||||
|
|
@ -959,7 +961,7 @@ class EditPage {
|
|||
|
||||
return $handler->makeEmptyContent();
|
||||
} else {
|
||||
#FIXME: nasty side-effect!
|
||||
# nasty side-effect, but needed for consistency
|
||||
$this->content_model = $rev->getContentModel();
|
||||
$this->content_format = $rev->getContentFormat();
|
||||
|
||||
|
|
@ -1008,7 +1010,6 @@ class EditPage {
|
|||
|
||||
$content = $this->getPreloadedContent( $preload );
|
||||
$text = $content->serialize( $this->content_format );
|
||||
#XXX: really use serialized form? use ContentHandler::getContentText() instead?!
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
|
@ -1105,8 +1106,7 @@ class EditPage {
|
|||
|
||||
case self::AS_PARSE_ERROR:
|
||||
$wgOut->addWikiText( '<div class="error">' . $status->getWikiText() . '</div>');
|
||||
#FIXME: cause editform to be shown again, not just an error!
|
||||
return false;
|
||||
return true;
|
||||
|
||||
case self::AS_SUCCESS_NEW_ARTICLE:
|
||||
$query = $resultDetails['redirect'] ? 'redirect=no' : '';
|
||||
|
|
@ -1200,9 +1200,20 @@ class EditPage {
|
|||
return $status;
|
||||
}
|
||||
|
||||
try {
|
||||
# Construct Content object
|
||||
$textbox_content = ContentHandler::makeContent( $this->textbox1, $this->getTitle(),
|
||||
$this->content_model, $this->content_format );
|
||||
} catch (MWContentSerializationException $ex) {
|
||||
$status->fatal( 'content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
|
||||
$status->value = self::AS_PARSE_ERROR;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
|
||||
# Check image redirect
|
||||
if ( $this->mTitle->getNamespace() == NS_FILE &&
|
||||
Title::newFromRedirect( $this->textbox1 ) instanceof Title && #FIXME: use content handler to check for redirect
|
||||
$textbox_content->isRedirect() &&
|
||||
!$wgUser->isAllowed( 'upload' ) ) {
|
||||
$code = $wgUser->isAnon() ? self::AS_IMAGE_REDIRECT_ANON : self::AS_IMAGE_REDIRECT_LOGGED;
|
||||
$status->setResult( false, $code );
|
||||
|
|
@ -1312,291 +1323,278 @@ class EditPage {
|
|||
$this->mArticle->loadPageData( 'fromdbmaster' );
|
||||
$new = !$this->mArticle->exists();
|
||||
|
||||
try {
|
||||
if ( $new ) {
|
||||
// Late check for create permission, just in case *PARANOIA*
|
||||
if ( !$this->mTitle->userCan( 'create' ) ) {
|
||||
$status->fatal( 'nocreatetext' );
|
||||
$status->value = self::AS_NO_CREATE_PERMISSION;
|
||||
wfDebug( __METHOD__ . ": no create permission\n" );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
if ( $new ) {
|
||||
// Late check for create permission, just in case *PARANOIA*
|
||||
if ( !$this->mTitle->userCan( 'create' ) ) {
|
||||
$status->fatal( 'nocreatetext' );
|
||||
$status->value = self::AS_NO_CREATE_PERMISSION;
|
||||
wfDebug( __METHOD__ . ": no create permission\n" );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
|
||||
# Don't save a new article if it's blank.
|
||||
if ( $this->textbox1 == '' ) {
|
||||
$status->setResult( false, self::AS_BLANK_ARTICLE );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
# Don't save a new article if it's blank.
|
||||
if ( $this->textbox1 == '' ) {
|
||||
$status->setResult( false, self::AS_BLANK_ARTICLE );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
|
||||
// Run post-section-merge edit filter
|
||||
if ( !wfRunHooks( 'EditFilterMerged', array( $this, $this->textbox1, &$this->hookError, $this->summary ) ) ) {
|
||||
# Error messages etc. could be handled within the hook...
|
||||
$status->fatal( 'hookaborted' );
|
||||
$status->value = self::AS_HOOK_ERROR;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
} elseif ( $this->hookError != '' ) {
|
||||
# ...or the hook could be expecting us to produce an error
|
||||
$status->fatal( 'hookaborted' );
|
||||
$status->value = self::AS_HOOK_ERROR_EXPECTED;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
// Run post-section-merge edit filter
|
||||
if ( !wfRunHooks( 'EditFilterMerged', array( $this, $this->textbox1, &$this->hookError, $this->summary ) ) ) {
|
||||
# Error messages etc. could be handled within the hook...
|
||||
$status->fatal( 'hookaborted' );
|
||||
$status->value = self::AS_HOOK_ERROR;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
} elseif ( $this->hookError != '' ) {
|
||||
# ...or the hook could be expecting us to produce an error
|
||||
$status->fatal( 'hookaborted' );
|
||||
$status->value = self::AS_HOOK_ERROR_EXPECTED;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
|
||||
$content = ContentHandler::makeContent( $this->textbox1, $this->getTitle(),
|
||||
$this->content_model, $this->content_format );
|
||||
$content = $textbox_content;
|
||||
|
||||
$result['sectionanchor'] = '';
|
||||
if ( $this->section == 'new' ) {
|
||||
if ( $this->sectiontitle !== '' ) {
|
||||
// Insert the section title above the content.
|
||||
$content = $content->addSectionHeader( $this->sectiontitle );
|
||||
|
||||
// Jump to the new section
|
||||
$result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
|
||||
|
||||
// If no edit summary was specified, create one automatically from the section
|
||||
// title and have it link to the new section. Otherwise, respect the summary as
|
||||
// passed.
|
||||
if ( $this->summary === '' ) {
|
||||
$cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
|
||||
$this->summary = wfMessage( 'newsectionsummary', $cleanSectionTitle )->inContentLanguage()->text() ;
|
||||
}
|
||||
} elseif ( $this->summary !== '' ) {
|
||||
// Insert the section title above the content.
|
||||
$content = $content->addSectionHeader( $this->sectiontitle );
|
||||
|
||||
// Jump to the new section
|
||||
$result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
|
||||
|
||||
// Create a link to the new section from the edit summary.
|
||||
$cleanSummary = $wgParser->stripSectionName( $this->summary );
|
||||
$this->summary = wfMessage( 'newsectionsummary', $cleanSummary )->inContentLanguage()->text() ;
|
||||
}
|
||||
}
|
||||
|
||||
$status->value = self::AS_SUCCESS_NEW_ARTICLE;
|
||||
|
||||
} else { # not $new
|
||||
|
||||
# Article exists. Check for edit conflict.
|
||||
|
||||
$this->mArticle->clear(); # Force reload of dates, etc.
|
||||
$timestamp = $this->mArticle->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->summary ) {
|
||||
// Probably a duplicate submission of a new comment.
|
||||
// This can happen when squid resends a request after
|
||||
// a timeout but the first one actually went through.
|
||||
wfDebug( __METHOD__ . ": duplicate new section submission; trigger edit conflict!\n" );
|
||||
} else {
|
||||
// New comment; suppress conflict.
|
||||
$this->isConflict = false;
|
||||
wfDebug( __METHOD__ . ": conflict suppressed; new section\n" );
|
||||
}
|
||||
} elseif ( $this->section == '' && $this->userWasLastToEdit( $wgUser->getId(), $this->edittime ) ) {
|
||||
# Suppress edit conflict with self, except for section edits where merging is required.
|
||||
wfDebug( __METHOD__ . ": Suppressing edit conflict, same user.\n" );
|
||||
$this->isConflict = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If sectiontitle is set, use it, otherwise use the summary as the section title (for
|
||||
// backwards compatibility with old forms/bots).
|
||||
$result['sectionanchor'] = '';
|
||||
if ( $this->section == 'new' ) {
|
||||
if ( $this->sectiontitle !== '' ) {
|
||||
$sectionTitle = $this->sectiontitle;
|
||||
} else {
|
||||
$sectionTitle = $this->summary;
|
||||
}
|
||||
// Insert the section title above the content.
|
||||
$content = $content->addSectionHeader( $this->sectiontitle );
|
||||
|
||||
$textbox_content = ContentHandler::makeContent( $this->textbox1, $this->getTitle(),
|
||||
$this->content_model, $this->content_format );
|
||||
$content = null;
|
||||
// Jump to the new section
|
||||
$result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
|
||||
|
||||
if ( $this->isConflict ) {
|
||||
wfDebug( __METHOD__ . ": conflict! getting section '{$this->section}' for time '{$this->edittime}'"
|
||||
. " (article time '{$timestamp}')\n" );
|
||||
|
||||
$content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content,
|
||||
$sectionTitle, $this->edittime );
|
||||
} else {
|
||||
wfDebug( __METHOD__ . ": getting section '{$this->section}'\n" );
|
||||
$content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle );
|
||||
}
|
||||
|
||||
if ( is_null( $content ) ) {
|
||||
wfDebug( __METHOD__ . ": activating conflict; section replace failed.\n" );
|
||||
$this->isConflict = true;
|
||||
$content = $textbox_content; // do not try to merge here!
|
||||
} elseif ( $this->isConflict ) {
|
||||
# Attempt merge
|
||||
if ( $this->mergeChangesIntoContent( $textbox_content ) ) {
|
||||
// Successful merge! Maybe we should tell the user the good news?
|
||||
$this->isConflict = false;
|
||||
$content = $textbox_content;
|
||||
wfDebug( __METHOD__ . ": Suppressing edit conflict, successful merge.\n" );
|
||||
} else {
|
||||
$this->section = '';
|
||||
#$this->textbox1 = $text; #redundant, nothing to do here?
|
||||
wfDebug( __METHOD__ . ": Keeping edit conflict, failed merge.\n" );
|
||||
// If no edit summary was specified, create one automatically from the section
|
||||
// title and have it link to the new section. Otherwise, respect the summary as
|
||||
// passed.
|
||||
if ( $this->summary === '' ) {
|
||||
$cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
|
||||
$this->summary = wfMessage( 'newsectionsummary', $cleanSectionTitle )->inContentLanguage()->text() ;
|
||||
}
|
||||
} elseif ( $this->summary !== '' ) {
|
||||
// Insert the section title above the content.
|
||||
$content = $content->addSectionHeader( $this->sectiontitle );
|
||||
|
||||
// Jump to the new section
|
||||
$result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
|
||||
|
||||
// Create a link to the new section from the edit summary.
|
||||
$cleanSummary = $wgParser->stripSectionName( $this->summary );
|
||||
$this->summary = wfMessage( 'newsectionsummary', $cleanSummary )->inContentLanguage()->text() ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->isConflict ) {
|
||||
$status->setResult( false, self::AS_CONFLICT_DETECTED );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
$status->value = self::AS_SUCCESS_NEW_ARTICLE;
|
||||
|
||||
// Run post-section-merge edit filter
|
||||
$hook_args = array( $this, $content, &$this->hookError, $this->summary );
|
||||
} else { # not $new
|
||||
|
||||
if ( !ContentHandler::runLegacyHooks( 'EditFilterMerged', $hook_args )
|
||||
|| !wfRunHooks( 'EditFilterMergedContent', $hook_args ) ) {
|
||||
# Error messages etc. could be handled within the hook...
|
||||
$status->fatal( 'hookaborted' );
|
||||
$status->value = self::AS_HOOK_ERROR;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
} elseif ( $this->hookError != '' ) {
|
||||
# ...or the hook could be expecting us to produce an error
|
||||
$status->fatal( 'hookaborted' );
|
||||
$status->value = self::AS_HOOK_ERROR_EXPECTED;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
# Article exists. Check for edit conflict.
|
||||
|
||||
$content = ContentHandler::makeContent( $this->textbox1, $this->getTitle(),
|
||||
$this->content_model, $this->content_format );
|
||||
$this->mArticle->clear(); # Force reload of dates, etc.
|
||||
$timestamp = $this->mArticle->getTimestamp();
|
||||
|
||||
# Handle the user preference to force summaries here, but not for null edits
|
||||
if ( $this->section != 'new' && !$this->allowBlankSummary
|
||||
&& !$content->equals( $this->getOriginalContent() )
|
||||
&& !$content->isRedirect() ) # check if it's not a redirect
|
||||
{
|
||||
if ( md5( $this->summary ) == $this->autoSumm ) {
|
||||
$this->missingSummary = true;
|
||||
$status->fatal( 'missingsummary' );
|
||||
$status->value = self::AS_SUMMARY_NEEDED;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
wfDebug( "timestamp: {$timestamp}, edittime: {$this->edittime}\n" );
|
||||
|
||||
# And a similar thing for new sections
|
||||
if ( $this->section == 'new' && !$this->allowBlankSummary ) {
|
||||
if ( trim( $this->summary ) == '' ) {
|
||||
$this->missingSummary = true;
|
||||
$status->fatal( 'missingsummary' ); // or 'missingcommentheader' if $section == 'new'. Blegh
|
||||
$status->value = self::AS_SUMMARY_NEEDED;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
|
||||
# All's well
|
||||
wfProfileIn( __METHOD__ . '-sectionanchor' );
|
||||
$sectionanchor = '';
|
||||
if ( $timestamp != $this->edittime ) {
|
||||
$this->isConflict = true;
|
||||
if ( $this->section == 'new' ) {
|
||||
if ( $this->textbox1 == '' ) {
|
||||
$this->missingComment = true;
|
||||
$status->fatal( 'missingcommenttext' );
|
||||
$status->value = self::AS_TEXTBOX_EMPTY;
|
||||
wfProfileOut( __METHOD__ . '-sectionanchor' );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
if ( $this->sectiontitle !== '' ) {
|
||||
$sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
|
||||
// If no edit summary was specified, create one automatically from the section
|
||||
// title and have it link to the new section. Otherwise, respect the summary as
|
||||
// passed.
|
||||
if ( $this->summary === '' ) {
|
||||
$cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
|
||||
$this->summary = wfMessage( 'newsectionsummary', $cleanSectionTitle )->inContentLanguage()->text() ;
|
||||
}
|
||||
} elseif ( $this->summary !== '' ) {
|
||||
$sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
|
||||
# This is a new section, so create a link to the new section
|
||||
# in the revision summary.
|
||||
$cleanSummary = $wgParser->stripSectionName( $this->summary );
|
||||
$this->summary = wfMessage( 'newsectionsummary', $cleanSummary )->inContentLanguage()->text() ;
|
||||
}
|
||||
} elseif ( $this->section != '' ) {
|
||||
# Try to get a section anchor from the section source, redirect to edited section if header found
|
||||
# XXX: might be better to integrate this into Article::replaceSection
|
||||
# for duplicate heading checking and maybe parsing
|
||||
$hasmatch = preg_match( "/^ *([=]{1,6})(.*?)(\\1) *\\n/i", $this->textbox1, $matches );
|
||||
# we can't deal with anchors, includes, html etc in the header for now,
|
||||
# headline would need to be parsed to improve this
|
||||
if ( $hasmatch && strlen( $matches[2] ) > 0 ) {
|
||||
$sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $matches[2] );
|
||||
if ( $this->mArticle->getUserText() == $wgUser->getName() &&
|
||||
$this->mArticle->getComment() == $this->summary ) {
|
||||
// Probably a duplicate submission of a new comment.
|
||||
// This can happen when squid resends a request after
|
||||
// a timeout but the first one actually went through.
|
||||
wfDebug( __METHOD__ . ": duplicate new section submission; trigger edit conflict!\n" );
|
||||
} else {
|
||||
// New comment; suppress conflict.
|
||||
$this->isConflict = false;
|
||||
wfDebug( __METHOD__ . ": conflict suppressed; new section\n" );
|
||||
}
|
||||
} elseif ( $this->section == '' && $this->userWasLastToEdit( $wgUser->getId(), $this->edittime ) ) {
|
||||
# Suppress edit conflict with self, except for section edits where merging is required.
|
||||
wfDebug( __METHOD__ . ": Suppressing edit conflict, same user.\n" );
|
||||
$this->isConflict = false;
|
||||
}
|
||||
$result['sectionanchor'] = $sectionanchor;
|
||||
wfProfileOut( __METHOD__ . '-sectionanchor' );
|
||||
|
||||
// Save errors may fall down to the edit form, but we've now
|
||||
// merged the section into full text. Clear the section field
|
||||
// so that later submission of conflict forms won't try to
|
||||
// replace that into a duplicated mess.
|
||||
$this->textbox1 = $content->serialize( $this->content_format );
|
||||
$this->section = '';
|
||||
|
||||
$status->value = self::AS_SUCCESS_UPDATE;
|
||||
}
|
||||
|
||||
// Check for length errors again now that the section is merged in
|
||||
$this->kblength = (int)( strlen( $content->serialize( $this->content_format ) ) / 1024 );
|
||||
if ( $this->kblength > $wgMaxArticleSize ) {
|
||||
$this->tooBig = true;
|
||||
$status->setResult( false, self::AS_MAX_ARTICLE_SIZE_EXCEEDED );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
|
||||
$flags = EDIT_DEFER_UPDATES | EDIT_AUTOSUMMARY |
|
||||
( $new ? EDIT_NEW : EDIT_UPDATE ) |
|
||||
( ( $this->minoredit && !$this->isNew ) ? EDIT_MINOR : 0 ) |
|
||||
( $bot ? EDIT_FORCE_BOT : 0 );
|
||||
|
||||
$doEditStatus = $this->mArticle->doEditContent( $content, $this->summary, $flags,
|
||||
false, null, $this->content_format );
|
||||
|
||||
if ( $doEditStatus->isOK() ) {
|
||||
$result['redirect'] = $content->isRedirect();
|
||||
$this->commitWatch();
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
// If sectiontitle is set, use it, otherwise use the summary as the section title (for
|
||||
// backwards compatibility with old forms/bots).
|
||||
if ( $this->sectiontitle !== '' ) {
|
||||
$sectionTitle = $this->sectiontitle;
|
||||
} else {
|
||||
// Failure from doEdit()
|
||||
// Show the edit conflict page for certain recognized errors from doEdit(),
|
||||
// but don't show it for errors from extension hooks
|
||||
$errors = $doEditStatus->getErrorsArray();
|
||||
if ( in_array( $errors[0][0], array( 'edit-gone-missing', 'edit-conflict',
|
||||
'edit-already-exists' ) ) )
|
||||
{
|
||||
$this->isConflict = true;
|
||||
// Destroys data doEdit() put in $status->value but who cares
|
||||
$doEditStatus->value = self::AS_END;
|
||||
}
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $doEditStatus;
|
||||
$sectionTitle = $this->summary;
|
||||
}
|
||||
} catch (MWContentSerializationException $ex) {
|
||||
$status->fatal( 'content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
|
||||
$status->value = self::AS_PARSE_ERROR;
|
||||
|
||||
$content = null;
|
||||
|
||||
if ( $this->isConflict ) {
|
||||
wfDebug( __METHOD__ . ": conflict! getting section '{$this->section}' for time '{$this->edittime}'"
|
||||
. " (article time '{$timestamp}')\n" );
|
||||
|
||||
$content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content,
|
||||
$sectionTitle, $this->edittime );
|
||||
} else {
|
||||
wfDebug( __METHOD__ . ": getting section '{$this->section}'\n" );
|
||||
$content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle );
|
||||
}
|
||||
|
||||
if ( is_null( $content ) ) {
|
||||
wfDebug( __METHOD__ . ": activating conflict; section replace failed.\n" );
|
||||
$this->isConflict = true;
|
||||
$content = $textbox_content; // do not try to merge here!
|
||||
} elseif ( $this->isConflict ) {
|
||||
# Attempt merge
|
||||
if ( $this->mergeChangesIntoContent( $textbox_content ) ) {
|
||||
// Successful merge! Maybe we should tell the user the good news?
|
||||
$this->isConflict = false;
|
||||
$content = $textbox_content;
|
||||
wfDebug( __METHOD__ . ": Suppressing edit conflict, successful merge.\n" );
|
||||
} else {
|
||||
$this->section = '';
|
||||
#$this->textbox1 = $text; #redundant, nothing to do here?
|
||||
wfDebug( __METHOD__ . ": Keeping edit conflict, failed merge.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->isConflict ) {
|
||||
$status->setResult( false, self::AS_CONFLICT_DETECTED );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
|
||||
// Run post-section-merge edit filter
|
||||
$hook_args = array( $this, $content, &$this->hookError, $this->summary );
|
||||
|
||||
if ( !ContentHandler::runLegacyHooks( 'EditFilterMerged', $hook_args )
|
||||
|| !wfRunHooks( 'EditFilterMergedContent', $hook_args ) ) {
|
||||
# Error messages etc. could be handled within the hook...
|
||||
$status->fatal( 'hookaborted' );
|
||||
$status->value = self::AS_HOOK_ERROR;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
} elseif ( $this->hookError != '' ) {
|
||||
# ...or the hook could be expecting us to produce an error
|
||||
$status->fatal( 'hookaborted' );
|
||||
$status->value = self::AS_HOOK_ERROR_EXPECTED;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
|
||||
# Handle the user preference to force summaries here, but not for null edits
|
||||
if ( $this->section != 'new' && !$this->allowBlankSummary
|
||||
&& !$content->equals( $this->getOriginalContent() )
|
||||
&& !$content->isRedirect() ) # check if it's not a redirect
|
||||
{
|
||||
if ( md5( $this->summary ) == $this->autoSumm ) {
|
||||
$this->missingSummary = true;
|
||||
$status->fatal( 'missingsummary' );
|
||||
$status->value = self::AS_SUMMARY_NEEDED;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
|
||||
# And a similar thing for new sections
|
||||
if ( $this->section == 'new' && !$this->allowBlankSummary ) {
|
||||
if ( trim( $this->summary ) == '' ) {
|
||||
$this->missingSummary = true;
|
||||
$status->fatal( 'missingsummary' ); // or 'missingcommentheader' if $section == 'new'. Blegh
|
||||
$status->value = self::AS_SUMMARY_NEEDED;
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
|
||||
# All's well
|
||||
wfProfileIn( __METHOD__ . '-sectionanchor' );
|
||||
$sectionanchor = '';
|
||||
if ( $this->section == 'new' ) {
|
||||
if ( $this->textbox1 == '' ) {
|
||||
$this->missingComment = true;
|
||||
$status->fatal( 'missingcommenttext' );
|
||||
$status->value = self::AS_TEXTBOX_EMPTY;
|
||||
wfProfileOut( __METHOD__ . '-sectionanchor' );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
if ( $this->sectiontitle !== '' ) {
|
||||
$sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
|
||||
// If no edit summary was specified, create one automatically from the section
|
||||
// title and have it link to the new section. Otherwise, respect the summary as
|
||||
// passed.
|
||||
if ( $this->summary === '' ) {
|
||||
$cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
|
||||
$this->summary = wfMessage( 'newsectionsummary', $cleanSectionTitle )->inContentLanguage()->text() ;
|
||||
}
|
||||
} elseif ( $this->summary !== '' ) {
|
||||
$sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
|
||||
# This is a new section, so create a link to the new section
|
||||
# in the revision summary.
|
||||
$cleanSummary = $wgParser->stripSectionName( $this->summary );
|
||||
$this->summary = wfMessage( 'newsectionsummary', $cleanSummary )->inContentLanguage()->text() ;
|
||||
}
|
||||
} elseif ( $this->section != '' ) {
|
||||
# Try to get a section anchor from the section source, redirect to edited section if header found
|
||||
# XXX: might be better to integrate this into Article::replaceSection
|
||||
# for duplicate heading checking and maybe parsing
|
||||
$hasmatch = preg_match( "/^ *([=]{1,6})(.*?)(\\1) *\\n/i", $this->textbox1, $matches );
|
||||
# we can't deal with anchors, includes, html etc in the header for now,
|
||||
# headline would need to be parsed to improve this
|
||||
if ( $hasmatch && strlen( $matches[2] ) > 0 ) {
|
||||
$sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $matches[2] );
|
||||
}
|
||||
}
|
||||
$result['sectionanchor'] = $sectionanchor;
|
||||
wfProfileOut( __METHOD__ . '-sectionanchor' );
|
||||
|
||||
// Save errors may fall down to the edit form, but we've now
|
||||
// merged the section into full text. Clear the section field
|
||||
// so that later submission of conflict forms won't try to
|
||||
// replace that into a duplicated mess.
|
||||
$this->textbox1 = $content->serialize( $this->content_format );
|
||||
$this->section = '';
|
||||
|
||||
$status->value = self::AS_SUCCESS_UPDATE;
|
||||
}
|
||||
|
||||
// Check for length errors again now that the section is merged in
|
||||
$this->kblength = (int)( strlen( $content->serialize( $this->content_format ) ) / 1024 );
|
||||
if ( $this->kblength > $wgMaxArticleSize ) {
|
||||
$this->tooBig = true;
|
||||
$status->setResult( false, self::AS_MAX_ARTICLE_SIZE_EXCEEDED );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
}
|
||||
|
||||
$flags = EDIT_DEFER_UPDATES | EDIT_AUTOSUMMARY |
|
||||
( $new ? EDIT_NEW : EDIT_UPDATE ) |
|
||||
( ( $this->minoredit && !$this->isNew ) ? EDIT_MINOR : 0 ) |
|
||||
( $bot ? EDIT_FORCE_BOT : 0 );
|
||||
|
||||
$doEditStatus = $this->mArticle->doEditContent( $content, $this->summary, $flags,
|
||||
false, null, $this->content_format );
|
||||
|
||||
if ( $doEditStatus->isOK() ) {
|
||||
$result['redirect'] = $content->isRedirect();
|
||||
$this->commitWatch();
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
} else {
|
||||
// Failure from doEdit()
|
||||
// Show the edit conflict page for certain recognized errors from doEdit(),
|
||||
// but don't show it for errors from extension hooks
|
||||
$errors = $doEditStatus->getErrorsArray();
|
||||
if ( in_array( $errors[0][0], array( 'edit-gone-missing', 'edit-conflict',
|
||||
'edit-already-exists' ) ) )
|
||||
{
|
||||
$this->isConflict = true;
|
||||
// Destroys data doEdit() put in $status->value but who cares
|
||||
$doEditStatus->value = self::AS_END;
|
||||
}
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $doEditStatus;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1663,7 +1661,7 @@ class EditPage {
|
|||
$ok = $this->mergeChangesIntoContent( $editContent );
|
||||
|
||||
if ( $ok ) {
|
||||
$editText = $editContent->serialize( $this->content_format ); #XXX: really serialize?!
|
||||
$editText = $editContent->serialize( $this->content_format );
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
@ -1952,7 +1950,8 @@ class EditPage {
|
|||
}
|
||||
}
|
||||
|
||||
#FIXME: add EditForm plugin interface and use it here! #FIXME: search for textarea1 and textares2, and allow EditForm to override all uses.
|
||||
//@todo: add EditForm plugin interface and use it here!
|
||||
// search for textarea1 and textares2, and allow EditForm to override all uses.
|
||||
$wgOut->addHTML( Html::openElement( 'form', array( 'id' => self::EDITFORM_ID, 'name' => self::EDITFORM_ID,
|
||||
'method' => 'post', 'action' => $this->getActionURL( $this->getContextTitle() ),
|
||||
'enctype' => 'multipart/form-data' ) ) );
|
||||
|
|
@ -2069,7 +2068,13 @@ class EditPage {
|
|||
Linker::formatHiddenCategories( $this->mArticle->getHiddenCategories() ) ) );
|
||||
|
||||
if ( $this->isConflict ) {
|
||||
$this->showConflict();
|
||||
try {
|
||||
$this->showConflict();
|
||||
} catch ( MWContentSerializationException $ex ) {
|
||||
// this can't really happen, but be nice if it does.
|
||||
$msg = wfMessage( 'content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
|
||||
$wgOut->addWikiText( '<div class="error">' . $msg->text() . '</div>');
|
||||
}
|
||||
}
|
||||
|
||||
$wgOut->addHTML( $this->editFormTextBottom . "\n</form>\n" );
|
||||
|
|
@ -2143,7 +2148,7 @@ class EditPage {
|
|||
|
||||
if ( $this->section != '' && $this->section != 'new' ) {
|
||||
if ( !$this->summary && !$this->preview && !$this->diff ) {
|
||||
$sectionTitle = self::extractSectionTitle( $this->textbox1 );
|
||||
$sectionTitle = self::extractSectionTitle( $this->textbox1 ); //FIXME: use Content object
|
||||
if ( $sectionTitle !== false ) {
|
||||
$this->summary = "/* $sectionTitle */ ";
|
||||
}
|
||||
|
|
@ -2493,7 +2498,12 @@ HTML
|
|||
$wgOut->addHTML( '</div>' );
|
||||
|
||||
if ( $this->formtype == 'diff' ) {
|
||||
$this->showDiff();
|
||||
try {
|
||||
$this->showDiff();
|
||||
} catch ( MWContentSerializationException $ex ) {
|
||||
$msg = wfMessage( 'content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
|
||||
$wgOut->addWikiText( '<div class="error">' . $msg->text() . '</div>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2541,7 +2551,6 @@ HTML
|
|||
$oldContent = $this->getOriginalContent();
|
||||
}
|
||||
|
||||
#XXX: handle parse errors ?
|
||||
$textboxContent = ContentHandler::makeContent( $this->textbox1, $this->getTitle(),
|
||||
$this->content_model, $this->content_format );
|
||||
|
||||
|
|
@ -2661,8 +2670,8 @@ HTML
|
|||
if ( wfRunHooks( 'EditPageBeforeConflictDiff', array( &$this, &$wgOut ) ) ) {
|
||||
$wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" );
|
||||
|
||||
$content1 = ContentHandler::makeContent( $this->textbox1, $this->getTitle(), $this->content_model, $this->content_format ); #XXX: handle parse errors?
|
||||
$content2 = ContentHandler::makeContent( $this->textbox2, $this->getTitle(), $this->content_model, $this->content_format ); #XXX: handle parse errors?
|
||||
$content1 = ContentHandler::makeContent( $this->textbox1, $this->getTitle(), $this->content_model, $this->content_format );
|
||||
$content2 = ContentHandler::makeContent( $this->textbox2, $this->getTitle(), $this->content_model, $this->content_format );
|
||||
|
||||
$handler = ContentHandler::getForModelID( $this->content_model );
|
||||
$de = $handler->createDifferenceEngine( $this->mArticle->getContext() );
|
||||
|
|
@ -2859,11 +2868,10 @@ HTML
|
|||
|
||||
$parserOptions->enableLimitReport();
|
||||
|
||||
#XXX: For CSS/JS pages, we should have called the ShowRawCssJs hook here.
|
||||
# But it's now deprecated, so never mind
|
||||
$content = $content->preSaveTransform( $this->mTitle, $wgUser, $parserOptions );
|
||||
# For CSS/JS pages, we should have called the ShowRawCssJs hook here.
|
||||
# But it's now deprecated, so never mind
|
||||
|
||||
// TODO: might be a saner way to get a meaningfull context here?
|
||||
$content = $content->preSaveTransform( $this->mTitle, $wgUser, $parserOptions );
|
||||
$parserOutput = $content->getParserOutput( $this->getArticle()->getTitle(), null, $parserOptions );
|
||||
|
||||
$previewHTML = $parserOutput->getText();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @group Editing
|
||||
* @group API
|
||||
* @group Database
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue