<?php
// It initializes session to capture $_SESSION['PRODUCTION'] var
session_start();
/**
* PHP Version of the Dean Edwards 's Packer de Dean Edwards, a JavaScript Compressor/Obfuscator.
* @link http://joliclic.free.fr/php/javascript-packer/en/
*/
require_once('phpclasses/packer/class.JavaScriptPacker.php');
/**
* CSSTidy is an opensource CSS parser and optimiser. It is available as executeable
* file (available for Windows, Linux and OSX) which can be controlled per command
* line and as PHP script (both with almost the same functionality).
* @link http://csstidy.sourceforge.net/index.php
*/
require_once('phpclasses/csstidy/class.csstidy.php');
//This verifies if the class already was declared.
if(!class_exists('crushJsCss')){
/**
* Merge, compact, scramble and cache Javascript and CSS files
*
* This compact class and scrambles JavaScript files through Dean Edwards's
* algorithm implemented in a class PHP by Nicolas Martin. Also, it compacts and
* optimize files CSS through the class CSSTidy. Finally, it compacts everything
* through gzip. And to save bandwidth, it creates files cache.
*
* @author Antonio Jozzolino <hide@address.com>
* @since Fri Aug 01 2008 08:25:51 GMT-0300
* @changed Wed Aug 06 2008 09:30:43 GMT-0300
* @version 0.01
* @link http://www.sgd.com.br
* @link http://dean.edwards.name/packer/
* @link http://joliclic.free.fr/php/javascript-packer/en/
* @link http://csstidy.sourceforge.net/index.php
* @link http://rakaz.nl/item/make_your_pages_load_faster_by_combining_and_compressing_javascript_and_css_files
* @link http://www.sgd.com.br/content/view/42/88888891/ Compactando, criptografando e juntando arquivos javascript e css (Artigo)
* @example examples/index.php Html
* @example examples/javascript.php Javascript
* @example examples/css.php CSS
*/
class crushJsCss{
/**
* @access public
* @var bolean Define to false for test phase
*/
var $production = true;
/**
* @access public
* @var string key [ "file"] absolute script path. Use $_SERVER["DOCUMENT_ROOT"] if your server permit it.
* @var bolean key[ "pack"] optional. True to scramble script, false to no modification.
*/
var $scripts;
/**
* @access public
* @var string Define scramble level . Values: 'None', 'Numeric', 'Normal', 'High ASCII'. 'Normal' is default value.
* @see http://dean.edwards.name/packer/usage/
*/
var $js_encoding = 'Normal';
/**
* @access public
* @var bolean True is default value.
* @see http://dean.edwards.name/packer/usage/
*/
var $js_fastDecode = true;
/**
* @access public
* @var bolean False is default value.
* @see http://dean.edwards.name/packer/usage/
*/
var $js_specialChars = false;
/**
* @access public
* @var string absolute script path to cache directory. $_SERVER["DOCUMENT_ROOT"] ."/cache" is default value. This directory should have writing permission (chmod -c 775)
*/
var $cachedir;
/**
* @access public
* @var string "javascript" or "css". "javascript " is default value.
*/
var $type = 'javascript';
/**
* @access private
* @var string define which compact method browser client suports, gzip, deflare or none.
*/
var $encoding = 'none';
/**
* @access private
* @var string name of cache file.
*/
var $cachefile;
/**
* @access private
* @var string compact method
*/
var $gzip;
/**
* @access private
* @var string compact method
*/
var $deflate;
/**
* @access public
* @var bolean If true, Remove unnecessary backslashes ("\"). False is default value.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_remove_bslash = false;
/**
* @access public
* @var bolean If true, compat "#000000" to "#000". True is default value.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_compress_colors = true;
/**
* @access public
* @var bolean if true, change "bold" to "700". True is default value.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_compress_font_weight = true;
/**
* @access public
* @var bolean if true, change all selector to lower case. Default is false.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_lowercase_s = false;
/**
* @access public
* @var numeric 0 = Dont't Optimise, 1 = Safe Optimisations, 2 = All Optisiations. Default is 1.
* @see http://csstidy.sourceforge.net/usage.php
* @see http://www.dustindiaz.com/css-shorthand/
*/
var $tidy_cfg_optimise_shorthands = 1;
/**
* @access public
* @var bolean if true, Remove last ";" . False is default.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_remove_last_semicolon = false;
/**
* @access public
* @var numeric case for properties. 0 = no change, 1 = lowercase, 2 = uppercase. 0 is default.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_case_properties = 0;
/**
* @access public
* @var bolean sort properties in ascendant order. False is default.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_sort_properties = false;
/**
* @access public
* @var bolean sort selectors in ascendant order. False is default.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_sort_selectors = false;
/**
* @access public
* @var numeric 0 = Do not change anything, 1 = Only separate selectors (split at .), 2 = Merge selectors with same properties (fast). 2 is default.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_merge_selectors = 2;
/**
* @access public
* @var bolean Discard invalid properties based at $tidy_cfg_discard_invalid_properties value. False is default.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_discard_invalid_properties = false;
/**
* @access public
* @var string Possible values are 'CSS1.0', 'CSS2.0', 'CSS2.1'. Default is 'CSS2.1'
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_css_level = 'CSS2.1';
/**
* @access public
* @var bolean. Save comments, hacks, etc. Most optimisations can *not* be applied if this is enabled. Default is false.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_preserve_css = false;
/**
* @access public
* @var bolean. Insert a first line with a comment like this: "CSSTidy 1.3dev: Tue, 05 Aug 2008 14:56:53 +0200" . Default is false.
* @see http://csstidy.sourceforge.net/usage.php
*/
var $tidy_cfg_timestamp = false;
/**
* Construtor function
*
* This function set defaults values and determine client browser capabilities.
* @access public
*/
function crushJsCss()
{
$this->production = (isset($_SESSION['PRODUCTION'])) ? $_SESSION['PRODUCTION'] : $this->production;
$this->cachedir = (!$this->cachedir)? $_SERVER["DOCUMENT_ROOT"].'/cache' : $this->cachedir;
// Determine supported compression method
$this->gzip = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
$this->deflate = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate');
// Determine used compression method
$this->encoding = $this->gzip ? 'gzip' : ($this->deflate ? 'deflate' : 'none');
// Check for buggy versions of Internet Explorer
if (!strstr($_SERVER['HTTP_USER_AGENT'], 'Opera') &&
preg_match('/^Mozilla\/4\.0 \(compatible; MSIE ([0-9]\.[0-9])/i', $_SERVER['HTTP_USER_AGENT'], $matches)) {
$version = floatval($matches[1]);
if ($version < 6)
$this->encoding = 'none';
if ($version == 6 && !strstr($_SERVER['HTTP_USER_AGENT'], 'EV1'))
$this->encoding = 'none';
}
}
/**
* Merge, compact and scramble javascript and css files
*
* This function first checks whether the file needs new version or the version stored in cache can be used.
* If a new file should be created, the function checks the variable $type to determine if a file is javascript or css.
* The function also check the $production and $scripts["pack"], to determine whether the file should be compressed.
* All css or javascripts files are merged into a single file and submitted to function gzipIt, which compact and return the content according to the client browser´s capabilities.
* @access public
* @return string string or binary content
*/
function jscss()
{
$this->cache();
$str = '';
foreach ($this->scripts as $file){
$src = file_get_contents($file['file']);
if($this->production && !isset($file['pack'])){
if($this->type == 'javascript'){
$packer = new JavaScriptPacker($src, $this->js_encoding, $this->js_fastDecode, $this->js_specialChars);
$str .= "\n" .(preg_replace('/[\n\r]/', ";\n", $packer->pack()));
}else{
$css = new csstidy();
$css->set_cfg('remove_bslash' , $this->tidy_cfg_remove_bslash);
$css->set_cfg('compress_colors' , $this->tidy_cfg_compress_colors);
$css->set_cfg('compress_font-weight' , $this->tidy_cfg_compress_font_weight);
$css->set_cfg('lowercase_s' , $this->tidy_cfg_lowercase_s);
$css->set_cfg('optimise_shorthands' , $this->tidy_cfg_optimise_shorthands);
$css->set_cfg('remove_last_;' , $this->tidy_cfg_remove_last_semicolon);
$css->set_cfg('case_properties' , $this->tidy_cfg_case_properties);
$css->set_cfg('sort_properties' , $this->tidy_cfg_sort_properties);
$css->set_cfg('sort_selectors' , $this->tidy_cfg_sort_selectors);
$css->set_cfg('merge_selectors' , $this->tidy_cfg_merge_selectors);
$css->set_cfg('discard_invalid_properties' , $this->tidy_cfg_discard_invalid_properties);
$css->set_cfg('css_level' , $this->tidy_cfg_css_level);
$css->set_cfg('preserve_css' , $this->tidy_cfg_preserve_css);
$css->set_cfg('timestamp' , $this->tidy_cfg_timestamp);
$css->parse($src);
$str .= "\n" . $css->print->plain();
}
}else{
$str .= "\n" . $src;
}
}
$this->gzipIt($str);
}
/**
* It verifies cache´s contents
*
* It verifies that cache is valid. If yes, the version of the cache is sent. If the client's browser already has the file, nothing is sent.
* @access private
* @return string or binary content
*/
function cache()
{
$size = 0;
foreach ($this->scripts as $file){
$chaged[] = filemtime($file['file']);
$size += strlen($file['file']);
}
sort($chaged, SORT_NUMERIC);
// Try the cache first to see if the combined files were already generated
$hash = md5($chaged[count($chaged)-1]);
$this->cachefile = 'cache-' . $hash . '_S'.$size.'.' . $this->type . ($this->encoding != 'none' ? '.' . $this->encoding : '');
if (file_exists($this->cachedir . '/' . $this->cachefile)) {
// Send Etag hash
header ("Etag: \"" . $hash . "\"");
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) == '"' . $this->cachefile . '"'){
// Return visit and no modifications, so do not send anything
header ("HTTP/1.0 304 Not Modified");
header ('Content-Length: 0');
exit;
}
if ($fp = fopen($this->cachedir . '/' . $this->cachefile, 'rb')) {
header ('Vary: Accept-Encoding');
if ($this->encoding != 'none') {
header ("Content-Encoding: " . $this->encoding);
}
header ("Content-Type: text/" . $this->type);
header ("Content-Length: " . filesize($this->cachedir . '/' . $this->cachefile));
fpassthru($fp);
fclose($fp);
exit;
}
}
}
/**
* Compact javascript and css files and save in cache directory
*
* It ensures the client's browser accepts compressed files. If yes, return the file to accept compaction.
* If not, return the file without compress. Save the file in the cache for later use.
* @access private
* @param string $contents
* @return string string or binary content
*/
function gzipIt($contents)
{
// Send Content-Type
header ("Content-Type: text/" . $this->type);
if (isset($this->encoding) && $this->encoding != 'none'){
// Send compressed contents
$contents = gzencode($contents, 9, $this->gzip ? FORCE_GZIP : FORCE_DEFLATE);
header ('Vary: Accept-Encoding');
header ("Content-Encoding: " . $this->encoding);
header ('Content-Length: ' . strlen($contents));
print $contents;
}else{
// Send regular contents
header ('Content-Length: ' . strlen($contents));
echo $contents;
}
// Store cache
if ($fp = fopen($this->cachedir . '/' . $this->cachefile, 'wb')){
fwrite($fp, $contents);
fclose($fp);
}
}
}
}
?>