| 
<?php 
 /**
 * CssShrink
 *
 * @package CssShrink v1.0 - CSS Compressor & Uncompressor
 * @author João Romão (iceburn.info)
 * @version 2008
 * @access public
 */
 class CssShrink {
 
 // Alowed 'normal' CSS chars regex constant
 const chars_regex = '[^a-z0-9-_\{\}\>:;\*\.\#,\/\/\s\'\)\(\[\]!%@=\$\^]';
 
 public static $css;
 
 
 /**
 * CssShrink::compressed()
 *
 * @return string
 */
 public function compressed() {
 return self::filter($this->css);
 }
 
 
 /**
 * CssShrink::uncompressed()
 *
 * @return string
 */
 public function uncompressed($str = null) {
 return self::reverse(self::prepare(is_null($str) ? $this->css : $str));
 }
 
 
 /**
 * CssShrink::gain()
 *
 * @return int
 */
 public function gain() {
 return (int)(strlen($this->css) - strlen(self::filter($this->css)));
 }
 
 
 /**
 * CssShrink::dump2file()
 *
 * @param mixed $filename
 * @param mixed $contents
 * @return bool
 */
 public function dump2file($filename, $contents) {
 
 // Attempt to create file, if not exists
 if(!is_file($filename)) {
 touch($filename) or die('Attempt to create inexistent file failed!');
 }
 
 // Attempt to chmod 777 before write
 chmod($filename, 0777);
 
 // Write to file
 if(file_put_contents($filename, $contents, LOCK_EX)) {
 chmod($filename, 0644);
 return true;
 } else {
 // chmod 644, even if cannot write to file
 chmod($filename, 0644);
 }
 
 return false;
 }
 
 
 /**
 * CssShrink::prepare()
 *
 * @param mixed $str
 * @return string
 */
 private static function prepare($str) {
 
 // Globalize quotes format
 $str = str_replace('"', "'", $str);
 
 // Only process allowed CSS chars, and strip all others
 $str = preg_replace('/' . self::chars_regex . '/i', '', $str);
 
 // Remove CSS Comments
 $str = preg_replace('/(\/\*(.*?)\*\/)/s', '', $str);
 
 // Remove all unecessary spaces
 $str = preg_replace('/\s\s+/', ' ', $str);
 
 return $str;
 }
 
 
 /**
 * CssShrink::filter()
 *
 * @param mixed $css
 * @return string
 */
 private static function filter($css) {
 
 $css = self::prepare($css);
 
 // Remove spaces around certain chars
 $css = preg_replace('/(\s)?(:|;|,|{|})(\s)?/s', '\\2', $css);
 
 /**
 * Final clean up:
 * - Semi-colon is not needed in last atribute
 * - In url() quotes are not needed
 */
 $css = str_replace(array("('", "')", ';}'), array('(', ')', '}'), $css);
 
 return trim($css);
 }
 
 
 /**
 * CssShrink::reverse()
 *
 * @param mixed $css
 * @return string
 */
 private static function reverse($css) {
 
 $css = self::prepare($css);
 
 // Remove unhandled line breaks and tabs
 $css = str_replace(array("\n", "\r", "\t"), ' ', $css);
 
 // Add spaces next to certain chars
 $css = preg_replace('/(\s)?(;|:|,|{|})(\s)?/s', '\\2 ', $css);
 
 // Some extra CSS beautify and cleanup
 $src = array('(', ')', ';}', "(''", "'')");
 $rep = array("('", "')", '}', "('", "')");
 $css = str_replace($src, $rep, $css);
 unset($src, $rep);
 
 // Add new lines after '{', ';' and '}'
 $src = array('{', '}', ';');
 $rep = array(" {\n", ";}\n\n", ";\n");
 $css = str_replace($src, $rep, $css);
 unset($src, $rep);
 
 // Temporary, turn the whole CSS into an array
 // TODO: Simplify the array process, and process everything as a string
 $css_array = array_map('ltrim', explode("\n", $css));
 
 $ncss = array();
 
 foreach ($css_array as $data) {
 
 if(!ereg('^;', $data)) {
 
 //  Make indents
 $data = (preg_match('/({|}|,)/', $data) && !ereg('^(font)', $data)) ? str_replace(': ', ':', $data) : '    ' . $data;
 
 // Remove space after ':' in URL's
 $data = preg_replace("/(http:)(\s)/", '\\1', $data);
 
 // Add to new array
 $ncss[] = $data;
 
 // Free some memory
 unset($data);
 }
 }
 
 // Free some memory
 unset($css_array);
 
 // Correct selectors with no content (removes the ';' previously added)
 $css = preg_replace("/({)\n(\s){4};\n(})/s", "\\1 \\3", implode("\n", $ncss));
 
 // Free some memory
 unset($ncss);
 
 return rtrim($css);
 }
 
 
 } // end of class 'CssShrink'
 ?>
 |