[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 3 require_once( dirname(__FILE__).'/Version.php'); 4 5 /** 6 * Utility for handling the generation and caching of css files 7 * 8 * @package Less 9 * @subpackage cache 10 * 11 */ 12 class Less_Cache{ 13 14 // directory less.php can use for storing data 15 public static $cache_dir = false; 16 17 // prefix for the storing data 18 public static $prefix = 'lessphp_'; 19 20 // prefix for the storing vars 21 public static $prefix_vars = 'lessphpvars_'; 22 23 // specifies the number of seconds after which data created by less.php will be seen as 'garbage' and potentially cleaned up 24 public static $gc_lifetime = 604800; 25 26 27 /** 28 * Save and reuse the results of compiled less files. 29 * The first call to Get() will generate css and save it. 30 * Subsequent calls to Get() with the same arguments will return the same css filename 31 * 32 * @param array $less_files Array of .less files to compile 33 * @param array $parser_options Array of compiler options 34 * @param array $modify_vars Array of variables 35 * @return string Name of the css file 36 */ 37 public static function Get( $less_files, $parser_options = array(), $modify_vars = array() ){ 38 39 40 //check $cache_dir 41 if( isset($parser_options['cache_dir']) ){ 42 Less_Cache::$cache_dir = $parser_options['cache_dir']; 43 } 44 45 if( empty(Less_Cache::$cache_dir) ){ 46 throw new Exception('cache_dir not set'); 47 } 48 49 if( isset($parser_options['prefix']) ){ 50 Less_Cache::$prefix = $parser_options['prefix']; 51 } 52 53 if( empty(Less_Cache::$prefix) ){ 54 throw new Exception('prefix not set'); 55 } 56 57 if( isset($parser_options['prefix_vars']) ){ 58 Less_Cache::$prefix_vars = $parser_options['prefix_vars']; 59 } 60 61 if( empty(Less_Cache::$prefix_vars) ){ 62 throw new Exception('prefix_vars not set'); 63 } 64 65 self::CheckCacheDir(); 66 $less_files = (array)$less_files; 67 68 69 //create a file for variables 70 if( !empty($modify_vars) ){ 71 $lessvars = Less_Parser::serializeVars($modify_vars); 72 $vars_file = Less_Cache::$cache_dir . Less_Cache::$prefix_vars . sha1($lessvars) . '.less'; 73 74 if( !file_exists($vars_file) ){ 75 file_put_contents($vars_file, $lessvars); 76 } 77 78 $less_files += array($vars_file => '/'); 79 } 80 81 82 // generate name for compiled css file 83 $hash = md5(json_encode($less_files)); 84 $list_file = Less_Cache::$cache_dir . Less_Cache::$prefix . $hash . '.list'; 85 86 // check cached content 87 if( !isset($parser_options['use_cache']) || $parser_options['use_cache'] === true ){ 88 if( file_exists($list_file) ){ 89 90 self::ListFiles($list_file, $list, $cached_name); 91 $compiled_name = self::CompiledName($list, $hash); 92 93 // if $cached_name is the same as the $compiled name, don't regenerate 94 if( !$cached_name || $cached_name === $compiled_name ){ 95 96 $output_file = self::OutputFile($compiled_name, $parser_options ); 97 98 if( $output_file && file_exists($output_file) ){ 99 @touch($list_file); 100 return basename($output_file); // for backwards compatibility, we just return the name of the file 101 } 102 } 103 } 104 } 105 106 $compiled = self::Cache( $less_files, $parser_options ); 107 if( !$compiled ){ 108 return false; 109 } 110 111 $compiled_name = self::CompiledName( $less_files, $hash ); 112 $output_file = self::OutputFile($compiled_name, $parser_options ); 113 114 115 //save the file list 116 $list = $less_files; 117 $list[] = $compiled_name; 118 $cache = implode("\n",$list); 119 file_put_contents( $list_file, $cache ); 120 121 122 //save the css 123 file_put_contents( $output_file, $compiled ); 124 125 126 //clean up 127 self::CleanCache(); 128 129 return basename($output_file); 130 } 131 132 /** 133 * Force the compiler to regenerate the cached css file 134 * 135 * @param array $less_files Array of .less files to compile 136 * @param array $parser_options Array of compiler options 137 * @param array $modify_vars Array of variables 138 * @return string Name of the css file 139 */ 140 public static function Regen( $less_files, $parser_options = array(), $modify_vars = array() ){ 141 $parser_options['use_cache'] = false; 142 return self::Get( $less_files, $parser_options, $modify_vars ); 143 } 144 145 public static function Cache( &$less_files, $parser_options = array() ){ 146 147 148 // get less.php if it exists 149 $file = dirname(__FILE__) . '/Less.php'; 150 if( file_exists($file) && !class_exists('Less_Parser') ){ 151 require_once($file); 152 } 153 154 $parser_options['cache_dir'] = Less_Cache::$cache_dir; 155 $parser = new Less_Parser($parser_options); 156 157 158 // combine files 159 foreach($less_files as $file_path => $uri_or_less ){ 160 161 //treat as less markup if there are newline characters 162 if( strpos($uri_or_less,"\n") !== false ){ 163 $parser->Parse( $uri_or_less ); 164 continue; 165 } 166 167 $parser->ParseFile( $file_path, $uri_or_less ); 168 } 169 170 $compiled = $parser->getCss(); 171 172 173 $less_files = $parser->allParsedFiles(); 174 175 return $compiled; 176 } 177 178 179 private static function OutputFile( $compiled_name, $parser_options ){ 180 181 //custom output file 182 if( !empty($parser_options['output']) ){ 183 184 //relative to cache directory? 185 if( preg_match('#[\\\\/]#',$parser_options['output']) ){ 186 return $parser_options['output']; 187 } 188 189 return Less_Cache::$cache_dir.$parser_options['output']; 190 } 191 192 return Less_Cache::$cache_dir.$compiled_name; 193 } 194 195 196 private static function CompiledName( $files, $extrahash ){ 197 198 //save the file list 199 $temp = array(Less_Version::cache_version); 200 foreach($files as $file){ 201 $temp[] = filemtime($file)."\t".filesize($file)."\t".$file; 202 } 203 204 return Less_Cache::$prefix.sha1(json_encode($temp).$extrahash).'.css'; 205 } 206 207 208 public static function SetCacheDir( $dir ){ 209 Less_Cache::$cache_dir = $dir; 210 } 211 212 public static function CheckCacheDir(){ 213 214 Less_Cache::$cache_dir = str_replace('\\','/',Less_Cache::$cache_dir); 215 Less_Cache::$cache_dir = rtrim(Less_Cache::$cache_dir,'/').'/'; 216 217 if( !file_exists(Less_Cache::$cache_dir) ){ 218 if( !mkdir(Less_Cache::$cache_dir) ){ 219 throw new Less_Exception_Parser('Less.php cache directory couldn\'t be created: '.Less_Cache::$cache_dir); 220 } 221 222 }elseif( !is_dir(Less_Cache::$cache_dir) ){ 223 throw new Less_Exception_Parser('Less.php cache directory doesn\'t exist: '.Less_Cache::$cache_dir); 224 225 }elseif( !is_writable(Less_Cache::$cache_dir) ){ 226 throw new Less_Exception_Parser('Less.php cache directory isn\'t writable: '.Less_Cache::$cache_dir); 227 228 } 229 230 } 231 232 233 /** 234 * Delete unused less.php files 235 * 236 */ 237 public static function CleanCache(){ 238 static $clean = false; 239 240 if( $clean ){ 241 return; 242 } 243 244 $files = scandir(Less_Cache::$cache_dir); 245 if( $files ){ 246 $check_time = time() - self::$gc_lifetime; 247 foreach($files as $file){ 248 249 // don't delete if the file wasn't created with less.php 250 if( strpos($file,Less_Cache::$prefix) !== 0 ){ 251 continue; 252 } 253 254 $full_path = Less_Cache::$cache_dir . $file; 255 256 // make sure the file still exists 257 // css files may have already been deleted 258 if( !file_exists($full_path) ){ 259 continue; 260 } 261 $mtime = filemtime($full_path); 262 263 // don't delete if it's a relatively new file 264 if( $mtime > $check_time ){ 265 continue; 266 } 267 268 $parts = explode('.',$file); 269 $type = array_pop($parts); 270 271 272 // delete css files based on the list files 273 if( $type === 'css' ){ 274 continue; 275 } 276 277 278 // delete the list file and associated css file 279 if( $type === 'list' ){ 280 self::ListFiles($full_path, $list, $css_file_name); 281 if( $css_file_name ){ 282 $css_file = Less_Cache::$cache_dir . $css_file_name; 283 if( file_exists($css_file) ){ 284 unlink($css_file); 285 } 286 } 287 } 288 289 unlink($full_path); 290 } 291 } 292 293 $clean = true; 294 } 295 296 297 /** 298 * Get the list of less files and generated css file from a list file 299 * 300 */ 301 static function ListFiles($list_file, &$list, &$css_file_name ){ 302 303 $list = explode("\n",file_get_contents($list_file)); 304 305 //pop the cached name that should match $compiled_name 306 $css_file_name = array_pop($list); 307 308 if( !preg_match('/^' . Less_Cache::$prefix . '[a-f0-9]+\.css$/',$css_file_name) ){ 309 $list[] = $css_file_name; 310 $css_file_name = false; 311 } 312 313 } 314 315 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |