Index: branches/5.2.x/core/units/categories/categories_event_handler.php =================================================================== diff -u -N -r14664 -r14714 --- branches/5.2.x/core/units/categories/categories_event_handler.php (.../categories_event_handler.php) (revision 14664) +++ branches/5.2.x/core/units/categories/categories_event_handler.php (.../categories_event_handler.php) (revision 14714) @@ -1,6 +1,6 @@ setEventParam('constrain_info', Array ($constrain, '')); } + + /** + * Parses category part of url, build main part of url + * + * @param int $rewrite_mode Mode in what rewrite listener was called. Possbile two modes: REWRITE_MODE_BUILD, REWRITE_MODE_PARSE. + * @param string $prefix Prefix, that listener uses for system integration + * @param Array $params Params, that are used for url building or created during url parsing. + * @param Array $url_parts Url parts to parse (only for parsing). + * @param bool $keep_events Keep event names in resulting url (only for building). + * @return bool|string|Array Return true to continue to next listener; return false (when building) not to rewrite given prefix; return false (when parsing) to stop processing at this listener. + */ + public function CategoryRewriteListener($rewrite_mode = REWRITE_MODE_BUILD, $prefix, &$params, &$url_parts, $keep_events = false) + { + if ($rewrite_mode == REWRITE_MODE_BUILD) { + return $this->_buildMainUrl($prefix, $params, $keep_events); + } + + if ( $this->_parseFriendlyUrl($url_parts, $params) ) { + // friendly urls work like exact match only! + return false; + } + + $this->_parseCategory($url_parts, $params); + + return true; + } + + /** + * Build main part of every url + * + * @param string $prefix_special + * @param Array $params + * @param bool $keep_events + * @return string + */ + protected function _buildMainUrl($prefix_special, &$params, $keep_events) + { + $ret = ''; + list ($prefix) = explode('.', $prefix_special); + + $rewrite_processor =& $this->Application->recallObject('kRewriteUrlProcessor'); + /* @var $rewrite_processor kRewriteUrlProcessor */ + + $processed_params = $rewrite_processor->getProcessedParams($prefix_special, $params, $keep_events); + if ($processed_params === false) { + return ''; + } + + // add language + if ($processed_params['m_lang'] && ($processed_params['m_lang'] != $rewrite_processor->primaryLanguageId)) { + $language_name = $this->Application->getCache('language_names[%LangIDSerial:' . $processed_params['m_lang'] . '%]'); + if ($language_name === false) { + $sql = 'SELECT PackName + FROM ' . TABLE_PREFIX . 'Language + WHERE LanguageId = ' . $processed_params['m_lang']; + $language_name = $this->Conn->GetOne($sql); + + $this->Application->setCache('language_names[%LangIDSerial:' . $processed_params['m_lang'] . '%]', $language_name); + } + + $ret .= $language_name . '/'; + } + + // add theme + if ($processed_params['m_theme'] && ($processed_params['m_theme'] != $rewrite_processor->primaryThemeId)) { + $theme_name = $this->Application->getCache('theme_names[%ThemeIDSerial:' . $processed_params['m_theme'] . '%]'); + if ($theme_name === false) { + $sql = 'SELECT Name + FROM ' . TABLE_PREFIX . 'Theme + WHERE ThemeId = ' . $processed_params['m_theme']; + $theme_name = $this->Conn->GetOne($sql); + + $this->Application->setCache('theme_names[%ThemeIDSerial:' . $processed_params['m_theme'] . '%]', $theme_name); + + } + + $ret .= $theme_name . '/'; + } + + // inject custom url parts made by other rewrite listeners just after language/theme url parts + if ($params['inject_parts']) { + $ret .= implode('/', $params['inject_parts']) . '/'; + } + + // add category + if ($processed_params['m_cat_id'] > 0 && $params['pass_category']) { + $category_filename = $this->Application->getCategoryCache($processed_params['m_cat_id'], 'filenames'); + + preg_match('/^Content\/(.*)/i', $category_filename, $regs); + + if ($regs) { + $template = array_key_exists('t', $params) ? $params['t'] : false; + + if (strtolower($regs[1]) == strtolower($template)) { + // we could have category path like "Content/" in this case remove template + $params['pass_template'] = false; + } + + $ret .= $regs[1] . '/'; + } + + $params['category_processed'] = true; + } + + // reset category page + $force_page_adding = false; + if (array_key_exists('reset', $params) && $params['reset']) { + unset($params['reset']); + + if ($processed_params['m_cat_id']) { + $processed_params['m_cat_page'] = 1; + $force_page_adding = true; + } + } + + if ((array_key_exists('category_processed', $params) && $params['category_processed'] && ($processed_params['m_cat_page'] > 1)) || $force_page_adding) { + // category name was added before AND category page number found + $ret = rtrim($ret, '/') . '_' . $processed_params['m_cat_page'] . '/'; + } + + $template = array_key_exists('t', $params) ? $params['t'] : false; + $category_template = ($processed_params['m_cat_id'] > 0) && $params['pass_category'] ? $this->Application->getCategoryCache($processed_params['m_cat_id'], 'category_designs') : ''; + + if ((strtolower($template) == '__default__') && ($processed_params['m_cat_id'] == 0)) { + // for "Home" category set template to index when not set + $template = 'index'; + } + + // remove template from url if it is category index cached template OR site homepage + if (($template == $category_template) || (mb_strtolower($template) == '__default__') || ($template == 'index')) { + // given template is also default template for this category OR '__default__' given OR site homepage + $params['pass_template'] = false; + } + + if ($template && $params['pass_template']) { + $ret .= $template . '/'; + } + + return mb_strtolower( rtrim($ret, '/') ); + } + + /** + * Checks if whole url_parts matches a whole In-CMS page + * + * @param Array $url_parts + * @param Array $vars + * @return bool + */ + protected function _parseFriendlyUrl($url_parts, &$vars) + { + if (!$url_parts) { + return false; + } + + $sql = 'SELECT CategoryId, NamedParentPath + FROM ' . TABLE_PREFIX . 'Category + WHERE FriendlyURL = ' . $this->Conn->qstr(implode('/', $url_parts)); + $friendly = $this->Conn->GetRow($sql); + + $rewrite_processor =& $this->Application->recallObject('kRewriteUrlProcessor'); + /* @var $rewrite_processor kRewriteUrlProcessor */ + + if ($friendly) { + $vars['m_cat_id'] = $friendly['CategoryId']; + $vars['t'] = preg_replace('/^Content\//i', '', $friendly['NamedParentPath']); + + while ($url_parts) { + $rewrite_processor->partParsed( array_shift($url_parts) ); + } + + return true; + } + + return false; + } + + /** + * Extracts category part from url + * + * @param Array $url_parts + * @param Array $vars + * @return bool + */ + protected function _parseCategory($url_parts, &$vars) + { + if (!$url_parts) { + return false; + } + + $res = false; + $url_part = array_shift($url_parts); + + $category_id = 0; + $last_category_info = false; + $category_path = $url_part == 'content' ? '' : 'content'; + + $rewrite_processor =& $this->Application->recallObject('kRewriteUrlProcessor'); + /* @var $rewrite_processor kRewriteUrlProcessor */ + + do { + $category_path = trim($category_path . '/' . $url_part, '/'); + // bb_ -> forums/bb_2 + if ( !preg_match('/^bb_[\d]+$/', $url_part) && preg_match('/(.*)_([\d]+)$/', $category_path, $rets) ) { + $category_path = $rets[1]; + $vars['m_cat_page'] = $rets[2]; + } + + $sql = 'SELECT CategoryId, SymLinkCategoryId, NamedParentPath + FROM ' . TABLE_PREFIX . 'Category + WHERE (LOWER(NamedParentPath) = ' . $this->Conn->qstr($category_path) . ') AND (ThemeId = ' . $vars['m_theme'] . ' OR ThemeId = 0)'; + $category_info = $this->Conn->GetRow($sql); + + if ($category_info !== false) { + $last_category_info = $category_info; + $rewrite_processor->partParsed($url_part); + + $url_part = array_shift($url_parts); + $res = true; + } + } while ($category_info !== false && $url_part); + + if ($last_category_info) { + // this category is symlink to other category, so use it's url instead + // (used in case if url prior to symlink adding was indexed by spider or was bookmarked) + if ($last_category_info['SymLinkCategoryId']) { + $sql = 'SELECT CategoryId, NamedParentPath + FROM ' . TABLE_PREFIX . 'Category + WHERE (CategoryId = ' . $last_category_info['SymLinkCategoryId'] . ')'; + $category_info = $this->Conn->GetRow($sql); + + if ($category_info) { + // web symlinked category was found use it + // TODO: maybe 302 redirect should be made to symlinked category url (all other url parts should stay) + $last_category_info = $category_info; + } + } + + // 1. Set virtual page as template, this will be replaced to physical template later in kApplication::Run. + // 2. Don't set CachedTemplate field as template here, because we will loose original page associated with it's cms blocks! + $vars['t'] = mb_strtolower( preg_replace('/^Content\//i', '', $last_category_info['NamedParentPath']), 'UTF-8' ); + + $vars['m_cat_id'] = $last_category_info['CategoryId']; + $vars['is_virtual'] = true; // for template from POST, strange code there! + } + else { + $vars['m_cat_id'] = 0; + } + + return $res; + } } \ No newline at end of file