diff --git a/app/code/community/Mage/Core/Model/Cache.php b/app/code/community/Mage/Core/Model/Cache.php
new file mode 100644
index 0000000..a587240
--- /dev/null
+++ b/app/code/community/Mage/Core/Model/Cache.php
@@ -0,0 +1,720 @@
+ 1,
+ 'hashed_directory_perm' => 0777,
+ 'file_name_prefix' => 'mage',
+ );
+
+ /**
+ * List of available request processors
+ *
+ * @var array
+ */
+ protected $_requestProcessors = array();
+
+ /**
+ * Disallow cache saving
+ *
+ * @var bool
+ */
+ protected $_disallowSave = false;
+
+ /**
+ * List of allowed cache options
+ *
+ * @var array
+ */
+ protected $_allowedCacheOptions;
+
+
+ /**
+ * DB connection
+ *
+ * @var string|null
+ */
+ protected $_dbConnection = 'core_write';
+
+ /**
+ * Class constructor. Initialize cache instance based on options
+ *
+ * @param array $options
+ */
+ public function __construct(array $options = array())
+ {
+ $this->_defaultBackendOptions['cache_dir'] = isset($options['cache_dir']) ? $options['cache_dir'] :
+ Mage::getBaseDir('cache');
+ /**
+ * Initialize id prefix
+ */
+ $this->_idPrefix = isset($options['id_prefix']) ? $options['id_prefix'] : '';
+ if (!$this->_idPrefix && isset($options['prefix'])) {
+ $this->_idPrefix = $options['prefix'];
+ }
+ if (empty($this->_idPrefix)) {
+ $this->_idPrefix = substr(md5(Mage::getConfig()->getOptions()->getEtcDir()), 0, 3).'_';
+ }
+
+ $backend = $this->_getBackendOptions($options);
+ $frontend = $this->_getFrontendOptions($options);
+
+ $this->_frontend = Zend_Cache::factory('Varien_Cache_Core', $backend['type'], $frontend, $backend['options'],
+ true, true, true
+ );
+
+ if (isset($options['request_processors'])) {
+ $this->_requestProcessors = $options['request_processors'];
+ }
+
+ if (isset($options['disallow_save'])) {
+ $this->_disallowSave = (bool)$options['disallow_save'];
+ }
+ }
+
+ /**
+ * Get cache backend options. Result array contain backend type ('type' key) and backend options ('options')
+ *
+ * @param array $cacheOptions
+ * @return array
+ */
+ protected function _getBackendOptions(array $cacheOptions)
+ {
+ $enable2levels = false;
+ $type = isset($cacheOptions['backend']) ? $cacheOptions['backend'] : $this->_defaultBackend;
+ if (isset($cacheOptions['backend_options']) && is_array($cacheOptions['backend_options'])) {
+ $options = $cacheOptions['backend_options'];
+ } else {
+ $options = array();
+ }
+
+ $backendType = false;
+ switch (strtolower($type)) {
+ case 'sqlite':
+ if (extension_loaded('sqlite') && isset($options['cache_db_complete_path'])) {
+ $backendType = 'Sqlite';
+ }
+ break;
+ case 'memcached':
+ if (extension_loaded('memcached')) {
+ if (isset($cacheOptions['memcached'])) {
+ $options = $cacheOptions['memcached'];
+ }
+ $enable2levels = true;
+ $backendType = 'Libmemcached';
+ } elseif (extension_loaded('memcache')) {
+ if (isset($cacheOptions['memcached'])) {
+ $options = $cacheOptions['memcached'];
+ }
+ $enable2levels = true;
+ $backendType = 'Memcached';
+ }
+ break;
+ case 'apc':
+ if (extension_loaded('apc') && ini_get('apc.enabled')) {
+ $enable2levels = true;
+ $backendType = 'Apc';
+ }
+ break;
+ case 'xcache':
+ if (extension_loaded('xcache')) {
+ $enable2levels = true;
+ $backendType = 'Xcache';
+ }
+ break;
+ case 'eaccelerator':
+ case 'varien_cache_backend_eaccelerator':
+ if (extension_loaded('eaccelerator') && ini_get('eaccelerator.enable')) {
+ $enable2levels = true;
+ $backendType = 'Varien_Cache_Backend_Eaccelerator';
+ }
+ break;
+ case 'varien_cache_backend_database':
+ case 'database':
+ $backendType = 'Varien_Cache_Backend_Database';
+ $options = $this->getDbAdapterOptions($options);
+ break;
+ default:
+ if ($type != $this->_defaultBackend) {
+ try {
+ if (class_exists($type, true)) {
+ $implements = class_implements($type, true);
+ if (in_array('Zend_Cache_Backend_Interface', $implements)) {
+ $backendType = $type;
+ if (isset($options['enable_two_levels'])) {
+ $enable2levels = true;
+ }
+ }
+ }
+ } catch (Exception $e) {
+ }
+ }
+ }
+
+ if (!$backendType) {
+ $backendType = $this->_defaultBackend;
+ foreach ($this->_defaultBackendOptions as $option => $value) {
+ if (!array_key_exists($option, $options)) {
+ $options[$option] = $value;
+ }
+ }
+ }
+
+ $backendOptions = array('type' => $backendType, 'options' => $options);
+ if ($enable2levels) {
+ $backendOptions = $this->_getTwoLevelsBackendOptions($backendOptions, $cacheOptions);
+ }
+ return $backendOptions;
+ }
+
+ /**
+ * Get options for database backend type
+ *
+ * @param array $options
+ * @return array
+ */
+ protected function getDbAdapterOptions(array $options = array())
+ {
+ if (isset($options['connection'])) {
+ $this->_dbConnection = $options['connection'];
+ }
+
+ $options['adapter_callback'] = array($this, 'getDbAdapter');
+ $options['data_table'] = Mage::getSingleton('core/resource')->getTableName('core/cache');
+ $options['tags_table'] = Mage::getSingleton('core/resource')->getTableName('core/cache_tag');
+ return $options;
+ }
+
+ /**
+ * Initialize two levels backend model options
+ *
+ * @param array $fastOptions fast level backend type and options
+ * @param array $cacheOptions all cache options
+ * @return array
+ */
+ protected function _getTwoLevelsBackendOptions($fastOptions, $cacheOptions)
+ {
+ $options = array();
+ $options['fast_backend'] = $fastOptions['type'];
+ $options['fast_backend_options'] = $fastOptions['options'];
+ $options['fast_backend_custom_naming'] = true;
+ $options['fast_backend_autoload'] = true;
+ $options['slow_backend_custom_naming'] = true;
+ $options['slow_backend_autoload'] = true;
+
+ if (isset($cacheOptions['auto_refresh_fast_cache'])) {
+ $options['auto_refresh_fast_cache'] = (bool)$cacheOptions['auto_refresh_fast_cache'];
+ } else {
+ $options['auto_refresh_fast_cache'] = false;
+ }
+ if (isset($cacheOptions['slow_backend'])) {
+ $options['slow_backend'] = $cacheOptions['slow_backend'];
+ } else {
+ $options['slow_backend'] = $this->_defaultBackend;
+ }
+ if (isset($cacheOptions['slow_backend_options'])) {
+ $options['slow_backend_options'] = $cacheOptions['slow_backend_options'];
+ } else {
+ $options['slow_backend_options'] = $this->_defaultBackendOptions;
+ }
+ if ($options['slow_backend'] == 'database') {
+ $options['slow_backend'] = 'Varien_Cache_Backend_Database';
+ $options['slow_backend_options'] = $this->getDbAdapterOptions($options['slow_backend_options']);
+ if (isset($cacheOptions['slow_backend_store_data'])) {
+ $options['slow_backend_options']['store_data'] = (bool)$cacheOptions['slow_backend_store_data'];
+ } else {
+ $options['slow_backend_options']['store_data'] = false;
+ }
+ }
+
+ $backend = array(
+ 'type' => 'TwoLevels',
+ 'options' => $options
+ );
+ return $backend;
+ }
+
+ /**
+ * Get options of cache frontend (options of Zend_Cache_Core)
+ *
+ * @param array $cacheOptions
+ * @return array
+ */
+ protected function _getFrontendOptions(array $cacheOptions)
+ {
+ $options = isset($cacheOptions['frontend_options']) ? $cacheOptions['frontend_options'] : array();
+ if (!array_key_exists('caching', $options)) {
+ $options['caching'] = true;
+ }
+ if (!array_key_exists('lifetime', $options)) {
+ $options['lifetime'] = isset($cacheOptions['lifetime']) ? $cacheOptions['lifetime']
+ : self::DEFAULT_LIFETIME;
+ }
+ if (!array_key_exists('automatic_cleaning_factor', $options)) {
+ $options['automatic_cleaning_factor'] = 0;
+ }
+ $options['cache_id_prefix'] = $this->_idPrefix;
+ return $options;
+ }
+
+ /**
+ * Prepare unified valid identifier with prefix
+ *
+ * @param string $id
+ * @return string
+ */
+ protected function _id($id)
+ {
+ if ($id) {
+ $id = strtoupper($id);
+ }
+ return $id;
+ }
+
+ /**
+ * Prepare cache tags.
+ *
+ * @param array $tags
+ * @return array
+ */
+ protected function _tags($tags = array())
+ {
+ foreach ($tags as $key => $value) {
+ $tags[$key] = $this->_id($value);
+ }
+ return $tags;
+ }
+
+ /**
+ * Get cache frontend API object
+ *
+ * @return Varien_Cache_Core
+ */
+ public function getFrontend()
+ {
+ return $this->_frontend;
+ }
+
+ /**
+ * Load data from cache by id
+ *
+ * @param string $id
+ * @return string
+ */
+ public function load($id)
+ {
+ return $this->getFrontend()->load($this->_id($id));
+ }
+
+ /**
+ * Save data
+ *
+ * @param string $data
+ * @param string $id
+ * @param array $tags
+ * @param int $lifeTime
+ * @return bool
+ */
+ public function save($data, $id, $tags = array(), $lifeTime = null)
+ {
+ //Start patch for 100 routers problem
+ if (strpos($id,'config_global_stores_') !== false) {
+ $xml = new SimpleXMLElement($data);
+ $xmlPath = $xml->xpath('web/routers/standard');
+
+ if (count($xmlPath) != 1) {
+ $e = new Exception();
+ Mage::log($e->getTraceAsString(), null, 'corrupt-cache.log', true);
+
+ //Returning true to prevent it from saving an incomplete cache entry
+ return true;
+ }
+ }
+
+ if ($this->_disallowSave) {
+ return true;
+ }
+
+ /**
+ * Add global magento cache tag to all cached data exclude config cache
+ */
+ if (!in_array(Mage_Core_Model_Config::CACHE_TAG, $tags)) {
+ $tags[] = Mage_Core_Model_App::CACHE_TAG;
+ }
+ return $this->getFrontend()->save((string)$data, $this->_id($id), $this->_tags($tags), $lifeTime);
+ }
+
+ /**
+ * Remove cached data by identifier
+ *
+ * @param string $id
+ * @return bool
+ */
+ public function remove($id)
+ {
+ return $this->getFrontend()->remove($this->_id($id));
+ }
+
+ /**
+ * Clean cached data by specific tag
+ *
+ * @param array $tags
+ * @return bool
+ */
+ public function clean($tags=array())
+ {
+ $mode = Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG;
+ if (!empty($tags)) {
+ if (!is_array($tags)) {
+ $tags = array($tags);
+ }
+ $res = $this->getFrontend()->clean($mode, $this->_tags($tags));
+ } else {
+ $res = $this->getFrontend()->clean($mode, array(Mage_Core_Model_App::CACHE_TAG));
+ $res = $res && $this->getFrontend()->clean($mode, array(Mage_Core_Model_Config::CACHE_TAG));
+ }
+ return $res;
+ }
+
+ /**
+ * Flush cached data
+ *
+ * @return bool
+ */
+ public function flush()
+ {
+ $res = $this->getFrontend()->clean();
+ return $res;
+ }
+
+ /**
+ * Get adapter for database cache backend model
+ *
+ * @return Zend_Db_Adapter_Abstract
+ */
+ public function getDbAdapter()
+ {
+ return Mage::getSingleton('core/resource')->getConnection($this->_dbConnection);
+ }
+
+ /**
+ * Get cache resource model
+ *
+ * @return Mage_Core_Model_Mysql4_Cache
+ */
+ protected function _getResource()
+ {
+ return Mage::getResourceSingleton('core/cache');
+ }
+
+ /**
+ * Initialize cache types options
+ *
+ * @return Mage_Core_Model_Cache
+ */
+ protected function _initOptions()
+ {
+ $options = $this->load(self::OPTIONS_CACHE_ID);
+ if ($options === false) {
+ $options = $this->_getResource()->getAllOptions();
+ if (is_array($options)) {
+ $this->_allowedCacheOptions = $options;
+ $this->save(serialize($this->_allowedCacheOptions), self::OPTIONS_CACHE_ID);
+ } else {
+ $this->_allowedCacheOptions = array();
+ }
+ } else {
+ $this->_allowedCacheOptions = unserialize($options);
+ }
+
+ if (Mage::getConfig()->getOptions()->getData('global_ban_use_cache')) {
+ foreach ($this->_allowedCacheOptions as $key => $val) {
+ $this->_allowedCacheOptions[$key] = false;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Save cache usage options
+ *
+ * @param array $options
+ * @return Mage_Core_Model_Cache
+ */
+ public function saveOptions($options)
+ {
+ $this->remove(self::OPTIONS_CACHE_ID);
+ $this->_getResource()->saveAllOptions($options);
+ return $this;
+ }
+
+ /**
+ * Check if cache can be used for specific data type
+ *
+ * @param string $typeCode
+ * @return bool
+ */
+ public function canUse($typeCode)
+ {
+ if (is_null($this->_allowedCacheOptions)) {
+ $this->_initOptions();
+ }
+
+ if (empty($typeCode)) {
+ return $this->_allowedCacheOptions;
+ }
+
+ if (isset($this->_allowedCacheOptions[$typeCode])) {
+ return (bool)$this->_allowedCacheOptions[$typeCode];
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Disable cache usage for specific data type
+ *
+ * @param string $typeCode
+ * @return Mage_Core_Model_Cache
+ */
+ public function banUse($typeCode)
+ {
+ $this->_allowedCacheOptions[$typeCode] = false;
+ return $this;
+ }
+
+ /**
+ * Get cache tags by cache type from configuration
+ *
+ * @param string $type
+ * @return array
+ */
+ public function getTagsByType($type)
+ {
+ $path = self::XML_PATH_TYPES . '/' . $type . '/tags';
+ $tagsConfig = Mage::getConfig()->getNode($path);
+ if ($tagsConfig) {
+ $tags = (string) $tagsConfig;
+ $tags = explode(',', $tags);
+ } else {
+ $tags = false;
+ }
+ return $tags;
+ }
+
+ /**
+ * Get information about all declared cache types
+ *
+ * @return array
+ */
+ public function getTypes()
+ {
+ $types = array();
+ $config = Mage::getConfig()->getNode(self::XML_PATH_TYPES);
+ if ($config) {
+ foreach ($config->children() as $type=>$node) {
+ $types[$type] = new Varien_Object(array(
+ 'id' => $type,
+ 'cache_type' => Mage::helper('core')->__((string)$node->label),
+ 'description' => Mage::helper('core')->__((string)$node->description),
+ 'tags' => strtoupper((string) $node->tags),
+ 'status' => (int)$this->canUse($type),
+ ));
+ }
+ }
+ return $types;
+ }
+
+ /**
+ * Get invalidate types codes
+ *
+ * @return array
+ */
+ protected function _getInvalidatedTypes()
+ {
+ $types = $this->load(self::INVALIDATED_TYPES);
+ if ($types) {
+ $types = unserialize($types);
+ } else {
+ $types = array();
+ }
+ return $types;
+ }
+
+ /**
+ * Save invalidated cache types
+ *
+ * @param array $types
+ * @return Mage_Core_Model_Cache
+ */
+ protected function _saveInvalidatedTypes($types)
+ {
+ $this->save(serialize($types), self::INVALIDATED_TYPES);
+ return $this;
+ }
+
+ /**
+ * Get array of all invalidated cache types
+ *
+ * @return array
+ */
+ public function getInvalidatedTypes()
+ {
+ $invalidatedTypes = array();
+ $types = $this->_getInvalidatedTypes();
+ if ($types) {
+ $allTypes = $this->getTypes();
+ foreach ($types as $type => $flag) {
+ if (isset($allTypes[$type]) && $this->canUse($type)) {
+ $invalidatedTypes[$type] = $allTypes[$type];
+ }
+ }
+ }
+ return $invalidatedTypes;
+ }
+
+ /**
+ * Mark specific cache type(s) as invalidated
+ *
+ * @param string|array $typeCode
+ * @return Mage_Core_Model_Cache
+ */
+ public function invalidateType($typeCode)
+ {
+ $types = $this->_getInvalidatedTypes();
+ if (!is_array($typeCode)) {
+ $typeCode = array($typeCode);
+ }
+ foreach ($typeCode as $code) {
+ $types[$code] = 1;
+ }
+ $this->_saveInvalidatedTypes($types);
+ return $this;
+ }
+
+ /**
+ * Clean cached data for specific cache type
+ *
+ * @param string $typeCode
+ * @return Mage_Core_Model_Cache
+ */
+ public function cleanType($typeCode)
+ {
+ $tags = $this->getTagsByType($typeCode);
+ $this->clean($tags);
+
+ $types = $this->_getInvalidatedTypes();
+ unset($types[$typeCode]);
+ $this->_saveInvalidatedTypes($types);
+ return $this;
+ }
+
+ /**
+ * Try to get response body from cache storage with predefined processors
+ *
+ * @return bool
+ */
+ public function processRequest()
+ {
+ if (empty($this->_requestProcessors)) {
+ return false;
+ }
+
+ $content = false;
+ foreach ($this->_requestProcessors as $processor) {
+ $processor = $this->_getProcessor($processor);
+ if ($processor) {
+ $content = $processor->extractContent($content);
+ }
+ }
+
+ if ($content) {
+ Mage::app()->getResponse()->appendBody($content);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get request processor object
+ */
+ protected function _getProcessor($processor)
+ {
+ return new $processor;
+ }
+}
+
diff --git a/app/code/community/Mage/Core/Model/Config.php b/app/code/community/Mage/Core/Model/Config.php
new file mode 100644
index 0000000..9099cad
--- /dev/null
+++ b/app/code/community/Mage/Core/Model/Config.php
@@ -0,0 +1,1684 @@
+
+ */
+class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base
+{
+ const CACHE_TAG = 'CONFIG';
+
+ /**
+ * Flag which allow use cache logic
+ *
+ * @var bool
+ */
+ protected $_useCache = false;
+
+ /**
+ * Instructions for spitting config cache
+ * array(
+ * $sectionName => $recursionLevel
+ * )
+ * Recursion level provide availability cache subnodes separatly
+ *
+ * @var array
+ */
+ protected $_cacheSections = array(
+ 'admin' => 0,
+ 'adminhtml' => 0,
+ 'crontab' => 0,
+ 'install' => 0,
+ 'stores' => 1,
+ 'websites' => 0
+ );
+
+ /**
+ * Loaded Configuration by cached sections
+ *
+ * @var array
+ */
+ protected $_cacheLoadedSections = array();
+
+ /**
+ * Configuration options
+ *
+ * @var Mage_Core_Model_Config_Options
+ */
+ protected $_options;
+
+ /**
+ * Storage for generated class names
+ *
+ * @var array
+ */
+ protected $_classNameCache = array();
+
+ /**
+ * Storage for generated block class names
+ *
+ * @var unknown_type
+ */
+ protected $_blockClassNameCache = array();
+
+ /**
+ * Storage of validated secure urls
+ *
+ * @var array
+ */
+ protected $_secureUrlCache = array();
+
+ /**
+ * System environment server variables
+ *
+ * @var array
+ */
+ protected $_distroServerVars;
+
+ /**
+ * Array which is using for replace placeholders of server variables
+ *
+ * @var array
+ */
+ protected $_substServerVars;
+
+ /**
+ * Resource model
+ * Used for operations with DB
+ *
+ * @var Mage_Core_Model_Mysql4_Config
+ */
+ protected $_resourceModel;
+
+ /**
+ * Configuration for events by area
+ *
+ * @var array
+ */
+ protected $_eventAreas;
+
+ /**
+ * Flag cache for existing or already created directories
+ *
+ * @var array
+ */
+ protected $_dirExists = array();
+
+ /**
+ * Flach which allow using cache for config initialization
+ *
+ * @var bool
+ */
+ protected $_allowCacheForInit = true;
+
+ /**
+ * Property used during cache save process
+ *
+ * @var array
+ */
+ protected $_cachePartsForSave = array();
+
+ /**
+ * Empty configuration object for loading and megring configuration parts
+ *
+ * @var Mage_Core_Model_Config_Base
+ */
+ protected $_prototype;
+
+ /**
+ * Flag which identify what local configuration is loaded
+ *
+ * @var bool
+ */
+ protected $_isLocalConfigLoaded = false;
+
+ /**
+ * Depricated properties
+ *
+ * @deprecated
+ */
+ protected $_baseDirCache = array();
+ protected $_customEtcDir = null;
+
+ /**
+ * Flag which allow to use modules from local code pool
+ *
+ * @var bool
+ */
+ protected $_canUseLocalModules = null;
+
+ /**
+ * Active modules array per namespace
+ * @var array
+ */
+ private $_moduleNamespaces = null;
+
+ /**
+ * Modules allowed to load
+ * If empty - all modules are allowed
+ *
+ * @var array
+ */
+ protected $_allowedModules = array();
+
+ /**
+ * Class construct
+ *
+ * @param mixed $sourceData
+ */
+ public function __construct($sourceData=null)
+ {
+ $this->setCacheId('config_global');
+ $this->_options = new Mage_Core_Model_Config_Options($sourceData);
+ $this->_prototype = new Mage_Core_Model_Config_Base();
+ $this->_cacheChecksum = null;
+ parent::__construct($sourceData);
+ }
+
+ /**
+ * Get config resource model
+ *
+ * @return Mage_Core_Store_Mysql4_Config
+ */
+ public function getResourceModel()
+ {
+ if (is_null($this->_resourceModel)) {
+ $this->_resourceModel = Mage::getResourceModel('core/config');
+ }
+ return $this->_resourceModel;
+ }
+
+ /**
+ * Get configuration options object
+ *
+ * @return Mage_Core_Model_Config_Options
+ */
+ public function getOptions()
+ {
+ return $this->_options;
+ }
+
+ /**
+ * Set configuration options
+ *
+ * @param array $options
+ * @return Mage_Core_Model_Config
+ */
+ public function setOptions($options)
+ {
+ if (is_array($options)) {
+ $this->getOptions()->addData($options);
+ }
+ return $this;
+ }
+
+ /**
+ * Initialization of core configuration
+ *
+ * @return Mage_Core_Model_Config
+ */
+ public function init($options=array())
+ {
+ $this->setCacheChecksum(null);
+ $this->_cacheLoadedSections = array();
+ $this->setOptions($options);
+ $this->loadBase();
+
+ $cacheLoad = $this->loadModulesCache();
+ if ($cacheLoad) {
+ return $this;
+ }
+
+ //100 Router Fix Start
+ $this->_useCache = false;
+ //100 Router Fix End
+
+ $this->loadModules();
+ $this->loadDb();
+ $this->saveCache();
+ return $this;
+ }
+
+ /**
+ * Load base system configuration (config.xml and local.xml files)
+ *
+ * @return Mage_Core_Model_Config
+ */
+ public function loadBase()
+ {
+ $etcDir = $this->getOptions()->getEtcDir();
+ $files = glob($etcDir.DS.'*.xml');
+ $this->loadFile(current($files));
+ while ($file = next($files)) {
+ $merge = clone $this->_prototype;
+ $merge->loadFile($file);
+ $this->extend($merge);
+ }
+ if (in_array($etcDir.DS.'local.xml', $files)) {
+ $this->_isLocalConfigLoaded = true;
+ }
+ return $this;
+ }
+
+ /**
+ * Load cached modules configuration
+ *
+ * @return bool
+ */
+ public function loadModulesCache()
+ {
+ if (Mage::isInstalled(array('etc_dir' => $this->getOptions()->getEtcDir()))) {
+ if ($this->_canUseCacheForInit()) {
+ Varien_Profiler::start('mage::app::init::config::load_cache');
+ $loaded = $this->loadCache();
+ Varien_Profiler::stop('mage::app::init::config::load_cache');
+ if ($loaded) {
+ $this->_useCache = true;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Load modules configuration
+ *
+ * @return Mage_Core_Model_Config
+ */
+ public function loadModules()
+ {
+ Varien_Profiler::start('config/load-modules');
+ $this->_loadDeclaredModules();
+
+ $resourceConfig = sprintf('config.%s.xml', $this->_getResourceConnectionModel('core'));
+ $this->loadModulesConfiguration(array('config.xml',$resourceConfig), $this);
+
+ /**
+ * Prevent local.xml directives overwriting
+ */
+ $mergeConfig = clone $this->_prototype;
+ $this->_isLocalConfigLoaded = $mergeConfig->loadFile($this->getOptions()->getEtcDir().DS.'local.xml');
+ if ($this->_isLocalConfigLoaded) {
+ $this->extend($mergeConfig);
+ }
+
+ $this->applyExtends();
+ Varien_Profiler::stop('config/load-modules');
+ return $this;
+ }
+
+ /**
+ * Check if local configuration (DB connection, etc) is loaded
+ *
+ * @return bool
+ */
+ public function isLocalConfigLoaded()
+ {
+ return $this->_isLocalConfigLoaded;
+ }
+
+ /**
+ * Load config data from DB
+ *
+ * @return Mage_Core_Model_Config
+ */
+ public function loadDb()
+ {
+ if ($this->_isLocalConfigLoaded && Mage::isInstalled()) {
+ Varien_Profiler::start('config/load-db');
+ $dbConf = $this->getResourceModel();
+ $dbConf->loadToXml($this);
+ Varien_Profiler::stop('config/load-db');
+ }
+ return $this;
+ }
+
+ /**
+ * Reinitialize configuration
+ *
+ * @param array $options
+ * @return Mage_Core_Model_Config
+ */
+ public function reinit($options = array())
+ {
+ $this->_allowCacheForInit = false;
+ $this->_useCache = false;
+ return $this->init($options);
+ }
+
+ /**
+ * Check local modules enable/disable flag
+ * If local modules are disbled remove local modules path from include dirs
+ *
+ * return true if local modules enabled and false if disabled
+ *
+ * @return bool
+ */
+ protected function _canUseLocalModules()
+ {
+ if ($this->_canUseLocalModules !== null) {
+ return $this->_canUseLocalModules;
+ }
+
+ $disableLocalModules = (string)$this->getNode('global/disable_local_modules');
+ if (!empty($disableLocalModules)) {
+ $disableLocalModules = (('true' === $disableLocalModules) || ('1' === $disableLocalModules));
+ } else {
+ $disableLocalModules = false;
+ }
+
+ if ($disableLocalModules && !defined('COMPILER_INCLUDE_PATH')) {
+ set_include_path(
+ // excluded '/app/code/local'
+ BP . DS . 'app' . DS . 'code' . DS . 'community' . PS .
+ BP . DS . 'app' . DS . 'code' . DS . 'core' . PS .
+ BP . DS . 'lib' . PS .
+ Mage::registry('original_include_path')
+ );
+ }
+ $this->_canUseLocalModules = !$disableLocalModules;
+ return $this->_canUseLocalModules;
+ }
+
+ /**
+ * Check if cache can be used for config initialization
+ *
+ * @return bool
+ */
+ protected function _canUseCacheForInit()
+ {
+ return Mage::app()->useCache('config') && $this->_allowCacheForInit
+ && !$this->_loadCache($this->_getCacheLockId());
+ }
+
+ /**
+ * Retrieve cache object
+ *
+ * @return Zend_Cache_Frontend_File
+ */
+ public function getCache()
+ {
+ return Mage::app()->getCache();
+ }
+
+ /**
+ * Get lock flag cache identifier
+ *
+ * @return string
+ */
+ protected function _getCacheLockId()
+ {
+ return $this->getCacheId().'.lock';
+ }
+
+ /**
+ * Save configuration cache
+ *
+ * @param array $tags cache tags
+ * @return Mage_Core_Model_Config
+ */
+ public function saveCache($tags=array())
+ {
+ if (!Mage::app()->useCache('config')) {
+ return $this;
+ }
+ if (!in_array(self::CACHE_TAG, $tags)) {
+ $tags[] = self::CACHE_TAG;
+ }
+ $cacheLockId = $this->_getCacheLockId();
+ if ($this->_loadCache($cacheLockId)) {
+ return $this;
+ }
+
+ if (!empty($this->_cacheSections)) {
+ $xml = clone $this->_xml;
+ foreach ($this->_cacheSections as $sectionName => $level) {
+ $this->_saveSectionCache($this->getCacheId(), $sectionName, $xml, $level, $tags);
+ unset($xml->$sectionName);
+ }
+ $this->_cachePartsForSave[$this->getCacheId()] = $xml->asNiceXml('', false);
+ } else {
+ return parent::saveCache($tags);
+ }
+
+ $this->_saveCache(time(), $cacheLockId, array(), 60);
+ $this->removeCache();
+ foreach ($this->_cachePartsForSave as $cacheId => $cacheData) {
+ $this->_saveCache($cacheData, $cacheId, $tags, $this->getCacheLifetime());
+ }
+ unset($this->_cachePartsForSave);
+ $this->_removeCache($cacheLockId);
+ return $this;
+ }
+
+ /**
+ * Save cache of specified
+ *
+ * @param string $idPrefix cache id prefix
+ * @param string $sectionName
+ * @param Varien_Simplexml_Element $source
+ * @param int $recursionLevel
+ * @return Mage_Core_Model_Config
+ */
+ protected function _saveSectionCache($idPrefix, $sectionName, $source, $recursionLevel=0, $tags=array())
+ {
+ if ($source && $source->$sectionName) {
+ $cacheId = $idPrefix . '_' . $sectionName;
+ if ($recursionLevel > 0) {
+ foreach ($source->$sectionName->children() as $subSectionName => $node) {
+ $this->_saveSectionCache(
+ $cacheId, $subSectionName, $source->$sectionName, $recursionLevel-1, $tags
+ );
+ }
+ }
+ $this->_cachePartsForSave[$cacheId] = $source->$sectionName->asNiceXml('', false);
+ }
+ return $this;
+ }
+
+ /**
+ * Load config section cached data
+ *
+ * @param string $sectionName
+ * @return Varien_Simplexml_Element
+ */
+ protected function _loadSectionCache($sectionName)
+ {
+ $cacheId = $this->getCacheId() . '_' . $sectionName;
+ $xmlString = $this->_loadCache($cacheId);
+
+ /**
+ * If we can't load section cache (problems with cache storage)
+ */
+ if (!$xmlString) {
+ $this->_useCache = false;
+ $this->reinit($this->_options);
+ return false;
+ } else {
+ $xml = simplexml_load_string($xmlString, $this->_elementClass);
+ return $xml;
+ }
+ }
+
+ /**
+ * Load cached data by identifier
+ *
+ * @param string $id
+ * @return string
+ */
+ protected function _loadCache($id)
+ {
+ return Mage::app()->loadCache($id);
+ }
+
+ /**
+ * Save cache data
+ *
+ * @param string $data
+ * @param string $id
+ * @param array $tags
+ * @param false|int $lifetime
+ * @return Mage_Core_Model_Config
+ */
+ protected function _saveCache($data, $id, $tags=array(), $lifetime=false)
+ {
+ return Mage::app()->saveCache($data, $id, $tags, $lifetime);
+ }
+
+ /**
+ * Clear cache data by id
+ *
+ * @param string $id
+ * @return Mage_Core_Model_Config
+ */
+ protected function _removeCache($id)
+ {
+ return Mage::app()->removeCache($id);
+ }
+
+ /**
+ * Remove configuration cache
+ *
+ * @return Mage_Core_Model_Config
+ */
+ public function removeCache()
+ {
+ Mage::app()->cleanCache(array(self::CACHE_TAG));
+ return parent::removeCache();
+ }
+
+ /**
+ * Configuration cache clean process
+ *
+ * @return Mage_Core_Model_Config
+ */
+ public function cleanCache()
+ {
+ return $this->reinit();
+ }
+
+ /**
+ * Getter for section configuration object
+ *
+ * @param array $path
+ * @return Mage_Core_Model_Config_Element
+ */
+ protected function _getSectionConfig($path)
+ {
+ $section = $path[0];
+ if (!isset($this->_cacheSections[$section])) {
+ return false;
+ }
+ $sectionPath = array_slice($path, 0, $this->_cacheSections[$section]+1);
+ $sectionKey = implode('_', $sectionPath);
+
+ if (!isset($this->_cacheLoadedSections[$sectionKey])) {
+ Varien_Profiler::start('init_config_section:' . $sectionKey);
+ $this->_cacheLoadedSections[$sectionKey] = $this->_loadSectionCache($sectionKey);
+ Varien_Profiler::stop('init_config_section:' . $sectionKey);
+ }
+
+ if ($this->_cacheLoadedSections[$sectionKey] === false) {
+ return false;
+ }
+ return $this->_cacheLoadedSections[$sectionKey];
+ }
+
+ /**
+ * Get node value from cached section data
+ *
+ * @param array $path
+ * @return Mage_Core_Model_Config
+ */
+ public function getSectionNode($path)
+ {
+ $section = $path[0];
+ $config = $this->_getSectionConfig($path);
+ $path = array_slice($path, $this->_cacheSections[$section] + 1);
+ if ($config) {
+ return $config->descend($path);
+ }
+ return false;
+ }
+
+ /**
+ * Returns node found by the $path and scope info
+ *
+ * @param string $path
+ * @param string $scope
+ * @param string|int $scopeCode
+ * @return Mage_Core_Model_Config_Element
+ */
+ public function getNode($path=null, $scope='', $scopeCode=null)
+ {
+ if ($scope !== '') {
+ if (('store' === $scope) || ('website' === $scope)) {
+ $scope .= 's';
+ }
+ if (('default' !== $scope) && is_int($scopeCode)) {
+ if ('stores' == $scope) {
+ $scopeCode = Mage::app()->getStore($scopeCode)->getCode();
+ } elseif ('websites' == $scope) {
+ $scopeCode = Mage::app()->getWebsite($scopeCode)->getCode();
+ } else {
+ Mage::throwException(Mage::helper('core')->__('Unknown scope "%s".', $scope));
+ }
+ }
+ $path = $scope . ($scopeCode ? '/' . $scopeCode : '' ) . (empty($path) ? '' : '/' . $path);
+ }
+
+ /**
+ * Check path cache loading
+ */
+ if ($this->_useCache && ($path !== null)) {
+ $path = explode('/', $path);
+ $section= $path[0];
+ if (isset($this->_cacheSections[$section])) {
+ $res = $this->getSectionNode($path);
+ if ($res !== false) {
+ return $res;
+ }
+ }
+ }
+ return parent::getNode($path);
+ }
+
+ /**
+ * Create node by $path and set its value.
+ *
+ * @param string $path separated by slashes
+ * @param string $value
+ * @param bool $overwrite
+ * @return Varien_Simplexml_Config
+ */
+ public function setNode($path, $value, $overwrite = true)
+ {
+ if ($this->_useCache && ($path !== null)) {
+ $sectionPath = explode('/', $path);
+ $config = $this->_getSectionConfig($sectionPath);
+ if ($config) {
+ $sectionPath = array_slice($sectionPath, $this->_cacheSections[$sectionPath[0]]+1);
+ $sectionPath = implode('/', $sectionPath);
+ $config->setNode($sectionPath, $value, $overwrite);
+ }
+ }
+ return parent::setNode($path, $value, $overwrite);
+ }
+
+
+ /**
+ * Retrive Declared Module file list
+ *
+ * @return array
+ */
+ protected function _getDeclaredModuleFiles()
+ {
+ $etcDir = $this->getOptions()->getEtcDir();
+ $moduleFiles = glob($etcDir . DS . 'modules' . DS . '*.xml');
+
+ if (!$moduleFiles) {
+ return false;
+ }
+
+ $collectModuleFiles = array(
+ 'base' => array(),
+ 'mage' => array(),
+ 'custom' => array()
+ );
+
+ foreach ($moduleFiles as $v) {
+ $name = explode(DIRECTORY_SEPARATOR, $v);
+ $name = substr($name[count($name) - 1], 0, -4);
+
+ if ($name == 'Mage_All') {
+ $collectModuleFiles['base'][] = $v;
+ } else if (substr($name, 0, 5) == 'Mage_') {
+ $collectModuleFiles['mage'][] = $v;
+ } else {
+ $collectModuleFiles['custom'][] = $v;
+ }
+ }
+
+ return array_merge(
+ $collectModuleFiles['base'],
+ $collectModuleFiles['mage'],
+ $collectModuleFiles['custom']
+ );
+ }
+
+ /**
+ * Add module(s) to allowed list
+ *
+ * @param strung|array $module
+ * @return Mage_Core_Model_Config
+ */
+ public function addAllowedModules($module)
+ {
+ if (is_array($module)) {
+ foreach ($module as $moduleName) {
+ $this->addAllowedModules($moduleName);
+ }
+ } elseif (!in_array($module, $this->_allowedModules)) {
+ $this->_allowedModules[] = $module;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Define if module is allowed
+ *
+ * @param string $moduleName
+ * @return bool
+ */
+ protected function _isAllowedModule($moduleName)
+ {
+ if (empty($this->_allowedModules)) {
+ return true;
+ } else {
+ return in_array($moduleName, $this->_allowedModules);
+ }
+ }
+
+ /**
+ * Load declared modules configuration
+ *
+ * @param null $mergeConfig depricated
+ * @return Mage_Core_Model_Config
+ */
+ protected function _loadDeclaredModules($mergeConfig = null)
+ {
+ $moduleFiles = $this->_getDeclaredModuleFiles();
+ if (!$moduleFiles) {
+ return ;
+ }
+
+ Varien_Profiler::start('config/load-modules-declaration');
+
+ $unsortedConfig = new Mage_Core_Model_Config_Base();
+ $unsortedConfig->loadString('');
+ $fileConfig = new Mage_Core_Model_Config_Base();
+
+ // load modules declarations
+ foreach ($moduleFiles as $file) {
+ $fileConfig->loadFile($file);
+ $unsortedConfig->extend($fileConfig);
+ }
+
+ $moduleDepends = array();
+ foreach ($unsortedConfig->getNode('modules')->children() as $moduleName => $moduleNode) {
+ if (!$this->_isAllowedModule($moduleName)) {
+ continue;
+ }
+
+ $depends = array();
+ if ($moduleNode->depends) {
+ foreach ($moduleNode->depends->children() as $depend) {
+ $depends[$depend->getName()] = true;
+ }
+ }
+ $moduleDepends[$moduleName] = array(
+ 'module' => $moduleName,
+ 'depends' => $depends,
+ 'active' => ('true' === (string)$moduleNode->active ? true : false),
+ );
+ }
+
+ // check and sort module dependence
+ $moduleDepends = $this->_sortModuleDepends($moduleDepends);
+
+ // create sorted config
+ $sortedConfig = new Mage_Core_Model_Config_Base();
+ $sortedConfig->loadString('');
+
+ foreach ($unsortedConfig->getNode()->children() as $nodeName => $node) {
+ if ($nodeName != 'modules') {
+ $sortedConfig->getNode()->appendChild($node);
+ }
+ }
+
+ foreach ($moduleDepends as $moduleProp) {
+ $node = $unsortedConfig->getNode('modules/'.$moduleProp['module']);
+ $sortedConfig->getNode('modules')->appendChild($node);
+ }
+
+ $this->extend($sortedConfig);
+
+ Varien_Profiler::stop('config/load-modules-declaration');
+ return $this;
+ }
+
+ /**
+ * Sort modules and check depends
+ *
+ * @param array $modules
+ * @return array
+ */
+ protected function _sortModuleDepends($modules)
+ {
+ foreach ($modules as $moduleName => $moduleProps) {
+ $depends = $moduleProps['depends'];
+ foreach ($moduleProps['depends'] as $depend => $true) {
+ if ($moduleProps['active'] && ((!isset($modules[$depend])) || empty($modules[$depend]['active']))) {
+ Mage::throwException(
+ Mage::helper('core')->__('Module "%1$s" requires module "%2$s".', $moduleName, $depend)
+ );
+ }
+ $depends = array_merge($depends, $modules[$depend]['depends']);
+ }
+ $modules[$moduleName]['depends'] = $depends;
+ }
+ $modules = array_values($modules);
+
+ $size = count($modules) - 1;
+ for ($i = $size; $i >= 0; $i--) {
+ for ($j = $size; $i < $j; $j--) {
+ if (isset($modules[$i]['depends'][$modules[$j]['module']])) {
+ $value = $modules[$i];
+ $modules[$i] = $modules[$j];
+ $modules[$j] = $value;
+ }
+ }
+ }
+
+ $definedModules = array();
+ foreach ($modules as $moduleProp) {
+ foreach ($moduleProp['depends'] as $dependModule => $true) {
+ if (!isset($definedModules[$dependModule])) {
+ Mage::throwException(
+ Mage::helper('core')->__('Module "%1$s" cannot depend on "%2$s".', $moduleProp['module'], $dependModule)
+ );
+ }
+ }
+ $definedModules[$moduleProp['module']] = true;
+ }
+
+ return $modules;
+ }
+
+ /**
+ * Determine whether provided name begins from any available modules, according to namespaces priority
+ * If matched, returns as the matched module "factory" name or a fully qualified module name
+ *
+ * @param string $name
+ * @param bool $asFullModuleName
+ * @return string
+ */
+ public function determineOmittedNamespace($name, $asFullModuleName = false)
+ {
+ if (null === $this->_moduleNamespaces) {
+ $this->_moduleNamespaces = array();
+ foreach ($this->_xml->xpath('modules/*') as $m) {
+ if ((string)$m->active == 'true') {
+ $moduleName = $m->getName();
+ $module = strtolower($moduleName);
+ $this->_moduleNamespaces[substr($module, 0, strpos($module, '_'))][$module] = $moduleName;
+ }
+ }
+ }
+
+ $name = explode('_', strtolower($name));
+ $partsNum = count($name);
+ $defaultNamespaceFlag = false;
+ foreach ($this->_moduleNamespaces as $namespaceName => $namespace) {
+ // assume the namespace is omitted (default namespace only, which comes first)
+ if ($defaultNamespaceFlag === false) {
+ $defaultNamespaceFlag = true;
+ $defaultNS = $namespaceName . '_' . $name[0];
+ if (isset($namespace[$defaultNS])) {
+ return $asFullModuleName ? $namespace[$defaultNS] : $name[0]; // return omitted as well
+ }
+ }
+ // assume namespace is qualified
+ if(isset($name[1])) {
+ $fullNS = $name[0] . '_' . $name[1];
+ if (2 <= $partsNum && isset($namespace[$fullNS])) {
+ return $asFullModuleName ? $namespace[$fullNS] : $fullNS;
+ }
+ }
+ }
+ return '';
+ }
+
+ /**
+ * Iterate all active modules "etc" folders and combine data from
+ * specidied xml file name to one object
+ *
+ * @param string $fileName
+ * @param null|Mage_Core_Model_Config_Base $mergeToObject
+ * @return Mage_Core_Model_Config_Base
+ */
+ public function loadModulesConfiguration($fileName, $mergeToObject = null, $mergeModel=null)
+ {
+ $disableLocalModules = !$this->_canUseLocalModules();
+
+ if ($mergeToObject === null) {
+ $mergeToObject = clone $this->_prototype;
+ $mergeToObject->loadString('');
+ }
+ if ($mergeModel === null) {
+ $mergeModel = clone $this->_prototype;
+ }
+ $modules = $this->getNode('modules')->children();
+ foreach ($modules as $modName=>$module) {
+ if ($module->is('active')) {
+ if ($disableLocalModules && ('local' === (string)$module->codePool)) {
+ continue;
+ }
+ if (!is_array($fileName)) {
+ $fileName = array($fileName);
+ }
+
+ foreach ($fileName as $configFile) {
+ $configFile = $this->getModuleDir('etc', $modName).DS.$configFile;
+ if ($mergeModel->loadFile($configFile)) {
+
+ $this->_makeEventsLowerCase(Mage_Core_Model_App_Area::AREA_GLOBAL, $mergeModel);
+ $this->_makeEventsLowerCase(Mage_Core_Model_App_Area::AREA_FRONTEND, $mergeModel);
+ $this->_makeEventsLowerCase(Mage_Core_Model_App_Area::AREA_ADMIN, $mergeModel);
+ $this->_makeEventsLowerCase(Mage_Core_Model_App_Area::AREA_ADMINHTML, $mergeModel);
+
+ $mergeToObject->extend($mergeModel, true);
+ }
+ }
+ }
+ }
+ return $mergeToObject;
+ }
+
+ /**
+ * Retrieve temporary directory path
+ *
+ * @return string
+ */
+ public function getTempVarDir()
+ {
+ return $this->getOptions()->getVarDir();
+ }
+
+ /**
+ * Get default server variables values
+ *
+ * @return array
+ */
+ public function getDistroServerVars()
+ {
+ if (!$this->_distroServerVars) {
+
+ if (isset($_SERVER['SCRIPT_NAME']) && isset($_SERVER['HTTP_HOST'])) {
+ $secure = (!empty($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!='off')) || $_SERVER['SERVER_PORT']=='443';
+ $scheme = ($secure ? 'https' : 'http') . '://' ;
+
+ $hostArr = explode(':', $_SERVER['HTTP_HOST']);
+ $host = $hostArr[0];
+ $port = isset(
+ $hostArr[1]) && (!$secure && $hostArr[1]!=80 || $secure && $hostArr[1]!=443
+ ) ? ':'.$hostArr[1] : '';
+ $path = Mage::app()->getRequest()->getBasePath();
+
+ $baseUrl = $scheme.$host.$port.rtrim($path, '/').'/';
+ } else {
+ $baseUrl = 'http://localhost/';
+ }
+
+ $options = $this->getOptions();
+ $this->_distroServerVars = array(
+ 'root_dir' => $options->getBaseDir(),
+ 'app_dir' => $options->getAppDir(),
+ 'var_dir' => $options->getVarDir(),
+ 'base_url' => $baseUrl,
+ );
+
+ foreach ($this->_distroServerVars as $k=>$v) {
+ $this->_substServerVars['{{'.$k.'}}'] = $v;
+ }
+ }
+ return $this->_distroServerVars;
+ }
+
+ public function substDistroServerVars($data)
+ {
+ $this->getDistroServerVars();
+ return str_replace(
+ array_keys($this->_substServerVars),
+ array_values($this->_substServerVars),
+ $data
+ );
+ }
+
+ /**
+ * Get module config node
+ *
+ * @param string $moduleName
+ * @return Varien_Simplexml_Object
+ */
+ function getModuleConfig($moduleName='')
+ {
+ $modules = $this->getNode('modules');
+ if (''===$moduleName) {
+ return $modules;
+ } else {
+ return $modules->$moduleName;
+ }
+ }
+
+ /**
+ * Get module setup class instance.
+ *
+ * Defaults to Mage_Core_Setup
+ *
+ * @param string|Varien_Simplexml_Object $module
+ * @return object
+ */
+ function getModuleSetup($module='')
+ {
+ $className = 'Mage_Core_Setup';
+ if (''!==$module) {
+ if (is_string($module)) {
+ $module = $this->getModuleConfig($module);
+ }
+ if (isset($module->setup)) {
+ $moduleClassName = $module->setup->getClassName();
+ if (!empty($moduleClassName)) {
+ $className = $moduleClassName;
+ }
+ }
+ }
+ return new $className($module);
+ }
+
+ /**
+ * Get base filesystem directory. depends on $type
+ *
+ * If $moduleName is specified retrieves specific value for the module.
+ *
+ * @deprecated in favor of Mage_Core_Model_Config_Options
+ * @todo get global dir config
+ * @param string $type
+ * @return string
+ */
+ public function getBaseDir($type='base')
+ {
+ return $this->getOptions()->getDir($type);
+ }
+
+ /**
+ * Get temporary data directory name
+ *
+ * @param string $path
+ * @param string $type
+ * @return string
+ */
+ public function getVarDir($path=null, $type='var')
+ {
+ $dir = Mage::getBaseDir($type).($path!==null ? DS.$path : '');
+ if (!$this->createDirIfNotExists($dir)) {
+ return false;
+ }
+ return $dir;
+ }
+
+ public function createDirIfNotExists($dir)
+ {
+ return $this->getOptions()->createDirIfNotExists($dir);
+ }
+
+ /**
+ * Get module directory by directory type
+ *
+ * @param string $type
+ * @param string $moduleName
+ * @return string
+ */
+ public function getModuleDir($type, $moduleName)
+ {
+ $codePool = (string)$this->getModuleConfig($moduleName)->codePool;
+ $dir = $this->getOptions()->getCodeDir().DS.$codePool.DS.uc_words($moduleName, DS);
+
+ switch ($type) {
+ case 'etc':
+ $dir .= DS.'etc';
+ break;
+
+ case 'controllers':
+ $dir .= DS.'controllers';
+ break;
+
+ case 'sql':
+ $dir .= DS.'sql';
+ break;
+ case 'data':
+ $dir .= DS.'data';
+ break;
+
+ case 'locale':
+ $dir .= DS.'locale';
+ break;
+ }
+
+ $dir = str_replace('/', DS, $dir);
+ return $dir;
+ }
+
+ /**
+ * Load event observers for an area (front, admin)
+ *
+ * @param string $area
+ * @return boolean
+ */
+ public function loadEventObservers($area)
+ {
+ $events = $this->getNode("$area/events");
+ if ($events) {
+ $events = $events->children();
+ } else {
+ return false;
+ }
+
+ foreach ($events as $event) {
+ $eventName = strtolower($event->getName());
+ $observers = $event->observers->children();
+ foreach ($observers as $observer) {
+ switch ((string)$observer->type) {
+ case 'singleton':
+ $callback = array(
+ Mage::getSingleton((string)$observer->class),
+ (string)$observer->method
+ );
+ break;
+ case 'object':
+ case 'model':
+ $callback = array(
+ Mage::getModel((string)$observer->class),
+ (string)$observer->method
+ );
+ break;
+ default:
+ $callback = array($observer->getClassName(), (string)$observer->method);
+ break;
+ }
+
+ $args = (array)$observer->args;
+ $observerClass = $observer->observer_class ? (string)$observer->observer_class : '';
+ Mage::addObserver($eventName, $callback, $args, $observer->getName(), $observerClass);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Get standard path variables.
+ *
+ * To be used in blocks, templates, etc.
+ *
+ * @param array|string $args Module name if string
+ * @return array
+ */
+ public function getPathVars($args=null)
+ {
+ $path = array();
+
+ $path['baseUrl'] = Mage::getBaseUrl();
+ $path['baseSecureUrl'] = Mage::getBaseUrl('link', true);
+
+ return $path;
+ }
+
+ /**
+ * Retrieve class name by class group
+ *
+ * @param string $groupType currently supported model, block, helper
+ * @param string $classId slash separated class identifier, ex. group/class
+ * @param string $groupRootNode optional config path for group config
+ * @return string
+ */
+ public function getGroupedClassName($groupType, $classId, $groupRootNode=null)
+ {
+ if (empty($groupRootNode)) {
+ $groupRootNode = 'global/'.$groupType.'s';
+ }
+
+ $classArr = explode('/', trim($classId));
+ $group = $classArr[0];
+ $class = !empty($classArr[1]) ? $classArr[1] : null;
+
+ if (isset($this->_classNameCache[$groupRootNode][$group][$class])) {
+ return $this->_classNameCache[$groupRootNode][$group][$class];
+ }
+
+ $config = $this->_xml->global->{$groupType.'s'}->{$group};
+
+ // First - check maybe the entity class was rewritten
+ $className = null;
+ if (isset($config->rewrite->$class)) {
+ $className = (string)$config->rewrite->$class;
+ } else {
+ /**
+ * Backwards compatibility for pre-MMDB extensions.
+ * In MMDB release resource nodes <..._mysql4> were renamed to <..._resource>. So is left
+ * to keep name of previously used nodes, that still may be used by non-updated extensions.
+ */
+ if (isset($config->deprecatedNode)) {
+ $deprecatedNode = $config->deprecatedNode;
+ $configOld = $this->_xml->global->{$groupType.'s'}->$deprecatedNode;
+ if (isset($configOld->rewrite->$class)) {
+ $className = (string) $configOld->rewrite->$class;
+ }
+ }
+ }
+
+ // Second - if entity is not rewritten then use class prefix to form class name
+ if (empty($className)) {
+ if (!empty($config)) {
+ $className = $config->getClassName();
+ }
+ if (empty($className)) {
+ $className = 'mage_'.$group.'_'.$groupType;
+ }
+ if (!empty($class)) {
+ $className .= '_'.$class;
+ }
+ $className = uc_words($className);
+ }
+
+ $this->_classNameCache[$groupRootNode][$group][$class] = $className;
+ return $className;
+ }
+
+ /**
+ * Retrieve block class name
+ *
+ * @param string $blockType
+ * @return string
+ */
+ public function getBlockClassName($blockType)
+ {
+ if (strpos($blockType, '/')===false) {
+ return $blockType;
+ }
+ return $this->getGroupedClassName('block', $blockType);
+ }
+
+ /**
+ * Retrieve helper class name
+ *
+ * @param string $name
+ * @return string
+ */
+ public function getHelperClassName($helperName)
+ {
+ if (strpos($helperName, '/') === false) {
+ $helperName .= '/data';
+ }
+ return $this->getGroupedClassName('helper', $helperName);
+ }
+
+ /**
+ * Retreive resource helper instance
+ *
+ * Example:
+ * $config->getResourceHelper('cms')
+ * will instantiate Mage_Cms_Model_Resource_Helper_
+ *
+ * @param string $moduleName
+ * @return Mage_Core_Model_Resource_Helper_Abstract|false
+ */
+ public function getResourceHelper($moduleName)
+ {
+ $connectionModel = $this->_getResourceConnectionModel($moduleName);
+ $helperClass = sprintf('%s/helper_%s', $moduleName, $connectionModel);
+ $helperClassName = $this->_getResourceModelFactoryClassName($helperClass);
+ if ($helperClassName) {
+ return $this->getModelInstance($helperClassName, $moduleName);
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieve module class name
+ *
+ * @param sting $modelClass
+ * @return string
+ */
+ public function getModelClassName($modelClass)
+ {
+ $modelClass = trim($modelClass);
+ if (strpos($modelClass, '/')===false) {
+ return $modelClass;
+ }
+ return $this->getGroupedClassName('model', $modelClass);
+ }
+
+ /**
+ * Get model class instance.
+ *
+ * Example:
+ * $config->getModelInstance('catalog/product')
+ *
+ * Will instantiate Mage_Catalog_Model_Mysql4_Product
+ *
+ * @param string $modelClass
+ * @param array|object $constructArguments
+ * @return Mage_Core_Model_Abstract|false
+ */
+ public function getModelInstance($modelClass='', $constructArguments=array())
+ {
+ $className = $this->getModelClassName($modelClass);
+ if (class_exists($className)) {
+ Varien_Profiler::start('CORE::create_object_of::'.$className);
+ $obj = new $className($constructArguments);
+ Varien_Profiler::stop('CORE::create_object_of::'.$className);
+ return $obj;
+ } else {
+ return false;
+ }
+ }
+
+ public function getNodeClassInstance($path)
+ {
+ $config = Mage::getConfig()->getNode($path);
+ if (!$config) {
+ return false;
+ } else {
+ $className = $config->getClassName();
+ return new $className();
+ }
+ }
+
+ /**
+ * Get resource model object by alias
+ *
+ * @param string $modelClass
+ * @param array $constructArguments
+ * @return object
+ */
+ public function getResourceModelInstance($modelClass='', $constructArguments=array())
+ {
+ $factoryName = $this->_getResourceModelFactoryClassName($modelClass);
+ if (!$factoryName) {
+ return false;
+ }
+ return $this->getModelInstance($factoryName, $constructArguments);
+ }
+
+ /**
+ * Get resource configuration for resource name
+ *
+ * @param string $name
+ * @return Varien_Simplexml_Object
+ */
+ public function getResourceConfig($name)
+ {
+ return $this->_xml->global->resources->{$name};
+ }
+
+ /**
+ * Get connection configuration
+ *
+ * @param string $name
+ * @return Varien_Simplexml_Element
+ */
+ public function getResourceConnectionConfig($name)
+ {
+ $config = $this->getResourceConfig($name);
+ if ($config) {
+ $conn = $config->connection;
+ if ($conn) {
+ if (!empty($conn->use)) {
+ return $this->getResourceConnectionConfig((string)$conn->use);
+ } else {
+ return $conn;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Retrieve resource type configuration for resource name
+ *
+ * @param string $type
+ * @return Varien_Simplexml_Object
+ */
+ public function getResourceTypeConfig($type)
+ {
+ return $this->_xml->global->resource->connection->types->{$type};
+ }
+
+ /**
+ * Retrieve store Ids for $path with checking
+ *
+ * if empty $allowValues then retrieve all stores values
+ *
+ * return array($storeId=>$pathValue)
+ *
+ * @param string $path
+ * @param array $allowValues
+ * @return array
+ */
+ public function getStoresConfigByPath($path, $allowValues = array(), $useAsKey = 'id')
+ {
+ $storeValues = array();
+ $stores = $this->getNode('stores');
+ foreach ($stores->children() as $code => $store) {
+ switch ($useAsKey) {
+ case 'id':
+ $key = (int) $store->descend('system/store/id');
+ break;
+
+ case 'code':
+ $key = $code;
+ break;
+
+ case 'name':
+ $key = (string) $store->descend('system/store/name');
+ }
+ if ($key === false) {
+ continue;
+ }
+
+ $pathValue = (string) $store->descend($path);
+
+ if (empty($allowValues)) {
+ $storeValues[$key] = $pathValue;
+ } else if (in_array($pathValue, $allowValues)) {
+ $storeValues[$key] = $pathValue;
+ }
+ }
+ return $storeValues;
+ }
+
+ /**
+ * Check whether given path should be secure according to configuration security requirements for URL
+ * "Secure" should not be confused with https protocol, it is about web/secure/*_url settings usage only
+ *
+ * @param string $url
+ * @return bool
+ */
+ public function shouldUrlBeSecure($url)
+ {
+ if (!Mage::getStoreConfigFlag(Mage_Core_Model_Store::XML_PATH_SECURE_IN_FRONTEND)) {
+ return false;
+ }
+
+ if (!isset($this->_secureUrlCache[$url])) {
+ $this->_secureUrlCache[$url] = false;
+ $secureUrls = $this->getNode('frontend/secure_url');
+ foreach ($secureUrls->children() as $match) {
+ if (strpos($url, (string)$match) === 0) {
+ $this->_secureUrlCache[$url] = true;
+ break;
+ }
+ }
+ }
+
+ return $this->_secureUrlCache[$url];
+ }
+
+ /**
+ * Get DB table names prefix
+ *
+ * @return string
+ */
+ public function getTablePrefix()
+ {
+ return $this->_xml->global->resources->db->table_prefix;
+ }
+
+ /**
+ * Get events configuration
+ *
+ * @param string $area event area
+ * @param string $eventName event name
+ * @return Mage_Core_Model_Config_Element
+ */
+ public function getEventConfig($area, $eventName)
+ {
+ //return $this->getNode($area)->events->{$eventName};
+ if (!isset($this->_eventAreas[$area])) {
+ $this->_eventAreas[$area] = $this->getNode($area)->events;
+ }
+ return $this->_eventAreas[$area]->{$eventName};
+ }
+
+ /**
+ * Save config value to DB
+ *
+ * @param string $path
+ * @param string $value
+ * @param string $scope
+ * @param int $scopeId
+ * @return Mage_Core_Store_Config
+ */
+ public function saveConfig($path, $value, $scope = 'default', $scopeId = 0)
+ {
+ $resource = $this->getResourceModel();
+ $resource->saveConfig(rtrim($path, '/'), $value, $scope, $scopeId);
+
+ return $this;
+ }
+
+ /**
+ * Delete config value from DB
+ *
+ * @param string $path
+ * @param string $scope
+ * @param int $scopeId
+ * @return Mage_Core_Model_Config
+ */
+ public function deleteConfig($path, $scope = 'default', $scopeId = 0)
+ {
+ $resource = $this->getResourceModel();
+ $resource->deleteConfig(rtrim($path, '/'), $scope, $scopeId);
+
+ return $this;
+ }
+
+ /**
+ * Get fieldset from configuration
+ *
+ * @param string $name fieldset name
+ * @param string $root fieldset area, could be 'admin'
+ * @return null|array
+ */
+ public function getFieldset($name, $root = 'global')
+ {
+ $rootNode = $this->getNode($root.'/fieldsets');
+ if (!$rootNode) {
+ return null;
+ }
+ return $rootNode->$name ? $rootNode->$name->children() : null;
+ }
+
+ /**
+ * Retrieve resource connection model name
+ *
+ * @param string $moduleName
+ * @return string
+ */
+ protected function _getResourceConnectionModel($moduleName = null)
+ {
+ $config = null;
+ if (!is_null($moduleName)) {
+ $setupResource = $moduleName . '_setup';
+ $config = $this->getResourceConnectionConfig($setupResource);
+ }
+ if (!$config) {
+ $config = $this->getResourceConnectionConfig(Mage_Core_Model_Resource::DEFAULT_SETUP_RESOURCE);
+ }
+
+ return (string)$config->model;
+ }
+
+ /**
+ * Get factory class name for a resource
+ *
+ * @param string $modelClass
+ * @return string|false
+ */
+ protected function _getResourceModelFactoryClassName($modelClass)
+ {
+ $classArray = explode('/', $modelClass);
+ if (count($classArray) != 2) {
+ return false;
+ }
+
+ list($module, $model) = $classArray;
+ if (!isset($this->_xml->global->models->{$module})) {
+ return false;
+ }
+
+ $moduleNode = $this->_xml->global->models->{$module};
+ if (!empty($moduleNode->resourceModel)) {
+ $resourceModel = (string)$moduleNode->resourceModel;
+ } else {
+ return false;
+ }
+
+ return $resourceModel . '/' . $model;
+ }
+
+ /**
+ * Get a resource model class name
+ *
+ * @param string $modelClass
+ * @return string|false
+ */
+ public function getResourceModelClassName($modelClass)
+ {
+ $factoryName = $this->_getResourceModelFactoryClassName($modelClass);
+ if ($factoryName) {
+ return $this->getModelClassName($factoryName);
+ }
+ return false;
+ }
+
+ /**
+ * Makes all events to lower-case
+ *
+ * @param string $area
+ * @param Varien_Simplexml_Config $mergeModel
+ */
+ protected function _makeEventsLowerCase($area, Varien_Simplexml_Config $mergeModel)
+ {
+ $events = $mergeModel->getNode($area . "/" . Mage_Core_Model_App_Area::PART_EVENTS);
+ if ($events !== false) {
+ $children = clone $events->children();
+ /** @var Mage_Core_Model_Config_Element $event */
+ foreach ($children as $event) {
+ if ($this->_isNodeNameHasUpperCase($event)) {
+ $oldName = $event->getName();
+ $newEventName = strtolower($oldName);
+ if (!isset($events->$newEventName)) {
+ /** @var Mage_Core_Model_Config_Element $newNode */
+ $newNode = $events->addChild($newEventName, $event);
+ $newNode->extend($event);
+ }
+ unset($events->$oldName);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks is event name has upper-case letters
+ *
+ * @param Mage_Core_Model_Config_Element $event
+ * @return bool
+ */
+ protected function _isNodeNameHasUpperCase(Mage_Core_Model_Config_Element $event)
+ {
+ return (strtolower($event->getName()) !== (string)$event->getName());
+ }
+}
+
diff --git a/composer.json b/composer.json
index 59450fe..9b3108f 100755
--- a/composer.json
+++ b/composer.json
@@ -21,6 +21,14 @@
"app/code/community/Webbhuset/Bugfix/",
"app/code/community/Webbhuset/Bugfix/"
],
+ [
+ "app/code/community/Mage/Core/Model/Cache.php",
+ "app/code/community/Mage/Core/Model/Cache.php"
+ ],
+ [
+ "app/code/community/Mage/Core/Model/Config.php",
+ "app/code/community/Mage/Core/Model/Config.php"
+ ],
[
"app/code/community/Mage/Adminhtml/Block/Media/Uploader.php",
"app/code/community/Mage/Adminhtml/Block/Media/Uploader.php"