Seditio Source
Root |
./othercms/PHPFusion 9.10.20/includes/classes/PHPFusion/Atom/lib/Less/Cache.php
<?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;
        }

    }

}