From 4f1e3a69de99055c903d8d8203c7a93c7e28e998 Mon Sep 17 00:00:00 2001 From: Daniel Friesen Date: Tue, 26 Aug 2008 14:07:31 +0000 Subject: [PATCH] Commit initial portion of EditPage refactoring. This isn't complete, but nothing is broken. The goal here is to make it possible for extensions to subclass the editpage and override certain areas of it while allowing the rest to keep it's presence without needing to copy code from core which may change. * Use $this->action instead of hardcoded 'submit's so this may be overridden for subclasses that use a different action=... * Move all the header setting into a new setHeaders() function. This way subclasses can tweak the title, this was previously impossible because of how scattered setPageTitle calls were. * Move the previewarea stuff that was being duplicated in 2 places into it's own function. * Move some inputs into a beforetext function * Move wpTextbox1 into a special function. And create a textbox function to unify textarea creation. wpTextbox1 and wpTextbox2 now have a unified style due to this. (Though the metadata textarea could use this applied to it as well) * Move edittools into a function. * In getPreviewText; ** Don't use $wgOut ** Move template and other parseroutput related code outside of the function and simply set a $this->parserOutput variable while we're in here. (We should probably also move the $wgOut->addParserOutputNoText call somewhere else, and move most of the preview parsing into one of the initialization functions. --- includes/EditPage.php | 294 +++++++++++++++++++++++++----------------- 1 file changed, 175 insertions(+), 119 deletions(-) diff --git a/includes/EditPage.php b/includes/EditPage.php index c3baebb4bf..af1cb0aae5 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -44,6 +44,7 @@ class EditPage { var $mArticle; var $mTitle; + var $action; var $mMetaData = ''; var $isConflict = false; var $isCssJsSubpage = false; @@ -61,7 +62,8 @@ class EditPage { var $allowBlankSummary = false; var $autoSumm = ''; var $hookError = ''; - var $mPreviewTemplates; + #var $mPreviewTemplates; + var $mParserOutput; var $mBaseRevision = false; # Form values @@ -92,6 +94,7 @@ class EditPage { function EditPage( $article ) { $this->mArticle =& $article; $this->mTitle = $article->getTitle(); + $this->action = 'submit'; # Placeholders for text injection by hooks (empty per default) $this->editFormPageTop = @@ -1059,6 +1062,30 @@ class EditPage { return true; } + function setHeaders() { + global $wgOut, $wgTitle; + $wgOut->setRobotPolicy( 'noindex,nofollow' ); + if ( $this->formtype == 'preview' ) { + $wgOut->setPageTitleActionText( wfMsg( 'preview' ) ); + } + if ( $this->isConflict ) { + $wgOut->setPageTitle( wfMsg( 'editconflict', $wgTitle->getPrefixedText() ) ); + } + if( $this->section != '' ) { + $msg = $this->section == 'new' ? 'editingcomment' : 'editingsection'; + $wgOut->setPageTitle( wfMsg( $msg, $wgTitle->getPrefixedText() ) ); + } else { + # Use the title defined by DISPLAYTITLE magic word when present + if( isset($this->mParserOutput) + && ( $dt = $this->mParserOutput->getDisplayTitle() ) !== false ) { + $title = $dt; + } else { + $title = $wgTitle->getPrefixedText(); + } + $wgOut->setPageTitle( wfMsg( 'editing', $title ) ); + } + } + /** * Send the edit form and related headers to $wgOut * @param $formCallback Optional callable that takes an OutputPage @@ -1082,46 +1109,41 @@ class EditPage { wfRunHooks( 'EditPage::showEditForm:initial', array( &$this ) ) ; - $wgOut->setRobotPolicy( 'noindex,nofollow' ); + #need to parse the preview early so that we know which templates are used, + #otherwise users with "show preview after edit box" will get a blank list + #we parse this near the beginning so that setHeaders can do the title + #setting work instead of leaving it in getPreviewText + $previewOutput = ''; + if ( $this->formtype == 'preview' ) { + $previewOutput = $this->getPreviewText(); + } + + $this->setHeaders(); # Enabled article-related sidebar, toplinks, etc. $wgOut->setArticleRelated( true ); - if ( $this->formtype == 'preview' ) { - $wgOut->setPageTitleActionText( wfMsg( 'preview' ) ); - } - if ( $this->isConflict ) { - $s = wfMsg( 'editconflict', $wgTitle->getPrefixedText() ); - $wgOut->setPageTitle( $s ); $wgOut->addWikiMsg( 'explainconflict' ); $this->textbox2 = $this->textbox1; $this->textbox1 = $this->getContent(); $this->edittime = $this->mArticle->getTimestamp(); } else { - if( $this->section != '' ) { - if( $this->section == 'new' ) { - $s = wfMsg('editingcomment', $wgTitle->getPrefixedText() ); - } else { - $s = wfMsg('editingsection', $wgTitle->getPrefixedText() ); - $matches = array(); - if( !$this->summary && !$this->preview && !$this->diff ) { - preg_match( "/^(=+)(.+)\\1/mi", - $this->textbox1, - $matches ); - if( !empty( $matches[2] ) ) { - global $wgParser; - $this->summary = "/* " . - $wgParser->stripSectionName(trim($matches[2])) . - " */ "; - } + if( $this->section != '' && $this->section != 'new' ) { + $matches = array(); + if( !$this->summary && !$this->preview && !$this->diff ) { + preg_match( "/^(=+)(.+)\\1/mi", + $this->textbox1, + $matches ); + if( !empty( $matches[2] ) ) { + global $wgParser; + $this->summary = "/* " . + $wgParser->stripSectionName(trim($matches[2])) . + " */ "; } } - } else { - $s = wfMsg( 'editing', $wgTitle->getPrefixedText() ); } - $wgOut->setPageTitle( $s ); if ( $this->missingComment ) { $wgOut->wrapWikiMsg( '
$1
', 'missingcommenttext' ); @@ -1217,20 +1239,7 @@ class EditPage { $wgOut->addHTML( "\n" ); } - #need to parse the preview early so that we know which templates are used, - #otherwise users with "show preview after edit box" will get a blank list - if ( $this->formtype == 'preview' ) { - $previewOutput = $this->getPreviewText(); - } - - $rows = $wgUser->getIntOption( 'rows' ); - $cols = $wgUser->getIntOption( 'cols' ); - - $ew = $wgUser->getOption( 'editwidth' ); - if ( $ew ) $ew = " style=\"width:100%\""; - else $ew = ''; - - $q = 'action=submit'; + $q = 'action='.$this->action; #if ( "no" == $redirect ) { $q .= "&redirect=no"; } $action = $wgTitle->escapeLocalURL( $q ); @@ -1282,16 +1291,9 @@ class EditPage { $wgOut->addHTML( $this->editFormPageTop ); if ( $wgUser->getOption( 'previewontop' ) ) { - - if ( 'preview' == $this->formtype ) { - $this->showPreview( $previewOutput ); - } else { - $wgOut->addHTML( '
' ); - } - - if ( 'diff' == $this->formtype ) { - $this->showDiff(); - } + $this->displayPreviewArea( $previewOutput ); + // Spacer for the edit toolbar + $wgOut->addHTML( '


' ); } @@ -1330,7 +1332,7 @@ class EditPage { if( !$this->preview && !$this->diff ) { $wgOut->setOnloadHandler( 'document.editform.wpTextbox1.focus()' ); } - $templates = ($this->preview || $this->section != '') ? $this->mPreviewTemplates : $this->mArticle->getUsedTemplates(); + $templates = $this->getTemplates(); $formattedtemplates = $sk->formatTemplates( $templates, $this->preview, $this->section != ''); $hiddencats = $this->mArticle->getHiddenCategories(); @@ -1341,11 +1343,15 @@ class EditPage { $metadata = $this->mMetaData ; $metadata = htmlspecialchars( $wgContLang->recodeForEdit( $metadata ) ) ; $top = wfMsgWikiHtml( 'metadata_help' ); + /* ToDo: Replace with clean code */ + $ew = $wgUser->getOption( 'editwidth' ); + if ( $ew ) $ew = " style=\"width:100%\""; + else $ew = ''; + /* /ToDo */ $metadata = $top . "" ; } else $metadata = "" ; - $hidden = ''; $recreate = ''; if ($this->wasDeletedSinceLastEdit()) { if ( 'save' != $this->formtype ) { @@ -1354,7 +1360,6 @@ class EditPage { // Hide the toolbar and edit area, use can click preview to get it back // Add an confirmation checkbox and explanation. $toolbar = ''; - $hidden = 'type="hidden" style="display:none;"'; $recreate = $wgOut->parse( wfMsg( 'confirmrecreate', $this->lastDelete->user_name , $this->lastDelete->log_comment )); $recreate .= "
". @@ -1388,40 +1393,27 @@ END wfRunHooks( 'EditPage::showEditForm:fields', array( &$this, &$wgOut ) ); // Put these up at the top to ensure they aren't lost on early form submission - $wgOut->addHTML( " -section ) . "\" name=\"wpSection\" /> -starttime}\" name=\"wpStarttime\" />\n -edittime}\" name=\"wpEdittime\" />\n -scrolltop}\" name=\"wpScrolltop\" id=\"wpScrolltop\" />\n" ); - - $encodedtext = htmlspecialchars( $this->safeUnicodeOutput( $this->textbox1 ) ); - if( $encodedtext !== '' ) { - // Ensure there's a newline at the end, otherwise adding lines - // is awkward. - // But don't add a newline if the ext is empty, or Firefox in XHTML - // mode will show an extra newline. A bit annoying. - $encodedtext .= "\n"; - } + $this->showFormBeforeText(); $wgOut->addHTML( <<editFormTextBeforeContent} - END ); + $this->showTextbox1(); $wgOut->wrapWikiMsg( "
\n$1\n
", $copywarnMsg ); - $wgOut->addHTML( $this->editFormTextAfterWarn ); - $wgOut->addHTML( " + $wgOut->addHTML( <<editFormTextAfterWarn} {$metadata} {$editsummary} {$summarypreview} {$checkboxhtml} {$safemodehtml} -"); +END +); $wgOut->addHTML( "
@@ -1445,20 +1437,18 @@ END $token = htmlspecialchars( $wgUser->editToken() ); $wgOut->addHTML( "\n\n" ); - $wgOut->addHtml( '
' ); - $wgOut->addWikiMsgArray( 'edittools', array(), array( 'content' ) ); - $wgOut->addHtml( '
' ); - - $wgOut->addHTML( $this->editFormTextAfterTools ); + $this->showEditTools(); - $wgOut->addHTML( " + $wgOut->addHTML( <<editFormTextAfterTools}
{$formattedtemplates}
{$formattedhiddencats}
-"); +END +); if ( $this->isConflict && wfRunHooks( 'EditPageBeforeConflictDiff', array( &$this, &$wgOut ) ) ) { $wgOut->wrapWikiMsg( '==$1==', "yourdiff" ); @@ -1468,26 +1458,89 @@ END $de->showDiff( wfMsg( "yourtext" ), wfMsg( "storedversion" ) ); $wgOut->wrapWikiMsg( '==$1==', "yourtext" ); - $wgOut->addHTML( "" ); + $this->showTextbox2(); } $wgOut->addHTML( $this->editFormTextBottom ); $wgOut->addHTML( "\n" ); if ( !$wgUser->getOption( 'previewontop' ) ) { + $this->displayPreviewArea( $previewOutput ); + } - if ( $this->formtype == 'preview') { - $this->showPreview( $previewOutput ); - } else { - $wgOut->addHTML( '
' ); - } + wfProfileOut( $fname ); + } - if ( $this->formtype == 'diff') { - $this->showDiff(); - } + protected function showFormBeforeText() { + return " +section ) . "\" name=\"wpSection\" /> +starttime}\" name=\"wpStarttime\" />\n +edittime}\" name=\"wpEdittime\" />\n +scrolltop}\" name=\"wpScrolltop\" id=\"wpScrolltop\" />\n"; + } + + protected function showTextbox1() { + $attribs = array( 'tabindex' => 1 ); + + if( $this->wasDeletedSinceLastEdit() ) + $attribs['type'] = 'hidden'; + + $this->showTextbox( $this->textbox1, 'wpTextbox1', $attribs ); + } + + protected function showTextbox2() { + $this->showTextbox( $encodedtext, 'wpTextbox2', array( 'tabindex' => 6 ) ); + } + + protected function showTextbox( $content, $name, $attribs = array() ) { + global $wgOut, $wgUser; + + $encodedtext = htmlspecialchars( $this->safeUnicodeOutput( $content ) ); + if( $encodedtext !== '' ) { + // Ensure there's a newline at the end, otherwise adding lines + // is awkward. + // But don't add a newline if the ext is empty, or Firefox in XHTML + // mode will show an extra newline. A bit annoying. + $encodedtext .= "\n"; + } + + $attribs = array( + 'accesskey' => ',', + 'id' => $name, + ); + + if( $wgUser->getOption( 'editwidth' ) ) + $attribs['style'] = 'width: 100%'; + + $wgOut->addHTML( Xml::textarea( + $name, + $encodedtext, + $wgUser->getIntOption( 'cols' ), $wgUser->getIntOption( 'rows' ), + $attribs ) ); + } + protected function displayPreviewArea( $previewOutput ) { + global $wgOut; + if ( $this->formtype == 'preview') { + $this->showPreview( $previewOutput ); + } else { + $wgOut->addHTML( '
' ); } - wfProfileOut( $fname ); + if ( $this->formtype == 'diff') { + $this->showDiff(); + } + } + + protected function displayPreviewArea( $previewOutput ) { + global $wgOut; + if ( $this->formtype == 'preview') { + $this->showPreview( $previewOutput ); + } else { + $wgOut->addHTML( '
' ); + } + + if ( $this->formtype == 'diff') { + $this->showDiff(); + } } /** @@ -1524,12 +1577,19 @@ END function doLivePreviewScript() { global $wgOut, $wgTitle; $wgOut->addScriptFile( 'preview.js' ); - $liveAction = $wgTitle->getLocalUrl( 'action=submit&wpPreview=true&live=true' ); + $liveAction = $wgTitle->getLocalUrl( "action={$this->action}&wpPreview=true&live=true" ); return "return !lpDoPreview(" . "editform.wpTextbox1.value," . '"' . $liveAction . '"' . ")"; } + protected function showEditTools() { + global $wgOut; + $wgOut->addHtml( '
' ); + $wgOut->addWikiMsgArray( 'edittools', array(), array( 'content' ) ); + $wgOut->addHtml( '
' ); + } + function getLastDelete() { $dbr = wfGetDB( DB_SLAVE ); $fname = 'EditPage::getLastDelete'; @@ -1569,8 +1629,7 @@ END function getPreviewText() { global $wgOut, $wgUser, $wgTitle, $wgParser, $wgLang, $wgContLang; - $fname = 'EditPage::getPreviewText'; - wfProfileIn( $fname ); + wfProfileIn( __METHOD__ ); if ( $this->mTriedSave && !$this->mTokenOk ) { if ( $this->mTokenOkExceptSuffix ) { @@ -1604,9 +1663,9 @@ END } $parserOptions->setTidy(true); $parserOutput = $wgParser->parse( $previewtext , $this->mTitle, $parserOptions ); - $wgOut->addHTML( $parserOutput->mText ); + //$wgOut->addHTML( $parserOutput->mText ); $previewHTML = ''; - } else if( $rt = Title::newFromRedirect( $this->textbox1 ) ) { + } elseif( $rt = Title::newFromRedirect( $this->textbox1 ) ) { $previewHTML = $this->mArticle->viewRedirect( $rt, false ); } else { $toparse = $this->textbox1; @@ -1643,20 +1702,9 @@ END $this->mTitle, $parserOptions ); $previewHTML = $parserOutput->getText(); + $this->mParserOutput = $parserOutput; $wgOut->addParserOutputNoText( $parserOutput ); - # ParserOutput might have altered the page title, so reset it - # Also, use the title defined by DISPLAYTITLE magic word when present - if( ( $dt = $parserOutput->getDisplayTitle() ) !== false ) { - $wgOut->setPageTitle( wfMsg( 'editing', $dt ) ); - } else { - $wgOut->setPageTitle( wfMsg( 'editing', $wgTitle->getPrefixedText() ) ); - } - - foreach ( $parserOutput->getTemplates() as $ns => $template) - foreach ( array_keys( $template ) as $dbk) - $this->mPreviewTemplates[] = Title::makeTitle($ns, $dbk); - if ( count( $parserOutput->getWarnings() ) ) { $note .= "\n\n" . implode( "\n\n", $parserOutput->getWarnings() ); } @@ -1665,18 +1713,26 @@ END $previewhead = '

' . htmlspecialchars( wfMsg( 'preview' ) ) . "

\n" . "
" . $wgOut->parse( $note ) . "
\n"; if ( $this->isConflict ) { - $previewhead.='

' . htmlspecialchars( wfMsg( 'previewconflict' ) ) . "

\n"; + $previewhead .='

' . htmlspecialchars( wfMsg( 'previewconflict' ) ) . "

\n"; } - if( $wgUser->getOption( 'previewontop' ) ) { - // Spacer for the edit toolbar - $previewfoot = '


'; + wfProfileOut( __METHOD__ ); + return $previewhead . $previewHTML; + } + + function getTemplates() { + if( $this->preview || $this->section != '' ) { + $templates = array(); + if( !isset($this->mParserOutput) ) return $templates; + foreach( $this->mParserOutput->getTemplates() as $ns => $template) { + foreach( array_keys( $template ) as $dbk ) { + $templates[] = Title::makeTitle($ns, $dbk); + } + } + return $templates; } else { - $previewfoot = ''; + return $this->mArticle->getUsedTemplates(); } - - wfProfileOut( $fname ); - return $previewhead . $previewHTML . $previewfoot; } /** @@ -1697,8 +1753,8 @@ END # Spit out the source or the user's modified version if( $source !== false ) { - $rows = $wgUser->getOption( 'rows' ); - $cols = $wgUser->getOption( 'cols' ); + $rows = $wgUser->getIntOption( 'rows' ); + $cols = $wgUser->getIntOption( 'cols' ); $attribs = array( 'id' => 'wpTextbox1', 'name' => 'wpTextbox1', 'cols' => $cols, 'rows' => $rows, 'readonly' => 'readonly' ); $wgOut->addHtml( '
' ); $wgOut->addWikiMsg( $first ? 'blockedoriginalsource' : 'blockededitsource', $this->mTitle->getPrefixedText() ); -- 2.20.1