Maintenance script to check LESS files for validity

A reworked version of script from I068686854ad79e2f63a08d81b1af02f373110613

Move leccs instantiation code to ResourceLoader because it doesn't depend on any
particular module's state.

Change-Id: I733b53171dca77f50a30e5bd0bd5f1b456e4c85d
This commit is contained in:
Max Semenik 2013-09-28 11:40:03 +04:00
parent 2bc2f5d98c
commit 5c51cb96ea
4 changed files with 129 additions and 40 deletions

View file

@ -1213,4 +1213,41 @@ class ResourceLoader {
public static function isValidModuleName( $moduleName ) {
return !preg_match( '/[|,!]/', $moduleName ) && strlen( $moduleName ) <= 255;
}
/**
* Returns LESS compiler set up for use with MediaWiki
*
* @since 1.22
* @return lessc
*/
public static function getLessCompiler() {
global $wgResourceLoaderLESSFunctions, $wgResourceLoaderLESSImportPaths;
$less = new lessc();
$less->setPreserveComments( true );
$less->setVariables( self::getLESSVars() );
$less->setImportDir( $wgResourceLoaderLESSImportPaths );
foreach ( $wgResourceLoaderLESSFunctions as $name => $func ) {
$less->registerFunction( $name, $func );
}
return $less;
}
/**
* Get global LESS variables.
*
* $since 1.22
* @return array: Map of variable names to string CSS values.
*/
public static function getLESSVars() {
global $wgResourceLoaderLESSVars;
static $lessVars = null;
if ( $lessVars === null ) {
$lessVars = $wgResourceLoaderLESSVars;
// Sort by key to ensure consistent hashing for cache lookups.
ksort( $lessVars );
}
return $lessVars;
}
}

View file

@ -490,7 +490,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
* @param string $path
* @return string: the stylesheet language name
*/
protected function getStyleSheetLang( $path ) {
public function getStyleSheetLang( $path ) {
return preg_match( '/\.less$/i', $path ) ? 'less' : 'css';
}
@ -579,6 +579,23 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
);
}
/**
* Returns all stlyle files used bt this module
* @return array
*/
public function getAllStyleFiles() {
$files = array();
foreach( (array)$this->styles as $key => $value ) {
if ( is_array( $value ) ) {
$path = $key;
} else {
$path = $value;
}
$files[] = $this->getLocalPath( $path );
}
return $files;
}
/**
* Gets the contents of a list of JavaScript files.
*
@ -717,7 +734,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
protected static function getLESSCacheKey( $fileName ) {
global $wgShowExceptionDetails;
$vars = json_encode( self::getLESSVars() );
$vars = json_encode( ResourceLoader::getLESSVars() );
$hash = md5( $fileName . $vars );
return wfMemcKey( 'resourceloader', 'less', (string)$wgShowExceptionDetails, $hash );
}
@ -749,7 +766,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
$source = $fileName;
}
$compiler = self::lessCompiler();
$compiler = ResourceLoader::getLessCompiler();
$expire = 0;
try {
$result = $compiler->cachedCompile( $source );

View file

@ -407,9 +407,6 @@ abstract class ResourceLoaderModule {
private static $jsParser;
private static $parseCacheVersion = 1;
/** @var array Global LESS variables */
private static $lessVars;
/**
* Validate a given script file; if valid returns the original source.
* If invalid, returns replacement JS source that throws an exception.
@ -457,40 +454,6 @@ abstract class ResourceLoaderModule {
return self::$jsParser;
}
/**
* @since 1.22
* @return lessc
*/
protected static function lessCompiler() {
global $wgResourceLoaderLESSFunctions, $wgResourceLoaderLESSImportPaths;
$less = new lessc();
$less->setPreserveComments( true );
$less->setVariables( self::getLESSVars() );
$less->setImportDir( $wgResourceLoaderLESSImportPaths );
foreach ( $wgResourceLoaderLESSFunctions as $name => $func ) {
$less->registerFunction( $name, $func );
}
return $less;
}
/**
* Get global LESS variables.
*
* @since 1.22
* @return array: Map of variable names to string CSS values.
*/
protected static function getLESSVars() {
global $wgResourceLoaderLESSVars;
if ( self::$lessVars === null ) {
self::$lessVars = $wgResourceLoaderLESSVars;
// Sort by key to ensure consistent hashing for cache lookups.
ksort( self::$lessVars );
}
return self::$lessVars;
}
/**
* Safe version of filemtime(), which doesn't throw a PHP warning if the file doesn't exist
* but returns 1 instead.

72
maintenance/checkLess.php Normal file
View file

@ -0,0 +1,72 @@
<?php
/**
* Checks LESS files in known resources for errors
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup Maintenance
*/
require_once __DIR__ . '/Maintenance.php';
/**
* @ingroup Maintenance
*/
class CheckLess extends Maintenance {
public function __construct() {
parent::__construct();
$this->mDescription = 'Checks LESS files for errors';
}
public function execute() {
$result = false;
$resourceLoader = new ResourceLoader();
foreach ( $resourceLoader->getModuleNames() as $name ) {
/** @var ResourceLoaderFileModule $module */
$module = $resourceLoader->getModule( $name );
if ( !$module || !$module instanceof ResourceLoaderFileModule ) {
continue;
}
$hadErrors = false;
foreach ( $module->getAllStyleFiles() as $file ) {
if ( $module->getStyleSheetLang( $file ) !== 'less' ) {
continue;
}
try {
$compiler = ResourceLoader::getLessCompiler();
$compiler->compileFile( $file );
} catch ( Exception $e ) {
if ( !$hadErrors ) {
$this->error( "Errors checking module $name:\n" );
$hadErrors = true;
}
$this->error( $e->getMessage() . "\n" );
$result = true;
}
}
}
if ( !$result ) {
$this->output( "No errors found\n" );
} else {
die( 1 );
}
}
}
$maintClass = 'CheckLess';
require_once RUN_MAINTENANCE_IF_MAIN;