Changeset View
Changeset View
Standalone View
Standalone View
core/kernel/utility/factory.php
<?php | <?php | ||||
/** | /** | ||||
* @version $Id$ | * @version $Id$ | ||||
* @package In-Portal | * @package In-Portal | ||||
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. | * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. | ||||
* @license GNU/GPL | * @license GNU/GPL | ||||
* In-Portal is Open Source software. | * In-Portal is Open Source software. | ||||
* This means that this software may have been modified pursuant | * This means that this software may have been modified pursuant | ||||
* the GNU General Public License, and as distributed it includes | * the GNU General Public License, and as distributed it includes | ||||
* or is derivative of works licensed under the GNU General Public License | * or is derivative of works licensed under the GNU General Public License | ||||
* or other free or open source software licenses. | * or other free or open source software licenses. | ||||
* See http://www.in-portal.org/license for copyright notices and details. | * See http://www.in-portal.org/license for copyright notices and details. | ||||
*/ | */ | ||||
use Intechnic\InPortal\Core\kernel\utility\ClassDiscovery\ClassMapBuilder; | |||||
defined('FULL_PATH') or die('restricted access!'); | defined('FULL_PATH') or die('restricted access!'); | ||||
class kFactory extends kBase implements kiCacheable { | class kFactory extends kBase implements kiCacheable { | ||||
/** | /** | ||||
* Mapping between class name and file name | * Mapping between class name and file name | ||||
* where class definition can be found. | * where class definition can be found. | ||||
* File path absolute! | * File path absolute! | ||||
* | * | ||||
* @var Array | * @var Array | ||||
* @access protected | * @access protected | ||||
*/ | */ | ||||
protected $classMap = Array (); | protected $classMap = Array (); | ||||
/** | /** | ||||
* The PSR-4 compliant namespace-to-folder mapping. | |||||
* | |||||
* @var array | |||||
*/ | |||||
protected $namespaceMap = array(); | |||||
/** | |||||
* Map class names to their pseudo | * Map class names to their pseudo | ||||
* class names, e.g. key=pseudo_class, | * class names, e.g. key=pseudo_class, | ||||
* value=real_class_name | * value=real_class_name | ||||
* | * | ||||
* @var Array | * @var Array | ||||
* @access protected | * @access protected | ||||
*/ | */ | ||||
protected $realClasses = Array (); | protected $realClasses = Array (); | ||||
Show All 9 Lines | |||||
public function __construct() | public function __construct() | ||||
{ | { | ||||
parent::__construct(); | parent::__construct(); | ||||
spl_autoload_register(Array (&$this, 'autoload')); | spl_autoload_register(Array (&$this, 'autoload')); | ||||
} | } | ||||
/** | /** | ||||
* Configures module-based autoloader. | |||||
* | |||||
* @return void | |||||
*/ | |||||
public function configureAutoloader() | |||||
{ | |||||
if ( !$this->Application->ModuleInfo ) { | |||||
$error_msg = 'Autoloader configuration can be only performed after module information is available'; | |||||
throw new LogicException($error_msg); | |||||
} | |||||
$this->namespaceMap = array(); | |||||
foreach ( $this->Application->ModuleInfo as $module_name => $module_info ) { | |||||
if ( $module_name == 'In-Portal' ) { | |||||
continue; | |||||
} | |||||
$this->namespaceMap[$module_info['ClassNamespace']] = rtrim($module_info['Path'], '/'); | |||||
} | |||||
if ( defined('IS_INSTALL') && IS_INSTALL ) { | |||||
// During installation process all modules, because unit configs from all modules are scanned too. | |||||
$class_map_builders = ClassMapBuilder::createBuilders(); | |||||
} | |||||
else { | |||||
$class_map_builders = ClassMapBuilder::createBuilders($this->Application->ModuleInfo); | |||||
} | |||||
foreach ( $class_map_builders as $class_map_builder ) { | |||||
$class_map = $class_map_builder->get(); | |||||
$class_names = array_keys($class_map); | |||||
$this->classMap = array_merge($this->classMap, $class_map); | |||||
$this->realClasses = array_merge($this->realClasses, array_combine($class_names, $class_names)); | |||||
} | |||||
} | |||||
/** | |||||
* Sets data from cache to object | * Sets data from cache to object | ||||
* | * | ||||
* @param Array $data | * @param Array $data | ||||
* @return void | * @return void | ||||
* @access public | * @access public | ||||
*/ | */ | ||||
public function setFromCache(&$data) | public function setFromCache(&$data) | ||||
{ | { | ||||
$this->classMap = $data['Factory.Files']; | $this->classMap = $data['Factory.Files']; | ||||
$this->namespaceMap = $data['Factory.Namespaces']; | |||||
$this->realClasses = $data['Factory.realClasses']; | $this->realClasses = $data['Factory.realClasses']; | ||||
} | } | ||||
/** | /** | ||||
* Performs automatic loading of classes registered with the factory | * Performs automatic loading of classes registered with the factory | ||||
* | * | ||||
* @param string $class | * @param string $class | ||||
* @return bool|null | * @return bool|null | ||||
Show All 39 Lines | |||||
else { | else { | ||||
// PEAR-like class name | // PEAR-like class name | ||||
$class_path = null; | $class_path = null; | ||||
$class_name = $class; | $class_name = $class; | ||||
} | } | ||||
$class_path .= str_replace('_', DIRECTORY_SEPARATOR, $class_name) . '.php'; | $class_path .= str_replace('_', DIRECTORY_SEPARATOR, $class_name) . '.php'; | ||||
foreach ($this->Application->ModuleInfo as $module_name => $module_info) { | foreach ( $this->namespaceMap as $namespace_prefix => $namespace_path ) { | ||||
if ( $module_name == 'In-Portal' ) { | if ( strpos($class, $namespace_prefix) === 0 ) { | ||||
continue; | |||||
} | |||||
if ( strpos($class, $module_info['ClassNamespace']) === 0 ) { | |||||
$test_class_path = str_replace( | $test_class_path = str_replace( | ||||
str_replace('\\', DIRECTORY_SEPARATOR, $module_info['ClassNamespace']), | str_replace('\\', DIRECTORY_SEPARATOR, $namespace_prefix), | ||||
rtrim($module_info['Path'], '/'), | $namespace_path, | ||||
$class_path | $class_path | ||||
); | ); | ||||
if ( file_exists(FULL_PATH . DIRECTORY_SEPARATOR . $test_class_path) ) { | if ( file_exists(FULL_PATH . DIRECTORY_SEPARATOR . $test_class_path) ) { | ||||
return DIRECTORY_SEPARATOR . $test_class_path; | return DIRECTORY_SEPARATOR . $test_class_path; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return $this->classMap[$class] = false; | return $this->classMap[$class] = false; | ||||
} | } | ||||
/** | /** | ||||
* Gets object data for caching | * Gets object data for caching | ||||
* | * | ||||
* @return Array | * @return Array | ||||
* @access public | * @access public | ||||
*/ | */ | ||||
public function getToCache() | public function getToCache() | ||||
{ | { | ||||
ksort($this->classMap); | |||||
ksort($this->namespaceMap); | |||||
ksort($this->realClasses); | |||||
return Array ( | return Array ( | ||||
'Factory.Files' => $this->classMap, | 'Factory.Files' => $this->classMap, | ||||
'Factory.Namespaces' => $this->namespaceMap, | |||||
'Factory.realClasses' => $this->realClasses, | 'Factory.realClasses' => $this->realClasses, | ||||
); | ); | ||||
} | } | ||||
/** | /** | ||||
* Splits any mixing of prefix and | * Splits any mixing of prefix and | ||||
* special into correct ones | * special into correct ones | ||||
* | * | ||||
Show All 19 Lines | |||||
} | } | ||||
$special = isset($tmp[0][1]) ? $tmp[0][1] : ''; | $special = isset($tmp[0][1]) ? $tmp[0][1] : ''; | ||||
$prefix_special .= '.' . $special; // new2 | $prefix_special .= '.' . $special; // new2 | ||||
return Array ('prefix' => $prefix, 'special' => $special, 'prefix_special' => $prefix_special); | return Array ('prefix' => $prefix, 'special' => $special, 'prefix_special' => $prefix_special); | ||||
} | } | ||||
/** | /** | ||||
* Returns object using params specified, creates it if is required | * Returns object using params specified, creates it if is required. | ||||
* | |||||
* @param string $name Object name in factory. | |||||
* @param string $pseudo_class Pseudo class. | |||||
* @param Array $event_params Event params. | |||||
* @param Array $arguments Constructor arguments. | |||||
* | * | ||||
* @param string $name | |||||
* @param string $pseudo_class | |||||
* @param Array $event_params | |||||
* @param Array $arguments | |||||
* @return kBase | * @return kBase | ||||
* @access public | |||||
* @throws kFactoryException | |||||
*/ | */ | ||||
public function getObject($name, $pseudo_class = '', $event_params = Array (), $arguments = Array ()) | public function getObject($name, $pseudo_class = '', $event_params = Array (), $arguments = Array ()) | ||||
{ | { | ||||
$name = rtrim($name, '.'); | $name = rtrim($name, '.'); | ||||
if ( isset($this->Storage[$name]) ) { | if ( isset($this->Storage[$name]) ) { | ||||
return $this->Storage[$name]; | return $this->Storage[$name]; | ||||
} | } | ||||
$ret = $this->processPrefix($name); | $ret = $this->processPrefix($name); | ||||
if ( !$pseudo_class ) { | if ( !$pseudo_class ) { | ||||
$pseudo_class = $ret['prefix']; | $pseudo_class = $ret['prefix']; | ||||
} | } | ||||
if ( !isset($this->realClasses[$pseudo_class]) ) { | |||||
$error_msg = 'RealClass not defined for pseudo_class <strong>' . $pseudo_class . '</strong>'; | |||||
if ( $this->Application->isInstalled() ) { | |||||
throw new kFactoryException($error_msg); | |||||
} | |||||
else { | |||||
if ( $this->Application->isDebugMode() ) { | |||||
$this->Application->Debugger->appendTrace(); | |||||
} | |||||
trigger_error($error_msg, E_USER_WARNING); | |||||
} | |||||
return false; | |||||
} | |||||
if ( defined('DEBUG_MODE') && defined('DBG_FACTORY') && DBG_FACTORY && $this->Application->isDebugMode() ) { | if ( defined('DEBUG_MODE') && defined('DBG_FACTORY') && DBG_FACTORY && $this->Application->isDebugMode() ) { | ||||
$this->Application->Debugger->appendHTML('<b>Creating object:</b> Pseudo class: ' . $pseudo_class . ' Prefix: ' . $name); | $this->Application->Debugger->appendHTML('<b>Creating object:</b> Pseudo class: ' . $pseudo_class . ' Prefix: ' . $name); | ||||
$this->Application->Debugger->appendTrace(); | $this->Application->Debugger->appendTrace(); | ||||
} | } | ||||
$this->Storage[$name] = $this->makeClass($pseudo_class, $arguments); | $this->Storage[$name] = $this->makeClass($pseudo_class, $arguments); | ||||
$this->Storage[$name]->Init($ret['prefix'], $ret['special']); | $this->Storage[$name]->Init($ret['prefix'], $ret['special']); | ||||
$this->Application->EventManager->runBuildEvent($ret['prefix_special'], $pseudo_class, $event_params); | $this->Application->EventManager->runBuildEvent($ret['prefix_special'], $pseudo_class, $event_params); | ||||
Show All 21 Lines | |||||
* @access public | * @access public | ||||
*/ | */ | ||||
public function hasObject($name) | public function hasObject($name) | ||||
{ | { | ||||
return isset($this->Storage[$name]); | return isset($this->Storage[$name]); | ||||
} | } | ||||
/** | /** | ||||
* Get's real class name for pseudo class, | * Get's real class name for pseudo class, includes class file and creates class instance. | ||||
* includes class file and creates class | |||||
* instance. | |||||
* All parameters except first one are passed to object constuctor | |||||
* through mediator method makeClass that creates instance of class | |||||
* | * | ||||
* Pattern: Factory Method | * Pattern: Factory Method | ||||
* | * | ||||
* @param string $pseudo_class | * @param string $pseudo_class Pseudo class. | ||||
* @param Array $arguments | * @param array $arguments Constructor arguments. | ||||
* | |||||
* @return kBase | * @return kBase | ||||
* @access public | * @throws kFactoryException When class not found. | ||||
*/ | */ | ||||
public function makeClass($pseudo_class, $arguments = Array ()) | public function makeClass($pseudo_class, $arguments = Array ()) | ||||
{ | { | ||||
if ( !isset($this->realClasses[$pseudo_class]) ) { | |||||
$error_msg = 'RealClass not defined for "<strong>' . $pseudo_class . '</strong>" pseudo_class.'; | |||||
$error_msg .= ' Please use "<strong>php tools/build_class_map.php</strong>" to discover new classes.'; | |||||
if ( $this->Application->isInstalled() ) { | |||||
throw new kFactoryException($error_msg); | |||||
} | |||||
else { | |||||
if ( $this->Application->isDebugMode() ) { | |||||
$this->Application->Debugger->appendTrace(); | |||||
} | |||||
trigger_error($error_msg, E_USER_WARNING); | |||||
} | |||||
return false; | |||||
} | |||||
$real_class = $this->realClasses[$pseudo_class]; | $real_class = $this->realClasses[$pseudo_class]; | ||||
$mem_before = memory_get_usage(); | $mem_before = memory_get_usage(); | ||||
$time_before = microtime(true); | $time_before = microtime(true); | ||||
$arguments = (array)$arguments; | $arguments = (array)$arguments; | ||||
if ( !$arguments ) { | if ( !$arguments ) { | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Line(s) | |||||
{ | { | ||||
unset($this->classMap[$real_class]); | unset($this->classMap[$real_class]); | ||||
} | } | ||||
} | } | ||||
class kFactoryException extends Exception { | class kFactoryException extends Exception { | ||||
} | } | ||||
No newline at end of file |