From 63d5dfbc3fea5a9c6e718421bf971ff6c77656ce Mon Sep 17 00:00:00 2001 From: Anton Samuelsson Date: Fri, 16 Sep 2016 14:41:15 +0200 Subject: [PATCH 1/3] Added Magento 1.9.2.4 core files --- app/code/community/Mage/Core/Model/Cache.php | 705 +++++++ app/code/community/Mage/Core/Model/Config.php | 1678 +++++++++++++++++ 2 files changed, 2383 insertions(+) create mode 100644 app/code/community/Mage/Core/Model/Cache.php create mode 100644 app/code/community/Mage/Core/Model/Config.php 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..0c785db --- /dev/null +++ b/app/code/community/Mage/Core/Model/Cache.php @@ -0,0 +1,705 @@ + 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) + { + 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..65da05d --- /dev/null +++ b/app/code/community/Mage/Core/Model/Config.php @@ -0,0 +1,1678 @@ + + */ +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; + } + $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()); + } +} From ff8671c88eb974d32e143856cfcfe851427c1baf Mon Sep 17 00:00:00 2001 From: Anton Samuelsson Date: Fri, 16 Sep 2016 14:43:47 +0200 Subject: [PATCH 2/3] This issue is solved in Magento EE SUPEE-4755 but ignored in any Magneto CE path. --- app/code/community/Mage/Core/Model/Cache.php | 1 + app/code/community/Mage/Core/Model/Config.php | 6 ++++++ composer.json | 8 ++++++++ 3 files changed, 15 insertions(+) diff --git a/app/code/community/Mage/Core/Model/Cache.php b/app/code/community/Mage/Core/Model/Cache.php index 0c785db..e91957c 100644 --- a/app/code/community/Mage/Core/Model/Cache.php +++ b/app/code/community/Mage/Core/Model/Cache.php @@ -703,3 +703,4 @@ 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 index 65da05d..9099cad 100644 --- a/app/code/community/Mage/Core/Model/Config.php +++ b/app/code/community/Mage/Core/Model/Config.php @@ -256,6 +256,11 @@ public function init($options=array()) if ($cacheLoad) { return $this; } + + //100 Router Fix Start + $this->_useCache = false; + //100 Router Fix End + $this->loadModules(); $this->loadDb(); $this->saveCache(); @@ -1676,3 +1681,4 @@ 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" From 50ae0ecc677f514615e4e0170b7664945e3dde9f Mon Sep 17 00:00:00 2001 From: Anton Samuelsson Date: Fri, 16 Sep 2016 14:48:40 +0200 Subject: [PATCH 3/3] Added the missing patched file --- app/code/community/Mage/Core/Model/Cache.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/code/community/Mage/Core/Model/Cache.php b/app/code/community/Mage/Core/Model/Cache.php index e91957c..a587240 100644 --- a/app/code/community/Mage/Core/Model/Cache.php +++ b/app/code/community/Mage/Core/Model/Cache.php @@ -390,6 +390,20 @@ public function load($id) */ 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; }