From 8b870be6e13bcdcff466a615b416fa4c0678f3e7 Mon Sep 17 00:00:00 2001 From: Daniel Kinzler Date: Fri, 23 Mar 2012 16:55:15 +0000 Subject: [PATCH] baby steps towards editing structured data --- includes/ContentHandler.php | 129 +++++++++++++++++++----------------- includes/EditPage.php | 37 ++++++++--- includes/Revision.php | 55 +++++++-------- includes/WikiPage.php | 8 ++- 4 files changed, 126 insertions(+), 103 deletions(-) diff --git a/includes/ContentHandler.php b/includes/ContentHandler.php index 67bc81206d..496d7c9578 100644 --- a/includes/ContentHandler.php +++ b/includes/ContentHandler.php @@ -304,84 +304,91 @@ abstract class ContentHandler { public function getAutoDeleteReason( Title $title, &$hasHistory ) { global $wgContLang; - $dbw = wfGetDB( DB_MASTER ); + try { + $dbw = wfGetDB( DB_MASTER ); - // Get the last revision - $rev = Revision::newFromTitle( $title ); + // Get the last revision + $rev = Revision::newFromTitle( $title ); - if ( is_null( $rev ) ) { - return false; - } + if ( is_null( $rev ) ) { + return false; + } - // Get the article's contents - $content = $rev->getContent(); - $blank = false; + // Get the article's contents + $content = $rev->getContent(); + $blank = false; - // If the page is blank, use the text from the previous revision, - // which can only be blank if there's a move/import/protect dummy revision involved - if ( $content->getSize() == 0 ) { - $prev = $rev->getPrevious(); + // If the page is blank, use the text from the previous revision, + // which can only be blank if there's a move/import/protect dummy revision involved + if ( $content->getSize() == 0 ) { + $prev = $rev->getPrevious(); - if ( $prev ) { - $content = $rev->getContent(); - $blank = true; + if ( $prev ) { + $content = $rev->getContent(); + $blank = true; + } } - } - // Find out if there was only one contributor - // Only scan the last 20 revisions - $res = $dbw->select( 'revision', 'rev_user_text', - array( 'rev_page' => $title->getArticleID(), $dbw->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' ), - __METHOD__, - array( 'LIMIT' => 20 ) - ); - - if ( $res === false ) { - // This page has no revisions, which is very weird - return false; - } - - $hasHistory = ( $res->numRows() > 1 ); - $row = $dbw->fetchObject( $res ); + // Find out if there was only one contributor + // Only scan the last 20 revisions + $res = $dbw->select( 'revision', 'rev_user_text', + array( 'rev_page' => $title->getArticleID(), $dbw->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' ), + __METHOD__, + array( 'LIMIT' => 20 ) + ); + + if ( $res === false ) { + // This page has no revisions, which is very weird + return false; + } - if ( $row ) { // $row is false if the only contributor is hidden - $onlyAuthor = $row->rev_user_text; - // Try to find a second contributor - foreach ( $res as $row ) { - if ( $row->rev_user_text != $onlyAuthor ) { // Bug 22999 - $onlyAuthor = false; - break; + $hasHistory = ( $res->numRows() > 1 ); + $row = $dbw->fetchObject( $res ); + + if ( $row ) { // $row is false if the only contributor is hidden + $onlyAuthor = $row->rev_user_text; + // Try to find a second contributor + foreach ( $res as $row ) { + if ( $row->rev_user_text != $onlyAuthor ) { // Bug 22999 + $onlyAuthor = false; + break; + } } + } else { + $onlyAuthor = false; } - } else { - $onlyAuthor = false; - } - // Generate the summary with a '$1' placeholder - if ( $blank ) { - // The current revision is blank and the one before is also - // blank. It's just not our lucky day - $reason = wfMsgForContent( 'exbeforeblank', '$1' ); - } else { - if ( $onlyAuthor ) { - $reason = wfMsgForContent( 'excontentauthor', '$1', $onlyAuthor ); + // Generate the summary with a '$1' placeholder + if ( $blank ) { + // The current revision is blank and the one before is also + // blank. It's just not our lucky day + $reason = wfMsgForContent( 'exbeforeblank', '$1' ); } else { - $reason = wfMsgForContent( 'excontent', '$1' ); + if ( $onlyAuthor ) { + $reason = wfMsgForContent( 'excontentauthor', '$1', $onlyAuthor ); + } else { + $reason = wfMsgForContent( 'excontent', '$1' ); + } } - } - if ( $reason == '-' ) { - // Allow these UI messages to be blanked out cleanly - return ''; - } + if ( $reason == '-' ) { + // Allow these UI messages to be blanked out cleanly + return ''; + } + + // Max content length = max comment length - length of the comment (excl. $1) + $text = $content->getTextForSummary( 255 - ( strlen( $reason ) - 2 ) ); - // Max content length = max comment length - length of the comment (excl. $1) - $text = $content->getTextForSummary( 255 - ( strlen( $reason ) - 2 ) ); + // Now replace the '$1' placeholder + $reason = str_replace( '$1', $text, $reason ); - // Now replace the '$1' placeholder - $reason = str_replace( '$1', $text, $reason ); + return $reason; + } catch (MWException $e) { + # if a page is horribly broken, we still want to be able to delete it. so be lenient about errors here. + wfDebug("Error while building auto delete summary: $e"); + } - return $reason; + return ''; } /** diff --git a/includes/EditPage.php b/includes/EditPage.php index 054c2efd1d..aff1ea9a05 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -706,6 +706,9 @@ class EditPage { $this->content_model = $request->getText( 'model', $content_handler->getModelName() ); #may be overridden by revision $this->content_format = $request->getText( 'format', $content_handler->getDefaultFormat() ); #may be overridden by revision + #TODO: check if the desired model is allowed in this namespace, and if a transition from the page's current model to the new model is allowed + #TODO: check if the desired content model supports the given content format! + $this->live = $request->getCheck( 'live' ); $this->editintro = $request->getText( 'editintro', // Custom edit intro for new sections @@ -920,7 +923,7 @@ class EditPage { */ private function getCurrentContent() { $rev = $this->mArticle->getRevision(); - $content = $rev->getContent( Revision::RAW ); + $content = $rev ? $rev->getContent( Revision::RAW ) : null; if ( $content === false || $content === null ) { if ( !$this->content_model ) $this->content_model = $this->getTitle()->getContentModelName(); @@ -1520,7 +1523,7 @@ class EditPage { ( ( $this->minoredit && !$this->isNew ) ? EDIT_MINOR : 0 ) | ( $bot ? EDIT_FORCE_BOT : 0 ); - $doEditStatus = $this->mArticle->doEditContent( $content, $this->summary, $flags ); + $doEditStatus = $this->mArticle->doEditContent( $content, $this->summary, $flags, false, null, $this->content_format ); if ( $doEditStatus->isOK() ) { $result['redirect'] = $content->isRedirect(); @@ -1918,6 +1921,9 @@ class EditPage { $wgOut->addHTML( Html::hidden( 'oldid', $this->oldid ) ); + $wgOut->addHTML( Html::hidden( 'format', $this->content_format ) ); + $wgOut->addHTML( Html::hidden( 'model', $this->content_model ) ); + if ( $this->section == 'new' ) { $this->showSummaryInput( true, $this->summary ); $wgOut->addHTML( $this->getSummaryPreview( true, $this->summary ) ); @@ -1948,6 +1954,9 @@ class EditPage { $wgOut->addWikiText( $this->getCopywarn() ); + $wgOut->addHTML( Html::element( 'p', null, "model: " . $this->content_model ) ); #FIXME: content handler debug stuff, DELETE! + $wgOut->addHTML( Html::element( 'p', null, "format: " . $this->content_format ) ); #FIXME: content handler debug stuff, DELETE! + $wgOut->addHTML( $this->editFormTextAfterWarn ); $this->showStandardInputs(); @@ -2692,8 +2701,7 @@ HTML # don't parse non-wikitext pages, show message about preview # XXX: stupid php bug won't let us use $this->getContextTitle()->isCssJsSubpage() here -- This note has been there since r3530. Sure the bug was fixed time ago? - #FIXME: get appropriate content handler! - if ( $this->isCssJsSubpage || !$this->mTitle->isWikitextPage() ) { + if ( $this->isCssJsSubpage || $this->mTitle->isCssOrJsPage() ) { #TODO: kill all special case handling for CSS/JS content! if( $this->mTitle->isCssJsSubpage() ) { $level = 'user'; } elseif( $this->mTitle->isCssOrJsPage() ) { @@ -2715,30 +2723,39 @@ HTML } else { throw new MWException( 'A CSS/JS (sub)page but which is not css nor js!' ); } - } + } #FIXME: else $previewtext is undefined! $parserOutput = $wgParser->parse( $previewtext, $this->mTitle, $parserOptions ); $previewHTML = $parserOutput->mText; - $previewHTML .= "
\n" . htmlspecialchars( $this->textbox1 ) . "\n
\n"; + $previewHTML .= "
\n" . htmlspecialchars( $this->textbox1 ) . "\n
\n"; #FIXME: use content object! } else { $rt = Title::newFromRedirectArray( $this->textbox1 ); if ( $rt ) { $previewHTML = $this->mArticle->viewRedirect( $rt, false ); } else { - $toparse = $this->textbox1; + $content = ContentHandler::makeContent( $this->textbox1, $this->getTitle(), $this->content_model, $this->content_format ); # If we're adding a comment, we need to show the # summary as the headline if ( $this->section == "new" && $this->summary != "" ) { - $toparse = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->summary ) . "\n\n" . $toparse; + $content = $content->addSectionHeader( $this->summary ); } + $toparse_orig = $content->serialize( $this->content_format ); + $toparse = $toparse_orig; wfRunHooks( 'EditPageGetPreviewText', array( $this, &$toparse ) ); + if ( $toparse !== $toparse_orig ) { + #hook changed the text, create new Content object + $content = ContentHandler::makeContent( $toparse, $this->getTitle(), $this->content_model, $this->content_format ); + } + + wfRunHooks( 'EditPageGetPreviewContent', array( $this, &$content ) ); # FIXME: document new hook + $parserOptions->enableLimitReport(); - $toparse = $wgParser->preSaveTransform( $toparse, $this->mTitle, $wgUser, $parserOptions ); - $parserOutput = $wgParser->parse( $toparse, $this->mTitle, $parserOptions ); + $content = $content->preSaveTransform( $this->mTitle, $wgUser, $parserOptions ); + $parserOutput = $content->getParserOutput( $this->mTitle, null, $parserOptions ); $previewHTML = $parserOutput->getText(); $this->mParserOutput = $parserOutput; diff --git a/includes/Revision.php b/includes/Revision.php index 4c62d049ef..1e36e34d7f 100644 --- a/includes/Revision.php +++ b/includes/Revision.php @@ -479,13 +479,7 @@ class Revision { $this->mSha1 = isset( $row['sha1'] ) ? strval( $row['sha1'] ) : null; $this->mContentModelName = isset( $row['content_model'] ) ? strval( $row['content_model'] ) : null; - $this->mContentFormat = isset( $row['content_format'] ) ? strval( $row['content_format'] ) : null; - - if( !isset( $row->rev_content_format ) || is_null( $row->rev_content_format ) ) { - $this->mContentFormat = null; # determine on demand if needed - } else { - $this->mContentFormat = $row->rev_content_format; - } + $this->mContentFormat = isset( $row['content_format'] ) ? strval( $row['content_format'] ) : null; // Enforce spacing trimming on supplied text $this->mComment = isset( $row['comment'] ) ? trim( strval( $row['comment'] ) ) : null; @@ -843,7 +837,7 @@ class Revision { $this->mText = $this->loadText(); } - $this->mContent = $handler->unserialize( $this->mText, $title, $format ); + $this->mContent = is_null( $this->mText ) ? null : $handler->unserialize( $this->mText, $format ); } return $this->mContent; @@ -1104,28 +1098,29 @@ class Revision { $rev_id = isset( $this->mId ) ? $this->mId : $dbw->nextSequenceValue( 'revision_rev_id_seq' ); - $dbw->insert( 'revision', - array( - 'rev_id' => $rev_id, - 'rev_page' => $this->mPage, - 'rev_text_id' => $this->mTextId, - 'rev_comment' => $this->mComment, - 'rev_minor_edit' => $this->mMinorEdit ? 1 : 0, - 'rev_user' => $this->mUser, - 'rev_user_text' => $this->mUserText, - 'rev_timestamp' => $dbw->timestamp( $this->mTimestamp ), - 'rev_deleted' => $this->mDeleted, - 'rev_len' => $this->mSize, - 'rev_parent_id' => is_null( $this->mParentId ) - ? $this->getPreviousRevisionId( $dbw ) - : $this->mParentId, - 'rev_sha1' => is_null( $this->mSha1 ) - ? Revision::base36Sha1( $this->mText ) - : $this->mSha1, - 'rev_content_model' => $this->getContentModelName(), - 'rev_content_format' => $this->getContentFormat(), - ), __METHOD__ - ); + + $row = array( + 'rev_id' => $rev_id, + 'rev_page' => $this->mPage, + 'rev_text_id' => $this->mTextId, + 'rev_comment' => $this->mComment, + 'rev_minor_edit' => $this->mMinorEdit ? 1 : 0, + 'rev_user' => $this->mUser, + 'rev_user_text' => $this->mUserText, + 'rev_timestamp' => $dbw->timestamp( $this->mTimestamp ), + 'rev_deleted' => $this->mDeleted, + 'rev_len' => $this->mSize, + 'rev_parent_id' => is_null( $this->mParentId ) + ? $this->getPreviousRevisionId( $dbw ) + : $this->mParentId, + 'rev_sha1' => is_null( $this->mSha1 ) + ? Revision::base36Sha1( $this->mText ) + : $this->mSha1, + 'rev_content_model' => $this->getContentModelName(), + 'rev_content_format' => $this->getContentFormat(), + ); + + $dbw->insert( 'revision', $row, __METHOD__ ); $this->mId = !is_null( $rev_id ) ? $rev_id : $dbw->insertId(); diff --git a/includes/WikiPage.php b/includes/WikiPage.php index d2b19b22d6..adf72f854a 100644 --- a/includes/WikiPage.php +++ b/includes/WikiPage.php @@ -1397,7 +1397,9 @@ class WikiPage extends Page { 'parent_id' => $oldid, 'user' => $user->getId(), 'user_text' => $user->getName(), - 'timestamp' => $now + 'timestamp' => $now, + 'content_model' => $content->getModelName(), + 'content_format' => $serialisation_format, ) ); $changed = !$content->equals( $old_content ); @@ -1502,7 +1504,9 @@ class WikiPage extends Page { 'len' => $newsize, 'user' => $user->getId(), 'user_text' => $user->getName(), - 'timestamp' => $now + 'timestamp' => $now, + 'content_model' => $content->getModelName(), + 'content_format' => $serialisation_format, ) ); $revisionId = $revision->insertOn( $dbw ); -- 2.20.1