Location: PHPKode > scripts > crushJsCss > crushjscss/class_crushJsCss.php
<?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);
			}	
		}		
	}
}
?>
Return current item: crushJsCss