X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2FEditPage.php;h=457b2b586cc200ab040548abf1cde31cfdae101e;hb=b9f3c44797c8d72769281a541b8a95d1f6ec3df2;hp=e8bfd95b25768155d9b6c9e0e4e6e0da0d6a6dfc;hpb=ef74c0a1783428b1065e2ff03bf97a3468053316;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/EditPage.php b/includes/EditPage.php index e8bfd95b25..457b2b586c 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -42,7 +42,14 @@ class EditPage { const AS_IMAGE_REDIRECT_ANON = 233; const AS_IMAGE_REDIRECT_LOGGED = 234; + /** + * @var Article + */ var $mArticle; + + /** + * @var Title + */ var $mTitle; private $mContextTitle = null; var $action; @@ -50,6 +57,8 @@ class EditPage { var $isCssJsSubpage = false; var $isCssSubpage = false; var $isJsSubpage = false; + var $isWrongCaseCssJsPage = false; + var $isNew = false; // new page or new section var $deletedSinceEdit; var $formtype; var $firsttime; @@ -66,7 +75,12 @@ class EditPage { var $autoSumm = ''; var $hookError = ''; #var $mPreviewTemplates; + + /** + * @var ParserOutput + */ var $mParserOutput; + var $mBaseRevision = false; var $mShowSummaryField = true; @@ -87,6 +101,7 @@ class EditPage { public $editFormTextBottom; public $editFormTextAfterContent; public $previewTextAfterContent; + public $mPreloadText; /* $didSave should be set to true whenever an article was succesfully altered. */ public $didSave = false; @@ -96,7 +111,7 @@ class EditPage { /** * @todo document - * @param $article + * @param $article Article */ function __construct( $article ) { $this->mArticle =& $article; @@ -115,6 +130,9 @@ class EditPage { $this->mPreloadText = ""; } + /** + * @return Article + */ function getArticle() { return $this->mArticle; } @@ -146,6 +164,8 @@ class EditPage { /** * Fetch initial editing page content. + * + * @param $def_text string * @returns mixed string on success, $def_text for invalid sections * @private */ @@ -224,7 +244,7 @@ class EditPage { // was created, or we may simply have got bogus input. $this->editFormPageTop .= $wgOut->parse( '
' . wfMsgNoTrans( 'undo-norev' ) . '
' ); } - } else if ( $section != '' ) { + } elseif ( $section != '' ) { if ( $section == 'new' ) { $text = $this->getPreloadedText( $preload ); } else { @@ -238,7 +258,11 @@ class EditPage { return $text; } - /** Use this method before edit() to preload some text into the edit box */ + /** + * Use this method before edit() to preload some text into the edit box + * + * @param $text string + */ public function setPreloadedText( $text ) { $this->mPreloadText = $text; } @@ -279,7 +303,7 @@ class EditPage { return ''; } - /* + /** * Check if a page was deleted while the user was editing it, before submit. * Note that we rely on the logging table, which hasn't been always there, * but that doesn't matter, because this only applies to brand new @@ -308,6 +332,8 @@ class EditPage { /** * Checks whether the user entered a skin name in uppercase, * e.g. "User:Example/Monobook.css" instead of "monobook.css" + * + * @return bool */ protected function isWrongCaseCssJsPage() { if( $this->mTitle->isCssJsSubpage() ) { @@ -366,11 +392,13 @@ class EditPage { $this->preview = true; } - $wgOut->addModules( array( 'mediawiki.legacy.edit', 'mediawiki.action.edit' ) ); + $wgOut->addModules( array( 'mediawiki.action.edit' ) ); if ( $wgUser->getOption( 'uselivepreview', false ) ) { $wgOut->addModules( 'mediawiki.legacy.preview' ); } + // Bug #19334: textarea jumps when editing articles in IE8 + $wgOut->addStyle( 'common/IE80Fixes.css', 'screen', 'IE 8' ); $permErrors = $this->getEditPermissionErrors(); if ( $permErrors ) { @@ -383,9 +411,9 @@ class EditPage { } else { if ( $this->save ) { $this->formtype = 'save'; - } else if ( $this->preview ) { + } elseif ( $this->preview ) { $this->formtype = 'preview'; - } else if ( $this->diff ) { + } elseif ( $this->diff ) { $this->formtype = 'diff'; } else { # First time through $this->firsttime = true; @@ -406,10 +434,11 @@ class EditPage { $this->isConflict = false; // css / js subpages of user pages get a special treatment - $this->isCssJsSubpage = $this->mTitle->isCssJsSubpage(); - $this->isCssSubpage = $this->mTitle->isCssSubpage(); - $this->isJsSubpage = $this->mTitle->isJsSubpage(); + $this->isCssJsSubpage = $this->mTitle->isCssJsSubpage(); + $this->isCssSubpage = $this->mTitle->isCssSubpage(); + $this->isJsSubpage = $this->mTitle->isJsSubpage(); $this->isWrongCaseCssJsPage = $this->isWrongCaseCssJsPage(); + $this->isNew = !$this->mTitle->exists() || $this->section == 'new'; # Show applicable editing introductions if ( $this->formtype == 'initial' || $this->firsttime ) @@ -470,6 +499,9 @@ class EditPage { wfProfileOut( __METHOD__ ); } + /** + * @return array + */ protected function getEditPermissionErrors() { global $wgUser; $permErrors = $this->mTitle->getUserPermissionsErrors( 'edit', $wgUser ); @@ -563,7 +595,7 @@ class EditPage { /** * @todo document - * @param $request + * @param $request WebRequest */ function importFormData( &$request ) { global $wgLang, $wgUser; @@ -630,7 +662,7 @@ class EditPage { # The unmarked state will be assumed to be a save, # if the form seems otherwise complete. wfDebug( __METHOD__ . ": Passed token check.\n" ); - } else if ( $this->diff ) { + } elseif ( $this->diff ) { # Failed token check, but only requested "Show Changes". wfDebug( __METHOD__ . ": Failed token check; Show Changes requested.\n" ); } else { @@ -694,7 +726,7 @@ class EditPage { $this->bot = $request->getBool( 'bot', true ); $this->nosummary = $request->getBool( 'nosummary' ); - // FIXME: unused variable? + // @todo FIXME: Unused variable? $this->oldid = $request->getInt( 'oldid' ); $this->live = $request->getCheck( 'live' ); @@ -760,8 +792,8 @@ class EditPage { $ip = User::isIP( $username ); if ( !$user->isLoggedIn() && !$ip ) { # User does not exist $wgOut->wrapWikiMsg( "
\n$1\n
", - array( 'userpage-userdoesnotexist', $username ) ); - } else if ( $user->isBlocked() ) { # Show log extract if the user is currently blocked + array( 'userpage-userdoesnotexist', wfEscapeWikiText( $username ) ) ); + } elseif ( $user->isBlocked() ) { # Show log extract if the user is currently blocked LogEventsList::showLogExtract( $wgOut, 'block', @@ -820,7 +852,11 @@ class EditPage { /** * Attempt submission (no UI) - * @return one of the constants describing the result + * + * @param $result + * @param $bot bool + * + * @return int one of the constants describing the result */ function internalAttemptSave( &$result, $bot = false ) { global $wgFilterCallback, $wgUser, $wgParser; @@ -978,7 +1014,6 @@ class EditPage { # Article exists. Check for edit conflict. $this->mArticle->clear(); # Force reload of dates, etc. - $this->mArticle->forUpdate( true ); # Lock the article wfDebug( "timestamp: {$this->mArticle->getTimestamp()}, edittime: {$this->edittime}\n" ); @@ -1018,7 +1053,7 @@ class EditPage { wfDebug( __METHOD__ . ": activating conflict; section replace failed.\n" ); $this->isConflict = true; $text = $this->textbox1; // do not try to merge here! - } else if ( $this->isConflict ) { + } elseif ( $this->isConflict ) { # Attempt merge if ( $this->mergeChangesInto( $text ) ) { // Successful merge! Maybe we should tell the user the good news? @@ -1093,7 +1128,7 @@ class EditPage { $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 and strlen( $matches[2] ) > 0 ) { + if ( $hasmatch && strlen( $matches[2] ) > 0 ) { $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $matches[2] ); } } @@ -1120,7 +1155,7 @@ class EditPage { $flags = EDIT_DEFER_UPDATES | EDIT_AUTOSUMMARY | ( $new ? EDIT_NEW : EDIT_UPDATE ) | - ( $this->minoredit ? EDIT_MINOR : 0 ) | + ( ( $this->minoredit && !$this->isNew ) ? EDIT_MINOR : 0 ) | ( $bot ? EDIT_FORCE_BOT : 0 ); $status = $this->mArticle->doEdit( $text, $this->summary, $flags ); @@ -1141,13 +1176,14 @@ class EditPage { * Commit the change of watch status */ protected function commitWatch() { + global $wgUser; if ( $this->watchthis xor $this->mTitle->userIsWatching() ) { $dbw = wfGetDB( DB_MASTER ); $dbw->begin(); if ( $this->watchthis ) { - $this->mArticle->doWatch(); + WatchAction::doWatch( $this->mTitle, $wgUser ); } else { - $this->mArticle->doUnwatch(); + WatchAction::doUnwatch( $this->mTitle, $wgUser ); } $dbw->commit(); } @@ -1157,6 +1193,11 @@ class EditPage { * Check if no edits were made by other users since * the time a user started editing the page. Limit to * 50 revisions for the sake of performance. + * + * @param $id int + * @param $edittime string + * + * @return bool */ protected function userWasLastToEdit( $id, $edittime ) { if( !$id ) return false; @@ -1179,7 +1220,10 @@ class EditPage { /** * Check given input text against $wgSpamRegex, and return the text of the first match. - * @return mixed -- matching string or false + * + * @param $text string + * + * @return string|false matching string or false */ public static function matchSpamRegex( $text ) { global $wgSpamRegex; @@ -1190,7 +1234,10 @@ class EditPage { /** * Check given input text against $wgSpamRegex, and return the text of the first match. - * @return mixed -- matching string or false + * + * @parma $text string + * + * @return string|false matching string or false */ public static function matchSummarySpamRegex( $text ) { global $wgSummarySpamRegex; @@ -1198,6 +1245,11 @@ class EditPage { return self::matchSpamRegexInternal( $text, $regexes ); } + /** + * @param $text string + * @param $regexes array + * @return bool|string + */ protected static function matchSpamRegexInternal( $text, $regexes ) { foreach( $regexes as $regex ) { $matches = array(); @@ -1211,7 +1263,7 @@ class EditPage { /** * Initialise form fields in the object * Called on the first invocation, e.g. when a user clicks an edit link - * @returns bool -- if the requested section is valid + * @return bool -- if the requested section is valid */ function initialiseForm() { global $wgUser; @@ -1229,8 +1281,12 @@ class EditPage { # Already watched $this->watchthis = true; } - if ( $wgUser->getOption( 'minordefault' ) ) $this->minoredit = true; - if ( $this->textbox1 === false ) return false; + if ( $wgUser->getOption( 'minordefault' ) && !$this->isNew ) { + $this->minoredit = true; + } + if ( $this->textbox1 === false ) { + return false; + } wfProxyCheck(); return true; } @@ -1260,9 +1316,8 @@ class EditPage { /** * Send the edit form and related headers to $wgOut - * @param $formCallback Optional callable that takes an OutputPage - * parameter; will be called during form output - * near the top, for captchas and the like. + * @param $formCallback Callback that takes an OutputPage parameter; will be called + * during form output near the top, for captchas and the like. */ function showEditForm( $formCallback = null ) { global $wgOut, $wgUser; @@ -1327,7 +1382,6 @@ class EditPage { // @todo move this to a cleaner conditional instead of blanking a variable } $wgOut->addHTML( << HTML ); @@ -1347,9 +1401,12 @@ HTML // It is better to not parse the comment at all than to have templates expanded in the middle // TODO: can the checkLabel be moved outside of the div so that wrapWikiMsg could be used? + $key = $comment === '' + ? 'confirmrecreate-noreason' + : 'confirmrecreate'; $wgOut->addHTML( '
' . - wfMsgExt( 'confirmrecreate', 'parseinline', $username, "$comment" ) . + wfMsgExt( $key, 'parseinline', $username, "$comment" ) . Xml::checkLabel( wfMsg( 'recreate' ), 'wpRecreate', 'wpRecreate', false, array( 'title' => $sk->titleAttrib( 'recreate' ), 'tabindex' => 1, 'id' => 'wpRecreate' ) ) . @@ -1379,6 +1436,8 @@ HTML $wgOut->addHTML( $this->editFormTextBeforeContent ); + $wgOut->addHTML( $toolbar ); + if ( $this->isConflict ) { // In an edit conflict bypass the overrideable content form method // and fallback to the raw wpTextbox1 since editconflicts can't be @@ -1477,7 +1536,7 @@ HTML if ( !$this->mArticle->mRevision->userCan( Revision::DELETED_TEXT ) ) { $wgOut->wrapWikiMsg( "\n", 'rev-deleted-text-permission' ); - } else if ( $this->mArticle->mRevision->isDeleted( Revision::DELETED_TEXT ) ) { + } elseif ( $this->mArticle->mRevision->isDeleted( Revision::DELETED_TEXT ) ) { $wgOut->wrapWikiMsg( "\n", 'rev-deleted-text-view' ); } @@ -1567,10 +1626,10 @@ HTML * inferred by the id given to the input. You can remove them both by * passing array( 'id' => false ) to $userInputAttrs. * - * @param $summary The value of the summary input - * @param $labelText The html to place inside the label - * @param $inputAttrs An array of attrs to use on the input - * @param $spanLabelAttrs An array of attrs to use on the span inside the label + * @param $summary string The value of the summary input + * @param $labelText string The html to place inside the label + * @param $inputAttrs array of attrs to use on the input + * @param $spanLabelAttrs array of attrs to use on the span inside the label * * @return array An array in the format array( $label, $input ) */ @@ -1613,11 +1672,13 @@ HTML # Add a class if 'missingsummary' is triggered to allow styling of the summary line $summaryClass = $this->missingSummary ? 'mw-summarymissed' : 'mw-summary'; if ( $isSubjectPreview ) { - if ( $this->nosummary ) + if ( $this->nosummary ) { return; + } } else { - if ( !$this->mShowSummaryField ) + if ( !$this->mShowSummaryField ) { return; + } } $summary = $wgContLang->recodeForEdit( $summary ); $labelText = wfMsgExt( $isSubjectPreview ? 'subject' : 'summary', 'parseinline' ); @@ -1710,6 +1771,10 @@ HTML # Then it must be protected based on static groups (regular) $classes[] = 'mw-textarea-protected'; } + # Is the title cascade-protected? + if ( $this->mTitle->isCascadeProtected() ) { + $classes[] = 'mw-textarea-cprotected'; + } } $attribs = array( 'tabindex' => 1 ); if ( is_array($customAttribs) ) @@ -1727,7 +1792,7 @@ HTML } protected function showTextbox2() { - $this->showTextbox( $this->textbox2, 'wpTextbox2', array( 'tabindex' => 6 ) ); + $this->showTextbox( $this->textbox2, 'wpTextbox2', array( 'tabindex' => 6, 'readonly' ) ); } protected function showTextbox( $content, $name, $customAttribs = array() ) { @@ -1750,6 +1815,13 @@ HTML 'style' => '' // avoid php notices when appending preferences (appending allows customAttribs['style'] to still work ); + global $wgBetterDirectionality; + if( $wgBetterDirectionality ) { + $pageLang = $this->mTitle->getPageLanguage(); + $attribs['lang'] = $pageLang->getCode(); + $attribs['dir'] = $pageLang->getDir(); + } + $wgOut->addHTML( Html::textarea( $name, $wikitext, $attribs ) ); } @@ -1865,7 +1937,7 @@ HTML $wgOut->addHTML( "
\n\n" ); } - /* + /** * Show an edit conflict. textbox1 is already shown in showEditForm(). * If you want to use another entry point to this function, be careful. */ @@ -1932,7 +2004,7 @@ HTML } else { $note = wfMsg( 'session_fail_preview' ); } - } else if ( $this->incompleteForm ) { + } elseif ( $this->incompleteForm ) { $note = wfMsg( 'edit_form_incomplete' ); } else { $note = wfMsg( 'previewnote' ); @@ -1947,8 +2019,14 @@ HTML if ( $wgRawHtml && !$this->mTokenOk ) { // Could be an offsite preview attempt. This is very unsafe if // HTML is enabled, as it could be an attack. - $parsedNote = $wgOut->parse( "
" . - wfMsg( 'session_fail_preview_html' ) . "
" ); + $parsedNote = ''; + if ( $this->textbox1 !== '' ) { + // Do not put big scary notice, if previewing the empty + // string, which happens when you initially edit + // a category page, due to automatic preview-on-open. + $parsedNote = $wgOut->parse( "
" . + wfMsg( 'session_fail_preview_html' ) . "
" ); + } wfProfileOut( __METHOD__ ); return $parsedNote; } @@ -1993,13 +2071,6 @@ HTML wfRunHooks( 'EditPageGetPreviewText', array( $this, &$toparse ) ); - // Parse mediawiki messages with correct target language - if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) { - list( /* $unused */, $lang ) = MessageCache::singleton()->figureMessage( $this->mTitle->getText() ); - $obj = wfGetLangObj( $lang ); - $parserOptions->setTargetLanguage( $obj ); - } - $parserOptions->setTidy( true ); $parserOptions->enableLimitReport(); $parserOutput = $wgParser->parse( $this->mArticle->preSaveTransform( $toparse ), @@ -2025,14 +2096,26 @@ HTML '

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

" . $wgOut->parse( $note ) . $conflict . "\n"; + global $wgBetterDirectionality; + if( $wgBetterDirectionality ) { + $pageLang = $this->mTitle->getPageLanguage(); + $attribs = array( 'lang' => $pageLang->getCode(), 'dir' => $pageLang->getDir(), + 'class' => 'mw-content-'.$pageLang->getDir() ); + $previewHTML = Html::rawElement( 'div', $attribs, $previewHTML ); + } wfProfileOut( __METHOD__ ); return $previewhead . $previewHTML . $this->previewTextAfterContent; } + /** + * @return Array + */ function getTemplates() { if ( $this->preview || $this->section != '' ) { $templates = array(); - if ( !isset( $this->mParserOutput ) ) return $templates; + if ( !isset( $this->mParserOutput ) ) { + return $templates; + } foreach( $this->mParserOutput->getTemplates() as $ns => $template) { foreach( array_keys( $template ) as $dbk ) { $templates[] = Title::makeTitle($ns, $dbk); @@ -2114,7 +2197,7 @@ HTML * Produce the stock "your edit contains spam" page * * @param $match Text which triggered one or more filters - * @deprecated Use method spamPageWithContent() instead + * @deprecated since 1.17 Use method spamPageWithContent() instead */ static function spamPage( $match = false ) { global $wgOut, $wgTitle; @@ -2168,6 +2251,10 @@ HTML /** * @private * @todo document + * + * @parma $editText string + * + * @return bool */ function mergeChangesInto( &$editText ){ wfProfileIn( __METHOD__ ); @@ -2223,14 +2310,6 @@ HTML return true; } - /** - * @deprecated use $wgParser->stripSectionName() - */ - function pseudoParseSectionAnchor( $text ) { - global $wgParser; - return $wgParser->stripSectionName( $text ); - } - /** * Format an anchor fragment as it would appear for a given section name * @param $text String @@ -2399,11 +2478,10 @@ HTML $paramList = implode( ',', array_map( array( 'Xml', 'encodeJsVar' ), $params ) ); - $script .= "addButton($paramList);\n"; + $script .= "mw.toolbar.addButton($paramList);\n"; } - $wgOut->addScript( Html::inlineScript( - "if ( window.mediaWiki ) { jQuery(function(){{$script}}); }" + "if ( window.mediaWiki ) {{$script}}" ) ); $toolbar .= "\n"; @@ -2429,19 +2507,22 @@ HTML $checkboxes = array(); - $checkboxes['minor'] = ''; - $minorLabel = wfMsgExt( 'minoredit', array( 'parseinline' ) ); - if ( $wgUser->isAllowed( 'minoredit' ) ) { - $attribs = array( - 'tabindex' => ++$tabindex, - 'accesskey' => wfMsg( 'accesskey-minoredit' ), - 'id' => 'wpMinoredit', - ); - $checkboxes['minor'] = - Xml::check( 'wpMinoredit', $checked['minor'], $attribs ) . - " "; + // don't show the minor edit checkbox if it's a new page or section + if ( !$this->isNew ) { + $checkboxes['minor'] = ''; + $minorLabel = wfMsgExt( 'minoredit', array( 'parseinline' ) ); + if ( $wgUser->isAllowed( 'minoredit' ) ) { + $attribs = array( + 'tabindex' => ++$tabindex, + 'accesskey' => wfMsg( 'accesskey-minoredit' ), + 'id' => 'wpMinoredit', + ); + $checkboxes['minor'] = + Xml::check( 'wpMinoredit', $checked['minor'], $attribs ) . + " "; + } } $watchLabel = wfMsgExt( 'watchthis', array( 'parseinline' ) ); @@ -2542,7 +2623,9 @@ HTML echo $s; } - + /** + * @return string + */ public function getCancelLink() { global $wgUser; @@ -2606,6 +2689,11 @@ HTML : $text; } + /** + * @param $request WebRequest + * @param $text string + * @return string + */ function safeUnicodeText( $request, $text ) { $text = rtrim( $text ); return $request->getBool( 'safemode' ) @@ -2650,7 +2738,7 @@ HTML $result = ""; $working = 0; for( $i = 0; $i < strlen( $invalue ); $i++ ) { - $bytevalue = ord( $invalue{$i} ); + $bytevalue = ord( $invalue[$i] ); if ( $bytevalue <= 0x7F ) { //0xxx xxxx $result .= chr( $bytevalue ); $bytesleft = 0; @@ -2687,13 +2775,13 @@ HTML function unmakesafe( $invalue ) { $result = ""; for( $i = 0; $i < strlen( $invalue ); $i++ ) { - if ( ( substr( $invalue, $i, 3 ) == "&#x" ) && ( $invalue{$i+3} != '0' ) ) { + if ( ( substr( $invalue, $i, 3 ) == "&#x" ) && ( $invalue[$i+3] != '0' ) ) { $i += 3; $hexstring = ""; do { - $hexstring .= $invalue{$i}; + $hexstring .= $invalue[$i]; $i++; - } while( ctype_xdigit( $invalue{$i} ) && ( $i < strlen( $invalue ) ) ); + } while( ctype_xdigit( $invalue[$i] ) && ( $i < strlen( $invalue ) ) ); // Do some sanity checks. These aren't needed for reversability, // but should help keep the breakage down if the editor @@ -2798,7 +2886,7 @@ HTML case self::AS_NO_CREATE_PERMISSION: $this->noCreatePermission(); - return; + return false; case self::AS_BLANK_ARTICLE: $wgOut->redirect( $this->getContextTitle()->getFullURL() ); @@ -2810,6 +2898,9 @@ HTML } } + /** + * @return Revision + */ function getBaseRevision() { if ( !$this->mBaseRevision ) { $db = wfGetDB( DB_MASTER );