Merge branch 'MDL-35155-27' of git://github.com/danpoltawski/moodle into MOODLE_27_STABLE
[moodle.git] / lib / lessphp / Cache.php
blob7556e0a295042dbc858f9b768967daeb9b58dceb
1 <?php
3 require_once( dirname(__FILE__).'/Version.php');
5 /**
6 * Utility for handling the generation and caching of css files
8 * @package Less
9 * @subpackage cache
12 class Less_Cache{
14 public static $cache_dir = false; // directory less.php can use for storing data
17 /**
18 * Save and reuse the results of compiled less files.
19 * The first call to Get() will generate css and save it.
20 * Subsequent calls to Get() with the same arguments will return the same css filename
22 * @param array $less_files Array of .less files to compile
23 * @param array $parser_options Array of compiler options
24 * @param boolean $use_cache Set to false to regenerate the css file
25 * @return string Name of the css file
27 public static function Get( $less_files, $parser_options = array(), $use_cache = true ){
30 //check $cache_dir
31 if( isset($parser_options['cache_dir']) ){
32 Less_Cache::$cache_dir = $parser_options['cache_dir'];
35 if( empty(Less_Cache::$cache_dir) ){
36 throw new Exception('cache_dir not set');
39 self::CheckCacheDir();
41 // generate name for compiled css file
42 $less_files = (array)$less_files;
43 $hash = md5(json_encode($less_files));
44 $list_file = Less_Cache::$cache_dir.'lessphp_'.$hash.'.list';
47 // check cached content
48 if( $use_cache === true && file_exists($list_file) ){
50 $list = explode("\n",file_get_contents($list_file));
52 //pop the cached name that should match $compiled_name
53 $cached_name = array_pop($list);
54 if( !preg_match('/^lessphp_[a-f0-9]+\.css$/',$cached_name) ){
55 $list[] = $cached_name;
56 $cached_name = false;
58 $compiled_name = self::CompiledName($list);
60 // if $cached_name != $compiled_name, we know we need to recompile
61 if( !$cached_name || $cached_name === $compiled_name ){
63 $output_file = self::OutputFile($compiled_name, $parser_options );
65 if( $output_file && file_exists($output_file) ){
66 @touch($list_file);
67 @touch($output_file);
68 return basename($output_file); // for backwards compatibility, we just return the name of the file
74 $compiled = self::Cache( $less_files, $parser_options );
75 if( !$compiled ){
76 return false;
79 $compiled_name = self::CompiledName( $less_files );
80 $output_file = self::OutputFile($compiled_name, $parser_options );
83 //save the file list
84 $list = $less_files;
85 $list[] = $compiled_name;
86 $cache = implode("\n",$list);
87 file_put_contents( $list_file, $cache );
90 //save the css
91 file_put_contents( $output_file, $compiled );
94 //clean up
95 self::CleanCache();
97 return basename($output_file);
101 * Force the compiler to regenerate the cached css file
103 * @param array $less_files Array of .less files to compile
104 * @param array $parser_options Array of compiler options
105 * @return string Name of the css file
107 public static function Regen( $less_files, $parser_options = array() ){
108 return self::Get( $less_files, $parser_options, false );
111 public static function Cache( &$less_files, $parser_options = array() ){
114 // get less.php if it exists
115 $file = dirname(__FILE__) . '/Less.php';
116 if( file_exists($file) && !class_exists('Less_Parser') ){
117 require_once($file);
120 $parser_options['cache_dir'] = Less_Cache::$cache_dir;
121 $parser = new Less_Parser($parser_options);
124 // combine files
125 foreach($less_files as $file_path => $uri_or_less ){
127 //treat as less markup if there are newline characters
128 if( strpos($uri_or_less,"\n") !== false ){
129 $parser->Parse( $uri_or_less );
130 continue;
133 $parser->ParseFile( $file_path, $uri_or_less );
136 $compiled = $parser->getCss();
139 $less_files = $parser->allParsedFiles();
141 return $compiled;
145 private static function OutputFile( $compiled_name, $parser_options ){
147 //custom output file
148 if( !empty($parser_options['output']) ){
150 //relative to cache directory?
151 if( preg_match('#[\\\\/]#',$parser_options['output']) ){
152 return $parser_options['output'];
155 return Less_Cache::$cache_dir.$parser_options['output'];
158 return Less_Cache::$cache_dir.$compiled_name;
162 private static function CompiledName( $files ){
164 //save the file list
165 $temp = array(Less_Version::cache_version);
166 foreach($files as $file){
167 $temp[] = filemtime($file)."\t".filesize($file)."\t".$file;
170 return 'lessphp_'.sha1(json_encode($temp)).'.css';
174 public static function SetCacheDir( $dir ){
175 Less_Cache::$cache_dir = $dir;
178 public static function CheckCacheDir(){
180 Less_Cache::$cache_dir = str_replace('\\','/',Less_Cache::$cache_dir);
181 Less_Cache::$cache_dir = rtrim(Less_Cache::$cache_dir,'/').'/';
183 if( !file_exists(Less_Cache::$cache_dir) ){
184 if( !mkdir(Less_Cache::$cache_dir) ){
185 throw new Less_Exception_Parser('Less.php cache directory couldn\'t be created: '.Less_Cache::$cache_dir);
188 }elseif( !is_dir(Less_Cache::$cache_dir) ){
189 throw new Less_Exception_Parser('Less.php cache directory doesn\'t exist: '.Less_Cache::$cache_dir);
191 }elseif( !is_writable(Less_Cache::$cache_dir) ){
192 throw new Less_Exception_Parser('Less.php cache directory isn\'t writable: '.Less_Cache::$cache_dir);
199 public static function CleanCache(){
200 static $clean = false;
202 if( $clean ){
203 return;
206 $files = scandir(Less_Cache::$cache_dir);
207 if( $files ){
208 $check_time = time() - 604800;
209 foreach($files as $file){
210 if( strpos($file,'lessphp_') !== 0 ){
211 continue;
213 $full_path = Less_Cache::$cache_dir.'/'.$file;
214 if( filemtime($full_path) > $check_time ){
215 continue;
217 unlink($full_path);
221 $clean = true;