* Enhanced OutputPage to support js2 style javascript without scriptloader enabled
authorMichael Dale <dale@users.mediawiki.org>
Thu, 17 Sep 2009 01:19:02 +0000 (01:19 +0000)
committerMichael Dale <dale@users.mediawiki.org>
Thu, 17 Sep 2009 01:19:02 +0000 (01:19 +0000)
** loadGM output
** unique request id based on wikiTitle revision / file time
* Moved jsAutoLoadClasses to setup.php ( made conditional )

includes/AutoLoader.php
includes/OutputPage.php
includes/Setup.php
includes/json/FormatJson.php
js2/mwEmbed/jsScriptLoader.php

index 5051ad3..6b06a80 100644 (file)
@@ -623,11 +623,6 @@ $wgJSAutoloadLocalClasses = array(
        'ajaxCategories' => 'js2/ajaxcategories.js',
 );
 
-//Include the js2 autoLoadClasses
-//@@todo move jsAutoloadLocalClasses.php to post Setup so we have default values and can check the $wgEnableJS2system var
-$wgMwEmbedDirectory = "js2/mwEmbed/";
-require_once("$IP/js2/mwEmbed/php/jsAutoloadLocalClasses.php");
-
 class AutoLoader {
        /**
         * autoload - take a class name and attempt to load it
index a5da831..abf33fe 100644 (file)
@@ -16,10 +16,9 @@ class OutputPage {
 
        var $mScriptLoaderClassList = array();
 
-       // The most recent revision ID of any wikiPage script that is grouped in the script request
-       var $mLatestScriptRevID = 0;
-
        var $mScripts = '', $mLinkColours, $mPageLinkTitle = '', $mHeadItems = array();
+       var $mInlineMsg = array();
+
        var $mTemplateIds = array();
 
        var $mAllowUserJs;
@@ -119,7 +118,7 @@ class OutputPage {
         */
        function addScriptFile( $file ) {
                global $wgStylePath, $wgScript, $wgUser;
-               global $wgJSAutoloadClasses, $wgJSAutoloadLocalClasses, $wgEnableScriptLoader, $wgScriptPath;
+               global $wgEnableScriptLoader, $wgScriptPath;
 
                if( substr( $file, 0, 1 ) == '/' ) {
                        $path = $file;
@@ -127,42 +126,41 @@ class OutputPage {
                        $path = "{$wgStylePath}/common/{$file}";
                }
 
-               if( $wgEnableScriptLoader ) {
-                       if( strpos( $path, $wgScript ) !== false ) {
-                               $reqPath = str_replace( $wgScript . '?', '', $path );
-                               $reqArgs = explode( '&', $reqPath );
-                               $reqSet = array();
+               // If the class can be determined, use the addScriptClass method
+               $js_class = $this->getJsClassFromPath( $path );
+               if( $js_class ) {
+                       $this->addScriptClass( $js_class );
+                       return true;
+               }
 
-                               foreach( $reqArgs as $arg ) {
-                                       list( $key, $var ) = explode( '=', $arg );
-                                       $reqSet[$key] = $var;
-                               }
+               //do checks for wiki-titles
+               if( strpos( $path, $wgScript ) !== false ) {
+                       $reqPath = str_replace( $wgScript . '?', '', $path );
+                       $reqArgs = explode( '&', $reqPath );
+                       $reqSet = array();
+
+                       foreach( $reqArgs as $arg ) {
+                               list( $key, $var ) = explode( '=', $arg );
+                               $reqSet[$key] = $var;
+                       }
 
-                               if( isset( $reqSet['title'] ) && $reqSet != '' ) {
+                       if( isset( $reqSet['title'] ) && $reqSet != '' ) {
+                               $jsTitleClass = 'WT:' . $reqSet['title'];
+                               if( $wgEnableScriptLoader ) {
                                        // 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.
-                                       // If there is no title, we will just use $wgStyleVersion, 
-                                       // which should be updated on the relevant commits.
-                                       $t = Title::newFromText( $reqSet['title'] );
-                                       if( $t && $t->exists() ) {
-                                               if( $t->getLatestRevID() > $this->mLatestScriptRevID  )
-                                                       $this->mLatestScriptRevID = $t->getLatestRevID();
-                                       }
+                                       $this->mScriptLoaderClassList[] = $jsTitleClass . $ext_param ;
+                                       return true;
+                               }else{
+                                       $this->addScript( Html::linkedScript(
+                                                               wfAppendQuery( $path, $this->getURIDparam( $jsTitleClass ) )
+                                                       )
+                                               );
                                        return true;
                                }
                        }
-
-                       // If the class can be determined, add it to the class list to be loaded later
-                       $js_class = $this->getJsClassFromPath( $path );
-                       if( $js_class ) {
-                               $this->mScriptLoaderClassList[] = $js_class;
-                               return true;
-                       }
                }
-
                // If the script loader could not be used, just add the script to the header
                $this->addScript( Html::linkedScript( wfAppendQuery( $path, $this->getURIDparam() ) ) );
        }
@@ -171,7 +169,7 @@ class OutputPage {
         * Add the core scripts that are included on every page, for later output into the header
         */
        function addCoreScripts2Top(){
-               global $wgEnableScriptLoader, $wgJSAutoloadLocalClasses, $wgScriptPath, $wgStylePath, $wgEnableJS2system;
+               global $wgEnableScriptLoader, $wgJSAutoloadLocalClasses, $wgScriptPath, $wgEnableJS2system;
                // @todo We should deprecate wikibits in favor of mv_embed and jQuery
 
                if( $wgEnableJS2system ){
@@ -181,38 +179,30 @@ class OutputPage {
                }
 
                if( $wgEnableScriptLoader ){
+                       //add core to top of mScripts
                        $this->mScripts = $this->getScriptLoaderJs( $core_classes ) . $this->mScripts;
                } else {
                        $so = '';
-                       foreach( $core_classes as $s ){
-                               if( isset( $wgJSAutoloadLocalClasses[$s] ) ){
-                                       $path = $wgJSAutoloadLocalClasses[$s];
-                                       // @fixme this is an awful hack
-                                       if( substr( $path, 0, 4 ) == "http"  || substr( $path, 0, 1 ) == '/' ) {
-                                               // Assume a full or local path
-                                       } elseif( substr( $path, 0, 6 ) == "skins/" ) {
-                                               $path = $wgStylePath . substr( $path, 5 );
-                                       } else {
-                                               $path = $wgScriptPath . "/" . $path;
-                                       }
-                                       $so .= Html::linkedScript( $path . "?" . $this->getURIDparam() );
-                               }
+                       //make sure scripts are on top:
+                       $postMscripts = $this->mScripts;
+                       $this->mScripts = '';
+                       foreach( $core_classes as $js_class ){
+                               $this->addScriptClass( $js_class );
                        }
-                       $this->mScripts =  $so . $this->mScripts;
+                       $this->mScripts .= $postMscripts;
                }
        }
 
        /**
-        * @param $js_class string Name of the JavaScript class
+        * @param string $js_class Name of the JavaScript class
         * @return boolean False if the class wasn't found, true on success
         */
        function addScriptClass( $js_class ){
                global $wgDebugJavaScript, $wgJSAutoloadLocalClasses, $wgJSAutoloadClasses,
                                $wgEnableScriptLoader, $wgStyleVersion, $wgScriptPath;
 
-               if( isset( $wgJSAutoloadClasses[$js_class] ) 
-                       || isset( $wgJSAutoloadLocalClasses[$js_class] ) ) 
-               {
+               $path = jsScriptLoader::getJsPathFromClass( $js_class );
+               if( $path !== false ){
                        if( $wgEnableScriptLoader ) {
                                // Register it with the script loader
                                if( !in_array( $js_class, $this->mScriptLoaderClassList ) ) {
@@ -220,17 +210,18 @@ class OutputPage {
                                }
                        } else {
                                // Source the script directly
-                               $path = $wgScriptPath . '/';
-                               if( isset( $wgJSAutoloadClasses[$js_class] ) ) {
-                                       $path .= $wgJSAutoloadClasses[$js_class];
-                               } elseif( isset( $wgJSAutoloadLocalClasses[$js_class] ) ) {
-                                       $path .= $wgJSAutoloadLocalClasses[$js_class];
-                               }
-                               $urlAppend = ( $wgDebugJavaScript ) ? time() : $wgStyleVersion;
+                               $path = $wgScriptPath . '/' . $path;
+                               $urlAppend = ( $wgDebugJavaScript ) ? time() : $this->getURIDparam( $js_class );
                                $this->addScript( Html::linkedScript( "$path?$urlAppend" ) );
+
+                               //merge in language text:
+                               $inlineMsg = jsScriptLoader::getLocalizedMsgsFromClass( $js_class );
+                               if( $inlineMsg != '' )
+                                       $this->addScript( Html::inlineScript( $inlineMsg ));
                        }
                        return true;
                }
+               print "could not find: $js_class\n";
                wfDebug( __METHOD__ . ' could not find js_class: ' . $js_class );
                return false; // could not find the class
        }
@@ -252,7 +243,7 @@ class OutputPage {
                                                 $wgRequest->getVal( 'debug' ) == '1' )
                                         ? '&debug=true' : '';
 
-               return Html::linkedScript( wfScript( 'mwScriptLoader' ) . 
+               return Html::linkedScript( wfScript( 'mwScriptLoader' ) .
                        "?class={$class_list}{$debug_param}&" . $this->getURIDparam( $classAry) );
        }
 
@@ -264,9 +255,13 @@ class OutputPage {
                if( $wgDebugJavaScript ) {
                        return 'urid=' . time();
                } else {
-                       $ftime=0;
-                       if($wgScriptModifiedCheck) {
-                               foreach( $classAry as $class ) {
+                       //support single class_name attr
+                       if( gettype( $classAry) == 'string'  ){
+                               $classAry = array( $classAry );
+                       }
+                       $ftime =  $frev = 0;
+                       foreach( $classAry as $class ) {
+                               if( $wgScriptModifiedCheck ) {
                                        $js_path =  jsScriptLoader::getJsPathFromClass( $class );
                                        if( $js_path ) {
                                                $cur_ftime = filemtime ( $IP ."/". $js_path );
@@ -274,16 +269,26 @@ class OutputPage {
                                                        $ftime = $cur_ftime;
                                        }
                                }
+                               // Add the latest revision ID if the class set includes a WT (wiki title)
+                               if( substr($class, 0, 3) == 'WT:'){
+                                       $title_str = substr($class, 3);
+                                       $t = Title::newFromText( $title_str );
+                                       if( $t && $t->exists() ) {
+                                               if( $t->getLatestRevID() > $frev  )
+                                                       $frev = $t->getLatestRevID();
+                                       }
+                               }
                        }
+                       //build the actual unique request id:
                        $urid = "urid={$wgStyleVersion}";
 
-                       // Add the latest revision ID if we have it
-                       if($this->mLatestScriptRevID != 0 )
-                               $urid .= "_{$this->mLatestScriptRevID}";
-
-                       // Add the file modification time
+                       // Add the file modification time if set
                        if( $ftime != 0 )
-                               $urid .= "_".$ftime;
+                               $urid .= "_" . $ftime;
+
+                       //add the wiki rev id if set
+                       if( $frev != 0 )
+                               $urid.= "_" . $frev;
 
                        return $urid;
                }
@@ -1691,8 +1696,10 @@ class OutputPage {
 
        /**
         * @return string The doctype, opening <html>, and head element.
+        *
+        * @param $sk Skin The given Skin
         */
-       public function headElement( Skin $sk ) {
+       public function headElement( Skin $sk , $includeStyle = true ) {
                global $wgDocType, $wgDTD, $wgContLanguageCode, $wgOutputEncoding, $wgMimeType;
                global $wgXhtmlDefaultNamespace, $wgXhtmlNamespaces;
                global $wgContLang, $wgUseTrackbacks, $wgStyleVersion, $wgEnableScriptLoader, $wgHtml5;
index 23ac018..c736207 100644 (file)
@@ -319,13 +319,17 @@ $wgArticle = null;
 wfProfileOut( $fname.'-misc2' );
 wfProfileIn( $fname.'-extensions' );
 
-/*
- * load the $wgExtensionMessagesFiles for the script loader
- * this can't be done in a normal extension type way
- * since the script-loader is an entry point
- */
+# load the $wgExtensionMessagesFiles for the script loader
+# this can't be done in a normal extension type way
+# since the script-loader is an entry point
+#
 $wgExtensionMessagesFiles['mwEmbed'] = "{$IP}/js2/mwEmbed/php/languages/mwEmbed.i18n.php";
 
+# Include the js2/mwEmbed autoLoadClasses if js2 is enabled
+if( $wgEnableJS2system ){
+       require_once("$IP/js2/mwEmbed/php/jsAutoloadLocalClasses.php");
+}
+
 # Extension setup functions for extensions other than skins
 # Entries should be added to this variable during the inclusion
 # of the extension file. This allows the extension to perform
index 3fbb21b..6db4a23 100644 (file)
@@ -18,15 +18,15 @@ class FormatJson{
                        return json_encode($value);
                }
        }
-       public static function decode($value, $assoc=false){
+       public static function decode( $value, $assoc=false ){
                if (!function_exists('json_decode') ) {
                        $json = new Services_JSON();
-                       $jsonDec = $json->decode($value);
-                       if($assoc)
+                       $jsonDec = $json->decode( $value );
+                       if( $assoc )
                                $jsonDec = wfObjectToArray( $jsonDec );
                        return $jsonDec;
                } else {
-                       return json_decode($value, $assoc);
+                       return json_decode( $value, $assoc );
                }
        }
 }
index c60afb5..56f400a 100644 (file)
@@ -22,6 +22,9 @@ class jsScriptLoader {
        var $jsvarurl = false; // whether we should include generated JS (special class '-')
        var $doProcReqFlag = true;
 
+       //@@todo fix: will break down if someone does }); in their msg text
+       const loadGMregEx = '/loadGM\s*\(\s*{(.*)}\s*\)\s*/siU';
+
        function doScriptLoader() {
                global  $wgJSAutoloadClasses, $wgJSAutoloadLocalClasses, $wgEnableScriptLoaderJsFile, $IP,
                                $wgEnableScriptMinify, $wgUseFileCache;
@@ -229,7 +232,7 @@ class jsScriptLoader {
                                                        $this->rKey .= $reqFile;
                                                }
                                        } else {
-                                               $this->error_msg .= 'Not valid requsted JavaScript file' . "\n";
+                                               $this->error_msg .= 'Not valid requested JavaScript file' . "\n";
                                        }
                                }
                        }
@@ -256,18 +259,18 @@ class jsScriptLoader {
                        return false;
                }
        }
-       function doProcessJsFile( $file_name ) {
+       function doProcessJsFile( $file_path ) {
                global $IP, $wgEnableScriptLocalization, $IP;
 
                // Load the file
-               $str = @file_get_contents( "{$IP}/{$file_name}" );
+               $str = @file_get_contents( "{$IP}/{$file_path}" );
 
                if ( $str === false ) {
                        // @@todo check PHP error level. Don't want to expose paths if errors are hidden.
-                       $this->error_msg .= 'Requested File: ' . htmlspecialchars( $file_name ) . ' could not be read' . "\n";
+                       $this->error_msg .= 'Requested File: ' . htmlspecialchars( $file_path ) . ' could not be read' . "\n";
                        return '';
                }
-               $this->cur_file = $file_name;
+               $this->cur_file = $file_path;
 
                // Strip out js_log debug lines. Not much luck with this regExp yet:
                // if( !$this->debug )
@@ -276,19 +279,28 @@ class jsScriptLoader {
                // Do language swap
                if ( $wgEnableScriptLocalization )
                        $str = preg_replace_callback(
-                               // @@todo fix: will break down if someone does }) in their msg text
-                               '/loadGM\s*\(\s*{(.*)}\s*\)\s*/siU',
-                               array( $this, 'languageMsgReplace' ),
-                               $str
-                       );
-
+                                       self::loadGMregEx,
+                                       array( $this, 'languageMsgReplace' ),
+                                       $str
+                               );
                return $str;
        }
-
-       function languageMsgReplace( $jvar ) {
+       static public function getLocalizedMsgsFromClass( $class ){
+               global $IP;
+               $path = self::getJsPathFromClass( $class );
+               // Load the file
+               $str = @file_get_contents( "{$IP}/{$path}" );
+               //extract the msg:
+               preg_match(self::loadGMregEx, $str, $matches);
+               if( isset( $matches[1] )){
+                       return self::languageMsgReplace( $matches, false );
+               }
+               //if could not parse return empty string:
+               return '';
+       }
+       static public function languageMsgReplace( $jvar ) {
                if ( !isset( $jvar[1] ) )
-                       return;
-
+                       return '';
                $jmsg = FormatJson::decode( '{' . $jvar[1] . '}', true );
 
                // Do the language lookup
@@ -296,14 +308,20 @@ class jsScriptLoader {
                        foreach ( $jmsg as $msgKey => $default_en_value ) {
                                $jmsg[$msgKey] = wfMsgNoTrans( $msgKey );
                        }
-                       // Return the updated loadGM JSON with fixed new lines
+                       // Return the updated loadGM JSON with updated msgs:
                        return 'loadGM( ' . FormatJson::encode( $jmsg ) . ')';
                } else {
-                       $this->error_msg .= "Could not parse JSON language msg in File:\n" .
-                                                               htmlspecialchars ( $this->cur_file ) . "\n";
+                       print_r($jvar);
+
+                       // Could not parse JSON return error: (maybe a alert?)
+                       //we just make a note in the code, visitors will get the fallback language,
+                       //developers will read the js source when its not behaving as expected.
+                       return "/*
+* Could not parse JSON language messages in this file,
+* Please check that loadGM call contains valid JSON (not javascript)
+*/\n\n" . $jvar[0]; //include the original fallback loadGM
+
                }
-               // Could not parse JSON (throw error?)
-               return $jvar[0];
        }
 }