_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);
}
}
}