Index: branches/5.2.x/core/kernel/utility/factory.php =================================================================== diff -u -N -r13840 -r14095 --- branches/5.2.x/core/kernel/utility/factory.php (.../factory.php) (revision 13840) +++ branches/5.2.x/core/kernel/utility/factory.php (.../factory.php) (revision 14095) @@ -1,6 +1,6 @@ Files = $data['Factory.Files']; + $this->realClasses = $data['Factory.realClasses']; + $this->Dependencies = $data['Factory.Dependencies']; + } + + /** + * Gets object data for caching + * + * @access public + * @return Array + */ + public function getToCache() + { + return Array ( + 'Factory.Files' => $this->Files, + 'Factory.realClasses' => $this->realClasses, + 'Factory.Dependencies' => $this->Dependencies, + ); + } + + /** * Splits any mixing of prefix and * special into correct ones * @@ -83,115 +111,58 @@ /** - * Returns object using params specified, - * creates it if is required + * Returns object using params specified, creates it if is required * * @param string $name * @param string $pseudo_class * @param Array $event_params - * @return Object + * @param Array $arguments + * @return kBase */ - function &getObject($name,$pseudo_class='',$event_params=Array()) + function &getObject($name, $pseudo_class = '', $event_params = Array (), $arguments = Array ()) { - $name=rtrim($name,'.'); - if( isset($this->Storage[$name]) ) return $this->Storage[$name]; - $ret=$this->processPrefix($name); - if (!$pseudo_class) $pseudo_class = $ret['prefix']; + $name = rtrim($name, '.'); - if (!isset($this->realClasses[$pseudo_class])) - { - if( $this->Application->isDebugMode() ) $this->Application->Debugger->appendTrace(); - $error_level = $this->Application->isInstalled() ? E_USER_ERROR : E_USER_WARNING; - trigger_error('RealClass not defined for pseudo_class '.$pseudo_class.'', $error_level); - $false = false; - return $false; + if ( isset($this->Storage[$name]) ) { + return $this->Storage[$name]; } - if (defined('DEBUG_MODE') && defined('DBG_FACTORY') && DBG_FACTORY && $this->Application->isDebugMode()) { - global $debugger; + $ret = $this->processPrefix($name); - $debugger->appendHTML('Creating object: Pseudo class: '.$pseudo_class.' Prefix: '.$name); - $debugger->appendTrace(); + if (!$pseudo_class) { + $pseudo_class = $ret['prefix']; } - $this->Storage[$name] =& $this->makeClass($pseudo_class); - $this->Storage[$name]->Init($ret['prefix'],$ret['special'],$event_params); + if ( !isset($this->realClasses[$pseudo_class]) ) { + $error_msg = 'RealClass not defined for pseudo_class ' . $pseudo_class . ''; - $prefix=$this->Storage[$name]->Prefix; - $special=$this->Storage[$name]->Special; + if ( $this->Application->isInstalled() ) { + throw new Exception($error_msg); + } + else { + if ( $this->Application->isDebugMode() ) { + $this->Application->Debugger->appendTrace(); + } -// $event_manager =& $this->Storage['EventManager']; - $event =& $this->Application->EventManager->getBuildEvent($pseudo_class); - if($event) - { - $event->Init($prefix,$special); - foreach($event_params as $param_name=>$param_value) - { - $event->setEventParam($param_name,$param_value); + trigger_error($error_msg, E_USER_WARNING); } - $this->Application->HandleEvent($event); - } - return $this->Storage[$name]; - } - - /** - * Returns object using Variable number of params specified, - * creates it if is required - * all params after 4th are passed to object constructor - * - * @param string $name - * @param string $pseudo_class - * @param Array $event_params - * @return Object - */ - function &getObjectP($name,$pseudo_class='',$event_params=Array()) - { - $ret=$this->processPrefix($name); - if (!$pseudo_class) $pseudo_class = $ret['prefix']; - $name=rtrim($name,'.'); - if( isset($this->Storage[$name]) ) return $this->Storage[$name]; - - if (!isset($this->realClasses[$pseudo_class])) - { - if( $this->Application->isDebugMode() ) $this->Application->Debugger->appendTrace(); - $error_level = $this->Application->isInstalled() ? E_USER_ERROR : E_USER_WARNING; - trigger_error('RealClass not defined for pseudo_class '.$pseudo_class.'', $error_level); $false = false; return $false; } - if (defined('DEBUG_MODE') && defined('DBG_FACTORY') && DBG_FACTORY && $this->Application->isDebugMode()) { - global $debugger; - $debugger->appendHTML('Creating object: Pseudo class: '.$pseudo_class.' Prefix: '.$name); - $debugger->appendTrace(); + if ( defined('DEBUG_MODE') && defined('DBG_FACTORY') && DBG_FACTORY && $this->Application->isDebugMode() ) { + $this->Application->Debugger->appendHTML('Creating object: Pseudo class: '.$pseudo_class.' Prefix: '.$name); + $this->Application->Debugger->appendTrace(); } - $funs_args = func_get_args(); - array_splice($funs_args, 0, 3, Array($pseudo_class) ); + $this->Storage[$name] =& $this->makeClass($pseudo_class, $arguments); + $this->Storage[$name]->Init($ret['prefix'], $ret['special']); + $this->Application->EventManager->runBuildEvent($ret['prefix_special'], $pseudo_class, $event_params); - $this->Storage[$name] =& ref_call_user_func_array( Array(&$this,'makeClass'), $funs_args); - $this->Storage[$name]->Init($ret['prefix'],$ret['special'],$event_params); - - $prefix=$this->Storage[$name]->Prefix; - $special=$this->Storage[$name]->Special; - - $event_manager =& $this->getObject('EventManager'); - $event =& $event_manager->getBuildEvent($pseudo_class); - if($event) - { - $event->Init($prefix,$special); - foreach($event_params as $param_name=>$param_value) - { - $event->setEventParam($param_name,$param_value); - } - $this->Application->HandleEvent($event); - } - return $this->Storage[$name]; } - /** * Removes object from storage, so next time it could be created from scratch * @@ -211,18 +182,18 @@ */ function includeClassFile($real_class) { - if (class_exists($real_class)) return; - if(!isset($this->Files[$real_class])) { - trigger_error('Real Class '.$real_class.' is not registered with the Factory', E_USER_ERROR); + if ( class_exists($real_class) ) { + return; } - if(!file_exists(FULL_PATH.$this->Files[$real_class])) { - if ($this->Application->isDebugMode()) { - $this->Application->Debugger->appendTrace(); - } - trigger_error('Include file for class '.$real_class.' ('.FULL_PATH.$this->Files[$real_class].') does not exists', E_USER_ERROR); + if( !isset($this->Files[$real_class]) ) { + throw new Exception('Real Class ' . $real_class . ' is not registered with the Factory'); } + if( !file_exists(FULL_PATH . $this->Files[$real_class]) ) { + throw new Exception('Include file for class ' . $real_class . ' (' . FULL_PATH . $this->Files[$real_class] . ') does not exists'); + } + if( isset( $this->Dependencies[$real_class] ) ) { foreach($this->Dependencies[$real_class] as $dep_class_name) @@ -231,7 +202,7 @@ } } - k4_include_once(FULL_PATH.$this->Files[$real_class]); + kUtil::includeOnce(FULL_PATH.$this->Files[$real_class]); } /** @@ -242,37 +213,44 @@ * through mediator method makeClass that creates instance of class * * @param string $pseudo_class - * @return Object - * @access private + * @param Array $arguments + * @return kBase + * @access public */ - function &makeClass($pseudo_class) + public function &makeClass($pseudo_class, $arguments = Array ()) { $real_class = $this->realClasses[$pseudo_class]; - if (!class_exists($real_class)) $this->includeClassFile($real_class); + if ( !class_exists($real_class) ) { + $this->includeClassFile($real_class); + } + $mem_before = memory_get_usage(); - $time_before = getmicrotime(); + $time_before = microtime(true); - if( func_num_args() == 1 ) - { + if ( !is_array($arguments) ) { + // fallback for code, that doesn't know how to pass arguments + $arguments = Array ($arguments); + } + + if (!$arguments) { $class = new $real_class(); } - else - { - $func_args = func_get_args(); - $pseudo_class = array_shift($func_args); - $class =& ref_call_user_func_array( Array($real_class,'makeClass'), $func_args ); + else { + $reflection = new ReflectionClass($real_class); + $class = $reflection->newInstanceArgs($arguments); } - if( defined('DEBUG_MODE') && DEBUG_MODE && constOn('DBG_PROFILE_MEMORY') ) - { + + if ( defined('DEBUG_MODE') && DEBUG_MODE && defined('DBG_PROFILE_MEMORY') && DBG_PROFILE_MEMORY && $this->Application->isDebugMode() ) { $mem_after = memory_get_usage(); - $time_after = getmicrotime(); + $time_after = microtime(true); $mem_used = $mem_after - $mem_before; $time_used = $time_after - $time_before; - global $debugger; - $debugger->appendHTML('Factroy created '.$real_class.' - used '.round($mem_used/1024, 3).'Kb time: '.round($time_used, 5)); - $debugger->profilerAddTotal('objects', null, $mem_used); + + $this->Application->Debugger->appendHTML('Factroy created '.$real_class.' - used '.round($mem_used/1024, 3).'Kb time: '.round($time_used, 5)); + $this->Application->Debugger->profilerAddTotal('objects', null, $mem_used); } + return $class; } @@ -287,27 +265,54 @@ */ function registerClass($real_class, $file, $pseudo_class=null, $dependecies = Array() ) { - if(!isset($pseudo_class)) $pseudo_class = $real_class; - if (!isset($this->Files[$real_class])) { + if ( !isset($pseudo_class) ) { + $pseudo_class = $real_class; + } + + if ( !isset($this->Files[$real_class]) ) { $this->Files[$real_class] = preg_replace('/^'.preg_quote(FULL_PATH, '/').'/', '', $file, 1); } - if (isset($this->realClasses[$pseudo_class])) { + if ( isset($this->realClasses[$pseudo_class]) ) { $this->registerDependency($real_class, $pseudo_class); } - if($dependecies) - { - if (!is_array($dependecies)) $dependecies = array($dependecies); + if ($dependecies) { + if ( !is_array($dependecies) ) { + $dependecies = Array ($dependecies); + } + foreach ($dependecies as $required_class) { $this->registerDependency($real_class, $required_class); } } - $this->realClasses[$pseudo_class]=$real_class; + $this->realClasses[$pseudo_class] = $real_class; } /** + * Unregisters existing class from factory + * + * @param string $real_class Real name of class as in class declaration + * @param string $pseudo_class Name under this class object is accessed using getObject method + */ + function unregisterClass($real_class, $pseudo_class = null) + { + if ( !isset($pseudo_class) ) { + $pseudo_class = $real_class; + } + + unset($this->Files[$real_class]); + + if ( !array_key_exists($real_class, $this->Dependencies) ) { + return ; + } + + $this->realClasses[$pseudo_class] = $this->Dependencies[$real_class][0]; + unset( $this->Dependencies[$real_class] ); + } + + /** * Add $class_name to required classes list for $depended_class class. * All required class files are included before $depended_class file is included * @@ -317,15 +322,16 @@ */ function registerDependency($depended_class, $class_name) { + if ($this->realClasses[$class_name] == $depended_class) { + // same class + return ; + } + $dependencies =& $this->Dependencies[$depended_class]; + $dependency_exists = is_array($dependencies) && in_array($this->realClasses[$class_name], $dependencies); - $conditions = Array(); - $conditions['exists'] = is_array($dependencies) && in_array($this->realClasses[$class_name], $dependencies); - $conditions['same_class'] = $this->realClasses[$class_name] == $depended_class; - - if (!$conditions['exists'] && !$conditions['same_class']) { + if ( !$dependency_exists ) { $dependencies[] = $this->realClasses[$class_name]; } } - } \ No newline at end of file