Login   Register  
PHP Classes
elePHPant
Icontem

File: namespaces.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Salvan Grégory  >  Namespaces  >  namespaces.php  >  Download  
File: namespaces.php
Role: Class source
Content type: text/plain
Description: the main file
Class: Namespaces
Load classes from defined namespaces
Author: By
Last change: Code clean
Date: 5 years ago
Size: 14,666 bytes
 

Contents

Class file image Download
<?php
ini_set('display_errors',1);
error_reporting(E_ALL);
/*
 * a mix of ArrayObject and ArrayIterator
 * created to have ArrayIterator basics functionnalities on an ArrayObject 
 * and to iterate it on it real offset
 */
class ArrayObjectIterator extends ArrayObject
	{
	
		public function __construct ($array, $flags=0, $iterator_class = "ArrayIterator")
 			{
 				parent::__construct( $array, $flags, $iterator_class );
 			}
 		public function setCurrent($index,$strict=false) { 
 			if (!array_key_exists($index,$this))return false;
 			$start=key($this);
 			if (($start == $index && $strict == false )|| $start === $index)return true;
 			if(is_int($index)) {
 				if ($index>$start) for ($i=0;$i<$index-$start;$i++) next($this);
 				else for ($i=0;$i<$start-$index;$i++) prev($this);
 				return true;
 			} else {
 				reset($this);
 				if ($strict) {
 					while (key($this)!==$index) {
 						if (next($this)===false)return false;
 					}
 					return true;
 				} else {
 					while (key($this)!=$index) {
 						if (next($this)===false)return false;
 					}
 					return true;
 				}
 			}
 		}
 		public function next(){
 			return next($this);
 		}
 		public function prev() {
 			return prev($this);
 		}
 		public function current() {
 			return current($this);
 		}
 		public function end() {
 			return end($this);
 		}
 		public function reset() {
 			return reset($this);
 		}
 		public function key() {
 			return key($this);
 		}
	}
/**
 * Class nException (modified EException) to manage Exception like errors and displays its like PHP standards messages 
 * @package namespaces
 * @subpackage nException
 * @author Salvan Gregory <dev@europeaweb.com>
 * @version 1.a
 * @copyright Copyright (c) 2008, Salvan Gregory europeaweb.com
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 */
class nException extends Exception 
{
	public static $levels = array(E_ERROR,E_WARNING,E_NOTICE);
	/*
	 * function to call if exists when method trigger() is called
	 */
	public static $trigger= array(E_ERROR  =>'shownException',
																E_WARNING=>'shownException',
																E_NOTICE =>'shownException');
	/*
	 * errors reporting:  0=> Silent mode
												1=> Show error in the current page only
												2=> Log error only
												3=> Show error in the current page and log it.
	*/
	public static $reporting=array(E_ERROR=>1,E_WARNING=>1,E_NOTICE=>2);
	/*
	 * String used as error title in logs and html
	 */
	public static $titles=array(E_ERROR=>'ERROR',E_WARNING=>'WARNING',E_NOTICE=>'NOTICE');
	/*
	 * Show or not errors in the page, overide reporting
	 */
	public static $display = true;
	/*
	 * if true, add trace to log message
	 */
	public static $log_verbose = false; 
	
  public function __construct($message, $code = 0) {
  	if (in_array($code,nException::$levels)) {
  		namespaces::$errors[$code][]=&$this;
  	} else namespaces::$errors[E_ERROR][]=&$this;
    parent::__construct($message,$code);
  }
  /**
   * method that show or/and log message and stop script execution as defined in the configuration 
   * or if an existing function is defined in the static var $trigger call this function  
   */
  public function trigger() {
  	$c=$this->getCode();
  	if (isset(nException::$trigger[$c]) && function_exists(nException::$trigger[$c])) {
  		return nException::$trigger[$c]($this);
  	}
  	//default:
  	if ($c!=E_NOTICE && $c!=E_WARNING) $c=E_ERROR; 
  	$r=nException::$reporting;
  	//we show the error:
  	if (nException::$display==true && isset($r[$c]) && ($r[$c]==1 || $r[$c] == 3)) {
  		echo $this->dump();
  	}
  	//we log the error:
  	if (isset($r[$c]) && ($r[$c]==2 || $r[$c] == 3)) {
  		$this->log();
  	}
  	//stop execution if it's an error:
  	if ($c==E_ERROR) exit();
  }
  /**
   * method to show the message
   */
  private function dump() {
  	$c=$this->getCode();
  	if (isset(nException::$titles[$c])) $title=nException::$titles[$c];
  	else $title="nException";
  	$ret= "<font size='1'><table dir='ltr' border='1' cellspacing='0' cellpadding='1'>
			<tr><th align='left' bgcolor='#f57900' colspan='5'>
					<span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span>
							".$title.": ".$this->getMessage()." in ".$this->file." on line <i>".$this->line."</i>
			</th></tr>
			<tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>
			<tr><th align='center' bgcolor='#eeeeec'>#</th>
					<th align='left' bgcolor='#eeeeec'>Line</th>
							<th align='left' bgcolor='#eeeeec'>Function</th>
							<th align='left' bgcolor='#eeeeec'>Args</th>
							<th align='left' bgcolor='#eeeeec'>Location</th></tr>
			";
			$t=$this->getTrace();
			$p=realpath('.');
			$pp=realpath('..');
			foreach ($t as $s=>$infos) {
				$f=str_replace(array($p,$pp),array('.','..'),$infos['file']);
				$args=array();
				foreach ($infos['args'] as $v) {
					$args[]=var_export($v,true);
				}
				$ret.="<tr>
				<td bgcolor='#eeeeec' align='center'>".$s."</td>
				<td bgcolor='#eeeeec' align='center'>".$infos['line']."</td>
				<td bgcolor='#eeeeec' align='left'>".$infos['function']."</td>
				<td bgcolor='#eeeeec'>".implode($args,'</br>')."</td>
				<td title='".$infos['file']."' bgcolor='#eeeeec'>".$f."</td>
				</tr>";
			
			}
			$ret.="</table></font>";
			return $ret;
  }
  /**
   * method that log the Exception
   */
  private function log() {
  	$c=$this->getCode();
  	if (isset(nException::$titles[$c])) $title=nException::$titles[$c];
  	else $title="ERROR";
  	error_log("Namespaces [$title] : ".$this->getMessage()." in file ".$this->file." :".$this->line);
  	if (nException::$log_verbose==true){
  		$message=$this->getTraceAsString();
  		$message=explode("\n",$message);
  		foreach ($message as $s) {
  			error_log("          [VERBOSE] : ".$s);
  		}
  	}
  	
  }
  public function __tostring() {
  	return $this->dump();
  }
  /**
   * launch the Exception $exception and trigger it to fake an user defined error 
   */
  public static function nError($exception) {
  	try {
  		throw $exception;
  	} catch (Exception $e) {
  		$e->trigger();
  	}
  }
}

 /** 
 * Main class: include or require files in a name space.
 * @package namespaces
 * @author Salvan Gregory <dev@europeaweb.com>
 * @version 1.0
 * @copyright Copyright (c) 2008, Salvan Gregory europeaweb.com
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
 class namespaces extends ArrayObjectIterator
 	{
 		// arrays to store functions and classes names:
 		private static $func=array(),$class=array();
 		//the unique instance of the class:
 		private static $__;
 		//errors :
 		public static $errors=array(E_ERROR=>array(), E_WARNING=>array(), E_NOTICE=>array());
 		//whether or not to fix called functions and new objects in the namespace they are loaded: 
 		public static $static=false;
 		//if false try to load functions or classes from others namespaces when they're not in the current: 
 		public static $strict=false;
 		/**
 		 * private constructor to allow only one instance
 		 */
 		private  function namespaces ()
 			{
 				parent::__construct(array('GLOBAL'),ArrayObject::ARRAY_AS_PROPS);
 			}
 		/**
 		 * public static constructor
 		 */
 		public static function create()
 			{
 				if (!isset(self::$__)) {
        	self::$__= new namespaces();
        } else nException::nError(new nException('An instance of namespace is already defined !',E_NOTICE));
      	return self::$__;
 			}
 		/**
 		 * disallow clone
 		 */
 		protected function __clone() {}
 		
 		public static function use_namespace($index) {
 			if(!is_int($index)) {
 				$r=array_keys((array) self::$__ ,$index);
 				if (isset($r[0]))$index = $r[0];
 				else return false;
 			}
 			return self::$__->setCurrent($index);
 		}
 		
 		public static function get_namespace() {
			$r = current(self::$__);
			if ($r==false) {
				self::use_namespace('GLOBAL');
				return 'GLOBAL';
			} else return $r;
		}
		
		public static function set_namespace($namespace) {
			if (is_string($namespace) && !in_array($namespace, (array) self::$__)) {
				self::$__[]=$namespace;
			}
 			use_namespace($namespace);
		}
		private static function load_file_into_namespace($file,$namespace=false,$static=-1) {
			if ($namespace===false) $namespace=self::get_namespace();
 			else self::set_namespace($namespace);
 			if (!is_bool($static))$static= is_bool(self::$static) ? self::$static :false; 
			if (file_exists($file))$fp=file_get_contents($file);
			else throw new nException('File "'.$file.'" doesn\'t exist !',E_WARNING);
			preg_match_all('@(?<!public|static|private|protected)\s+function\s+(\w+)@',$fp,$res);
			preg_match_all('@class\s+(\w+)@',$fp,$res1);
			$rep =' '.$namespace.'_';
			$f=isset($res[1]) ? array_unique( $res [1] ):array();
			$c=isset($res1[1])? array_unique( $res1[1] ):array();
			$res = implode('|',$f).'|'.implode('|',$c);
			if ($static) {
				//we add the namespace prefix before each functions and classes names:
				$mask='@[\s\n\(\=](?='.$res.'[\s\(])@';
			} else {
				//we add the namespace prefix before functions and classes declarations only:
				$mask='@(?<=function|class)\s+(?='.$res.'[\s\(])@';
			}
			//we clean the code :
			$fp=preg_replace(array('@<\?php@',$mask),array('',$rep),$fp);
			//we load classes and functions with their prefix :
 			if (@eval($fp)=== false){
 				throw new nException('Can\'t evaluate the code of file '.$file.' !',E_WARNING);
 			}
 			//for each class name we create a generic class and add the name to the static var $class:
			foreach ($c as $cl) {
				self::add_class($cl,$namespace);
			}
			// for each function name we create a generic function and add the name to the static var $func: 
			foreach ($f as $func) {
				self::add_func($func,$namespace);
			}
		}
 		public static function require_to_namespace($file,$namespace=false,$static=-1) 
 			{
				self::load_file_into_namespace($file,$namespace,$static);
 			}
 		public static function include_to_namespace($file,$namespace=false,$static=-1)
 			{
				try {
 					self::load_file_into_namespace($file,$namespace,$static);
 				} catch (Exception $e) {
 					$e->trigger();
 				}
 			}	
 		public static function get_class_name($name) 
 			{
		 		$nm=self::get_namespace().'_'.$name;
 				if (isset(namespaces::$class[$nm])) return $nm;
 				elseif(namespaces::$strict==false) {
 					$cl=array_keys(self::$class,$name,true);
 					$ret=reset($cl);
 					while ($ret!=false && !class_exists($ret)) $ret=next($cl);
 					if ($ret!=false) return $ret;
 				}
				nException::nError(new nException('Class '.$name.' not defined in namespace '.$nm.'!',E_NOTICE));
				return false;
 			}

 		public static function get_func_name($name)
 			{
 				$nm=self::get_namespace().'_'.$name;
 				if (isset(self::$func[$nm])) return $nm;
 				elseif(self::$strict==false) {
 					$f=array_keys(self::$func,$name,true);
 					$f = current($f);
 					if ($f!=false) return $f;
 				}
 				nException::nError(new nException('Function '.$name.' not defined in namespace '.$nm.'!',E_NOTICE));
				return false;
 			}
 			
 		public static function add_class($classname, $namespace=false) {
 			if ($namespace==false) $namespace=self::get_namespace();
 			self::set_namespace($namespace);
			if (!isset(self::$class[$namespace.'_'.$classname])){
				if(!class_exists($classname)) eval(_create_abstractClass($classname));
				else nException::nError(new nException('Class '.$classname.' is already defined !',E_NOTICE));
				self::$class[$namespace.'_'.$classname]=$classname;
			}
 		}
 		
 		public static function add_func($funcname, $namespace=false) {
 			if ($namespace==false) $namespace=self::get_namespace();
 			self::set_namespace($namespace);
 			if (!isset(self::$func[$namespace.'_'.$funcname])){
				if(!function_exists($funcname)) eval(_create_abstractFunction($funcname));
				else nException::nError(new nException('Function '.$funcname.' is already defined !',E_NOTICE));
				self::$func[$namespace.'_'.$funcname]=$funcname;
			}
 		}
 	}//end of class namespaces


abstract class _abstractClass 
	{
 		public $_this;
 		function _abstractClass () {
 			$args = func_get_args();
 			$cl=get_class($this);
 			$name=namespaces::get_class_name($cl);
 			if ($name==false || $name==$cl || !class_exists($name)) { 
 				nException::nError(new nException('Class '.$cl.' is not defined in a namespace !',E_WARNING));
 			}
 			$arg=implode('],$args[',array_keys($args));
 			if ($arg!='') $arg='$args['.$arg.']';
 			$this->_this= @eval('return new '.$name."(".$arg.");");
 			if ($this->_this===false) { 
 				nException::nError(new nException('Class '.$cl.'('.$name.') error while creating the object !',E_ERROR));
 			}
 		}
		public function __set($n,$v) {
			$this->_this->$n=$v;
		}
		public function &__get($n) {
			return $this->_this->$n;
		}
		public function __call($f,$a) {
 			renameObj($this);
			return call_user_func_array(array($this->_this,$f),$a);
		}
	}
	


function _create_abstractClass ($cl) {
	return '
		class '.$cl.' extends _abstractClass {
			public static function create() {
				$args = func_get_args();
 				$name=namespaces::get_class_name("'.$cl.'");
 				$arg=implode(\'],$args[\',array_keys($args));
 				if ($arg!="")$arg=\'$args[\'.$arg.\']\';
 				return @eval("return new ".$name."(".$arg.");"); 
			}
		};';	
}
	
function _create_abstractFunction ($func) {
	return '
		function '.$func.'() {
			$args = func_get_args();
			$nm=namespaces::get_func_name("'.$func.'");
			if (function_exists($nm))return call_user_func_array($nm,$args);
			else {
				nException::nError(new nException("Function '.$func.' not defined in a namespace !",E_WARNING));
			}
		}';	
}
 	
 function use_namespace($namespace) {
 	return namespaces::use_namespace($namespace);
}

function get_namespace() {
		return namespaces::get_namespace();	
}

function set_namespace($namespace) {
		return namespaces::set_namespace($namespace);	
}

function require_to_namespace($file,$namespace=false,$static=-1) {
	namespaces::require_to_namespace($file,$namespace,$static);
} 
function include_to_namespace($file,$namespace=false,$static=-1) {
	namespaces::include_to_namespace($file,$namespace,$static);
} 
function renameObj($obj=false) {
	if ($obj!==false && is_object($obj)) {
		$k=array_keys($GLOBALS, $obj, true);
		foreach ($k as $key) {
			if (isset($obj->_this))$GLOBALS[$key]=&$obj->_this;
		}
	} else {
		foreach ($GLOBALS as $k=>$v) {
			if (is_object($v) && isset($v->_this))$GLOBALS[$k]=&$v->_this;
		}
	}
}
 
 /**
  * init namespaces
  * default namespace is GLOBAL (current($__) return 'GLOBAL')
  */
 $_ENV['__NAMESPACES__']= $__ = namespaces::create();
 
 
 
?>