/classes/core/StaticTools/dev/StaticTools_dev.php
PHP | 1446 lines | 863 code | 124 blank | 459 comment | 221 complexity | ec932d5cc03df815fbf78110a804b88f MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- <?php
- class StaticTools{
- /**
- * inherits the contents of self::$options recursively
- * @param string $class
- * @param int|string $recursionLimit either a className to stop looking after, or a number of classes. Pass 0 for no limit.
- * @param boolean $applyToParents if true, options will be recursively set on parents
- */
- public static function staticPropertiesInherit($class=null, $recursionLimit = 'DoDb',$applyToParents=true){
- if(!$class){$class = get_called_class();}
- if(!isset(self::$_inherited[$class])){
- $props = array();
- $ancestors = self::ancestors($class,$recursionLimit);
- if($ancestors){
- $ancestors = array_reverse($ancestors);
- while($ancestors){
- $className = array_shift($ancestors);
- $ancestorProps = self::getStaticProperties($className);
- $props = self::extendArray($props, $ancestorProps);
- if($applyToParents || !$ancestors){
- self::$options[$className] = $props;
- self::$_inherited[$className] = true;
- }
- }
- }
- }
- }
- /**
- * Returns an option from the $options array
- **/
- private static function &staticOptionGet($option,$className=null){
- if(!$class){$class = get_called_class();}
- if(!isset(self::$_inherited[$class])){self::staticPropertiesInherit($className);}
- if(is_array($option)){
- $ref = &self::$options[$className];
- while($option){
- $key = array_shift($option);
- if(array_key_exists($key,$ref) && is_array($ref[$key])){
- $ref = &$ref[$key];
- }else{
- return null;
- }
- }
- return $ref;
- }
- else if(isset(self::$options[$className][$option])){return self::$options[$className][$option];}
- $null = null;
- return $null;
- }
-
- private static function staticOptionSet($option,$value,$className=null){
- if(!$class){$class = get_called_class();}
- if(!isset(self::$_inherited[$class])){self::staticPropertiesInherit($className);}
- if(is_array($option)){
- $ref = &self::$options[$className];
- while($option){
- $key = array_shift($option);
- if(array_key_exists($key,$ref)){
- if(!is_array($ref[$key])){throw new Exception('Invalid path for staticOptionSet',E_USER_ERROR); return null;}
- }else{
- $ref[$key] = array();
- }
- $ref = &$ref[$key];
- }
- if($value===null){unset($ref);}else{$ref = $value;}
- }
- self::$options[$className][$option] = $value;
- }
- /**
- * Gets inherited static variables from parent classes and actually commits the inherited data to the classe's properties.
- * This is not useful as you'd be better off calling staticOptionGet()
- **/
- private static function staticPropertiesCommit($className=null){
- if(!$class){$class = get_called_class();}
- if(!isset(self::$_inherited[$className]) || !self::$_inherited[$className]){self::inheritOptions($className);}
- if(isset(self::$options[$className])){
- $options = self::$options[$className];
- foreach($options as $property=>$value){
- if(class_exists($className) && property_exists($className, $property)){
- eval($className.'::$'.$property.'=$value;');
- };
-
- }
- }
- }
- public static function staticPropertiesGet($class=null){
- if(!$class){$class = get_called_class();}
- if(!isset(self::$_properties[$class])){
- $classRef = new ReflectionClass($class);
- self::$_properties[$class] = $classRef->getStaticProperties();
- }
- return self::$_properties[$class];
- }
-
- // <editor-fold defaultstate="collapsed" desc="constants">
- const GETSET_ASSOC_APPEND = 1;
- const GETSET_ASSOC_REPLACE = 2;
- const GETSET_ASSOC_MERGE = 4;
- const GETSET_NUM_APPEND = 8;
- const GETSET_NUM_REPLACE = 16;
- const GETSET_NUM_MERGE = 32;
- const GETSET_STRING_CONVERT = 64;
- const GETSET_STRING_REPLACE = 128;
- const GETSET_CREATE_IF_NOT_EXISTS = 256;
- const GETSET_USE_OBJECT_METHODS = 512;
- const GETSET_USE_OBJECT_CALL = 1024;
- const GETSET_USE_WILDCARD = 2048;
- const GETSET_BYPASS_CHECK = 4096;
- const ERRORS_DO_REPORT = 8192;
- const CRLF = "\n\r";
- const TAB = "\t";
-
- // </editor-fold>
- // <editor-fold defaultstate="collapsed" desc="static vars">
- static private $_throwErrorsLimit = E_USER_ERROR;
- static private $_ancestors = array();
- static protected $_instances = null;
- static protected $_log = null;
- static protected $_language = 'en_US';
- static protected $_delimiter = '/';
- static protected $_doLog = true;
- static protected $_translations = array(
- 'en_US' => array(
- 'ERRORS' => array(
-
- )
- )
- );
- static $static = array();
- protected static $_hooks = array();
- // </editor-fold>
- // <editor-fold defaultstate="collapsed" desc="static methods">
- /*******************************************************************************
- * STATIC INITIALIZATION METHODS
- ******************************************************************************/
- // <editor-fold defaultstate="collapsed" desc="static init">
- /**
- * Initiates a static class, effectively calling a kind of a "constructor" on the class.
- * Stores initialized classes so this function is called only once per class
- * @param string|array $options the options to initialize the class
- * @param string $class the class name. Defaults to StaticTools
- * @param string $method a public static method of the class. if no method is defined, internal methods will be used
- * @param string|array $mergeStatics if set, static properties passed will be merged
- * @param string|int $recursionLimit used by staticPropertyMerged
- */
- public static function staticInit($options=null,$class=null,$method=null,$mergeStatics=null,$recursionLimit='StaticTools'){
- if(!$class){$class = get_called_class();}
- if(!isset(self::$static[$class]['init'])){
- if(!isset(self::$static[$class])){self::$static[$class] = array();}
- if($options){
- if($method){$class::$method($options);}
- else if(is_string($options)){self::_staticInitString($options,$class);}
- else if(is_array($options)){self::_staticInitArray($options,$class);}
- else if(is_object($options)){self::_staticInitObject($object, $class);}
- else{self::error('ERRORS>>MAIN>>unrecognized configuration type %%config%%',E_USER_ERROR,array('config'=>(string)$options));}
- }
- if($mergeStatics){
- self::staticPropertyMerge($class, $mergeStatics, $recursionLimit, false);
- }
- self::callHook('StaticToolsHook_staticInit', $class);
- $static[$class]['init'] = true;
- }else{self::error('ERRORS>>MAIN>>class %%class%% is already initialized',E_USER_NOTICE,array('class'=>$class));}
- }
-
- protected static function _staticInitString($option,$class){
- $found = self::callHook('StaticToolsHook_staticInitString', $options=array('options'=>$string,'class'=>$class));
- if(!$found){
- self::error(
- 'ERRORS>>MAIN>>a string constructor %%string%% was passed to %%class%%, but no suitable handler was found',
- E_USER_WARNING,
- array('class'=>$class,'string'=>$option)
- );
- }
- }
- protected static function _staticInitArray(array $options,$class){
- self::callHook('StaticToolsHook_staticInitArray', $options=array('options'=>$options,'class'=>$class));
- self::array_merge_recursive(self::$static[$class], $options);
- }
- protected static function _staticInitObject($object,$class){
- self::callHook('StaticToolsHook_staticInitArray', $options=array('options'=>$object,'class'=>$class));
- $object = (array)$object;
- self::array_merge_recursive(self::$static[$class], $object);
- }
- /**
- * Merges all static properties of a class with parent classes properties
- * @param string $class the base class
- * @param string|array $properties a property to merge, or several properties. The property has to be public
- * @param string|int $recursionLimit where to stop in finding ancestors
- * @param boolean $mergeAtParents if true, parent's properties will be merged with their own parents
- * @param boolean $refresh if true, will refresh parent classes
- */
- public static function staticPropertyMerge($class,$properties,$recursionLimit='StaticTools',$mergeAtParents=false,$refresh=false){
- $ancestors = self::ancestors($class, $recursionLimit, $refresh);
- if(!is_array($properties)){$properties = array($properties);}
- if(!$mergeAtParents){
- array_shift($ancestors);
- foreach($ancestors as $parentClass){
- foreach($properties as $property){
- if(isset($parentClass::$$property)){
- self::extendArray($class::$$property, $parentClass::$$property);
- }
- }
- }
- }else{
- while($ancestors){
- $parentClass = array_pop($ancestors);
- $class = array_pop($ancestors);
- if($parentClass && $class){
- foreach($properties as $property){
- if(isset($parentClass::$$property)){
- self::extendArray($class::$$property, $parentClass::$$property);
- }
- }
- }
- }
- }
- }
- // </editor-fold>
- /*******************************************************************************
- * STATIC CONSTRUCTORS METHODS
- ******************************************************************************/
- // <editor-fold defaultstate="collapsed" desc="static constructors">
- /**
- * Allows you to return an instance of the called class;
- * This is the same as using the "new" constructor, with two advantages:<br><ol>
- * <li>it allows you to chain methods directly</li>
- * <li>it allows you to return a particular instance of the object by passing an id, thus using
- * something close to a singleton pattern</li>
- * </ul>
- * @param mixed $options constructor options. If the was previously instanciated, this does nothing
- * @param string|int $id some string to remember the object by, or an integer. This is passed by reference, so you can pass
- * a null id and get the assigned id
- * @return StaticTools
- */
- public static function getClassInstance($options=null,&$id=null,$class=null){
- if(!$class){$class = get_called_class();}
- if(!isset(self::$_instances[$class])){self::$_instances[$class] = array();}
- if($id!==null){
- if(isset(self::$_instances[$class][$id])){return self::$_instances[$class][$id]['object'];}
- return false;
- }else{
- $id = count(self::$_instances[$class]);
- }
- $object = new $class($options);
- self::$_instances[$self][$id] = array('object'=>$object);
- self::callHook('StaticToolsHook_getClassInstance', $options=array('options'=>$options,'class'=>$class,'id'=>$id,'object'=>$object));
- return $object;
- }
- /**
- * Gets the number of instances of a particular class
- * @param string $class
- * @return int
- */
- public function classInstancesCount($class=null){
- if(!$class){$class = get_called_class();}
- if(isset(self::$_instances[$class])){return count(self::$_instances[$class]);}
- return 0;
- }
- /**
- * Wrapper for getObject() that uses '_singleton' as a key.
- * Allows you to use a cached singleton for your calls
- * @param mixed $options constructor options. If the was previously instanciated, this does nothing
- * @return StaticTools
- */
- public static function singleton($options=null){
- return self::getClassInstance('_singleton', $options);
- }
- /**
- * Removes an instance from the instances pool and returns that instance
- * @param int|string|object $idOrObj either the key of the object, or the object instance itself (slower)
- * @param string $class the class type. Defaults to the object's class if an object was passed, or StaticTools
- * @return boolean|object the unset object in an array, or false if the object was not found
- */
- public static function unsetClassInstance($idOrObj,$class=null){
- $isObj = is_object($idOrObj);
- if(!$class){
- if($isObj){$class = get_class($idOrObj);}
- else{$class=get_called_class();}
- }
- if(!isset(self::$_instances[$class])){return false;}
- if($isObj){$idOrObj = array_search($idOrObj, self::$_instances[$class]);}
- if($idOrObj!==null && $idOrObj!==false && isset(self::$_instances[$class][$idOrObj])){
- $obj = self::$_instance[$class][$idOrObj];
- unset(self::$_instances[$class][$idOrObj]);
- return $obj;
- }
- return false;
- }
- // </editor-fold>
- /*******************************************************************************
- * STATIC OPTIONS
- ******************************************************************************/
- // <editor-fold defaultstate="collapsed" desc="static global options">
- /**
- * Sets or retrieves the delimiter used in paths. Defaults to '/'
- * @param string $delimiter
- * @return string
- */
- public static function delimiter($delimiter=NULL){
- if(func_num_args()){self::$_delimiter = $delimiter;}
- return self::$_delimiter;
- }
- /**
- * By defaults, returns the class name.
- * @param string $name the name to pass
- * @param string $class default to this class
- */
- public static function systemName($class=null,$name=null){
- if(!$class){$class = get_called_class();}
- if($name){self::$static[$class]['strings']['systemName'] = $name;}
- if(!isset(self::$static[$class]['strings']['systemName'])){self::$static[$class]['strings']['systemName'] = $class;}
- return self::$static[$class]['strings']['systemName'];
- }
- /**
- * Sets or Returns the singular name of the class. Defaults to the class name
- * @param string $name
- * @return string
- */
- public function singularName($name=null){
- if(!$class){$class = get_called_class();}
- if($name){self::$static[$class]['strings']['singularName'] = $name;}
- if(!isset(self::$static[$class]['strings']['singularName'])){self::$static[$class]['strings']['singularName'] = self::systemName($class,null);}
- return self::$static[$class]['strings']['singularName'];
- }
- /**
- * Sets or Returns the singular name of the class. Defaults to the class name, pluralized
- * @param string $name
- * @return string
- */
- public function pluralName($name=null){
- if(!$class){$class = get_called_class();}
- if($name){self::$static[$class]['strings']['pluralName'] = $name;}
- if(!isset(self::$static[$class]['strings']['pluralName'])){self::$static[$class]['strings']['pluralName'] = self::systemName($class,null);}
- return self::$static[$class]['strings']['pluralName'];
- }
- /**
- * Returns ancestors classes
- * @param string $class the startic class name. Defaults to this class
- * @param string|int $recursionLimit either a className to stop looking after, or a number of classes
- * @param boolean $refresh will discard cached ancestors
- * @return array an array of ancestors
- */
- public static function ancestors($class=null,$recursionLimit='StaticTools',$refresh=false){
- if(!$class){$class = get_called_class();}
- if($refresh || !isset(self::$_ancestors[$class])){
- $ancestors = array($class);
- $r = ($recursionLimit && is_int($recursionLimit))? $recursionLimit : 0;
- $n = 0;
- while($class && (!$recursionLimit || $class!=$recursionLimit) && (!$r || $n<$r)){
- $class = get_parent_class($class);
- if(isset(self::$_ancestors[$class])){
- $ancestors = array_merge($ancestors,self::$_ancestors[$class]);
- $class=null;
- }else{$ancestors[] = $class;}
- }
- self::$_ancestors[$class] = $ancestors;
- }
- return self::$_ancestors[$class];
- }
- // </editor-fold>
- // <editor-fold defaultstate="collapsed" desc="static options">
-
- /**
- * sets a static option
- * @param string $class defaults to this class
- * @param array|string $path the keys chain to get to the value
- * @param string|int $recursionLimit either a className to stop looking after, or a number of classes
- */
- public static function setStaticOption($class, $path,$value){
- if(!$class){$class = get_called_class();}
- $path = self::makePath($path);
- if(!isset(self::$static[$class])){self::$static[$class] = array();}
- $opts = &self::$static[$class];
- while($path){
- $key = array_shift($path);
- if($path && !isset($opts[$key])){
- $opts[$key] = array();
- }
- $opts = &$opts[$key];
- }
- $opts = $value;
- }
- /**
- * Unsets a static option
- * @param string $class the class name
- * @param array $path
- * @return boolean true if the value was unset, false if it was not found
- */
- public static function unsetStaticOption($class, $path){
- if(!$class){$class = get_called_class();}
- if(!isset(self::$static[$class])){return null;}
- $path = self::makePath($path);
- $opts = &self::$static[$class];
- while($path){
- $key = array_shift($path);
- if($path && isset($opts[$key])){
- if($path){$opts = &$opts[$key];}
- else{unset($opts[$key]); return true;}
- }
- }
- return false;
- }
- /**
- * returns a static option. The option is returned by reference so you can modify it.<br>
- * If the option is not found, ancestors will be searched for it until the key is found.<br>
- * If you don't want the function to look for the value in parent classes, pass 0 to the recursion limit.
- * @param string $class defaults to this class
- * @param array|string $path the keys chain to get to the value
- * @param string|int $recursionLimit either a className to stop looking after, or a number of classes
- * @param boolean $throwExceptionIfNotFound if true and the value is not found, will throw a E_USER_NOTICE
- * @return mixed the option, or null
- */
- public static function &getStaticOption($class, $path,$recursionLimit='StaticTools',$throwExceptionIfNotFound=false){
- if(!$class){$class = get_called_class();}
- $ancestors = ($recursionLimit)? self::ancestors($class, $recursionLimit) : array($class);
- $path = self::makePath($path);
- foreach($ancestors as $class){
- if(isset(self::$static[$class])){
- $_path = $path;
- $opts = &self::$static[$class];
- $valid = true;
- while($valid && $_path){
- $key = array_shift($_path);
- if(isset($opts[$key])){$opts = &$opts[$key];}
- else{$valid = false;}
- }
- if($valid){return $opts;}
- }
- }
- $null=null;
- if($throwExceptionIfNotFound){
- self::error(
- 'ERRORS>>MAIN>>%%key%% was not found in %%class%%',
- E_USER_NOTICE,
- array('key'=>implode('/',$path),'class'=>$class)
- );
- }
- return $null;
- }
- // </editor-fold>
- /*******************************************************************************
- * STATIC STRING METHODS
- ******************************************************************************/
- // <editor-fold defaultstate="collapsed" desc="translation">
- static public function t($string,array $replacements=null,$lang=null){
- if(!$lang){$lang = self::lng();}
- $path = explode('>>',$string);
- $string = array_pop($path);
- if($lang && isset(self::$_language[$lang])){
- $ref = &self::$_language[$lang];
- if($path){
- $found = true;
- while($path){
- $key = array_shift($path);
- if(isset($ref[$key])){$ref = &$ref[$key];}
- else{$found=false;break;}
- }
- }
- if($found){$string = $ref;}
- }
- if($replacements){
- $string = self::string_replace($string,$replacements);
- }
- return $string;
- }
- public static function ln($lang=null){
- if($lang){self::$_language = $lang;}
- return $lang;
- }
- public static function string_replace($string,$replacements){
- $keys = array_keys($replacements);
- foreach($keys as &$k){$k = '%%'.$k.'%%';}
- $string = str_replace($key, $replacements, $string);
- return $string;
- }
- // </editor-fold>
- /*******************************************************************************
- * STATIC ERROR REPORTING METHODS
- ******************************************************************************/
- // <editor-fold defaultstate="collapsed" desc="error reporting and debugging">
- /**
- * Logs a message in an array. This does not get printed anywhere
- * @param string $message
- * @param array $replacements
- * @param mixed $code this determines the importance of the message. The lower the more important
- * @return string the rendered message
- */
- static public function log($message=null,array $replacements=null,$code=null,$class=null){
- if(!$class){$class = get_called_class();}
- if($message){
- if(!isset(self::$_log[$class])){self::$_log[$class] = array();}
- $message = self::t($message, $replacements);
- self::$_log[$class][] = array(
- 'code' => $code,
- 'message' => $message
- );
- return $message;
- }
- }
- static public function log_get($class=null){
- if($class){return (isset(self::$_log[$class]))? self::$_log[$class]:false;}
- return self::$_log;
- }
- /**
- * Prints the debug messages in an organized list
- * @param string $class the class name
- * @param boolean $doPrint if false, will return the array without printing it. defaults to true
- * @param int $code anything lower than $code will be printed. If $code=null, everything will be printed
- * @return string the rendered log
- */
- static public function log_print($class=null,$doPrint=true,$code=null){
- $log = self::log_get($class);
- $r = '';
- if($log){
- $r.='<div class="DoLog log"><h3>'.$class.' log</h3><ul>'.self::CRLF;
- foreach($log as $l){
- if($code===null || $code>=$l['code']){
- $r.=self::TAB.'<li>'.$l['message'].'</li>'.self::CRLF;
- }
- }
- $r.='</ul></div>'.self::CRLF;
- }
- if($doPrint){echo $r;}
- return $r;
- }
- /**
- * Gets or sets the limit after which errors will throw exceptions. Defaults to E_USER_ERROR (1024)
- * @param int $n
- * @return int
- */
- static public function throwErrorsFrom($n=null){
- if($n!==null){self::$_throwErrorsLimit = $n;}
- return self::$_throwErrorsLimit;
- }
- /**
- * Logs an error and/or outputs it
- * @param string $message you can pass a translatable message, such as key>>secondKey>>message
- * @param int $error_type error type constant (defaults to E_USER_NOTICE)
- * @param array $replacements
- * @return string the rendered message
- */
- static public function error($message=NULL, $error_type=E_USER_NOTICE, array $replacements=NULL,$class=null){
- $t = debug_backtrace();
- array_shift($t);
- $trigger = array_shift($t);
- $start = array_pop($t);
- if(!$class){$class = get_called_class();}
- $system_message = $self::log('ERRORS>>MAIN>>Error %%errorType%%: Occurred in %%fileTriggered%% on line %%lineTriggered%% in function %%functionTriggered%% and started in %%fileStarted%% on %%lineStarted%% in function %%functionStarted%%, with message:%%message%%', array(
- 'fileTriggered' => $trigger['file'],
- 'lineTriggered' => $trigger['line'],
- 'functionTriggered' => $trigger['function'],
- 'fileStarted' => $start['file'],
- 'lineStarted' => $start['file'],
- 'functionStarted' => $start['function'],
- 'message' => self::t($message,$replacements),
- 'errorType' => $error_type
- ),
- $error_type,
- $class
- );
- if($error_type<=self::throwErrorsFrom()){$self::handleError($system_message,$error_type);}
- return $system_message;
- }
- /**
- * Throws an exception. Override in children
- * @param <type> $message
- * @param <type> $error_type
- */
- static public function handleError($message,$error_type){
- $found = self::callHook('StaticToolsHook_handleError', $options=array('message'=>$message,'code'=>$error_type));
- if(!$found){
- throw new Exception($message, $error_type);
- }
- }
- // </editor-fold>
- /*******************************************************************************
- * HOOKS AND EVENT LISTENERS
- ******************************************************************************/
- // <editor-fold defaultstate="collapsed" desc="hooks & events listeners">
- /**
- * Sets a hook
- * @param string $hookName
- * @param array | string $hookFunction
- */
- public static function hook($hookName,$hookFunction){
- if(!isset(self::$_hooks[$hookName])){self::$_hooks[$hookName] = array($hookFunction);}
- else{self::$_hooks[$hookName][] = $hookFunction;}
- }
- /**
- * Calls hooks
- * @param string $hook
- * @param mixed &$params parameters to pass
- * @return boolean true if the hook was found
- */
- public static function callHook($hook,&$params=null){
- if(isset(self::$_hooks[$hookName])){
- $hooks = self::$_hooks[$hookName];
- foreach($hooks as $function){
- $f = self::analyzeCallBack($function);
- $method = $f['method'];
- $obj = $f['obj'];
- switch($f['type']){
- case 'class':
- $obj::$method($params,$function['parameters']);
- break;
- case 'object':
- $obj->$method($params,$function['parameters']);
- break;
- case 'function':
- $method($params);
- break;
- default:
- self::error('ERRORS>>MAIN>>hook %%hook%% is invalid', E_USER_ERROR, array('hook'=>(string)$function));
- break;
- }
- }
- return true;
- }
- return false;
- }
- /**
- * Analyzes a callback object. Returns a string with keys: type,obj,method,parameters<br>
- * type can be 'class', 'object', 'function', for which you respectively call the function as
- * $obj::$method(), $obj->$method(), $method().<br>
- * the 'parameters' array holds whatever is left from the provided callback
- * @param string|array $callBack
- * @return array
- */
- public static function analyzeCallBack($callBack){
- $r = array(
- 'type' => null,
- 'obj' => null,
- 'method' => null,
- 'parameters'=> null
- );
- if(is_array($callBack)){
- $r['obj'] = array_shift($function);
- $r['method'] = array_shift($function);
- $r['type'] = is_string($obj) ? 'class':'object';
- $r['parameters'] = $callBack;
- }
- else if(is_string($callBack)){
- $r['type'] = 'function';
- $r['method'] = $callBack;
- }
- return $r;
- }
- // </editor-fold>
- // <editor-fold defaultstate="collapsed" desc="static plugins management">
- /**
- *
- * @param string $baseClass the class that calls the plugin
- * @param string $pluginClass the plugin name
- * @param mixed $options options to pass to the constructor
- * @param boolean $throwErrorIfAlreadyRegistered if true and the plugin has already been registered, will throw an error
- */
- public static function pluginRegisterForClass($baseClass,$pluginClass,$options=null,$throwErrorIfAlreadyRegistered=true){
- if(!isset(self::$static[$baseClass]['plugins'][$pluginClass])){
- self::$static[$baseClass]['plugins'][$pluginClass] = $options;
- }
- else if($throwErrorIfAlreadyRegistered){
- self::error('ERRORS>>PLUGINS>>Plugin %%plugin%% already registered', E_USER_WARNING, array('plugin'=>$pluginClass));
- }
- }
- /**
- *
- * @param string $baseClass the class that calls the plugin
- * @param string $pluginClass the plugin name
- * @param boolean $throwErrorIfNotExists if true and the plugin was not registered, will throw an error
- */
- public static function pluginUnregisterForClass($baseClass,$pluginClass,$throwErrorIfNotExists=false){
- if(isset(self::$static[$baseClass]['plugins'][$pluginClass])){unset(self::$static[$baseClass]['plugins'][$pluginClass]);}
- else if($throwErrorIfNotExists){
- self::error('ERRORS>>PLUGINS>>Plugin %%plugin%% was never registered', E_USER_NOTICE, array('plugin'=>$pluginClass));
- }
- }
- /**
- * Returns true if the plugin is registered to the class. It does not tell if the plugin has been initialized
- * for a particular object! For this, use pluginIsInitializedForObject()
- * @param string $baseClass
- * @param string $pluginClass
- * @return boolean
- */
- public static function pluginIsRegisteredForClass($baseClass,$pluginClass){
- return isset(self::$static[$baseClass]['plugins'][$pluginClass]);
- }
- /**
- * Returns all plugins registered for a class. This does not tell if the plugins of an object
- * have been initialized or not! For this, use pluginsGetAll()
- * @param string $baseClass
- * @return array
- */
- public static function pluginsNamesForClass($baseClass){
- if(isset(self::$static[$baseClass]['plugins'])){return self::$static[$baseClass]['plugins'];}
- return null;
- }
- /**
- * Returns the options set for a plugin
- * @param string $baseClass the class that calls the plugin
- * @param string $pluginClass the plugin name
- * @return mixed
- */
- public static function pluginOptionsForClass($baseClass,$pluginClass){
- if(isset(self::$static[$baseClass]['plugins'][$pluginClass])){return self::$static[$baseClass]['plugins'][$pluginClass];}
- return null;
- }
- /**
- * Initializes all registered plugins for a particular object
- * @param string $baseClass the class that calls the plugin
- * @param string|int $uniqueId the unique identifier of the object calling the plugin
- * @param array $initializedPlugins an array passed by reference that will be populated with the initialized plugins
- * @param boolean $throwErrorIfAlreadyRegistered if true and the plugin is already registered, will throw an error
- * @return array the initialized plugins
- */
- public static function pluginsInitializeAllForObject($baseClass,$uniqueId,&$initializedPlugins = array(),$throwErrorIfAlreadyRegistered=true){
- $plugins = self::pluginsNamesForClass($baseClass);
- if($plugins){
- foreach($plugins as $pluginClass=>$options){
- $initializedPlugins[$pluginClass] = self::pluginInitializeForObject($baseClass, $uniqueId, $pluginClass, $options, $throwErrorIfAlreadyRegistered);
- }
- }
- return $initializedPlugins;
- }
- /**
- * Creates an instance of a plugin to be used with a particular ID. If the plugin was not previously registered
- * with pluginRegister, an notice will be thrown
- * @param string $baseClass the class that calls the plugin
- * @param string|int $uniqueId the unique identifier of the object calling the plugin
- * @param string $pluginClass the plugin name
- * @param mixed $options options to pass to the constructor. Defaults to the options passed to pluginRegister()
- * @param boolean $throwErrorIfAlreadyInit if the plugin is already initialized and this is true, an error will be thrown
- * @return <type>
- */
- public static function pluginInitializeForObject($baseClass,$uniqueId,$pluginClass,$options=null,$throwErrorIfAlreadyInit=true){
- if(!isset(self::$_instances[$baseClass][$uniqueId]['plugins'])){self::$_instances[$baseClass][$uniqueId]['plugins']=array();}
- if(!isset(self::$_instances[$baseClass][$uniqueId]['plugins'][$pluginClass])){
- if(!self::pluginIsRegisteredForClass($baseClass, $pluginClass)){
- self::error(
- 'ERRORS>>PLUGINS>>plugin %%plugin%% is not registered for class %%class%%',
- E_USER_NOTICE,
- array('plugin'=>$pluginClass,'class'=>$baseClass),
- $baseClass
- );
- }
- if(!$options){$options = self::pluginOptionsForClass($baseClass, $pluginClass);}
- self::$_instances[$baseClass][$uniqueId]['plugins'][$pluginClass] = new $pluginClass($options);
- }else if($throwErrorIfAlreadyInit){
- self::error(
- 'ERRORS>>PLUGINS>>plugin %%plugin%% is already registered for class %%class%%',
- E_USER_ERROR,
- array('plugin'=>$pluginClass,'class'=>$baseClass),
- $baseClass
- );
- }
- return self::$_instances[$baseClass][$uniqueId]['plugins'][$pluginClass];
- }
- /**
- * checks if the plugin has been initialized for the object
- * @param string $baseClass the class that calls the plugin
- * @param string|int $uniqueId the unique identifier of the object calling the plugin
- * @param string $pluginClass the plugin name
- * @return boolean
- */
- public static function pluginIsInitializedForObject($baseClass,$uniqueId,$pluginClass){
- return isset(self::$_instances[$baseClass][$uniqueId]['plugins'][$pluginClass]);
- }
- /**
- * Returns a particular plugin. The plugin has to be initialized prior
- * @param string $baseClass the class that calls the plugin
- * @param string|int $uniqueId the unique identifier of the object calling the plugin
- * @param string $pluginClass the plugin name
- * @param boolean $throwErrorIfNotExists if the plugin is not initialized, and this is true, then an error will be thrown
- * @return object the plugin, or false if the plugin was not found
- */
- public static function pluginGet($baseClass,$uniqueId,$pluginClass,$throwErrorIfNotExists=true){
- if(!self::pluginIsInitializedForObject($baseClass, $uniqueId, $pluginClass)){
- if($throwErrorIfNotExists){
- self::error(
- 'ERRORS>>PLUGINS>>plugin %%plugin%% does not exist for class %%class%% with id %%id%%',
- E_USER_ERROR,
- array('plugin'=>$pluginClass,'class'=>$baseClass,'id'=>$uniqueId),
- $baseClass
- );
- }
- return false;
- }
- return self::$_instances[$baseClass][$uniqueId]['plugins'][$pluginClass];
- }
- /**
- * Returns all initialized plugins objects
- * @param string $baseClass the class that calls the plugin
- * @param string|int $uniqueId the unique identifier of the object calling the plugin
- * @return array an array of plugins objects
- */
- public static function pluginsGetAll($baseClass,$uniqueId){
- return isset(self::$_instances[$baseClass][$uniqueId]['plugins'])?self::$_instances[$baseClass][$uniqueId]['plugins']:null;
- }
- /**
- * Checks if the plugin has the provided method
- * @param string $baseClass the class that calls the plugin
- * @param string|int $uniqueId the unique identifier of the object calling the plugin
- * @param string $pluginClass the plugin name
- * @param string $method_name the method name
- * @param boolean $throwErrorIfNotExists if the plugin is not initialized, and this is true, then an error will be thrown
- * @return boolean
- */
- public static function pluginHasMethod($baseClass,$uniqueId,$pluginClass,$method_name,$throwErrorIfNotExists=true){
- if(!self::pluginIsInitializedForObject($baseClass, $uniqueId, $pluginClass)){
- if($throwErrorIfNotExists){
- self::error(
- 'ERRORS>>PLUGINS>>plugin %%plugin%% does not exist for class %%class%% with id %%id%%',
- E_USER_ERROR,
- array('plugin'=>$pluginClass,'class'=>$baseClass,'id'=>$uniqueId),
- $baseClass
- );
- }
- return false;
- }
- return method_exists(self::$_instances[$baseClass][$uniqueId]['plugins'][$pluginClass], $method_name);
- }
- /**
- * Runs a method on the plugin
- * @param string $baseClass the class that calls the plugin
- * @param string|int $uniqueId the unique identifier of the object calling the plugin
- * @param string $pluginClass the plugin name
- * @param string $method_name the method name
- * @param object $obj the object calling the method
- * @param mixed $args arguments for the method
- * @param boolean $throwErrorIfNotExists
- * @return mixed the result of the function
- */
- public static function pluginRunMethod($baseClass,$uniqueId,$pluginClass,$method_name,$obj,&$args=null,$throwErrorIfNotExists=true){
- if(self::pluginHasMethod($baseClass, $uniqueId, $pluginClass, $method_name, $throwErrorIfNotExists)){
- $return = null;
- self::$_instances[$baseClass][$uniqueId]['plugins'][$pluginClass]->$method_name($args,$obj,$return);
- return $return;
- }
- return null;
- }
- /**
- * Either cycles through all plugins, calling $method on each of them, or returns the value of the first method found
- * @param string $baseClass the base class
- * @param int|string uniqueID the identifier of the object. You can use the same identifier for multiple objects, if it not
- * important to create a new instance of the plugins for each object
- * @param string $method the name of the method the method will receive two arguments: $args, and $this (the current object)
- * @param object $obj the object running the plugins
- * @param mixed $args arguments to be passed to the method
- * @param boolean $stopOnSuccess if true, will stop when it finds the method on any plugin
- * @return mixed the result of the first plugin to have the method if $stopOnSuccess, or nothing
- */
- public static function pluginRunAll($baseClass,$uniqueId,$method,$obj,&$args=null,$stopOnSuccess=false){
- $plugins = self::pluginsGetAll($baseClass, $uniqueId);
- $return = null;
- if($plugins){
- foreach($plugins as $plugin){
- if(method_exists($plugin, $method)){
- $plugin->$method($args,$obj,$return);
- if($stopOnSuccess){return $return;}
- }
- }
- }
- }
- /**
- * This method will attempt to run the method on the calling object first, then will cycle through all plugins
- * until it finds the method. The results of the method are then cached so any subsequent calls to this method
- * return the same result.
- * @param string $baseClass the base class
- * @param int|string uniqueID the identifier of the object. You can use the same identifier for multiple objects, if it not
- * important to create a new instance of the plugins for each object
- * @param string $method the name of the method the method will receive two arguments: $args, and $this (the current object)
- * @param object $obj the object running the plugins
- * @param mixed $args arguments to be passed to the method
- * @param boolean $stopOnSuccess if true, will stop when it finds the method on any plugin
- * @param boolean $refresh if true, discards the previous result and refreshes the cache
- * @return mixed
- */
- public static function pluginRunMethodCached($baseClass,$uniqueId,$method_name,$obj,&$args=null,$stopOnSuccess=false,$refresh=false){
- if($refresh || !isset(self::$_instances[$baseClass][$uniqueId]['cache'][$method_name])){
- if(method_exists($obj, $method_name)){
- $result = $obj->$method_name($args);
- }else{
- $result = false;
- $plugins = self::pluginsGetAll($baseClass, $uniqueId);
- if($plugins){
- foreach($plugins as $plugin){
- if(method_exists($plugin, $method)){
- $plugin->$method($args,$obj,$result);
- if($stopOnSuccess){break;}
- }
- }
- }
- }
- self::$_instances[$baseClass][$uniqueId]['cache'][$method_name] = $result;
- }
- return self::$_instances[$baseClass][$uniqueId]['cache'][$method_name];
- }
- /**
- * Checks if the class has that method, taking into account all registered plugins
- * @param string $baseClass the base class
- * @param int|string uniqueID the identifier of the object. You can use the same identifier for multiple objects, if it not
- * important to create a new instance of the plugins for each object
- * @param string $method the name of the method the method will receive two arguments: $args, and $this (the current object)
- * @param object $obj the object with plugins
- * @return boolean|string if the method is found on the object, true will be returned; if the method is found on a plugin, the
- * plugin name is returned. If the method is not found at all, false is returned
- */
- public static function classHasMethod($baseClass,$uniqueId,$method_name,$obj){
- if(method_exists($obj, $method_name)){return true;}
- $plugins = self::pluginsGetAll($baseClass, $uniqueId);
- if($plugins){
- foreach($plugins as $plugin){
- if(method_exists($plugin, $method)){
- return $plugin;
- }
- }
- }
- return false;
- }
- // </editor-fold>
- /*******************************************************************************
- * PATH MANAGEMENT FOR ARRAYS
- ******************************************************************************/
- // <editor-fold defaultstate="collapsed" desc="path management">
- /**
- * Explodes a string path into chunks, according to delimiter()
- * @param array|string $path
- * @param array $prepent prepends values to the path
- * @param string $delimiter leave this empty to use the default delimiter
- * @return array
- */
- static public function makePath(&$path,array $prepend=NULL,$delimiter=null){
- if(!is_array($path) && $path){$path = explode(($delimiter? $delimier : self::$_delimiter), $path);}
- if($prepend){$path = ($path) ? array_merge($prepend,$path):$prepend;}
- return $path;
- }
- // </editor-fold>
- /*******************************************************************************
- * ARRAY FUNCTIONS
- ******************************************************************************/
- // <editor-fold defaultstate="collapsed" desc="array management">
- /**
- * Gets a value by a certain path.
- * @param string $path
- * @param array $array
- * @param binary $flags<br/> Available flags:<pre>
- * StaticTools::GETSET_ASSOC_APPEND If an associative array is found, the new value will be appended: ('a'=>1) becomes ('a'=>array(1,2))
- * StaticTools::GETSET_ASSOC_REPLACE If an associative array is found, the new value will replace itL ('a'=>1) becomes ('a'=>2)
- * StaticTools::GETSET_ASSOC_MERGE If an associating array is found, both values will be merged. This will mostly yield to the same results
- * as GETSET_ASSOC_APPEND, but can differ. Uses array_merge_recursive().
- * StaticTools::GETSET_NUM_APPEND If a numeric array is found, the new value will be appended: (0=>'a') becomes (0=>'a',1=>'b')
- * StaticTools::GETSET_NUM_REPLACE If an associative array is found, the new value will replace itL (1=>'a') becomes (1=>'b')
- * StaticTools::GETSET_NUM_MERGE If an associating array is found, both values will be merged: (0=>'a') becomes (0=>array('a', 'b')).
- * StaticTools::GETSET_STRING_CONVERT
- * StaticTools::GETSET_STRING_REPLACE
- * StaticTools::GETSET_CREATE_IF_NOT_EXISTS
- * StaticTools::GETSET_USE_OBJECT_METHODS
- * StaticTools::GETSET_USE_OBJECT_CALL
- * StaticTools::GETSET_USE_WILDCARD
- * StaticTools::GETSET_BYPASS_CHECK
- * StaticTools::ERRORS_DO_REPORT
- * </pre>
- * @param string $wildcard defaults to '*'
- * @return array | mixed the array retrieved
- */
- static public function &getByPath(array $path, array &$array, $flags=NULL, $wildcard = '*'){
- if(!$flags){$flags = StaticTools::GETSET_USE_WILDCARD;}
- $return = NULL;
- $doUseWildcard = $flags & StaticTools::GETSET_USE_WILDCARD;
- if(!$path){return $array;}
- $r = &$array;
- while($path){
- $p = array_shift($path);
- if($doUseWildcard && $p===$wildcard){
- if(is_array($r)){
- $return = array();
- foreach($r as $k=>$v){
- $return[$k] = & static::getByPath($path, $r[$k], $flags, $wildcard);
- }
- return $return;
- }
- }
- if(isset($r[$p]) && is_array($r)){
- $r = &$r[$p];
- }
- else{
- $doReportErrors = $flags & StaticTools::ERRORS_DO_REPORT;
- if($doReportErrors){self::error('ERRORS>>MAIN>>key %%key%% was not found', E_USER_NOTICE, array('key'=>$p));}
- return $return;
- }
- }
- return $r;
- }
- static public function unsetByPath(array $path, array &$array, $flags=NULL, $wildcard = '*'){
- if(!$flags){$flags = StaticTools::GETSET_USE_WILDCARD;}
- $return = NULL;
- $doUseWildcard = $flags & StaticTools::GETSET_USE_WILDCARD;
- if(!$path){return $array;}
- $r = &$array;
- while($path){
- $p = array_shift($path);
- if($doUseWildcard && $p===$wildcard){
- if(is_array($r)){
- $return = array();
- foreach($r as $k=>$v){
- $return[$k] = static::unsetByPath($path, $r[$k], $flags, $wildcard);
- }
- return $return;
- }
- }
- if(isset($r[$p])){
- if(!$path){
- $return = $r[$p];
- unset($r[$p]);
- if(count($r)==0){$r = NULL;}
- return $return;
- }
- $r = &$r[$p];
- }
- else{
- $doReportErrors = $flags & StaticTools::ERRORS_DO_REPORT;
- if($doReportErrors){
- self::error('ERRORS>>MAIN>>key %%key%% was not found', E_USER_NOTICE, array('key'=>$p));
- }
- return $return;
- }
- }
- }
- static public function _setByPath(array $path, &$array, $value, $flags=NULL, $object=NULL){
- if($flags===NULL){
- $flags = StaticTools::ERRORS_DO_REPORT |
- StaticTools::GETSET_STRING_REPLACE |
- StaticTools::GETSET_STRING_CONVERT |
- StaticTools::GETSET_ASSOC_MERGE |
- StaticTools::GETSET_NUM_APPEND |
- StaticTools::GETSET_CREATE_IF_NOT_EXISTS;
- }
- $doReportErrors = $flags & StaticTools::ERRORS_DO_REPORT;
- $r = &$array;
- while($path){
- $p = array_shift($path);
- if($path){
- if(!isset($r[$p])){
- $doCreateIfNotExists = $flags & StaticTools::GETSET_CREATE_IF_NOT_EXISTS;
- if($doCreateIfNotExists){
- $r[$p] = array();
- $r = &$r[$p];
- }else if($doReportErrors){
- self::error('ERRORS>>MAIN>>index %%key%% was not set in array', E_USER_NOTICE, array('key'=>$p));
- }else{return NULL;}
- }
- else if(is_string($r[$p])){
- $doConvertString = $flags & StaticTools::GETSET_STRING_CONVERT;
- if($doConvertString){
- $str = $r[$p];
- $r = array($p=>array(), $str);
- $r = &$r[$p];
- }else if($doReportErrors){
- self::error('ERRORS>>MAIN>>index %%key%% cannot be set on string %%string%%', E_USER_NOTICE, array('key'=>$p,'string'=>$r));
- }else{return NULL;}
- }
- else if(is_array($r[$p])){
- $r = &$r[$p];
- }
- else if($doReportErrors){
- self::error('ERRORS>>MAIN>>object %%key%% could not be set', E_USER_NOTICE, array('key'=>(string)$p));
- }
- }else if(isset($r[$p]) && is_array($r[$p])){
- if(is_numeric($p)){
- $doNumericAppend = $flags & StaticTools::GETSET_NUM_APPEND;
- $doNumericReplace = $flags & StaticTools::GETSET_NUM_REPLACE;
- $doNumericMerge = $flags & StaticTools::GETSET_NUM_MERGE;
- if($doNumericAppend){
- if($r[$p]){$r[] = $value;}
- else{$r[$p] = $value;}
- }else if($doNumericReplace){
- $r[$p] = $value;
- }else if($doNumericMerge){
- array_merge_recursive((array)$r[$p], (array)$value);
- }else if($doReportErrors){
- self::error('ERRORS>>MAIN>>value %%value%% could not be set', E_USER_NOTICE, array('value'=>$value));
- }else{
- return $object;
- }
- }else{
- $doAssocAppend = $flags & StaticTools::GETSET_ASSOC_APPEND;
- $doAssocReplace = $flags & StaticTools::GETSET_ASSOC_REPLACE;
- $doAssocMerge = $flags & StaticTools::GETSET_ASSOC_MERGE;
- if($doAssocReplace){
- $r[$p] = $value;
- }else if($doAssocAppend){
- if($r[$p]){
- $oldVal = $r[$p];
- $r[$p] = array($oldVal, $value);
- }else{
- $r[$p] = (array)$value;
- }
- }else if($doAssocMerge){
- $r[$p] = array_merge_recursive((array)$r[$p],(array)$value);
- }else if($doReportErrors){
- self::error('ERRORS>>MAIN>>value %%value%% could not be set', E_USER_NOTICE, array('value'=>$value));
- }
- }
- }else{
- $doReplaceString = $flags & StaticTools::GETSET_STRING_REPLACE;
- if(isset($r[$p])){
- if($doReplaceString){$r[$p] = &$value;}
- else{
- if($doReportErrors){
- self::error('ERRORS>>MAIN>>value %%value%% could not be replaced', E_USER_NOTICE, array('value'=>$value));
- }
- }
- }
- else{
- $r[$p] = &$value;
- }
- }
- }
- return $object;
- }
- /**
- * Merges two or more arrays
- * @param array $data the array to extend
- * @param array $extend the data to merge with
- * @param array $extend... pass as many arrays as you want
- * @return array
- */
- public static function extendArray($data,$extend){
- $arrays = func_get_args();
- $c = count($arrays);
- if($c<2){
- self::error('extendArray uses two or more arguments, only %%n%% arguments passed', E_USER_ERROR, array('n'=>$c));
- return null;
- }
- $data = array_shift($arrays);
- while($arrays){
- $extend = array_shift($arrays);
- if(is_array($data) && is_array($extend)){
- foreach($extend as $k=>$v){
- if(!isset($data[$k])){$data[$k] = $extend[$k];}
- else{
- if(is_numeric($k)){$data[] = $v;}
- else{$data[$k] = self::extendArray($data[$k],$extend[$k]);}
- }
- }
- }else if(is_array($data)){
- $data[] = $extend;
- }else if(is_array($extend)){
- array_unshift($extend, $data);
- $data = $extend;
- }else{
- $data = $extend;
- }
- }
- return $data;
- }
-
- // </editor-fold>
- /*******************************************************************************
- * FEEDING FUNCTIONS
- ******************************************************************************/
- // <editor-fold defaultstate="collapsed" desc="feeding">
- /**
- * Returns or sets the unique identifier of the object<br/>
- * This is used in debug strings mainly, but also to generate classes for the object,
- * and acts as a default for several settings.<br/>
- * defaults to the class name.<br/>
- * This method is chainable.
- * @param string $systemName
- * @return string| StaticTools
- */
- public function systemName($systemName=NULL){
- if(!func_num_args()){
- if(!isset($this->_vars['system']['name'])){$this->_vars['system']['name'] = static::systemId().'_'.$this->InstanceId();}
- return $this->_vars['system']['name'];
- }
- $this->_vars['system']['name'] = $systemName; return $this;
- }
- /**
- * Sets several options at the same time. This is used to initiate the object<br/>
- * You can pass either a string, which will set a default variable, or an array.<br/>
- * The array can be used either to set the variables directly, or get passed to the object's methods.
- * In other words, <code>
- * array('systemName'=>'something')
- * </code>
- * can either set <code>
- * systemName('something')
- * </code>
- * or
- * <code>
- * ->systemName = 'something'
- * </code>
- * You can set flags:<ul>
- * <li><strong>StaticTools::GETSET_USE_OBJECT_CALL</strong> : Will call the object's methods. If __call() is set, the function
- * will make use of it</li>
- * <li><strong>StaticTools::GETSET_USE_OBJECT_METHODS</strong> : same, but will call only native functions</li>
- * <li><strong>StaticTools::GETSET_BYPASS_CHECK</strong> : will bypass method_exists() and is_callable() functions, making the function
- * run faster</li>
- * </ul>
- * Pass either of the flags to use methods instead of pass the variables directly.<br/>
- * This method is chainable.
- * @param object $object the object to feed
- * @param array $objectVar the array to feed options to
- * @param array | string $options
- * @param int $flags
- * @return StaticTools
- */
- public static function feedObject($object,&$objectVar,$options,$flags = NULL){
- if($options){
- if(is_array($options) || is_object($options)){
- $doUseFunctions = $flags & StaticTools::GETSET_USE_OBJECT_CALL;
- $doUseMethods = $flags & StaticTools::GETSET_USE_OBJECT_METHODS;
- if($doUseFunctions || $doUseMethods){
- return self::_feedFunctions($object, $options, $flags);
- }else{
- return self::_feedArray($object, $options);
- }
- }
- else{return self::_feedString($object, $options);}
- }
- return $object;
- }
- /**
- * This function is called by feed(). For each key in the array, it will call the relevant
- * method on the object.<br/>
- * You can pass flags:<ul>
- * <li><strong>StaticTools::GETSET_USE_OBJECT_CALL</strong> : Will call the object's methods. If __call() is set, the function
- * will make use of it</li>
- * <li><strong>StaticTools::GETSET_USE_OBJECT_METHODS</strong> : same, but will call only native functions</li>
- * <li><strong>StaticTools::GETSET_BYPASS_CHECK</strong> : will bypass method_exists() and is_callable() functions,
- * thus making the function faster</li>
- * </ul>
- * @param object $object the object to run methods of
- * @param array $options
- * @param int $flags flags to pass
- * @return StaticTools the object passed
- */
- protected static function _feedFunctions($object, array $options, $flags =…
Large files files are truncated, but you can click here to view the full file