From 64d98ed7395b4b0351d36f986984d4a9ceb07e5a Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 19 Apr 2012 19:22:04 +0200 Subject: [PATCH] codemirror exec js --- htdocs/application/libraries/carabiner.php | 999 ++++++++++++------ htdocs/application/libraries/cssmin.php | 2 +- htdocs/application/libraries/curl.php | 304 ++++++ htdocs/application/views/view/view_footer.php | 32 +- htdocs/static/js/codemirror_exec.js | 18 + 5 files changed, 1041 insertions(+), 314 deletions(-) create mode 100644 htdocs/application/libraries/curl.php create mode 100644 htdocs/static/js/codemirror_exec.js diff --git a/htdocs/application/libraries/carabiner.php b/htdocs/application/libraries/carabiner.php index bf2a80c..a33bdcc 100644 --- a/htdocs/application/libraries/carabiner.php +++ b/htdocs/application/libraries/carabiner.php @@ -12,26 +12,30 @@ * * 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 include them, unless you'll be using them elsewhise. Carabiner will include them + * 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/ } + * 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 }. + * 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 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 others. + * 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 - * @version 1.2 + * @author Tony Dewan + * @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 */ /* @@ -44,22 +48,30 @@ $this->load->library('carabiner'); ----------------------------------------------------------------------------------------------- - Configure it like so: + 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, + 'base_uri' => base_url(), 'combine' => TRUE, - 'dev' => FALSE + 'dev' => FALSE, + 'minify_js' => TRUE, + 'minify_css' => TRUE ); $this->carabiner->config($carabiner_config); ----------------------------------------------------------------------------------------------- - There are 8 options. 4 are required: + There are 9 options. 3 are required: script_dir STRING Path to the script directory. Relative to the CI front controller (index.php) @@ -70,11 +82,12 @@ 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/ - - - 4 are not required: + 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. @@ -89,6 +102,9 @@ 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: ----------------------------------------------------------------------------------------------- @@ -101,10 +117,9 @@ // add a css file with a mediatype $this->carabiner->css('admin/print.css','print'); ----------------------------------------------------------------------------------------------- - - To set a (prebuilt) production version of a js asset: + 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' ); @@ -114,7 +129,7 @@ ----------------------------------------------------------------------------------------------- - And to prevent a file from being combined: + 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 ); @@ -122,12 +137,11 @@ // 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 + // a single array (this is redundant, but supported anyway) $this->carabiner->css( array('mobile.css', 'handheld', 'mobile.prod.css') ); // an array of arrays @@ -139,6 +153,35 @@ $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: ----------------------------------------------------------------------------------------------- @@ -147,7 +190,23 @@ //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. @@ -160,37 +219,45 @@ $this->carabiner->empty_cache('js'); // clear both - $this->carabiner->empty_cache(); + $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 { - var $base_uri = ''; + public $base_uri = ''; - var $script_dir = ''; - var $script_path = ''; - var $script_uri = ''; + public $script_dir = ''; + public $script_path = ''; + public $script_uri = ''; - var $style_dir = ''; - var $style_path = ''; - var $style_uri = ''; + public $style_dir = ''; + public $style_path = ''; + public $style_uri = ''; - var $cache_dir = ''; - var $cache_path = ''; - var $cache_uri = ''; + public $cache_dir = ''; + public $cache_path = ''; + public $cache_uri = ''; - var $dev = FALSE; - var $combine = TRUE; + public $dev = FALSE; + public $combine = TRUE; - var $minify_js = TRUE; - var $minify_css = TRUE; + public $minify_js = TRUE; + public $minify_css = TRUE; + public $force_curl = FALSE; - var $js = array(); - var $css = array(); + private $js = array('main'=>array()); + private $css = array('main'=>array()); + private $loaded = array(); - var $CI; + private $CI; /** @@ -199,48 +266,75 @@ class Carabiner { public function __construct() { $this->CI =& get_instance(); - log_message('debug', 'Carabiner Asset Management library initialized.'); - + 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 - * @param Array of config variables. Requires script_dir(string), style_dir(string), cache_dir(string), and base_uri(string). - * dev(bool), combine(bool), minify_js(bool), minify_css(bool) are optional. + * @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 = dirname(BASEPATH).'/'.$this->script_dir; - $this->script_path = $this->script_dir; + $this->script_path = FCPATH.$this->script_dir; $this->script_uri = $this->base_uri.$this->script_dir; - //$this->style_path = dirname(BASEPATH).'/'.$this->style_dir; - $this->style_path = $this->style_dir; + $this->style_path = FCPATH.$this->style_dir; $this->style_uri = $this->base_uri.$this->style_dir; - //$this->cache_path = dirname(BASEPATH).'/'.$this->cache_dir; - $this->cache_path = $this->cache_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 Flag whether the file is to be combined 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) + public function js($dev_file, $prod_file = '', $combine = TRUE, $minify = TRUE, $group = 'main') { - + if( is_array($dev_file) ){ if( is_array($dev_file[0]) ){ @@ -250,8 +344,10 @@ class Carabiner { $d = $file[0]; $p = (isset($file[1])) ? $file[1] : ''; $c = (isset($file[2])) ? $file[2] : $combine; - - $this->_asset('js', $d, $p, $c); + $m = (isset($file[3])) ? $file[3] : $minify; + $g = (isset($file[4])) ? $file[4] : $group; + + $this->_asset('js', $d, $p, $c, $m, NULL, $g); } @@ -260,15 +356,17 @@ class Carabiner { $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); + $this->_asset('js', $d, $p, $c, $m, NULL, $g); } - + }else{ - $this->_asset('js', $dev_file, $prod_file, $combine); - + $this->_asset('js', $dev_file, $prod_file, $combine, $minify, NULL, $group); + } } @@ -276,12 +374,16 @@ class Carabiner { /** * 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 Flag whether the file is to be combined. 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 = 'all', $prod_file = '', $combine = TRUE) + public function css($dev_file, $media = 'screen', $prod_file = '', $combine = TRUE, $minify = TRUE, $group = 'main') { if( is_array($dev_file) ){ @@ -294,256 +396,461 @@ class Carabiner { $m = (isset($file[1])) ? $file[1] : $media; $p = (isset($file[2])) ? $file[2] : ''; $c = (isset($file[3])) ? $file[3] : $combine; - - $this->_asset('css', $d, $p, $c, $m); + $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($file[1])) ? $file[1] : $media; + $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; - - $this->_asset('css', $d, $p, $c, $m); + $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, $media); + $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 - * @param String of the type of asset (lowercase) . css | js + * @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 Flag whether the file is to be combined. Defaults to true. 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 = TRUE, $media = 'screen') + private function _asset($type, $dev_file, $prod_file = '', $combine, $minify, $media = 'screen', $group = 'main') { if ($type == 'css') : - $this->css[$media][] = array( 'dev'=>$dev_file ); - $index = count($this->css[$media]) - 1; - - if($prod_file != '') $this->{$type}[$media][$index]['prod'] = $prod_file; - $this->css[$media][$index]['combine'] = $combine; + $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->{$type}[] = array( 'dev'=>$dev_file ); - $index = count($this->{$type}) - 1; + + $this->js[$group][] = array( 'dev'=>$dev_file ); + $index = count($this->js[$group]) - 1; - if($prod_file != '') $this->js[$index]['prod'] = $prod_file; - $this->js[$index]['combine'] = $combine; + 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 - * @param Flag the asset type: css|js + * @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) - { + 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( empty($this->js) ) return; // if there aren't any js files, just stop! + if( isset($this->css[$flag]) && ($group_filter == NULL || $group_filter == 'css') ) + $this->_display_css($flag); + break; + } + } - // if we're in a dev environment - if($this->dev){ - - foreach($this->js as $ref): - - echo $this->_tag('js', $ref['dev']); - - endforeach; - - - // if we're combining files - } elseif($this->combine) { - $lastmodified = 0; - $files = array(); - $filenames = ''; - $not_combined = ''; - - foreach ($this->js as $ref) { + /** + * 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; + - // 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'] == false): - $not_combined .= (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'] ) : array('dev'=>$ref['dev']); - endif; + } + + + + /** + * 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; } - $filename = $lastmodified . md5($filenames).'.js'; - - if( !file_exists($this->cache_path.$filename) ) $this->_combine('js', $files, $filename); - - echo $not_combined; - echo $this->_tag('js', $filename, TRUE); - - - - // if we're minifying. but not combining - } elseif(!$this->combine && $this->minify_js) { - - // minify each file, cache it, and serve it up. Oy. - foreach($this->js as $ref): - - if( isset($ref['prod']) ){ - - $f = $ref['prod']; - - echo $this->_tag('js', $f, FALSE); - - } 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; - - }else{ - - foreach($this->js as $ref): - - $f = (isset($ref['prod'])) ? $ref['prod'] : $ref['dev']; - echo $this->_tag('js', $f); - - endforeach; - - } - - break; - - case 'css': - - if( empty($this->css) ) return; // there aren't any css assets, so just stop! - - if($this->dev){ // we're in a development environment - - foreach($this->css as $media => $refs): - - foreach($refs as $ref): - - echo $this->_tag('css', $ref['dev'], FALSE, $media); - - endforeach; - - endforeach; - - } elseif($this->combine) { // we're combining and minifying - - foreach($this->css as $media => $refs): - - // lets try to cache it, shall we? - $lastmodified = 0; - $files = array(); - $filenames = ''; - $not_combined = ''; - - foreach ($refs as $ref): - - $lastmodified = max($lastmodified, filemtime( realpath( $this->style_path . $ref['dev'] ) ) ); - $filenames .= $ref['dev']; - - if($ref['combine'] == false): - $not_combined .= (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'] ) : array('dev'=>$ref['dev']); - endif; - - endforeach; - - $filename = $lastmodified . md5($filenames).'.css'; - - if( !file_exists($this->cache_path.$filename) ) $this->_combine('css', $files, $filename); - - echo $not_combined; - echo $this->_tag('css', $filename, TRUE, $media); - - endforeach; - - } elseif(!$this->combine && $this->minify_css) { // we want to minify, but not combine - - foreach($this->css as $media => $refs): - - foreach($refs as $ref): - - if( isset($ref['prod']) ){ - - $f = $this->style_uri . $ref['prod']; - - } else { - - $f = filemtime( realpath( $this->style_path . $ref['dev'] ) ) . md5($ref['dev']) . '.css'; - - if( !file_exists($this->cache_path.$f) ): + echo $this->_tag('css', $f, TRUE, $media); - $c = $this->_minify( 'css', $ref['dev'] ); - $this->_cache($f, $c); - - endif; - } + endforeach; + + endforeach; + + + + }else{ // we're in a production environment, but not minifying or combining. - echo $this->_tag('css', $f, TRUE, $media); - - endforeach; - - endforeach; + foreach($this->css[$group] as $media => $refs): + + foreach($refs as $ref): - }else{ // we're in a production environment, but not minifying or combining - - foreach($this->css as $media => $refs): - - foreach($refs as $ref): - - $f = (isset($ref['prod'])) ? $ref['prod'] : $ref['dev']; - echo $this->_tag('css', $f, FALSE, $media); - - endforeach; - - endforeach; - - } - - break; + $f = (isset($ref['prod'])) ? $ref['prod'] : $ref['dev']; + echo $this->_tag('css', $f, FALSE, $media); + + endforeach; + + endforeach; } + } /** * Internal function for compressing/combining scripts - * @param 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) - * @param Filename of the file-to-be + * @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) { @@ -555,14 +862,17 @@ class Carabiner { foreach($files as $file): - - if($minify): + $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: - $file_data .= file_get_contents( realpath($path.$file['dev']) ) ."\n"; + $r = ( $this->isURL($file[$v]) ) ? $file[$v] : realpath($path.$file[$v]); + $file_data .= $this->_get_contents( $r ) ."\n"; endif; @@ -575,19 +885,24 @@ class Carabiner { /** * Internal function for minifying assets - * @param Flag the asset type: css|js - * @param Contents to be minified + * @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); + switch($flag){ case 'js': - $this->CI->load->library('jsmin'); - - $contents = file_get_contents( realpath($this->script_path.$file_ref) ); + $this->_load('jsmin'); + + $contents = $this->_get_contents( $ref ); return $this->CI->jsmin->minify($contents); break; @@ -595,58 +910,98 @@ class Carabiner { case 'css': - $this->CI->load->library('cssmin'); - $this->CI->cssmin->config(array('relativePath'=>$this->style_uri)); + $this->_load('cssmin'); - $contents = file_get_contents( realpath($this->style_path.$file_ref) ); + $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 - * @param filename of the new file - * @param Contents of the new file + * @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) { - $filepath = $this->cache_path . $filename; - //change ernscht: $filepath = realpath($this->cache_path . $filename); - file_put_contents( $filepath, $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 - * @param flag for type: css|js - * @param Reference of file. - * @param Flag for cache dir. Defaults to FALSE. - * @param Media type for the tag. Only applies to CSS links. defaults to 'screen' + * @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 = ($cache) ? $this->cache_uri : $this->style_uri; + $dir = ( $this->isURL($ref) ) ? '' : ( ($cache) ? $this->cache_uri : $this->style_uri ); - echo ''."\r\n"; + return ''."\r\n"; break; case 'js': - $dir = ($cache) ? $this->cache_uri : $this->script_uri; + $dir = ( $this->isURL($ref) ) ? '' : ( ($cache) ? $this->cache_uri : $this->script_uri ); - echo ''."\r\n"; + return ''."\r\n"; break; @@ -657,15 +1012,19 @@ class Carabiner { /** * Function used to clear the asset cache. If no flag is set, both CSS and JS will be emptied. - * @param Flag the asset type: css|js|both + * @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) + 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': @@ -674,28 +1033,37 @@ class Carabiner { foreach( $files as $file ){ $ext = substr( strrchr( $file, '.' ), 1 ); + $fl = strlen(substr( $file, 0, -(strlen($flag)+1) )); - if ( $ext == $flag ) { - - unlink( $this->cache_path . $file ); - + 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 ); - - if ( $ext == 'js' || $ext == 'css') { - - unlink( $this->cache_path . $file ); + $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; } } @@ -705,4 +1073,41 @@ class Carabiner { } } -} \ No newline at end of file + + /** + * 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); + } +} diff --git a/htdocs/application/libraries/cssmin.php b/htdocs/application/libraries/cssmin.php index 704f6f9..c51216d 100644 --- a/htdocs/application/libraries/cssmin.php +++ b/htdocs/application/libraries/cssmin.php @@ -63,7 +63,7 @@ public function cssmin() { - log_message('debug', 'CSS Minification library initialized.'); + log_message('debug', 'CSSMin library initialized.'); } diff --git a/htdocs/application/libraries/curl.php b/htdocs/application/libraries/curl.php new file mode 100644 index 0000000..7f045a8 --- /dev/null +++ b/htdocs/application/libraries/curl.php @@ -0,0 +1,304 @@ +CI =& get_instance(); + log_message('debug', 'cURL Class Initialized'); + + if (!function_exists('curl_init')) { + log_message('error', 'cURL Class - PHP was not built with cURL enabled. Rebuild PHP with --with-curl to use cURL.') ; + } + + if($url) $this->create($url); + } + + /* ================================================================================= + * SIMPLE METHODS + * Using these methods you can make a quick and easy cURL call with one line. + * ================================================================================= */ + + // Return a get request results + public function simple_get($url, $options = array()) + { + // If a URL is provided, create new session + $this->create($url); + + // Add in the specific options provided + $this->options($options); + + return $this->execute(); + } + + // Send a post request on its way with optional parameters (and get output) + // $url = '', $params = array(), $options = array() + public function simple_post($url, $params = array(), $options = array()) + { + $this->create($url); + + $this->post($params, $options); + + return $this->execute(); + } + + // Send a post request on its way with optional parameters (and get output) + // $url = '', $params = array(), $options = array() + public function simple_put($url, $params = array(), $options = array()) + { + $this->create($url); + + $this->put($params, $options); + + return $this->execute(); + } + + // Send a post request on its way with optional parameters (and get output) + // $url = '', $params = array(), $options = array() + public function simple_delete($url) + { + $this->create($url); + + $this->http_method('delete'); + + return $this->execute(); + } + + public function simple_ftp_get($url, $file_path, $username = '', $password = '') + { + // If there is no ftp:// or any protocol entered, add ftp:// + if(!preg_match('!^(ftp|sftp)://! i', $url)) { + $url = 'ftp://'.$url; + } + + // Use an FTP login + if($username != '') + { + $auth_string = $username; + + if($password != '') + { + $auth_string .= ':'.$password; + } + + // Add the user auth string after the protocol + $url = str_replace('://', '://'.$auth_string.'@', $url); + } + + // Add the filepath + $url .= $file_path; + + $this->options(CURLOPT_BINARYTRANSFER, TRUE); + $this->options(CURLOPT_VERBOSE, TRUE); + + return $this->execute(); + } + + /* ================================================================================= + * ADVANCED METHODS + * Use these methods to build up more complex queries + * ================================================================================= */ + + public function post($params = array(), $options = array()) { + + // If its an array (instead of a query string) then format it correctly + if(is_array($params)) { + $params = http_build_query($params); + } + + // Add in the specific options provided + $this->options($options); + + $this->http_method('post'); + + $this->option(CURLOPT_POST, TRUE); + $this->option(CURLOPT_POSTFIELDS, $params); + } + + public function put($params = array(), $options = array()) { + + // If its an array (instead of a query string) then format it correctly + if(is_array($params)) { + $params = http_build_query($params); + } + + // Add in the specific options provided + $this->options($options); + + $this->option(CURLOPT_PUT, TRUE); + $this->option(CURLOPT_POSTFIELDS, $params); + } + + public function set_cookies($params = array()) { + + if(is_array($params)) { + $params = http_build_query($params); + } + + $this->option(CURLOPT_COOKIE, $params); + return $this; + } + + public function http_header($header_string) + { + $this->headers[] = $header_string; + } + + public function http_method($method) + { + $this->options[CURLOPT_CUSTOMREQUEST] = strtoupper($method); + return $this; + } + + public function http_login($username = '', $password = '', $type = 'any') + { + $this->option(CURLOPT_HTTPAUTH, constant('CURLAUTH_'.strtoupper($type) )); + $this->option(CURLOPT_USERPWD, $username.':'.$password); + return $this; + } + + public function proxy($url = '', $port = 80) { + + $this->option(CURLOPT_HTTPPROXYTUNNEL. TRUE); + $this->option(CURLOPT_PROXY, $url.':'. 80); + return $this; + } + + public function proxy_login($username = '', $password = '') { + $this->option(CURLOPT_PROXYUSERPWD, $username.':'.$password); + return $this; + } + + public function options($options = array()) + { + // Merge options in with the rest - done as array_merge() does not overwrite numeric keys + foreach($options as $option_code => $option_value) + { + $this->option($option_code, $option_value); + } + unset($option_code, $option_value); + + // Set all options provided + curl_setopt_array($this->session, $this->options); + + return $this; + } + + public function option($code, $value) { + $this->options[$code] = $value; + return $this; + } + + // Start a session from a URL + public function create($url) { + + // Reset the class + $this->set_defaults(); + + // If no a protocol in URL, assume its a CI link + if(!preg_match('!^\w+://! i', $url)) { + $this->CI->load->helper('url'); + $url = site_url($url); + } + + $this->url = $url; + $this->session = curl_init($this->url); + + return $this; + } + + // End a session and return the results + public function execute() + { + // Set two default options, and merge any extra ones in + if(!isset($this->options[CURLOPT_TIMEOUT])) $this->options[CURLOPT_TIMEOUT] = 30; + if(!isset($this->options[CURLOPT_RETURNTRANSFER])) $this->options[CURLOPT_RETURNTRANSFER] = TRUE; + if(!isset($this->options[CURLOPT_FOLLOWLOCATION])) $this->options[CURLOPT_FOLLOWLOCATION] = TRUE; + if(!isset($this->options[CURLOPT_FAILONERROR])) $this->options[CURLOPT_FAILONERROR] = TRUE; + + if(!empty($this->headers)) + { + $this->option(CURLOPT_HTTPHEADER, $this->headers); + } + + $this->options(); + + // Execute the request & and hide all output + $this->responce = curl_exec($this->session); + + // Request failed + if($this->responce === FALSE) + { + $this->error_code = curl_errno($this->session); + $this->error_string = curl_error($this->session); + + curl_close($this->session); + $this->session = NULL; + return FALSE; + } + + // Request successful + else + { + $this->info = curl_getinfo($this->session); + + curl_close($this->session); + $this->session = NULL; + return $this->responce; + } + } + + + public function debug() + { + echo "=============================================
\n"; + echo "

CURL Test

\n"; + echo "=============================================
\n"; + echo "

Responce

\n"; + echo "".nl2br(htmlentities($this->responce))."
\n\n"; + + if($this->error_string) + { + echo "=============================================
\n"; + echo "

Errors

"; + echo "Code: ".$this->error_code."
\n"; + echo "Message: ".$this->error_string."
\n"; + } + + echo "=============================================
\n"; + echo "

Info

"; + echo "
";
+        print_r($this->info);
+        echo "
"; + } + + private function set_defaults() + { + $this->responce = ''; + $this->info = array(); + $this->options = array(); + $this->error_code = 0; + $this->error_string = ''; + } +} +// END cURL Class + +/* End of file cURL.php */ +/* Location: ./application/libraries/curl.php */ \ No newline at end of file diff --git a/htdocs/application/views/view/view_footer.php b/htdocs/application/views/view/view_footer.php index f147cc0..b6d83b6 100755 --- a/htdocs/application/views/view/view_footer.php +++ b/htdocs/application/views/view/view_footer.php @@ -8,26 +8,26 @@ $this->carabiner->js('jquery.timers.js'); $this->carabiner->js('jquery.clipboard.js'); $this->carabiner->js('stikked.js'); $this->carabiner->js('codemirror/codemirror.js'); -$this->carabiner->js('codemirror/mode/xml/xml.js'); -$this->carabiner->js('codemirror/mode/javascript/javascript.js'); -$this->carabiner->js('codemirror/mode/css/css.js'); -$this->carabiner->js('codemirror/mode/clike/clike.js'); -$this->carabiner->js('codemirror/mode/php/php.js'); - $this->carabiner->display('js'); +$codemirror_specific = array( + 'js' => array( + array('codemirror/mode/xml/xml.js'), + array('codemirror/mode/javascript/javascript.js'), + array('codemirror/mode/css/css.js'), + array('codemirror/mode/clike/clike.js'), + array('codemirror/mode/php/php.js'), + ) +); + +$codemirror_specific['js'][] = array('codemirror_exec.js'); + +$this->carabiner->group('codemirror', $codemirror_specific); + +$this->carabiner->display('codemirror'); + ?> diff --git a/htdocs/static/js/codemirror_exec.js b/htdocs/static/js/codemirror_exec.js new file mode 100644 index 0000000..a8721c4 --- /dev/null +++ b/htdocs/static/js/codemirror_exec.js @@ -0,0 +1,18 @@ +var CM = window.CM || {} + +CM.init = function() { + var editor = CodeMirror.fromTextArea(document.getElementById("code"), { + mode: "application/x-httpd-php", + lineNumbers: true, + lineWrapping: true, + onCursorActivity: function() { + editor.setLineClass(hlLine, null, null); + hlLine = editor.setLineClass(editor.getCursor().line, null, "activeline"); + } + }); + var hlLine = editor.setLineClass(0, "activeline"); +}; + +$(document).ready(function() { + CM.init(); +});