Location: PHPKode > projects > Simple Way to Usenet > libs/core/misc/configs.class.php
<?php
/**
 *  
 * @author  Benjamin Gillissen <hide@address.com>
 * 
 *	**************************************************************

	Copyright (C) 2009  Benjamin Gillissen
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details at:
	http://www.gnu.org/copyleft/gpl.html

 *	**************************************************************
 */
class configs {
	
	const speed = TRUE;
	private static $CONF=Array();
	private static $LOADED=Array();
	private static $OVERLAY=Array();
	

	public static function get($file, $ref=NULL, $subs=NULL, $type='opt'){
		//echo "Config::get($file, $ref, ".print_r($subs, TRUE).")<br/>";
		$base = self::read($file, $type);
		if ( isset(self::$OVERLAY[$file]) ){
			//echo "Overlay is present<br/>"; 
			$over = &self::$OVERLAY[$file]; 
		} else {
			$over = Array();
		}
		if ( $base === FALSE ){
			//echo 'nobase<br/>'; 
			return FALSE; 
		}
		if ( $ref === NULL ){ return array_merge($over, $base); }
		if ( !isset($base[$ref]) AND !isset($over[$ref]) ){
			//echo 'nobase, noover a first level<br/>'; 
			return FALSE; 
		}
		if ( $subs === NULL ){
			
			if ( isset($over[$ref]) ){
				if ( is_array($over[$ref]) ){
					if ( isset($base[$ref]) ){ return array_merge($base[$ref], $over[$ref]); }
				} 
				return $over[$ref]; 
			}
			if ( !isset($base[$ref]) ){ return FALSE; }
			return $base[$ref];
			 
		} elseif ( !is_array($subs) ){
			//echo 'subs is not an array<br/>';
			if ( isset($over[$ref][$subs]) ){
				//echo 'returning overlay value<br/>'; 
				return $over[$ref][$subs]; 
			} 
			if ( !isset($base[$ref][$subs]) ){
				//echo 'returning false, not set<br/>'; 
				return FALSE; 
			}
			//echo 'returning base value<br/>';
			return $base[$ref][$subs];
			 
		} else {
			
			if ( isset($base[$ref]) ){ $btmp = $base[$ref]; } else { $btmp = Array(); }
			if ( isset($over[$ref]) ){ $otmp = $over[$ref]; }
			unset($base);
			//echo 'Recursive search for '.print_r($subs, TRUE)."<br/>\n";
			foreach($subs as $depth => $key ){
				if ( isset($btmp[$key]) ){ 
					$btmp = $btmp[$key]; 
				} else { 
					unset($btmp); 
				}
				//echo "$depth] $key checking overlay<br/>\n";
				if ( isset($otmp[$key]) ){ 
					$otmp = $otmp[$key]; 
				} else { 
					unset($otmp); 
				}
			}
			if ( isset($otmp) ){ return $otmp; }
			if ( isset($btmp) ){ return $btmp; }
			return FALSE;
			
		}
	}
	
	public static function set($file, $ref, $val, $subs=NULL, $type='opt'){
		//define new value into overlay, will not set something that is set in file conf, 
		//but check only last depth. so i can define new channel
		$base = self::read($file, $type);
		if ( $subs === NULL ){

			if ( isset($base[$ref]) ){
				if ( !is_array($base[$ref]) OR !is_array($val) ){
					//errors::raise('Configuration runtime overwrite is not allowed !', CORE_LOG_ERROR, 'CONF');
					return FALSE;
				}
			}
			self::$OVERLAY[$file][$ref] = $val;
			return TRUE;
				
		} elseif ( !is_array($subs) ){
			
			if ( isset($base[$ref][$subs]) ){ 
				errors::raise('Configuration runtime overwrite is not allowed !', CORE_LOG_ERROR, 'CONF');
				return FALSE; 
			}
			self::$OVERLAY[$file][$ref][$subs] = $val;
			return TRUE;
			
		} else {
			
			if ( isset($base[$ref]) ){ $btmp = $base[$ref]; } else { $btmp = Array(); }//$btmp = $base[$ref];
			unset($base);
			foreach($subs as $depth => $key ){
				if ( isset($btmp[$key]) ){ $btmp = $btmp[$key]; } else { unset($btmp); }
			}
			if ( isset($btmp) ){
				errors::raise('Configuration runtime overwrite is not allowed !', CORE_LOG_ERROR, 'CONF');
				return FALSE;
			}
			if ( !isset(self::$OVERLAY[$file][$ref]) ){	self::$OVERLAY[$file][$ref] = Array(); }
			$tmp = & self::$OVERLAY[$file][$ref];
			foreach($subs as $depth => $key ){
				if ( $depth == count($subs)-1 ){
					$tmp[$key] = $val;
					return TRUE; 
				} elseif ( !isset($tmp[$key]) ){ 
					$tmp[$key] = Array(); 
				}
				$tmp = & $tmp[$key];
			}
		}
		
		return FALSE;
	}
	
	private static function read($file, $type='opt'){
		if ( isset(self::$LOADED[$file]) ){
			if ( self::$LOADED[$file] === FALSE ) {
				return FALSE; 
			} elseif (self::speed ){
				return unserialize(self::$CONF[$file]);
			}
		}
		if ( $type === 'opt' ){
			$p = CORE::getdeps(PATH_OPTS, $file, NULL, 'opt', 'php');
		} elseif ( $type === 'cnf' ){
			$p = CORE::getdeps(PATH_OPTS, $file, NULL, 'cnf', 'php');
		} else {
			errors::raise("Option : Invalid file type '$type', only 'opt' and 'cnf' are valid !", CORE_LOG_ERROR, 'CONF');
			return FALSE; 
		}
		if ( FALSE === $p ){ 
			//echo "config: $file notfound, send event<br/>\n";
			self::$LOADED[$file] = FALSE;
			errors::raise("Option : missing file $file.opt.php, not found in ".PATH_OPTS." !", CORE_LOG_WARNING, 'CONF');
			return FALSE; 
		} elseif ( !is_readable($p) ){ 
			//echo "config: $file noread, send event<br/>\n";
			self::$LOADED[$file] = FALSE;
			errors::raise("Option : file $file is not readable !", CORE_LOG_WARNING, 'CONF');
			return FALSE; 
		} elseif ( REDIRECT_PHP_ERRORS ){
			if ( ! assert('(FALSE !== ($buf = include($p)) )') ){
				//echo "config: $file assertfailure, send event<br/>\n";
				self::$LOADED[$file] = FALSE;
				errors::raise("Option : assert failed for file $file !", CORE_LOG_ERROR, 'CONF');
				return FALSE;
			}	
		} else {
			$buf = include($p);
		}
		self::$LOADED[$file] = is_array($buf);
		if ( FALSE === self::$LOADED[$file] ){
			errors::raise("Option : file $file didn't return an array !", CORE_LOG_ERROR, 'CONF');
			return FALSE;
		}
		if ( self::speed ){ 
			self::$CONF[$file] = serialize($buf);
			unset($buf); 
		}
		//errors::raise('Configuration : "'.$file.'" has been loaded', CORE_LOG_DEBUG, 'CONF');
		if ( self::speed ){ 
			//errors::raise("$file configuration is using ".round(strlen(self::$CONF[$file])/1024, 2)."KBytes of memory", CORE_LOG_NOTICE, 'CONF'); 
			return self::read($file, $type);
		}
		return $buf;
	}
	
	public static function loaded(){
		foreach(self::$LOADED as $file => $null){ $o[] = $file; }
		if ( !isset($o) ){ return Array(); }
		return $o;
	}
}
Return current item: Simple Way to Usenet