website_jukni/pastebin/application/libraries/Carabiner.php

1120 lines
33 KiB
PHP
Raw Normal View History

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
// -------------------------------------------------------------------------------------------------
/**
* Carabiner
* Asset Management Library
*
* Carabiner manages javascript and CSS assets. It will react differently depending on whether
* it is in a production or development environment. In a production environment, it will combine,
* minify, and cache assets. (As files are changed, new cache files will be generated.) In a
* development environment, it will simply include references to the original assets.
*
* Carabiner requires the JSMin {@link http://codeigniter.com/forums/viewthread/103039/ released here}
* and CSSMin {@link http://codeigniter.com/forums/viewthread/103269/ released here} libraries included.
* You don't need to load them unless you'll be using them elsewhise. Carabiner will load them
* automatically as needed.
*
* Notes: Carabiner does not implement GZIP encoding, because I think that the web server should
* handle that. If you need GZIP in an Asset Library, AssetLibPro {@link http://code.google.com/p/assetlib-pro/}
* does it. I've also chosen not to implement any kind of javascript obfuscation (like packer),
* because of the client-side decompression overhead. More about this idea from {@link http://ejohn.org/blog/library-loading-speed/ John Resig}.
* However, that's not to say you can't do it. You can easily provide a production version of a script
* that is packed. However, note that combining a packed script with minified scripts could cause
* problems. In that case, you can flag it to be not combined.
*
* Carabiner is inspired by Minify {@link http://code.google.com/p/minify/ by Steve Clay}, PHP
* Combine {@link http://rakaz.nl/extra/code/combine/ by Niels Leenheer} and AssetLibPro
* {@link http://code.google.com/p/assetlib-pro/ by Vincent Esche}, among other things.
*
* @package CodeIgniter
* @subpackage Libraries
* @category Asset Management
* @author Tony Dewan <tonydewan.com/contact>
* @version 1.45
* @license http://www.opensource.org/licenses/bsd-license.php BSD licensed.
*
* @todo fix new bugs. Duh.
* @todo check for 'absolute' path in asset references
*/
/*
===============================================================================================
USAGE
===============================================================================================
Load the library as normal:
-----------------------------------------------------------------------------------------------
$this->load->library('carabiner');
-----------------------------------------------------------------------------------------------
Configuration can happen in either a config file (included), or by passing an array of values
to the config() method. Config options passed to the config() method will override options in
the config file.
See the included config file for more info.
To configure Carabiner using the config() method, do this:
-----------------------------------------------------------------------------------------------
$carabiner_config = array(
'script_dir' => 'assets/scripts/',
'style_dir' => 'assets/styles/',
'cache_dir' => 'assets/cache/',
'base_uri' => base_url(),
'combine' => TRUE,
'dev' => FALSE,
'minify_js' => TRUE,
'minify_css' => TRUE
);
$this->carabiner->config($carabiner_config);
-----------------------------------------------------------------------------------------------
There are 9 options. 3 are required:
script_dir
STRING Path to the script directory. Relative to the CI front controller (index.php)
style_dir
STRING Path to the style directory. Relative to the CI front controller (index.php)
cache_dir
STRING Path to the cache directory. Must be writable. Relative to the CI front controller (index.php)
6 are not required:
base_uri
STRING Base uri of the site, like http://www.example.com/ Defaults to the CI config value for
base_url.
dev
BOOL Flags whether your in a development environment or not. See above for what this means.
Defaults to FALSE.
combine
BOOLEAN Flags whether to combine files. Defaults to TRUE.
minify_js
BOOLEAN Flags whether to minify javascript. Defaults to TRUE.
minify_css
BOOLEAN Flags whether to minify CSS. Defaults to TRUE.
force_curl
BOOLEAN Flags whether cURL should always be used for URL file references. Defaults to FALSE.
Add assets like so:
-----------------------------------------------------------------------------------------------
// add a js file
$this->carabiner->js('scripts.js');
// add a css file
$this->carabiner->css('reset.css');
// add a css file with a mediatype
$this->carabiner->css('admin/print.css','print');
-----------------------------------------------------------------------------------------------
To set a (prebuilt) production version of an asset:
-----------------------------------------------------------------------------------------------
// JS: pass a second string to the method with a path to the production version
$this->carabiner->js('wymeditor/wymeditor.js', 'wymeditor/wymeditor.pack.js' );
// add a css file with prebuilt production version
$this->carabiner->css('framework/type.css', 'screen', 'framework/type.pack.css');
-----------------------------------------------------------------------------------------------
And to prevent an individual asset file from being combined:
-----------------------------------------------------------------------------------------------
// JS: pass a boolean FALSE as the third attribute of the method
$this->carabiner->js('wymeditor/wymeditor.js', 'wymeditor.pack.js', FALSE );
// CSS: pass a boolean FALSE as the fourth attribute of the method
$this->carabiner->css('framework/type.css', 'screen', 'framework/type.pack.css', FALSE);
-----------------------------------------------------------------------------------------------
You can also pass arrays (and arrays of arrays) to these methods. Like so:
-----------------------------------------------------------------------------------------------
// a single array (this is redundant, but supported anyway)
$this->carabiner->css( array('mobile.css', 'handheld', 'mobile.prod.css') );
// an array of arrays
$js_assets = array(
array('dev/jquery.js', 'prod/jquery.js'),
array('dev/jquery.ext.js', 'prod/jquery.ext.js'),
)
$this->carabiner->js( $js_assets );
-----------------------------------------------------------------------------------------------
Carabiner is smart enough to recognize URLs and treat them differently:
-----------------------------------------------------------------------------------------------
$this->carabiner->js('http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js');
-----------------------------------------------------------------------------------------------
You can also define groups of assets
-----------------------------------------------------------------------------------------------
// Define JS
$js = array(
array('prototype.js'),
array('scriptaculous.js')
);
// create group
$this->carabiner->group('prototaculous', array('js'=>$js) );
// an IE only group
$css = array('iefix.css');
$js = array('iefix.js');
$this->carabiner->group('iefix', array('js'=>$js, 'css'=>$js) );
// you can even assign an asset to a group individually
// by passing the group name to the last parameter of the css/js functions
$this->carabiner->css('spec.css', 'screen', 'spec-min.css', TRUE, FALSE, 'spec');
-----------------------------------------------------------------------------------------------
To output your assets, including appropriate markup:
-----------------------------------------------------------------------------------------------
// display css
$this->carabiner->display('css');
//display js
$this->carabiner->display('js');
// display both
$this->carabiner->display(); // OR $this->carabiner->display('both');
// display group
$this->carabiner->display('jquery'); // group name defined as jquery
// display filterd group
$this->carabiner->display('main', 'js'); // group name defined as main, only display JS
// return string of asset references
$string = $this->carabiner->display_string('main');
-----------------------------------------------------------------------------------------------
Note that the standard display function calls (the first 3 listed above) will only output
those assets not associated with a group (which are all included in the 'main' group). Groups
must be explicitly displayed via the 4th call listed above.
Since Carabiner won't delete old cached files, you'll need to clear them out manually.
To do so programatically:
-----------------------------------------------------------------------------------------------
// clear css cache
$this->carabiner->empty_cache('css');
//clear js cache
$this->carabiner->empty_cache('js');
// clear both
$this->carabiner->empty_cache(); // OR $this->carabiner->empty_cache('both');
// clear before a certain date
$this->carabiner->empty_cache('both', 'now'); // String denoting a time before which cache
// files will be removed. Any string that
// strtotime() can take is acceptable.
// Defaults to 'now'.
-----------------------------------------------------------------------------------------------
===============================================================================================
*/
class Carabiner {
public $base_uri = '';
public $script_dir = '';
public $script_path = '';
public $script_uri = '';
public $style_dir = '';
public $style_path = '';
public $style_uri = '';
public $cache_dir = '';
public $cache_path = '';
public $cache_uri = '';
public $dev = FALSE;
public $combine = TRUE;
public $minify_js = TRUE;
public $minify_css = TRUE;
public $force_curl = FALSE;
private $js = array('main'=>array());
private $css = array('main'=>array());
private $loaded = array();
private $CI;
/**
* Class Constructor
*/
public function __construct()
{
$this->CI =& get_instance();
log_message('debug', 'Carabiner: Library initialized.');
if( $this->CI->config->load('carabiner', TRUE, TRUE) ){
log_message('debug', 'Carabiner: config loaded from config file.');
$carabiner_config = $this->CI->config->item('carabiner');
$this->config($carabiner_config);
}
}
/**
* Load Config
* @access public
* @param Array of config variables. Requires script_dir(string), style_dir(string), and cache_dir(string).
* base_uri(string), dev(bool), combine(bool), minify_js(bool), minify_css(bool), and force_curl(bool) are optional.
* @return Void
*/
public function config($config)
{
foreach ($config as $key => $value)
{
if($key == 'groups') {
foreach($value as $group_name => $assets){
$this->group($group_name, $assets);
}
break;
}
$this->$key = $value;
}
// set the default value for base_uri from the config
if($this->base_uri == '') $this->base_uri = $this->CI->config->item('base_url');
// use the provided values to define the rest of them
$this->script_path = FCPATH.$this->script_dir;
$this->script_uri = $this->base_uri.$this->script_dir;
$this->style_path = FCPATH.$this->style_dir;
$this->style_uri = $this->base_uri.$this->style_dir;
$this->cache_path = FCPATH.$this->cache_dir;
$this->cache_uri = $this->base_uri.$this->cache_dir;
log_message('debug', 'Carabiner: library configured.');
}
/**
* Add JS file to queue
* @access public
* @param String of the path to development version of the JS file. Could also be an array, or array of arrays.
* @param String of the path to production version of the JS file. NOT REQUIRED
* @param Boolean flag whether the file is to be combined. NOT REQUIRED
* @param String of the group name with which the asset is to be associated. NOT REQUIRED
* @return Void
*/
public function js($dev_file, $prod_file = '', $combine = TRUE, $minify = TRUE, $group = 'main')
{
if( is_array($dev_file) ){
if( is_array($dev_file[0]) ){
foreach($dev_file as $file){
$d = $file[0];
$p = (isset($file[1])) ? $file[1] : '';
$c = (isset($file[2])) ? $file[2] : $combine;
$m = (isset($file[3])) ? $file[3] : $minify;
$g = (isset($file[4])) ? $file[4] : $group;
$this->_asset('js', $d, $p, $c, $m, NULL, $g);
}
}else{
$d = $dev_file[0];
$p = (isset($dev_file[1])) ? $dev_file[1] : '';
$c = (isset($dev_file[2])) ? $dev_file[2] : $combine;
$m = (isset($dev_file[3])) ? $dev_file[3] : $minify;
$g = (isset($dev_file[4])) ? $dev_file[4] : $group;
$this->_asset('js', $d, $p, $c, $m, NULL, $g);
}
}else{
$this->_asset('js', $dev_file, $prod_file, $combine, $minify, NULL, $group);
}
}
/**
* Add CSS file to queue
* @access public
* @param String of the path to development version of the CSS file. Could also be an array, or array of arrays.
* @param String of the media type, usually one of (screen, print, handheld) for css. Defaults to screen.
* @param String of the path to production version of the CSS file. NOT REQUIRED
* @param Boolean flag whether the file is to be combined. NOT REQUIRED
* @param Boolean flag whether the file is to be minified. NOT REQUIRED
* @param String of the group name with which the asset is to be associated. NOT REQUIRED
* @return Void
*/
public function css($dev_file, $media = 'screen', $prod_file = '', $combine = TRUE, $minify = TRUE, $group = 'main')
{
if( is_array($dev_file) ){
if( is_array($dev_file[0]) ){
foreach($dev_file as $file){
$d = $file[0];
$m = (isset($file[1])) ? $file[1] : $media;
$p = (isset($file[2])) ? $file[2] : '';
$c = (isset($file[3])) ? $file[3] : $combine;
$y = (isset($file[4])) ? $file[4] : $minify;
$g = (isset($file[5])) ? $file[5] : $group;
$this->_asset('css', $d, $p, $c, $y, $m, $g);
}
}else{
$d = $dev_file[0];
$m = (isset($dev_file[1])) ? $dev_file[1] : $media;
$p = (isset($dev_file[2])) ? $dev_file[2] : '';
$c = (isset($dev_file[3])) ? $dev_file[3] : $combine;
$y = (isset($dev_file[4])) ? $dev_file[4] : $minify;
$g = (isset($dev_file[5])) ? $dev_file[5] : $group;
$this->_asset('css', $d, $p, $c, $y, $m, $g);
}
}else{
$this->_asset('css', $dev_file, $prod_file, $combine, $minify, $media, $group);
}
}
/**
* Add Assets to a group
* @access public
* @param String of the name of the group. should not contain spaces or punctuation
* @param array of assets to be included in the group
* @return Void
*/
public function group($group_name, $assets)
{
if(!isset($assets['js']) && !isset($assets['css']) ){
log_message('error', "Carabiner: The asset group definition named '{$group_name}' does not contain a well formed array.");
return;
}
if( isset($assets['js']) )
$this->js($assets['js'], '', TRUE, TRUE, $group_name);
if( isset($assets['css']) )
$this->css($assets['css'], 'screen', '', TRUE, TRUE, $group_name);
}
/**
* Add an asset to queue
* @access private
* @param String of the type of asset (lowercase). css | js
* @param String of the path to development version of the asset.
* @param String of the path to production version of the asset. NOT REQUIRED
* @param Boolean flag whether the file is to be combined. Defaults to true. NOT REQUIRED
* @param Boolean flag whether the file is to be minified. Defaults to true. NOT REQUIRED
* @param String of the media type associated with the asset. Only applicable to CSS assets. NOT REQUIRED
* @param String of the group name with which the asset is to be associated. NOT REQUIRED
* @return Void
*/
private function _asset($type, $dev_file, $prod_file = '', $combine, $minify, $media = 'screen', $group = 'main')
{
if ($type == 'css') :
$this->css[$group][$media][] = array( 'dev'=>$dev_file );
$index = count($this->css[$group][$media]) - 1;
if($prod_file != '') $this->css[$group][$media][$index]['prod'] = $prod_file;
$this->css[$group][$media][$index]['combine'] = $combine;
$this->css[$group][$media][$index]['minify'] = $minify;
else :
$this->js[$group][] = array( 'dev'=>$dev_file );
$index = count($this->js[$group]) - 1;
if($prod_file != '') $this->js[$group][$index]['prod'] = $prod_file;
$this->js[$group][$index]['combine'] = $combine;
$this->js[$group][$index]['minify'] = $minify;
endif;
}
/**
* Display HTML references to the assets
* @access public
* @param String flag the asset type: css || js || both, OR the group name
* @param String flag the asset type to filter a group (e.g. only show 'js' for this group)
* @return Void
*/
public function display($flag = 'both', $group_filter = NULL)
{
switch($flag){
case 'JS':
case 'js':
$this->_display_js();
break;
case 'CSS':
case 'css':
$this->_display_css();
break;
case 'both':
$this->_display_js();
$this->_display_css();
break;
default:
if( isset($this->js[$flag]) && ($group_filter == NULL || $group_filter == 'js') )
$this->_display_js($flag);
if( isset($this->css[$flag]) && ($group_filter == NULL || $group_filter == 'css') )
$this->_display_css($flag);
break;
}
}
/**
* HTML references to the assets, returned as a string
* @access public
* @param String flag the asset type: css || js || both, OR the group name
* @return String of HTML references
*/
public function display_string($flag='both', $group_filter = NULL)
{
ob_start(); // note: according to the manual, nesting ob calls is okay
// so this shouldn't cause any problems even if you're using ob already
$this->display($flag, $group_filter);
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
/**
* Display HTML references to the js assets
* @access private
* @param String of the asset group name
* @return Void
*/
private function _display_js($group = 'main')
{
if( empty($this->js) ) return; // if there aren't any js files, just stop!
if( !isset($this->js[$group]) ): // the group you asked for doesn't exist. This should never happen, but better to be safe than sorry.
log_message('error', "Carabiner: The JavaScript asset group named '{$group}' does not exist.");
return;
endif;
// if we're in a dev environment
if($this->dev){
foreach($this->js[$group] as $ref):
echo $this->_tag('js', $ref['dev']);
endforeach;
// if we're combining files and minifying them
} elseif($this->combine && $this->minify_js) {
$lastmodified = 0;
$files = array();
$filenames = '';
foreach($this->js[$group] as $ref):
// get the last modified date of the most recently modified file
$lastmodified = max( $lastmodified , filemtime(realpath($this->script_path.$ref['dev'])) );
$filenames .= $ref['dev'];
if(!$ref['combine']):
echo (isset($ref['prod'])) ? $this->_tag('js', $ref['prod']) : $this->_tag('js', $ref['dev']);
elseif(!$ref['minify']):
$files[] = (isset($ref['prod'])) ? array('prod'=>$ref['prod'], 'dev'=>$ref['dev'], 'minify'=>$ref['minify'] ) : array('dev'=>$ref['dev'], 'minify'=>$ref['minify']);
else:
$files[] = (isset($ref['prod'])) ? array('prod'=>$ref['prod'], 'dev'=>$ref['dev'] ) : array('dev'=>$ref['dev']);
endif;
endforeach;
$lastmodified = ($lastmodified == 0) ? '0000000000' : $lastmodified;
$filename = $lastmodified . md5($filenames).'.js';
if( !file_exists($this->cache_path.$filename) ) $this->_combine('js', $files, $filename);
echo $this->_tag('js', $filename, TRUE);
// if we're combining files but not minifying
} elseif($this->combine && !$this->minify_js) {
$lastmodified = 0;
$files = array();
$filenames = '';
foreach($this->js[$group] as $ref):
// get the last modified date of the most recently modified file
$lastmodified = max( $lastmodified , filemtime(realpath($this->script_path.$ref['dev'])) );
$filenames .= $ref['dev'];
if(!$ref['combine']):
echo (isset($ref['prod'])) ? $this->_tag('js', $ref['prod']) : $this->_tag('js', $ref['dev']);
else:
$files[] = (isset($ref['prod'])) ? array('prod'=>$ref['prod'], 'dev'=>$ref['dev'], 'minify'=> FALSE ) : array('dev'=>$ref['dev'], 'minify'=> FALSE);
endif;
endforeach;
$lastmodified = ($lastmodified == 0) ? '0000000000' : $lastmodified;
$filename = $lastmodified . md5($filenames).'.js';
if( !file_exists($this->cache_path.$filename) ) $this->_combine('js', $files, $filename);
echo $this->_tag('js', $filename, TRUE);
// if we're minifying. but not combining
} elseif(!$this->combine && $this->minify_js) {
foreach($this->js[$group] as $ref):
if( isset( $ref['prod']) ){
$f = $ref['prod'];
} elseif( !$ref['minify'] ){
$f = $ref['dev'];
} else {
$f = filemtime( realpath( $this->script_path . $ref['dev'] ) ) . md5($ref['dev']) . '.js';
if( !file_exists($this->cache_path.$f) ):
$c = $this->_minify( 'js', $ref['dev'] );
$this->_cache($f, $c);
endif;
}
echo $this->_tag('js', $f, TRUE);
endforeach;
// we're not in dev mode, but combining isn't okay and minifying isn't allowed.
// -- this will just display the production version if there is one, dev if there isn't.
}else{
foreach($this->js[$group] as $ref):
$f = (isset($ref['prod'])) ? $ref['prod'] : $ref['dev'];
echo $this->_tag('js', $f);
endforeach;
}
}
/**
* Display HTML references to the css assets
* @access private
* @param String of the asset group name
* @return Void
*/
private function _display_css($group = 'main')
{
if( empty($this->css) ) return; // there aren't any css assets, so just stop!
if( !isset($this->css[$group]) ): // the group you asked for doesn't exist. This should never happen, but better to be safe than sorry.
log_message('error', "Carabiner: The CSS asset group named '{$group}' does not exist.");
return;
endif;
if($this->dev){ // we're in a development environment
foreach($this->css[$group] as $media => $refs):
foreach($refs as $ref):
echo $this->_tag('css', $ref['dev'], FALSE, $media);
endforeach;
endforeach;
} elseif($this->combine && $this->minify_css) { // we're combining and minifying
foreach($this->css[$group] as $media => $refs):
// lets try to cache it, shall we?
$lastmodified = 0;
$files = array();
$filenames = '';
foreach ($refs as $ref):
$lastmodified = max($lastmodified, filemtime( realpath( $this->style_path . $ref['dev'] ) ) );
$filenames .= $ref['dev'];
if(!$ref['combine']):
echo (isset($ref['prod'])) ? $this->_tag('css', $ref['prod'], $media) : $this->_tag('css', $ref['dev'], $media);
elseif(!$ref['minify']):
$files[] = (isset($ref['prod'])) ? array('prod'=>$ref['prod'], 'dev'=>$ref['dev'], 'minify'=>$ref['minify'] ) : array('dev'=>$ref['dev'], 'minify'=>$ref['minify']);
else:
$files[] = (isset($ref['prod'])) ? array('prod'=>$ref['prod'], 'dev'=>$ref['dev'] ) : array('dev'=>$ref['dev']);
endif;
endforeach;
$lastmodified = ($lastmodified == 0) ? '0000000000' : $lastmodified;
$filename = $lastmodified . md5($filenames).'.css';
if( !file_exists($this->cache_path.$filename) ) $this->_combine('css', $files, $filename);
echo $this->_tag('css', $filename, TRUE, $media);
endforeach;
} elseif($this->combine && !$this->minify_css) { // we're combining bot not minifying
foreach($this->css[$group] as $media => $refs):
// lets try to cache it, shall we?
$lastmodified = 0;
$files = array();
$filenames = '';
foreach ($refs as $ref):
$lastmodified = max($lastmodified, filemtime( realpath( $this->style_path . $ref['dev'] ) ) );
$filenames .= $ref['dev'];
if($ref['combine'] == false):
echo (isset($ref['prod'])) ? $this->_tag('css', $ref['prod'], $media) : $this->_tag('css', $ref['dev'], $media);
else:
$files[] = (isset($ref['prod'])) ? array('prod'=>$ref['prod'], 'dev'=>$ref['dev'], 'minify'=>FALSE ) : array('dev'=>$ref['dev'], 'minify'=>FALSE);
endif;
endforeach;
$lastmodified = ($lastmodified == 0) ? '0000000000' : $lastmodified;
$filename = $lastmodified . md5($filenames).'.css';
if( !file_exists($this->cache_path.$filename) ) $this->_combine('css', $files, $filename);
echo $this->_tag('css', $filename, TRUE, $media);
endforeach;
} elseif(!$this->combine && $this->minify_css) { // we want to minify, but not combine
foreach($this->css[$group] as $media => $refs):
foreach($refs as $ref):
if( isset($ref['prod']) ){
$f = $this->style_uri . $ref['prod'];
} elseif( !$ref['minify'] ){
$f = $this->style_uri . $ref['dev'];
} else {
$f = filemtime( realpath( $this->style_path . $ref['dev'] ) ) . md5($ref['dev']) . '.css';
if( !file_exists($this->cache_path.$f) ):
$c = $this->_minify( 'css', $ref['dev'] );
$this->_cache($f, $c);
endif;
}
echo $this->_tag('css', $f, TRUE, $media);
endforeach;
endforeach;
}else{ // we're in a production environment, but not minifying or combining.
foreach($this->css[$group] as $media => $refs):
foreach($refs as $ref):
$f = (isset($ref['prod'])) ? $ref['prod'] : $ref['dev'];
echo $this->_tag('css', $f, FALSE, $media);
endforeach;
endforeach;
}
}
/**
* Internal function for compressing/combining scripts
* @access private
* @param String flag the asset type: css|js
* @param array of file references to be combined. Should contain arrays, as included in primary asset arrays: ('dev'=>$dev, 'prod'=>$prod, 'minify'=>TRUE||FALSE)
* @param String of the filename of the file-to-be
* @return Void
*/
private function _combine($flag, $files, $filename)
{
$file_data = '';
$path = ($flag == 'css') ? $this->style_path : $this->script_path;
$minify = ($flag == 'css') ? $this->minify_css : $this->minify_js;
foreach($files as $file):
$v = (isset($file['prod']) ) ? 'prod' : 'dev';
if( (isset($file['minify']) && $file['minify'] == true) || (!isset($file['minify']) && $minify) ):
$file_data .= $this->_minify( $flag, $file['dev'] ) . "\n";
else:
$r = ( $this->isURL($file[$v]) ) ? $file[$v] : realpath($path.$file[$v]);
$file_data .= $this->_get_contents( $r ) ."\n";
endif;
endforeach;
$this->_cache( $filename, $file_data );
}
/**
* Internal function for minifying assets
* @access private
* @param String flag the asset type: css|js
* @param String of the path to the file whose contents should be minified
* @return String minified contents of file
*/
private function _minify($flag, $file_ref)
{
$path = ($flag == 'css') ? $this->style_path : $this->script_path;
$ref = ( $this->isURL($file_ref) ) ? $file_ref : realpath($path.$file_ref);
//hack for stikked themes
if(!file_exists($ref)){
$path = ($flag == 'css') ? 'themes/default/css/' : $this->script_path;
$ref = ( $this->isURL($file_ref) ) ? $file_ref : realpath($path.$file_ref);
}
switch($flag){
case 'js':
$this->_load('jsmin');
$contents = $this->_get_contents( $ref );
return $this->CI->jsmin->minify($contents);
break;
case 'css':
$this->_load('cssmin');
$rel = ( $this->isURL($file_ref) ) ? $file_ref : dirname($this->style_uri.$file_ref).'/';
$this->CI->cssmin->config(array('relativePath'=>$rel));
$contents = $this->_get_contents( $ref );
return $this->CI->cssmin->minify($contents);
break;
}
}
/**
* Internal function for getting a files contents, using cURL or file_get_contents, depending on circumstances
* @access private
* @param String of full path to the file (or full URL, if appropriate)
* @return String of files contents
*/
private function _get_contents($ref)
{
if( $this->isURL($ref) && ( ini_get('allow_url_fopen') == 0 || $this->force_curl ) ):
$this->_load('curl');
$contents = $this->CI->curl->simple_get($ref);
else:
$contents = file_get_contents( $ref );
endif;
return $contents;
}
/**
* Internal function for writing cache files
* @access private
* @param String of filename of the new file
* @param String of contents of the new file
* @return boolean Returns true on successful cache, false on failure
*/
private function _cache($filename, $file_data)
{
if(empty($file_data)):
log_message('debug', 'Carabiner: Cache file '.$filename.' was empty and therefore not written to disk at '.$this->cache_path);
return false;
endif;
$filepath = $this->cache_path . $filename;
$success = file_put_contents( $filepath, $file_data );
if($success) :
log_message('debug', 'Carabiner: Cache file '.$filename.' was written to '.$this->cache_path);
return TRUE;
else :
log_message('error', 'Carabiner: There was an error writing cache file '.$filename.' to '.$this->cache_path);
return FALSE;
endif;
}
/**
* Internal function for making tag strings
* @access private
* @param String flag for type: css|js
* @param String of reference of file.
* @param Boolean flag for cache dir. Defaults to FALSE.
* @param String Media type for the tag. Only applies to CSS links. defaults to 'screen'
* @return String containing an HTML tag reference to given reference
*/
private function _tag($flag, $ref, $cache = FALSE, $media = 'screen')
{
switch($flag){
case 'css':
$dir = ( $this->isURL($ref) ) ? '' : ( ($cache) ? $this->cache_uri : $this->style_uri );
return '<link type="text/css" rel="stylesheet" href="'.$dir.$ref.'" media="'.$media.'" />'."\r\n";
break;
case 'js':
$dir = ( $this->isURL($ref) ) ? '' : ( ($cache) ? $this->cache_uri : $this->script_uri );
return '<script type="text/javascript" src="'.$dir.$ref.'" charset="'.$this->CI->config->item('charset').'"></script>'."\r\n";
break;
}
}
/**
* Function used to clear the asset cache. If no flag is set, both CSS and JS will be emptied.
* @access public
* @param String flag the asset type: css|js|both
* @param String denoting a time before which cache files will be removed. Any string that strtotime() can take is acceptable. Defaults to now.
* @return Void
*/
public function empty_cache($flag = 'both', $before = 'now')
{
$this->CI->load->helper('file');
$files = get_filenames($this->cache_path);
$before = strtotime($before);
switch($flag){
case 'js':
case 'css':
foreach( $files as $file ){
$ext = substr( strrchr( $file, '.' ), 1 );
$fl = strlen(substr( $file, 0, -(strlen($flag)+1) ));
if ( ($ext == $flag) && $fl >= 42 && ( filemtime( $this->cache_path . $file ) < $before) ) {
$success = unlink( $this->cache_path . $file );
if($success) : log_message('debug', 'Carabiner: Cache file '.$file.' was removed from '.$this->cache_path);
else : log_message('error', 'Carabiner: There was an error removing cache file '.$file.' from '.$this->cache_path);
endif;
}
}
break;
case 'both':
default:
foreach( $files as $file ){
$ext = substr( strrchr( $file, '.' ), 1 );
$fl = strlen(substr( $file, 0, -3 ));
if ( ($ext == 'js' || $ext == 'css') && $fl >= 42 && ( filemtime( $this->cache_path . $file ) < $before) ) {
$success = unlink( $this->cache_path . $file );
if($success) : log_message('debug', 'Carabiner: Cache file '.$file.' was removed from '.$this->cache_path);
else : log_message('error', 'Carabiner: There was an error removing cache file '.$file.' from '.$this->cache_path);
endif;
}
}
break;
}
}
/**
* Function used to prevent multiple load calls for the same CI library
* @access private
* @param String library name
* @return FALSE on empty call and when library is already loaded, TRUE when library loaded
*/
private function _load($lib=NULL)
{
if($lib == NULL) return FALSE;
if( isset($this->loaded[$lib]) ):
return FALSE;
else:
$this->CI->load->library($lib);
$this->loaded[$lib] = TRUE;
log_message('debug', 'Carabiner: Codeigniter library '."'$lib'".' loaded');
return TRUE;
endif;
}
/**
* isURL
* Checks if the provided string is a URL. Allows for port, path and query string validations.
* This should probably be moved into a helper file, but I hate to add a whole new file for
* one little 2-line function.
* @access public
* @param string to be checked
* @return boolean Returns TRUE/FALSE
*/
public static function isURL($string)
{
$pattern = '@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)@';
return preg_match($pattern, $string);
}
}