Index: core/kernel/utility/unit_config_cloner.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/kernel/utility/unit_config_cloner.php (revision ) +++ core/kernel/utility/unit_config_cloner.php (revision ) @@ -0,0 +1,172 @@ +reader = $reader; + } + + /** + * Sets data from cache to object + * + * @param Array $data + */ + public function setFromCache(&$data) + { + $this->clones = $data['ConfigCloner.clones']; + } + + /** + * Gets object data for caching + * + * @return Array + */ + public function getToCache() + { + return array( + 'ConfigCloner.clones' => $this->clones, + ); + } + + /** + * Creates unit configs, based on 'Clones' option. + * + * @param string $prefix Unit config prefix. + * + * @return array + */ + public function extrude($prefix) + { + $main_config = $this->reader->getUnitConfig($prefix); + $sub_configs = $main_config->getSetting('Clones', array()); + + if ( isset($this->clones[$prefix]) ) { + $sub_configs = array_merge($sub_configs, $this->clones[$prefix]); + } + + if ( !$sub_configs ) { + return array(); + } + + $processed = array(); + $main_config->setSetting('Clones', null); + unset($this->clones[$prefix]); + + if ( !isset($this->clones[$prefix]) ) { + $this->clones[$prefix] = array(); + } + + foreach ( $sub_configs as $sub_prefix => $sub_config_data ) { + $this->clones[$prefix][$sub_prefix] = $sub_config_data; + + $sub_config_data['Prefix'] = $sub_prefix; + $sub_config = $this->prepareClone($main_config, $sub_config_data); + $this->reader->add($sub_config, $this->reader->getPrefixFile($prefix)); + + array_push($processed, $sub_prefix); + } + + if ( !$prefix ) { + // configs, that used only for cloning & not used itself + $this->reader->remove($prefix); + } + + return array_unique($processed); + } + + /** + * Prepares data for of cloned unit config. + * + * @param kUnitConfig $main_config Main unit config. + * @param array $sub_config_data Sub config data. + * + * @return kUnitConfig + */ + protected function prepareClone(kUnitConfig $main_config, $sub_config_data) + { + $ret = kUtil::array_merge_recursive($main_config->getRaw(), $sub_config_data); + + foreach ($sub_config_data as $key => $value) { + if ( !$value && is_array($value) ) { + unset($ret[$key]); + } + } + + return new kUnitConfig($sub_config_data['Prefix'], $ret); + } + + /** + * Creates clones (where needed) and parses them. + * + * @param array $prefixes Unit config prefixes. + * + * @return array + */ + public function extrudeAndParse(array $prefixes) + { + $cloned_prefixes = array(); + + foreach ( $prefixes as $prefix ) { + $cloned_prefixes = array_merge($cloned_prefixes, $this->extrude($prefix)); + } + + foreach ( $cloned_prefixes as $cloned_prefix ) { + $this->reader->getUnitConfig($cloned_prefix)->parse(); + } + + return array_unique($cloned_prefixes); + } + + /** + * Process clones, that were defined via OnAfterConfigRead event + * + * @return void + */ + public function processDynamicallyAdded() + { + $new_clones = $this->extrudeAndParse($this->reader->getPrefixes()); + + // execute delayed methods for cloned unit configs + $this->Application->cacheManager->applyDelayedUnitProcessing(); + + // call OnAfterConfigRead for cloned configs + foreach ( $new_clones as $prefix ) { + $this->reader->runAfterConfigRead($prefix); + } + } +} Index: core/kernel/utility/http_query.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/kernel/utility/http_query.php (revision 15908) +++ core/kernel/utility/http_query.php (revision ) @@ -170,29 +170,7 @@ */ protected function getQueryString($prefix) { - $ret = $this->Application->getUnitConfig($prefix)->getQueryString(Array ()); - - if ( !$ret && preg_match('/(.*?)-(.*)/', $prefix, $regs) ) { - // "#prefix" (new format), "prefix" (old format) - return $this->_getQueryString('#' . $regs[2]); - } - - return $ret; - } - - /** - * Returns query string (with safety check against missing prefixes) - * - * @param string $prefix - * @return Array - */ - private function _getQueryString($prefix) - { - if ( $this->Application->prefixRegistred($prefix) ) { - return $this->Application->getUnitConfig($prefix)->getQueryString(); - } - - return substr($prefix, 0, 1) == '#' ? $this->_getQueryString( substr($prefix, 1) ) : Array (); + return $this->Application->getUnitConfig($prefix)->getQueryString(Array ()); } /** Index: core/install/upgrades.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/install/upgrades.php (revision 15908) +++ core/install/upgrades.php (revision ) @@ -73,9 +73,14 @@ $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); /* @var $ml_helper kMultiLanguageHelper */ - $this->Application->UnitConfigReader->iterateConfigs(Array (&$this, 'updateTextFields'), $ml_helper->getLanguages()); + $languages = $ml_helper->getLanguages(); + $this->Application->UnitConfigReader->ReReadConfigs(); + + foreach ($this->Application->UnitConfigReader->getPrefixes() as $prefix) { + $this->updateTextFields($prefix, $languages); - } - } + } + } + } /** * Moves ReplacementTags functionality from EmailMessage to Events table @@ -108,46 +113,50 @@ * Callback function, that makes all ml fields of text type null with same default value * * @param string $prefix - * @param Array $config_data * @param Array $languages - * @return bool + * + * @return boolean */ - function updateTextFields($prefix, &$config_data, $languages) + function updateTextFields($prefix, $languages) { - if (!isset($config_data['TableName']) || !isset($config_data['Fields'])) { + $config = $this->Application->getUnitConfig($prefix); + + if ( $config->getTableName() === false || $config->getFields() === false ) { // invalid config found or prefix not found return false; } - $table_name = $config_data['TableName']; + $table_name = $config->getTableName(); - $table_structure = $this->Conn->Query('DESCRIBE '.$table_name, 'Field'); + $table_structure = $this->Conn->Query('DESCRIBE ' . $table_name, 'Field'); + - if (!$table_structure) { + if ( !$table_structure ) { // table not found return false; } - $sqls = Array (); + $sqls = Array(); - foreach ($config_data['Fields'] as $field => $options) { + + foreach ( $config->getFields() as $field => $options ) { - if (isset($options['formatter']) && $options['formatter'] == 'kMultiLanguage' && !isset($options['master_field'])) { + if ( isset($options['formatter']) && $options['formatter'] == 'kMultiLanguage' && !isset($options['master_field']) ) { // update all l_ fields (new format) - foreach ($languages as $language_id) { + foreach ( $languages as $language_id ) { - $ml_field = 'l'.$language_id.'_'.$field; + $ml_field = 'l' . $language_id . '_' . $field; - if ($table_structure[$ml_field]['Type'] == 'text') { + if ( $table_structure[$ml_field]['Type'] == 'text' ) { - $sqls[] = 'CHANGE '.$ml_field.' '.$ml_field.' TEXT NULL DEFAULT NULL'; + $sqls[] = 'CHANGE ' . $ml_field . ' ' . $ml_field . ' TEXT NULL DEFAULT NULL'; } } // update if found (old format) - if (isset($table_structure[$field]) && $table_structure[$field]['Type'] == 'text') { + if ( isset($table_structure[$field]) && $table_structure[$field]['Type'] == 'text' ) { - $sqls[] = 'CHANGE '.$field.' '.$field.' TEXT NULL DEFAULT NULL'; + $sqls[] = 'CHANGE ' . $field . ' ' . $field . ' TEXT NULL DEFAULT NULL'; } } } - if ($sqls) { + if ( $sqls ) { - $sql = 'ALTER TABLE '.$table_name.' '.implode(', ', $sqls); + $sql = 'ALTER TABLE ' . $table_name . ' ' . implode(', ', $sqls); $this->Conn->Query($sql); } \ No newline at end of file Index: core/kernel/managers/request_manager.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/kernel/managers/request_manager.php (revision 15908) +++ core/kernel/managers/request_manager.php (revision ) @@ -138,12 +138,6 @@ { $event = new kEvent($prefix_special . ':' . $event_name); - if ( preg_match('/(.*?)-(.*)/', $event->Prefix, $regs) && $this->Application->prefixRegistred($regs[1]) ) { - // this is event from cloned config -> load parent config to create valid clone - $this->Application->UnitConfigReader->loadConfig($regs[1]); - $this->Application->UnitConfigReader->runAfterConfigRead($regs[1]); - } - if ( !$this->Application->EventManager->verifyEventPrefix($event, true) ) { $false = false; \ No newline at end of file Index: core/kernel/managers/cache_manager.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/kernel/managers/cache_manager.php (revision 15908) +++ core/kernel/managers/cache_manager.php (revision ) @@ -303,7 +303,7 @@ // maybe discover keys automatically from corresponding classes $cache_keys = Array ( 'Factory.Files', 'Factory.realClasses', - 'ConfigReader.prefixFiles', + 'ConfigReader.prefixFiles', 'ConfigCloner.clones', 'EventManager.beforeHooks', 'EventManager.afterHooks', 'EventManager.scheduledTasks', 'EventManager.buildEvents', 'Application.ReplacementTemplates', 'Application.RewriteListeners', 'Application.ModuleInfo', 'Application.ConfigHash', 'Application.ConfigCacheIds', \ No newline at end of file Index: core/units/admin/admin_events_handler.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/units/admin/admin_events_handler.php (revision 15908) +++ core/units/admin/admin_events_handler.php (revision ) @@ -693,7 +693,7 @@ protected function OnCheckPrefixConfig(kEvent $event) { $prefix = $this->Application->GetVar('config_prefix'); - $config_file = $this->Application->UnitConfigReader->prefixFiles[$prefix]; + $config_file = $this->Application->UnitConfigReader->getPrefixFile($prefix); $this->Application->InitParser(); \ No newline at end of file Index: core/kernel/application.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/kernel/application.php (revision 15908) +++ core/kernel/application.php (revision ) @@ -734,6 +734,7 @@ $this->registerClass('kUnitConfig', KERNEL_PATH . '/utility/unit_config.php'); $this->registerClass('kUnitConfigReader', KERNEL_PATH . '/utility/unit_config_reader.php'); + $this->registerClass('kUnitConfigCloner', KERNEL_PATH . '/utility/unit_config_cloner.php'); $this->registerClass('PasswordHash', KERNEL_PATH . '/utility/php_pass.php'); // Params class descendants @@ -2337,7 +2338,7 @@ */ public function prefixRegistred($prefix) { - return $this->UnitConfigReader->prefixRegistred($prefix); + return $this->UnitConfigReader->prefixRegistered($prefix); } /** Index: core/kernel/utility/unit_config_reader.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/kernel/utility/unit_config_reader.php (revision 15908) +++ core/kernel/utility/unit_config_reader.php (revision ) @@ -17,96 +17,130 @@ class kUnitConfigReader extends kBase implements kiCacheable { /** - * Configs reader + * Unit config data storage. * - * @var Array|kUnitConfig[] - * @access private + * @var kUnitConfig[] */ - var $configData = Array(); + protected $configData = array(); - var $configFiles = Array(); + /** + * List of discovered unit config files. + * + * @var array + */ + protected $configFiles = array(); - var $CacheExpired = false; + /** + * Mapping between unit config prefixes and files, where they data is stored. + * + * @var array + */ + protected $prefixFiles = array(); - var $prefixFiles = array(); + /** + * Tells, that it's final stage of application initialization, where OnAfterConfigRead events can be called. + * + * @var boolean + */ + protected $finalStage = false; - var $ProcessAllConfigs = false; - var $FinalStage = false; - var $StoreCache = false; - var $AfterConfigProcessed = array(); + /** + * Determines if cache should be stored. + * + * @var boolean + */ + protected $storeCache = false; /** + * List of unit configs, that have called their OnAfterConfigRead event. + * + * @var array + */ + protected $afterConfigProcessed = array(); + + /** * Escaped directory separator for using in regular expressions * * @var string */ - var $_directorySeparator = ''; + protected $directorySeparator = ''; /** * Regular expression for detecting module folder * * @var string */ - var $_moduleFolderRegExp = ''; + protected $moduleFolderRegExp = ''; /** * Folders to skip during unit config search * - * @var Array + * @var array */ - var $_skipFolders = Array ('CVS', '.svn', 'admin_templates', 'libchart'); + protected $skipFolders = array('CVS', '.svn', 'admin_templates', 'libchart'); /** - * Creates instance of unit config reader + * Cloner. * + * @var kUnitConfigCloner */ + protected $cloner; + + /** + * Creates instance of unit config reader. + */ public function __construct() { parent::__construct(); - $this->_directorySeparator = preg_quote(DIRECTORY_SEPARATOR); + $this->directorySeparator = preg_quote(DIRECTORY_SEPARATOR); $editor_path = explode('/', trim(EDITOR_PATH, '/')); - $this->_skipFolders[] = array_pop($editor_path); // last of cmseditor folders + $this->skipFolders[] = array_pop($editor_path); // last of cmseditor folders - $this->_moduleFolderRegExp = '#' . $this->_directorySeparator . '(core|modules' . $this->_directorySeparator . '.*?)' . $this->_directorySeparator . '#'; + $this->moduleFolderRegExp = '#' . $this->directorySeparator . '(core|modules' . $this->directorySeparator . '.*?)' . $this->directorySeparator . '#'; + + $this->cloner = $this->Application->makeClass('kUnitConfigCloner', array($this)); } /** * Sets data from cache to object * * @param Array $data - * @access public */ public function setFromCache(&$data) { + $this->cloner->setFromCache($data); + $this->prefixFiles = $data['ConfigReader.prefixFiles']; } /** * Gets object data for caching * - * @access public * @return Array */ public function getToCache() { - return Array ( + return array_merge( + $this->cloner->getToCache(), + array( - 'ConfigReader.prefixFiles' => $this->prefixFiles, + 'ConfigReader.prefixFiles' => $this->prefixFiles, + ) ); } - function scanModules($folderPath, $cache = true) + public function scanModules($folder_path, $cache = true) { - if (defined('IS_INSTALL') && IS_INSTALL && !defined('FORCE_CONFIG_CACHE')) { + if ( defined('IS_INSTALL') && IS_INSTALL && !defined('FORCE_CONFIG_CACHE') ) { // disable config caching during installation $cache = false; } - if ($cache) { + if ( $cache ) { $restored = $this->Application->cacheManager->LoadUnitCache(); - if ($restored) { + if ( $restored ) { if ( defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode() ) { $this->Application->Debugger->appendHTML('UnitConfigReader: Restoring Cache'); } @@ -119,14 +153,15 @@ $this->Application->Debugger->appendHTML('UnitConfigReader: Generating Cache'); } - $this->ProcessAllConfigs = true; + // === lines below would only executed on cold start (no unit config cache) === - $this->includeConfigFiles($folderPath, $cache); - $this->ParseConfigs(); + // no cache found -> include all unit configs to create it ! + $this->includeConfigFiles($folder_path, $cache); + $this->parseConfigs(); // tell AfterConfigRead to store cache if needed // can't store it here because AfterConfigRead needs ability to change config data - $this->StoreCache = $cache; + $this->storeCache = $cache; if ( !$this->Application->InitDone ) { // scanModules is called multiple times during installation process @@ -134,53 +169,22 @@ // get build-in rewrite listeners ONLY to be able to parse mod-rewrite url when unit config cache is missing $this->retrieveCollections(); - $this->_sortRewriteListeners(); + $this->sortRewriteListeners(); } $this->Application->cacheManager->applyDelayedUnitProcessing(); } - function findConfigFiles($folderPath, $level = 0) + /** + * Locates (recursively) and reads all unit configs at given path. + * + * @param string $folder_path Folder path. + * @param boolean $cache Store information to cache. + * + * @throws Exception When unit config file is missing a prefix defined inside it. + */ + protected function includeConfigFiles($folder_path, $cache = true) { - // 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 - - $base_folder = FULL_PATH . $folderPath . DIRECTORY_SEPARATOR; - $sub_folders = glob($base_folder . '*', GLOB_ONLYDIR); - if (!$sub_folders) { - return ; - } - - if ($level == 0) { - // don't scan Front-End themes because of extensive directory structure - $sub_folders = array_diff($sub_folders, Array ($base_folder . 'themes', $base_folder . 'tools')); - } - - foreach ($sub_folders as $full_path) { - $sub_folder = substr($full_path, strlen($base_folder)); - - if (in_array($sub_folder, $this->_skipFolders)) { - continue; - } - - if (preg_match('/^\./', $sub_folder)) { - // don't scan ".folders" - continue; - } - - $config_name = $this->getConfigName($folderPath . DIRECTORY_SEPARATOR . $sub_folder); - - if (file_exists(FULL_PATH . $config_name)) { - $this->configFiles[] = $config_name; - } - - $this->findConfigFiles($full_path, $level + 1); - } - } - - function includeConfigFiles($folderPath, $cache = true) - { $this->Application->refreshModuleInfo(); if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) { @@ -198,8 +202,8 @@ } } else { - $this->findConfigFiles(FULL_PATH . DIRECTORY_SEPARATOR . 'core'); // search from core directory - $this->findConfigFiles($folderPath); // search from modules directory + $this->findConfigFiles(FULL_PATH . DIRECTORY_SEPARATOR . 'core'); // search from "core" directory + $this->findConfigFiles($folder_path); // search from "modules" directory if ( $cache ) { if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) { @@ -211,79 +215,159 @@ } } - foreach ($this->configFiles as $filename) { + foreach ( $this->configFiles as $filename ) { $prefix = $this->PreloadConfigFile($filename); - if (!$prefix) { + if ( !$prefix ) { throw new Exception('Prefix not defined in config file ' . $filename . ''); } } + // TODO: needed? - if ($cache) { + if ( $cache ) { unset($this->configFiles); } } /** - * Process all read config files - called ONLY when there is no cache! + * Recursively searches for unit configs in given folder. * + * @param string $folder_path Path to the folder. + * @param int $level Deep level of the folder. + * + * @return void */ - function ParseConfigs() + protected function findConfigFiles($folder_path, $level = 0) { - // 1. process normal configs - $prioritized_configs = Array (); + // if FULL_PATH = "/" ensure, that all "/" in $folderPath are not deleted + $reg_exp = '/^' . preg_quote(FULL_PATH, '/') . '/'; + $folder_path = preg_replace($reg_exp, '', $folder_path, 1); // this make sense, since $folderPath may NOT contain FULL_PATH - foreach ($this->configData as $prefix => $config) { - if ( $config->getConfigPriority() !== false ) { - $prioritized_configs[$prefix] = $config->getConfigPriority(); + $base_folder = FULL_PATH . $folder_path . DIRECTORY_SEPARATOR; + $sub_folders = glob($base_folder . '*', GLOB_ONLYDIR); + + if ( !$sub_folders ) { + return; + } + + if ( $level == 0 ) { + // don't scan Front-End themes because of extensive directory structure + $sub_folders = array_diff($sub_folders, array($base_folder . 'themes', $base_folder . 'tools')); + } + + foreach ( $sub_folders as $full_path ) { + $sub_folder = substr($full_path, strlen($base_folder)); + + if ( in_array($sub_folder, $this->skipFolders) || preg_match('/^\./', $sub_folder) ) { + // don't scan skipped or hidden folders continue; } - $config->parse(); + $config_name = $this->getConfigName($folder_path . DIRECTORY_SEPARATOR . $sub_folder); + + if ( file_exists(FULL_PATH . $config_name) ) { + $this->configFiles[] = $config_name; - } + } - foreach ($this->configData as $prefix => $config) { - $this->postProcessConfig($prefix, 'AggregateConfigs', 'sub_prefix'); - $clones = $this->postProcessConfig($prefix, 'Clones', 'prefix'); + $this->findConfigFiles($full_path, $level + 1); } + } - // 2. process prioritized configs - asort($prioritized_configs); + /** + * Process all read config files - called ONLY when there is no cache! + * + * @return void + */ + protected function parseConfigs() + { + $this->parseUnitConfigs($this->getUnitConfigsWithoutPriority()); + $this->parseUnitConfigs($this->getUnitConfigsWithPriority()); + } - foreach ($prioritized_configs as $prefix => $priority) { + /** + * Parses unit config sub-set. + * + * @param array $prefixes Unit config prefixes. + * + * @return array + */ + protected function parseUnitConfigs(array $prefixes) + { + foreach ( $prefixes as $prefix ) { $this->configData[$prefix]->parse(); } + + $this->cloner->extrudeAndParse($prefixes); } - function AfterConfigRead($store_cache = null) + /** + * Returns unit configs prefixes without priority defined. + * + * @return array + */ + protected function getUnitConfigsWithoutPriority() { -// if (!$this->ProcessAllConfigs) return ; - $this->FinalStage = true; + $ret = array(); + - foreach ($this->configData as $prefix => $config) { + foreach ( $this->configData as $prefix => $config ) { + if ( $config->getConfigPriority() === false ) { + $ret[] = $prefix; + } + } + + return $ret; + } + + /** + * Returns unit configs prefixes with priority defined. + * + * @return array + */ + protected function getUnitConfigsWithPriority() + { + $ret = array(); + + foreach ( $this->configData as $prefix => $config ) { + $priority = $config->getConfigPriority(); + + if ( $priority !== false ) { + $ret[$prefix] = $priority; + } + } + + asort($ret); + + return array_keys($ret); + } + + public function AfterConfigRead($store_cache = null) + { + $this->finalStage = true; + + foreach ($this->configData as $prefix => $config) { $this->runAfterConfigRead($prefix); } if ( !isset($store_cache) ) { // $store_cache not overridden -> use global setting - $store_cache = $this->StoreCache; + $store_cache = $this->storeCache; } if ( $store_cache || (defined('IS_INSTALL') && IS_INSTALL) ) { // cache is not stored during install, but dynamic clones should be processed in any case - $this->processDynamicClones(); + $this->cloner->processDynamicallyAdded(); $this->retrieveCollections(); } if ( $store_cache ) { - $this->_sortRewriteListeners(); + $this->sortRewriteListeners(); $this->Application->HandleEvent(new kEvent('adm:OnAfterCacheRebuild')); - $this->Application->cacheManager->UpdateUnitCache(); if ( defined('DEBUG_MODE') && DEBUG_MODE && defined('DBG_VALIDATE_CONFIGS') && DBG_VALIDATE_CONFIGS ) { // validate configs here to have changes from OnAfterConfigRead hooks to prefixes - foreach ($this->configData as $prefix => $config) { + foreach ( $this->configData as $config ) { if ( !$config->getTableName() ) { continue; } @@ -297,15 +381,16 @@ /** * Sort rewrite listeners according to RewritePriority (non-prioritized listeners goes first) * + * @return void */ - function _sortRewriteListeners() + protected function sortRewriteListeners() { - $listeners = Array (); - $prioritized_listeners = Array (); + $listeners = array(); + $prioritized_listeners = array(); // process non-prioritized listeners - foreach ($this->Application->RewriteListeners as $prefix => $listener_data) { + foreach ( $this->Application->RewriteListeners as $prefix => $listener_data ) { - if ($listener_data['priority'] === false) { + if ( $listener_data['priority'] === false ) { $listeners[$prefix] = $listener_data; } else { @@ -315,7 +400,8 @@ // process prioritized listeners asort($prioritized_listeners, SORT_NUMERIC); + - foreach ($prioritized_listeners as $prefix => $priority) { + foreach ( $prioritized_listeners as $prefix => $priority ) { $listeners[$prefix] = $this->Application->RewriteListeners[$prefix]; } @@ -323,10 +409,11 @@ } /** - * Re-reads all configs + * Re-reads all configs. * + * @return void */ - function ReReadConfigs() + public function ReReadConfigs() { // don't reset prefix file, since file scanning could slow down the process $prefix_files_backup = $this->prefixFiles; @@ -334,49 +421,21 @@ $this->prefixFiles = $prefix_files_backup; // parse all configs - $this->ProcessAllConfigs = true; - $this->AfterConfigProcessed = Array (); + $this->afterConfigProcessed = array(); $this->includeConfigFiles(MODULES_PATH, false); - $this->ParseConfigs(); + $this->parseConfigs(); $this->AfterConfigRead(false); - $this->processDynamicClones(); - - // don't call kUnitConfigReader::retrieveCollections since it - // will overwrite what we already have in kApplication class instance + $this->cloner->processDynamicallyAdded(); + $this->retrieveCollections(); } /** - * Process clones, that were defined via OnAfterConfigRead event - * - */ - function processDynamicClones() - { - $new_clones = Array(); - foreach ($this->configData as $prefix => $config) { - $clones = $this->postProcessConfig($prefix, 'Clones', 'prefix'); - - if ($clones) { - $new_clones = array_merge($new_clones, $clones); - } - } - - // execute delayed methods for cloned unit configs - $this->Application->cacheManager->applyDelayedUnitProcessing(); - - // call OnAfterConfigRead for cloned configs - $new_clones = array_unique($new_clones); - foreach ($new_clones as $prefix) { - $this->runAfterConfigRead($prefix); - } - } - - /** * Process all collectible unit config options here to also catch ones, defined from OnAfterConfigRead events * */ - function retrieveCollections() + protected function retrieveCollections() { - foreach ($this->configData as $prefix => $config) { + foreach ( $this->configData as $prefix => $config ) { // collect replacement templates if ( $config->getReplacementTemplates() ) { $this->Application->ReplacementTemplates = array_merge($this->Application->ReplacementTemplates, $config->getReplacementTemplates()); @@ -388,10 +447,10 @@ if ( !is_array($rewrite_listeners) ) { // when one method is used to build and parse url - $rewrite_listeners = Array ($rewrite_listeners, $rewrite_listeners); + $rewrite_listeners = array($rewrite_listeners, $rewrite_listeners); } - foreach ($rewrite_listeners as $index => $rewrite_listener) { + foreach ( $rewrite_listeners as $index => $rewrite_listener ) { if ( strpos($rewrite_listener, ':') === false ) { $rewrite_listeners[$index] = $prefix . '_EventHandler:' . $rewrite_listener; } @@ -399,65 +458,58 @@ $rewrite_priority = $config->getRewritePriority(); - $this->Application->RewriteListeners[$prefix] = Array ('listener' => $rewrite_listeners, 'priority' => $rewrite_priority); + $this->Application->RewriteListeners[$prefix] = array('listener' => $rewrite_listeners, 'priority' => $rewrite_priority); } } } - function postProcessConfig($prefix, $config_key, $dst_prefix_var) + public function loadConfig($prefix) { - $main_config = $this->configData[$prefix]; - $sub_configs = $main_config->getSetting($config_key); + $preloaded_prefix = $this->PreloadConfigFile($this->getPrefixFile($prefix)); - if ( !$sub_configs ) { - return Array (); + if ( $this->finalStage ) { + // run prefix OnAfterConfigRead so all hooks to it can define their clones + $this->runAfterConfigRead($preloaded_prefix); } - $processed = Array (); - $main_config->setSetting($config_key, null); + $clones = $this->cloner->extrude($preloaded_prefix); - foreach ($sub_configs as $sub_prefix => $sub_config_data) { - if ( $config_key == 'AggregateConfigs' && !isset($this->configData[$sub_prefix]) ) { - $this->loadConfig($sub_prefix); + if ( $this->finalStage ) { + foreach ( $clones as $a_prefix ) { + $this->runAfterConfigRead($a_prefix); } - - $sub_config_data['Prefix'] = $sub_prefix; - $sub_config_base = $this->configData[$$dst_prefix_var]->getRaw(); - $sub_config = new kUnitConfig($sub_prefix, kUtil::array_merge_recursive($sub_config_base, $sub_config_data)); - $this->configData[$sub_prefix] = $sub_config; - - // when merging empty array to non-empty results non-empty array, but empty is required - foreach ($sub_config_data as $sub_key => $sub_value) { - if ( !$sub_value && is_array($sub_value) ) { - $sub_config->setSetting($sub_key, null); - } - } + } + } - if ( $config_key == 'Clones' ) { - $this->prefixFiles[$sub_prefix] = $this->prefixFiles[$prefix]; + /** + * Runs OnAfterConfigRead event for given prefix once. + * + * @param string $prefix Unit config prefix. + * + * @return void + */ + public function runAfterConfigRead($prefix) + { + if ( in_array($prefix, $this->afterConfigProcessed) ) { + return; - } + } - $this->postProcessConfig($sub_prefix, $config_key, $dst_prefix_var); + $this->Application->HandleEvent(new kEvent($prefix . ':OnAfterConfigRead')); - if ( $config_key == 'AggregateConfigs' ) { - $processed = array_merge($this->postProcessConfig($sub_prefix, 'Clones', 'prefix'), $processed); + if ( !(defined('IS_INSTALL') && IS_INSTALL) ) { + // allow to call OnAfterConfigRead multiple times during install + array_push($this->afterConfigProcessed, $prefix); - } + } - elseif ( $this->ProcessAllConfigs ) { - $this->configData[$sub_prefix]->parse(); - } + } - array_push($processed, $sub_prefix); - } - - if ( !$prefix ) { - // configs, that used only for cloning & not used itself - unset($this->configData[$prefix]); - } - - return array_unique($processed); - } - - function PreloadConfigFile($filename) + /** + * Loads unit config file contents from disk. + * + * @param string $filename Unit config filename. + * + * @return string + */ + protected function PreloadConfigFile($filename) { $config_found = file_exists(FULL_PATH . $filename) && $this->configAllowed($filename); @@ -495,10 +547,9 @@ $prefix = $config->getPrefix(); } - preg_match($this->_moduleFolderRegExp, $filename, $regs); + preg_match($this->moduleFolderRegExp, $filename, $regs); $config->setModuleFolder(str_replace(DIRECTORY_SEPARATOR, '/', $regs[1])); $config->setBasePath(dirname(FULL_PATH . $filename)); - $config->setFilename($filename); if ( $config->getAdminTemplatePath() !== false ) { // append template base folder for admin templates path of this prefix @@ -515,8 +566,7 @@ ); } - $this->configData[$prefix] = $config; - $this->prefixFiles[$prefix] = $filename; + $this->add($config, $filename); return $prefix; } @@ -534,55 +584,40 @@ return 'dummy'; } - function loadConfig($prefix) + /** + * Sets a file, for a given prefix. + * + * @param kUnitConfig $config Unit config. + * @param string $filename File. + * + * @return void + */ + public function add(kUnitConfig $config, $filename) { - if ( !isset($this->prefixFiles[$prefix]) ) { - throw new Exception('Configuration file for prefix "' . $prefix . '" is unknown'); + $config->setFilename($filename); - return ; + $prefix = $config->getPrefix(); + $this->configData[$prefix] = $config; + $this->prefixFiles[$prefix] = $filename; - } + } - $file = $this->prefixFiles[$prefix]; - $prefix = $this->PreloadConfigFile($file); - - if ($this->FinalStage) { - // run prefix OnAfterConfigRead so all - // hooks to it can define their clones - $this->runAfterConfigRead($prefix); - } - - $clones = $this->postProcessConfig($prefix, 'AggregateConfigs', 'sub_prefix'); - $clones = array_merge($this->postProcessConfig($prefix, 'Clones', 'prefix'), $clones); - - if ($this->FinalStage) { - $clones = array_unique($clones); - - foreach ($clones as $a_prefix) { - $this->runAfterConfigRead($a_prefix); - } - } - } - - function runAfterConfigRead($prefix) + /** + * Removes unit config. + * + * @param string $prefix Unit config prefix. + * + * @return void + */ + public function remove($prefix) { - if (in_array($prefix, $this->AfterConfigProcessed)) { - return ; + unset($this->configData[$prefix], $this->prefixFiles[$prefix]); - } + } - $this->Application->HandleEvent( new kEvent($prefix . ':OnAfterConfigRead') ); - - if (!(defined('IS_INSTALL') && IS_INSTALL)) { - // allow to call OnAfterConfigRead multiple times during install - array_push($this->AfterConfigProcessed, $prefix); - } - } - /** * Returns unit config for given prefix * * @param string $prefix * @return kUnitConfig - * @access public */ public function getUnitConfig($prefix = null) { @@ -597,7 +632,6 @@ * Returns prefixes of unit configs, that were registered * * @return Array - * @access public */ public function getPrefixes() { @@ -608,84 +642,82 @@ * Get's config file name based * on folder name supplied * - * @param string $folderPath + * @param string $folder_path * @return string - * @access private */ - function getConfigName($folderPath) + protected function getConfigName($folder_path) { - return $folderPath . DIRECTORY_SEPARATOR . basename($folderPath) . '_config.php'; + return $folder_path . DIRECTORY_SEPARATOR . basename($folder_path) . '_config.php'; } /** - * Checks if config file is allowed for includion (if module of config is installed) + * Checks if config file is allowed for inclusion (if module of config is installed). * - * @param string $config_path relative path from in-portal directory + * @param string $config_path Relative path from In-Portal directory. + * + * @return boolean */ - function configAllowed($config_path) + protected function configAllowed($config_path) { static $module_paths = null; - if (defined('IS_INSTALL') && IS_INSTALL) { + if ( defined('IS_INSTALL') && IS_INSTALL ) { // at installation start no modules in db and kernel configs could not be read return true; } - if (preg_match('#^' . $this->_directorySeparator . 'core#', $config_path)) { + if ( preg_match('#^' . $this->directorySeparator . 'core#', $config_path) ) { // always allow to include configs from "core" module's folder return true; } - if (!$this->Application->ModuleInfo) { + if ( !$this->Application->ModuleInfo ) { return false; } - if (!isset($module_paths)) { + if ( !isset($module_paths) ) { - $module_paths = Array (); + $module_paths = array(); - foreach ($this->Application->ModuleInfo as $module_name => $module_info) { + foreach ( $this->Application->ModuleInfo as $module_info ) { $module_paths[] = str_replace('/', DIRECTORY_SEPARATOR, rtrim($module_info['Path'], '/')); } $module_paths = array_unique($module_paths); } - preg_match($this->_moduleFolderRegExp, $config_path, $rets); + preg_match($this->moduleFolderRegExp, $config_path, $regs); // config file path starts with module folder path - return in_array($rets[1], $module_paths); + return in_array($regs[1], $module_paths); } /** * Returns true if config exists and is allowed for reading * - * @param string $prefix - * @return bool + * @param string $prefix Unit config prefix. + * + * @return boolean */ - function prefixRegistred($prefix) + public function prefixRegistered($prefix) { - return isset($this->prefixFiles[$prefix]) ? true : false; + return isset($this->prefixFiles[$prefix]); } /** - * Returns config file for given prefix + * Returns unit config file location by it's prefix. * - * @param string $prefix + * @param string $prefix Unit config prefix. + * * @return string + * @throws Exception When unit config is not found. */ - function getPrefixFile($prefix) + public function getPrefixFile($prefix) { - return array_key_exists($prefix, $this->prefixFiles) ? $this->prefixFiles[$prefix] : false; + if ( !isset($this->prefixFiles[$prefix]) ) { + throw new Exception('Configuration file for prefix "' . $prefix . '" is unknown'); - } + } - function iterateConfigs($callback_function, $params) - { - $this->includeConfigFiles(MODULES_PATH); //make sure to re-read all configs - $this->AfterConfigRead(); - - foreach ($this->configData as $prefix => $config) { - $callback_function[0]->$callback_function[1]($prefix, $config, $params); - } + return $this->prefixFiles[$prefix]; } } \ No newline at end of file