Index: branches/5.2.x/core/kernel/utility/unit_config_reader.php =================================================================== diff -u -N -r14092 -r14095 --- branches/5.2.x/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 14092) +++ branches/5.2.x/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 14095) @@ -1,6 +1,6 @@ _directorySeparator = preg_quote(DIRECTORY_SEPARATOR); @@ -73,11 +71,62 @@ $this->_moduleFolderRegExp = '#' . $this->_directorySeparator . '(core|modules' . $this->_directorySeparator . '.*?)' . $this->_directorySeparator . '#'; } + /** + * Sets data from cache to object + * + * @param Array $data + * @access public + */ + public function setFromCache(&$data) + { + $this->prefixFiles = $data['ConfigReader.prefixFiles']; + } + + /** + * Gets object data for caching + * + * @access public + * @return Array + */ + public function getToCache() + { + return Array ( + 'ConfigReader.prefixFiles' => $this->prefixFiles, + ); + } + function CacheParsedData() { - $event_manager =& $this->Application->recallObject('EventManager'); $aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray'); + /* @var $aggregator kArray */ + $this->preloadConfigVars(); // preloading will put to cache + + $cache = array_merge( + $this->Application->Factory->getToCache(), + $this->getToCache(), + $this->Application->EventManager->getToCache(), + $aggregator->getToCache(), + $this->Application->getToCache() + ); + + if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { + $this->Application->setCache('master:configs_parsed', serialize($cache)); + $this->Application->setCache('master:config_files', serialize($this->configFiles)); + } + else { + $this->Application->setDBCache('configs_parsed', serialize($cache)); + $this->Application->setDBCache('config_files', serialize($this->configFiles)); + } + + $cache_rebuild_by = SERVER_NAME . ' (' . getenv('REMOTE_ADDR') . ') - ' . adodb_date('d/m/Y H:i:s'); + $this->Application->setDBCache('last_cache_rebuild', $cache_rebuild_by); + + unset($this->configFiles); + } + + function preloadConfigVars() + { $config_vars = Array ( // session related 'SessionTimeout', @@ -109,47 +158,10 @@ foreach ($config_vars as $var) { $this->Application->ConfigValue($var); } - - $cache = Array( - 'Factory.Files' => $this->Application->Factory->Files, - 'Factory.realClasses' => $this->Application->Factory->realClasses, - 'Factory.Dependencies' => $this->Application->Factory->Dependencies, - 'ConfigReader.prefixFiles' => $this->prefixFiles, - 'EventManager.buildEvents' => $event_manager->buildEvents, - 'EventManager.beforeRegularEvents' => $event_manager->beforeRegularEvents, - 'EventManager.afterRegularEvents' => $event_manager->afterRegularEvents, - 'EventManager.beforeHooks' => $event_manager->beforeHooks, - 'EventManager.afterHooks' => $event_manager->afterHooks, - 'TagsAggregator.data' => $aggregator->_Array, - - // the following caches should be reset based on admin interaction (adjusting config, enabling modules etc) - 'Application.Caches.ConfigVariables' => $this->Application->Caches['ConfigVariables'], - 'Application.ConfigCacheIds' => $this->Application->ConfigCacheIds, - 'Application.ConfigHash' => $this->Application->ConfigHash, - 'Application.ReplacementTemplates' => $this->Application->ReplacementTemplates, - 'Application.RewriteListeners' => $this->Application->RewriteListeners, - 'Application.ModuleInfo' => $this->Application->ModuleInfo, - ); - - if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { - $this->Application->setCache('master:configs_parsed', serialize($cache)); - $this->Application->setCache('master:config_files', serialize($this->configFiles)); - } - else { - $this->Application->setDBCache('configs_parsed', serialize($cache)); - $this->Application->setDBCache('config_files', serialize($this->configFiles)); - } - - $cache_rebuild_by = SERVER_NAME . ' (' . getenv('REMOTE_ADDR') . ') - ' . adodb_date('d/m/Y H:i:s'); - $this->Application->setDBCache('last_cache_rebuild', $cache_rebuild_by); - - unset($this->configFiles); } function RestoreParsedData() { - $conn =& $this->Application->GetADODBConnection(); - if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { $data = $this->Application->getCache('master:configs_parsed', false); } @@ -158,42 +170,29 @@ } if ($data) { - $cache = unserialize($data); - $this->Application->Factory->Files = $cache['Factory.Files']; - $this->Application->Factory->realClasses = $cache['Factory.realClasses']; - $this->Application->Factory->Dependencies = $cache['Factory.Dependencies']; - $this->prefixFiles = $cache['ConfigReader.prefixFiles']; + $cache = unserialize($data); // 126 KB all modules + unset($data); - $event_manager =& $this->Application->recallObject('EventManager'); - $event_manager->buildEvents = $cache['EventManager.buildEvents']; - $event_manager->beforeRegularEvents = $cache['EventManager.beforeRegularEvents']; - $event_manager->afterRegularEvents = $cache['EventManager.afterRegularEvents']; - $event_manager->beforeHooks = $cache['EventManager.beforeHooks']; - $event_manager->afterHooks = $cache['EventManager.afterHooks']; + $this->Application->Factory->setFromCache($cache); + $this->setFromCache($cache); + $this->Application->EventManager->setFromCache($cache); $aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray'); - $aggregator->_Array = $cache['TagsAggregator.data']; + /* @var $aggregator kArray */ - $this->Application->ConfigHash = $cache['Application.ConfigHash']; + $aggregator->setFromCache($cache); + $this->Application->setFromCache($cache); + unset($cache); - $this->Application->Caches['ConfigVariables'] = $cache['Application.ConfigCacheIds']; - $this->Application->ConfigCacheIds = $cache['Application.ConfigCacheIds']; - - $this->Application->ReplacementTemplates = $cache['Application.ReplacementTemplates']; - $this->Application->RewriteListeners = $cache['Application.RewriteListeners']; - - $this->Application->ModuleInfo = $cache['Application.ModuleInfo']; - return true; } - else return false; + + return false; } function ResetParsedData($include_sections = false) { - $conn =& $this->Application->GetADODBConnection(); - if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { $this->Application->deleteCache('master:configs_parsed'); } @@ -220,29 +219,31 @@ if ($cache) { $restored = $this->RestoreParsedData(); - if ($restored) return; + if ($restored) { + if ( defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode() ) { + $this->Application->Debugger->appendHTML('UnitConfigReader: Restoring Cache'); + } + + return; + } } + if ( defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode() ) { + $this->Application->Debugger->appendHTML('UnitConfigReader: Generating Cache'); + } + $this->ProcessAllConfigs = true; $this->includeConfigFiles($folderPath, $cache); $this->ParseConfigs(); - // tell AfterConfigRead to store cache if neede + // tell AfterConfigRead to store cache if needed // can't store it here beacuse AfterConfigRead needs ability to change config data $this->StoreCache = $cache; } function findConfigFiles($folderPath, $level = 0) { - /*if ($level == 0) { - if ($this->Application->isDebugMode()) { - $start_time = getmicrotime(); - $this->Application->Debugger->appendHTML('kUnitConfigReader::findConfigFiles("' . $folderPath . '")'); - $this->Application->Debugger->appendTrace(); - } - }*/ - // if FULL_PATH = "/" ensure, that all "/" in $folderPath are not deleted $reg_exp = '/^' . preg_quote(FULL_PATH, '/') . '/'; $folderPath = preg_replace($reg_exp, '', $folderPath, 1); // this make sense, since $folderPath may NOT contain FULL_PATH @@ -278,12 +279,6 @@ $this->findConfigFiles($full_path, $level + 1); } - - /*if ($level == 0) { - if ($this->Application->isDebugMode()) { - $this->Application->Debugger->appendHTML('kUnitConfigReader::findConfigFiles("' . FULL_PATH . $folderPath . '"): ' . (getmicrotime() - $start_time)); - } - }*/ } function includeConfigFiles($folderPath, $cache = true) @@ -309,11 +304,11 @@ $this->findConfigFiles($folderPath); // search from modules directory } - foreach ($this->configFiles as $filename) - { + foreach ($this->configFiles as $filename) { $prefix = $this->PreloadConfigFile($filename); + if (!$prefix) { - trigger_error('Prefix not defined in config file ' . $filename, E_USER_ERROR); + throw new Exception('Prefix not defined in config file ' . $filename . ''); } } } @@ -372,10 +367,10 @@ if ($store_cache) { $this->_sortRewriteListeners(); - + $after_event = new kEvent('adm:OnAfterCacheRebuild'); $this->Application->HandleEvent($after_event); - + $this->CacheParsedData(); if (defined('DEBUG_MODE') && DEBUG_MODE && defined('DBG_VALIDATE_CONFIGS') && DBG_VALIDATE_CONFIGS) { @@ -384,7 +379,7 @@ if (!isset($config['TableName'])) continue; $this->ValidateConfig($prefix); } - } + } } } @@ -511,105 +506,126 @@ */ function parseConfig($prefix) { + $this->parseClasses($prefix); + $this->parseAgents($prefix); + $this->parseHooks($prefix); + $this->parseAggregatedTags($prefix); + } + + protected function parseClasses($prefix) + { $config =& $this->configData[$prefix]; - $event_manager =& $this->Application->recallObject('EventManager'); - /* @var $event_manager kEventManager */ + $register_classes = $this->getClasses($prefix); - $register_classes = getArrayValue($config,'RegisterClasses'); - if (!$register_classes) $register_classes = Array(); - $class_params=Array('ItemClass','ListClass','EventHandlerClass','TagProcessorClass'); - foreach($class_params as $param_name) - { - if ( !(isset($config[$param_name]) ) ) continue; - $config[$param_name]['pseudo'] = $this->getPrefixByParamName($param_name,$prefix); - $register_classes[] = $config[$param_name]; - } + foreach ($register_classes as $class_info) { + // remember class dependencies + $class_name = $class_info['class']; + $require_classes = isset($class_info['require_classes']) ? $class_info['require_classes'] : Array (); - foreach($register_classes as $class_info) - { - $require_classes = getArrayValue($class_info, 'require_classes'); if ($require_classes) { - if (!is_array($require_classes)) { - $require_classes = array($require_classes); + $require_classes = (array)$require_classes; + + if ( !isset($config['_Dependencies'][$class_name]) ) { + $config['_Dependencies'][$class_name] = Array (); } - if (!isset($config['_Dependencies'][$class_info['class']])) { - $config['_Dependencies'][$class_info['class']] = array(); - } - $config['_Dependencies'][$class_info['class']] = array_merge($config['_Dependencies'][$class_info['class']], $require_classes); + + $config['_Dependencies'][$class_name] = array_merge($config['_Dependencies'][$class_name], $require_classes); } + // register class $this->Application->registerClass( - $class_info['class'], + $class_name, $config['BasePath'] . DIRECTORY_SEPARATOR . $class_info['file'], - $class_info['pseudo']/*, - getArrayValue($class_info, 'require_classes')*/ + $class_info['pseudo'] ); - if (getArrayValue($class_info, 'build_event')) { - $event_manager->registerBuildEvent($class_info['pseudo'],$class_info['build_event']); + + if ( isset($class_info['build_event']) && $class_info['build_event'] ) { + $this->Application->EventManager->registerBuildEvent($class_info['pseudo'], $class_info['build_event']); } } + } - $regular_events = getArrayValue($config, 'RegularEvents'); - if ($regular_events) { - foreach ($regular_events as $short_name => $regular_event_info) { - $event_status = array_key_exists('Status', $regular_event_info) ? $regular_event_info['Status'] : STATUS_ACTIVE; - $event_manager->registerRegularEvent( $short_name, $config['Prefix'].':'.$regular_event_info['EventName'], $regular_event_info['RunInterval'], $regular_event_info['Type'], $event_status); - } + protected function parseAgents($prefix) + { + $config =& $this->configData[$prefix]; + + if ( !isset($config['RegularEvents']) || !$config['RegularEvents'] ) { + return ; } - $hooks = getArrayValue($config, 'Hooks'); - if (is_array($hooks) && count($hooks) > 0) { - foreach ($hooks as $hook) { - if (isset($config['ParentPrefix']) && $hook['HookToPrefix'] == $config['ParentPrefix']) { - trigger_error('Depricated Hook Usage [prefix: '.$config['Prefix'].'; do_prefix: '.$hook['DoPrefix'].'] use #PARENT# as HookToPrefix value, where HookToPrefix is same as ParentPrefix', defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_NOTICE); - } + $regular_events = $config['RegularEvents']; - if ($hook['HookToPrefix'] == '') { - $hook['HookToPrefix'] = $config['Prefix']; // new: set hooktoprefix to current prefix if not set - } + foreach ($regular_events as $short_name => $regular_event_info) { + $event_status = array_key_exists('Status', $regular_event_info) ? $regular_event_info['Status'] : STATUS_ACTIVE; + $this->Application->EventManager->registerAgent( $short_name, $config['Prefix'] . ':' . $regular_event_info['EventName'], $regular_event_info['RunInterval'], $regular_event_info['Type'], $event_status ); + } + } - if (isset($config['ParentPrefix'])) { - // new: allow to set hook to parent prefix what ever it is - if ($hook['HookToPrefix'] == '#PARENT#') { - $hook['HookToPrefix'] = $config['ParentPrefix']; - } + protected function parseHooks($prefix) + { + $config =& $this->configData[$prefix]; - if ($hook['DoPrefix'] == '#PARENT#') { - $hook['DoPrefix'] = $config['ParentPrefix']; - } - } - elseif ($hook['HookToPrefix'] == '#PARENT#' || $hook['DoPrefix'] == '#PARENT#') { - continue; // we need parent prefix but it's not set ! - } + if ( !isset($config['Hooks']) || !$config['Hooks'] ) { + return ; + } - $do_prefix = $hook['DoPrefix'] == '' ? $config['Prefix'] : $hook['DoPrefix']; + $hooks = $config['Hooks']; - if ( !is_array($hook['HookToEvent']) ) { - $hook_events = Array( $hook['HookToEvent'] ); + foreach ($hooks as $hook) { + if ( isset($config['ParentPrefix']) && ($hook['HookToPrefix'] == $config['ParentPrefix']) ) { + trigger_error('Depricated Hook Usage [prefix: ' . $config['Prefix'] . '; do_prefix: ' . $hook['DoPrefix'] . '] use #PARENT# as HookToPrefix value, where HookToPrefix is same as ParentPrefix', defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_NOTICE); + } + + if ($hook['HookToPrefix'] == '') { + // new: set hooktoprefix to current prefix if not set + $hook['HookToPrefix'] = $config['Prefix']; + } + + if ( isset($config['ParentPrefix']) ) { + // new: allow to set hook to parent prefix what ever it is + if ($hook['HookToPrefix'] == '#PARENT#') { + $hook['HookToPrefix'] = $config['ParentPrefix']; } - else { - $hook_events = $hook['HookToEvent']; + + if ($hook['DoPrefix'] == '#PARENT#') { + $hook['DoPrefix'] = $config['ParentPrefix']; } - foreach ($hook_events as $hook_event) { - $this->Application->registerHook($hook['HookToPrefix'], $hook['HookToSpecial'], $hook_event, $hook['Mode'], $do_prefix, $hook['DoSpecial'], $hook['DoEvent'], $hook['Conditional']); - } } + elseif ($hook['HookToPrefix'] == '#PARENT#' || $hook['DoPrefix'] == '#PARENT#') { + // we need parent prefix but it's not set ! + continue; + } + + $hook_events = (array)$hook['HookToEvent']; + $do_prefix = $hook['DoPrefix'] == '' ? $config['Prefix'] : $hook['DoPrefix']; + + foreach ($hook_events as $hook_event) { + $hook_event = $hook['HookToPrefix'] . '.' . $hook['HookToSpecial'] . ':' . $hook_event; + $do_event = $do_prefix . '.' . $hook['DoSpecial'] . ':' . $hook['DoEvent']; + + $this->Application->registerHook($hook_event, $do_event, $hook['Mode'], $hook['Conditional']); + } } + } - if ( is_array(getArrayValue($config, 'AggregateTags')) ) { - foreach ($config['AggregateTags'] as $aggregate_tag) { - if (isset($config['ParentPrefix'])) { - if ($aggregate_tag['AggregateTo'] == $config['ParentPrefix']) { - trigger_error('Depricated Aggregate Tag Usage [prefix: '.$config['Prefix'].'; AggregateTo: '.$aggregate_tag['AggregateTo'].'] use #PARENT# as AggregateTo value, where AggregateTo is same as ParentPrefix', defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_NOTICE); - } + protected function parseAggregatedTags($prefix) + { + $config =& $this->configData[$prefix]; + $aggregated_tags = isset($config['AggregateTags']) ? $config['AggregateTags'] : Array (); - if ($aggregate_tag['AggregateTo'] == '#PARENT#') { - $aggregate_tag['AggregateTo'] = $config['ParentPrefix']; - } + foreach ($aggregated_tags as $aggregate_tag) { + if ( isset($config['ParentPrefix']) ) { + if ($aggregate_tag['AggregateTo'] == $config['ParentPrefix']) { + trigger_error('Depricated Aggregate Tag Usage [prefix: '.$config['Prefix'].'; AggregateTo: '.$aggregate_tag['AggregateTo'].'] use #PARENT# as AggregateTo value, where AggregateTo is same as ParentPrefix', defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_NOTICE); } - $aggregate_tag['LocalPrefix'] = $config['Prefix']; - $this->Application->registerAggregateTag($aggregate_tag); + + if ($aggregate_tag['AggregateTo'] == '#PARENT#') { + $aggregate_tag['AggregateTo'] = $config['ParentPrefix']; + } } + + $aggregate_tag['LocalPrefix'] = $config['Prefix']; + $this->Application->registerAggregateTag($aggregate_tag); } } @@ -621,19 +637,18 @@ $tablename = $config['TableName']; $float_types = Array ('float', 'double', 'numeric'); - $conn =& $this->Application->GetADODBConnection(); - $table_found = $conn->Query('SHOW TABLES LIKE "'.$tablename.'"'); + $table_found = $this->Conn->Query('SHOW TABLES LIKE "'.$tablename.'"'); if (!$table_found) { // config present, but table missing, strange - safeDefine('DBG_RAISE_ON_WARNINGS', 1); + kUtil::safeDefine('DBG_RAISE_ON_WARNINGS', 1); $debugger->appendHTML("Config Warning: Table $tablename missing, but prefix ".$config['Prefix']." requires it!"); $debugger->WarningCount++; return ; } - $res = $conn->Query('DESCRIBE '.$tablename); + $res = $this->Conn->Query('DESCRIBE '.$tablename); $config_link = $debugger->getFileLink(FULL_PATH.$this->prefixFiles[$config['Prefix']], 1, $config['Prefix']); $error_messages = Array ( @@ -765,7 +780,7 @@ $error_prefix = 'Config Error'.(count($config_errors) > 1 ? 's' : '').': for prefix '.$config_link.' ('.$tablename.') in unit config:
'; $config_errors = $error_prefix.'   '.implode('
   ', $config_errors); - safeDefine('DBG_RAISE_ON_WARNINGS', 1); + kUtil::safeDefine('DBG_RAISE_ON_WARNINGS', 1); $debugger->appendHTML($config_errors); $debugger->WarningCount++; } @@ -776,17 +791,21 @@ return ''.var_export($value, true).' of '.gettype($value); } - function ProcessDependencies($prefix) + protected function ProcessDependencies($prefix) { $config =& $this->configData[$prefix]; $deps = getArrayValue($config, '_Dependencies'); - if (!$deps) return ; + if (!$deps) { + return ; + } + foreach ($deps as $real_class => $requires) { foreach ($requires as $class) { $this->Application->registerDependency($real_class, $class); } } + unset($config['_Dependencies']); } @@ -805,7 +824,7 @@ $this->loadConfig($sub_prefix); } $sub_config['Prefix'] = $sub_prefix; - $this->configData[$sub_prefix] = array_merge_recursive2($this->configData[$$dst_prefix_var], $sub_config); + $this->configData[$sub_prefix] = kUtil::array_merge_recursive($this->configData[$$dst_prefix_var], $sub_config); // when merging empty array to non-empty results non-empty array, but empty is required foreach ($sub_config as $sub_key => $sub_value) { @@ -840,7 +859,7 @@ if (defined('DEBUG_MODE') && DEBUG_MODE && defined('DBG_PROFILE_INCLUDES') && DBG_PROFILE_INCLUDES) { if ( in_array($filename, get_required_files()) ) { - return; + return ''; } global $debugger; @@ -900,11 +919,12 @@ function loadConfig($prefix) { - if (!isset($this->prefixFiles[$prefix])) { - if ($this->Application->isDebugMode()) $this->Application->Debugger->appendTrace(); - trigger_error('Configuration file for prefix '.$prefix.' is unknown', E_USER_ERROR); + if ( !isset($this->prefixFiles[$prefix]) ) { + throw new Exception('Configuration file for prefix ' . $prefix . ' is unknown'); + return ; } + $file = $this->prefixFiles[$prefix]; $prefix = $this->PreloadConfigFile($file); @@ -919,6 +939,7 @@ if ($this->FinalStage) { $clones = array_unique($clones); + foreach ($clones as $a_prefix) { $this->runAfterConfigRead($a_prefix); } @@ -1009,15 +1030,34 @@ } - function getPrefixByParamName($paramName,$prefix) + protected function getClasses($prefix) { - $pseudo_class_map=Array( - 'ItemClass'=>'%s', - 'ListClass'=>'%s_List', - 'EventHandlerClass'=>'%s_EventHandler', - 'TagProcessorClass'=>'%s_TagProcessor' + $config =& $this->configData[$prefix]; + $class_params = Array ('ItemClass', 'ListClass', 'EventHandlerClass', 'TagProcessorClass'); + $register_classes = isset($config['RegisterClasses']) ? $config['RegisterClasses'] : Array (); + + foreach ($class_params as $param_name) { + if ( !isset($config[$param_name]) ) { + continue; + } + + $config[$param_name]['pseudo'] = $this->getPseudoByOptionName($param_name, $prefix); + $register_classes[] = $config[$param_name]; + } + + return $register_classes; + } + + protected function getPseudoByOptionName($option_name, $prefix) + { + $pseudo_class_map = Array ( + 'ItemClass' => '%s', + 'ListClass' => '%s_List', + 'EventHandlerClass' => '%s_EventHandler', + 'TagProcessorClass' => '%s_TagProcessor' ); - return sprintf($pseudo_class_map[$paramName],$prefix); + + return sprintf($pseudo_class_map[$option_name], $prefix); } /**