Location: PHPKode > scripts > OOCSS > oocss/oocss.php
<?
/**
 * Object Oriented CSS v1.0
 * August 2, 2009
 * Corey Hart @ http://www.codenothing.com
 */ 
// Cache Directory & Debugging Mode
define('OOCSS_CACHE_DIR', dirname(__FILE__).'/cache/');
define('OOCSS_DEBUG_MODE', false);


Class ObjectOrientedCSS
{
	var $vars = array();
	var $file = '';
	var $file_path = '';
	var $cache_path = '';

	function __construct(){
		// File Path
		$this->getFilePath();

		// Cached Files are stored based on file change times of
		// this file and the file requested
		$time['file'] = date('Y-m-d H:i:s', filemtime($this->file_path));
		$time['oocss'] = date('Y-m-d H:i:s', filemtime(__FILE__));
		$this->cache_path = OOCSS_CACHE_DIR.md5($this->file_path . $time['file'] . $time['oocss']).'.css';

		// If there is no cached file, parse requested file
		if (!is_file($this->cache_path))
			$this->runParse();
	}

	function getFilePath(){
		// Use current selected path if possible
		$this->file_path = $_SERVER['DOCUMENT_ROOT'] . $_SERVER['REDIRECT_URL'];
		if (! is_file($this->file_path)){
			// See if there's a css extension of the file
			$this->file_path = preg_replace("/\.oocss$/i", '.css', $this->file_path);
			if (is_file($this->file_path)){
				return $this->file_path;
			} else {
				die('Could not find a stylesheet');
			}
		}
	}

	function runParse(){
		// Raw file trimmed down to single line
		$this->getFileContent($this->file_path);

		// Run variable conversions first
		$this->variableReplacement();

		// Loop through and create the tree
		$tree = $this->convertLoop($this->prepFileForLoop());

		// Process tree for output
		$this->file = $this->processFile($tree);

		// Cache converted file
		$this->outputFile($tree);
	}

	function getFileContent($file){
		// Trim file down to single line
		$this->file = trim(file_get_contents($file));
		$this->file = preg_replace("/\n|\r|\t/", ' ', $this->file);
		$this->file = preg_replace("/\/\*(.*?)\*\//", '', $this->file);
		$this->file = preg_replace("/\s{2,}/", ' ', $this->file);
	}

	function variableReplacement(){
		preg_match_all("/([$][a-zA-Z0-9_]+)\s*=\s*([^;]+);/", $this->file, $matches);
		for ($i=0, $imax=count($matches[0]); $i<$imax; $i++){
			// Matches
			$string = $matches[0][$i];
			$var = $matches[1][$i];
			$value = $matches[2][$i];

			// Check for multiple definitions
			if (strpos($value, '{') !== false){
				$value = str_replace('{', '', $value);
				$value = str_replace('}', '', $value);
				$value = str_replace(',', ';', $value);
			}

			// Store the var for debugging
			$this->vars[$var] = $value;

			// Remove the declaration from the file
			$this->file = str_replace($string, '', $this->file);

			// Enforce semi-colon replacement
			$this->file = str_replace($var.';', $value.';', $this->file);
		}
	}

	function prepFileForLoop(){
		// Remove all comments
		$this->file = preg_replace("/\/\*(.*?)\*\//", '', $this->file);

		// Line out as much as possible
		$this->file = preg_replace("/([{]|[}]|;)/", "$1\n", $this->file);

		// Return each line
		return explode("\n", str_replace('}', "\n}", $this->file));
	}

	function convertLoop(&$file){
		$ret = $old = array();
		while ($file){
			$line = trim(array_shift($file));
			if (!$line || $line == ''){
				continue;
			}
			else if (strpos($line, '{') !== false){
				// Take out the tag
				$tag = trim(array_shift(explode('{', $line)));

				// Store old tag for merging
				if (isset($ret[$tag]))
					$old = $ret;

				// Run recursive loop of all levels
				$ret[$tag] = $this->convertLoop($file);

				// If old tag found, merge results
				if ($old){
					$ret = array_merge_recursive($old, $ret);
					$old = array();
				}
			}
			else if (strpos($line, '}') !== false){
				return $ret;
			}
			else{
				$ret['props'][] = $line;
			}
		}
		return $ret;
	}

	function processFile($file, $tag=''){
		$levels = array();
		foreach ($file as $key => $value){
			if ($key == 'props'){
				foreach ($value as $prop)
					$str .= "\t$prop\n";
			}
			else if (is_array($value)){
				$levels[$key] = $value;
			}
		}

		// Only add string if it exists with a tag
		if (($tag = trim($tag)) && $tag != '' && $str != ''){
			// Remove Lingering direct descendent tag and trim it
			$trimedTag = trim(preg_replace('/[>]$/', '', $tag));
			$str = "$trimedTag {\n$str}\n\n";
		}

		// Loop through nested levels
		foreach ($levels as $key=>$value)
			$str .= $this->processFile($value, $tag.' '.$key);

		// Return concatenated string
		return $str;
	}

	function outputFile($tree){
		// Add commented out notes in debug mode
		if (OOCSS_DEBUG_MODE){
			$str = "/*******\nOOCSS DEBUGGING TREES\n\n";
			$str .= "Variables Stored: ";
			$str .= print_r($this->vars, true);
			$str .= "\n\nTree Parsed: ";
			$str .= print_r($tree, true);
			$str .= "******/\n\n\n\n";
			// Prepend string to file
			$this->file = $str.$this->file;
		}

		// Cache compression
		$fh = fopen($this->cache_path, 'w');
		fwrite($fh, $this->file);
		fclose($fh);
	}

	function __destruct(){
		header('Content-type: text/css');
		readfile($this->cache_path);
	}
};

new ObjectOrientedCSS;
?>
Return current item: OOCSS