Index: branches/5.2.x/core/kernel/languages/phrases_cache.php =================================================================== diff -u -N -r14095 -r14184 --- branches/5.2.x/core/kernel/languages/phrases_cache.php (.../phrases_cache.php) (revision 14095) +++ branches/5.2.x/core/kernel/languages/phrases_cache.php (.../phrases_cache.php) (revision 14184) @@ -1,6 +1,6 @@ LanguageId = 1; } else { - if ($this->Application->isAdmin) { - $this->LanguageId = $this->Application->Session->GetField('Language'); - } - else { - $this->LanguageId = $this->Application->GetVar('m_lang'); - - if ($this->Application->GetVar('admin')) { - $admin_session =& $this->Application->recallObject('Session.admin'); - /* @var $admin_session Session */ - - $this->AdminLanguageId = $admin_session->GetField('Language'); + if ( !isset($language_id) ) { + if ($this->Application->isAdmin) { + $language_id = $this->Application->Session->GetField('Language'); } + else { + $language_id = $this->Application->GetVar('m_lang'); + } } - } - if (isset($this->Application->Caches['PhraseList'])) { - $this->LoadPhrases( $this->Application->Caches['PhraseList'] ); - } - } + $this->LanguageId = $language_id; - function GetCachedIds() - { - $cache_key = md5($this->Application->GetVar('t') . $this->Application->GetVar('m_theme') . $this->Application->GetVar('m_lang')); + if (!$this->Application->isAdmin && $this->Application->GetVar('admin')) { + $admin_session =& $this->Application->recallObject('Session.admin'); + /* @var $admin_session Session */ - $sql = 'SELECT PhraseList, ConfigVariables - FROM ' . TABLE_PREFIX . 'PhraseCache - WHERE Template = ' . $this->Conn->qstr($cache_key); - $res = $this->Conn->GetRow($sql); - - if ($res && $res['ConfigVariables']) { - $this->Application->OriginalConfigCacheIds = explode(',', $res['ConfigVariables']); - $this->Application->ConfigCacheIds = $this->Application->OriginalConfigCacheIds; + $this->AdminLanguageId = $admin_session->GetField('Language'); + } } - return ($res === false) ? Array() : explode(',', $res['PhraseList']); + $this->LoadPhrases($phrase_ids); } function LoadPhrases($ids) { if ( !is_array($ids) || !implode('', $ids) ) { - return; + return ; } $sql = 'SELECT l' . $this->LanguageId . '_Translation, PhraseKey FROM ' . TABLE_PREFIX . 'Phrase WHERE PhraseId IN (' . implode(',', $ids) . ') AND l' . $this->LanguageId . '_Translation IS NOT NULL'; $this->Phrases = $this->Conn->GetCol($sql, 'PhraseKey'); - /*foreach($phrases as $phrase => $tanslation) - { - $this->AddCachedPhrase(mb_strtoupper($phrase), $tanslation); - }*/ - - $this->Ids = $ids; - $this->OriginalIds = $ids; + $this->Ids = $this->OriginalIds = $ids; } function AddCachedPhrase($label, $value, $allow_editing = true) @@ -207,29 +188,6 @@ return is_array($this->Ids) && count($this->Ids) > 0 && $this->Ids != $this->OriginalIds; } - /** - * Copy from Application->UpdateCache method - * - * @deprecated - */ - function UpdateCache() - { - $update = false; - //something changed - $update = $update || (is_array($this->Ids) && count($this->Ids) > 0 && $this->Ids != $this->OriginalIds); - $update = $update || (count($this->Application->ConfigCacheIds) && $this->Application->ConfigCacheIds != $this->Application->OriginalConfigCacheIds); - if ($update) { - $query = sprintf("REPLACE %s (PhraseList, CacheDate, Template, ConfigVariables) - VALUES (%s, %s, %s, %s)", - TABLE_PREFIX.'PhraseCache', - $this->Conn->Qstr(join(',', $this->Ids)), - adodb_mktime(), - $this->Conn->Qstr(md5($this->Application->GetVar('t').$this->Application->GetVar('m_theme').$this->Application->GetVar('m_lang'))), - $this->Conn->qstr(implode(',', array_unique($this->Application->ConfigCacheIds)))); - $this->Conn->Query($query); - } - } - function GetPhrase($label, $allow_editing = true, $use_admin = false) { if (!isset($this->LanguageId)) { Index: branches/5.2.x/core/kernel/utility/formatters/password_formatter.php =================================================================== diff -u -N -r14095 -r14184 --- branches/5.2.x/core/kernel/utility/formatters/password_formatter.php (.../password_formatter.php) (revision 14095) +++ branches/5.2.x/core/kernel/utility/formatters/password_formatter.php (.../password_formatter.php) (revision 14184) @@ -1,6 +1,6 @@ Application->ConfigValue('Min_Password'); // for error message too + $min_length = $object->GetFieldOption($password_field, 'min_length', false, $min_length); + if (mb_strlen($new_password) < $min_length) { $error_msg = '+' . sprintf($this->Application->Phrase($phrase_error_prefix.'_passwords_too_short'), $min_length); // + -> not phrase $object->SetError($password_field, 'passwords_min_length', $error_msg); Index: branches/5.2.x/core/units/helpers/category_helper.php =================================================================== diff -u -N -r14095 -r14184 --- branches/5.2.x/core/units/helpers/category_helper.php (.../category_helper.php) (revision 14095) +++ branches/5.2.x/core/units/helpers/category_helper.php (.../category_helper.php) (revision 14184) @@ -1,6 +1,6 @@ Application->GetVar('t'); - $physical_template = array_search($current_template, $this->Application->structureTemplateMapping); + $physical_template = $this->Application->getPhysicalTemplate($current_template); if ($physical_template !== false) { // replace menu template name with it's actual template name on disk Index: branches/5.2.x/core/units/modules/modules_event_handler.php =================================================================== diff -u -N -r14095 -r14184 --- branches/5.2.x/core/units/modules/modules_event_handler.php (.../modules_event_handler.php) (revision 14095) +++ branches/5.2.x/core/units/modules/modules_event_handler.php (.../modules_event_handler.php) (revision 14184) @@ -1,6 +1,6 @@ status = kEvent::erSUCCESS; $event->setRedirectParams(Array ('opener' => 's'), true); - $this->Application->UnitConfigReader->ResetParsedData(true); //true to reset sections cache also + $this->Application->DeleteUnitCache(true); //true to reset sections cache also $event->SetRedirectParam('RefreshTree', 1); } } Index: branches/5.2.x/core/units/helpers/mod_rewrite_helper.php =================================================================== diff -u -N -r14095 -r14184 --- branches/5.2.x/core/units/helpers/mod_rewrite_helper.php (.../mod_rewrite_helper.php) (revision 14095) +++ branches/5.2.x/core/units/helpers/mod_rewrite_helper.php (.../mod_rewrite_helper.php) (revision 14184) @@ -1,6 +1,6 @@ Application->VerifyThemeId(); $this->Application->VerifyLanguageId(); - $this->Application->Phrases->Init('phrases'); + + // no need, since we don't have any cached phrase IDs + nobody will use PhrasesCache::LanguageId soon + // $this->Application->Phrases->Init('phrases'); } /** @@ -347,7 +349,7 @@ do { $template_path = implode('/', $url_parts); - $physical_template = array_search($template_path, $this->Application->structureTemplateMapping); + $physical_template = $this->Application->getPhysicalTemplate($template_path); if (($physical_template !== false) && (substr($physical_template, 0, 3) != 'id:')) { // replace menu template name with it's actual template name on disk @@ -831,7 +833,7 @@ $ret .= 'bb_' . $processed_params[$prefix_special . '_id'] . '/'; } else { - $filename = $this->Application->getFilename($prefix, $processed_params[$prefix_special . '_id'], $category_id); + $filename = $this->getFilename($prefix, $processed_params[$prefix_special . '_id'], $category_id); if ($filename !== false) { $ret .= $filename . '/'; } @@ -858,6 +860,48 @@ } /** + * Returns item's filename that corresponds id passed. If possible, then get it from cache + * + * @param string $prefix + * @param int $id + * @param int $category_id + * @return string + */ + function getFilename($prefix, $id, $category_id = null) + { + if ($prefix == 'c') { + throw new Exception('Method "' . __FUNCTION__ . '" no longer work with "c" prefix. Please use "getCategoryCache" method instead'); + + return false; + } + + $category_id = isset($category_id) ? $category_id : $this->Application->GetVar('m_cat_id'); + + $cache_key = 'filenames[%' . $this->Application->incrementCacheSerial($prefix, $id, false) . '%]:' . (int)$category_id; + $filename = $this->Application->getCache($cache_key); + + if ($filename === false) { + $this->Conn->nextQueryCachable = true; + $sql = 'SELECT ResourceId + FROM ' . $this->Application->getUnitOption($prefix, 'TableName') . ' + WHERE ' . $this->Application->getUnitOption($prefix, 'IDField') . ' = ' . $this->Conn->qstr($id); + $resource_id = $this->Conn->GetOne($sql); + + $this->Conn->nextQueryCachable = true; + $sql = 'SELECT Filename + FROM ' . TABLE_PREFIX . 'CategoryItems + WHERE (ItemResourceId = ' . $resource_id . ') AND (CategoryId = ' . (int)$category_id . ')'; + $filename = $this->Conn->GetOne($sql); + + if ($filename !== false) { + $this->Application->setCache($cache_key, $filename); + } + } + + return $filename; + } + + /** * Sets template and id, corresponding to category item given in url * * @param Array $url_parts Index: branches/5.2.x/core/kernel/managers/url_manager.php =================================================================== diff -u -N --- branches/5.2.x/core/kernel/managers/url_manager.php (revision 0) +++ branches/5.2.x/core/kernel/managers/url_manager.php (revision 14184) @@ -0,0 +1,631 @@ +Application->GetVar('m_theme'); + } + + if (!$t) { + // when template not specified, use current + $t = $this->Application->GetVar('t'); + } + + $t = preg_replace('/^Content\//i', '', $t); + + if (substr($t, -4) == '.tpl') { + // cut template extension (deprecated link format) + $t = substr($t, 0, strlen($t) - 4); + } + + if (substr($t, 0, 3) == 'id:') { + // link to structure page using it's id + $params['m_cat_id'] = substr($t, 3); + $t = $this->structureTemplateMapping[$t]; + } + + if (array_key_exists('use_section', $params)) { + $use_section = $params['use_section']; + unset($params['use_section']); + } + + if (isset($use_section) && $use_section && array_key_exists($t . ':' . $theme_id, $this->structureTemplateMapping)) { + // structure template corresponding to given physical template + $t = $this->structureTemplateMapping[$t . ':' . $theme_id]; + unset($params['use_section']); + } + + if (preg_match('/external:(.*)/', $t, $rets)) { + // external url + return $rets[1]; + } + + if ($this->Application->isAdmin && $prefix == '') $prefix = ADMIN_DIRECTORY; + if ($this->Application->isAdmin && $prefix == '_FRONT_END_') $prefix = ''; + + $index_file = $this->getIndexFile($prefix, $index_file, $params); + + if (isset($params['_auto_prefix_'])) { + unset($params['_auto_prefix_']); // this is parser-related param, do not need to pass it here + } + + $ssl = isset($params['__SSL__']) ? $params['__SSL__'] : null; + if ($ssl !== null) { + $session =& $this->Application->recallObject('Session'); + /* @var $session Session */ + + $target_url = rtrim($this->Application->BaseURL('', $ssl, false), '/'); + $cookie_url = trim($session->CookieDomain . $session->CookiePath, '/.'); + + // set session to GET_ONLY, to pass sid only if sid is REAL AND session is set + if (!preg_match('#' . preg_quote($cookie_url) . '#', $target_url) && $session->SessionSet) { + // when SSL<->NON-SSL redirect to different domain pass SID in url + $session->SetMode(Session::smGET_ONLY); + } + } + + if (isset($params['opener']) && $params['opener'] == 'u') { + $wid = $this->Application->GetVar('m_wid'); + $stack_name = rtrim('opener_stack_'.$wid, '_'); + $opener_stack = $this->Application->RecallVar($stack_name); + + if ($opener_stack && $opener_stack != serialize(Array())) { + $opener_stack = unserialize($opener_stack); + list($index_file, $env) = explode('|', $opener_stack[count($opener_stack) - 1]); + $ret = $this->Application->BaseURL($prefix, $ssl).$index_file.'?'.ENV_VAR_NAME.'='.$env; + if ( getArrayValue($params,'escape') ) $ret = addslashes($ret); + + if (isset($params['m_opener']) && $params['m_opener'] == 'u') { + array_pop($opener_stack); + if (!$opener_stack) { + $this->Application->RemoveVar($stack_name); + // remove popups last templates, because popup is closing now + $this->Application->RemoveVar('last_template_'.$wid); + $this->Application->RemoveVar('last_template_popup_'.$wid); + + // don't save popups last templates again :) + $this->Application->SetVar('skip_last_template', 1); + } + else { + $this->Application->StoreVar($stack_name, serialize($opener_stack)); + } + + /*// store window relations + $window_relations = $this->Application->RecallVar('window_relations'); + $window_relations = $window_relations ? unserialize($window_relations) : Array (); + if (array_key_exists($wid, $window_relations)) { + unset($window_relations[$wid]); + $this->Application->StoreVar('window_relations', serialize($window_relations)); + }*/ + } + return $ret; + } + else { + //define('DBG_REDIRECT', 1); + $t = $this->Application->GetVar('t'); + } + } + + $pass = isset($params['pass']) ? $params['pass'] : ''; + + // pass events with url + $pass_events = false; + if( isset($params['pass_events']) ) + { + $pass_events = $params['pass_events']; + unset($params['pass_events']); + } + + $map_link = ''; + if( isset($params['anchor']) ) + { + $map_link = '#'.$params['anchor']; + unset($params['anchor']); + } + + if ( isset($params['no_amp']) ) + { + $params['__URLENCODE__'] = $params['no_amp']; + unset($params['no_amp']); + } + + $no_rewrite = false; + if( isset($params['__NO_REWRITE__']) ) + { + $no_rewrite = true; + unset($params['__NO_REWRITE__']); + } + + $force_rewrite = false; + if( isset($params['__MOD_REWRITE__']) ) + { + $force_rewrite = true; + unset($params['__MOD_REWRITE__']); + } + + $force_no_sid = false; + if( isset($params['__NO_SID__']) ) + { + $force_no_sid = true; + unset($params['__NO_SID__']); + } + + // append pass through variables to each link to be build + $params = array_merge($this->getPassThroughVariables($params), $params); + + if ($force_rewrite || ($this->Application->RewriteURLs($ssl) && !$no_rewrite)) { + static $rewrite_listeners_done = false; + + if (!$rewrite_listeners_done) { + $mod_rewrite_helper =& $this->Application->recallObject('ModRewriteHelper'); + /* @var $mod_rewrite_helper kModRewriteHelper */ + + $mod_rewrite_helper->initRewriteListeners(); + + $rewrite_listeners_done = true; + } + + $session =& $this->Application->recallObject('Session'); + + if ($session->NeedQueryString() && !$force_no_sid) { + $params['sid'] = $this->Application->GetSID(); + } + + $url = $this->BuildEnv_NEW($t, $params, $pass, $pass_events); + $ret = $this->Application->BaseURL($prefix, $ssl).$url.$map_link; + } + else { + unset($params['pass_category']); // we don't need to pass it when mod_rewrite is off + $env = $this->BuildEnv($t, $params, $pass, $pass_events); + $ret = $this->Application->BaseURL($prefix, $ssl).$index_file.'?'.$env.$map_link; + } + + return $ret; + } + + /** + * Returns variables with values that should be passed throught with this link + variable list + * + * @param Array $params + * @return Array + */ + function getPassThroughVariables(&$params) + { + static $cached_pass_through = null; + + if (isset($params['no_pass_through']) && $params['no_pass_through']) { + unset($params['no_pass_through']); + return Array(); + } + + // because pass through is not changed during script run, then we can cache it + if (is_null($cached_pass_through)) { + + $cached_pass_through = Array(); + $pass_through = $this->Application->GetVar('pass_through'); + + if ($pass_through) { + // names of variables to pass to each link + $cached_pass_through['pass_through'] = $pass_through; + $pass_through = explode(',', $pass_through); + foreach ($pass_through as $pass_through_var) { + $cached_pass_through[$pass_through_var] = $this->Application->GetVar($pass_through_var); + } + } + + } + + return $cached_pass_through; + } + + function BuildEnv($t, $params, $pass='all', $pass_events = false, $env_var = true) + { + if ($this->Application->GetVar('admin') || (array_key_exists('admin', $params) && $params['admin'])) { + $params['admin'] = 1; + + if (!array_key_exists('editing_mode', $params)) { + $params['editing_mode'] = EDITING_MODE; + } + } + + $session =& $this->Application->recallObject('Session'); + $ssl = isset($params['__SSL__']) ? $params['__SSL__'] : 0; + $sid = $session->NeedQueryString() && !$this->Application->RewriteURLs($ssl) ? $this->Application->GetSID() : ''; +// if (getArrayValue($params,'admin') == 1) $sid = $this->Application->GetSID(); + + $ret = ''; + if ($env_var) { + $ret = ENV_VAR_NAME.'='; + } + + $ret .= $sid . '-'; // SID-TEMPLATE + + $encode = false; + if (isset($params['__URLENCODE__'])) { + $encode = $params['__URLENCODE__']; + unset($params['__URLENCODE__']); + } + + if (isset($params['__SSL__'])) { + unset($params['__SSL__']); + } + + $env_string = ''; + $category_id = isset($params['m_cat_id']) ? $params['m_cat_id'] : $this->Application->GetVar('m_cat_id'); + + $item_id = false; + $pass_info = $this->getPassInfo($pass); + if ($pass_info) { + if ($pass_info[0] == 'm') array_shift($pass_info); + foreach ($pass_info as $pass_element) { + list($prefix) = explode('.', $pass_element); + $require_rewrite = $this->Application->findModule('Var', $prefix); + if ($require_rewrite) { + $item_id = isset($params[$pass_element.'_id']) ? $params[$pass_element.'_id'] : $this->Application->GetVar($pass_element.'_id'); + } + $env_string .= ':'.$this->BuildModuleEnv($pass_element, $params, $pass_events); + } + } + + if (strtolower($t) == '__default__') { + if (is_numeric($item_id)) { + $mod_rw_helper =& $this->Application->recallObject('ModRewriteHelper'); + /* @var $mod_rw_helper kModRewriteHelper */ + + $t = $mod_rw_helper->GetItemTemplate($category_id, $pass_element); // $pass_element should be the last processed element + // $t = $this->Application->getCategoryCache($category_id, 'item_templates'); + } + elseif ($category_id) { + $t = strtolower(preg_replace('/^Content\//i', '', $this->Application->getCategoryCache($category_id, 'filenames') )); + } + else { + $t = 'index'; + } + } + + $ret .= $t.':'.$this->BuildModuleEnv('m', $params, $pass_events).$env_string; + + unset($params['pass'], $params['opener'], $params['m_event']); + + if (array_key_exists('escape', $params) && $params['escape']) { + $ret = addslashes($ret); + unset($params['escape']); + } + + if ($params) { + $params_str = ''; + $join_string = $encode ? '&' : '&'; + + foreach ($params as $param => $value) { + $params_str .= $join_string . $param . '=' . $value; + } + + $ret .= $params_str; + } + + if ($encode) { + $ret = str_replace('\\', '%5C', $ret); + } + + return $ret; + } + + function BuildEnv_NEW($t, $params, $pass='all', $pass_events = false) + { + if ($this->Application->GetVar('admin') || (array_key_exists('admin', $params) && $params['admin'])) { + $params['admin'] = 1; + + if (!array_key_exists('editing_mode', $params)) { + $params['editing_mode'] = EDITING_MODE; + } + } + + $ret = ''; + $env = ''; + + $encode = false; + + if (isset($params['__URLENCODE__'])) { + $encode = $params['__URLENCODE__']; + unset($params['__URLENCODE__']); + } + + if (isset($params['__SSL__'])) { + unset($params['__SSL__']); + } + + $catalog_item_found = false; + $pass_info = $this->getPassInfo($pass); + + if ($pass_info) { + if ($pass_info[0] == 'm') { + array_shift($pass_info); + } + + $inject_parts = Array (); // url parts for beginning of url + $params['t'] = $t; // make template available for rewrite listeners + $params['pass_template'] = true; // by default we keep given template in resulting url + + if (!array_key_exists('pass_category', $params)) { + $params['pass_category'] = false; // by default we don't keep categories in url + } + + foreach ($pass_info as $pass_index => $pass_element) { + list ($prefix) = explode('.', $pass_element); + $catalog_item = $this->Application->findModule('Var', $prefix) && $this->Application->getUnitOption($prefix, 'CatalogItem'); + + if (array_key_exists($prefix, $this->Application->RewriteListeners)) { + // if next prefix is same as current, but with special => exclude current prefix from url + $next_prefix = array_key_exists($pass_index + 1, $pass_info) ? $pass_info[$pass_index + 1] : false; + if ($next_prefix) { + $next_prefix = substr($next_prefix, 0, strlen($prefix) + 1); + if ($prefix . '.' == $next_prefix) { + continue; + } + } + + // rewrited url part + $url_part = $this->BuildModuleEnv_NEW($pass_element, $params, $pass_events); + + if (is_string($url_part) && $url_part) { + $ret .= $url_part . '/'; + + if ($catalog_item) { + // pass category later only for catalog items + $catalog_item_found = true; + } + } + elseif (is_array($url_part)) { + // rewrite listener want to insert something at the beginning of url too + if ($url_part[0]) { + $inject_parts[] = $url_part[0]; + } + + if ($url_part[1]) { + $ret .= $url_part[1] . '/'; + } + + if ($catalog_item) { + // pass category later only for catalog items + $catalog_item_found = true; + } + } elseif ($url_part === false) { + // rewrite listener decided not to rewrite given $pass_element + $env .= ':' . $this->BuildModuleEnv($pass_element, $params, $pass_events); + } + } + else { + $env .= ':' . $this->BuildModuleEnv($pass_element, $params, $pass_events); + } + } + + if ($catalog_item_found || preg_match('/c\.[-\d]*/', implode(',', $pass_info))) { + // "c" prefix is present -> keep category + $params['pass_category'] = true; + } + + $params['inject_parts'] = $inject_parts; + + $ret = $this->BuildModuleEnv_NEW('m', $params, $pass_events) . '/' . $ret; + $cat_processed = array_key_exists('category_processed', $params) && $params['category_processed']; + + // remove tempporary parameters used by listeners + unset($params['t'], $params['inject_parts'], $params['pass_template'], $params['pass_category'], $params['category_processed']); + + if (array_key_exists('url_ending', $params)) { + $ret = trim($ret, '/') . $params['url_ending']; + unset($params['url_ending']); + } + else { + $ret = trim($ret, '/') . MOD_REWRITE_URL_ENDING; + } + + if ($env) { + $params[ENV_VAR_NAME] = ltrim($env, ':'); + } + } + + unset($params['pass'], $params['opener'], $params['m_event']); + + if (array_key_exists('escape', $params) && $params['escape']) { + $ret = addslashes($ret); + unset($params['escape']); + } + + $ret = str_replace('%2F', '/', urlencode($ret)); + + if ($params) { + $params_str = ''; + $join_string = $encode ? '&' : '&'; + + foreach ($params as $param => $value) { + $params_str .= $join_string . $param . '=' . $value; + } + + $ret .= '?' . substr($params_str, strlen($join_string)); + } + + if ($encode) { + $ret = str_replace('\\', '%5C', $ret); + } + + return $ret; + } + + /** + * Builds env part that corresponds prefix passed + * + * @param string $prefix_special item's prefix & [special] + * @param Array $params url params + * @param bool $pass_events + */ + function BuildModuleEnv($prefix_special, &$params, $pass_events = false) + { + list($prefix) = explode('.', $prefix_special); + $query_vars = $this->Application->getUnitOption($prefix, 'QueryString'); + + //if pass events is off and event is not implicity passed + if( !$pass_events && !isset($params[$prefix_special.'_event']) ) { + $params[$prefix_special.'_event'] = ''; // remove event from url if requested + //otherwise it will use value from get_var + } + + if(!$query_vars) return ''; + + $tmp_string = Array(0 => $prefix_special); + foreach($query_vars as $index => $var_name) + { + //if value passed in params use it, otherwise use current from application + $var_name = $prefix_special.'_'.$var_name; + $tmp_string[$index] = isset( $params[$var_name] ) ? $params[$var_name] : $this->Application->GetVar($var_name); + if ( isset($params[$var_name]) ) unset( $params[$var_name] ); + } + + $escaped = array(); + foreach ($tmp_string as $tmp_val) { + $escaped[] = str_replace(Array('-',':'), Array('\-','\:'), $tmp_val); + } + + $ret = implode('-', $escaped); + if ($this->Application->getUnitOption($prefix, 'PortalStyleEnv') == true) + { + $ret = preg_replace('/^([a-zA-Z]+)-([0-9]+)-(.*)/','\\1\\2-\\3', $ret); + } + return $ret; + } + + function BuildModuleEnv_NEW($prefix_special, &$params, $keep_events = false) + { + list ($prefix) = explode('.', $prefix_special); + + $url_parts = Array (); + $listener = $this->Application->RewriteListeners[$prefix][0]; + + $ret = $listener[0]->$listener[1](REWRITE_MODE_BUILD, $prefix_special, $params, $url_parts, $keep_events); + + return $ret; + } + + /** + * Returns sorted array of passed prefixes (to build url from) + * + * @param string $pass + * @return Array + */ + function getPassInfo($pass = 'all') + { + if (!$pass) $pass = 'all'; + $pass = trim( + preg_replace( + '/(?<=,|\\A)all(?=,|\\z)/', + trim($this->Application->GetVar('passed'), ','), + trim($pass, ',') + ), + ','); + + if (!$pass) { + return Array(); + } + + $pass_info = array_unique( explode(',', $pass) ); // array( prefix[.special], prefix[.special] ... + + // we need to keep that sorting despite the sorting below, because this sorts prefixes with same priority by name + sort($pass_info, SORT_STRING); // to be prefix1,prefix1.special1,prefix1.special2,prefix3.specialX + + foreach ($pass_info as $prefix) { + list ($prefix_only, ) = explode('.', $prefix, 2); + $sorted[$prefix] = $this->Application->getUnitOption($prefix_only, 'RewritePriority', 0); + } + + asort($sorted, SORT_NUMERIC); + $pass_info = array_keys($sorted); + + // ensure that "m" prefix is at the beginning + $main_index = array_search('m', $pass_info); + if ($main_index !== false) { + unset($pass_info[$main_index]); + array_unshift($pass_info, 'm'); + } + + return $pass_info; + } + + /** + * Returns index file, that could be passed as parameter to method, as parameter to tag and as constant or not passed at all + * + * @param string $prefix + * @param string $index_file + * @param Array $params + * @return string + */ + function getIndexFile($prefix, $index_file, &$params) + { + if (isset($params['index_file'])) { + $index_file = $params['index_file']; + unset($params['index_file']); + return $index_file; + } + + if (isset($index_file)) { + return $index_file; + } + + if (defined('INDEX_FILE')) { + return INDEX_FILE; + } + + $cut_prefix = trim(BASE_PATH, '/').'/'.trim($prefix, '/'); + return trim(preg_replace('/'.preg_quote($cut_prefix, '/').'(.*)/', '\\1', $_SERVER['PHP_SELF']), '/'); + } + + function getPhysicalTemplate($template) + { + return array_search($template, $this->structureTemplateMapping); + } + + /** + * Loads template mapping for Front-End + * + */ + function LoadStructureTemplateMapping() + { + if (!$this->Application->isAdmin) { + $category_helper =& $this->Application->recallObject('CategoryHelper'); + /* @var $category_helper CategoryHelper */ + + $this->structureTemplateMapping = $category_helper->getTemplateMapping(); + } + } +} \ No newline at end of file Index: branches/5.2.x/core/units/users/users_event_handler.php =================================================================== diff -u -N -r14095 -r14184 --- branches/5.2.x/core/units/users/users_event_handler.php (.../users_event_handler.php) (revision 14095) +++ branches/5.2.x/core/units/users/users_event_handler.php (.../users_event_handler.php) (revision 14184) @@ -1,6 +1,6 @@ GetFieldOptions('RootPassword'); $field_options['salt'] = 'b38'; - $object->SetFieldOptions('RootPassword', $field_options); - $verify_options = $object->GetFieldOptions('VerifyRootPassword'); - $verify_options['salt'] = 'b38'; - $object->SetFieldOptions('VerifyRootPassword', $verify_options); // this is internal hack to allow root/root passwords for dev if ($this->Application->isDebugMode() && $field_values['RootPassword'] == 'root') { - $this->Application->ConfigHash['Min_Password'] = 4; + $field_options['min_length'] = 4; } + $object->SetFieldOptions('RootPassword', $field_options); + + $verify_options = $object->GetFieldOptions('VerifyRootPassword'); + $verify_options['salt'] = 'b38'; + $object->SetFieldOptions('VerifyRootPassword', $verify_options); + $this->RemoveRequiredFields($object); $object->SetDBField('RootPassword', $this->Application->ConfigValue('RootPass')); $object->SetFieldsFromHash($field_values); Index: branches/5.2.x/core/kernel/managers/cache_manager.php =================================================================== diff -u -N --- branches/5.2.x/core/kernel/managers/cache_manager.php (revision 0) +++ branches/5.2.x/core/kernel/managers/cache_manager.php (revision 14184) @@ -0,0 +1,574 @@ +cacheHandler =& $this->Application->makeClass('kCache'); + } + + /** + * Returns cache key, used to cache phrase and configuration variable IDs used on current page + * + * @return string + * @access protected + */ + protected function getCacheKey() + { + // TODO: maybe language part isn't required, since same phrase from different languages have one ID now + return $this->Application->GetVar('t') . $this->Application->GetVar('m_theme') . $this->Application->GetVar('m_lang') . $this->Application->isAdmin; + } + + /** + * Loads phrases and configuration variables, that were used on this template last time + * + * @access public + */ + public function LoadApplicationCache() + { + $phrase_ids = $config_ids = Array (); + + $sql = 'SELECT PhraseList, ConfigVariables + FROM ' . TABLE_PREFIX . 'PhraseCache + WHERE Template = ' . $this->Conn->qstr( md5($this->getCacheKey()) ); + $res = $this->Conn->GetRow($sql); + + if ($res) { + if ( $res['PhraseList'] ) { + $phrase_ids = explode(',', $res['PhraseList']); + } + + if ( $res['ConfigVariables'] ) { + $config_ids = array_diff( explode(',', $res['ConfigVariables']), $this->originalConfigIDs); + } + } + + $this->Application->Phrases->Init('phrases', '', null, $phrase_ids); + $this->configIDs = $this->originalConfigIDs = $config_ids; + + $this->InitConfig(); + } + + /** + * Updates phrases and configuration variables, that were used on this template + * + * @access public + */ + public function UpdateApplicationCache() + { + $update = false; + + //something changed + $update = $update || $this->Application->Phrases->NeedsCacheUpdate(); + $update = $update || (count($this->configIDs) && $this->configIDs != $this->originalConfigIDs); + + if ($update) { + $fields_hash = Array ( + 'PhraseList' => implode(',', $this->Application->Phrases->Ids), + 'CacheDate' => adodb_mktime(), + 'Template' => md5( $this->getCacheKey() ), + 'ConfigVariables' => implode(',', array_unique($this->configIDs)), + ); + + $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'PhraseCache', 'REPLACE'); + } + } + + /** + * Loads configuration variables, that were used on this template last time + * + * @access protected + */ + protected function InitConfig() + { + if (!$this->originalConfigIDs) { + return ; + } + + $sql = 'SELECT VariableValue, VariableName + FROM ' . TABLE_PREFIX . 'ConfigurationValues + WHERE VariableId IN (' . implode(',', $this->originalConfigIDs) . ')'; + $config_variables = $this->Conn->GetCol($sql, 'VariableName'); + + $this->configVariables = array_merge($this->configVariables, $config_variables); + } + + /** + * Returns configuration option value by name + * + * @param string $name + * @return string + * @access public + */ + public function ConfigValue($name) + { + if ($name == 'Smtp_AdminMailFrom') { + $res = $this->Application->siteDomainField('AdminEmail'); + + if ($res) { + return $res; + } + } + + if ( array_key_exists($name, $this->configVariables) ) { + return $this->configVariables[$name]; + } + + if ( defined('IS_INSTALL') && IS_INSTALL && !$this->Application->TableFound('ConfigurationValues') ) { + return false; + } + + $this->Conn->nextQueryCachable = true; + $sql = 'SELECT VariableId, VariableValue + FROM ' . TABLE_PREFIX . 'ConfigurationValues + WHERE VariableName = ' . $this->Conn->qstr($name); + $res = $this->Conn->GetRow($sql); + + if ($res !== false) { + $this->configIDs[] = $res['VariableId']; + $this->configVariables[$name] = $res['VariableValue']; + + return $res['VariableValue']; + } + + return false; + } + + /** + * Loads data, that was cached during unit config parsing + * + * @return bool + * @access public + */ + public function LoadUnitCache() + { + if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { + $data = $this->Application->getCache('master:configs_parsed', false); + } + else { + $data = $this->Application->getDBCache('configs_parsed'); + } + + if ($data) { + $cache = unserialize($data); // 126 KB all modules + unset($data); + + $this->Application->Factory->setFromCache($cache); + $this->Application->UnitConfigReader->setFromCache($cache); + $this->Application->EventManager->setFromCache($cache); + + $aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray'); + /* @var $aggregator kArray */ + + $aggregator->setFromCache($cache); + $this->setFromCache($cache); + $this->Application->setFromCache($cache); + unset($cache); + + return true; + + } + + return false; + } + + /** + * Updates data, that was parsed from unit configs this time + * + * @access public + */ + public function UpdateUnitCache() + { + $aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray'); + /* @var $aggregator kArray */ + + $this->preloadConfigVars(); // preloading will put to cache + + $cache = array_merge( + $this->Application->Factory->getToCache(), + $this->Application->UnitConfigReader->getToCache(), + $this->Application->EventManager->getToCache(), + $aggregator->getToCache(), + $this->getToCache(), + $this->Application->getToCache() + ); + + $cache_rebuild_by = SERVER_NAME . ' (' . getenv('REMOTE_ADDR') . ') - ' . adodb_date('d/m/Y H:i:s'); + + if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { + $this->Application->setCache('master:configs_parsed', serialize($cache)); + $this->Application->setCache('master:last_cache_rebuild', $cache_rebuild_by); + } + else { + $this->Application->setDBCache('configs_parsed', serialize($cache)); + $this->Application->setDBCache('last_cache_rebuild', $cache_rebuild_by); + } + } + + /** + * Deletes all data, that was cached during unit config parsing (including unit config locations) + * + * @param bool $include_sections + * @access public + */ + public function DeleteUnitCache($include_sections = false) + { + if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { + $this->Application->deleteCache('master:configs_parsed'); + } + else { + $this->Application->deleteDBCache('configs_parsed'); + } + + if ($include_sections) { + if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { + $this->Application->deleteCache('master:sections_parsed'); + } + else { + $this->Application->deleteDBCache('sections_parsed'); + } + } + } + + /** + * Preloads widely used configuration variables, so they will get to cache for sure + * + * @access protected + */ + protected function preloadConfigVars() + { + $config_vars = Array ( + // session related + 'SessionTimeout', + 'SessionCookieName', + 'SessionCookieDomains', + 'SessionBrowserSignatureCheck', + 'SessionIPAddressCheck', + 'CookieSessions', + 'KeepSessionOnBrowserClose', + 'User_GuestGroup', + 'User_LoggedInGroup', + + // output related + 'UseModRewrite', + 'UseContentLanguageNegotiation', + 'UseOutputCompression', + 'OutputCompressionLevel', + 'Config_Site_Time', + 'SystemTagCache', + + // tracking related + 'UseChangeLog', + 'UseVisitorTracking', + 'ModRewriteUrlEnding', + 'ForceModRewriteUrlEnding', + 'UseCronForRegularEvent', + ); + + $escaped_config_vars = array_map(Array (&$this->Conn, 'qstr'), $config_vars); + + $sql = 'SELECT VariableId, VariableName, VariableValue + FROM ' . TABLE_PREFIX . 'ConfigurationValues + WHERE VariableName IN (' . implode(',', $escaped_config_vars) . ')'; + $data = $this->Conn->Query($sql, 'VariableId'); + + foreach ($data as $variable_id => $variable_info) { + $this->configIDs[] = $variable_id; + $this->configVariables[ $variable_info['VariableName'] ] = $variable_info['VariableValue']; + } + } + + /** + * Sets data from cache to object + * + * @param Array $data + * @access public + */ + public function setFromCache(&$data) + { + $this->configVariables = $data['Application.ConfigHash']; + $this->configIDs = $this->originalConfigIDs = $data['Application.ConfigCacheIds']; + } + + /** + * Gets object data for caching + * The following caches should be reset based on admin interaction (adjusting config, enabling modules etc) + * + * @access public + * @return Array + */ + public function getToCache() + { + return Array ( + 'Application.ConfigHash' => $this->configVariables, + 'Application.ConfigCacheIds' => $this->configIDs, + + // not in use, since it only represents template specific values, not global ones + // 'Application.Caches.ConfigVariables' => $this->originalConfigIDs, + ); + } + + /** + * Returns caching type (none, memory, temporary) + * + * @return int + * @access public + */ + public function isCachingType($caching_type) + { + return $this->cacheHandler->getCachingType() == $caching_type; + } + + /** + * Prints caching statistics + * + * @access public + */ + public function printStatistics() + { + $this->cacheHandler->printStatistics(); + } + + /** + * Returns cached $key value from cache named $cache_name + * + * @param int $key key name from cache + * @param bool $store_locally store data locally after retrieved + * @return mixed + * @access public + */ + public function getCache($key, $store_locally = true) + { + return $this->cacheHandler->getCache($key, $store_locally); + } + + /** + * Adds new value to cache $cache_name and identified by key $key + * + * @param int $key key name to add to cache + * @param mixed $value value of chached record + * @param int $expiration when value expires (0 - doesn't expire) + * @access public + */ + public function setCache($key, $value, $expiration = 0) + { + return $this->cacheHandler->setCache($key, $value, $expiration); + } + + /** + * Deletes key from cache + * + * @param string $key + * @access public + */ + public function deleteCache($key) + { + $this->cacheHandler->delete($key); + } + + /** + * Reset's all memory cache at once + * + * @access public + */ + public function resetCache() + { + $this->cacheHandler->reset(); + } + + /** + * Returns value from database cache + * + * @param string $name key name + * @return mixed + * @access public + */ + public function getDBCache($name) + { + $this->Conn->nextQueryCachable = true; + + $sql = 'SELECT Data, Cached, LifeTime + FROM ' . TABLE_PREFIX . 'Cache + WHERE VarName = ' . $this->Conn->qstr($name); + $data = $this->Conn->GetRow($sql); + + if ($data) { + $lifetime = (int)$data['LifeTime']; // in seconds + if (($lifetime > 0) && ($data['Cached'] + $lifetime < adodb_mktime())) { + // delete expired + $this->Conn->nextQueryCachable = true; + + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache + WHERE VarName = ' . $this->Conn->qstr($name); + $this->Conn->Query($sql); + + return false; + } + + return $data['Data']; + } + + return false; + } + + /** + * Sets value to database cache + * + * @param string $name + * @param mixed $value + * @param int $expiration + * @access public + */ + public function setDBCache($name, $value, $expiration = false) + { + if ((int)$expiration <= 0) { + $expiration = -1; + } + + $fields_hash = Array ( + 'VarName' => $name, + 'Data' => &$value, + 'Cached' => adodb_mktime(), + 'LifeTime' => (int)$expiration, + ); + + $this->Conn->nextQueryCachable = true; + $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE'); + } + + /** + * Deletes key from database cache + * + * @param string $name + * @access public + */ + public function deleteDBCache($name) + { + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache + WHERE VarName = ' . $this->Conn->qstr($name); + $this->Conn->Query($sql); + } + + /** + * Increments serial based on prefix and it's ID (optional) + * + * @param string $prefix + * @param int $id ID (value of IDField) or ForeignKeyField:ID + * @param bool $increment + * @access public + */ + public function incrementCacheSerial($prefix, $id = null, $increment = true) + { + $pascal_case_prefix = implode('', array_map('ucfirst', explode('-', $prefix))); + $serial_name = $pascal_case_prefix . (isset($id) ? 'IDSerial:' . $id : 'Serial'); + + if ($increment) { + if (defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode()) { + $this->Application->Debugger->appendHTML('Incrementing serial: ' . $serial_name . '.'); + } + + $this->setCache($serial_name, (int)$this->getCache($serial_name) + 1); + + if (!defined('IS_INSTALL') || !IS_INSTALL) { + // delete cached mod-rewrite urls related to given prefix and id + $delete_clause = isset($id) ? $prefix . ':' . $id : $prefix; + + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'CachedUrls + WHERE Prefixes LIKE ' . $this->Conn->qstr('%|' . $delete_clause . '|%'); + $this->Conn->Query($sql); + } + } + + return $serial_name; + } + + /** + * Returns cached category informaton by given cache name. All given category + * information is recached, when at least one of 4 caches is missing. + * + * @param int $category_id + * @param string $name cache name = {filenames, category_designs, category_tree} + * @return string + * @access public + */ + public function getCategoryCache($category_id, $name) + { + $serial_name = '[%CIDSerial:' . $category_id . '%]'; + $cache_key = $name . $serial_name; + $ret = $this->getCache($cache_key); + + if ($ret === false) { + if (!$category_id) { + // don't query database for "Home" category (ID = 0), because it doesn't exist in database + return false; + } + + // this allows to save 2 sql queries for each category + $this->Conn->nextQueryCachable = true; + $sql = 'SELECT NamedParentPath, CachedTemplate, TreeLeft, TreeRight + FROM ' . TABLE_PREFIX . 'Category + WHERE CategoryId = ' . (int)$category_id; + $category_data = $this->Conn->GetRow($sql); + + if ($category_data !== false) { + // only direct links to category pages work (symlinks, container pages and so on won't work) + $this->setCache('filenames' . $serial_name, $category_data['NamedParentPath']); + $this->setCache('category_designs' . $serial_name, ltrim($category_data['CachedTemplate'], '/')); + $this->setCache('category_tree' . $serial_name, $category_data['TreeLeft'] . ';' . $category_data['TreeRight']); + } + } + + return $this->getCache($cache_key); + } +} \ No newline at end of file Index: branches/5.2.x/core/kernel/utility/unit_config_reader.php =================================================================== diff -u -N -r14095 -r14184 --- branches/5.2.x/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 14095) +++ branches/5.2.x/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 14184) @@ -1,6 +1,6 @@ Application->recallObject('TagsAggregator', 'kArray'); - /* @var $aggregator kArray */ - - $this->preloadConfigVars(); // preloading will put to cache - - $cache = array_merge( - $this->Application->Factory->getToCache(), - $this->getToCache(), - $this->Application->EventManager->getToCache(), - $aggregator->getToCache(), - $this->Application->getToCache() - ); - - if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { - $this->Application->setCache('master:configs_parsed', serialize($cache)); - $this->Application->setCache('master:config_files', serialize($this->configFiles)); - } - else { - $this->Application->setDBCache('configs_parsed', serialize($cache)); - $this->Application->setDBCache('config_files', serialize($this->configFiles)); - } - - $cache_rebuild_by = SERVER_NAME . ' (' . getenv('REMOTE_ADDR') . ') - ' . adodb_date('d/m/Y H:i:s'); - $this->Application->setDBCache('last_cache_rebuild', $cache_rebuild_by); - - unset($this->configFiles); - } - - function preloadConfigVars() - { - $config_vars = Array ( - // session related - 'SessionTimeout', - 'SessionCookieName', - 'SessionCookieDomains', - 'SessionBrowserSignatureCheck', - 'SessionIPAddressCheck', - 'CookieSessions', - 'KeepSessionOnBrowserClose', - 'User_GuestGroup', - 'User_LoggedInGroup', - - // output related - 'UseModRewrite', - 'UseContentLanguageNegotiation', - 'UseOutputCompression', - 'OutputCompressionLevel', - 'Config_Site_Time', - 'SystemTagCache', - - // tracking related - 'UseChangeLog', - 'UseVisitorTracking', - 'ModRewriteUrlEnding', - 'ForceModRewriteUrlEnding', - 'UseCronForRegularEvent', - ); - - foreach ($config_vars as $var) { - $this->Application->ConfigValue($var); - } - } - - function RestoreParsedData() - { - if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { - $data = $this->Application->getCache('master:configs_parsed', false); - } - else { - $data = $this->Application->getDBCache('configs_parsed'); - } - - if ($data) { - $cache = unserialize($data); // 126 KB all modules - unset($data); - - $this->Application->Factory->setFromCache($cache); - $this->setFromCache($cache); - $this->Application->EventManager->setFromCache($cache); - - $aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray'); - /* @var $aggregator kArray */ - - $aggregator->setFromCache($cache); - $this->Application->setFromCache($cache); - unset($cache); - - return true; - - } - - return false; - } - - function ResetParsedData($include_sections = false) - { - if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { - $this->Application->deleteCache('master:configs_parsed'); - } - else { - $this->Application->deleteDBCache('configs_parsed'); - } - - if ($include_sections) { - if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { - $this->Application->deleteCache('master:sections_parsed'); - } - else { - $this->Application->deleteDBCache('sections_parsed'); - } - } - } - function scanModules($folderPath, $cache = true) { if (defined('IS_INSTALL') && IS_INSTALL && !defined('FORCE_CONFIG_CACHE')) { @@ -218,7 +103,8 @@ } if ($cache) { - $restored = $this->RestoreParsedData(); + $restored = $this->Application->cacheManager->LoadUnitCache(); + if ($restored) { if ( defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode() ) { $this->Application->Debugger->appendHTML('UnitConfigReader: Restoring Cache'); @@ -292,7 +178,7 @@ $data = $this->Application->getDBCache('config_files'); } - if ($cache && $data) { + if ($data) { $this->configFiles = unserialize($data); if ( !defined('DBG_VALIDATE_CONFIGS') && !DBG_VALIDATE_CONFIGS ) { @@ -302,6 +188,15 @@ else { $this->findConfigFiles(FULL_PATH . DIRECTORY_SEPARATOR . 'core'); // search from core directory $this->findConfigFiles($folderPath); // search from modules directory + + if ($cache) { + if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { + $this->Application->setCache('master:config_files', serialize($this->configFiles)); + } + else { + $this->Application->setDBCache('config_files', serialize($this->configFiles)); + } + } } foreach ($this->configFiles as $filename) { @@ -311,6 +206,10 @@ throw new Exception('Prefix not defined in config file ' . $filename . ''); } } + + if ($cache) { + unset($this->configFiles); + } } /** @@ -354,7 +253,7 @@ $this->runAfterConfigRead($prefix); } - if (!isset($store_cache)) { + if ( !isset($store_cache) ) { // store cache not overrided -> use global setting $store_cache = $this->StoreCache; } @@ -371,7 +270,7 @@ $after_event = new kEvent('adm:OnAfterCacheRebuild'); $this->Application->HandleEvent($after_event); - $this->CacheParsedData(); + $this->Application->cacheManager->UpdateUnitCache(); if (defined('DEBUG_MODE') && DEBUG_MODE && defined('DBG_VALIDATE_CONFIGS') && DBG_VALIDATE_CONFIGS) { // validate configs here to have changes from OnAfterConfigRead hooks to prefixes Index: branches/5.2.x/core/kernel/application.php =================================================================== diff -u -N -r14095 -r14184 --- branches/5.2.x/core/kernel/application.php (.../application.php) (revision 14095) +++ branches/5.2.x/core/kernel/application.php (.../application.php) (revision 14184) @@ -1,6 +1,6 @@ Factory = new kFactory(); $this->registerDefaultClasses(); $this->Phrases = new PhrasesCache(); - $this->memoryCache =& $this->Factory->makeClass('Cache'); - $this->EventManager =& $this->Factory->makeClass('EventManager'); + + $this->cacheManager =& $this->makeClass('kCacheManager'); + $this->cacheManager->InitCache(); + + $this->UrlManager =& $this->makeClass('kUrlManager'); + $this->EventManager =& $this->makeClass('EventManager'); $this->Factory->Storage['EventManager'] =& $this->EventManager; $this->RegisterDefaultBuildEvents(); @@ -360,7 +349,7 @@ $this->StoreVar('UserGroups', $user_groups, true); // true for optional } - $this->LoadStructureTemplateMapping(); + $this->UrlManager->LoadStructureTemplateMapping(); $this->HttpQuery->AfterInit(); $this->Session->ValidateExpired(); @@ -369,8 +358,7 @@ $this->Debugger->appendTimestamp('Processed HTTPQuery AfterInit'); } - $this->LoadCache(); - $this->InitConfig(); + $this->cacheManager->LoadApplicationCache(); $site_timezone = $this->ConfigValue('Config_Site_Time'); @@ -516,22 +504,6 @@ } kUtil::safeDefine('THEMES_PATH', $path); - - /*$theme_id = $this->GetVar('m_theme'); - if (!$theme_id) { - $theme_id = $this->GetDefaultThemeId(); - if (!$theme_id) { - if (!defined('IS_INSTALL')) $this->ApplicationDie('No Primary Theme Selected'); - } - } - $this->SetVar('m_theme', $theme_id); - $this->SetVar('theme.current_id', $theme_id ); // KOSTJA: this is to fool theme' getPassedId - $theme =& $this->recallObject('theme.current'); - if (!$theme->IsLoaded() || !$theme->GetDBField('Enabled')) { - if (!defined('IS_INSTALL')) $this->ApplicationDie('Unknown or disabled theme'); - } - - kUtil::safeDefine('THEMES_PATH', '/themes/'.$theme->GetDBField('Name'));*/ } function GetFrontThemePath($force=0) @@ -695,16 +667,18 @@ $this->registerClass('kTempTablesHandler', KERNEL_PATH . '/utility/temp_handler.php'); $this->registerClass('kEventManager', KERNEL_PATH . '/event_manager.php', 'EventManager', 'kiCacheable'); - $this->registerClass('kHookManager', KERNEL_PATH . '/managers/hook_manager.php', 'kHookManager', 'kiCacheable'); - $this->registerClass('kAgentManager', KERNEL_PATH . '/managers/agent_manager.php', 'kAgentManager', 'kiCacheable'); - $this->registerClass('kRequestManager', KERNEL_PATH . '/managers/request_manager.php', 'kRequestManager'); + $this->registerClass('kHookManager', KERNEL_PATH . '/managers/hook_manager.php', null, 'kiCacheable'); + $this->registerClass('kAgentManager', KERNEL_PATH . '/managers/agent_manager.php', null, 'kiCacheable'); + $this->registerClass('kRequestManager', KERNEL_PATH . '/managers/request_manager.php'); + $this->registerClass('kUrlManager', KERNEL_PATH . '/managers/url_manager.php'); + $this->registerClass('kCacheManager', KERNEL_PATH . '/managers/cache_manager.php', null, 'kiCacheable'); $this->registerClass('kUnitConfigReader', KERNEL_PATH . '/utility/unit_config_reader.php'); $this->registerClass('kArray', KERNEL_PATH . '/utility/params.php'); $this->registerClass('Params', KERNEL_PATH . '/utility/params.php'); $this->registerClass('Params', KERNEL_PATH . '/utility/params.php', 'kActions'); - $this->registerClass('kCache', KERNEL_PATH . '/utility/cache.php', 'Cache', 'Params'); + $this->registerClass('kCache', KERNEL_PATH . '/utility/cache.php', 'kCache', 'Params'); $this->registerClass('kHTTPQuery', KERNEL_PATH . '/utility/http_query.php', 'HTTPQuery', 'Params'); $this->registerClass('kHelper', KERNEL_PATH . '/kbase.php'); @@ -733,7 +707,7 @@ $this->registerClass('kEmailSendingHelper', KERNEL_PATH . '/utility/email_send.php', 'EmailSender', 'kHelper'); $this->registerClass('kSocket', KERNEL_PATH . '/utility/socket.php', 'Socket'); - if (file_exists(MODULES_PATH . '/in-commerce/units/currencies/currency_rates.php')) { + if ( file_exists(MODULES_PATH . '/in-commerce/units/currencies/currency_rates.php') ) { $this->registerClass('kCurrencyRates', MODULES_PATH . '/in-commerce/units/currencies/currency_rates.php'); } @@ -753,87 +727,22 @@ * @param int $category_id * @param string $name cache name = {filenames, category_designs, category_tree} * @return string + * @access public */ - function getCategoryCache($category_id, $name) + public function getCategoryCache($category_id, $name) { - $serial_name = '[%CIDSerial:' . $category_id . '%]'; - $cache_key = $name . $serial_name; - $ret = $this->getCache($cache_key); - - if ($ret === false) { - if (!$category_id) { - // don't query database for "Home" category (ID = 0), because it doesn't exist in database - return false; - } - - // this allows to save 2 sql queries for each category - $this->Conn->nextQueryCachable = true; - $sql = 'SELECT NamedParentPath, CachedTemplate, TreeLeft, TreeRight - FROM ' . TABLE_PREFIX . 'Category - WHERE CategoryId = ' . (int)$category_id; - $category_data = $this->Conn->GetRow($sql); - - if ($category_data !== false) { - // only direct links to category pages work (symlinks, container pages and so on won't work) - $this->setCache('filenames' . $serial_name, $category_data['NamedParentPath']); - $this->setCache('category_designs' . $serial_name, ltrim($category_data['CachedTemplate'], '/')); - $this->setCache('category_tree' . $serial_name, $category_data['TreeLeft'] . ';' . $category_data['TreeRight']); - } - } - - return $this->getCache($cache_key); + return $this->cacheManager->getCategoryCache($category_id, $name); } /** - * Returns item's filename that corresponds id passed. If possible, then get it from cache - * - * @param string $prefix - * @param int $id - * @param int $category_id - * @return string - */ - function getFilename($prefix, $id, $category_id = null) - { - if ($prefix == 'c') { - throw new Exception('Method "' . __FUNCTION__ . '" no longer work with "c" prefix. Please use "getCategoryCache" method instead'); - - return false; - } - - $category_id = isset($category_id) ? $category_id : $this->GetVar('m_cat_id'); - - $cache_key = 'filenames[%' . $this->incrementCacheSerial($prefix, $id, false) . '%]:' . (int)$category_id; - $filename = $this->getCache($cache_key); - - if ($filename === false) { - $this->Conn->nextQueryCachable = true; - $sql = 'SELECT ResourceId - FROM ' . $this->getUnitOption($prefix, 'TableName') . ' - WHERE ' . $this->getUnitOption($prefix, 'IDField') . ' = ' . $this->Conn->qstr($id); - $resource_id = $this->Conn->GetOne($sql); - - $this->Conn->nextQueryCachable = true; - $sql = 'SELECT Filename - FROM ' . TABLE_PREFIX . 'CategoryItems - WHERE (ItemResourceId = ' . $resource_id . ') AND (CategoryId = ' . (int)$category_id . ')'; - $filename = $this->Conn->GetOne($sql); - - if ($filename !== false) { - $this->setCache($cache_key, $filename); - } - } - - return $filename; - } - - /** * Returns caching type (none, memory, temporary) * * @return int + * @access public */ - function isCachingType($caching_type) + public function isCachingType($caching_type) { - return $this->memoryCache->getCachingType() == $caching_type; + return $this->cacheManager->isCachingType($caching_type); } /** @@ -842,30 +751,24 @@ * @param string $prefix * @param int $id ID (value of IDField) or ForeignKeyField:ID * @param bool $increment + * @access public */ - function incrementCacheSerial($prefix, $id = null, $increment = true) + public function incrementCacheSerial($prefix, $id = null, $increment = true) { - $pascal_case_prefix = implode('', array_map('ucfirst', explode('-', $prefix))); - $serial_name = $pascal_case_prefix . (isset($id) ? 'IDSerial:' . $id : 'Serial'); + return $this->cacheManager->incrementCacheSerial($prefix, $id, $increment); + } - if ($increment) { - if (defined('DEBUG_MODE') && DEBUG_MODE && $this->isDebugMode()) { - $this->Debugger->appendHTML('Incrementing serial: ' . $serial_name . '.'); - } - - $this->setCache($serial_name, (int)$this->getCache($serial_name) + 1); - - if (!defined('IS_INSTALL') || !IS_INSTALL) { - // delete cached mod-rewrite urls related to given prefix and id - $delete_clause = isset($id) ? $prefix . ':' . $id : $prefix; - - $sql = 'DELETE FROM ' . TABLE_PREFIX . 'CachedUrls - WHERE Prefixes LIKE ' . $this->Conn->qstr('%|' . $delete_clause . '|%'); - $this->Conn->Query($sql); - } - } - - return $serial_name; + /** + * Returns cached $key value from cache named $cache_name + * + * @param int $key key name from cache + * @param bool $store_locally store data locally after retrieved + * @return mixed + * @access public + */ + public function getCache($key, $store_locally = true) + { + return $this->cacheManager->getCache($key, $store_locally); } /** @@ -874,102 +777,68 @@ * @param int $key key name to add to cache * @param mixed $value value of chached record * @param int $expiration when value expires (0 - doesn't expire) + * @access public */ - function setCache($key, $value, $expiration = 0) + public function setCache($key, $value, $expiration = 0) { - return $this->memoryCache->setCache($key, $value, $expiration); + return $this->cacheManager->setCache($key, $value, $expiration); } /** - * Sets value to database cache + * Deletes key from cache * - * @param string $name - * @param mixed $value - * @param int $expiration + * @param string $key + * @access public */ - function setDBCache($name, $value, $expiration = false) + public function deleteCache($key) { - if ((int)$expiration <= 0) { - $expiration = -1; - } - - $fields_hash = Array ( - 'VarName' => $name, - 'Data' => &$value, - 'Cached' => adodb_mktime(), - 'LifeTime' => (int)$expiration, - ); - - $this->Conn->nextQueryCachable = true; - $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE'); + $this->cacheManager->deleteCache($key); } /** - * Returns cached $key value from cache named $cache_name + * Reset's all memory cache at once * - * @param int $key key name from cache - * @param bool $store_locally store data locally after retrieved - * @return mixed + * @access public */ - function getCache($key, $store_locally = true) + public function resetCache() { - return $this->memoryCache->getCache($key, $store_locally); + $this->cacheManager->resetCache(); } /** * Returns value from database cache * * @param string $name key name * @return mixed + * @access public */ - function getDBCache($name) + public function getDBCache($name) { - $this->Conn->nextQueryCachable = true; - - $sql = 'SELECT Data, Cached, LifeTime - FROM ' . TABLE_PREFIX . 'Cache - WHERE VarName = ' . $this->Conn->qstr($name); - $data = $this->Conn->GetRow($sql); - - if ($data) { - $lifetime = (int)$data['LifeTime']; // in seconds - if (($lifetime > 0) && ($data['Cached'] + $lifetime < adodb_mktime())) { - // delete expired - $this->Conn->nextQueryCachable = true; - - $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache - WHERE VarName = ' . $this->Conn->qstr($name); - $this->Conn->Query($sql); - - return false; - } - - return $data['Data']; - } - - return false; + return $this->cacheManager->getDBCache($name); } /** - * Deletes key from cache + * Sets value to database cache * - * @param string $key + * @param string $name + * @param mixed $value + * @param int $expiration + * @access public */ - function deleteCache($key) + public function setDBCache($name, $value, $expiration = false) { - $this->memoryCache->delete($key); + $this->cacheManager->setDBCache($name, $value, $expiration); } /** * Deletes key from database cache * * @param string $name + * @access public */ - function deleteDBCache($name) + public function deleteDBCache($name) { - $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache - WHERE VarName = ' . $this->Conn->qstr($name); - $this->Conn->Query($sql); + $this->cacheManager->deleteDBCache($name); } /** @@ -1118,7 +987,7 @@ $this->Session->SaveData(); if (kUtil::constOn('DBG_CACHE')) { - $this->memoryCache->printStatistics(); + $this->cacheManager->printStatistics(); } $this->HTML = ob_get_clean() . $this->HTML . $this->Debugger->printReport(true); @@ -1143,7 +1012,7 @@ echo $this->HTML; } - $this->UpdateCache(); + $this->cacheManager->UpdateApplicationCache(); flush(); if (!$debug_mode) { @@ -1512,223 +1381,20 @@ } /** - * Returns index file, that could be passed as parameter to method, as parameter to tag and as constant or not passed at all - * - * @param string $prefix - * @param string $index_file - * @param Array $params - * @return string - */ - function getIndexFile($prefix, $index_file, &$params) - { - if (isset($params['index_file'])) { - $index_file = $params['index_file']; - unset($params['index_file']); - return $index_file; - } - - if (isset($index_file)) { - return $index_file; - } - - if (defined('INDEX_FILE')) { - return INDEX_FILE; - } - - $cut_prefix = trim(BASE_PATH, '/').'/'.trim($prefix, '/'); - return trim(preg_replace('/'.preg_quote($cut_prefix, '/').'(.*)/', '\\1', $_SERVER['PHP_SELF']), '/'); - } - - /** * Return href for template * * @access public * @param string $t Template path * @var string $prefix index.php prefix - could be blank, 'admin' */ - function HREF($t, $prefix = '', $params = null, $index_file = null) + public function HREF($t, $prefix = '', $params = null, $index_file = null) { - static $theme_id = null; + return $this->UrlManager->HREF($t, $prefix, $params, $index_file); + } - if (!isset($theme_id)) { - $theme_id = $this->GetVar('m_theme'); - } - - if (!$t) { - // when template not specified, use current - $t = $this->GetVar('t'); - } - - $t = preg_replace('/^Content\//i', '', $t); - - if (substr($t, -4) == '.tpl') { - // cut template extension (deprecated link format) - $t = substr($t, 0, strlen($t) - 4); - } - - if (substr($t, 0, 3) == 'id:') { - // link to structure page using it's id - $params['m_cat_id'] = substr($t, 3); - $t = $this->structureTemplateMapping[$t]; - } - - if (array_key_exists('use_section', $params)) { - $use_section = $params['use_section']; - unset($params['use_section']); - } - - if (isset($use_section) && $use_section && array_key_exists($t . ':' . $theme_id, $this->structureTemplateMapping)) { - // structure template corresponding to given physical template - $t = $this->structureTemplateMapping[$t . ':' . $theme_id]; - unset($params['use_section']); - } - - if (preg_match('/external:(.*)/', $t, $rets)) { - // external url - return $rets[1]; - } - - if ($this->isAdmin && $prefix == '') $prefix = ADMIN_DIRECTORY; - if ($this->isAdmin && $prefix == '_FRONT_END_') $prefix = ''; - - $index_file = $this->getIndexFile($prefix, $index_file, $params); - - if (isset($params['_auto_prefix_'])) { - unset($params['_auto_prefix_']); // this is parser-related param, do not need to pass it here - } - - $ssl = isset($params['__SSL__']) ? $params['__SSL__'] : null; - if ($ssl !== null) { - $session =& $this->recallObject('Session'); - /* @var $session Session */ - - $target_url = rtrim($this->BaseURL('', $ssl, false), '/'); - $cookie_url = trim($session->CookieDomain . $session->CookiePath, '/.'); - - // set session to GET_ONLY, to pass sid only if sid is REAL AND session is set - if (!preg_match('#' . preg_quote($cookie_url) . '#', $target_url) && $session->SessionSet) { - // when SSL<->NON-SSL redirect to different domain pass SID in url - $session->SetMode(Session::smGET_ONLY); - } - } - - if (isset($params['opener']) && $params['opener'] == 'u') { - $wid = $this->GetVar('m_wid'); - $stack_name = rtrim('opener_stack_'.$wid, '_'); - $opener_stack = $this->RecallVar($stack_name); - - if ($opener_stack && $opener_stack != serialize(Array())) { - $opener_stack = unserialize($opener_stack); - list($index_file, $env) = explode('|', $opener_stack[count($opener_stack) - 1]); - $ret = $this->BaseURL($prefix, $ssl).$index_file.'?'.ENV_VAR_NAME.'='.$env; - if ( getArrayValue($params,'escape') ) $ret = addslashes($ret); - - if (isset($params['m_opener']) && $params['m_opener'] == 'u') { - array_pop($opener_stack); - if (!$opener_stack) { - $this->RemoveVar($stack_name); - // remove popups last templates, because popup is closing now - $this->RemoveVar('last_template_'.$wid); - $this->RemoveVar('last_template_popup_'.$wid); - - // don't save popups last templates again :) - $this->SetVar('skip_last_template', 1); - } - else { - $this->StoreVar($stack_name, serialize($opener_stack)); - } - - /*// store window relations - $window_relations = $this->RecallVar('window_relations'); - $window_relations = $window_relations ? unserialize($window_relations) : Array (); - if (array_key_exists($wid, $window_relations)) { - unset($window_relations[$wid]); - $this->StoreVar('window_relations', serialize($window_relations)); - }*/ - } - return $ret; - } - else { - //define('DBG_REDIRECT', 1); - $t = $this->GetVar('t'); - } - } - - $pass = isset($params['pass']) ? $params['pass'] : ''; - - // pass events with url - $pass_events = false; - if( isset($params['pass_events']) ) - { - $pass_events = $params['pass_events']; - unset($params['pass_events']); - } - - $map_link = ''; - if( isset($params['anchor']) ) - { - $map_link = '#'.$params['anchor']; - unset($params['anchor']); - } - - if ( isset($params['no_amp']) ) - { - $params['__URLENCODE__'] = $params['no_amp']; - unset($params['no_amp']); - } - - $no_rewrite = false; - if( isset($params['__NO_REWRITE__']) ) - { - $no_rewrite = true; - unset($params['__NO_REWRITE__']); - } - - $force_rewrite = false; - if( isset($params['__MOD_REWRITE__']) ) - { - $force_rewrite = true; - unset($params['__MOD_REWRITE__']); - } - - $force_no_sid = false; - if( isset($params['__NO_SID__']) ) - { - $force_no_sid = true; - unset($params['__NO_SID__']); - } - - // append pass through variables to each link to be build - $params = array_merge($this->getPassThroughVariables($params), $params); - - if ($force_rewrite || ($this->RewriteURLs($ssl) && !$no_rewrite)) { - static $rewrite_listeners_done = false; - - if (!$rewrite_listeners_done) { - $mod_rewrite_helper =& $this->recallObject('ModRewriteHelper'); - /* @var $mod_rewrite_helper kModRewriteHelper */ - - $mod_rewrite_helper->initRewriteListeners(); - - $rewrite_listeners_done = true; - } - - $session =& $this->recallObject('Session'); - - if ($session->NeedQueryString() && !$force_no_sid) { - $params['sid'] = $this->GetSID(); - } - - $url = $this->BuildEnv_NEW($t, $params, $pass, $pass_events); - $ret = $this->BaseURL($prefix, $ssl).$url.$map_link; - } - else { - unset($params['pass_category']); // we don't need to pass it when mod_rewrite is off - $env = $this->BuildEnv($t, $params, $pass, $pass_events); - $ret = $this->BaseURL($prefix, $ssl).$index_file.'?'.$env.$map_link; - } - - return $ret; + function getPhysicalTemplate($template) + { + return $this->UrlManager->getPhysicalTemplate($template); } /** @@ -1739,359 +1405,12 @@ */ function getPassThroughVariables(&$params) { - static $cached_pass_through = null; - - if (isset($params['no_pass_through']) && $params['no_pass_through']) { - unset($params['no_pass_through']); - return Array(); - } - - // because pass through is not changed during script run, then we can cache it - if (is_null($cached_pass_through)) { - - $cached_pass_through = Array(); - $pass_through = $this->GetVar('pass_through'); - - if ($pass_through) { - // names of variables to pass to each link - $cached_pass_through['pass_through'] = $pass_through; - $pass_through = explode(',', $pass_through); - foreach ($pass_through as $pass_through_var) { - $cached_pass_through[$pass_through_var] = $this->GetVar($pass_through_var); - } - } - - } - - return $cached_pass_through; + return $this->UrlManager->getPassThroughVariables($params); } - - /** - * Returns sorted array of passed prefixes (to build url from) - * - * @param string $pass - * @return Array - */ - function getPassInfo($pass = 'all') - { - if (!$pass) $pass = 'all'; - $pass = trim( - preg_replace( - '/(?<=,|\\A)all(?=,|\\z)/', - trim($this->GetVar('passed'), ','), - trim($pass, ',') - ), - ','); - - if (!$pass) { - return Array(); - } - - $pass_info = array_unique( explode(',', $pass) ); // array( prefix[.special], prefix[.special] ... - - // we need to keep that sorting despite the sorting below, because this sorts prefixes with same priority by name - sort($pass_info, SORT_STRING); // to be prefix1,prefix1.special1,prefix1.special2,prefix3.specialX - - foreach ($pass_info as $prefix) { - list ($prefix_only, ) = explode('.', $prefix, 2); - $sorted[$prefix] = $this->getUnitOption($prefix_only, 'RewritePriority', 0); - } - - asort($sorted, SORT_NUMERIC); - $pass_info = array_keys($sorted); - - // ensure that "m" prefix is at the beginning - $main_index = array_search('m', $pass_info); - if ($main_index !== false) { - unset($pass_info[$main_index]); - array_unshift($pass_info, 'm'); - } - return $pass_info; - } - - function BuildEnv_NEW($t, $params, $pass='all', $pass_events = false) - { - if ($this->GetVar('admin') || (array_key_exists('admin', $params) && $params['admin'])) { - $params['admin'] = 1; - - if (!array_key_exists('editing_mode', $params)) { - $params['editing_mode'] = EDITING_MODE; - } - } - - $ret = ''; - $env = ''; - - $encode = false; - - if (isset($params['__URLENCODE__'])) { - $encode = $params['__URLENCODE__']; - unset($params['__URLENCODE__']); - } - - if (isset($params['__SSL__'])) { - unset($params['__SSL__']); - } - - $catalog_item_found = false; - $pass_info = $this->getPassInfo($pass); - - if ($pass_info) { - if ($pass_info[0] == 'm') { - array_shift($pass_info); - } - - $inject_parts = Array (); // url parts for beginning of url - $params['t'] = $t; // make template available for rewrite listeners - $params['pass_template'] = true; // by default we keep given template in resulting url - - if (!array_key_exists('pass_category', $params)) { - $params['pass_category'] = false; // by default we don't keep categories in url - } - - foreach ($pass_info as $pass_index => $pass_element) { - list ($prefix) = explode('.', $pass_element); - $catalog_item = $this->findModule('Var', $prefix) && $this->getUnitOption($prefix, 'CatalogItem'); - - if (array_key_exists($prefix, $this->RewriteListeners)) { - // if next prefix is same as current, but with special => exclude current prefix from url - $next_prefix = array_key_exists($pass_index + 1, $pass_info) ? $pass_info[$pass_index + 1] : false; - if ($next_prefix) { - $next_prefix = substr($next_prefix, 0, strlen($prefix) + 1); - if ($prefix . '.' == $next_prefix) { - continue; - } - } - - // rewrited url part - $url_part = $this->BuildModuleEnv_NEW($pass_element, $params, $pass_events); - - if (is_string($url_part) && $url_part) { - $ret .= $url_part . '/'; - - if ($catalog_item) { - // pass category later only for catalog items - $catalog_item_found = true; - } - } - elseif (is_array($url_part)) { - // rewrite listener want to insert something at the beginning of url too - if ($url_part[0]) { - $inject_parts[] = $url_part[0]; - } - - if ($url_part[1]) { - $ret .= $url_part[1] . '/'; - } - - if ($catalog_item) { - // pass category later only for catalog items - $catalog_item_found = true; - } - } elseif ($url_part === false) { - // rewrite listener decided not to rewrite given $pass_element - $env .= ':' . $this->BuildModuleEnv($pass_element, $params, $pass_events); - } - } - else { - $env .= ':' . $this->BuildModuleEnv($pass_element, $params, $pass_events); - } - } - - if ($catalog_item_found || preg_match('/c\.[-\d]*/', implode(',', $pass_info))) { - // "c" prefix is present -> keep category - $params['pass_category'] = true; - } - - $params['inject_parts'] = $inject_parts; - - $ret = $this->BuildModuleEnv_NEW('m', $params, $pass_events) . '/' . $ret; - $cat_processed = array_key_exists('category_processed', $params) && $params['category_processed']; - - // remove tempporary parameters used by listeners - unset($params['t'], $params['inject_parts'], $params['pass_template'], $params['pass_category'], $params['category_processed']); - - if (array_key_exists('url_ending', $params)) { - $ret = trim($ret, '/') . $params['url_ending']; - unset($params['url_ending']); - } - else { - $ret = trim($ret, '/') . MOD_REWRITE_URL_ENDING; - } - - if ($env) { - $params[ENV_VAR_NAME] = ltrim($env, ':'); - } - } - - unset($params['pass'], $params['opener'], $params['m_event']); - - if (array_key_exists('escape', $params) && $params['escape']) { - $ret = addslashes($ret); - unset($params['escape']); - } - - $ret = str_replace('%2F', '/', urlencode($ret)); - - $params_str = ''; - $join_string = $encode ? '&' : '&'; - - foreach ($params as $param => $value) { - $params_str .= $join_string . $param . '=' . $value; - } - - if ($params_str) { - $ret .= '?' . substr($params_str, strlen($join_string)); - } - - if ($encode) { - $ret = str_replace('\\', '%5C', $ret); - } - - return $ret; - } - - function BuildModuleEnv_NEW($prefix_special, &$params, $keep_events = false) - { - list ($prefix) = explode('.', $prefix_special); - - $url_parts = Array (); - $listener = $this->RewriteListeners[$prefix][0]; - - $ret = $listener[0]->$listener[1](REWRITE_MODE_BUILD, $prefix_special, $params, $url_parts, $keep_events); - - return $ret; - } - - /** - * Builds env part that corresponds prefix passed - * - * @param string $prefix_special item's prefix & [special] - * @param Array $params url params - * @param bool $pass_events - */ - function BuildModuleEnv($prefix_special, &$params, $pass_events = false) - { - list($prefix) = explode('.', $prefix_special); - $query_vars = $this->getUnitOption($prefix, 'QueryString'); - - //if pass events is off and event is not implicity passed - if( !$pass_events && !isset($params[$prefix_special.'_event']) ) { - $params[$prefix_special.'_event'] = ''; // remove event from url if requested - //otherwise it will use value from get_var - } - - if(!$query_vars) return ''; - - $tmp_string = Array(0 => $prefix_special); - foreach($query_vars as $index => $var_name) - { - //if value passed in params use it, otherwise use current from application - $var_name = $prefix_special.'_'.$var_name; - $tmp_string[$index] = isset( $params[$var_name] ) ? $params[$var_name] : $this->GetVar($var_name); - if ( isset($params[$var_name]) ) unset( $params[$var_name] ); - } - - $escaped = array(); - foreach ($tmp_string as $tmp_val) { - $escaped[] = str_replace(Array('-',':'), Array('\-','\:'), $tmp_val); - } - - $ret = implode('-', $escaped); - if ($this->getUnitOption($prefix, 'PortalStyleEnv') == true) - { - $ret = preg_replace('/^([a-zA-Z]+)-([0-9]+)-(.*)/','\\1\\2-\\3', $ret); - } - return $ret; - } - function BuildEnv($t, $params, $pass='all', $pass_events = false, $env_var = true) { - if ($this->GetVar('admin') || (array_key_exists('admin', $params) && $params['admin'])) { - $params['admin'] = 1; - - if (!array_key_exists('editing_mode', $params)) { - $params['editing_mode'] = EDITING_MODE; - } - } - - $session =& $this->recallObject('Session'); - $ssl = isset($params['__SSL__']) ? $params['__SSL__'] : 0; - $sid = $session->NeedQueryString() && !$this->RewriteURLs($ssl) ? $this->GetSID() : ''; -// if (getArrayValue($params,'admin') == 1) $sid = $this->GetSID(); - - $ret = ''; - if ($env_var) { - $ret = ENV_VAR_NAME.'='; - } - - $ret .= $sid . '-'; // SID-TEMPLATE - - $encode = false; - if (isset($params['__URLENCODE__'])) { - $encode = $params['__URLENCODE__']; - unset($params['__URLENCODE__']); - } - - if (isset($params['__SSL__'])) { - unset($params['__SSL__']); - } - - $env_string = ''; - $category_id = isset($params['m_cat_id']) ? $params['m_cat_id'] : $this->GetVar('m_cat_id'); - - $item_id = false; - $pass_info = $this->getPassInfo($pass); - if ($pass_info) { - if ($pass_info[0] == 'm') array_shift($pass_info); - foreach ($pass_info as $pass_element) { - list($prefix) = explode('.', $pass_element); - $require_rewrite = $this->findModule('Var', $prefix); - if ($require_rewrite) { - $item_id = isset($params[$pass_element.'_id']) ? $params[$pass_element.'_id'] : $this->GetVar($pass_element.'_id'); - } - $env_string .= ':'.$this->BuildModuleEnv($pass_element, $params, $pass_events); - } - } - - if (strtolower($t) == '__default__') { - if (is_numeric($item_id)) { - $mod_rw_helper =& $this->recallObject('ModRewriteHelper'); - /* @var $mod_rw_helper kModRewriteHelper */ - - $t = $mod_rw_helper->GetItemTemplate($category_id, $pass_element); // $pass_element should be the last processed element - // $t = $this->getCategoryCache($category_id, 'item_templates'); - } - elseif ($category_id) { - $t = strtolower(preg_replace('/^Content\//i', '', $this->getCategoryCache($category_id, 'filenames') )); - } - else { - $t = 'index'; - } - } - - $ret .= $t.':'.$this->BuildModuleEnv('m', $params, $pass_events).$env_string; - - unset($params['pass'], $params['opener'], $params['m_event']); - - if (array_key_exists('escape', $params) && $params['escape']) { - $ret = addslashes($ret); - unset($params['escape']); - } - - $join_string = $encode ? '&' : '&'; - $params_str = ''; - foreach ($params as $param => $value) - { - $params_str .= $join_string.$param.'='.$value; - } - $ret .= $params_str; - - if ($encode) { - $ret = str_replace('\\', '%5C', $ret); - } - return $ret; + return $this->UrlManager->BuildEnv($t, $params, $pass, $pass_events, $env_var); } function BaseURL($prefix = '', $ssl = null, $add_port = true) @@ -2283,125 +1602,17 @@ $this->Session->LoadPersistentVars(); } - function LoadCache() - { - // TODO: maybe language part isn't required, since same phrase from different languages have one ID now - $cache_key = $this->GetVar('t') . $this->GetVar('m_theme') . $this->GetVar('m_lang') . $this->isAdmin; - - $sql = 'SELECT PhraseList, ConfigVariables - FROM ' . TABLE_PREFIX . 'PhraseCache - WHERE Template = ' . $this->Conn->qstr( md5($cache_key) ); - $res = $this->Conn->GetRow($sql); - - if ($res) { - $this->Caches['PhraseList'] = $res['PhraseList'] ? explode(',', $res['PhraseList']) : Array (); - $config_ids = $res['ConfigVariables'] ? explode(',', $res['ConfigVariables']) : Array (); - - if (isset($this->Caches['ConfigVariables'])) { - $config_ids = array_diff($config_ids, $this->Caches['ConfigVariables']); - } - } - else { - $config_ids = Array (); - } - - $this->Phrases->Init('phrases'); - $this->Caches['ConfigVariables'] = $config_ids; - $this->ConfigCacheIds = $config_ids; - } - /** - * Loads template mapping for Front-End - * - */ - function LoadStructureTemplateMapping() - { - if (!$this->isAdmin) { - $category_helper =& $this->recallObject('CategoryHelper'); - /* @var $category_helper CategoryHelper */ - - $this->structureTemplateMapping = $category_helper->getTemplateMapping(); - } - } - - function UpdateCache() - { - $update = false; - //something changed - $update = $update || $this->Phrases->NeedsCacheUpdate(); - $update = $update || (count($this->ConfigCacheIds) && $this->ConfigCacheIds != $this->Caches['ConfigVariables']); - - if ($update) { - $cache_key = $this->GetVar('t').$this->GetVar('m_theme').$this->GetVar('m_lang').$this->isAdmin; - $query = sprintf("REPLACE %s (PhraseList, CacheDate, Template, ConfigVariables) - VALUES (%s, %s, %s, %s)", - TABLE_PREFIX.'PhraseCache', - $this->Conn->qstr(join(',', $this->Phrases->Ids)), - adodb_mktime(), - $this->Conn->qstr(md5($cache_key)), - $this->Conn->qstr(implode(',', array_unique($this->ConfigCacheIds)))); - $this->Conn->Query($query); - } - } - - function InitConfig() - { - if (isset($this->Caches['ConfigVariables']) && count($this->Caches['ConfigVariables']) > 0) { - $sql = 'SELECT VariableValue, VariableName - FROM ' . TABLE_PREFIX . 'ConfigurationValues - WHERE VariableId IN (' . implode(',', $this->Caches['ConfigVariables']) . ')'; - $this->ConfigHash = array_merge($this->ConfigHash, $this->Conn->GetCol($sql, 'VariableName')); - } - } - - /** * Returns configuration option value by name * * @param string $name * @return string */ function ConfigValue($name) { - if ($name == 'Smtp_AdminMailFrom') { - $res = $this->siteDomainField('AdminEmail'); - - if ($res) { - return $res; - } - } - - $res = array_key_exists($name, $this->ConfigHash) ? $this->ConfigHash[$name] : false; - if ($res !== false) { - return $res; - } - - if (defined('IS_INSTALL') && IS_INSTALL && !$this->TableFound('ConfigurationValues')) { - return false; - } - - $this->Conn->nextQueryCachable = true; - $sql = 'SELECT VariableId, VariableValue - FROM '.TABLE_PREFIX.'ConfigurationValues - WHERE VariableName = '.$this->Conn->qstr($name); - $res = $this->Conn->GetRow($sql); - - if ($res !== false) { - $this->ConfigHash[$name] = $res['VariableValue']; - $this->ConfigCacheIds[] = $res['VariableId']; - - return $res['VariableValue']; - } - - return false; + return $this->cacheManager->ConfigValue($name); } - function UpdateConfigCache() - { - if ($this->ConfigCacheIds) { - - } - } - /** * Allows to process any type of event * @@ -2498,7 +1709,7 @@ * @param Array $arguments * @return kBase */ - function &recallObject($name, $pseudo_class = null, $event_params = Array(), $arguments = Array ()) + public function &recallObject($name, $pseudo_class = null, $event_params = Array(), $arguments = Array ()) { $result =& $this->Factory->getObject($name, $pseudo_class, $event_params, $arguments); @@ -2537,7 +1748,7 @@ * @param string $name Object's name in the Storage * @author Kostja */ - function removeObject($name) + public function removeObject($name) { $this->Factory->DestroyObject($name); } @@ -2550,7 +1761,7 @@ * @return kBase * @access public */ - function &makeClass($pseudo_class, $arguments = Array ()) + public function &makeClass($pseudo_class, $arguments = Array ()) { $result =& $this->Factory->makeClass($pseudo_class, $arguments); @@ -2565,7 +1776,7 @@ * @author Alex * @access public */ - function isDebugMode($check_debugger = true) + public function isDebugMode($check_debugger = true) { $debug_mode = defined('DEBUG_MODE') && DEBUG_MODE; if ($check_debugger) { @@ -2608,13 +1819,9 @@ * @param mixed $default * @return string * @access public - * @author Alex */ - function getUnitOption($prefix, $option, $default = false) + public function getUnitOption($prefix, $option, $default = false) { - /*if (!isset($this->UnitConfigReader)) { - $this->UnitConfigReader =& $this->recallObject('kUnitConfigReader'); - }*/ return $this->UnitConfigReader->getUnitOption($prefix, $option, $default); } @@ -2624,12 +1831,10 @@ * @param string $prefix * @param string $name * @param string $value - * @author Alex * @access public */ - function setUnitOption($prefix, $option, $value) + public function setUnitOption($prefix, $option, $value) { -// $unit_config_reader =& $this->recallObject('kUnitConfigReader'); return $this->UnitConfigReader->setUnitOption($prefix,$option,$value); } @@ -2639,11 +1844,9 @@ * @param string $prefix * @return Array * @access public - * @author Alex */ - function getUnitOptions($prefix) + public function getUnitOptions($prefix) { -// $unit_config_reader =& $this->recallObject('kUnitConfigReader'); return $this->UnitConfigReader->getUnitOptions($prefix); } @@ -2653,11 +1856,8 @@ * @param string $prefix * @return bool */ - function prefixRegistred($prefix) + public function prefixRegistred($prefix) { - /*if (!isset($this->UnitConfigReader)) { - $this->UnitConfigReader =& $this->recallObject('kUnitConfigReader'); - }*/ return $this->UnitConfigReader->prefixRegistred($prefix); } @@ -2668,9 +1868,8 @@ * @param string $prefix_special * @return Array * @access public - * @author Alex */ - function processPrefix($prefix_special) + public function processPrefix($prefix_special) { return $this->Factory->processPrefix($prefix_special); } @@ -2688,7 +1887,6 @@ $this->EventManager->setEvent($prefix_special,$event_name); } - /** * SQL Error Handler * @@ -2976,6 +2174,8 @@ function CheckPermission($name, $type = 1, $cat_id = null) { $perm_helper =& $this->recallObject('PermissionsHelper'); + /* @var $perm_helper kPermissionsHelper */ + return $perm_helper->CheckPermission($name, $type, $cat_id); } @@ -3020,7 +2220,6 @@ function isModuleEnabled($module_name) { return $this->findModule('Name', $module_name) !== false; - } /** @@ -3288,6 +2487,11 @@ return $this->ModuleInfo['Core']['RootCat']; } + function DeleteUnitCache($include_sections = false) + { + $this->cacheManager->DeleteUnitCache($include_sections); + } + /** * Sets data from cache to object * @@ -3296,14 +2500,8 @@ */ public function setFromCache(&$data) { - $this->ConfigHash = $data['Application.ConfigHash']; - - $this->Caches['ConfigVariables'] = $data['Application.ConfigCacheIds']; // undefined attribute - $this->ConfigCacheIds = $data['Application.ConfigCacheIds']; - $this->ReplacementTemplates = $data['Application.ReplacementTemplates']; $this->RewriteListeners = $data['Application.RewriteListeners']; - $this->ModuleInfo = $data['Application.ModuleInfo']; } @@ -3316,17 +2514,10 @@ */ public function getToCache() { - return Array ( - 'Application.ConfigHash' => $this->ConfigHash, - - 'Application.Caches.ConfigVariables' => $this->Caches['ConfigVariables'], // undefined attribute - 'Application.ConfigCacheIds' => $this->ConfigCacheIds, - - 'Application.ReplacementTemplates' => $this->ReplacementTemplates, - 'Application.RewriteListeners' => $this->RewriteListeners, - - 'Application.ModuleInfo' => $this->ModuleInfo, - ); + return Array ( + 'Application.ReplacementTemplates' => $this->ReplacementTemplates, + 'Application.RewriteListeners' => $this->RewriteListeners, + 'Application.ModuleInfo' => $this->ModuleInfo, + ); } - } \ No newline at end of file Index: branches/5.2.x/core/kernel/globals.php =================================================================== diff -u -N -r14095 -r14184 --- branches/5.2.x/core/kernel/globals.php (.../globals.php) (revision 14095) +++ branches/5.2.x/core/kernel/globals.php (.../globals.php) (revision 14184) @@ -1,6 +1,6 @@ Application->SetVar('m_lang', $params['language_id']); - $this->Application->Phrases->Init(''); - - $this->Application->Phrases->LanguageId = $params['language_id']; - $this->Application->Phrases->LoadPhrases( $this->Application->Caches['PhraseList'] ); + $this->Application->Phrases->Init('phrases', '', $params['language_id']); } /** Index: branches/5.2.x/core/units/admin/admin_config.php =================================================================== diff -u -N -r14092 -r14184 --- branches/5.2.x/core/units/admin/admin_config.php (.../admin_config.php) (revision 14092) +++ branches/5.2.x/core/units/admin/admin_config.php (.../admin_config.php) (revision 14184) @@ -1,6 +1,6 @@ Array ( 'parent' => null, 'icon' => 'site', - 'label' => $this->Application->ConfigValue('Site_Name'), + 'label' => 'SITE_NAME', 'url' => Array ('t' => 'index', 'pass' => 'm', 'pass_section' => true, 'no_amp' => 1), 'permissions' => Array (), 'priority' => 0, Index: branches/5.2.x/core/units/admin/admin_events_handler.php =================================================================== diff -u -N -r14095 -r14184 --- branches/5.2.x/core/units/admin/admin_events_handler.php (.../admin_events_handler.php) (revision 14095) +++ branches/5.2.x/core/units/admin/admin_events_handler.php (.../admin_events_handler.php) (revision 14184) @@ -1,6 +1,6 @@ status = erSTOP; } - $this->Application->UnitConfigReader->ResetParsedData(); + $this->Application->DeleteUnitCache(); if ( $this->Application->GetVar('validate_configs') ) { $event->SetRedirectParam('validate_configs', 1); @@ -159,9 +159,7 @@ $event->status = kEvent::erSTOP; } - if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { - $this->Application->memoryCache->reset(); - } + $this->Application->resetCache(); } function OnCompileTemplates(&$event) @@ -1213,16 +1211,21 @@ { parent::OnAfterConfigRead($event); + $section_ajustments = $this->Application->getUnitOption($event->Prefix, 'SectionAdjustments'); + if (!$this->Application->ConfigValue('AdvancedUserManagement')) { - $section_ajustments = $this->Application->getUnitOption($event->Prefix, 'SectionAdjustments'); if (!$section_ajustments) { $section_ajustments = Array (); } $section_ajustments['in-portal:user_groups'] = 'remove'; - - $this->Application->setUnitOption($event->Prefix, 'SectionAdjustments', $section_ajustments); } + + $section_ajustments['in-portal:root'] = Array ( + 'label' => $this->Application->ConfigValue('Site_Name') + ); + + $this->Application->setUnitOption($event->Prefix, 'SectionAdjustments', $section_ajustments); } /** @@ -1244,7 +1247,7 @@ $this->Conn->Query($sql); if ($this->Conn->getAffectedRows()) { - $this->Application->UnitConfigReader->ResetParsedData(false); + $this->Application->DeleteUnitCache(false); } } Index: branches/5.2.x/core/units/configuration/configuration_event_handler.php =================================================================== diff -u -N -r14095 -r14184 --- branches/5.2.x/core/units/configuration/configuration_event_handler.php (.../configuration_event_handler.php) (revision 14095) +++ branches/5.2.x/core/units/configuration/configuration_event_handler.php (.../configuration_event_handler.php) (revision 14184) @@ -1,6 +1,6 @@ SetRedirectParam('refresh_tree', 1); } - $this->Application->UnitConfigReader->ResetParsedData($refresh_sections ? true : false); + $this->Application->DeleteUnitCache($refresh_sections ? true : false); } elseif ($this->Application->GetVar('errors_' . $event->getPrefixSpecial())) { // because we have list out there, and this is item