Explorar o código

#158 - Update LessPHP

AntonLV %!s(int64=11) %!d(string=hai) anos
pai
achega
9d80ac5593
Modificáronse 3 ficheiros con 159 adicións e 43 borrados
  1. 91 16
      plugins/lessphp/Cache.php
  2. 67 26
      plugins/lessphp/Less.php
  3. 1 1
      plugins/lessphp/Version.php

+ 91 - 16
plugins/lessphp/Cache.php

@@ -11,7 +11,17 @@ require_once( dirname(__FILE__).'/Version.php');
  */
 class Less_Cache{
 
-	public static $cache_dir = false;		// directory less.php can use for storing data
+	// directory less.php can use for storing data
+	public static $cache_dir	= false;
+
+	// prefix for the storing data
+	public static $prefix		= 'lessphp_';
+
+	// prefix for the storing vars
+	public static $prefix_vars	= 'lessphpvars_';
+
+	// specifies the number of seconds after which data created by less.php will be seen as 'garbage' and potentially cleaned up
+	public static $gc_lifetime	= 604800;
 
 
 	/**
@@ -36,6 +46,22 @@ class Less_Cache{
 			throw new Exception('cache_dir not set');
 		}
 
+		if( isset($parser_options['prefix']) ){
+			Less_Cache::$prefix = $parser_options['prefix'];
+		}
+
+		if( empty(Less_Cache::$prefix) ){
+			throw new Exception('prefix not set');
+		}
+
+		if( isset($parser_options['prefix_vars']) ){
+			Less_Cache::$prefix_vars = $parser_options['prefix_vars'];
+		}
+
+		if( empty(Less_Cache::$prefix_vars) ){
+			throw new Exception('prefix_vars not set');
+		}
+
 		self::CheckCacheDir();
 		$less_files = (array)$less_files;
 
@@ -43,7 +69,7 @@ class Less_Cache{
 		//create a file for variables
 		if( !empty($modify_vars) ){
 			$lessvars = Less_Parser::serializeVars($modify_vars);
-			$vars_file = Less_Cache::$cache_dir.'lessphpvars_' . sha1($lessvars) . '.less';
+			$vars_file = Less_Cache::$cache_dir . Less_Cache::$prefix_vars . sha1($lessvars) . '.less';
 
 			if( !file_exists($vars_file) ){
 				file_put_contents($vars_file, $lessvars);
@@ -55,21 +81,14 @@ class Less_Cache{
 
 		// generate name for compiled css file
 		$hash = md5(json_encode($less_files));
- 		$list_file = Less_Cache::$cache_dir.'lessphp_'.$hash.'.list';
+ 		$list_file = Less_Cache::$cache_dir . Less_Cache::$prefix . $hash . '.list';
 
 
  		// check cached content
  		if( !isset($parser_options['use_cache']) || $parser_options['use_cache'] === true ){
 			if( file_exists($list_file) ){
 
-				$list = explode("\n",file_get_contents($list_file));
-
-				//pop the cached name that should match $compiled_name
-				$cached_name = array_pop($list);
-				if( !preg_match('/^lessphp_[a-f0-9]+\.css$/',$cached_name) ){
-					$list[] = $cached_name;
-					$cached_name = false;
-				}
+				self::ListFiles($list_file, $list, $cached_name);
 				$compiled_name = self::CompiledName($list);
 
 				// if $cached_name != $compiled_name, we know we need to recompile
@@ -79,7 +98,6 @@ class Less_Cache{
 
 					if( $output_file && file_exists($output_file) ){
 						@touch($list_file);
-						@touch($output_file);
 						return basename($output_file); // for backwards compatibility, we just return the name of the file
 					}
 				}
@@ -184,7 +202,7 @@ class Less_Cache{
 			$temp[] = filemtime($file)."\t".filesize($file)."\t".$file;
 		}
 
-		return 'lessphp_'.sha1(json_encode($temp)).'.css';
+		return Less_Cache::$prefix.sha1(json_encode($temp)).'.css';
 	}
 
 
@@ -213,6 +231,10 @@ class Less_Cache{
 	}
 
 
+	/**
+	 * Delete unused less.php files
+	 *
+	 */
 	public static function CleanCache(){
 		static $clean = false;
 
@@ -222,15 +244,49 @@ class Less_Cache{
 
 		$files = scandir(Less_Cache::$cache_dir);
 		if( $files ){
-			$check_time = time() - 604800;
+			$check_time = time() - self::$gc_lifetime;
 			foreach($files as $file){
-				if( strpos($file,'lessphp_') !== 0 ){
+
+				// don't delete if the file wasn't created with less.php
+				if( strpos($file,Less_Cache::$prefix) !== 0 ){
 					continue;
 				}
+
 				$full_path = Less_Cache::$cache_dir.'/'.$file;
-				if( filemtime($full_path) > $check_time ){
+
+				// make sure the file still exists
+				// css files may have already been deleted
+				if( !file_exists($full_path) ){
+					continue;
+				}
+				$mtime = filemtime($full_path);
+
+				// don't delete if it's a relatively new file
+				if( $mtime > $check_time ){
 					continue;
 				}
+
+				$parts = explode('.',$file);
+				$type = array_pop($parts);
+
+
+				// delete css files based on the list files
+				if( $type === 'css' ){
+					continue;
+				}
+
+
+				// delete the list file and associated css file
+				if( $type === 'list' ){
+					self::ListFiles($full_path, $list, $css_file_name);
+					if( $css_file_name ){
+						$css_file = Less_Cache::$cache_dir.'/'.$css_file_name;
+						if( file_exists($css_file) ){
+							unlink($css_file);
+						}
+					}
+				}
+
 				unlink($full_path);
 			}
 		}
@@ -238,4 +294,23 @@ class Less_Cache{
 		$clean = true;
 	}
 
+
+	/**
+	 * Get the list of less files and generated css file from a list file
+	 *
+	 */
+	static function ListFiles($list_file, &$list, &$css_file_name ){
+
+		$list = explode("\n",file_get_contents($list_file));
+
+		//pop the cached name that should match $compiled_name
+		$css_file_name = array_pop($list);
+
+		if( !preg_match('/^' . Less_Cache::$prefix . '[a-f0-9]+\.css$/',$css_file_name) ){
+			$list[] = $css_file_name;
+			$css_file_name = false;
+		}
+
+	}
+
 }

+ 67 - 26
plugins/lessphp/Less.php

@@ -174,38 +174,48 @@ class Less_Parser{
 		$locale = setlocale(LC_NUMERIC, 0);
 		setlocale(LC_NUMERIC, "C");
 
+		try {
 
- 		$root = new Less_Tree_Ruleset(array(), $this->rules );
-		$root->root = true;
-		$root->firstRoot = true;
+	 		$root = new Less_Tree_Ruleset(array(), $this->rules );
+			$root->root = true;
+			$root->firstRoot = true;
 
 
-		$this->PreVisitors($root);
+			$this->PreVisitors($root);
 
-		self::$has_extends = false;
-		$evaldRoot = $root->compile($this->env);
+			self::$has_extends = false;
+			$evaldRoot = $root->compile($this->env);
 
 
 
-		$this->PostVisitors($evaldRoot);
+			$this->PostVisitors($evaldRoot);
 
-		if( Less_Parser::$options['sourceMap'] ){
-			$generator = new Less_SourceMap_Generator($evaldRoot, Less_Parser::$contentsMap, Less_Parser::$options );
-			// will also save file
-			// FIXME: should happen somewhere else?
-			$css = $generator->generateCSS();
-		}else{
-			$css = $evaldRoot->toCSS();
-		}
+			if( Less_Parser::$options['sourceMap'] ){
+				$generator = new Less_SourceMap_Generator($evaldRoot, Less_Parser::$contentsMap, Less_Parser::$options );
+				// will also save file
+				// FIXME: should happen somewhere else?
+				$css = $generator->generateCSS();
+			}else{
+				$css = $evaldRoot->toCSS();
+			}
 
-		if( Less_Parser::$options['compress'] ){
-			$css = preg_replace('/(^(\s)+)|((\s)+$)/', '', $css);
-		}
+			if( Less_Parser::$options['compress'] ){
+				$css = preg_replace('/(^(\s)+)|((\s)+$)/', '', $css);
+			}
+
+		} catch (Exception $exc) {
+        	   // Intentional fall-through so we can reset environment
+        	}
 
 		//reset php settings
 		@ini_set('precision',$precision);
 		setlocale(LC_NUMERIC, $locale);
 
+		// Rethrow exception after we handled resetting the environment
+		if (!empty($exc)) {
+            		throw $exc;
+        	}
+
 		return $css;
 	}
 
@@ -318,8 +328,13 @@ class Less_Parser{
 
 
 		$previousFileInfo = $this->env->currentFileInfo;
-		$filename = self::WinPath($filename);
+
+
+		if( $filename ){
+			$filename = self::WinPath(realpath($filename));
+		}
 		$uri_root = self::WinPath($uri_root);
+
 		$this->SetFileInfo($filename, $uri_root);
 
 		self::AddParsedFile($filename);
@@ -451,7 +466,17 @@ class Less_Parser{
 	 * @param string $file_path
 	 */
 	private function _parse( $file_path = null ){
+		if (ini_get("mbstring.func_overload")) {
+			$mb_internal_encoding = ini_get("mbstring.internal_encoding");
+			@ini_set("mbstring.internal_encoding", "ascii");
+		}
+
 		$this->rules = array_merge($this->rules, $this->GetRules( $file_path ));
+
+		//reset php settings
+		if (isset($mb_internal_encoding)) {
+			@ini_set("mbstring.internal_encoding", $mb_internal_encoding);
+		}
 	}
 
 
@@ -595,7 +620,7 @@ class Less_Parser{
 			$parts[] = $env;
 			$parts[] = Less_Version::cache_version;
 			$parts[] = Less_Parser::$options['cache_method'];
-			return Less_Cache::$cache_dir.'lessphp_'.base_convert( sha1(json_encode($parts) ), 16, 36).'.lesscache';
+			return Less_Cache::$cache_dir . Less_Cache::$prefix . base_convert( sha1(json_encode($parts) ), 16, 36) . '.lesscache';
 		}
 	}
 
@@ -4704,7 +4729,7 @@ class Less_Tree_Color extends Less_Tree{
 		// Values are capped between `0` and `255`, rounded and zero-padded.
 		//
 		if( $alpha < 1 ){
-			if( $alpha === 0 && isset($this->isTransparentKeyword) && $this->isTransparentKeyword ){
+			if( ( $alpha === 0 || $alpha === 0.0 ) && isset($this->isTransparentKeyword) && $this->isTransparentKeyword ){
 				return 'transparent';
 			}
 
@@ -5839,13 +5864,17 @@ class Less_Tree_Import extends Less_Tree{
 						$full_path = $path;
 						return array( $full_path, $uri );
 					}
-				}else{
+				}elseif( !empty($rootpath) ){
 					$path = rtrim($rootpath,'/\\').'/'.ltrim($evald_path,'/\\');
 
 					if( file_exists($path) ){
 						$full_path = Less_Environment::normalizePath($path);
 						$uri = Less_Environment::normalizePath(dirname($rooturi.$evald_path));
 						return array( $full_path, $uri );
+					} elseif( file_exists($path.'.less') ){
+						$full_path = Less_Environment::normalizePath($path.'.less');
+						$uri = Less_Environment::normalizePath(dirname($rooturi.$evald_path.'.less'));
+						return array( $full_path, $uri );
 					}
 				}
 			}
@@ -5887,7 +5916,7 @@ class Less_Tree_Import extends Less_Tree{
 	 */
 	private function Skip($path, $env){
 
-		$path = realpath($path);
+		$path = Less_Parser::winPath(realpath($path));
 
 		if( $path && Less_Parser::FileParsed($path) ){
 
@@ -7751,7 +7780,7 @@ class Less_Tree_Variable extends Less_Tree{
 			}
 		}
 
-		throw new Less_Exception_Compiler("variable " . $name . " is undefined in file ".$this->currentFileInfo["filename"], null, $this->index );
+		throw new Less_Exception_Compiler("variable " . $name . " is undefined in file ".$this->currentFileInfo["filename"], null, $this->index, $this->currentFileInfo);
 	}
 
 }
@@ -7974,7 +8003,7 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset{
 
 
 	// less.js : /lib/less/tree/mixin.js : tree.mixin.Definition
-	public function __construct($name, $params, $rules, $condition, $variadic = false, $frames = null ){
+	public function __construct($name, $params, $rules, $condition, $variadic = false, $frames = array() ){
 		$this->name = $name;
 		$this->selectors = array(new Less_Tree_Selector(array( new Less_Tree_Element(null, $name))));
 
@@ -8149,6 +8178,11 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset{
 			return true;
 		}
 
+		// set array to prevent error on array_merge
+		if(!is_array($this->frames)) {
+             $this->frames = array();
+        }
+
 		$frame = $this->compileParams($env, array_merge($this->frames,$env->frames), $args );
 
 		$compile_env = new Less_Environment();
@@ -8158,6 +8192,8 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset{
 				, $env->frames		// the current environment frames
 			);
 
+		$compile_env->functions = $env->functions;
+
 		return (bool)$this->condition->compile($compile_env);
 	}
 
@@ -9375,7 +9411,12 @@ class Less_Exception_Parser extends Exception{
 	 */
 	public function getLineNumber(){
 		if( $this->index ){
-			return substr_count($this->input, "\n", 0, $this->index) + 1;
+			// https://bugs.php.net/bug.php?id=49790
+			if (ini_get("mbstring.func_overload")) {
+				return substr_count(substr($this->input, 0, $this->index), "\n") + 1;
+			} else {
+				return substr_count($this->input, "\n", 0, $this->index) + 1;
+			}
 		}
 		return 1;
 	}

+ 1 - 1
plugins/lessphp/Version.php

@@ -8,7 +8,7 @@
  */
 class Less_Version{
 
-	const version = '1.7.0.2';			// The current build number of less.php
+	const version = '1.7.0.3';			// The current build number of less.php
 	const less_version = '1.7';			// The less.js version that this build should be compatible with
     const cache_version = '170';		// The parser cache version