Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1051887
unit_config_reader.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Fri, Jul 4, 5:56 AM
Size
18 KB
Mime Type
text/x-php
Expires
Sun, Jul 6, 5:56 AM (19 h, 39 m)
Engine
blob
Format
Raw Data
Handle
679390
Attached To
rINP In-Portal
unit_config_reader.php
View Options
<?php
/**
* @version $Id: unit_config_reader.php 15732 2013-04-18 17:50:13Z alex $
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined
(
'FULL_PATH'
)
or
die
(
'restricted access!'
);
class
kUnitConfigReader
extends
kBase
implements
kiCacheable
{
/**
* Configs reader
*
* @var Array|kUnitConfig[]
* @access private
*/
var
$configData
=
Array
();
var
$configFiles
=
Array
();
var
$CacheExpired
=
false
;
var
$prefixFiles
=
array
();
var
$ProcessAllConfigs
=
false
;
var
$FinalStage
=
false
;
var
$StoreCache
=
false
;
var
$AfterConfigProcessed
=
array
();
/**
* Escaped directory separator for using in regular expressions
*
* @var string
*/
var
$_directorySeparator
=
''
;
/**
* Regular expression for detecting module folder
*
* @var string
*/
var
$_moduleFolderRegExp
=
''
;
/**
* Folders to skip during unit config search
*
* @var Array
*/
var
$_skipFolders
=
Array
(
'CVS'
,
'.svn'
,
'admin_templates'
,
'libchart'
);
/**
* Creates instance of unit config reader
*
*/
public
function
__construct
()
{
parent
::
__construct
();
$this
->
_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 <strong>'
.
$filename
.
'</strong>'
);
}
}
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
;
}
$config
->
parse
();
}
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
->
configData
[
$prefix
]->
parse
();
}
}
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
;
}
$config
->
validate
();
}
}
}
}
/**
* 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
);
}
}
}
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
->
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
)
{
$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
));
$config
->
setFilename
(
$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 "<strong>'
.
$prefix
.
'</strong>" '
.
'is used in multiple unit config files: '
.
'"<strong>'
.
$this
->
prefixFiles
[
$prefix
]
.
'</strong>", "<strong>'
.
$filename
.
'</strong>"'
,
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 "<strong>'
.
$prefix
.
'</strong>" 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 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
)
{
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
);
}
/**
* 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
);
}
}
}
Event Timeline
Log In to Comment