PHP Classes

File: namespaces.php

Recommend this page to a friend!
  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: 15 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(); ?>