Merge the iwtransclusion branch back into trunk
[lhc/web/wiklou.git] / includes / EditPage.php
index 7dc1c0a..20a1f48 100644 (file)
@@ -374,9 +374,6 @@ class EditPage {
                wfProfileIn( __METHOD__ );
                wfDebug( __METHOD__.": enter\n" );
 
-               // This is not an article
-               $wgOut->setArticleFlag( false );
-
                $this->importFormData( $wgRequest );
                $this->firsttime = false;
 
@@ -792,7 +789,7 @@ class EditPage {
                        $ip = User::isIP( $username );
                        if ( !$user->isLoggedIn() && !$ip ) { # User does not exist
                                $wgOut->wrapWikiMsg( "<div class=\"mw-userpage-userdoesnotexist error\">\n$1\n</div>",
-                                       array( 'userpage-userdoesnotexist', $username ) );
+                                       array( 'userpage-userdoesnotexist', wfEscapeWikiText( $username ) ) );
                        } elseif ( $user->isBlocked() ) { # Show log extract if the user is currently blocked
                                LogEventsList::showLogExtract(
                                        $wgOut,
@@ -859,7 +856,7 @@ class EditPage {
         * @return int one of the constants describing the result
         */
        function internalAttemptSave( &$result, $bot = false ) {
-               global $wgFilterCallback, $wgUser, $wgParser;
+               global $wgFilterCallback, $wgUser, $wgRequest, $wgParser;
                global $wgMaxArticleSize;
 
                wfProfileIn( __METHOD__  );
@@ -891,7 +888,7 @@ class EditPage {
                }
                if ( $match !== false ) {
                        $result['spam'] = $match;
-                       $ip = wfGetIP();
+                       $ip = $wgRequest->getIP();
                        $pdbk = $this->mTitle->getPrefixedDBkey();
                        $match = str_replace( "\n", '', $match );
                        wfDebugLog( 'SpamRegex', "$ip spam regex hit [[$pdbk]]: \"$match\"" );
@@ -1031,15 +1028,12 @@ class EditPage {
                                                $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;
                                }
                        }
-                       $userid = $wgUser->getId();
-
-                       # Suppress edit conflict with self, except for section edits where merging is required.
-                       if ( $this->isConflict && $this->section == '' && $this->userWasLastToEdit( $userid, $this->edittime ) ) {
-                               wfDebug( __METHOD__ . ": Suppressing edit conflict, same user.\n" );
-                               $this->isConflict = false;
-                       }
 
                        if ( $this->isConflict ) {
                                wfDebug( __METHOD__ . ": conflict! getting section '$this->section' for time '$this->edittime' (article time '" .
@@ -1071,8 +1065,6 @@ class EditPage {
                                return self::AS_CONFLICT_DETECTED;
                        }
 
-                       $oldtext = $this->mArticle->getContent();
-
                        // Run post-section-merge edit filter
                        if ( !wfRunHooks( 'EditFilterMerged', array( $this, $text, &$this->hookError, $this->summary ) ) ) {
                                # Error messages etc. could be handled within the hook...
@@ -1085,7 +1077,8 @@ class EditPage {
                        }
 
                        # Handle the user preference to force summaries here, but not for null edits
-                       if ( $this->section != 'new' && !$this->allowBlankSummary && 0 != strcmp( $oldtext, $text )
+                       if ( $this->section != 'new' && !$this->allowBlankSummary
+                               && 0 != strcmp( $this->mArticle->getContent(), $text )
                                && !Title::newFromRedirect( $text ) ) # check if it's not a redirect
                        {
                                if ( md5( $this->summary ) == $this->autoSumm ) {
@@ -1320,12 +1313,10 @@ class EditPage {
         *     during form output near the top, for captchas and the like.
         */
        function showEditForm( $formCallback = null ) {
-               global $wgOut, $wgUser;
+               global $wgOut, $wgUser, $wgEnableInterwikiTranscluding, $wgEnableInterwikiTemplatesTracking;
 
                wfProfileIn( __METHOD__ );
 
-               $sk = $wgUser->getSkin();
-
                #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
@@ -1356,7 +1347,6 @@ class EditPage {
                        $toolbar = '';
                }
 
-
                $wgOut->addHTML( $this->editFormPageTop );
 
                if ( $wgUser->getOption( 'previewontop' ) ) {
@@ -1366,10 +1356,13 @@ class EditPage {
                $wgOut->addHTML( $this->editFormTextTop );
 
                $templates = $this->getTemplates();
-               $formattedtemplates = $sk->formatTemplates( $templates, $this->preview, $this->section != '');
+               $formattedtemplates = Linker::formatTemplates( $templates, $this->preview, $this->section != '');
+
+               $distantTemplates = $this->getDistantTemplates();
+               $formattedDistantTemplates = Linker::formatDistantTemplates( $distantTemplates, $this->preview, $this->section != '' );
 
                $hiddencats = $this->mArticle->getHiddenCategories();
-               $formattedhiddencats = $sk->formatHiddenCategories( $hiddencats );
+               $formattedhiddencats = Linker::formatHiddenCategories( $hiddencats );
 
                if ( $this->wasDeletedSinceLastEdit() && 'save' != $this->formtype ) {
                        $wgOut->wrapWikiMsg(
@@ -1408,7 +1401,7 @@ HTML
                                '<div class="mw-confirm-recreate">' .
                                wfMsgExt( $key, 'parseinline', $username, "<nowiki>$comment</nowiki>" ) .
                                Xml::checkLabel( wfMsg( 'recreate' ), 'wpRecreate', 'wpRecreate', false,
-                                       array( 'title' => $sk->titleAttrib( 'recreate' ), 'tabindex' => 1, 'id' => 'wpRecreate' )
+                                       array( 'title' => Linker::titleAttrib( 'recreate' ), 'tabindex' => 1, 'id' => 'wpRecreate' )
                                ) .
                                '</div>'
                        );
@@ -1466,6 +1459,21 @@ HTML
 <div class='templatesUsed'>
 {$formattedtemplates}
 </div>
+HTML
+);
+
+               if ( $wgEnableInterwikiTranscluding && $wgEnableInterwikiTemplatesTracking ) {
+                                       $wgOut->addHTML( <<<HTML
+{$this->editFormTextAfterTools}
+<div class='distantTemplatesUsed'>
+{$formattedDistantTemplates}
+</div>
+HTML
+);
+               }
+
+               $wgOut->addHTML( <<<HTML
+{$this->editFormTextAfterTools}
 <div class='hiddencats'>
 {$formattedhiddencats}
 </div>
@@ -1634,7 +1642,6 @@ HTML
         * @return array An array in the format array( $label, $input )
         */
        function getSummaryInput($summary = "", $labelText = null, $inputAttrs = null, $spanLabelAttrs = null) {
-               global $wgUser;
                //Note: the maxlength is overriden in JS to 250 and to make it use UTF-8 bytes, not characters.
                $inputAttrs = ( is_array($inputAttrs) ? $inputAttrs : array() ) + array(
                        'id' => 'wpSummary',
@@ -1642,7 +1649,7 @@ HTML
                        'tabindex' => '1',
                        'size' => 60,
                        'spellcheck' => 'true',
-               ) + $wgUser->getSkin()->tooltipAndAccessKeyAttribs( 'summary' );
+               ) + Linker::tooltipAndAccesskeyAttribs( 'summary' );
 
                $spanLabelAttrs = ( is_array($spanLabelAttrs) ? $spanLabelAttrs : array() ) + array(
                        'class' => $this->missingSummary ? 'mw-summarymissed' : 'mw-summary',
@@ -1697,15 +1704,14 @@ HTML
                if ( !$summary || ( !$this->preview && !$this->diff ) )
                        return "";
 
-               global $wgParser, $wgUser;
-               $sk = $wgUser->getSkin();
+               global $wgParser;
 
                if ( $isSubjectPreview )
                        $summary = wfMsgForContent( 'newsectionsummary', $wgParser->stripSectionName( $summary ) );
 
                $message = $isSubjectPreview ? 'subject-preview' : 'summary-preview';
 
-               $summary = wfMsgExt( $message, 'parseinline' ) . $sk->commentBlock( $summary, $this->mTitle, $isSubjectPreview );
+               $summary = wfMsgExt( $message, 'parseinline' ) . Linker::commentBlock( $summary, $this->mTitle, $isSubjectPreview );
                return Xml::tags( 'div', array( 'class' => 'mw-summary-preview' ), $summary );
        }
 
@@ -1815,12 +1821,9 @@ HTML
                        'style' => '' // avoid php notices when appending preferences (appending allows customAttribs['style'] to still work
                );
 
-               global $wgBetterDirectionality, $wgContLang;
-               if( $wgBetterDirectionality ) {
-                       $pageLang = $this->mTitle->getPageLanguage();
-                       $attribs['lang'] = $pageLang->getCode();
-                       $attribs['dir'] = $pageLang->getDir();
-               }
+               $pageLang = $this->mTitle->getPageLanguage();
+               $attribs['lang'] = $pageLang->getCode();
+               $attribs['dir'] = $pageLang->getDir();
 
                $wgOut->addHTML( Html::textarea( $name, $wikitext, $attribs ) );
        }
@@ -1883,16 +1886,16 @@ HTML
                if( !wfMessage( $msg )->isDisabled() ) {
                        global $wgOut;
                        $wgOut->addHTML( '<div class="mw-tos-summary">' );
-                       $wgOut->addWikiMsgArray( $msg, array() );
+                       $wgOut->addWikiMsg( $msg );
                        $wgOut->addHTML( '</div>' );
                }
        }
 
        protected function showEditTools() {
                global $wgOut;
-               $wgOut->addHTML( '<div class="mw-editTools">' );
-               $wgOut->addWikiMsgArray( 'edittools', array(), array( 'content' ) );
-               $wgOut->addHTML( '</div>' );
+               $wgOut->addHTML( '<div class="mw-editTools">' .
+                       wfMessage( 'edittools' )->inContentLanguage()->parse() .
+                       '</div>' );
        }
 
        protected function getCopywarn() {
@@ -1913,7 +1916,7 @@ HTML
        }
 
        protected function showStandardInputs( &$tabindex = 2 ) {
-               global $wgOut, $wgUser;
+               global $wgOut;
                $wgOut->addHTML( "<div class='editOptions'>\n" );
 
                if ( $this->section != 'new' ) {
@@ -1921,19 +1924,21 @@ HTML
                        $wgOut->addHTML( $this->getSummaryPreview( false, $this->summary ) );
                }
 
-               $checkboxes = $this->getCheckboxes( $tabindex, $wgUser->getSkin(),
+               $checkboxes = $this->getCheckboxes( $tabindex,
                        array( 'minor' => $this->minoredit, 'watch' => $this->watchthis ) );
                $wgOut->addHTML( "<div class='editCheckboxes'>" . implode( $checkboxes, "\n" ) . "</div>\n" );
                $wgOut->addHTML( "<div class='editButtons'>\n" );
                $wgOut->addHTML( implode( $this->getEditButtons( $tabindex ), "\n" ) . "\n" );
 
                $cancel = $this->getCancelLink();
-               $separator = wfMsgExt( 'pipe-separator' , 'escapenoentities' );
+               if ( $cancel !== '' ) {
+                       $cancel .= wfMsgExt( 'pipe-separator' , 'escapenoentities' );
+               }
                $edithelpurl = Skin::makeInternalOrExternalUrl( wfMsgForContent( 'edithelppage' ) );
                $edithelp = '<a target="helpwindow" href="'.$edithelpurl.'">'.
                        htmlspecialchars( wfMsg( 'edithelp' ) ).'</a> '.
                        htmlspecialchars( wfMsg( 'newwindow' ) );
-               $wgOut->addHTML( "      <span class='editHelp'>{$cancel}{$separator}{$edithelp}</span>\n" );
+               $wgOut->addHTML( "      <span class='editHelp'>{$cancel}{$edithelp}</span>\n" );
                $wgOut->addHTML( "</div><!-- editButtons -->\n</div><!-- editOptions -->\n" );
        }
 
@@ -2019,31 +2024,42 @@ 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( "<div class='previewnote'>" .
-                               wfMsg( 'session_fail_preview_html' ) . "</div>" );
+                       $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( "<div class='previewnote'>" .
+                                       wfMsg( 'session_fail_preview_html' ) . "</div>" );
+                       }
                        wfProfileOut( __METHOD__ );
                        return $parsedNote;
                }
 
-               # don't parse user css/js, show message about preview
+               # 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?
 
-               if ( $this->isCssJsSubpage || $this->mTitle->isCssOrJsPage() ) {
-                       $level = 'user';
-                       if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
+               if ( $this->isCssJsSubpage || !$this->mTitle->isWikitextPage() ) {
+                       if( $this->mTitle->isCssJsSubpage() ) {
+                               $level = 'user';
+                       } elseif( $this->mTitle->isCssOrJsPage() ) {
                                $level = 'site';
+                       } else {
+                               $level = false;
                        }
 
                        # Used messages to make sure grep find them:
                        # Messages: usercsspreview, userjspreview, sitecsspreview, sitejspreview
-                       if (preg_match( "/\\.css$/", $this->mTitle->getText() ) ) {
-                               $previewtext = "<div id='mw-{$level}csspreview'>\n" . wfMsg( "{$level}csspreview" ) . "\n</div>";
-                               $class = "mw-code mw-css";
-                       } elseif (preg_match( "/\\.js$/", $this->mTitle->getText() ) ) {
-                               $previewtext = "<div id='mw-{$level}jspreview'>\n" . wfMsg( "{$level}jspreview" ) . "\n</div>";
-                               $class = "mw-code mw-js";
-                       } else {
-                               throw new MWException( 'A CSS/JS (sub)page but which is not css nor js!' );
+                       if( $level ) {
+                               if (preg_match( "/\\.css$/", $this->mTitle->getText() ) ) {
+                                       $previewtext = "<div id='mw-{$level}csspreview'>\n" . wfMsg( "{$level}csspreview" ) . "\n</div>";
+                                       $class = "mw-code mw-css";
+                               } elseif (preg_match( "/\\.js$/", $this->mTitle->getText() ) ) {
+                                       $previewtext = "<div id='mw-{$level}jspreview'>\n" . wfMsg( "{$level}jspreview" ) . "\n</div>";
+                                       $class = "mw-code mw-js";
+                               } else {
+                                       throw new MWException( 'A CSS/JS (sub)page but which is not css nor js!' );
+                               }
                        }
 
                        $parserOptions->setTidy( true );
@@ -2065,12 +2081,6 @@ HTML
 
                                wfRunHooks( 'EditPageGetPreviewText', array( $this, &$toparse ) );
 
-                               // In which language to parse the page
-                               // (Should this still be only for MediaWiki pages, or for all pages?)
-                               if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
-                                       $parserOptions->setTargetLanguage( $this->mTitle->getPageLanguage() );
-                               }
-                               $parserOptions->setTargetLanguage( $this->mTitle->getPageLanguage() );
                                $parserOptions->setTidy( true );
                                $parserOptions->enableLimitReport();
                                $parserOutput = $wgParser->parse( $this->mArticle->preSaveTransform( $toparse ),
@@ -2096,12 +2106,11 @@ HTML
                        '<h2 id="mw-previewheader">' . htmlspecialchars( wfMsg( 'preview' ) ) . "</h2>" .
                        $wgOut->parse( $note ) . $conflict . "</div>\n";
 
-               global $wgBetterDirectionality;
-               if( $wgBetterDirectionality ) {
-                       $pageLang = $this->mTitle->getPageLanguage();
-                       $attribs = array( 'lang' => $pageLang->getCode(), 'dir' => $pageLang->getDir() );
-                       $previewHTML = Html::rawElement( 'div', $attribs, $previewHTML );
-               }
+               $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;
        }
@@ -2126,6 +2135,28 @@ HTML
                }
        }
 
+       function getDistantTemplates() {
+               global $wgEnableInterwikiTemplatesTracking;
+               if ( !$wgEnableInterwikiTemplatesTracking ) {
+                       return array( );
+               }
+               if ( $this->preview || $this->section != '' ) {
+                       $templates = array();
+                       if ( !isset( $this->mParserOutput ) ) return $templates;
+                       $templatesList = $this->mParserOutput->getDistantTemplates();
+                       foreach( $templatesList as $prefix => $templatesbyns ) {
+                               foreach( $templatesbyns as $ns => $template ) {
+                                       foreach( array_keys( $template ) as $dbk ) {
+                                               $templates[] = Title::makeTitle( $ns, $dbk, null, $prefix );
+                                       }
+                               }
+                       }
+                       return $templates;
+               } else {
+                       return $this->mArticle->getUsedDistantTemplates();
+               }
+       }
+
        /**
         * Call the stock "user is blocked" page
         */
@@ -2154,23 +2185,21 @@ HTML
         * Produce the stock "please login to edit pages" page
         */
        function userNotLoggedInPage() {
-               global $wgUser, $wgOut;
-               $skin = $wgUser->getSkin();
+               global $wgOut;
 
                $loginTitle = SpecialPage::getTitleFor( 'Userlogin' );
-               $loginLink = $skin->link(
+               $loginLink = Linker::linkKnown(
                        $loginTitle,
                        wfMsgHtml( 'loginreqlink' ),
                        array(),
-                       array( 'returnto' => $this->getContextTitle()->getPrefixedText() ),
-                       array( 'known', 'noclasses' )
+                       array( 'returnto' => $this->getContextTitle()->getPrefixedText() )
                );
 
                $wgOut->setPageTitle( wfMsg( 'whitelistedittitle' ) );
                $wgOut->setRobotPolicy( 'noindex,nofollow' );
                $wgOut->setArticleRelated( false );
 
-               $wgOut->addWikiMsgArray( 'whitelistedittext', array( $loginLink ), array( 'replaceafter' ) );
+               $wgOut->addHTML( wfMessage( 'whitelistedittext' )->rawParams( $loginLink )->parse() );
                $wgOut->returnToMain( false, $this->getContextTitle() );
        }
 
@@ -2338,10 +2367,8 @@ HTML
                 * filename of the button image (without path), the opening
                 * tag, the closing tag, optionally a sample text that is
                 * inserted between the two when no selection is highlighted
-                * and an option to select which switches the automatic
-                * selection of inserted text (default is true, see
-                * mw-editbutton-image).  The tip text is shown when the user
-                * moves the mouse over the button.
+                * and.  The tip text is shown when the user moves the mouse
+                * over the button.
                 *
                 * Also here: accesskeys (key), which are not used yet until
                 * someone can figure out a way to make them work in
@@ -2402,7 +2429,6 @@ HTML
                                'sample' => wfMsg( 'image_sample' ),
                                'tip'    => wfMsg( 'image_tip' ),
                                'key'    => 'D',
-                               'select' => true
                        ) : false,
                        $imagesAvailable ? array(
                                'image'  => $wgLang->getImageFile( 'button-media' ),
@@ -2458,10 +2484,6 @@ HTML
                                continue;
                        }
 
-                       if( !isset( $tool['select'] ) ) {
-                         $tool['select'] = true;
-                       }
-
                        $params = array(
                                $image = $wgStylePath . '/common/images/' . $tool['image'],
                                // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
@@ -2495,13 +2517,12 @@ HTML
         * minor and watch
         *
         * @param $tabindex Current tabindex
-        * @param $skin Skin object
         * @param $checked Array of checkbox => bool, where bool indicates the checked
         *                 status of the checkbox
         *
         * @return array
         */
-       public function getCheckboxes( &$tabindex, $skin, $checked ) {
+       public function getCheckboxes( &$tabindex, $checked ) {
                global $wgUser;
 
                $checkboxes = array();
@@ -2519,7 +2540,7 @@ HTML
                                $checkboxes['minor'] =
                                        Xml::check( 'wpMinoredit', $checked['minor'], $attribs ) .
                                        "&#160;<label for='wpMinoredit' id='mw-editpage-minoredit'" .
-                                       Xml::expandAttributes( array( 'title' => $skin->titleAttrib( 'minoredit', 'withaccess' ) ) ) .
+                                       Xml::expandAttributes( array( 'title' => Linker::titleAttrib( 'minoredit', 'withaccess' ) ) ) .
                                        ">{$minorLabel}</label>";
                        }
                }
@@ -2535,7 +2556,7 @@ HTML
                        $checkboxes['watch'] =
                                Xml::check( 'wpWatchthis', $checked['watch'], $attribs ) .
                                "&#160;<label for='wpWatchthis' id='mw-editpage-watch'" .
-                               Xml::expandAttributes( array( 'title' => $skin->titleAttrib( 'watch', 'withaccess' ) ) ) .
+                               Xml::expandAttributes( array( 'title' => Linker::titleAttrib( 'watch', 'withaccess' ) ) ) .
                                ">{$watchLabel}</label>";
                }
                wfRunHooks( 'EditPageBeforeEditChecks', array( &$this, &$checkboxes, &$tabindex ) );
@@ -2626,19 +2647,16 @@ HTML
         * @return string
         */
        public function getCancelLink() {
-               global $wgUser;
-
                $cancelParams = array();
                if ( !$this->isConflict && $this->mArticle->getOldID() > 0 ) {
                        $cancelParams['oldid'] = $this->mArticle->getOldID();
                }
 
-               return $wgUser->getSkin()->link(
+               return Linker::linkKnown(
                        $this->getContextTitle(),
                        wfMsgExt( 'cancel', array( 'parseinline' ) ),
                        array( 'id' => 'mw-editform-cancel' ),
-                       $cancelParams,
-                       array( 'known', 'noclasses' )
+                       $cancelParams
                );
        }