Stylize files added in r72349
authorSiebrand Mazeland <siebrand@users.mediawiki.org>
Sat, 4 Sep 2010 12:53:01 +0000 (12:53 +0000)
committerSiebrand Mazeland <siebrand@users.mediawiki.org>
Sat, 4 Sep 2010 12:53:01 +0000 (12:53 +0000)
includes/CSSJanus.php
includes/CSSMin.php
includes/MessageBlobStore.php
includes/ResourceLoader.php
includes/ResourceLoaderContext.php
includes/ResourceLoaderModule.php
load.php
maintenance/tests/ResourceLoaderFileModuleTest.php
maintenance/tests/ResourceLoaderTest.php

index 86d52b0..08e8e09 100644 (file)
 /**
  * This is a PHP port of CSSJanus, a utility that transforms CSS style sheets
  * written for LTR to RTL.
- * 
+ *
  * The original Python version of CSSJanus is Copyright 2008 by Google Inc. and
- * is distributed under the Apache license. 
- * 
+ * is distributed under the Apache license.
+ *
  * Original code: http://code.google.com/p/cssjanus/source/browse/trunk/cssjanus.py
  * License of original code: http://code.google.com/p/cssjanus/source/browse/trunk/LICENSE
  * @author Roan Kattouw
@@ -55,7 +55,6 @@ class CSSJanus {
                'lookbehind_not_letter' => '(?<![a-zA-Z])',
                'chars_within_selector' => '[^\}]*?',
                'noflip_annotation' => '\/\*\s*@noflip\s*\*\/',
-       
                'noflip_single' => null,
                'noflip_class' => null,
                'comment' => '/\/\*[^*]*\*+([^\/*][^*]*\*+)*\//',
@@ -74,7 +73,7 @@ class CSSJanus {
                'bg_horizontal_percentage' => null,
                'bg_horizontal_percentage_x' => null,
        );
-       
+
        /**
         * Build patterns we can't define above because they depend on other patterns.
         */
@@ -83,6 +82,7 @@ class CSSJanus {
                        // Patterns have already been built
                        return;
                }
+
                $patterns =& self::$patterns;
                $patterns['escape'] = "(?:{$patterns['unicode']}|\\[^\r\n\f0-9a-f])";
                $patterns['nmstart'] = "(?:[_a-z]|{$patterns['nonAscii']}|{$patterns['escape']})";
@@ -95,7 +95,6 @@ class CSSJanus {
                $patterns['lookahead_not_open_brace'] = "(?!({$patterns['nmchar']}|\r?\n|\s|#|\:|\.|\,|\+|>)*?{)";
                $patterns['lookahead_not_closing_paren'] = "(?!{$patterns['url_chars']}?{$patterns['valid_after_uri_chars']}\))";
                $patterns['lookahead_for_closing_paren'] = "(?={$patterns['url_chars']}?{$patterns['valid_after_uri_chars']}\))";
-               
                $patterns['noflip_single'] = "/({$patterns['noflip_annotation']}{$patterns['lookahead_not_open_brace']}[^;}]+;?)/i";
                $patterns['noflip_class'] = "/({$patterns['noflip_annotation']}{$patterns['chars_within_selector']}})/i";
                $patterns['body_direction_ltr'] = "/({$patterns['body_selector']}{$patterns['chars_within_selector']}{$patterns['direction']})ltr/i";
@@ -115,7 +114,7 @@ class CSSJanus {
                $patterns['bg_horizontal_percentage'] = "/(background(?:-position)?\s*:\s*[^%]*?)({$patterns['num']})(%\s*(?:{$patterns['quantity']}|{$patterns['ident']}))/";
                $patterns['bg_horizontal_percentage_x'] = "/(background-position-x\s*:\s*)({$patterns['num']})(%)/";
        }
-       
+
        /**
         * Transform an LTR stylesheet to RTL
         * @param string $css Stylesheet to transform
@@ -126,28 +125,29 @@ class CSSJanus {
        public static function transform( $css, $swapLtrRtlInURL = false, $swapLeftRightInURL = false ) {
                // We wrap tokens in ` , not ~ like the original implementation does.
                // This was done because ` is not a legal character in CSS and can only
-               // occur in URLs, where we escape it to %60 before inserting our tokens.        
+               // occur in URLs, where we escape it to %60 before inserting our tokens.
                $css = str_replace( '`', '%60', $css );
-               
+
                self::buildPatterns();
-               
+
                // Tokenize single line rules with /* @noflip */
                $noFlipSingle = new CSSJanus_Tokenizer( self::$patterns['noflip_single'], '`NOFLIP_SINGLE`' );
                $css = $noFlipSingle->tokenize( $css );
-               
+
                // Tokenize class rules with /* @noflip */
                $noFlipClass = new CSSJanus_Tokenizer( self::$patterns['noflip_class'], '`NOFLIP_CLASS`' );
                $css = $noFlipClass->tokenize( $css );
-               
+
                // Tokenize comments
                $comments = new CSSJanus_Tokenizer( self::$patterns['comment'], '`C`' );
                $css = $comments->tokenize( $css );
-               
+
                // LTR->RTL fixes start here
                $css = self::fixBodyDirection( $css );
                if ( $swapLtrRtlInURL ) {
                        $css = self::fixLtrRtlInURL( $css );
                }
+
                if ( $swapLeftRightInURL ) {
                        $css = self::fixLeftRightInURL( $css );
                }
@@ -155,18 +155,19 @@ class CSSJanus {
                $css = self::fixCursorProperties( $css );
                $css = self::fixFourPartNotation( $css );
                $css = self::fixBackgroundPosition( $css );
-               
+
                // Detokenize stuff we tokenized before
                $css = $comments->detokenize( $css );
                $css = $noFlipClass->detokenize( $css );
                $css = $noFlipSingle->detokenize( $css );
+
                return $css;
        }
-       
+
        /**
         * Replace direction: ltr; with direction: rtl; and vice versa, but *only*
         * those inside a body { .. } selector.
-        * 
+        *
         * Unlike the original implementation, this function doesn't suffer from
         * the bug causing "body\n{\ndirection: ltr;\n}" to be missed.
         * See http://code.google.com/p/cssjanus/issues/detail?id=15
@@ -176,9 +177,10 @@ class CSSJanus {
                        '$1' . self::$patterns['tmpToken'], $css );
                $css = preg_replace( self::$patterns['body_direction_rtl'], '$1ltr', $css );
                $css = str_replace( self::$patterns['tmpToken'], 'rtl', $css );
+
                return $css;
        }
-       
+
        /**
         * Replace 'ltr' with 'rtl' and vice versa in background URLs
         */
@@ -186,9 +188,10 @@ class CSSJanus {
                $css = preg_replace( self::$patterns['ltr_in_url'], self::$patterns['tmpToken'], $css );
                $css = preg_replace( self::$patterns['rtl_in_url'], 'ltr', $css );
                $css = str_replace( self::$patterns['tmpToken'], 'rtl', $css );
+
                return $css;
        }
-       
+
        /**
         * Replace 'left' with 'right' and vice versa in background URLs
         */
@@ -196,9 +199,10 @@ class CSSJanus {
                $css = preg_replace( self::$patterns['left_in_url'], self::$patterns['tmpToken'], $css );
                $css = preg_replace( self::$patterns['right_in_url'], 'left', $css );
                $css = str_replace( self::$patterns['tmpToken'], 'right', $css );
+
                return $css;
        }
-       
+
        /**
         * Flip rules like left: , padding-right: , etc.
         */
@@ -206,9 +210,10 @@ class CSSJanus {
                $css = preg_replace( self::$patterns['left'], self::$patterns['tmpToken'], $css );
                $css = preg_replace( self::$patterns['right'], 'left', $css );
                $css = str_replace( self::$patterns['tmpToken'], 'right', $css );
+
                return $css;
        }
-       
+
        /**
         * Flip East and West in rules like cursor: nw-resize;
         */
@@ -217,13 +222,14 @@ class CSSJanus {
                        '$1' . self::$patterns['tmpToken'], $css );
                $css = preg_replace( self::$patterns['cursor_west'], '$1e-resize', $css );
                $css = str_replace( self::$patterns['tmpToken'], 'w-resize', $css );
+
                return $css;
        }
-       
+
        /**
         * Swap the second and fourth parts in four-part notation rules like
         * padding: 1px 2px 3px 4px;
-        * 
+        *
         * Unlike the original implementation, this function doesn't suffer from
         * the bug where whitespace is not preserved when flipping four-part rules
         * and four-part color rules with multiple whitespace characters between
@@ -233,27 +239,29 @@ class CSSJanus {
        private static function fixFourPartNotation( $css ) {
                $css = preg_replace( self::$patterns['four_notation_quantity'], '$1$2$7$4$5$6$3', $css );
                $css = preg_replace( self::$patterns['four_notation_color'], '$1$2$3$8$5$6$7$4', $css );
+
                return $css;
        }
-       
+
        /**
-        * Flip horizontal background percentages. 
+        * Flip horizontal background percentages.
         */
        private static function fixBackgroundPosition( $css ) {
                $css = preg_replace_callback( self::$patterns['bg_horizontal_percentage'],
                        array( 'self', 'calculateNewBackgroundPosition' ), $css );
                $css = preg_replace_callback( self::$patterns['bg_horizontal_percentage_x'],
                        array( 'self', 'calculateNewBackgroundPosition' ), $css );
+
                return $css;
        }
-       
+
        /**
-        * Callback for calculateNewBackgroundPosition() 
+        * Callback for calculateNewBackgroundPosition()
         */
        private static function calculateNewBackgroundPosition( $matches ) {
                return $matches[1] . ( 100 - $matches[2] ) . $matches[3];
        }
-}      
+}
 
 /**
  * Utility class used by CSSJanus that tokenizes and untokenizes things we want
@@ -263,7 +271,7 @@ class CSSJanus {
 class CSSJanus_Tokenizer {
        private $regex, $token;
        private $originals;
-       
+
        /**
         * Constructor
         * @param $regex string Regular expression whose matches to replace by a token.
@@ -274,22 +282,22 @@ class CSSJanus_Tokenizer {
                $this->token = $token;
                $this->originals = array();
        }
-       
+
        /**
         * Replace all occurrences of $regex in $str with a token and remember
-        * the original strings. 
+        * the original strings.
         * @param $str string String to tokenize
         * @return string Tokenized string
         */
        public function tokenize( $str ) {
                return preg_replace_callback( $this->regex, array( $this, 'tokenizeCallback' ), $str );
        }
-       
+
        private function tokenizeCallback( $matches ) {
                $this->originals[] = $matches[0];
                return $this->token;
        }
-       
+
        /**
         * Replace tokens with their originals. If multiple strings were tokenized, it's important they be
         * detokenized in exactly the SAME ORDER.
@@ -303,11 +311,11 @@ class CSSJanus_Tokenizer {
                return preg_replace_callback( '/' . preg_quote( $this->token, '/' ) . '/',
                        array( $this, 'detokenizeCallback' ), $str );
        }
-       
+
        private function detokenizeCallback( $matches ) {
                $retval = current( $this->originals );
                next( $this->originals );
+
                return $retval;
        }
-       
-}
\ No newline at end of file
+}
index 3272bbe..ab49445 100644 (file)
@@ -1,22 +1,21 @@
 <?php
 
 class CSSMin {
-       
        /* Constants */
-       
+
        /**
         * Maximum file size to still qualify for in-line embedding as a data-URI
-        * 
+        *
         * 24,576 is used because Internet Explorer has a 32,768 byte limit for data URIs, which when base64 encoded will
         * result in a 1/3 increase in size.
         */
        const EMBED_SIZE_LIMIT = 24576;
-       
+
        /* Static Methods */
-       
+
        /**
         * Gets a list of local file paths which are referenced in a CSS style sheet
-        * 
+        *
         * @param $source string CSS data to remap
         * @param $path string File path where the source was read from (optional)
         * @return array List of local file references
@@ -24,39 +23,46 @@ class CSSMin {
        public static function getLocalFileReferences( $source, $path = null ) {
                $pattern = '/url\([\'"]?(?<file>[^\?\)\:]*)\??[^\)]*[\'"]?\)/';
                $files = array();
+
                if ( preg_match_all( $pattern, $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER ) ) {
                        foreach ( $matches as $match ) {
                                $file = ( isset( $path ) ? rtrim( $path, '/' ) . '/' : '' ) . "{$match['file'][0]}";
+
                                // Only proceed if we can access the file
                                if ( file_exists( $file ) ) {
                                        $files[] = $file;
                                }
                        }
                }
+
                return $files;
        }
-       
+
        /**
         * Remaps CSS URL paths and automatically embeds data URIs for URL rules preceded by an /* @embed * / comment
-        * 
+        *
         * @param $source string CSS data to remap
         * @param $path string File path where the source was read from
         * @return string Remapped CSS data
         */
        public static function remap( $source, $path ) {
                global $wgUseDataURLs;
+
                $pattern = '/((?<embed>\s*\/\*\s*\@embed\s*\*\/)(?<rule>[^\;\}]*))?url\([\'"]?(?<file>[^\?\)\:]*)\??[^\)]*[\'"]?\)(?<extra>[^;]*)[\;]?/';
                $offset = 0;
+
                while ( preg_match( $pattern, $source, $match, PREG_OFFSET_CAPTURE, $offset ) ) {
                        // Shortcuts
                        $embed = $match['embed'][0];
                        $rule = $match['rule'][0];
                        $extra = $match['extra'][0];
                        $file = "{$path}/{$match['file'][0]}";
+
                        // Only proceed if we can access the file
                        if ( file_exists( $file ) ) {
                                // Add version parameter as a time-stamp in ISO 8601 format, using Z for the timezone, meaning GMT
                                $url = "{$file}?" . gmdate( 'Y-m-d\TH:i:s\Z', round( filemtime( $file ), -2 ) );
+
                                // Detect when URLs were preceeded with embed tags, and also verify file size is below the limit
                                if ( $wgUseDataURLs && $match['embed'][1] > 0 && filesize( $file ) < self::EMBED_SIZE_LIMIT ) {
                                        // If we ever get to PHP 5.3, we should use the Fileinfo extension instead of mime_content_type
@@ -71,6 +77,7 @@ class CSSMin {
                                        // Build a CSS property with a remapped and versioned URL
                                        $replacement = "{$embed}{$rule}url({$url}){$extra};";
                                }
+
                                // Perform replacement on the source
                                $source = substr_replace( $source, $replacement, $match[0][1], strlen( $match[0][0] ) );
                                // Move the offset to the end of the replacement in the source
@@ -80,14 +87,15 @@ class CSSMin {
                        // Move the offset to the end of the match, leaving it alone
                        $offset = $match[0][1] + strlen( $match[0][0] );
                }
+
                return $source;
        }
-       
+
        /**
         * Removes whitespace from CSS data
-        * 
+        *
         * @param $source string CSS data to minify
-        * @return string Minified CSS data 
+        * @return string Minified CSS data
         */
        public static function minify( $css ) {
                return trim(
@@ -98,4 +106,4 @@ class CSSMin {
                        )
                );
        }
-}
\ No newline at end of file
+}
index 8fc72d0..51f3f72 100644 (file)
@@ -42,7 +42,7 @@ class MessageBlobStore {
                }
                // Try getting from the DB first
                $blobs = self::getFromDB( $modules, $lang );
-               
+
                // Generate blobs for any missing modules and store them in the DB
                $missing = array_diff( $modules, array_keys( $blobs ) );
                foreach ( $missing as $module ) {
@@ -51,9 +51,10 @@ class MessageBlobStore {
                                $blobs[$module] = $blob;
                        }
                }
+
                return $blobs;
        }
-       
+
        /**
         * Generate and insert a new message blob. If the blob was already
         * present, it is not regenerated; instead, the preexisting blob
@@ -64,10 +65,11 @@ class MessageBlobStore {
         */
        public static function insertMessageBlob( $module, $lang ) {
                $blob = self::generateMessageBlob( $module, $lang );
+
                if ( !$blob ) {
                        return false;
                }
-               
+
                $dbw = wfGetDb( DB_MASTER );
                $success = $dbw->insert( 'msg_resource', array(
                                'mr_lang' => $lang,
@@ -78,6 +80,7 @@ class MessageBlobStore {
                        __METHOD__,
                        array( 'IGNORE' )
                );
+
                if ( $success ) {
                        if ( $dbw->affectedRows() == 0 ) {
                                // Blob was already present, fetch it
@@ -91,6 +94,7 @@ class MessageBlobStore {
                                // Update msg_resource_links
                                $rows = array();
                                $mod = ResourceLoader::getModule( $module );
+
                                foreach ( $mod->getMessages() as $key ) {
                                        $rows[] = array(
                                                'mrl_resource' => $module,
@@ -102,9 +106,10 @@ class MessageBlobStore {
                                );
                        }
                }
+
                return $blob;
        }
-       
+
        /**
         * Update all message blobs for a given module.
         * @param $module string Module name
@@ -113,22 +118,24 @@ class MessageBlobStore {
         */
        public static function updateModule( $module, $lang = null ) {
                $retval = null;
-               
+
                // Find all existing blobs for this module
                $dbw = wfGetDb( DB_MASTER );
                $res = $dbw->select( 'msg_resource', array( 'mr_lang', 'mr_blob' ),
                        array( 'mr_resource' => $module ),
                        __METHOD__
                );
-               
+
                // Build the new msg_resource rows
                $newRows = array();
                $now = $dbw->timestamp();
                // Save the last-processed old and new blobs for later
                $oldBlob = $newBlob = null;
+
                foreach ( $res as $row ) {
                        $oldBlob = $row->mr_blob;
                        $newBlob = self::generateMessageBlob( $module, $row->mr_lang );
+
                        if ( $row->mr_lang === $lang ) {
                                $retval = $newBlob;
                        }
@@ -144,13 +151,13 @@ class MessageBlobStore {
                        array( array( 'mr_resource', 'mr_lang' ) ),
                        $newRows, __METHOD__
                );
-               
+
                // Figure out which messages were added and removed
                $oldMessages = array_keys( FormatJson::decode( $oldBlob, true ) );
                $newMessages = array_keys( FormatJson::decode( $newBlob, true ) );
                $added = array_diff( $newMessages, $oldMessages );
                $removed = array_diff( $oldMessages, $newMessages );
-               
+
                // Delete removed messages, insert added ones
                if ( $removed ) {
                        $dbw->delete( 'msg_resource_links', array(
@@ -159,35 +166,39 @@ class MessageBlobStore {
                                ), __METHOD__
                        );
                }
+
                $newLinksRows = array();
+
                foreach ( $added as $message ) {
                        $newLinksRows[] = array(
                                'mrl_resource' => $module,
                                'mrl_message' => $message
                        );
                }
+
                if ( $newLinksRows ) {
                        $dbw->insert( 'msg_resource_links', $newLinksRows, __METHOD__,
                                 array( 'IGNORE' ) // just in case
                        );
                }
-               
+
                return $retval;
        }
-       
+
        /**
         * Update a single message in all message blobs it occurs in.
         * @param $key string Message key
         */
        public static function updateMessage( $key ) {
                $dbw = wfGetDb( DB_MASTER );
-               
+
                // Keep running until the updates queue is empty.
                // Due to update conflicts, the queue might not be emptied
                // in one iteration.
                $updates = null;
                do {
                        $updates = self::getUpdatesForMessage( $key, $updates );
+
                        foreach ( $updates as $key => $update ) {
                                // Update the row on the condition that it
                                // didn't change since we fetched it by putting
@@ -200,7 +211,7 @@ class MessageBlobStore {
                                                'mr_timestamp' => $update['timestamp'] ),
                                        __METHOD__
                                );
-                               
+
                                // Only requeue conflicted updates.
                                // If update() returned false, don't retry, for
                                // fear of getting into an infinite loop
@@ -210,11 +221,11 @@ class MessageBlobStore {
                                }
                        }
                } while ( count( $updates ) );
-               
+
                // No need to update msg_resource_links because we didn't add
                // or remove any messages, we just changed their contents.
        }
-       
+
        public static function clear() {
                // TODO: Give this some more thought
                // TODO: Is TRUNCATE better?
@@ -222,7 +233,7 @@ class MessageBlobStore {
                $dbw->delete( 'msg_resource', '*', __METHOD__ );
                $dbw->delete( 'msg_resource_links', '*', __METHOD__ );
        }
-       
+
        /**
         * Create an update queue for updateMessage()
         * @param $key string Message key
@@ -231,6 +242,7 @@ class MessageBlobStore {
         */
        private static function getUpdatesForMessage( $key, $prevUpdates = null ) {
                $dbw = wfGetDb( DB_MASTER );
+
                if ( is_null( $prevUpdates ) ) {
                        // Fetch all blobs referencing $key
                        $res = $dbw->select(
@@ -241,23 +253,25 @@ class MessageBlobStore {
                        );
                } else {
                        // Refetch the blobs referenced by $prevUpdates
-                       
+
                        // Reorganize the (resource, lang) pairs in the format
                        // expected by makeWhereFrom2d()
                        $twoD = array();
+
                        foreach ( $prevUpdates as $update ) {
                                $twoD[$update['resource']][$update['lang']] = true;
                        }
-                       
+
                        $res = $dbw->select( 'msg_resource',
                                array(  'mr_resource', 'mr_lang', 'mr_blob', 'mr_timestamp' ),
                                $dbw->makeWhereFrom2d( $twoD, 'mr_resource', 'mr_lang' ),
                                __METHOD__
                        );
                }
-               
+
                // Build the new updates queue
                $updates = array();
+
                foreach ( $res as $row ) {
                        $updates[] = array(
                                'resource' => $row->mr_resource,
@@ -267,9 +281,10 @@ class MessageBlobStore {
                                        $key, $row->mr_lang )
                        );
                }
+
                return $updates;
        }
-       
+
        /**
         * Reencode a message blob with the updated value for a message
         * @param $blob string Message blob (JSON object)
@@ -280,9 +295,10 @@ class MessageBlobStore {
        private static function reencodeBlob( $blob, $key, $lang ) {
                $decoded = FormatJson::decode( $blob, true );
                $decoded[$key] = wfMsgExt( $key, array( 'language' => $lang ) );
+
                return FormatJson::encode( $decoded );
        }
-       
+
        /**
         * Get the message blobs for a set of modules from the database.
         * Modules whose blobs are not in the database are silently dropped.
@@ -297,6 +313,7 @@ class MessageBlobStore {
                        array( 'mr_resource' => $modules, 'mr_lang' => $lang ),
                        __METHOD__
                );
+
                foreach ( $res as $row ) {
                        $module = ResourceLoader::getModule( $row->mr_resource );
                        if ( !$module ) {
@@ -309,9 +326,10 @@ class MessageBlobStore {
                                $retval[$row->mr_resource] = $row->mr_blob;
                        }
                }
+
                return $retval;
        }
-       
+
        /**
         * Generate the message blob for a given module in a given language.
         * @param $module string Module name
@@ -321,9 +339,11 @@ class MessageBlobStore {
        private static function generateMessageBlob( $module, $lang ) {
                $mod = ResourceLoader::getModule( $module );
                $messages = array();
+
                foreach ( $mod->getMessages() as $key ) {
                        $messages[$key] = wfMsgExt( $key, array( 'language' => $lang ) );
                }
+
                return FormatJson::encode( $messages );
        }
 }
index f79114a..d568d28 100644 (file)
  *     ResourceLoader::respond( $wgRequest, $wgServer . $wgScriptPath . '/load.php' );
  */
 class ResourceLoader {
-       
        /* Protected Static Members */
-       
+
        // @var array list of module name/ResourceLoaderModule object pairs
        protected static $modules = array();
-       
+
        /* Protected Static Methods */
-       
+
        /**
         * Runs text through a filter, caching the filtered result for future calls
         *
@@ -79,18 +78,20 @@ class ResourceLoader {
         */
        protected static function filter( $filter, $data ) {
                global $wgMemc;
+
                // For empty or whitespace-only things, don't do any processing
                if ( trim( $data ) === '' ) {
                        return $data;
                }
-               
+
                // Try memcached
                $key = wfMemcKey( 'resourceloader', 'filter', $filter, md5( $data ) );
                $cached = $wgMemc->get( $key );
+
                if ( $cached !== false && $cached !== null ) {
                        return $cached;
                }
-               
+
                // Run the filter
                try {
                        switch ( $filter ) {
@@ -110,24 +111,25 @@ class ResourceLoader {
                } catch ( Exception $exception ) {
                        throw new MWException( 'Filter threw an exception: ' . $exception->getMessage() );
                }
-               
+
                // Save to memcached
                $wgMemc->set( $key, $result );
+
                return $result;
        }
-       
+
        /* Static Methods */
-       
+
        /**
         * Registers a module with the ResourceLoader system.
         *
         * Note that registering the same object under multiple names is not supported and may silently fail in all
         * kinds of interesting ways.
-        * 
+        *
         * @param {mixed} $name string of name of module or array of name/object pairs
         * @param {ResourceLoaderModule} $object module object (optional when using multiple-registration calling style)
         * @return {boolean} false if there were any errors, in which case one or more modules were not registered
-        * 
+        *
         * @todo We need much more clever error reporting, not just in detailing what happened, but in bringing errors to
         * the client in a way that they can easily see them if they want to, such as by using FireBug
         */
@@ -137,8 +139,10 @@ class ResourceLoader {
                        foreach ( $name as $key => $value ) {
                                self::register( $key, $value );
                        }
+
                        return;
                }
+
                // Disallow duplicate registrations
                if ( isset( self::$modules[$name] ) ) {
                        // A module has already been registered by this name
@@ -148,7 +152,7 @@ class ResourceLoader {
                self::$modules[$name] = $object;
                $object->setName( $name );
        }
-       
+
        /**
         * Gets a map of all modules and their options
         *
@@ -157,7 +161,7 @@ class ResourceLoader {
        public static function getModules() {
                return self::$modules;
        }
-       
+
        /**
         * Get the ResourceLoaderModule object for a given module name
         * @param $name string Module name
@@ -166,7 +170,7 @@ class ResourceLoader {
        public static function getModule( $name ) {
                return isset( self::$modules[$name] ) ? self::$modules[$name] : null;
        }
-       
+
        /**
         * Gets registration code for all modules, except pre-registered ones listed in self::$preRegisteredModules
         *
@@ -180,6 +184,7 @@ class ResourceLoader {
        public static function getModuleRegistrations( ResourceLoaderContext $context ) {
                $scripts = '';
                $registrations = array();
+
                foreach ( self::$modules as $name => $module ) {
                        // Support module loader scripts
                        if ( ( $loader = $module->getLoaderScript() ) !== false ) {
@@ -199,7 +204,7 @@ class ResourceLoader {
                }
                return $scripts . "mediaWiki.loader.register( " . FormatJson::encode( $registrations ) . " );";
        }
-       
+
        /**
         * Get the highest modification time of all modules, based on a given combination of language code,
         * skin name and debug mode flag.
@@ -210,14 +215,16 @@ class ResourceLoader {
         */
        public static function getHighestModifiedTime( ResourceLoaderContext $context ) {
                $time = 1; // wfTimestamp() treats 0 as 'now', so that's not a suitable choice
+
                foreach ( self::$modules as $module ) {
                        $time = max( $time, $module->getModifiedTime( $context ) );
                }
+
                return $time;
        }
-       
+
        /* Methods */
-       
+
        /*
         * Outputs a response to a resource load-request, including a content-type header
         *
@@ -237,6 +244,7 @@ class ResourceLoader {
                // Split requested modules into two groups, modules and missing
                $modules = array();
                $missing = array();
+
                foreach ( $context->getModules() as $name ) {
                        if ( isset( self::$modules[$name] ) ) {
                                $modules[] = $name;
@@ -244,52 +252,58 @@ class ResourceLoader {
                                $missing[] = $name;
                        }
                }
-               
+
                // Calculate the mtime and caching maxages for this request. We need this, 304 or no 304
                $mtime = 1;
                $maxage = PHP_INT_MAX;
                $smaxage = PHP_INT_MAX;
+
                foreach ( $modules as $name ) {
                        $mtime = max( $mtime, self::$modules[$name]->getModifiedTime( $context ) );
                        $maxage = min( $maxage, self::$modules[$name]->getClientMaxage() );
                        $smaxage = min( $smaxage, self::$modules[$name]->getServerMaxage() );
                }
-               
+
                // Output headers
                if ( $context->getOnly() === 'styles' ) {
                        header( 'Content-Type: text/css' );
                } else {
                        header( 'Content-Type: text/javascript' );
                }
+
                header( 'Last-Modified: ' . wfTimestamp( TS_RFC2822, $mtime ) );
                $expires = wfTimestamp( TS_RFC2822, min( $maxage, $smaxage ) + time() );
                header( "Cache-Control: public, maxage=$maxage, s-maxage=$smaxage" );
                header( "Expires: $expires" );
-               
+
                // Check if there's an If-Modified-Since header and respond with a 304 Not Modified if possible
                $ims = $context->getRequest()->getHeader( 'If-Modified-Since' );
+
                if ( $ims !== false && wfTimestamp( TS_UNIX, $ims ) == $mtime ) {
                        header( 'HTTP/1.0 304 Not Modified' );
                        header( 'Status: 304 Not Modified' );
                        return;
                }
-               
+
                // Use output buffering
                ob_start();
-               
+
                // Pre-fetch blobs
                $blobs = $context->shouldIncludeMessages() ?
                        MessageBlobStore::get( $modules, $context->getLanguage() ) : array();
-               
+
                // Generate output
                foreach ( $modules as $name ) {
                        // Scripts
                        $scripts = '';
+
                        if ( $context->shouldIncludeScripts() ) {
                                $scripts .= self::$modules[$name]->getScript( $context );
                        }
+
                        // Styles
                        $styles = '';
+
                        if (
                                $context->shouldIncludeStyles() &&
                                ( $styles .= self::$modules[$name]->getStyle( $context ) ) !== ''
@@ -299,8 +313,10 @@ class ResourceLoader {
                                }
                                $styles = $context->getDebug() ? $styles : self::filter( 'minify-css', $styles );
                        }
+
                        // Messages
                        $messages = isset( $blobs[$name] ) ? $blobs[$name] : '{}';
+
                        // Output
                        if ( $context->getOnly() === 'styles' ) {
                                echo $styles;
@@ -313,21 +329,26 @@ class ResourceLoader {
                                echo "mediaWiki.loader.implement( '$name', function() {{$scripts}},\n'$styles',\n$messages );\n";
                        }
                }
+
                // Update the status of script-only modules
                if ( $context->getOnly() === 'scripts' && !in_array( 'startup', $modules ) ) {
                        $statuses = array();
+
                        foreach ( $modules as $name ) {
                                $statuses[$name] = 'ready';
                        }
+
                        $statuses = FormatJson::encode( $statuses );
                        echo "mediaWiki.loader.state( $statuses );";
                }
+
                // Register missing modules
                if ( $context->shouldIncludeScripts() ) {
                        foreach ( $missing as $name ) {
                                echo "mediaWiki.loader.register( '$name', null, 'missing' );\n";
                        }
                }
+
                // Output the appropriate header
                if ( $context->getOnly() !== 'styles' ) {
                        if ( $context->getDebug() ) {
@@ -340,4 +361,4 @@ class ResourceLoader {
 }
 
 // FIXME: Temp hack
-require_once "$IP/resources/Resources.php";
\ No newline at end of file
+require_once "$IP/resources/Resources.php";
index c6a277f..3052b5f 100644 (file)
@@ -23,9 +23,8 @@
  * Object passed around to modules which contains information about the state of a specific loader request
  */
 class ResourceLoaderContext {
-       
        /* Protected Members */
-       
+
        protected $request;
        protected $server;
        protected $modules;
@@ -35,12 +34,12 @@ class ResourceLoaderContext {
        protected $debug;
        protected $only;
        protected $hash;
-       
+
        /* Methods */
-       
+
        public function __construct( WebRequest $request, $server ) {
                global $wgUser, $wgLang, $wgDefaultSkin;
-               
+
                $this->request = $request;
                $this->server = $server;
                // Interperet request
@@ -50,30 +49,33 @@ class ResourceLoaderContext {
                $this->skin = $request->getVal( 'skin' );
                $this->debug = $request->getVal( 'debug' ) === 'true' || $request->getBool( 'debug' );
                $this->only = $request->getVal( 'only' );
+
                // Fallback on system defaults
                if ( !$this->language ) {
                        $this->language = $wgLang->getCode();
                }
+
                if ( !$this->direction ) {
                        $this->direction = Language::factory( $this->language )->getDir();
                }
+
                if ( !$this->skin ) {
                        $this->skin = $wgDefaultSkin;
                }
        }
-       
+
        public function getRequest() {
                return $this->request;
        }
-       
+
        public function getServer() {
                return $this->server;
        }
-       
+
        public function getModules() {
                return $this->modules;
        }
-       
+
        public function getLanguage() {
                return $this->language;
        }
@@ -81,33 +83,33 @@ class ResourceLoaderContext {
        public function getDirection() {
                return $this->direction;
        }
-       
+
        public function getSkin() {
                return $this->skin;
        }
-       
+
        public function getDebug() {
                return $this->debug;
        }
-       
+
        public function getOnly() {
                return $this->only;
        }
-       
+
        public function shouldIncludeScripts() {
                return is_null( $this->only ) || $this->only === 'scripts';
        }
-       
+
        public function shouldIncludeStyles() {
                return is_null( $this->only ) || $this->only === 'styles';
        }
-       
+
        public function shouldIncludeMessages() {
                return is_null( $this->only ) || $this->only === 'messages';
        }
-       
+
        public function getHash() {
                return isset( $this->hash ) ?
                        $this->hash : $this->hash = implode( '|', array( $this->language, $this->skin, $this->debug ) );
        }
-}
\ No newline at end of file
+}
index b0b509d..febaeb7 100644 (file)
@@ -14,7 +14,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  * http://www.gnu.org/copyleft/gpl.html
- * 
+ *
  * @author Trevor Parscal
  * @author Roan Kattouw
  */
  * Interface for resource loader modules, with name registration and maxage functionality.
  */
 abstract class ResourceLoaderModule {
-       
        /* Protected Members */
-       
+
        protected $name = null;
-       
+
        /* Methods */
-       
+
        /**
         * Get this module's name. This is set when the module is registered
         * with ResourceLoader::register()
@@ -38,7 +37,7 @@ abstract class ResourceLoaderModule {
        public function getName() {
                return $this->name;
        }
-       
+
        /**
         * Set this module's name. This is called by ResourceLodaer::register()
         * when registering the module. Other code should not call this.
@@ -47,7 +46,7 @@ abstract class ResourceLoaderModule {
        public function setName( $name ) {
                $this->name = $name;
        }
-       
+
        /**
         * The maximum number of seconds to cache this module for in the
         * client-side (browser) cache. Override this only if you have a good
@@ -58,7 +57,7 @@ abstract class ResourceLoaderModule {
                global $wgResourceLoaderClientMaxage;
                return $wgResourceLoaderClientMaxage;
        }
-       
+
        /**
         * The maximum number of seconds to cache this module for in the
         * server-side (Squid / proxy) cache. Override this only if you have a
@@ -76,9 +75,9 @@ abstract class ResourceLoaderModule {
        public function getFlip( $context ) {
                return $context->getDirection() === 'rtl';
        }
-       
+
        /* Abstract Methods */
-       
+
        /**
         * Get all JS for this module for a given language and skin.
         * Includes all relevant JS except loader scripts.
@@ -88,14 +87,14 @@ abstract class ResourceLoaderModule {
         * @return string JS
         */
        public abstract function getScript( ResourceLoaderContext $context );
-       
+
        /**
         * Get all CSS for this module for a given skin.
         * @param $skin string Skin name
         * @return string CSS
         */
        public abstract function getStyle( ResourceLoaderContext $context );
-       
+
        /**
         * Get the messages needed for this module.
         *
@@ -103,13 +102,13 @@ abstract class ResourceLoaderModule {
         * @return array of message keys. Keys may occur more than once
         */
        public abstract function getMessages();
-       
+
        /**
         * Get the loader JS for this module, if set.
         * @return mixed Loader JS (string) or false if no custom loader set
         */
        public abstract function getLoaderScript();
-       
+
        /**
         * Get a list of modules this module depends on.
         *
@@ -126,7 +125,7 @@ abstract class ResourceLoaderModule {
         * @return array Array of module names (strings)
         */
        public abstract function getDependencies();
-       
+
        /**
         * Get this module's last modification timestamp for a given
         * combination of language, skin and debug mode flag. This is typically
@@ -145,9 +144,8 @@ abstract class ResourceLoaderModule {
  * Module based on local JS/CSS files. This is the most common type of module.
  */
 class ResourceLoaderFileModule extends ResourceLoaderModule {
-       
        /* Protected Members */
-       
+
        protected $scripts = array();
        protected $styles = array();
        protected $messages = array();
@@ -158,24 +156,24 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        protected $skinStyles = array();
        protected $loaders = array();
        protected $parameters = array();
-       
+
        // In-object cache for file dependencies
        protected $fileDeps = array();
        // In-object cache for mtime
        protected $modifiedTime = array();
-       
+
        /* Methods */
-       
+
        /**
         * Construct a new module from an options array.
         *
         * @param $options array Options array. If empty, an empty module will be constructed
-        * 
+        *
         * $options format:
         *      array(
         *              // Required module options (mutually exclusive)
         *              'scripts' => 'dir/script.js' | array( 'dir/script1.js', 'dir/script2.js' ... ),
-        *              
+        *
         *              // Optional module options
         *              'languageScripts' => array(
         *                      '[lang name]' => 'dir/lang.js' | '[lang name]' => array( 'dir/lang1.js', 'dir/lang2.js' ... )
@@ -183,7 +181,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         *              ),
         *              'skinScripts' => 'dir/skin.js' | array( 'dir/skin1.js', 'dir/skin2.js' ... ),
         *              'debugScripts' => 'dir/debug.js' | array( 'dir/debug1.js', 'dir/debug2.js' ... ),
-        * 
+        *
         *              // Non-raw module options
         *              'dependencies' => 'module' | array( 'module1', 'module2' ... )
         *              'loaderScripts' => 'dir/loader.js' | array( 'dir/loader1.js', 'dir/loader2.js' ... ),
@@ -228,7 +226,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        }
                }
        }
-       
+
        /**
         * Add script files to this module. In order to be valid, a module
         * must contain at least one script file.
@@ -237,7 +235,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        public function addScripts( $scripts ) {
                $this->scripts = array_merge( $this->scripts, (array)$scripts );
        }
-       
+
        /**
         * Add style (CSS) files to this module.
         * @param $styles mixed Path to CSS file (string) or array of paths
@@ -245,7 +243,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        public function addStyles( $styles ) {
                $this->styles = array_merge( $this->styles, (array)$styles );
        }
-       
+
        /**
         * Add messages to this module.
         * @param $messages mixed Message key (string) or array of message keys
@@ -253,7 +251,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        public function addMessages( $messages ) {
                $this->messages = array_merge( $this->messages, (array)$messages );
        }
-       
+
        /**
         * Add dependencies. Dependency information is taken into account when
         * loading a module on the client side. When adding a module on the
@@ -271,7 +269,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        public function addDependencies( $dependencies ) {
                $this->dependencies = array_merge( $this->dependencies, (array)$dependencies );
        }
-       
+
        /**
         * Add debug scripts to the module. These scripts are only included
         * in debug mode.
@@ -280,7 +278,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        public function addDebugScripts( $scripts ) {
                $this->debugScripts = array_merge( $this->debugScripts, (array)$scripts );
        }
-       
+
        /**
         * Add language-specific scripts. These scripts are only included for
         * a given language.
@@ -306,7 +304,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        array( $skin => $scripts )
                );
        }
-       
+
        /**
         * Add skin-specific CSS. These CSS files are only included for a
         * given skin. If there are no skin-specific CSS files for a skin,
@@ -320,7 +318,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        array( $skin => $scripts )
                );
        }
-       
+
        /**
         * Add loader scripts. These scripts are loaded on every page and are
         * responsible for registering this module using
@@ -337,23 +335,25 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        public function addLoaders( $scripts ) {
                $this->loaders = array_merge( $this->loaders, (array)$scripts );
        }
-       
+
        public function getScript( ResourceLoaderContext $context ) {
                $retval = $this->getPrimaryScript() . "\n" .
                        $this->getLanguageScript( $context->getLanguage() ) . "\n" .
                        $this->getSkinScript( $context->getSkin() );
+
                if ( $context->getDebug() ) {
                        $retval .= $this->getDebugScript();
                }
+
                return $retval;
        }
-       
+
        public function getStyle( ResourceLoaderContext $context ) {
                $style = $this->getPrimaryStyle() . "\n" . $this->getSkinStyle( $context->getSkin() );
-               
+
                // Extract and store the list of referenced files
                $files = CSSMin::getLocalFileReferences( $style );
-               
+
                // Only store if modified
                if ( $files !== $this->getFileDependencies( $context->getSkin() ) ) {
                        $encFiles = FormatJson::encode( $files );
@@ -365,30 +365,33 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                                        'md_deps' => $encFiles,
                                )
                        );
-                       
+
                        // Save into memcached
                        global $wgMemc;
+
                        $key = wfMemcKey( 'resourceloader', 'module_deps', $this->getName(), $context->getSkin() );
                        $wgMemc->set( $key, $encFiles );
                }
+
                return $style;
        }
-       
+
        public function getMessages() {
                return $this->messages;
        }
-       
+
        public function getDependencies() {
                return $this->dependencies;
        }
-       
+
        public function getLoaderScript() {
                if ( count( $this->loaders ) == 0 ) {
                        return false;
                }
+
                return self::concatScripts( $this->loaders );
        }
-       
+
        /**
         * Get the last modified timestamp of this module, which is calculated
         * as the highest last modified timestamp of its constituent files and
@@ -405,7 +408,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                if ( isset( $this->modifiedTime[$context->getHash()] ) ) {
                        return $this->modifiedTime[$context->getHash()];
                }
-               
+
                $files = array_merge(
                        $this->scripts,
                        $this->styles,
@@ -417,8 +420,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        $this->loaders,
                        $this->getFileDependencies( $context->getSkin() )
                );
+
                $filesMtime = max( array_map( 'filemtime', array_map( array( __CLASS__, 'remapFilename' ), $files ) ) );
-               
+
                // Get the mtime of the message blob
                // TODO: This timestamp is queried a lot and queried separately for each module. Maybe it should be put in memcached?
                $dbr = wfGetDb( DB_SLAVE );
@@ -428,13 +432,13 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        ), __METHOD__
                );
                $msgBlobMtime = $msgBlobMtime ? wfTimestamp( TS_UNIX, $msgBlobMtime ) : 0;
-               
+
                $this->modifiedTime[$context->getHash()] = max( $filesMtime, $msgBlobMtime );
                return $this->modifiedTime[$context->getHash()];
        }
-               
+
        /* Protected Members */
-       
+
        /**
         * Get the primary JS for this module. This is pulled from the
         * script files added through addScripts()
@@ -443,7 +447,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        protected function getPrimaryScript() {
                return self::concatScripts( $this->scripts );
        }
-       
+
        /**
         * Get the primary CSS for this module. This is pulled from the CSS
         * files added through addStyles()
@@ -452,7 +456,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        protected function getPrimaryStyle() {
                return self::concatStyles( $this->styles );
        }
-       
+
        /**
         * Get the debug JS for this module. This is pulled from the script
         * files added through addDebugScripts()
@@ -461,7 +465,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        protected function getDebugScript() {
                return self::concatScripts( $this->debugScripts );
        }
-       
+
        /**
         * Get the language-specific JS for a given language. This is pulled
         * from the language-specific script files added through addLanguageScripts()
@@ -473,7 +477,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                }
                return self::concatScripts( $this->languageScripts[$lang] );
        }
-       
+
        /**
         * Get the skin-specific JS for a given skin. This is pulled from the
         * skin-specific JS files added through addSkinScripts()
@@ -482,7 +486,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        protected function getSkinScript( $skin ) {
                return self::concatScripts( self::getSkinFiles( $skin, $this->skinScripts ) );
        }
-       
+
        /**
         * Get the skin-specific CSS for a given skin. This is pulled from the
         * skin-specific CSS files added through addSkinStyles()
@@ -491,7 +495,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        protected function getSkinStyle( $skin ) {
                return self::concatStyles( self::getSkinFiles( $skin, $this->skinStyles ) );
        }
-       
+
        /**
         * Helper function to get skin-specific data from an array.
         * @param $skin string Skin name
@@ -500,14 +504,16 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         */
        protected static function getSkinFiles( $skin, $map ) {
                $retval = array();
+
                if ( isset( $map[$skin] ) && $map[$skin] ) {
                        $retval = $map[$skin];
                } else if ( isset( $map['default'] ) ) {
                        $retval = $map['default'];
                }
+
                return $retval;
        }
-       
+
        /**
         * Get the files this module depends on indirectly for a given skin.
         * Currently these are only image files referenced by the module's CSS.
@@ -519,12 +525,13 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                if ( isset( $this->fileDeps[$skin] ) ) {
                        return $this->fileDeps[$skin];
                }
-               
+
                // Now try memcached
                global $wgMemc;
+
                $key = wfMemcKey( 'resourceloader', 'module_deps', $this->getName(), $skin );
                $deps = $wgMemc->get( $key );
-               
+
                if ( !$deps ) {
                        $dbr = wfGetDb( DB_SLAVE );
                        $deps = $dbr->selectField( 'module_deps', 'md_deps', array(
@@ -537,10 +544,12 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        }
                        $wgMemc->set( $key, $deps );
                }
+
                $this->fileDeps = FormatJson::decode( $deps, true );
+
                return $this->fileDeps;
        }
-       
+
        /**
         * Get the contents of a set of files and concatenate them, with
         * newlines in between. Each file is used only once.
@@ -550,7 +559,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        protected static function concatScripts( $files ) {
                return implode( "\n", array_map( 'file_get_contents', array_map( array( __CLASS__, 'remapFilename' ), array_unique( (array) $files ) ) ) );
        }
-       
+
        /**
         * Get the contents of a set of CSS files, remap then and concatenate
         * them, with newlines in between. Each file is used only once.
@@ -560,7 +569,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        protected static function concatStyles( $files ) {
                return implode( "\n", array_map( array( __CLASS__, 'remapStyle' ), array_unique( (array) $files ) ) );
        }
-       
+
        /**
         * Remap a relative to $IP. Used as a callback for array_map()
         * @param $file string File name
@@ -568,9 +577,10 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         */
        protected static function remapFilename( $file ) {
                global $IP;
+
                return "$IP/$file";
        }
-       
+
        /**
         * Get the contents of a CSS file and run it through CSSMin::remap().
         * This wrapper is needed so we can use array_map() in concatStyles()
@@ -587,44 +597,45 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
  * TODO: Add Site CSS functionality too
  */
 class ResourceLoaderSiteModule extends ResourceLoaderModule {
-       
        /* Protected Members */
-       
+
        // In-object cache for modified time
        protected $modifiedTime = null;
-       
+
        /* Methods */
-       
+
        public function getScript( ResourceLoaderContext $context ) {
                return Skin::newFromKey( $context->getSkin() )->generateUserJs();
        }
-       
+
        public function getModifiedTime( ResourceLoaderContext $context ) {
                if ( isset( $this->modifiedTime[$context->getHash()] ) ) {
                        return $this->modifiedTime[$context->getHash()];
                }
-               
+
                // HACK: We duplicate the message names from generateUserJs()
                // here and weird things (i.e. mtime moving backwards) can happen
                // when a MediaWiki:Something.js page is deleted
                $jsPages = array( Title::makeTitle( NS_MEDIAWIKI, 'Common.js' ),
                        Title::makeTitle( NS_MEDIAWIKI, ucfirst( $context->getSkin() ) . '.js' )
                );
-               
+
                // Do batch existence check
                // TODO: This would work better if page_touched were loaded by this as well
                $lb = new LinkBatch( $jsPages );
                $lb->execute();
-               
+
                $this->modifiedTime = 1; // wfTimestamp() interprets 0 as "now"
+
                foreach ( $jsPages as $jsPage ) {
                        if ( $jsPage->exists() ) {
                                $this->modifiedTime = max( $this->modifiedTime, wfTimestamp( TS_UNIX, $jsPage->getTouched() ) );
                        }
                }
+
                return $this->modifiedTime;
        }
-       
+
        public function getStyle( ResourceLoaderContext $context ) { return ''; }
        public function getMessages() { return array(); }
        public function getLoaderScript() { return ''; }
@@ -633,17 +644,17 @@ class ResourceLoaderSiteModule extends ResourceLoaderModule {
 
 
 class ResourceLoaderStartUpModule extends ResourceLoaderModule {
-       
        /* Protected Members */
-       
+
        protected $modifiedTime = null;
-       
+
        /* Methods */
-       
+
        public function getScript( ResourceLoaderContext $context ) {
                global $IP;
-               
+
                $scripts = file_get_contents( "$IP/resources/startup.js" );
+
                if ( $context->getOnly() === 'scripts' ) {
                        // Get all module registrations
                        $registration = ResourceLoader::getModuleRegistrations( $context );
@@ -668,6 +679,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                                        ), -2 ) )
                                )
                        );
+
                        // Build HTML code for loading jquery and mediawiki modules
                        $loadScript = Html::linkedScript( $context->getServer() . "?$query" );
                        // Add code to add jquery and mediawiki loading code; only if the current client is compatible
@@ -675,34 +687,39 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        // Delete the compatible function - it's not needed anymore
                        $scripts .= "delete window['isCompatible'];";
                }
+
                return $scripts;
        }
-       
+
        public function getModifiedTime( ResourceLoaderContext $context ) {
                global $IP;
+
                if ( !is_null( $this->modifiedTime ) ) {
                        return $this->modifiedTime;
                }
+
                // HACK getHighestModifiedTime() calls this function, so protect against infinite recursion
                $this->modifiedTime = filemtime( "$IP/resources/startup.js" );
                $this->modifiedTime = ResourceLoader::getHighestModifiedTime( $context );
                return $this->modifiedTime;
        }
-       
+
        public function getClientMaxage() {
                return 300; // 5 minutes
        }
-       
+
        public function getServerMaxage() {
                return 300; // 5 minutes
        }
-       
+
        public function getStyle( ResourceLoaderContext $context ) { return ''; }
+
        public function getFlip( $context ) {
                global $wgContLang;
+
                return $wgContLang->getDir() !== $context->getDirection();
        }
        public function getMessages() { return array(); }
        public function getLoaderScript() { return ''; }
        public function getDependencies() { return array(); }
-}
\ No newline at end of file
+}
index 9affd3d..a17e56d 100644 (file)
--- a/load.php
+++ b/load.php
@@ -22,7 +22,7 @@
  * @author Trevor Parscal
  *
  */
+
 require ( dirname( __FILE__ ) . '/includes/WebStart.php' );
 wfProfileIn( 'load.php' );
 
@@ -51,4 +51,4 @@ wfProfileOut( 'load.php' );
 wfLogProfilingData();
 
 // Shut down the database
-wfGetLBFactory()->shutdown();
\ No newline at end of file
+wfGetLBFactory()->shutdown();
index 5f5447c..5ad7d93 100644 (file)
@@ -1,16 +1,15 @@
 <?php
 
 class ResourceLoaderFileModuleTest extends PHPUnit_Framework_TestCase {
-
        /* Provider Methods */
-       
+
        public function provide() {
-               
+
        }
-       
+
        /* Test Methods */
-       
+
        public function test() {
-               
+
        }
-}
\ No newline at end of file
+}
index f899554..73c923f 100644 (file)
@@ -1,16 +1,15 @@
 <?php
 
 class ResourceLoaderTest extends PHPUnit_Framework_TestCase {
-       
        /* Provider Methods */
-       
+
        public function provide() {
-               
+
        }
-       
+
        /* Test Methods */
-       
+
        public function test() {
-               
+
        }
-}
\ No newline at end of file
+}