From aaadcd0eb336689ac6991956cd11aaafe3c6269f Mon Sep 17 00:00:00 2001 From: Daniel Kinzler Date: Fri, 23 Mar 2012 15:18:20 +0000 Subject: [PATCH] EditPage to use Content objects --- includes/Content.php | 23 ++++++++ includes/ContentHandler.php | 19 ++++-- includes/EditPage.php | 95 +++++++++++++++++++++--------- includes/WikiPage.php | 2 +- includes/diff/DifferenceEngine.php | 25 +++++++- 5 files changed, 128 insertions(+), 36 deletions(-) diff --git a/includes/Content.php b/includes/Content.php index d7e43bbdc8..52e3b1e880 100644 --- a/includes/Content.php +++ b/includes/Content.php @@ -166,6 +166,17 @@ abstract class Content { return $this; } + /** + * Returns a new WikitextContent object with the given section heading prepended, if supported. + * The default implementation just returns this Content object unmodified, ignoring the section header. + * + * @param $header String + * @return Content + */ + public function addSectionHeader( $header ) { + return $this; + } + /** * Returns a Content object with preload transformations applied (or this object if no transformations apply). * @@ -388,6 +399,18 @@ class WikitextContent extends TextContent { return $newContent; } + /** + * Returns a new WikitextContent object with the given section heading prepended. + * + * @param $header String + * @return Content + */ + public function addSectionHeader( $header ) { + $text = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->sectiontitle ) . "\n\n" . $this->getNativeData(); + + return new WikitextContent( $text ); + } + /** * Returns a Content object with pre-save transformations applied (or this object if no transformations apply). * diff --git a/includes/ContentHandler.php b/includes/ContentHandler.php index 567c8d6db4..d784a7c3a5 100644 --- a/includes/ContentHandler.php +++ b/includes/ContentHandler.php @@ -209,12 +209,19 @@ abstract class ContentHandler { } /** - public function updatePage( $title, $obj ) { - } - **/ - - public function getDiffEngine( Article $article ) { #FIXME: change interface of diff engine? or accept content objects here=? - $de = new DifferenceEngine( $article->getContext() ); + * Factory + * @param $context IContextSource context to use, anything else will be ignored + * @param $old Integer old ID we want to show and diff with. + * @param $new String either 'prev' or 'next'. + * @param $rcid Integer ??? FIXME (default 0) + * @param $refreshCache boolean If set, refreshes the diff cache + * @param $unhide boolean If set, allow viewing deleted revs + */ + public function getDifferenceEngine( IContextSource $context, $old = 0, $new = 0, $rcid = 0, #FIMXE: use everywhere! + $refreshCache = false, $unhide = false ) { + + $de = new DifferenceEngine( $context, $old, $new, $rcid, $refreshCache, $unhide ); + return $de; } diff --git a/includes/EditPage.php b/includes/EditPage.php index 6f6a26faba..054c2efd1d 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -920,7 +920,7 @@ class EditPage { */ private function getCurrentContent() { $rev = $this->mArticle->getRevision(); - $content = $rev->getContentObject( Revision::RAW ); + $content = $rev->getContent( Revision::RAW ); if ( $content === false || $content === null ) { if ( !$this->content_model ) $this->content_model = $this->getTitle()->getContentModelName(); @@ -1309,10 +1309,9 @@ class EditPage { $result['sectionanchor'] = ''; if ( $this->section == 'new' ) { - .........FIXME............... if ( $this->sectiontitle !== '' ) { // Insert the section title above the content. - $T_E_X_T = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->sectiontitle ) . "\n\n" . $T_E_X_T; + $content = $content->addSectionHeader( $this->sectiontitle ); // Jump to the new section $result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle ); @@ -1326,7 +1325,7 @@ class EditPage { } } elseif ( $this->summary !== '' ) { // Insert the section title above the content. - $T_E_X_T = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->summary ) . "\n\n" . $T_E_X_T; + $content = $content->addSectionHeader( $this->sectiontitle ); // Jump to the new section $result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->summary ); @@ -1376,27 +1375,34 @@ class EditPage { } else { $sectionTitle = $this->summary; } - + + $textbox_content = ContentHandler::makeContent( $this->textbox1, $this->getTitle(), $this->content_model, $this->content_format ); + $content = false; + if ( $this->isConflict ) { wfDebug( __METHOD__ . ": conflict! getting section '$this->section' for time '$this->edittime' (article time '{$timestamp}')\n" ); - $T_E_X_T = $this->mArticle->replaceSection( $this->section, $this->textbox1, $sectionTitle, $this->edittime ); #FIXME: use Content object throughout, make edit form aware of content model and serialization format + + $content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle, $this->edittime ); } else { wfDebug( __METHOD__ . ": getting section '$this->section'\n" ); - $T_E_X_T = $this->mArticle->replaceSection( $this->section, $this->textbox1, $sectionTitle ); #FIXME: use Content object throughout, make edit form aware of content model and serialization format + + $content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle ); } - if ( is_null( $T_E_X_T ) ) { + + if ( is_null( $content ) ) { wfDebug( __METHOD__ . ": activating conflict; section replace failed.\n" ); $this->isConflict = true; - $T_E_X_T = $this->textbox1; // do not try to merge here! #FIXME: unserialize Content + $content = $textbox_content; // do not try to merge here! } elseif ( $this->isConflict ) { # Attempt merge - if ( $this->mergeChangesInto( $T_E_X_T ) ) { #FIXME: passe/receive Content object + if ( $this->mergeChangesIntoContent( $textbox_content ) ) { // Successful merge! Maybe we should tell the user the good news? + $content = $textbox_content; $this->isConflict = false; wfDebug( __METHOD__ . ": Suppressing edit conflict, successful merge.\n" ); } else { $this->section = ''; - $this->textbox1 = $T_E_X_T; + #$this->textbox1 = $text; #redundant, nothing to do here? wfDebug( __METHOD__ . ": Keeping edit conflict, failed merge.\n" ); } } @@ -1408,7 +1414,8 @@ class EditPage { } // Run post-section-merge edit filter - if ( !wfRunHooks( 'EditFilterMerged', array( $this, $T_E_X_T, &$this->hookError, $this->summary ) ) ) { + if ( !wfRunHooks( 'EditFilterMerged', array( $this, $content->serialize( $this->content_format ), &$this->hookError, $this->summary ) ) + || !wfRunHooks( 'EditFilterMergedContent', array( $this, $content, &$this->hookError, $this->summary ) ) ) { #FIXME: document new hook # Error messages etc. could be handled within the hook... $status->fatal( 'hookaborted' ); $status->value = self::AS_HOOK_ERROR; @@ -1424,8 +1431,8 @@ class EditPage { # Handle the user preference to force summaries here, but not for null edits if ( $this->section != 'new' && !$this->allowBlankSummary - && $this->getOriginalContent()... != $T_E_X_T - && !Title::newFromRedirect( $T_E_X_T ) ) # check if it's not a redirect + && !$content->equals( $this->getOriginalContent() ) + && !$content->isRedirect() ) # check if it's not a redirect { if ( md5( $this->summary ) == $this->autoSumm ) { $this->missingSummary = true; @@ -1493,14 +1500,14 @@ class EditPage { // 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 = $T_E_X_T; + $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( $T_E_X_T ) / 1024 ); + $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 ); @@ -1513,10 +1520,10 @@ class EditPage { ( ( $this->minoredit && !$this->isNew ) ? EDIT_MINOR : 0 ) | ( $bot ? EDIT_FORCE_BOT : 0 ); - $doEditStatus = $this->mArticle->doEdit( $T_E_X_T, $this->summary, $flags ); # FIXME: use WikiPage::doEditContent() + $doEditStatus = $this->mArticle->doEditContent( $content, $this->summary, $flags ); if ( $doEditStatus->isOK() ) { - $result['redirect'] = Title::newFromRedirect( $T_E_X_T ) !== null; + $result['redirect'] = $content->isRedirect(); $this->commitWatch(); wfProfileOut( __METHOD__ ); return $status; @@ -1581,8 +1588,34 @@ class EditPage { * @parma $editText string * * @return bool + * @deprecated since 1.20 */ - function mergeChangesInto( &$editText ){ + function mergeChangesInto( &$editText ){ + wfDebug( __METHOD__, "1.20" ); + + $handler = ContentHandler::getForModelName( $this->content_model ); + $editContent = $handler->unserialize( $editText, $this->content_format ); + + $ok = $this->mergeChangesIntoContent( $editContent ); + + if ( $ok ) { + $editText = $editContent->serialize( $this->content_format ); #XXX: really serialize?! + return true; + } else { + return false; + } + } + + /** + * @private + * @todo document + * + * @parma $editText string + * + * @return bool + * @since since 1.20 + */ + private function mergeChangesIntoContent( &$editContent ){ wfProfileIn( __METHOD__ ); $db = wfGetDB( DB_MASTER ); @@ -1604,11 +1637,11 @@ class EditPage { $currentContent = $currentRevision->getContent(); $handler = ContentHandler::getForModelName( $baseContent->getModelName() ); - $editContent = $handler->unserialize( $editText, $this->content_format ); #FIXME: supply serialization fomrat from edit form! $result = $handler->merge3( $baseContent, $editContent, $currentContent ); + if ( $result ) { - $editText = ContentHandler::getContentText($result, $this->content_format ); #FIXME: supply serialization fomrat from edit form! + $editContent = $result; wfProfileOut( __METHOD__ ); return true; } else { @@ -2421,8 +2454,9 @@ HTML $oldtitle = wfMsgExt( 'currentrev', array( 'parseinline' ) ); $newtitle = wfMsgExt( 'yourtext', array( 'parseinline' ) ); - $de = new DifferenceEngine( $this->mArticle->getContext() ); - $de->setText( $oldContent, $newContent ); #FIXME: content-based diff! + $de = $oldContent->getContentHandler()->getDifferenceEngine( $this->mArticle->getContext() ); + $de->setContent( $oldContent, $newContent ); + $difftext = $de->getDiff( $oldtitle, $newtitle ); $de->showDiffStyle(); } else { @@ -2512,8 +2546,12 @@ HTML if ( wfRunHooks( 'EditPageBeforeConflictDiff', array( &$this, &$wgOut ) ) ) { $wgOut->wrapWikiMsg( '

$1

', "yourdiff" ); - $de = new DifferenceEngine( $this->mArticle->getContext() ); - $de->setText( $this->textbox2, $this->textbox1 ); + $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::getForModelName( $this->content_model ); + $de = $handler->getDifferenceEngine( $this->mArticle->getContext() ); + $de->setContent( $content2, $content1 ); $de->showDiff( wfMsgExt( 'yourtext', 'parseinline' ), wfMsg( 'storedversion' ) ); $wgOut->wrapWikiMsg( '

$1

', "yourtext" ); @@ -3140,9 +3178,12 @@ HTML $wgOut->addHTML( '' ); $wgOut->wrapWikiMsg( '

$1

', "yourdiff" ); - $de = new DifferenceEngine( $this->mArticle->getContext() ); #FIXME: get from content handler! - $de->setText( $this->getCurrentText(), $this->textbox2 ); #FIXME: make Content based + $handler = ContentHandler::getForTitle( $this->getTitle() ); + $de = $handler->getDifferenceEngine( $this->mArticle->getContext() ); + + $content2 = ContentHandler::makeContent( $this->textbox2, $this->getTitle(), $this->content_model, $this->content_format ); + $de->setContent( $this->getCurrentContent(), $content2 ); $de->showDiff( wfMsg( "storedversion" ), wfMsgExt( 'yourtext', 'parseinline' ) ); diff --git a/includes/WikiPage.php b/includes/WikiPage.php index f880d05a90..d2b19b22d6 100644 --- a/includes/WikiPage.php +++ b/includes/WikiPage.php @@ -1142,7 +1142,7 @@ class WikiPage extends Page { return ContentHandler::getContentText( $newContent ); #XXX: unclear what will happen for non-wikitext! } - public function replaceSectionContent( $section, $sectionContent, $sectionTitle = '', $edittime = null ) { + public function replaceSectionContent( $section, Content $sectionContent, $sectionTitle = '', $edittime = null ) { wfProfileIn( __METHOD__ ); if ( strval( $section ) == '' ) { diff --git a/includes/diff/DifferenceEngine.php b/includes/diff/DifferenceEngine.php index ca5f9c9a7c..98b7d299d9 100644 --- a/includes/diff/DifferenceEngine.php +++ b/includes/diff/DifferenceEngine.php @@ -67,7 +67,7 @@ class DifferenceEngine extends ContextSource { * @param $refreshCache boolean If set, refreshes the diff cache * @param $unhide boolean If set, allow viewing deleted revs */ - function __construct( $context = null, $old = 0, $new = 0, $rcid = 0, + function __construct( $context = null, $old = 0, $new = 0, $rcid = 0, # FIXME: use Contenthandler::getDifferenceEngine everywhere! $refreshCache = false, $unhide = false ) { if ( $context instanceof IContextSource ) { @@ -925,14 +925,35 @@ class DifferenceEngine extends ContextSource { /** * Use specified text instead of loading from the database + * @deprecated since 1.20 */ - function setText( $oldText, $newText ) { #FIXME: deprecate, use Content objects instead! + function setText( $oldText, $newText ) { + wfDeprecated( __METHOD__, "1.20" ); + $this->setText_internal( $oldText, $newText ); + } + + /** + * @private + * Use specified text instead of loading from the database + */ + private function setText_internal( $oldText, $newText ) { $this->mOldtext = $oldText; $this->mNewtext = $newText; $this->mTextLoaded = 2; $this->mRevisionsLoaded = true; } + /** + * Use specified text instead of loading from the database + * @since 1.20 + */ + function setContent( Content $oldContent, Content $newContent, $format = null ) { #FIXME: use this! + $oldText = $oldContent->serialize( $format ); + $newText = $newContent->serialize( $format ); + + return $this->setText_internal( $oldText, $newText ); + } + /** * Set the language in which the diff text is written * (Defaults to page content language). -- 2.20.1