extractBuildParams(); if ( $build_params === false ) { return ''; } $this->keepEvent(); list ($prefix) = explode('.', $this->buildPrefix); if ( !array_key_exists($prefix, $default_per_page) ) { /** @var ListHelper $list_helper */ $list_helper = $this->Application->recallObject('ListHelper'); $default_per_page[$prefix] = $list_helper->getDefaultPerPage($prefix); } if ( $build_params[$this->buildPrefix . '_id'] ) { $category_id = $this->getBuildParam('m_cat_id'); // If template is also item template of category, then remove template. $template = $this->getBuildParam('t', false); $item_template = $this->getUrlProcessor()->GetItemTemplate($category_id, $prefix); if ( $template == $item_template || strtolower($template) == '__default__' ) { // Given template is also default template for this category item or '__default__' given. $this->setBuildParam('pass_template', false); } // Get item's filename. if ( $prefix == 'bb' ) { $ret .= 'bb_' . $build_params[$this->buildPrefix . '_id'] . '/'; } else { $filename = $this->getFilename($prefix, $build_params[$this->buildPrefix . '_id'], $category_id); if ( $filename !== false ) { $ret .= $filename . '/'; } } } else { if ( $build_params[$this->buildPrefix . '_Page'] == 1 ) { // When printing category items and we are on the 1st page -> there is no information about // category item prefix and $params['pass_category'] will not be added automatically. $this->setBuildParam('pass_category', true); } elseif ( $build_params[$this->buildPrefix . '_Page'] > 1 ) { $this->setBuildParam('page', $build_params[$this->buildPrefix . '_Page']); } $per_page = $build_params[$this->buildPrefix . '_PerPage']; if ( $per_page && ($per_page != $default_per_page[$prefix]) ) { $this->setBuildParam('per_page', $build_params[$this->buildPrefix . '_PerPage']); } } return mb_strtolower(rtrim($ret, '/')); } /** * Parses url part. * * @param array $url_parts Url parts to parse. * @param array $params Parameters, that are used for url building or created during url parsing. * * @return boolean Return true to continue to next router; return false to stop processing at this router. */ public function parse(array &$url_parts, array &$params) { $module_prefix = $this->parseCategoryItemUrl($url_parts, $params); if ( $module_prefix !== false ) { $params['pass'][] = $module_prefix; $this->getUrlProcessor()->setModulePrefix($module_prefix); } return true; } /** * Returns item's filename that corresponds id passed. If possible, then get it from cache. * * @param string $prefix Prefix. * @param integer $id Id. * @param integer $category_id Category Id. * * @return string */ protected function getFilename($prefix, $id, $category_id = null) { $category_id = isset($category_id) ? $category_id : $this->Application->GetVar('m_cat_id'); $serial_name = $this->Application->incrementCacheSerial($prefix, $id, false); $cache_key = 'filenames[%' . $serial_name . '%]:' . (int)$category_id; $filename = $this->Application->getCache($cache_key); if ( $filename === false ) { $this->Conn->nextQueryCachable = true; $config = $this->Application->getUnitConfig($prefix); $sql = 'SELECT ResourceId FROM ' . $config->getTableName() . ' WHERE ' . $config->getIDField() . ' = ' . $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 Url parts. * @param array $params Params. * * @return boolean|string */ protected function parseCategoryItemUrl(array &$url_parts, array &$params) { if ( !$url_parts ) { return false; } $item_filename = end($url_parts); if ( is_numeric($item_filename) ) { // This page, don't process here. return false; } if ( $this->buildPrefix == 'bb' && preg_match('/^bb_([\d]+)/', $item_filename, $regs) ) { // Process topics separately, because they don't use item filenames. array_pop($url_parts); $this->partParsed($item_filename, 'rtl'); return $this->parseTopicUrl($regs[1], $params); } $cat_item = $this->findCategoryItem((int)$params['m_cat_id'], $item_filename); if ( $cat_item !== false ) { // Item found. $module_prefix = $cat_item['ItemPrefix']; $item_template = $this->getUrlProcessor()->GetItemTemplate($cat_item, $module_prefix, $params['m_theme']); // Converting ResourceId to corresponding Item id. $module_config = $this->Application->getUnitConfig($module_prefix); $sql = 'SELECT ' . $module_config->getIDField() . ' FROM ' . $module_config->getTableName() . ' WHERE ResourceId = ' . $cat_item['ItemResourceId']; $item_id = $this->Conn->GetOne($sql); if ( $item_id ) { array_pop($url_parts); $this->partParsed($item_filename, 'rtl'); if ( $item_template ) { // When template is found in category -> set it. $params['t'] = $item_template; } // We have category item id. $params[$module_prefix . '_id'] = $item_id; return $module_prefix; } } return false; } /** * Set's template and topic id corresponding to topic given in url * * @param integer $topic_id Topic ID. * @param array $params Params. * * @return string */ protected function parseTopicUrl($topic_id, array &$params) { $sql = 'SELECT c.ParentPath, c.CategoryId FROM ' . TABLE_PREFIX . 'Categories AS c WHERE c.CategoryId = ' . (int)$params['m_cat_id']; $cat_item = $this->Conn->GetRow($sql); $item_template = $this->getUrlProcessor()->GetItemTemplate($cat_item, 'bb', $params['m_theme']); if ( $item_template ) { $params['t'] = $item_template; } $params['bb_id'] = $topic_id; return 'bb'; } /** * Locating the item in CategoryItems by filename to detect its ItemPrefix and its category ParentPath. * * @param integer $category_id Category. * @param string $filename Filename. * * @return string */ protected function findCategoryItem($category_id, $filename) { static $cache = array(); $cache_key = $category_id . ':' . $filename; if ( !isset($cache[$cache_key]) ) { $sql = 'SELECT ci.ItemResourceId, ci.ItemPrefix, c.ParentPath, ci.CategoryId FROM ' . TABLE_PREFIX . 'CategoryItems AS ci LEFT JOIN ' . TABLE_PREFIX . 'Categories AS c ON c.CategoryId = ci.CategoryId WHERE (ci.CategoryId = ' . $category_id . ') AND (ci.Filename = ' . $this->Conn->qstr($filename) . ')'; $cache[$cache_key] = $this->Conn->GetRow($sql); } $category_item = $cache[$cache_key]; return $category_item && $category_item['ItemPrefix'] == $this->buildPrefix ? $category_item : false; } }