]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blobdiff - vendor/oyejorge/less.php/lib/Less/Cache.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / vendor / oyejorge / less.php / lib / Less / Cache.php
diff --git a/vendor/oyejorge/less.php/lib/Less/Cache.php b/vendor/oyejorge/less.php/lib/Less/Cache.php
new file mode 100644 (file)
index 0000000..40d0358
--- /dev/null
@@ -0,0 +1,319 @@
+<?php
+
+require_once( dirname(__FILE__).'/Version.php');
+
+/**
+ * Utility for handling the generation and caching of css files
+ *
+ * @package Less
+ * @subpackage cache
+ *
+ */
+class Less_Cache{
+
+       // 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;
+
+
+       /**
+        * Save and reuse the results of compiled less files.
+        * The first call to Get() will generate css and save it.
+        * Subsequent calls to Get() with the same arguments will return the same css filename
+        *
+        * @param array $less_files Array of .less files to compile
+        * @param array $parser_options Array of compiler options
+        * @param array $modify_vars Array of variables
+        * @return string Name of the css file
+        */
+       public static function Get( $less_files, $parser_options = array(), $modify_vars = array() ){
+
+
+               //check $cache_dir
+               if( isset($parser_options['cache_dir']) ){
+                       Less_Cache::$cache_dir = $parser_options['cache_dir'];
+               }
+
+               if( empty(Less_Cache::$cache_dir) ){
+                       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;
+
+
+               //create a file for variables
+               if( !empty($modify_vars) ){
+                       $lessvars = Less_Parser::serializeVars($modify_vars);
+                       $vars_file = Less_Cache::$cache_dir . Less_Cache::$prefix_vars . sha1($lessvars) . '.less';
+
+                       if( !file_exists($vars_file) ){
+                               file_put_contents($vars_file, $lessvars);
+                       }
+
+                       $less_files += array($vars_file => '/');
+               }
+
+
+               // generate name for compiled css file
+               $hash = md5(json_encode($less_files));
+               $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) ){
+
+                               self::ListFiles($list_file, $list, $cached_name);
+                               $compiled_name = self::CompiledName($list, $hash);
+
+                               // if $cached_name is the same as the $compiled name, don't regenerate
+                               if( !$cached_name || $cached_name === $compiled_name ){
+
+                                       $output_file = self::OutputFile($compiled_name, $parser_options );
+
+                                       if( $output_file && file_exists($output_file) ){
+                                               @touch($list_file);
+                                               return basename($output_file); // for backwards compatibility, we just return the name of the file
+                                       }
+                               }
+                       }
+               }
+
+               $compiled = self::Cache( $less_files, $parser_options );
+               if( !$compiled ){
+                       return false;
+               }
+
+               $compiled_name = self::CompiledName( $less_files, $hash );
+               $output_file = self::OutputFile($compiled_name, $parser_options );
+
+
+               //save the file list
+               $list = $less_files;
+               $list[] = $compiled_name;
+               $cache = implode("\n",$list);
+               file_put_contents( $list_file, $cache );
+
+
+               //save the css
+               file_put_contents( $output_file, $compiled );
+
+
+               //clean up
+               self::CleanCache();
+
+               return basename($output_file);
+       }
+
+       /**
+        * Force the compiler to regenerate the cached css file
+        *
+        * @param array $less_files Array of .less files to compile
+        * @param array $parser_options Array of compiler options
+        * @param array $modify_vars Array of variables
+        * @return string Name of the css file
+        */
+       public static function Regen( $less_files, $parser_options = array(), $modify_vars = array() ){
+               $parser_options['use_cache'] = false;
+               return self::Get( $less_files, $parser_options, $modify_vars );
+       }
+
+       public static function Cache( &$less_files, $parser_options = array() ){
+
+
+               // get less.php if it exists
+               $file = dirname(__FILE__) . '/Less.php';
+               if( file_exists($file) && !class_exists('Less_Parser') ){
+                       require_once($file);
+               }
+
+               $parser_options['cache_dir'] = Less_Cache::$cache_dir;
+               $parser = new Less_Parser($parser_options);
+
+
+               // combine files
+               foreach($less_files as $file_path => $uri_or_less ){
+
+                       //treat as less markup if there are newline characters
+                       if( strpos($uri_or_less,"\n") !== false ){
+                               $parser->Parse( $uri_or_less );
+                               continue;
+                       }
+
+                       $parser->ParseFile( $file_path, $uri_or_less );
+               }
+
+               $compiled = $parser->getCss();
+
+
+               $less_files = $parser->allParsedFiles();
+
+               return $compiled;
+       }
+
+
+       private static function OutputFile( $compiled_name, $parser_options ){
+
+               //custom output file
+               if( !empty($parser_options['output']) ){
+
+                       //relative to cache directory?
+                       if( preg_match('#[\\\\/]#',$parser_options['output']) ){
+                               return $parser_options['output'];
+                       }
+
+                       return Less_Cache::$cache_dir.$parser_options['output'];
+               }
+
+               return Less_Cache::$cache_dir.$compiled_name;
+       }
+
+
+       private static function CompiledName( $files, $extrahash ){
+
+               //save the file list
+               $temp = array(Less_Version::cache_version);
+               foreach($files as $file){
+                       $temp[] = filemtime($file)."\t".filesize($file)."\t".$file;
+               }
+
+               return Less_Cache::$prefix.sha1(json_encode($temp).$extrahash).'.css';
+       }
+
+
+       public static function SetCacheDir( $dir ){
+               Less_Cache::$cache_dir = $dir;
+               self::CheckCacheDir();
+       }
+
+       public static function CheckCacheDir(){
+
+               Less_Cache::$cache_dir = str_replace('\\','/',Less_Cache::$cache_dir);
+               Less_Cache::$cache_dir = rtrim(Less_Cache::$cache_dir,'/').'/';
+
+               if( !file_exists(Less_Cache::$cache_dir) ){
+                       if( !mkdir(Less_Cache::$cache_dir) ){
+                               throw new Less_Exception_Parser('Less.php cache directory couldn\'t be created: '.Less_Cache::$cache_dir);
+                       }
+
+               }elseif( !is_dir(Less_Cache::$cache_dir) ){
+                       throw new Less_Exception_Parser('Less.php cache directory doesn\'t exist: '.Less_Cache::$cache_dir);
+
+               }elseif( !is_writable(Less_Cache::$cache_dir) ){
+                       throw new Less_Exception_Parser('Less.php cache directory isn\'t writable: '.Less_Cache::$cache_dir);
+
+               }
+
+       }
+
+
+       /**
+        * Delete unused less.php files
+        *
+        */
+       public static function CleanCache(){
+               static $clean = false;
+
+
+               if( $clean || empty(Less_Cache::$cache_dir) ){
+                       return;
+               }
+
+               $clean = true;
+
+               // only remove files with extensions created by less.php
+               // css files removed based on the list files
+               $remove_types = array('lesscache'=>1,'list'=>1,'less'=>1,'map'=>1);
+
+               $files = scandir(Less_Cache::$cache_dir);
+               if( !$files ){
+                       return;
+               }
+
+               $check_time = time() - self::$gc_lifetime;
+               foreach($files as $file){
+
+
+                       // don't delete if the file wasn't created with less.php
+                       if( strpos($file,Less_Cache::$prefix) !== 0 ){
+                               continue;
+                       }
+
+                       $parts = explode('.',$file);
+                       $type = array_pop($parts);
+
+
+                       if( !isset($remove_types[$type]) ){
+                               continue;
+                       }
+
+                       $full_path = Less_Cache::$cache_dir . $file;
+                       $mtime = filemtime($full_path);
+
+                       // don't delete if it's a relatively new file
+                       if( $mtime > $check_time ){
+                               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);
+               }
+
+
+       }
+
+
+       /**
+        * 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;
+               }
+
+       }
+
+}