Comments and whitespace fixes only.
[lhc/web/wiklou.git] / includes / OutputPage.php
index 38754f2..de839bf 100644 (file)
@@ -15,8 +15,9 @@ class OutputPage {
        var $mCategoryLinks = array(), $mLanguageLinks = array();
 
        var $mScriptLoaderClassList = array();
-       // the most recent id of any script that is grouped in the script request
-       var $mLatestScriptRevID = 0; 
+
+       // The most recent revision ID of any script that is grouped in the script request
+       var $mLatestScriptRevID = 0;
 
        var $mScripts = '', $mLinkColours, $mPageLinkTitle = '', $mHeadItems = array();
        var $mTemplateIds = array();
@@ -97,18 +98,19 @@ class OutputPage {
                        array_push( $this->mKeywords, $text );
                }
        }
-       function addScript( $script ) { $this->mScripts .= "\t\t" . $script . "\n"; }
+       function addScript( $script ) {
+               $this->mScripts .= $script . "\n";
+       }
 
        /**
-        * Register and add a stylesheet from an extension directory.  
+        * Register and add a stylesheet from an extension directory.
         * @param $url String path to sheet.  Provide either a full url (beginning
         *             with 'http', etc) or a relative path from the document root
         *             (beginning with '/').  Otherwise it behaves identically to
         *             addStyle() and draws from the /skins folder.
         */
        public function addExtensionStyle( $url ) {
-               $linkarr = array( 'rel' => 'stylesheet', 'href' => $url, 'type' => 'text/css' );
-               array_push( $this->mExtStyles, $linkarr );
+               array_push( $this->mExtStyles, $url );
        }
 
        /**
@@ -116,7 +118,7 @@ class OutputPage {
         * @param string $file filename in skins/common or complete on-server path (/foo/bar.js)
         */
        function addScriptFile( $file ) {
-               global $wgStylePath, $wgStyleVersion, $wgJsMimeType, $wgScript, $wgUser;
+               global $wgStylePath, $wgScript, $wgUser;
                global $wgJSAutoloadClasses, $wgJSAutoloadLocalClasses, $wgEnableScriptLoader, $wgScriptPath;
 
                if( substr( $file, 0, 1 ) == '/' ) {
@@ -125,25 +127,27 @@ class OutputPage {
                        $path = "{$wgStylePath}/common/{$file}";
                }
 
-               if( $wgEnableScriptLoader ){
-                       if( strpos( $path, $wgScript ) !== false ){
+               if( $wgEnableScriptLoader ) {
+                       if( strpos( $path, $wgScript ) !== false ) {
                                $reqPath = str_replace( $wgScript . '?', '', $path );
                                $reqArgs = explode( '&', $reqPath );
                                $reqSet = array();
 
-                               foreach( $reqArgs as $arg ){
+                               foreach( $reqArgs as $arg ) {
                                        list( $key, $var ) = explode( '=', $arg );
                                        $reqSet[$key] = $var;
                                }
 
                                if( isset( $reqSet['title'] ) && $reqSet != '' ) {
-                                       // extract any extra param (for now just skin)
-                                       $ext_param = ( isset( $reqSet['useskin'] ) && $reqSet['useskin'] != '' ) ? '|useskin=' . ucfirst( $reqSet['useskin'] ) : '';
+                                       // Extract any extra parameters (for now just skin)
+                                       $ext_param = ( isset( $reqSet['useskin'] ) && $reqSet['useskin'] != '' )
+                                               ? '|useskin=' . ucfirst( $reqSet['useskin'] ) : '';
                                        $this->mScriptLoaderClassList[] = 'WT:' . $reqSet['title'] . $ext_param ;
-                                       // add the title revision to the key
+                                       // Add the title revision to the key.
+                                       // If there is no title, we will just use $wgStyleVersion, 
+                                       // which should be updated on the relevant commits.
                                        $t = Title::newFromText( $reqSet['title'] );
-                                       // if there is no title (don't worry we just use the $wgStyleVersion var (which should be updated on relevant commits)
-                                       if( $t && $t->exists() ){
+                                       if( $t && $t->exists() ) {
                                                if( $t->getLatestRevID() > $this->mLatestScriptRevID  )
                                                        $this->mLatestScriptRevID = $t->getLatestRevID();
                                        }
@@ -151,35 +155,24 @@ class OutputPage {
                                }
                        }
 
-                       // check for class from path:
+                       // If the class can be determined, add it to the class list to be loaded later
                        $js_class = $this->getJsClassFromPath( $path );
-                       if( $js_class ){
-                               // add to the class list:
+                       if( $js_class ) {
                                $this->mScriptLoaderClassList[] = $js_class;
                                return true;
                        }
                }
 
-               // if the script loader did not find a way to add the script than add using addScript
-               $this->addScript(
-                       Xml::element( 'script',
-                               array(
-                                       'type' => $wgJsMimeType,
-                                       'src' => wfAppendQuery( $path, $this->getURIDparam() ),
-                               ),
-                               '', false
-                       )
-               );
+               // If the script loader could not be used, just add the script to the header
+               $this->addScript( Html::linkedScript( wfAppendQuery( $path, $this->getURIDparam() ) ) );
        }
 
        /**
-        * This is the core script that is included on every page
-        * (they are requested separately to improve caching across
-        *  different page load types (edit, upload, view, etc)
+        * Add the core scripts that are included on every page, for later output into the header
         */
        function addCoreScripts2Top(){
-               global $wgEnableScriptLoader, $wgStyleVersion, $wgJSAutoloadLocalClasses, $wgJsMimeType, $wgScriptPath, $wgEnableJS2system;
-               //@@todo we should deprecate wikibits in favor of mv_embed and native jQuery functions
+               global $wgEnableScriptLoader, $wgJSAutoloadLocalClasses, $wgScriptPath, $wgEnableJS2system;
+               // @todo We should deprecate wikibits in favor of mv_embed and jQuery
 
                if( $wgEnableJS2system ){
                        $core_classes = array( 'window.jQuery', 'mv_embed', 'wikibits' );
@@ -193,12 +186,7 @@ class OutputPage {
                        $so = '';
                        foreach( $core_classes as $s ){
                                if( isset( $wgJSAutoloadLocalClasses[$s] ) ){
-                                       $so.= Xml::element( 'script', array(
-                                                       'type' => $wgJsMimeType,
-                                                       'src' => "{$wgScriptPath}/{$wgJSAutoloadLocalClasses[$s]}?" . $this->getURIDparam()
-                                               ),
-                                               '', false
-                                       );
+                                       $so .= Html::linkedScript( "{$wgScriptPath}/{$wgJSAutoloadLocalClasses[$s]}?" . $this->getURIDparam() );
                                }
                        }
                        $this->mScripts =  $so . $this->mScripts;
@@ -206,32 +194,31 @@ class OutputPage {
        }
 
        /**
-        * @param $js_class String: name of JavaScript class
-        * @return Boolean: false if class wasn't found, true on success
+        * @param $js_class string Name of the JavaScript class
+        * @return boolean False if the class wasn't found, true on success
         */
        function addScriptClass( $js_class ){
-               global $wgJSAutoloadClasses, $wgJSAutoloadLocalClasses, $wgJsMimeType,
+               global $wgDebugJavaScript, $wgJSAutoloadLocalClasses, $wgJSAutoloadClasses,
                                $wgEnableScriptLoader, $wgStyleVersion, $wgScriptPath;
 
-               if( isset( $wgJSAutoloadClasses[$js_class] ) || isset( $wgJSAutoloadLocalClasses[$js_class] ) ){
-                       if( $wgEnableScriptLoader ){
-                               if( !in_array( $js_class, $this->mScriptLoaderClassList ) ){
+               if( isset( $wgJSAutoloadClasses[$js_class] ) 
+                       || isset( $wgJSAutoloadLocalClasses[$js_class] ) ) 
+               {
+                       if( $wgEnableScriptLoader ) {
+                               // Register it with the script loader
+                               if( !in_array( $js_class, $this->mScriptLoaderClassList ) ) {
                                        $this->mScriptLoaderClassList[] = $js_class;
                                }
                        } else {
-                               // do a normal load of without the script-loader:
+                               // Source the script directly
                                $path = $wgScriptPath . '/';
-                               $path.= isset( $wgJSAutoloadClasses[$js_class] ) ? $wgJSAutoloadClasses[$js_class]:
-                                                       $wgJSAutoloadLocalClasses[$js_class];
-                               $this->addScript(
-                                       Xml::element( 'script',
-                                               array(
-                                                       'type' => $wgJsMimeType,
-                                                       'src' => "$path?$wgStyleVersion",
-                                               ),
-                                               '', false
-                                       )
-                               );
+                               if( isset( $wgJSAutoloadClasses[$js_class] ) ) {
+                                       $path .= $wgJSAutoloadClasses[$js_class];
+                               } elseif( isset( $wgJSAutoloadLocalClasses[$js_class] ) ) {
+                                       $path .= $wgJSAutoloadLocalClasses[$js_class];
+                               }
+                               $urlAppend = ( $wgDebugJavaScript ) ? time() : $wgStyleVersion;
+                               $this->addScript( Html::linkedScript( "$path?$urlAppend" ) );
                        }
                        return true;
                }
@@ -240,52 +227,68 @@ class OutputPage {
        }
 
        /**
-        * gets the scriptLoader javascript include
-        * @param $forcClassAry Boolean: false by default
+        * Get the <script> tag which will invoke the script loader
+        * @param $classAry A class array which, if given, overrides $this->mScriptLoaderClassList
         */
-       function getScriptLoaderJs( $forceClassAry = false ){
-               global $wgJsMimeType, $wgStyleVersion, $wgRequest, $wgDebugJavaScript;
-
-               if( !$forceClassAry ){
-                       $class_list = implode( ',', $this->mScriptLoaderClassList );
-               } else {
-                       $class_list = implode( ',', $forceClassAry );
+       function getScriptLoaderJs( $classAry = array() ) {
+               global $wgRequest, $wgDebugJavaScript;
+               // If no class array was provided, use mScriptLoaderClassList
+               if( !count( $classAry ) ) {
+                       $classAry = $this->mScriptLoaderClassList;
                }
+               $class_list = implode( ',', $classAry );
 
                $debug_param = ( $wgDebugJavaScript ||
                                                 $wgRequest->getVal( 'debug' ) == 'true' ||
                                                 $wgRequest->getVal( 'debug' ) == '1' )
                                         ? '&debug=true' : '';
 
-               //@@todo intelligent unique id generation based on svn version of file (rather than just grabbing the $wgStyleVersion var)
-               //@@todo we should check the packaged message text in this javascript file for updates and update the $mScriptLoaderURID id (in getJsClassFromPath)
-
-               //generate the unique request param (combine with the most recent revision id of any wiki page with the $wgStyleVersion var)
-
-
-               return Xml::element( 'script',
-                               array(
-                                       'type' => $wgJsMimeType,
-                                       'src' => wfScript( 'mwScriptLoader' ) . "?class={$class_list}{$debug_param}&".$this->getURIDparam(),
-                               ),
-                               '', false
-               );
+               return Html::linkedScript( wfScript( 'mwScriptLoader' ) . 
+                       "?class={$class_list}{$debug_param}&" . $this->getURIDparam( $classAry) );
        }
 
-       function getURIDparam(){
-               global $wgDebugJavaScript, $wgStyleVersion;
-               if( $wgDebugJavaScript ){
+       /**
+        * Get the unique request ID parameter for the script-loader request
+        */
+       function getURIDparam( $classAry = array() ) {
+               global $wgDebugJavaScript, $wgStyleVersion, $IP, $wgScriptModifiedCheck;
+               if( $wgDebugJavaScript ) {
                        return 'urid=' . time();
                } else {
-                       return "urid={$wgStyleVersion}_{$this->mLatestScriptRevID}";
+                       $ftime=0;
+                       if($wgScriptModifiedCheck) {
+                               foreach( $classAry as $class ) {
+                                       $js_path =  jsScriptLoader::getJsPathFromClass( $class );
+                                       if( $js_path ) {
+                                               $cur_ftime = filemtime ( $IP ."/". $js_path );
+                                               if( $cur_ftime > $ftime )
+                                                       $ftime = $cur_ftime;
+                                       }
+                               }
+                       }
+                       $urid = "urid={$wgStyleVersion}";
+
+                       // Add the latest revision ID if we have it
+                       if($this->mLatestScriptRevID != 0 )
+                               $urid .= "_{$this->mLatestScriptRevID}";
+
+                       // Add the file modification time
+                       if( $ftime != 0 )
+                               $urid .= "_".$ftime;
+
+                       return $urid;
                }
        }
 
-       function getJsClassFromPath( $path ){
+       /**
+        * Given a script path, get the JS class name, or false if no such path is registered.
+        * @param $path string
+        */
+       function getJsClassFromPath( $path ) {
                global $wgJSAutoloadClasses, $wgJSAutoloadLocalClasses, $wgScriptPath;
 
                $scriptLoaderPaths = array_merge( $wgJSAutoloadClasses,  $wgJSAutoloadLocalClasses );
-               foreach( $scriptLoaderPaths as $js_class => $js_path ){
+               foreach( $scriptLoaderPaths as $js_class => $js_path ) {
                        $js_path = "{$wgScriptPath}/{$js_path}";
                        if( $path == $js_path )
                                return $js_class;
@@ -298,14 +301,15 @@ class OutputPage {
         * @param string $script JavaScript text, no <script> tags
         */
        function addInlineScript( $script ) {
-               global $wgJsMimeType;
-               $this->mScripts .= "\t\t<script type=\"$wgJsMimeType\">/*<![CDATA[*/\n\t\t$script\n\t\t/*]]>*/</script>\n";
+               $this->mScripts .= Html::inlineScript( "\n$script\n" ) . "\n";
        }
 
+       /**
+        * Get all registered JS and CSS tags for the header.
+        */
        function getScript() {
                global $wgEnableScriptLoader;
                if( $wgEnableScriptLoader ){
-                       //include $this->mScripts (for anything that we could not package into the scriptloader
                        return $this->mScripts . "\n" . $this->getScriptLoaderJs() . $this->getHeadItems();
                } else {
                        return $this->mScripts . $this->getHeadItems();
@@ -330,7 +334,7 @@ class OutputPage {
 
        function setETag($tag) { $this->mETag = $tag; }
        function setArticleBodyOnly($only) { $this->mArticleBodyOnly = $only; }
-       function getArticleBodyOnly($only) { return $this->mArticleBodyOnly; }
+       function getArticleBodyOnly() { return $this->mArticleBodyOnly; }
 
        function addLink( $linkarr ) {
                # $linkarr should be an associative array of attributes. We'll escape on output.
@@ -458,22 +462,14 @@ class OutputPage {
         * @return null
         */
        public function setRobotPolicy( $policy ) {
-               $policy = explode( ',', $policy );
-               $policy = array_map( 'trim', $policy );
-
-               # The default policy is follow, so if nothing is said explicitly, we
-               # do that.
-               if( in_array( 'nofollow', $policy ) ) {
-                       $this->mFollowPolicy = 'nofollow';
-               } else {
-                       $this->mFollowPolicy = 'follow';
-               }
+               $policy = Article::formatRobotPolicy( $policy );
 
-               if( in_array( 'noindex', $policy ) ) {
-                       $this->mIndexPolicy = 'noindex';
-               } else {
-                       $this->mIndexPolicy = 'index';
-               }
+               if( isset( $policy['index'] ) ){
+                       $this->setIndexPolicy( $policy['index'] );
+               }
+               if( isset( $policy['follow'] ) ){
+                       $this->setFollowPolicy( $policy['follow'] );
+               }
        }
 
        /**
@@ -745,17 +741,6 @@ class OutputPage {
                $this->mNewSectionLink = $parserOutput->getNewSection();
                $this->mHideNewSectionLink = $parserOutput->getHideNewSection();
 
-               if( is_null( $wgExemptFromUserRobotsControl ) ) {
-                       $bannedNamespaces = $wgContentNamespaces;
-               } else {
-                       $bannedNamespaces = $wgExemptFromUserRobotsControl;
-               }
-               if( !in_array( $this->getTitle()->getNamespace(), $bannedNamespaces ) ) {
-                       # FIXME (bug 14900): This overrides $wgArticleRobotPolicies, and it
-                       # shouldn't
-                       $this->setIndexPolicy( $parserOutput->getIndexPolicy() );
-               }
-
                $this->mParseWarnings = $parserOutput->getWarnings();
                if ( $parserOutput->getCacheTime() == -1 ) {
                        $this->enableClientCache( false );
@@ -1050,7 +1035,7 @@ class OutputPage {
        public function output() {
                global $wgUser, $wgOutputEncoding, $wgRequest;
                global $wgContLanguageCode, $wgDebugRedirects, $wgMimeType;
-               global $wgJsMimeType, $wgUseAjax, $wgAjaxWatch;
+               global $wgUseAjax, $wgAjaxWatch;
                global $wgEnableMWSuggest, $wgUniversalEditButton;
                global $wgArticle;
 
@@ -1138,7 +1123,7 @@ class OutputPage {
 
                $sk = $wgUser->getSkin();
 
-               // add our core scripts to output
+               // Add our core scripts to output
                $this->addCoreScripts2Top();
 
                if ( $wgUseAjax ) {
@@ -1159,20 +1144,26 @@ class OutputPage {
                        $this->addScriptFile( 'rightclickedit.js' );
                }
 
+               global $wgUseAJAXCategories;
+               if ($wgUseAJAXCategories) {
+                       $this->addScriptClass( 'ajaxCategories' );
+               }
+
                if( $wgUniversalEditButton ) {
                        if( isset( $wgArticle ) && $this->getTitle() && $this->getTitle()->quickUserCan( 'edit' )
                                && ( $this->getTitle()->exists() || $this->getTitle()->quickUserCan( 'create' ) ) ) {
                                // Original UniversalEditButton
+                               $msg = wfMsg('edit');
                                $this->addLink( array(
                                        'rel' => 'alternate',
                                        'type' => 'application/x-wiki',
-                                       'title' => wfMsg( 'edit' ),
+                                       'title' => $msg,
                                        'href' => $this->getTitle()->getLocalURL( 'action=edit' )
                                ) );
                                // Alternate edit link
                                $this->addLink( array(
                                        'rel' => 'edit',
-                                       'title' => wfMsg( 'edit' ),
+                                       'title' => $msg,
                                        'href' => $this->getTitle()->getLocalURL( 'action=edit' )
                                ) );
                        }
@@ -1668,7 +1659,7 @@ class OutputPage {
                if ( $returnto == null ) {
                        $returnto = $wgRequest->getText( 'returnto' );
                }
-               
+
                if ( $returntoquery == null ) {
                        $returntoquery = $wgRequest->getText( 'returntoquery' );
                }
@@ -1713,7 +1704,7 @@ class OutputPage {
                        $this->setHTMLTitle(  wfMsg( 'pagetitle', $this->getPageTitle() ));
                }
 
-               $dir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
+               $dir = $wgContLang->getDir();
 
                if ( $wgHtml5 ) {
                        $ret .= "<!doctype html>\n";
@@ -1727,7 +1718,8 @@ class OutputPage {
                        $ret .= "xml:lang=\"$wgContLanguageCode\" lang=\"$wgContLanguageCode\" dir=\"$dir\">\n";
                }
 
-               $ret .= "<head>\n\t<title>" . htmlspecialchars( $this->getHTMLTitle() ) . "</title>\n\t";
+               $ret .= "<head>\n";
+               $ret .= "<title>" . htmlspecialchars( $this->getHTMLTitle() ) . "</title>\n";
                $ret .= implode( "\n", array(
                        $this->getHeadLinks(),
                        $this->buildCssLinks(),
@@ -1735,7 +1727,7 @@ class OutputPage {
                        $this->getHeadItems(),
                ));
                if( $sk->usercss ){
-                       $ret .= "<style type='text/css'>{$sk->usercss}</style>";
+                       $ret .= Html::inlineStyle( $sk->usercss );
                }
 
                if( $wgEnableScriptLoader )
@@ -1848,7 +1840,7 @@ class OutputPage {
                        }
                }
 
-               return implode( "\n\t", $tags ) . "\n";
+               return implode( "\n", $tags ) . "\n";
        }
 
        /**
@@ -1894,14 +1886,8 @@ class OutputPage {
         */
        public function addStyle( $style, $media='', $condition='', $dir='' ) {
                $options = array();
-               // In Opera, fullscreen mode is treated as projection mode, and it causes
-               // styles set for screen to not be loaded - thus breaking the page -  so
-               // we can just append projection to the media attribute when it's screen
-               // so the browser is happy and - with no side-effects on other browsers.
-               // Also - even though we expect the media type to be lowercase, but here
-               // we force it to lowercase to be safe.
-               if ( strtolower( $media ) == 'screen' )
-                       $media .= ',projection';
+               // Even though we expect the media type to be lowercase, but here we
+               // force it to lowercase to be safe.
                if( $media )
                        $options['media'] = $media;
                if( $condition )
@@ -1916,7 +1902,7 @@ class OutputPage {
         * @param $style_css Mixed: inline CSS
         */
        public function addInlineStyle( $style_css ){
-               $this->mScripts .= "<style type=\"text/css\">$style_css</style>";
+               $this->mScripts .= Html::inlineStyle( $style_css );
        }
 
        /**
@@ -1931,7 +1917,7 @@ class OutputPage {
                                $links[] = $link;
                }
 
-               return "\t" . implode( "\n\t", $links );
+               return implode( "\n", $links );
        }
 
        protected function styleLink( $style, $options ) {
@@ -1939,7 +1925,7 @@ class OutputPage {
 
                if( isset( $options['dir'] ) ) {
                        global $wgContLang;
-                       $siteDir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
+                       $siteDir = $wgContLang->getDir();
                        if( $siteDir != $options['dir'] )
                                return '';
                }
@@ -1950,7 +1936,7 @@ class OutputPage {
                                return '';
                        }
                } else {
-                       $media = '';
+                       $media = 'all';
                }
 
                if( substr( $style, 0, 1 ) == '/' ||
@@ -1962,15 +1948,7 @@ class OutputPage {
                        $url = $wgStylePath . '/' . $style . '?' . $wgStyleVersion;
                }
 
-               $attribs = array(
-                       'rel' => 'stylesheet',
-                       'href' => $url,
-                       'type' => 'text/css' );
-               if( $media ) {
-                       $attribs['media'] = $media;
-               }
-
-               $link = Xml::element( 'link', $attribs );
+               $link = Html::linkedStyle( $url, $media );
 
                if( isset( $options['condition'] ) ) {
                        $condition = htmlspecialchars( $options['condition'] );