_directorySeparator = preg_quote(DIRECTORY_SEPARATOR); $editor_path = explode('/', trim(EDITOR_PATH, '/')); $this->_skipFolders[] = array_pop($editor_path); // last of cmseditor folders $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 scanModules($folderPath, $cache = true) { if (defined('IS_INSTALL') && IS_INSTALL && !defined('FORCE_CONFIG_CACHE')) { // disable config caching during installation $cache = false; } if ($cache) { $restored = $this->Application->cacheManager->LoadUnitCache(); 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 needed // can't store it here because AfterConfigRead needs ability to change config data $this->StoreCache = $cache; if ( !$this->Application->InitDone ) { // scanModules is called multiple times during installation process $this->Application->InitManagers(); // 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->Application->cacheManager->applyDelayedUnitProcessing(); } function findConfigFiles($folderPath, $level = 0) { // 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) ) { $data = $this->Application->getCache('master:config_files', false, $cache ? CacheSettings::$unitCacheRebuildTime : 0); } else { $data = $this->Application->getDBCache('config_files', $cache ? CacheSettings::$unitCacheRebuildTime : 0); } if ( $data ) { $this->configFiles = unserialize($data); if ( !defined('DBG_VALIDATE_CONFIGS') && !DBG_VALIDATE_CONFIGS ) { shuffle($this->configFiles); } } else { $this->findConfigFiles(FULL_PATH . DIRECTORY_SEPARATOR . 'core'); // search from core directory $this->findConfigFiles($folderPath); // search from modules directory if ( $cache ) { if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) { $this->Application->setCache('master:config_files', serialize($this->configFiles)); } else { $this->Application->setDBCache('config_files', serialize($this->configFiles)); } } } foreach ($this->configFiles as $filename) { $prefix = $this->PreloadConfigFile($filename); if (!$prefix) { throw new Exception('Prefix not defined in config file ' . $filename . ''); } } if ($cache) { unset($this->configFiles); } } /** * Process all read config files - called ONLY when there is no cache! * */ function ParseConfigs() { // 1. process normal configs $prioritized_configs = Array (); foreach ($this->configData as $prefix => $config) { if ( $config->getConfigPriority() !== false ) { $prioritized_configs[$prefix] = $config->getConfigPriority(); continue; } $this->parseConfig($prefix); } foreach ($this->configData as $prefix => $config) { $this->postProcessConfig($prefix, 'AggregateConfigs', 'sub_prefix'); $clones = $this->postProcessConfig($prefix, 'Clones', 'prefix'); } // 2. process prioritized configs asort($prioritized_configs); foreach ($prioritized_configs as $prefix => $priority) { $this->parseConfig($prefix); } } function AfterConfigRead($store_cache = null) { // if (!$this->ProcessAllConfigs) return ; $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; } 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->retrieveCollections(); } if ( $store_cache ) { $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) { if ( !$config->getTableName() ) { continue; } $this->ValidateConfig($prefix); } } } } /** * Sort rewrite listeners according to RewritePriority (non-prioritized listeners goes first) * */ function _sortRewriteListeners() { $listeners = Array (); $prioritized_listeners = Array (); // process non-prioritized listeners foreach ($this->Application->RewriteListeners as $prefix => $listener_data) { if ($listener_data['priority'] === false) { $listeners[$prefix] = $listener_data; } else { $prioritized_listeners[$prefix] = $listener_data['priority']; } } // process prioritized listeners asort($prioritized_listeners, SORT_NUMERIC); foreach ($prioritized_listeners as $prefix => $priority) { $listeners[$prefix] = $this->Application->RewriteListeners[$prefix]; } $this->Application->RewriteListeners = $listeners; } /** * Re-reads all configs * */ function ReReadConfigs() { // don't reset prefix file, since file scanning could slow down the process $prefix_files_backup = $this->prefixFiles; $this->Application->cacheManager->EmptyUnitCache(); $this->prefixFiles = $prefix_files_backup; // parse all configs $this->ProcessAllConfigs = true; $this->AfterConfigProcessed = Array (); $this->includeConfigFiles(MODULES_PATH, false); $this->ParseConfigs(); $this->AfterConfigRead(false); $this->processDynamicClones(); // don't call kUnitConfigReader::retrieveCollections since it // will overwrite what we already have in kApplication class instance } /** * 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() { foreach ($this->configData as $prefix => $config) { // collect replacement templates if ( $config->getReplacementTemplates() ) { $this->Application->ReplacementTemplates = array_merge($this->Application->ReplacementTemplates, $config->getReplacementTemplates()); } // collect rewrite listeners if ( $config->getRewriteListener() ) { $rewrite_listeners = $config->getRewriteListener(); if ( !is_array($rewrite_listeners) ) { // when one method is used to build and parse url $rewrite_listeners = Array ($rewrite_listeners, $rewrite_listeners); } foreach ($rewrite_listeners as $index => $rewrite_listener) { if ( strpos($rewrite_listener, ':') === false ) { $rewrite_listeners[$index] = $prefix . '_EventHandler:' . $rewrite_listener; } } $rewrite_priority = $config->getRewritePriority(); $this->Application->RewriteListeners[$prefix] = Array ('listener' => $rewrite_listeners, 'priority' => $rewrite_priority); } } } /** * Register nessasary classes * This method should only process the data which is cached! * * @param string $prefix * @access private */ function parseConfig($prefix) { $this->parseClasses($prefix); $this->parseScheduledTasks($prefix); $this->parseHooks($prefix); $this->parseAggregatedTags($prefix); } protected function parseClasses($prefix) { $config = $this->configData[$prefix]; $register_classes = $this->getClasses($prefix); foreach ($register_classes as $class_info) { $this->Application->registerClass( $class_info['class'], $config->getBasePath() . DIRECTORY_SEPARATOR . $class_info['file'], $class_info['pseudo'] ); if ( isset($class_info['build_event']) && $class_info['build_event'] ) { $this->Application->delayUnitProcessing('registerBuildEvent', Array ($class_info['pseudo'], $class_info['build_event'])); } } } protected function parseScheduledTasks($prefix) { $config = $this->configData[$prefix]; if ( !$config->getScheduledTasks() ) { return ; } $scheduled_tasks = $config->getScheduledTasks(); foreach ($scheduled_tasks as $short_name => $scheduled_task_info) { $event_status = array_key_exists('Status', $scheduled_task_info) ? $scheduled_task_info['Status'] : STATUS_ACTIVE; $this->Application->delayUnitProcessing('registerScheduledTask', Array ( $short_name, $config->getPrefix() . ':' . $scheduled_task_info['EventName'], $scheduled_task_info['RunSchedule'], $event_status )); } } protected function parseHooks($prefix) { $config = $this->configData[$prefix]; if ( !$config->getHooks() ) { return; } $hooks = $config->getHooks(); foreach ($hooks as $hook) { if ( $config->getParentPrefix() && ($hook['HookToPrefix'] == $config->getParentPrefix()) ) { trigger_error('Deprecated Hook Usage [prefix: ' . $config->getPrefix() . '; 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->getPrefix(); } if ( $config->getParentPrefix() ) { // new: allow to set hook to parent prefix what ever it is if ( $hook['HookToPrefix'] == '#PARENT#' ) { $hook['HookToPrefix'] = $config->getParentPrefix(); } if ( $hook['DoPrefix'] == '#PARENT#' ) { $hook['DoPrefix'] = $config->getParentPrefix(); } } 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->getPrefix() : $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->delayUnitProcessing('registerHook', Array ($hook_event, $do_event, $hook['Mode'], $hook['Conditional'])); } } } protected function parseAggregatedTags($prefix) { $config = $this->configData[$prefix]; $aggregated_tags = $config->getAggregateTags(); if ( !$aggregated_tags ) { return; } foreach ($aggregated_tags as $aggregate_tag) { if ( $config->getParentPrefix() ) { if ( $aggregate_tag['AggregateTo'] == $config->getParentPrefix() ) { trigger_error('Deprecated Aggregate Tag Usage [prefix: ' . $config->getPrefix() . '; 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); } if ( $aggregate_tag['AggregateTo'] == '#PARENT#' ) { $aggregate_tag['AggregateTo'] = $config->getParentPrefix(); } } $aggregate_tag['LocalPrefix'] = $config->getPrefix(); $this->Application->delayUnitProcessing('registerAggregateTag', Array ($aggregate_tag)); } } function ValidateConfig($prefix) { global $debugger; $config = $this->configData[$prefix]; $table_name = $config->getTableName(); $float_types = Array ('float', 'double', 'numeric'); $table_found = $this->Conn->Query('SHOW TABLES LIKE "' . $table_name . '"'); if ( !$table_found ) { // config present, but table missing, strange kUtil::safeDefine('DBG_RAISE_ON_WARNINGS', 1); $debugger->appendHTML("Config Warning: Table $table_name missing, but prefix " . $prefix . " requires it!"); $debugger->WarningCount++; return; } $res = $this->Conn->Query('DESCRIBE ' . $table_name); $config_link = $debugger->getFileLink(FULL_PATH . $this->prefixFiles[$prefix], 1, $prefix); $error_messages = Array ( 'field_not_found' => 'Field %s exists in the database, but is not defined in config', 'default_missing' => 'Default value for field %s not set in config', 'not_null_error1' => 'Field %s is NOT NULL in the database, but is not configured as not_null', // or required', 'not_null_error2' => 'Field %s is described as NOT NULL in config, but does not have DEFAULT value', 'not_null_error3' => 'Field %s is described as NOT NULL in config, but is NULL in db', 'invalid_default' => 'Default value for field %s%s not sync. to db (in config = %s, in db = %s)', 'date_column_not_null_error' => 'Field %s must be NULL in config and database, since it contains date', 'user_column_default_error' => 'Field %s must be have NULL as default value, since it holds user id', 'type_missing' => 'Type definition for field %s missing in config', 'virtual_type_missing' => 'Type definition for virtual field %s missing in config', 'virtual_default_missing' => 'Default value for virtual field %s not set in config', 'virtual_not_null_error' => 'Virtual field %s cannot be not null, since it doesn\'t exist in database', 'invalid_calculated_field' => 'Calculated field %s is missing corresponding virtual field', ); $config_errors = Array (); $fields = $config->getFields(); $table_name = preg_replace('/^' . preg_quote(TABLE_PREFIX, '/') . '(.*)/', '\\1', $table_name); // remove table prefix if ( $fields ) { // validate unit config field declaration in relation to database table structure foreach ($res as $field) { $f_name = $field['Field']; if ( preg_match('/l[\d]+_[\w]/', $f_name) ) { // skip multilingual fields continue; } if ( !array_key_exists($f_name, $fields) ) { $config_errors[] = sprintf($error_messages['field_not_found'], $f_name); } else { $db_default = $field['Default']; if ( is_numeric($db_default) ) { $db_default = preg_match('/[\.,]/', $db_default) ? (float)$db_default : (int)$db_default; } $default_missing = false; $options = $fields[$f_name]; $not_null = isset($options['not_null']) && $options['not_null']; $formatter = array_key_exists('formatter', $options) ? $options['formatter'] : false; if ( !array_key_exists('default', $options) ) { $config_errors[] = sprintf($error_messages['default_missing'], $f_name); $default_missing = true; } if ( $field['Null'] != 'YES' ) { // field is NOT NULL in database (MySQL5 for null returns "NO", but MySQL4 returns "") if ( $f_name != $config->getIDField() && !isset($options['not_null']) /*&& !isset($options['required'])*/ ) { $config_errors[] = sprintf($error_messages['not_null_error1'], $f_name); } if ( $not_null && !isset($options['default']) ) { $config_errors[] = sprintf($error_messages['not_null_error2'], $f_name); } } elseif ( $not_null ) { $config_errors[] = sprintf($error_messages['not_null_error3'], $f_name); } if ( ($formatter == 'kDateFormatter') && $not_null ) { $config_errors[] = sprintf($error_messages['date_column_not_null_error'], $f_name); } // columns, holding userid should have NULL as default value if ( array_key_exists('type', $options) && !$default_missing ) { // both type and default value set if ( preg_match('/ById$/', $f_name) && $options['default'] !== null ) { $config_errors[] = sprintf($error_messages['user_column_default_error'], $f_name); } } if ( !array_key_exists('type', $options) ) { $config_errors[] = sprintf($error_messages['type_missing'], $f_name); } if ( !$default_missing && ($field['Type'] != 'text') ) { if ( is_null($db_default) && $not_null ) { $db_default = $options['type'] == 'string' ? '' : 0; } if ( $f_name == $config->getIDField() && $options['type'] != 'string' && $options['default'] !== 0 ) { $config_errors[] = sprintf($error_messages['invalid_default'], 'IDField ', $f_name, $this->varDump($options['default']), $this->varDump($field['Default'])); } else if ( ((string)$options['default'] != '#NOW#') && ($db_default !== $options['default']) && !in_array($options['type'], $float_types) ) { $config_errors[] = sprintf($error_messages['invalid_default'], '', $f_name, $this->varDump($options['default']), $this->varDump($db_default)); } } } } } // validate virtual fields if ( $config->getVirtualFields() ) { foreach ($config->getVirtualFields() as $f_name => $options) { if ( !array_key_exists('type', $options) ) { $config_errors[] = sprintf($error_messages['virtual_type_missing'], $f_name); } if ( array_key_exists('not_null', $options) ) { $config_errors[] = sprintf($error_messages['virtual_not_null_error'], $f_name); } if ( !array_key_exists('default', $options) ) { $config_errors[] = sprintf($error_messages['virtual_default_missing'], $f_name); } } } // validate calculated fields if ( $config->getCalculatedFieldSpecials() ) { $virtual_fields = $config->getVirtualFields(); foreach ($config->getCalculatedFieldSpecials() as $special) { foreach ($config->getCalculatedFieldsBySpecial($special) as $calculated_field => $calculated_field_expr) { if ( !isset($virtual_fields[$calculated_field]) ) { $config_errors[] = sprintf($error_messages['invalid_calculated_field'], $calculated_field); } } } $config_errors = array_unique($config_errors); } if ( $config_errors ) { $error_prefix = 'Config Error' . (count($config_errors) > 1 ? 's' : '') . ': for prefix ' . $config_link . ' (' . $table_name . ') in unit config:
'; $config_errors = $error_prefix . '   ' . implode('
   ', $config_errors); kUtil::safeDefine('DBG_RAISE_ON_WARNINGS', 1); $debugger->appendHTML($config_errors); $debugger->WarningCount++; } } function varDump($value) { return ''.var_export($value, true).' of '.gettype($value); } function postProcessConfig($prefix, $config_key, $dst_prefix_var) { $main_config = $this->configData[$prefix]; $sub_configs = $main_config->getSetting($config_key); if ( !$sub_configs ) { return Array (); } $processed = Array (); $main_config->setSetting($config_key, null); foreach ($sub_configs as $sub_prefix => $sub_config_data) { if ( $config_key == 'AggregateConfigs' && !isset($this->configData[$sub_prefix]) ) { $this->loadConfig($sub_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]; } $this->postProcessConfig($sub_prefix, $config_key, $dst_prefix_var); if ( $config_key == 'AggregateConfigs' ) { $processed = array_merge($this->postProcessConfig($sub_prefix, 'Clones', 'prefix'), $processed); } elseif ( $this->ProcessAllConfigs ) { $this->parseConfig($sub_prefix); } 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) { $config_found = file_exists(FULL_PATH . $filename) && $this->configAllowed($filename); if ( defined('DEBUG_MODE') && DEBUG_MODE && defined('DBG_PROFILE_INCLUDES') && DBG_PROFILE_INCLUDES ) { if ( in_array($filename, get_included_files()) ) { return ''; } global $debugger; if ( $config_found ) { $file = FULL_PATH . $filename; $file_crc = crc32($file); $debugger->ProfileStart('inc_' . $file_crc, $file); include_once($file); $debugger->ProfileFinish('inc_' . $file_crc); $debugger->profilerAddTotal('includes', 'inc_' . $file_crc); } } elseif ( $config_found ) { include_once(FULL_PATH . $filename); } if ( $config_found ) { /* @var $config kUnitConfig|Array */ if ( isset($config) && $config ) { // config file is included for 1st time -> save it's content for future processing if ( !is_object($config) ) { $prefix = array_key_exists('Prefix', $config) ? $config['Prefix'] : ''; $config = new kUnitConfig($prefix, $config); } else { $prefix = $config->getPrefix(); } preg_match($this->_moduleFolderRegExp, $filename, $regs); $config->setModuleFolder(str_replace(DIRECTORY_SEPARATOR, '/', $regs[1])); $config->setBasePath(dirname(FULL_PATH . $filename)); if ( $config->getAdminTemplatePath() !== false ) { // append template base folder for admin templates path of this prefix $module_templates = $regs[1] == 'core' ? '' : substr($regs[1], 8) . '/'; $config->setAdminTemplatePath($module_templates . $config->getAdminTemplatePath()); } if ( array_key_exists($prefix, $this->prefixFiles) && ($this->prefixFiles[$prefix] != $filename) ) { trigger_error( 'Single unit config prefix "' . $prefix . '" ' . 'is used in multiple unit config files: ' . '"' . $this->prefixFiles[$prefix] . '", "' . $filename . '"', E_USER_WARNING ); } $this->configData[$prefix] = $config; $this->prefixFiles[$prefix] = $filename; return $prefix; } else { $prefix = array_search($filename, $this->prefixFiles); if ( $prefix ) { // attempt is made to include config file twice or more, but include_once prevents that, // but file exists on hdd, then it is already saved to all required arrays, just return it's prefix return $prefix; } } } return 'dummy'; } function loadConfig($prefix) { if ( !isset($this->prefixFiles[$prefix]) ) { throw new Exception('Configuration file for prefix "' . $prefix . '" is unknown'); return ; } $file = $this->prefixFiles[$prefix]; $prefix = $this->PreloadConfigFile($file); if ($this->FinalStage) { // run prefix OnAfterConfigRead so all // hooks to it can define their clonses $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) { if (in_array($prefix, $this->AfterConfigProcessed)) { return ; } $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) { if ( !isset($this->configData[$prefix]) ) { $this->loadConfig($prefix); } return $this->configData[$prefix]; } /** * Returns prefixes of unit configs, that were registered * * @return Array * @access public */ public function getPrefixes() { return array_keys($this->configData); } protected function getClasses($prefix) { $config = $this->configData[$prefix]; $class_params = Array ('ItemClass', 'ListClass', 'EventHandlerClass', 'TagProcessorClass'); $register_classes = $config->getRegisterClasses(); foreach ($class_params as $param_name) { $value = $config->getSetting($param_name); if ( !$value ) { continue; } $value['pseudo'] = $this->getPseudoByOptionName($param_name, $prefix); $config->setSetting($param_name, $value); $register_classes[] = $value; } 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[$option_name], $prefix); } /** * Get's config file name based * on folder name supplied * * @param string $folderPath * @return string * @access private */ function getConfigName($folderPath) { return $folderPath . DIRECTORY_SEPARATOR . basename($folderPath) . '_config.php'; } /** * Checks if config file is allowed for includion (if module of config is installed) * * @param string $config_path relative path from in-portal directory */ function configAllowed($config_path) { static $module_paths = null; 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)) { // always allow to include configs from "core" module's folder return true; } if (!$this->Application->ModuleInfo) { return false; } if (!isset($module_paths)) { $module_paths = Array (); foreach ($this->Application->ModuleInfo as $module_name => $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); // config file path starts with module folder path return in_array($rets[1], $module_paths); } /** * Returns true if config exists and is allowed for reading * * @param string $prefix * @return bool */ function prefixRegistred($prefix) { return isset($this->prefixFiles[$prefix]) ? true : false; } /** * Returns config file for given prefix * * @param string $prefix * @return string */ function getPrefixFile($prefix) { return array_key_exists($prefix, $this->prefixFiles) ? $this->prefixFiles[$prefix] : false; } 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); } } }