Foxtrott has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/124275

Change subject: rework extension (switch LESS compiler, composer install, 
upgrade Bootstrap version)
......................................................................

rework extension (switch LESS compiler, composer install, upgrade Bootstrap 
version)

Change-Id: Ibbc7b79f208fbee51d3b54f1d85f325cac909858
---
D .gitmodules
M Bootstrap.php
D ResourceLoaderBootstrapModule.php
D bootstrap
A composer.json
R includes/BootstrapManager.php
A includes/Hooks.php
A includes/ResourceLoaderBootstrapModule.php
8 files changed, 362 insertions(+), 265 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Bootstrap 
refs/changes/75/124275/1

diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 8b0f01a..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "bootstrap"]
-       path = bootstrap
-       url = https://github.com/s7eph4n/bootstrap.git
diff --git a/Bootstrap.php b/Bootstrap.php
index ec3fad8..8ea835a 100644
--- a/Bootstrap.php
+++ b/Bootstrap.php
@@ -2,11 +2,11 @@
 /**
  * An extension providing the Bootstrap library to other extensions
  *
- * @see https://www.mediawiki.org/wiki/Extension:Bootstrap
- * @see http://twitter.github.io/bootstrap
+ * @see      https://www.mediawiki.org/wiki/Extension:Bootstrap
+ * @see      http://twitter.github.io/bootstrap
  *
- * @author Stephan Gambke
- * @version 0.2 alpha
+ * @author   Stephan Gambke
+ * @version  1.0-alpha
  *
  * @defgroup Bootstrap Bootstrap
  */
@@ -15,7 +15,7 @@
  * The main file of the Bootstrap extension
  *
  * @copyright (C) 2013, Stephan Gambke
- * @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public 
License, version 3 (or later)
+ * @license       http://www.gnu.org/licenses/gpl-3.0.html GNU General Public 
License, version 3 (or later)
  *
  * This file is part of the MediaWiki extension Bootstrap.
  * The Bootstrap extension is free software: you can redistribute it and/or
@@ -32,66 +32,45 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * @file
- * @ingroup Bootstrap
+ * @ingroup       Bootstrap
  */
-if ( !defined( 'MEDIAWIKI' ) ) {
-       die( 'This file is part of the MediaWiki extension Bootstrap, it is not 
a valid entry point.' );
-}
 
-if ( version_compare( $wgVersion, '1.22alpha', 'lt' ) ) {
-       die( '<b>Error:</b> This version of <a 
href="https://www.mediawiki.org/wiki/Extension:Bootstrap";>Bootstrap</a> is only 
compatible with MediaWiki 1.22 or above. You need to upgrade MediaWiki first.' 
);
-}
 
-/**
- * The extension version
- */
-define( 'BS_VERSION', '0.3 alpha' );
+call_user_func( function () {
 
-// register the extension
-$wgExtensionCredits['other'][] = array(
-       'path' => __FILE__,
-       'name' => 'Bootstrap',
-       'author' => '[http://www.mediawiki.org/wiki/User:F.trott Stephan 
Gambke]',
-       'url' => 'https://www.mediawiki.org/wiki/Extension:Bootstrap',
-       'descriptionmsg' => 'bootstrap-desc',
-       'version' => BS_VERSION,
-);
 
-// server-local path to this file
-$dir = dirname( __FILE__ );
+       if ( !defined( 'MEDIAWIKI' ) ) {
+               die( 'This file is part of the MediaWiki extension Bootstrap, 
it is not a valid entry point.' );
+       }
 
-// remote path to the Bootstrap extension
-$scriptPath = ( $wgExtensionAssetsPath === false ? $wgScriptPath . 
'/extensions' : $wgExtensionAssetsPath ) . '/Bootstrap';
+       if ( version_compare( $GLOBALS[ 'wgVersion' ], '1.22alpha', 'lt' ) ) {
+               die( '<b>Error:</b> This version of <a 
href="https://www.mediawiki.org/wiki/Extension:Bootstrap";>Bootstrap</a> is only 
compatible with MediaWiki 1.22 or above. You need to upgrade MediaWiki first.' 
);
+       }
 
-// register message files
-$wgMessagesDirs['Bootstrap'] = __DIR__ . '/i18n';
-$wgExtensionMessagesFiles['Bootstrap'] = $dir . '/Bootstrap.i18n.php';
+       /**
+        * The extension version
+        */
+       define( 'BS_VERSION', '1.0-alpha' );
 
-$wgAutoloadClasses['bootstrap\ResourceLoaderBootstrapModule'] = $dir . 
'/ResourceLoaderBootstrapModule.php';
-$wgAutoloadClasses['Bootstrap'] = $dir . '/Bootstrap.class.php';
+       // register the extension
+       $GLOBALS[ 'wgExtensionCredits' ][ 'other' ][ ] = array(
+               'path'           => __FILE__,
+               'name'           => 'Bootstrap',
+               'author'         => 
'[http://www.mediawiki.org/wiki/User:F.trott Stephan Gambke]',
+               'url'            => 
'https://www.mediawiki.org/wiki/Extension:Bootstrap',
+               'descriptionmsg' => 'bootstrap-desc',
+               'version'        => BS_VERSION,
+       );
 
-// register skeleton resource module with the Resource Loader
-$wgResourceModules['ext.bootstrap.styles'] = array(
-       'localBasePath' => $dir,
-       'remoteExtPath' => 'Bootstrap',
-       'class' => 'bootstrap\ResourceLoaderBootstrapModule',
-       'styles' => array(),
-       'variables' => array(
-               'icon-font-path' => "\"$scriptPath/bootstrap/fonts/\"",
-       ),
-       'paths' => array( $dir . '/bootstrap/less' ),
-       'dependencies' => array(),
-);
+       // register message files
+       $GLOBALS[ 'wgMessagesDirs' ][ 'Bootstrap' ] = __DIR__ . '/i18n';
+       $GLOBALS[ 'wgExtensionMessagesFiles' ][ 'Bootstrap' ] = __DIR__ . 
'/Bootstrap.i18n.php';
 
-$wgResourceModules['ext.bootstrap.scripts'] = array(
-       'localBasePath' => $dir,
-       'remoteExtPath' => 'Bootstrap',
-       'scripts' => array(),
-);
+       // register classes
+       $GLOBALS[ 'wgAutoloadClasses' ][ 
'bootstrap\ResourceLoaderBootstrapModule' ] = __DIR__ . 
'/includes/ResourceLoaderBootstrapModule.php';
+       $GLOBALS[ 'wgAutoloadClasses' ][ 'bootstrap\BootstrapManager' ] = 
__DIR__ . '/includes/BootstrapManager.php';
+       $GLOBALS[ 'wgAutoloadClasses' ][ 'bootstrap\Hooks' ] = __DIR__ . 
'/includes/Hooks.php';
 
-$wgResourceModules[ 'ext.bootstrap' ] = array(
-       'dependencies' => array( 'ext.bootstrap.styles', 
'ext.bootstrap.scripts' ),
-);
+       $GLOBALS[ 'wgHooks' ][ 'SetupAfterCache' ][ ] = 
'bootstrap\Hooks::onSetupAfterCache';
 
-unset( $dir );
-unset( $scriptPath );
+} );
diff --git a/ResourceLoaderBootstrapModule.php 
b/ResourceLoaderBootstrapModule.php
deleted file mode 100644
index e6f972d..0000000
--- a/ResourceLoaderBootstrapModule.php
+++ /dev/null
@@ -1,153 +0,0 @@
-<?php
-/**
- * File holding the ResourceLoaderBootstrapModule class
- *
- * @copyright (C) 2013, Stephan Gambke
- * @license   http://www.gnu.org/licenses/gpl-3.0.html GNU General Public 
License, version 3 (or later)
- *
- * This file is part of the MediaWiki extension Bootstrap.
- * The Bootstrap extension is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The Bootstrap extension is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @file
- * @ingroup   Bootstrap
- */
-
-namespace Bootstrap;
-
-use lessc;
-use ResourceLoader;
-use ResourceLoaderContext;
-use ResourceLoaderFileModule;
-
-/**
- * ResourceLoader module based on local JavaScript/LESS files.
- *
- * Different to the behaviour of ResourceLoaderFileModule this module compiles 
all LESS files in one compile context.
- *
- * It recognizes the following additional fields in $wgResourceModules:
- * * styles: array of LESS file names (with or without extension .less)
- * * variables: array of key value pairs representing LESS variables, that 
will be added to the LESS script after all
- *              files imports, i.e. that may override any variable set in 
style files
- * * paths: array of paths to search for style files; all these paths together 
represent one virtual file base and will
- *             be searched for a style file; this means it is not possible to 
include two LESS files with the same name
- *          even if in different paths
- *
- * @package Bootstrap
- */
-class ResourceLoaderBootstrapModule extends ResourceLoaderFileModule {
-
-       protected $variables = array();
-       protected $paths = array();
-
-       public function __construct( $options = array(), $localBasePath = null, 
$remoteBasePath = null
-       ) {
-
-               parent::__construct( $options, $localBasePath, $remoteBasePath 
);
-
-               if ( isset( $options[ 'variables' ] ) ) {
-                       $this->variables = $options[ 'variables' ];
-               }
-
-               if ( isset( $options[ 'paths' ] ) ) {
-                       $this->paths = $options[ 'paths' ];
-               }
-
-       }
-
-       /**
-        * Get the compiled Bootstrap styles
-        *
-        * @param ResourceLoaderContext $context
-        *
-        * @return array
-        */
-       public function getStyles( ResourceLoaderContext $context ) {
-
-               global $IP, $wgUser;
-
-               // Try for cache hit
-               $data     = $wgUser->getId(); // caching styles per user
-               $cacheKey = wfMemcKey( 'ext', 'bootstrap', $data );
-
-               $cache       = wfGetCache( CACHE_ANYTHING );
-               $cacheResult = $cache->get( $cacheKey );
-
-               // only use styles from cache if LocalSettings was not modified 
after the caching
-               if ( is_array( $cacheResult ) && $cacheResult[ 'storetime' ] >= 
filemtime( $IP . '/LocalSettings.php' ) ) {
-
-                       wfDebug( "ext.bootstrap: Cache hit: Got styles from 
cache.\n" );
-                       $styles = $cacheResult[ 'styles' ];
-
-               } else {
-
-                       if ( is_array( $cacheResult ) ) {
-                               wfDebug( "ext.bootstrap: Cache miss: Cache 
outdated, LocalSettings have changed.\n" );
-                       } else {
-                               wfDebug( "ext.bootstrap: Cache miss: Styles not 
found in cache.\n" );
-                       }
-
-                       $compiler = new lessc();
-
-                       // prepare a temp file containing all the variables to 
load
-                       // have to use a temp file for variables because inline 
variables do not overwrite @import'ed variables even if
-                       // set after the @import (see 
https://github.com/leafo/lessphp/issues/302 )
-                       $tmpFile = null;
-
-                       if ( !empty( $this->variables ) ) {
-
-                               $tmpFile = tempnam( sys_get_temp_dir(), 'php' );
-
-                               $handle = fopen( $tmpFile, 'w' );
-
-                               foreach ( $this->variables as $key => $value ) {
-                                       fwrite( $handle, "@$key: $value;\n" );
-                               }
-
-                               fclose( $handle );
-
-                               $this->styles[ ] = basename( $tmpFile );
-                               $this->paths[ ]  = dirname( $tmpFile );
-
-                       }
-
-                       // add all
-                       $lessCode = implode( array_map( function ( $module ) { 
return "@import \"$module\";\n"; }, $this->styles ) );
-
-                       // add additional paths for external files
-                       foreach ( $this->paths as $path ) {
-                               $compiler->addImportDir( $path );
-                       }
-
-                       try {
-
-                               $styles = array( 'all' => $compiler->compile( 
$lessCode ) );
-                               $cache->set( $cacheKey, array( 'styles' => 
$styles, 'storetime' => time() ) );
-
-                       } catch ( \Exception $e ) {
-                               wfDebug( $e->getMessage() );
-                               $styles = array( 'all' => '/* LESS compile 
error: ' . $e->getMessage() . '*/' );
-                       }
-
-                       unlink( $tmpFile );
-
-               }
-
-               return $styles;
-       }
-
-       public function supportsURLLoading() {
-
-               return false;
-       }
-}
diff --git a/bootstrap b/bootstrap
deleted file mode 160000
index 1e8a0bb..0000000
--- a/bootstrap
+++ /dev/null
-Subproject commit 1e8a0bbfb67e44ce9fd8a845239a775f5fcabf7a
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..384a07c
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,45 @@
+{
+       "name"       : "mediawiki/bootstrap",
+       "type"       : "mediawiki-extension",
+       "description": "Provides the Twitter Bootstrap3 web front-end framework 
to MediaWiki skins and extensions",
+       "keywords"   : [
+               "wiki",
+               "MediaWiki",
+               "extension",
+               "Twitter",
+               "Bootstrap"
+       ],
+       "homepage"   : "https://www.mediawiki.org/wiki/Extension:Bootstrap";,
+       "license"    : "GPL-3.0+",
+       "authors"    : [
+               {
+                       "name" : "Stephan Gambke",
+                       "email": "[email protected]",
+                       "role" : "Developer"
+               }
+       ],
+       "support"    : {
+               "wiki"  : "https://www.mediawiki.org/wiki/Extension:Bootstrap";,
+               "forum" : 
"https://www.mediawiki.org/wiki/Extension_talk:Bootstrap";,
+               "source": 
"https://git.wikimedia.org/tree/mediawiki%2Fextensions%2FBootstrap";,
+               "issues": 
"https://www.mediawiki.org/wiki/Extension_talk:Bootstrap";,
+               "irc"   : "irc://irc.freenode.org/mediawiki"
+       },
+       "require"    : {
+               "php"                : ">=5.3.0",
+               "composer/installers": "1.*,>=1.0.1",
+               "oyejorge/less.php"  : "~1.5",
+               "twitter/bootstrap"  : "~3.0"
+       },
+       "autoload"   : {
+               "files": [
+                       "Bootstrap.php"
+               ]
+       },
+       "extra"      : {
+               "branch-alias": {
+                       "dev-master": "1.x-dev"
+
+               }
+       }
+}
diff --git a/Bootstrap.class.php b/includes/BootstrapManager.php
similarity index 72%
rename from Bootstrap.class.php
rename to includes/BootstrapManager.php
index 82a3079..2a66b7c 100644
--- a/Bootstrap.class.php
+++ b/includes/BootstrapManager.php
@@ -23,13 +23,15 @@
  * @ingroup   Bootstrap
  */
 
+namespace bootstrap;
+
 /**
  * Class managing the Bootstrap framework.
  */
-class Bootstrap {
+class BootstrapManager {
 
 
-       static private $bootstrap = null;
+       static private $bootstrapManagerSingleton = null;
        static private $moduleDescriptions = array(
                'variables'            => array( 'styles' => 'variables' ),
                'mixins'               => array( 'styles' => 'mixins' ),
@@ -65,24 +67,24 @@
                'close'                => array( 'styles' => 'close' ),
 
                // Components w/ JavaScript
-               'modals'               => array( 'styles' => 'modals', 
'scripts' => 'bootstrap/js/modal.js' ),
-               'tooltip'              => array( 'styles' => 'tooltip', 
'scripts' => 'bootstrap/js/tooltip.js' ),
-               'popovers'             => array( 'styles' => 'popovers', 
'scripts' => 'bootstrap/js/popover.js', 'dependencies' => 'tooltip' ),
-               'carousel'             => array( 'styles' => 'carousel', 
'scripts' => 'bootstrap/js/carousel.js' ),
+               'modals'               => array( 'styles' => 'modals', 
'scripts' => 'modal' ),
+               'tooltip'              => array( 'styles' => 'tooltip', 
'scripts' => 'tooltip' ),
+               'popovers'             => array( 'styles' => 'popovers', 
'scripts' => 'popover', 'dependencies' => 'tooltip' ),
+               'carousel'             => array( 'styles' => 'carousel', 
'scripts' => 'carousel' ),
 
                // Utility classes
                'utilities'            => array( 'styles' => 'utilities' ),
                'responsive-utilities' => array( 'styles' => 
'responsive-utilities' ),
 
                // JS-only components
-               'affix'                => array( 'scripts' => 
'bootstrap/js/affix.js' ),
-               'alert'                => array( 'scripts' => 
'bootstrap/js/alert.js' ),
-               'button'               => array( 'scripts' => 
'bootstrap/js/button.js' ),
-               'collapse'             => array( 'scripts' => 
'bootstrap/js/collapse.js' ),
-               'dropdown'             => array( 'scripts' => 
'bootstrap/js/dropdown.js' ),
-               'scrollspy'            => array( 'scripts' => 
'bootstrap/js/scrollspy.js' ),
-               'tab'                  => array( 'scripts' => 
'bootstrap/js/tab.js' ),
-               'transition'           => array( 'scripts' => 
'bootstrap/js/transition.js' ),
+               'affix'                => array( 'scripts' => 'affix' ),
+               'alert'                => array( 'scripts' => 'alert' ),
+               'button'               => array( 'scripts' => 'button' ),
+               'collapse'             => array( 'scripts' => 'collapse' ),
+               'dropdown'             => array( 'scripts' => 'dropdown' ),
+               'scrollspy'            => array( 'scripts' => 'scrollspy' ),
+               'tab'                  => array( 'scripts' => 'tab' ),
+               'transition'           => array( 'scripts' => 'transition' ),
 
        );
 
@@ -101,23 +103,23 @@
 
        private $mModuleDescriptions;
 
-       public function __construct() {
+       protected function __construct() {
                $this->mModuleDescriptions = self::$moduleDescriptions;
        }
 
        /**
         * Returns the Bootstrap singleton.
         *
-        * @return Bootstrap
+        * @return BootstrapManager
         */
-       public static function getBootstrap() {
+       public static function getBootstrapManager() {
 
                // if singleton was not yet created
-               if ( self::$bootstrap === null ) {
+               if ( self::$bootstrapManagerSingleton === null ) {
                        self::initializeBootstrap();
                }
 
-               return self::$bootstrap;
+               return self::$bootstrapManagerSingleton;
        }
 
        /**
@@ -125,10 +127,10 @@
         */
        protected static function initializeBootstrap() {
 
-               self::$bootstrap = new Bootstrap();
+               self::$bootstrapManagerSingleton = new BootstrapManager();
 
                // add core Bootstrap modules
-               self::$bootstrap->addBootstrapModule( self::$coreModules );
+               self::$bootstrapManagerSingleton->addBootstrapModule( 
self::$coreModules );
        }
 
        /**
@@ -138,14 +140,12 @@
         */
        public function addBootstrapModule( $modules ) {
 
-               $modules = (array)$modules;
+               $modules = (array) $modules;
 
                foreach ( $modules as $module ) {
 
                        // if the module is known
-                       if ( array_key_exists( $module, 
$this->mModuleDescriptions ) ) {
-
-                               global $wgResourceModules;
+                       if ( isset( $this->mModuleDescriptions[ $module ] ) ) {
 
                                $description = $this->mModuleDescriptions[ 
$module ];
 
@@ -159,30 +159,34 @@
                                        $this->addBootstrapModule( 
$description[ 'dependencies' ] );
                                }
 
-                               // add less files to $wgResourceModules
-                               if ( isset( $description[ 'styles' ] ) ) {
-
-                                       $wgResourceModules[ 
'ext.bootstrap.styles' ][ 'styles' ] =
-                                               array_merge(
-                                                       $wgResourceModules[ 
'ext.bootstrap.styles' ][ 'styles' ],
-                                                       (array) $description[ 
'styles' ]
-                                               );
-                               }
-
-                               // add script files to $wgResourceModules
-                               if ( isset( $description[ 'scripts' ] ) ) {
-
-                                       $wgResourceModules[ 
'ext.bootstrap.scripts' ][ 'scripts' ] =
-                                               array_merge(
-                                                       $wgResourceModules[ 
'ext.bootstrap.scripts' ][ 'scripts' ],
-                                                       (array) $description[ 
'scripts' ]
-                                               );
-
-                               }
+                               $this->addFilesToGlobalResourceModules( 
'styles', $description, '.less' );
+                               $this->addFilesToGlobalResourceModules( 
'scripts', $description, '.js' );
 
                        }
                }
 
+       }
+
+       /**
+        * @param string       $filetype 'styles'|'scripts'
+        * @param array|string $description
+        * @param              $fileExt
+        *
+        * @internal param $relativePath
+        */
+       protected function addFilesToGlobalResourceModules ( $filetype, 
$description, $fileExt ) {
+
+               if ( isset( $description[ $filetype ] ) ) {
+
+                       $path = $GLOBALS[ 'wgResourceModules' ][ 
'ext.bootstrap.' . $filetype ][ 'localBasePath' ];
+
+                       $GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.' . 
$filetype ][ $filetype ] =
+                               array_merge(
+                                       $GLOBALS[ 'wgResourceModules' ][ 
'ext.bootstrap.' . $filetype ][ $filetype ],
+                                       array_map( function ( $filename ) use ( 
$fileExt ) { return $filename . $fileExt; }, (array) $description[ $filetype ])
+                               );
+
+               }
        }
 
        /**
@@ -194,18 +198,15 @@
        }
 
        /**
-        * @param string $path
         * @param string $file
+        * @param string $remotePath
+        *
+        * @internal param string $path
         */
-       public function addExternalModule( $path, $file ) {
+       public function addExternalModule( $file, $remotePath = '' ) {
 
                global $wgResourceModules;
-
-               if ( !in_array( $path, $wgResourceModules[ 
'ext.bootstrap.styles' ][ 'paths' ] ) ) {
-                       $wgResourceModules[ 'ext.bootstrap.styles' ][ 'paths' 
][ ] = $path;
-               }
-
-               $wgResourceModules[ 'ext.bootstrap.styles' ][ 'styles' ][ ] = 
$file;
+               $wgResourceModules[ 'ext.bootstrap.styles' ][ 'external styles' 
][ $file ] = $remotePath;
        }
 
        /**
diff --git a/includes/Hooks.php b/includes/Hooks.php
new file mode 100644
index 0000000..9160fe4
--- /dev/null
+++ b/includes/Hooks.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * File holding the BootstrapManager class
+ *
+ * @copyright (C) 2013, Stephan Gambke
+ * @license       http://www.gnu.org/licenses/gpl-3.0.html GNU General Public 
License, version 3 (or later)
+ *
+ * This file is part of the MediaWiki extension Bootstrap.
+ * The Bootstrap extension is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Bootstrap extension is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup       Bootstrap
+ */
+
+namespace bootstrap;
+
+/**
+ * Class Hooks holds the Bootstrap extension hook handlers
+ *
+ * @package bootstrap
+ */
+class Hooks {
+
+
+       public static function onSetupAfterCache() {
+
+               $localBasePath = $GLOBALS[ 'IP' ] . '/vendor/twitter/bootstrap';
+               $remoteBasePath = $GLOBALS[ 'wgScriptPath' ] . 
'/vendor/twitter/bootstrap';
+
+               // register skeleton resource module with the Resource Loader
+               $GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ] = 
array(
+                       'localBasePath'  => $localBasePath . '/less',
+                       'remoteBasePath' => $remoteBasePath. '/less',
+                       'class'          => 
'bootstrap\ResourceLoaderBootstrapModule',
+                       'styles'         => array(),
+                       'variables'      => array(
+                               'icon-font-path' => 
"\"$remoteBasePath/fonts/\"",
+                       ),
+                       'dependencies'   => array(),
+               );
+
+               $GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.scripts' ] = 
array(
+                       'localBasePath'  => $localBasePath . '/js',
+                       'remoteBasePath' => $remoteBasePath. '/js',
+                       'scripts'        => array(),
+               );
+
+               $GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap' ] = array(
+                       'dependencies' => array( 'ext.bootstrap.styles', 
'ext.bootstrap.scripts' ),
+               );
+
+               return true;
+
+       }
+
+}
diff --git a/includes/ResourceLoaderBootstrapModule.php 
b/includes/ResourceLoaderBootstrapModule.php
new file mode 100644
index 0000000..622139e
--- /dev/null
+++ b/includes/ResourceLoaderBootstrapModule.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * File holding the ResourceLoaderBootstrapModule class
+ *
+ * @copyright (C) 2013, Stephan Gambke
+ * @license       http://www.gnu.org/licenses/gpl-3.0.html GNU General Public 
License, version 3 (or later)
+ *
+ * This file is part of the MediaWiki extension Bootstrap.
+ * The Bootstrap extension is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Bootstrap extension is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @ingroup       Bootstrap
+ */
+
+namespace bootstrap;
+
+use lessc;
+use ResourceLoader;
+use ResourceLoaderContext;
+use ResourceLoaderFileModule;
+
+/**
+ * ResourceLoader module based on local JavaScript/LESS files.
+ *
+ * Different to the behaviour of ResourceLoaderFileModule this module compiles 
all LESS files in one compile context.
+ *
+ * It recognizes the following additional fields in $wgResourceModules:
+ * * styles: array of LESS file names (with or without extension .less)
+ * * variables: array of key value pairs representing LESS variables, that 
will be added to the LESS script after all
+ *              files imports, i.e. that may override any variable set in 
style files
+ * * paths: array of paths to search for style files; all these paths together 
represent one virtual file base and will
+ *            be searched for a style file; this means it is not possible to 
include two LESS files with the same name
+ *          even if in different paths
+ *
+ * @package Bootstrap
+ */
+class ResourceLoaderBootstrapModule extends ResourceLoaderFileModule {
+
+       protected $variables = array();
+       protected $paths = array();
+       protected $extStyles = array();
+
+       protected $styleText = null;
+
+       public function __construct( $options = array(), $localBasePath = null, 
$remoteBasePath = null
+       ) {
+
+               parent::__construct( $options, $localBasePath, $remoteBasePath 
);
+
+               if ( isset( $options[ 'variables' ] ) ) {
+                       $this->variables = $options[ 'variables' ];
+               }
+
+               if ( isset( $options[ 'paths' ] ) ) {
+                       $this->paths = $options[ 'paths' ];
+               }
+
+               if ( isset( $options[ 'external styles' ] ) ) {
+                       $this->extStyles = $options[ 'external styles' ];
+               }
+
+       }
+
+       /**
+        * Get the compiled Bootstrap styles
+        *
+        * @param ResourceLoaderContext $context
+        *
+        * @return array
+        */
+       public function getStyles( ResourceLoaderContext $context ) {
+
+               if ( $this->styleText === null ) {
+
+                       $this->retrieveStylesFromCache( $context );
+
+                       if ( $this->styleText === null ) {
+
+                               $this->compileStyles();
+                               $this->updateCache( $context );
+
+                       }
+               }
+
+               return array( 'all' => $this->styleText );
+       }
+
+       protected function getCacheKey( ResourceLoaderContext $context ) {
+               return wfMemcKey( 'ext', 'bootstrap', $context->getHash() );
+       }
+
+       protected function retrieveStylesFromCache( ResourceLoaderContext 
$context ) {
+
+               // Try for cache hit
+               $cache = wfGetCache( CACHE_ANYTHING );
+               $cacheResult = $cache->get( $this->getCacheKey( $context ) );
+
+               if ( is_array( $cacheResult ) ) {
+
+                       if ( $cacheResult[ 'storetime' ] >= filemtime( 
$GLOBALS[ 'IP' ] . '/LocalSettings.php' ) ) {
+
+                               $this->styleText = $cacheResult[ 'styles' ];
+
+                               wfDebug( "ext.bootstrap: Cache hit: Got styles 
from cache.\n" );
+                       } else {
+                               wfDebug( "ext.bootstrap: Cache miss: Cache 
outdated, LocalSettings have changed.\n" );
+                       }
+               } else {
+                       wfDebug( "ext.bootstrap: Cache miss: Styles not found 
in cache.\n" );
+               }
+       }
+
+       protected function updateCache( ResourceLoaderContext $context ) {
+
+               $cache = wfGetCache( CACHE_ANYTHING );
+               $cache->set( $this->getCacheKey( $context ), array( 'styles' => 
$this->styleText, 'storetime' => time() ) );
+
+       }
+
+       protected function compileStyles() {
+
+               $parser = new \Less_Parser();
+               $remotePath = $this->getRemotePath( '' );
+
+               try {
+
+                       foreach ( $this->styles as $style ) {
+                               $parser->parseFile( $this->getLocalPath( $style 
), $remotePath );
+                       }
+
+                       foreach ( $this->extStyles as $stylefile => $remotePath 
) {
+                               $parser->parseFile( $stylefile, $remotePath );
+                       }
+
+                       $parser->ModifyVars( $this->variables );
+
+                       $this->styleText = $parser->getCss();
+
+               } catch ( \Exception $e ) {
+                       wfDebug( $e->getMessage() );
+                       $this->styleText = '/* LESS compile error: ' . 
$e->getMessage() . '*/';
+               }
+
+       }
+
+       public function supportsURLLoading() {
+
+               return false;
+       }
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/124275
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibbc7b79f208fbee51d3b54f1d85f325cac909858
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Bootstrap
Gerrit-Branch: master
Gerrit-Owner: Foxtrott <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to