Index: branches/5.0.x/core/kernel/db/cat_tag_processor.php =================================================================== --- branches/5.0.x/core/kernel/db/cat_tag_processor.php (revision 12970) +++ branches/5.0.x/core/kernel/db/cat_tag_processor.php (revision 12971) @@ -1,822 +1,833 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.org/license for copyright notices and details. */ defined('FULL_PATH') or die('restricted access!'); class kCatDBTagProcessor extends kDBTagProcessor { /** * Permission Helper * * @var kPermissionsHelper */ var $PermHelper = null; function kCatDBTagProcessor() { parent::kDBTagProcessor(); $this->PermHelper = $this->Application->recallObject('PermissionsHelper'); } function ItemIcon($params) { $grids = $this->Application->getUnitOption($this->Prefix, 'Grids'); $grid = $grids[ $params['grid'] ]; if (!array_key_exists('Icons', $grid)) { return ''; } $icons = $grid['Icons']; if (array_key_exists('name', $params)) { $icon_name = $params['name']; return array_key_exists($icon_name, $icons) ? $icons[$icon_name] : ''; } $status_fields = $this->Application->getUnitOption($this->Prefix, 'StatusField'); if (!$status_fields) { return $icons['default']; } $object =& $this->getObject($params); /* @var $object kDBList */ $value = $object->GetDBField($status_fields[0]); // sets base status icon if ($value == STATUS_ACTIVE) { // if( $object->HasField('IsPop') && $object->GetDBField('IsPop') ) $value = 'POP'; // if( $object->HasField('IsHot') && $object->GetDBField('IsHot') ) $value = 'HOT'; if( $object->HasField('IsNew') && $object->GetDBField('IsNew') ) $value = 'NEW'; // if( $object->HasField('EditorsPick') && $object->GetDBField('EditorsPick') ) $value = 'PICK'; } return array_key_exists($value, $icons) ? $icons[$value] : $icons['default']; } /** * Allows to create valid mod-rewrite compatible link to module item * * @param Array $params * @param string $id_prefix * @return string */ function ItemLink($params, $id_prefix = null) { if (!isset($params['pass'])) { $params['pass'] = 'm,'.$this->Prefix; } $item_id = isset($params[$id_prefix.'_id']) && $params[$id_prefix.'_id']; if (!$item_id) { $item_id = $this->Application->GetVar($this->getPrefixSpecial().'_id'); if (!$item_id) { $item_id = $this->Application->GetVar($this->Prefix.'_id'); } } $params[$this->Prefix.'_id'] = $item_id; $object =& $this->getObject($params); $params['m_cat_id'] = $object->GetDBField('CategoryId'); $params['m_cat_page'] = 1; $params['pass_category'] = 1; return $this->Application->ProcessParsedTag('m', 't', $params); } /** * Builds link for browsing current item on Front-End * * @param Array $params * @return string */ function PageBrowseLink($params) { $themes_helper =& $this->Application->recallObject('ThemesHelper'); /* @var $themes_helper kThemesHelper */ + $site_config_helper =& $this->Application->recallObject('SiteConfigHelper'); + /* @var $site_config_helper SiteConfigHelper */ + + $settings = $site_config_helper->getSettings(); + + $params['editing_mode'] = $settings['default_editing_mode']; $params['m_theme'] = $themes_helper->getCurrentThemeId(); - $params['index_file'] = '../index.php'; + $params['index_file'] = 'index.php'; + $params['prefix'] = '_FRONT_END_'; $params['admin'] = 1; + if ($this->Application->ConfigValue('UseModRewrite')) { + $params['__MOD_REWRITE__'] = 1; + } + return $this->ItemLink($params); } function CategoryPath($params) { if ($this->Application->isAdminUser) { // path for module root category in admin if (!isset($params['cat_id'])) { $params['cat_id'] = $this->Application->RecallVar($params['session_var'], 0); } } else { // path for category item category in front-end $object =& $this->getObject($params); $params['cat_id'] = $object->GetDBField('CategoryId'); } return $this->Application->ProcessParsedTag('c', 'CategoryPath', $params); } function BuildListSpecial($params) { if ($this->Special != '') return $this->Special; if ( isset($params['parent_cat_id']) ) { $parent_cat_id = $params['parent_cat_id']; } else { $parent_cat_id = $this->Application->GetVar('c_id'); if (!$parent_cat_id) { $parent_cat_id = $this->Application->GetVar('m_cat_id'); } } $recursive = isset($params['recursive']); $list_unique_key = $this->getUniqueListKey($params).$recursive; if ($list_unique_key == '') { return parent::BuildListSpecial($params); } return crc32($parent_cat_id.$list_unique_key); } function CatalogItemCount($params) { $params['skip_quering'] = true; $object =& $this->GetList($params); if (!$object->Counted) { $object->CountRecs(); } return $object->NoFilterCount != $object->RecordsCount ? $object->RecordsCount.' / '.$object->NoFilterCount : $object->RecordsCount; } function ListReviews($params) { $prefix = $this->Prefix.'-rev'; $review_tag_processor =& $this->Application->recallObject($prefix.'.item_TagProcessor'); return $review_tag_processor->PrintList($params); } function ReviewCount($params) { $review_tag_processor =& $this->Application->recallObject('rev.item_TagProcessor'); return $review_tag_processor->TotalRecords($params); } function InitCatalogTab($params) { $tab_params['mode'] = $this->Application->GetVar('tm'); // single/multi selection possible $tab_params['special'] = $this->Application->GetVar('ts'); // use special for this tab $tab_params['dependant'] = $this->Application->GetVar('td'); // is grid dependant on categories grid // set default params (same as in catalog) if ($tab_params['mode'] === false) $tab_params['mode'] = 'multi'; if ($tab_params['special'] === false) $tab_params['special'] = ''; if ($tab_params['dependant'] === false) $tab_params['dependant'] = 'yes'; // pass params to block with tab content $params['name'] = $params['render_as']; $special = $tab_params['special'] ? $tab_params['special'] : $this->Special; $params['prefix'] = trim($this->Prefix.'.'.$special, '.'); $prefix_append = $this->Application->GetVar('prefix_append'); if ($prefix_append) { $params['prefix'] .= $prefix_append; } $default_grid = array_key_exists('default_grid', $params) ? $params['default_grid'] : 'Default'; $radio_grid = array_key_exists('radio_grid', $params) ? $params['radio_grid'] : 'Radio'; $params['cat_prefix'] = trim('c.'.$special, '.'); $params['tab_mode'] = $tab_params['mode']; $params['grid_name'] = ($tab_params['mode'] == 'multi') ? $default_grid : $radio_grid; $params['tab_dependant'] = $tab_params['dependant']; $params['show_category'] = $tab_params['special'] == 'showall' ? 1 : 0; // this is advanced view -> show category name if ($special == 'showall' || $special == 'user') { $params['grid_name'] .= 'ShowAll'; } return $this->Application->ParseBlock($params, 1); } /** * Show CachedNavbar of current item primary category * * @param Array $params * @return string */ function CategoryName($params) { // show category cachednavbar of $object =& $this->getObject($params); $category_id = isset($params['cat_id']) ? $params['cat_id'] : $object->GetDBField('CategoryId'); $category_path = $this->Application->getCache('category_paths', $category_id); if ($category_path === false) { // not chached if ($category_id > 0) { $cached_navbar = preg_replace('/^(Content&\|&|Content)/i', '', $object->GetField('CachedNavbar')); $category_path = trim($this->CategoryName( Array('cat_id' => 0) ).' > '.str_replace('&|&', ' > ', $cached_navbar), ' > '); } else { $category_path = $this->Application->Phrase( $this->Application->ConfigValue('Root_Name') ); } $this->Application->setCache('category_paths', $category_id, $category_path); } return $category_path; } /** * Allows to determine if original value should be shown * * @param Array $params * @return bool */ function DisplayOriginal($params) { // original id found & greather then zero + show original $display_original = isset($params['display_original']) && $params['display_original']; $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField'); if (!$owner_field) { $owner_field = 'CreatedById'; } $object =& $this->getObject($params); $perm_value = $this->PermHelper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $this->Prefix); return $display_original && ($perm_value == 1) && $this->Application->GetVar($this->Prefix.'.original_id'); } /** * Checks if user have one of required permissions * * @param Array $params * @return bool */ function HasPermission($params) { $perm_helper =& $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ $params['raise_warnings'] = 0; $object =& $this->getObject($params); /* @var $object kCatDBItem */ // 1. category restriction $params['cat_id'] = $object->isLoaded() ? $object->GetDBField('ParentPath') : $this->Application->GetVar('m_cat_id'); // 2. owner restriction $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField'); if (!$owner_field) { $owner_field = 'CreatedById'; } $is_owner = $object->GetDBField($owner_field) == $this->Application->RecallVar('user_id'); return $perm_helper->TagPermissionCheck($params, $is_owner); } /** * Creates link to current category or to module root category, when current category is home * * @param Array $params * @return string */ function SuggestItemLink($params) { if (!isset($params['cat_id'])) { $params['cat_id'] = $this->Application->GetVar('m_cat_id'); } if ($params['cat_id'] == 0) { $params['cat_id'] = $this->Application->findModule('Var', $this->Prefix, 'RootCat'); } $params['m_cat_page'] = 1; return $this->Application->ProcessParsedTag('c', 'CategoryLink', $params); } /** * Allows to detect if item has any additional images available * * @param Array $params * @return string */ function HasAdditionalImages($params) { $object =& $this->getObject($params); $sql = 'SELECT ImageId FROM '.$this->Application->getUnitOption('img', 'TableName').' WHERE ResourceId = '.$object->GetDBField('ResourceId').' AND DefaultImg != 1 AND Enabled = 1'; return $this->Conn->GetOne($sql) ? 1 : 0; } /** * Checks that item is pending * * @param Array $params * @return bool */ function IsPending($params) { $object =& $this->getObject($params); $pending_status = Array (STATUS_PENDING, STATUS_PENDING_EDITING); return in_array($object->GetDBField('Status'), $pending_status); } function IsFavorite($params) { static $favorite_status = Array (); $object =& $this->getObject($params); /* @var $object kDBList */ if (!isset($favorite_status[$this->Special])) { $resource_ids = $object->GetCol('ResourceId'); $user_id = $this->Application->RecallVar('user_id'); $sql = 'SELECT FavoriteId, ResourceId FROM '.$this->Application->getUnitOption('fav', 'TableName').' WHERE (PortalUserId = '.$user_id.') AND (ResourceId IN ('.implode(',', $resource_ids).'))'; $favorite_status[$this->Special] = $this->Conn->GetCol($sql, 'ResourceId'); } return isset($favorite_status[$this->Special][$object->GetDBField('ResourceId')]); } /** * Returns item's editors pick status (using not formatted value) * * @param Array $params * @return bool */ function IsEditorsPick($params) { $object =& $this->getObject($params); return $object->GetDBField('EditorsPick') == 1; } function FavoriteToggleLink($params) { $fav_prefix = $this->Prefix.'-fav'; $params['pass'] = implode(',', Array('m', $this->Prefix, $fav_prefix)); $params[$fav_prefix.'_event'] = 'OnFavoriteToggle'; return $this->ItemLink($params); } /** * Checks if item is passed in url * * @param Array $params * @return bool */ function ItemAvailable($params) { return $this->Application->GetVar($this->getPrefixSpecial().'_id') > 0; } function SortingSelected($params) { $list =& $this->GetList($params); $user_sorting_start = $this->getUserSortIndex(); $sorting_field = $list->GetOrderField($user_sorting_start); $sorting = strtolower($sorting_field . '|' . $list->GetOrderDirection($user_sorting_start)); $field_options = $list->GetFieldOptions($sorting_field); if (array_key_exists('formatter', $field_options) && $field_options['formatter'] == 'kMultiLanguage') { // remove language prefix $sorting = preg_replace('/^l[\d]+_(.*)/', '\\1', $sorting); $params['sorting'] = preg_replace('/^l[\d]+_(.*)/', '\\1', $params['sorting']); } return $sorting == strtolower($params['sorting']) ? $params['selected'] : ''; } function CombinedSortingDropDownName($params) { return $this->Prefix.'_CombinedSorting'; } /** * Prepares name for field with event in it (used only on front-end) * * @param Array $params * @return string */ function SubmitName($params) { return 'events['.$this->Prefix.']['.$params['event'].']'; } /** * Returns prefix + any word (used for shared between categories per page settings) * * @param Array $params * @return string */ function VarName($params) { return $this->Prefix.'_'.$params['type']; } /** * Checks if we are viewing module root category * * @param Array $params * @return bool */ function IsModuleHome($params) { $root_category = $this->Application->findModule('Var', $this->Prefix, 'RootCat'); return $root_category == $this->Application->GetVar('m_cat_id'); } /** * Dynamic votes indicator * * @param Array $params * * @return string */ function VotesIndicator($params) { $object =& $this->getObject($params); /* @var $object kDBItem */ $rating_helper =& $this->Application->recallObject('RatingHelper'); /* @var $rating_helper RatingHelper */ $small_style = array_key_exists('small_style', $params) ? $params['small_style'] : false; return $rating_helper->ratingBar($object, true, '', $small_style); } function RelevanceIndicator($params) { $object =& $this->getObject($params); $search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search'; $sql = 'SELECT Relevance FROM '.$search_results_table.' WHERE ResourceId = '.$object->GetDBField('ResourceId'); $percents_off = (int)(100 - (100 * $this->Conn->GetOne($sql))); $percents_off = ($percents_off < 0) ? 0 : $percents_off; if ($percents_off) { $params['percent_off'] = $percents_off; $params['percent_on'] = 100 - $percents_off; $params['name'] = $this->SelectParam($params, 'relevance_normal_render_as,block_relevance_normal'); } else { $params['name'] = $this->SelectParam($params, 'relevance_full_render_as,block_relevance_full'); } return $this->Application->ParseBlock($params); } function SearchResultField($params) { $ret = $this->Field($params); $keywords = unserialize( $this->Application->RecallVar('highlight_keywords') ); $opening = $this->Application->ParseBlock( Array('name' => $this->SelectParam($params, 'highlight_opening_render_as,block_highlight_opening')) ); $closing = $this->Application->ParseBlock( Array('name' => $this->SelectParam($params, 'highlight_closing_render_as,block_highlight_closing')) ); foreach ($keywords as $index => $keyword) { $keywords[$index] = preg_quote($keyword, '/'); } return preg_replace('/('.implode('|', $keywords).')/i', $opening.'\\1'.$closing, $ret); } /** * Shows keywords, that user searched * * @param Array $params * @return bool */ function SearchKeywords($params) { $keywords = $this->Application->GetVar('keywords'); $sub_search = $this->Application->GetVar('search_type') == 'subsearch'; return ($keywords !== false) && !$sub_search ? $keywords : $this->Application->RecallVar('keywords'); } function AdvancedSearchForm($params) { $search_table = $this->Application->getUnitOption('confs', 'TableName'); $module_name = $this->Application->findModule('Var', $this->Prefix, 'Name'); $sql = 'SELECT * FROM '.$search_table.' WHERE (ModuleName = '.$this->Conn->qstr($module_name).') AND (AdvancedSearch = 1) ORDER BY DisplayOrder'; $search_config = $this->Conn->Query($sql); $ret = ''; foreach ($search_config as $record) { $params['name'] = $this->SelectParam($params, 'and_or_render_as,and_or_block'); $params['field'] = $record['FieldName']; $params['andor'] = $this->Application->ParseBlock($params); $params['name'] = $this->SelectParam($params, $record['FieldType'].'_render_as,'.$record['FieldType'].'_block'); $params['caption'] = $this->Application->Phrase($record['DisplayName']); $ret .= $this->Application->ParseBlock($params); } return $ret; } /** * Returns last modification date of items in category / system * * @param Array $params * @return string */ function LastUpdated($params) { $category_id = $this->Application->GetVar('m_cat_id'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); if (isset($params['local']) && $params['local'] && $category_id > 0) { // scan only current category & it's children $sql = 'SELECT TreeLeft, TreeRight FROM ' . TABLE_PREFIX . 'Category WHERE CategoryId = ' . (int)$category_id; $tree_info = $this->Conn->GetRow($sql); $sql = 'SELECT MAX(item_table.Modified) AS ModDate, MAX(item_table.CreatedOn) AS NewDate FROM '.$table_name.' item_table LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON (item_table.ResourceId = ci.ItemResourceId) LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId WHERE c.TreeLeft BETWEEN '.$tree_info['TreeLeft'].' AND '.$tree_info['TreeRight']; } else { // scan all categories in system $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate FROM '.$table_name; } $row_data = $this->Conn->GetRow($sql); if (!$row_data) { return ''; } $date = $row_data[ $row_data['NewDate'] > $row_data['ModDate'] ? 'NewDate' : 'ModDate' ]; // format date $format = isset($params['format']) ? $params['format'] : '_regional_DateTimeFormat'; if (preg_match("/_regional_(.*)/", $format, $regs)) { $lang =& $this->Application->recallObject('lang.current'); if ($regs[1] == 'DateTimeFormat') { // combined format $format = $lang->GetDBField('DateFormat').' '.$lang->GetDBField('TimeFormat'); } else { // simple format $format = $lang->GetDBField($regs[1]); } } return adodb_date($format, $date); } /** * Counts category item count in system (not category-dependent) * * @param Array $params * @return int */ function ItemCount($params) { $count_helper =& $this->Application->recallObject('CountHelper'); /* @var $count_helper kCountHelper */ $today_only = isset($params['today']) && $params['today']; return $count_helper->ItemCount($this->Prefix, $today_only); } function CategorySelector($params) { $category_id = isset($params['category_id']) && is_numeric($params['category_id']) ? $params['category_id'] : false; if ($category_id === false) { // if category id not given use module root category $category_id = $this->Application->findModule('Var', $this->Prefix, 'RootCat'); } $id_field = $this->Application->getUnitOption('c', 'IDField'); $title_field = $this->Application->getUnitOption('c', 'TitleField'); $table_name = $this->Application->getUnitOption('c', 'TableName'); $count_helper =& $this->Application->recallObject('CountHelper'); /* @var $count_helper kCountHelper */ list ($view_perm, $view_filter) = $count_helper->GetPermissionClause('c', 'perm_cache'); // get category list (permission based) $sql = 'SELECT c.'.$title_field.', c.'.$id_field.' FROM '.$table_name.' c INNER JOIN '.TABLE_PREFIX.'PermCache perm_cache ON c.CategoryId = perm_cache.CategoryId WHERE (ParentId = '.$category_id.') AND ('.$view_filter.') AND (perm_cache.PermId = '.$view_perm.') AND (c.Status = '.STATUS_ACTIVE.') ORDER BY c.'.$title_field.' ASC'; $categories = $this->Conn->GetCol($sql, $id_field); $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; $block_params['strip_nl'] = 2; $ret = ''; foreach ($categories as $category_id => $category_name) { // print category $block_params['separator'] = isset($params['category_id']) ? $params['separator'] : ''; // return original separator, remove separator for top level categories $block_params['category_id'] = $category_id; $block_params['category_name'] = $category_name; $ret .= $this->Application->ParseBlock($block_params); // print it's children $block_params['separator'] = ' '.$params['separator']; $ret .= $this->CategorySelector($block_params); } return $ret; } function PrintMoreCategories($params) { $object =& $this->getObject(); /* @var $object kDBItem */ $category_ids = $this->Field($params); if (!$category_ids) { return ''; } $category_ids = explode('|', substr($category_ids, 1, -1)); $id_field = $this->Application->getUnitOption('c', 'IDField'); $title_field = $this->Application->getUnitOption('c', 'TitleField'); $table_name = $this->Application->getUnitOption('c', 'TableName'); $sql = 'SELECT '.$title_field.', '.$id_field.' FROM '.$table_name.' WHERE '.$id_field.' IN ('.implode(',', $category_ids).')'; $categories = $this->Conn->GetCol($sql, $id_field); $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; $ret = ''; foreach ($categories as $category_id => $category_name) { $block_params['category_id'] = $category_id; $block_params['category_name'] = $category_name; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } function DownloadFileLink($params) { $params[$this->getPrefixSpecial().'_event'] = 'OnDownloadFile'; return $this->ItemLink($params); } function ImageSrc($params) { list ($ret, $tag_processed) = $this->processAggregatedTag('ImageSrc', $params, $this->getPrefixSpecial()); return $tag_processed ? $ret : false; } /** * Registers hit for item (one time per session) * * @param Array $params */ function RegisterHit($params) { $object =& $this->getObject(); /* @var $object kCatDBItem */ if ($object->isLoaded()) { $object->RegisterHit(); } } /** * Returns link to item's author public profile * * @param Array $params * @return string */ function ProfileLink($params) { $object =& $this->getObject($params); $owner_field = array_key_exists('owner_field', $params) ? $params['owner_field'] : 'CreatedById'; $params['user_id'] = $object->GetDBField($owner_field); unset($params['owner_field']); return $this->Application->ProcessParsedTag('m', 'Link', $params); } /** * Checks, that "view in browse mode" functionality available * * @param Array $params * @return bool */ function BrowseModeAvailable($params) { $valid_special = $valid_special = $params['Special'] != 'user'; $not_selector = $this->Application->GetVar('type') != 'item_selector'; return $valid_special && $not_selector; } /** * Returns a link for editing product * * @param Array $params * @return string */ function ItemEditLink($params) { $object =& $this->getObject(); /* @var $object kDBList */ $edit_template = $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePath') . '/' . $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePrefix') . 'edit'; $url_params = Array ( 'm_opener' => 'd', $this->Prefix.'_mode' => 't', $this->Prefix.'_event' => 'OnEdit', $this->Prefix.'_id' => $object->GetID(), 'm_cat_id' => $object->GetDBField('CategoryId'), 'pass' => 'all,'.$this->Prefix, 'no_pass_through' => 1, ); return $this->Application->HREF($edit_template,'', $url_params); } function LanguageVisible($params) { $field = $this->SelectParam($params, 'name,field'); preg_match('/l([\d]+)_(.*)/', $field, $regs); $params['name'] = $regs[2]; return $this->HasLanguageError($params) || $this->Application->GetVar('m_lang') == $regs[1]; } function HasLanguageError($params) { static $languages = null; if (!isset($languages)) { $sql = 'SELECT ' . $this->Application->getUnitOption('lang', 'IDField') . ' FROM ' . $this->Application->getUnitOption('lang', 'TableName') . ' WHERE Enabled = 1'; $languages = $this->Conn->GetCol($sql); } $field = $this->SelectParam($params, 'name,field'); $object =& $this->getObject($params); /* @var $object kDBItem */ foreach ($languages as $language_id) { $check_field = 'l' . $language_id . '_' . $field; if ($object->GetErrorMsg($check_field, false)) { return true; } } return false; } } \ No newline at end of file Index: branches/5.0.x/core/units/categories/categories_tag_processor.php =================================================================== --- branches/5.0.x/core/units/categories/categories_tag_processor.php (revision 12970) +++ branches/5.0.x/core/units/categories/categories_tag_processor.php (revision 12971) @@ -1,1898 +1,1908 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.org/license for copyright notices and details. */ class CategoriesTagProcessor extends kDBTagProcessor { function SubCatCount($params) { $object =& $this->getObject($params); if (isset($params['today']) && $params['today']) { $sql = 'SELECT COUNT(*) FROM '.$object->TableName.' WHERE (ParentPath LIKE "'.$object->GetDBField('ParentPath').'%") AND (CreatedOn > '.(adodb_mktime() - 86400).')'; return $this->Conn->GetOne($sql) - 1; } return $object->GetDBField('CachedDescendantCatsQty'); } /** * Returns category count in system * * @param Array $params * @return int */ function CategoryCount($params) { $count_helper =& $this->Application->recallObject('CountHelper'); /* @var $count_helper kCountHelper */ $today_only = isset($params['today']) && $params['today']; return $count_helper->CategoryCount($today_only); } function IsNew($params) { $object =& $this->getObject($params); return $object->GetDBField('IsNew') ? 1 : 0; } function IsPick($params) { return $this->IsEditorsPick($params); } /** * Returns item's editors pick status (using not formatted value) * * @param Array $params * @return bool */ function IsEditorsPick($params) { $object =& $this->getObject($params); return $object->GetDBField('EditorsPick') == 1; } function ItemIcon($params) { $grids = $this->Application->getUnitOption($this->Prefix, 'Grids'); $grid = $grids[ $params['grid'] ]; if (!array_key_exists('Icons', $grid)) { return ''; } $icons = $grid['Icons']; if (array_key_exists('name', $params)) { $icon_name = $params['name']; return array_key_exists($icon_name, $icons) ? $icons[$icon_name] : ''; } $object =& $this->getObject($params); /* @var $object kDBList */ if ($object->GetDBField('CreatedBySystem')) { if (!$object->GetDBField('IsMenu')) { return 'icon16_section_menuhidden_system.png'; } return 'icon16_section_system.png'; } $status = $object->GetDBField('Status'); if ($status == STATUS_DISABLED) { return 'icon16_section_disabled.png'; } if (!$object->GetDBField('IsMenu')) { return 'icon16_section_menuhidden.png'; } if ($status == STATUS_PENDING) { return 'icon16_section_pending.png'; } if ($object->GetDBField('IsNew')) { return 'icon16_section_new.png'; } return 'icon16_section.png'; } function ItemCount($params) { $object =& $this->getObject($params); $ci_table = $this->Application->getUnitOption('l-ci', 'TableName'); $sql = 'SELECT COUNT(*) FROM ' . $object->TableName . ' c LEFT JOIN ' . $ci_table . ' ci ON c.CategoryId = ci.CategoryId WHERE (c.TreeLeft BETWEEN ' . $object->GetDBField('TreeLeft') . ' AND ' . $object->GetDBField('TreeRight') . ') AND NOT (ci.CategoryId IS NULL)'; return $this->Conn->GetOne($sql); } function ListCategories($params) { return $this->PrintList2($params); } function RootCategoryName($params) { return $this->Application->ProcessParsedTag('m', 'RootCategoryName', $params); } function CheckModuleRoot($params) { $module_name = getArrayValue($params, 'module') ? $params['module'] : 'In-Commerce'; $module_root_cat = $this->Application->findModule('Name', $module_name, 'RootCat'); $additional_cats = $this->SelectParam($params, 'add_cats'); if ($additional_cats) { $additional_cats = explode(',', $additional_cats); } else { $additional_cats = array(); } if ($this->Application->GetVar('m_cat_id') == $module_root_cat || in_array($this->Application->GetVar('m_cat_id'), $additional_cats)) { $home_template = getArrayValue($params, 'home_template'); if (!$home_template) return; $this->Application->Redirect($home_template, Array('pass'=>'all')); }; } function CategoryPath($params) { $category_helper =& $this->Application->recallObject('CategoryHelper'); /* @var $category_helper CategoryHelper */ return $category_helper->NavigationBar($params); } /** * Shows category path to specified category * * @param Array $params * @return string */ function FieldCategoryPath($params) { $object =& $this->getObject(); /* @var $object kDBItem */ $field = $this->SelectParam($params, 'name,field'); $category_id = $object->GetDBField($field); if ($category_id) { $params['cat_id'] = $category_id; return $this->CategoryPath($params); } return ''; } function CurrentCategoryName($params) { $cat_object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix.'_List'); $sql = 'SELECT '.$this->getTitleField().' FROM '.$cat_object->TableName.' WHERE CategoryId = '.(int)$this->Application->GetVar('m_cat_id'); return $this->Conn->GetOne($sql); } /** * Returns current category name * * @param Array $params * @return string * @todo Find where it's used */ function CurrentCategory($params) { return $this->CurrentCategoryName($params); } function getTitleField() { $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); return $ml_formatter->LangFieldName('Name'); } /** * Returns symlinked category for given category * * @param $category_id */ function getCategorySymLink($category_id) { static $cache = null; if (!$category_id) { // don't bother to get symlink for "Home" category return $category_id; } if (!isset($cache)) { $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); // get symlinked categories, that are not yet deleted $sql = 'SELECT c1.SymLinkCategoryId, c1.' . $id_field . ' FROM ' . $table_name . ' c1 JOIN ' . $table_name . ' c2 ON c1.SymLinkCategoryId = c2.' . $id_field; $cache = $this->Conn->GetCol($sql, $id_field); } return array_key_exists($category_id, $cache) ? $cache[$category_id] : $category_id; } function CategoryLink($params) { $category_id = getArrayValue($params, 'cat_id'); if ($category_id === false) { $category_id = $this->Application->GetVar($this->getPrefixSpecial() . '_id'); } if ("$category_id" == 'Root') { $category_id = $this->Application->findModule('Name', $params['module'], 'RootCat'); } elseif ("$category_id" == 'current') { $category_id = $this->Application->GetVar('m_cat_id'); } $category_id = $this->getCategorySymLink( (int)$category_id ); unset($params['cat_id'], $params['module']); $new_params = Array ('pass' => 'm', 'm_cat_id' => $category_id, 'pass_category' => 1); $params = array_merge_recursive2($params, $new_params); return $this->Application->ProcessParsedTag('m', 't', $params); } function CategoryList($params) { //$object =& $this->Application->recallObject( $this->getPrefixSpecial() , $this->Prefix.'_List', $params ); $object =& $this->GetList($params); if ($object->RecordsCount == 0) { if (isset($params['block_no_cats'])) { $params['name'] = $params['block_no_cats']; return $this->Application->ParseBlock($params); } else { return ''; } } if (isset($params['block'])) { return $this->PrintList($params); } else { $params['block'] = $params['block_main']; if (isset($params['block_row_start'])) { $params['row_start_block'] = $params['block_row_start']; } if (isset($params['block_row_end'])) { $params['row_end_block'] = $params['block_row_end']; } return $this->PrintList2($params); } } function Meta($params) { $object =& $this->Application->recallObject($this->Prefix); // .'.-item' /* @var $object CategoriesItem */ $meta_type = $params['name']; if ($object->isLoaded()) { // 1. get module prefix by current category $category_helper =& $this->Application->recallObject('CategoryHelper'); /* @var $category_helper CategoryHelper */ $category_path = explode('|', substr($object->GetDBField('ParentPath'), 1, -1)); $module_info = $category_helper->getCategoryModule($params, $category_path); // In-Edit & Proj-CMS module prefixes doesn't have custom field with item template if ($module_info && $module_info['Var'] != 'adm' && $module_info['Var'] != 'st') { // 2. get item template by current category & module prefix $mod_rewrite_helper = $this->Application->recallObject('ModRewriteHelper'); /* @var $mod_rewrite_helper kModRewriteHelper */ $category_params = Array ( 'CategoryId' => $object->GetID(), 'ParentPath' => $object->GetDBField('ParentPath'), ); $item_template = $mod_rewrite_helper->GetItemTemplate($category_params, $module_info['Var']); if ($this->Application->GetVar('t') == $item_template) { // we are located on item's details page $item =& $this->Application->recallObject($module_info['Var']); /* @var $item kCatDBItem */ // 3. get item's meta data $value = $item->GetField('Meta'.$meta_type); if ($value) { return $value; } } // 4. get category meta data $value = $object->GetField('Meta'.$meta_type); if ($value) { return $value; } } } // 5. get default meta data switch ($meta_type) { case 'Description': $config_name = 'Category_MetaDesc'; break; case 'Keywords': $config_name = 'Category_MetaKey'; break; } return $this->Application->ConfigValue($config_name); } function BuildListSpecial($params) { if (($this->Special != '') && !is_numeric($this->Special)) { // When recursive category list is printed (like in sitemap), then special // should be generated even if it's already present. Without it list on this // level will erase list on previous level, because it will be stored in same object. return $this->Special; } if ( isset($params['parent_cat_id']) ) { $parent_cat_id = $params['parent_cat_id']; } else { $parent_cat_id = $this->Application->GetVar($this->Prefix.'_id'); if (!$parent_cat_id) { $parent_cat_id = $this->Application->GetVar('m_cat_id'); } if (!$parent_cat_id) { $parent_cat_id = 0; } } $list_unique_key = $this->getUniqueListKey($params); // check for "admin" variable, because we are parsing front-end template from admin when using template editor feature if ($this->Application->GetVar('admin') || !$this->Application->isAdmin) { // add parent category to special, when on Front-End, // because there can be many category lists on same page $list_unique_key .= $parent_cat_id; } if ($list_unique_key == '') { return parent::BuildListSpecial($params); } return crc32($list_unique_key); } function IsCurrent($params) { $object =& $this->getObject($params); if ($object->GetID() == $this->Application->GetVar('m_cat_id')) { return true; } else { return false; } } /** * Substitutes category in last template base on current category * This is required becasue when you navigate catalog using AJAX, last_template is not updated * but when you open item edit from catalog last_template is used to build opener_stack * So, if we don't substitute m_cat_id in last_template, after saving item we'll get redirected * to the first category we've opened, not the one we navigated to using AJAX * * @param Array $params */ function UpdateLastTemplate($params) { $category_id = $this->Application->GetVar('m_cat_id'); $wid = $this->Application->GetVar('m_wid'); list($index_file, $env) = explode('|', $this->Application->RecallVar(rtrim('last_template_'.$wid, '_')), 2); $vars_backup = Array (); $vars = $this->Application->HttpQuery->processQueryString( str_replace('%5C', '\\', $env) ); foreach ($vars as $var_name => $var_value) { $vars_backup[$var_name] = $this->Application->GetVar($var_name); $this->Application->SetVar($var_name, $var_value); } // update required fields $this->Application->SetVar('m_cat_id', $category_id); $this->Application->Session->SaveLastTemplate($params['template']); foreach ($vars_backup as $var_name => $var_value) { $this->Application->SetVar($var_name, $var_value); } } function GetParentCategory($params) { $parent_id = 0; $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table = $this->Application->getUnitOption($this->Prefix,'TableName'); $cat_id = $this->Application->GetVar('m_cat_id'); if ($cat_id > 0) { $sql = 'SELECT ParentId FROM '.$table.' WHERE '.$id_field.' = '.$cat_id; $parent_id = $this->Conn->GetOne($sql); } return $parent_id; } function InitCacheUpdater($params) { safeDefine('CACHE_PERM_CHUNK_SIZE', 30); $continue = $this->Application->GetVar('continue'); $total_cats = (int) $this->Conn->GetOne('SELECT COUNT(*) FROM '.TABLE_PREFIX.'Category'); if ($continue === false && $total_cats > CACHE_PERM_CHUNK_SIZE) { // first step, if category count > CACHE_PERM_CHUNK_SIZE, then ask for cache update return true; } if ($continue === false) { // if we don't have to ask, then assume user selected "Yes" in permcache update dialog $continue = 1; } $updater =& $this->Application->recallObject('kPermCacheUpdater', null, Array('continue' => $continue)); /* @var $updater kPermCacheUpdater */ if ($continue === '0') { // No in dialog $updater->clearData(); $this->Application->Redirect($params['destination_template']); } $ret = false; // don't ask for update if ($continue == 1) { // Initial run $updater->setData(); } if ($continue == 2) { // Continuing // called from AJAX request => returns percent $needs_more = true; while ($needs_more && $updater->iteration <= CACHE_PERM_CHUNK_SIZE) { // until proceeeded in this step category count exceeds category per step limit $needs_more = $updater->DoTheJob(); } if ($needs_more) { // still some categories are left for next step $updater->setData(); } else { // all done -> redirect $updater->SaveData(); $this->Application->RemoveVar('PermCache_UpdateRequired'); $this->Application->Redirect($params['destination_template']); } $ret = $updater->getDonePercent(); } return $ret; } /** * Parses warning block, but with style="display: none;". Used during permissions saving from AJAX * * @param Array $params * @return string */ function SaveWarning($params) { if ($this->Prefix == 'st') { // don't use this method for other prefixes then Category, that use this tag processor return parent::SaveWarning($params); } $main_prefix = getArrayValue($params, 'main_prefix'); if ($main_prefix && $main_prefix != '$main_prefix') { $top_prefix = $main_prefix; } else { $top_prefix = $this->Application->GetTopmostPrefix($this->Prefix); } $temp_tables = substr($this->Application->GetVar($top_prefix.'_mode'), 0, 1) == 't'; $modified = $this->Application->RecallVar($top_prefix.'_modified'); if (!$temp_tables) { $this->Application->RemoveVar($top_prefix.'_modified'); return ''; } $block_name = $this->SelectParam($params, 'render_as,name'); if ($block_name) { $block_params = $this->prepareTagParams($params); $block_params['name'] = $block_name; $block_params['edit_mode'] = $temp_tables ? 1 : 0; $block_params['display'] = $temp_tables && $modified ? 1 : 0; return $this->Application->ParseBlock($block_params); } else { return $temp_tables && $modified ? 1 : 0; } return ; } /** * Allows to detect if this prefix has something in clipboard * * @param Array $params * @return bool */ function HasClipboard($params) { $clipboard = $this->Application->RecallVar('clipboard'); if ($clipboard) { $clipboard = unserialize($clipboard); foreach ($clipboard as $prefix => $clipboard_data) { foreach ($clipboard_data as $mode => $ids) { if (count($ids)) return 1; } } } return 0; } /** * Allows to detect if root category being edited * * @param Array $params */ function IsRootCategory($params) { $object =& $this->getObject($params); return $object->IsRoot(); } /** * Returns home category id * * @param Array $params * @return int */ function HomeCategory($params) { static $root_category = null; if (!isset($root_category)) { $root_category = $this->Application->findModule('Name', 'Core', 'RootCat'); } return $root_category; } /** * Used for disabling "Home" and "Up" buttons in category list * * @param Array $params * @return bool */ function ModuleRootCategory($params) { return $this->Application->GetVar('m_cat_id') == $this->HomeCategory($params); } function CatalogItemCount($params) { $params['skip_quering'] = true; $object =& $this->GetList($params); if (!$object->Counted) { $object->CountRecs(); } return $object->NoFilterCount != $object->RecordsCount ? $object->RecordsCount.' / '.$object->NoFilterCount : $object->RecordsCount; } function InitCatalog($params) { $tab_prefixes = $this->Application->GetVar('tp'); // {all, <prefixes_list>, none} if ($tab_prefixes === false) $tab_prefixes = 'all'; $skip_prefixes = isset($params['skip_prefixes']) && $params['skip_prefixes'] ? explode(',', $params['skip_prefixes']) : Array(); $replace_main = isset($params['replace_m']) && $params['replace_m']; // get all prefixes available $prefixes = Array(); foreach ($this->Application->ModuleInfo as $module_name => $module_data) { $prefix = $module_data['Var']; if ($prefix == 'adm'/* || $prefix == 'm'*/) continue; if ($prefix == 'm' && $replace_main) { $prefix = 'c'; } $prefixes[] = $prefix; } if ($tab_prefixes == 'none') { $skip_prefixes = array_unique(array_merge($skip_prefixes, $prefixes)); unset($skip_prefixes[ array_search($replace_main ? 'c' : 'm', $skip_prefixes) ]); } elseif ($tab_prefixes != 'all') { // prefix list here $tab_prefixes = explode(',', $tab_prefixes); // list of prefixes that should stay $skip_prefixes = array_unique(array_merge($skip_prefixes, array_diff($prefixes, $tab_prefixes))); } $params['name'] = $params['render_as']; $params['skip_prefixes'] = implode(',', $skip_prefixes); return $this->Application->ParseBlock($params, 1); } /** * Determines, that printed category/menu item is currently active (will also match parent category) * * @param Array $params * @return bool */ function IsActive($params) { static $current_path = null; if (!isset($current_path)) { $sql = 'SELECT ParentPath FROM ' . TABLE_PREFIX . 'Category WHERE CategoryId = ' . (int)$this->Application->GetVar('m_cat_id'); $current_path = $this->Conn->GetOne($sql); } if (array_key_exists('parent_path', $params)) { $test_path = $params['parent_path']; } else { $template = $params['template']; if ($template) { // when using from "c:CachedMenu" tag $sql = 'SELECT ParentPath FROM ' . TABLE_PREFIX . 'Category WHERE NamedParentPath = ' . $this->Conn->qstr('Content/' . $template); $test_path = $this->Conn->GetOne($sql); } else { // when using from "c:PrintList" tag $cat_id = array_key_exists('cat_id', $params) && $params['cat_id'] ? $params['cat_id'] : false; if ($cat_id === false) { // category not supplied -> get current from PrintList $category =& $this->getObject($params); } else { if ("$cat_id" == 'Root') { $cat_id = $this->Application->findModule('Name', $params['module'], 'RootCat'); } $category =& $this->Application->recallObject($this->Prefix . '.-c' . $cat_id, $this->Prefix, Array ('skip_autoload' => true)); $category->Load($cat_id); } $test_path = $category->GetDBField('ParentPath'); } } return strpos($current_path, $test_path) !== false; } /** * Checks if user have one of required permissions * * @param Array $params * @return bool */ function HasPermission($params) { $perm_helper =& $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ $params['raise_warnings'] = 0; $object =& $this->getObject($params); /* @var $object kDBItem */ $params['cat_id'] = $object->isLoaded() ? $object->GetDBField('ParentPath') : $this->Application->GetVar('m_cat_id'); return $perm_helper->TagPermissionCheck($params); } /** * Prepares name for field with event in it (used only on front-end) * * @param Array $params * @return string */ function SubmitName($params) { return 'events['.$this->Prefix.']['.$params['event'].']'; } /** * Returns last modification date of items in category / system * * @param Array $params * @return string */ function LastUpdated($params) { $category_id = $this->Application->GetVar('m_cat_id'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); if (isset($params['local']) && $params['local'] && $category_id > 0) { // scan only current category & it's children $sql = 'SELECT TreeLeft, TreeRight FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$category_id; $tree_info = $this->Conn->GetRow($sql); $sql = 'SELECT MAX(c.Modified) AS ModDate, MAX(c.CreatedOn) AS NewDate FROM '.TABLE_PREFIX.'Category c WHERE c.TreeLeft BETWEEN '.$tree_info['TreeLeft'].' AND '.$tree_info['TreeRight']; } else { // scan all categories in system $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate FROM '.$table_name; } $row_data = $this->Conn->GetRow($sql); if (!$row_data) { return ''; } $date = $row_data[ $row_data['NewDate'] > $row_data['ModDate'] ? 'NewDate' : 'ModDate' ]; // format date $format = isset($params['format']) ? $params['format'] : '_regional_DateTimeFormat'; if (preg_match("/_regional_(.*)/", $format, $regs)) { $lang =& $this->Application->recallObject('lang.current'); if ($regs[1] == 'DateTimeFormat') { // combined format $format = $lang->GetDBField('DateFormat').' '.$lang->GetDBField('TimeFormat'); } else { // simple format $format = $lang->GetDBField($regs[1]); } } return adodb_date($format, $date); } function CategoryItemCount($params) { $object =& $this->getObject($params); /* @var $object kDBList */ $params['cat_id'] = $object->GetID(); $count_helper =& $this->Application->recallObject('CountHelper'); /* @var $count_helper kCountHelper */ return $count_helper->CategoryItemCount($params['prefix'], $params); } /** * Returns prefix + any word (used for shared between categories per page settings) * * @param Array $params * @return string */ function VarName($params) { return $this->Prefix.'_'.$params['type']; } /** * Checks if current category is valid symbolic link to another category * * @param Array $params * @return string */ function IsCategorySymLink($params) { $object =& $this->getObject($params); /* @var $object kDBList */ $sym_category_id = $object->GetDBField('SymLinkCategoryId'); if (is_null($sym_category_id)) { return false; } $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); $sql = 'SELECT '.$id_field.' FROM '.$table_name.' WHERE '.$id_field.' = '.$sym_category_id; return $this->Conn->GetOne($sql)? true : false; } /** * Returns module prefix based on root category for given * * @param Array $params * @return string */ function GetModulePrefix($params) { $object =& $this->getObject($params); /* @var $object kDBItem */ $parent_path = explode('|', substr($object->GetDBField('ParentPath'), 1, -1)); $category_helper =& $this->Application->recallObject('CategoryHelper'); /* @var $category_helper CategoryHelper */ $module_info = $category_helper->getCategoryModule($params, $parent_path); return $module_info['Var']; } function ImageSrc($params) { list ($ret, $tag_processed) = $this->processAggregatedTag('ImageSrc', $params, $this->getPrefixSpecial()); return $tag_processed ? $ret : false; } function PageLink($params) { $t = isset($params['template']) ? $params['template'] : ''; unset($params['template']); if (!$t) $t = $this->Application->GetVar('t'); if (isset($params['page'])) { $this->Application->SetVar($this->getPrefixSpecial().'_Page', $params['page']); unset($params['page']); } $params['m_cat_page'] = $this->Application->GetVar($this->getPrefixSpecial().'_Page'); if (!isset($params['pass'])) { $params['pass'] = 'm,'.$this->getPrefixSpecial(); } return $this->Application->HREF($t, '', $params); } /** * Returns spelling suggestions against search keyword * * @param Array $params * @return string */ function SpellingSuggestions($params) { $keywords = unhtmlentities( trim($this->Application->GetVar('keywords')) ); if (!$keywords) { return ; } // 1. try to get already cached suggestion $suggestion = $this->Application->getCache('search.suggestion', $keywords); if ($suggestion !== false) { return $suggestion; } $table_name = $this->Application->getUnitOption('spelling-dictionary', 'TableName'); // 2. search suggestion in database $sql = 'SELECT SuggestedCorrection FROM ' . $table_name . ' WHERE MisspelledWord = ' . $this->Conn->qstr($keywords); $suggestion = $this->Conn->GetOne($sql); if ($suggestion !== false) { $this->Application->setCache('search.suggestion', $keywords, $suggestion); return $suggestion; } // 3. suggestion not found in database, ask webservice $app_id = $this->Application->ConfigValue('YahooApplicationId'); $url = 'http://search.yahooapis.com/WebSearchService/V1/spellingSuggestion?appid=' . $app_id . '&query='; $curl_helper =& $this->Application->recallObject('CurlHelper'); /* @var $curl_helper kCurlHelper */ $xml_data = $curl_helper->Send($url . urlencode($keywords)); $xml_helper =& $this->Application->recallObject('kXMLHelper'); /* @var $xml_helper kXMLHelper */ $root_node =& $xml_helper->Parse($xml_data); $result = $root_node->FindChild('RESULT'); /* @var $result kXMLNode */ if (is_object($result)) { // webservice responded -> save in local database $fields_hash = Array ( 'MisspelledWord' => $keywords, 'SuggestedCorrection' => $result->Data, ); $this->Conn->doInsert($fields_hash, $table_name); $this->Application->setCache('search.suggestion', $keywords, $result->Data); return $result->Data; } return ''; } /** * Shows link for searching by suggested word * * @param Array $params * @return string */ function SuggestionLink($params) { $params['keywords'] = $this->SpellingSuggestions($params); return $this->Application->ProcessParsedTag('m', 'Link', $params); } function InitCatalogTab($params) { $tab_params['mode'] = $this->Application->GetVar('tm'); // single/multi selection possible $tab_params['special'] = $this->Application->GetVar('ts'); // use special for this tab $tab_params['dependant'] = $this->Application->GetVar('td'); // is grid dependant on categories grid // set default params (same as in catalog) if ($tab_params['mode'] === false) $tab_params['mode'] = 'multi'; if ($tab_params['special'] === false) $tab_params['special'] = ''; if ($tab_params['dependant'] === false) $tab_params['dependant'] = 'yes'; // pass params to block with tab content $params['name'] = $params['render_as']; $special = $tab_params['special'] ? $tab_params['special'] : $this->Special; $params['prefix'] = trim($this->Prefix.'.'.$special, '.'); $prefix_append = $this->Application->GetVar('prefix_append'); if ($prefix_append) { $params['prefix'] .= $prefix_append; } $default_grid = array_key_exists('default_grid', $params) ? $params['default_grid'] : 'Default'; $radio_grid = array_key_exists('radio_grid', $params) ? $params['radio_grid'] : 'Radio'; $params['cat_prefix'] = trim('c.'.($tab_params['special'] ? $tab_params['special'] : $this->Special), '.'); $params['tab_mode'] = $tab_params['mode']; $params['grid_name'] = ($tab_params['mode'] == 'multi') ? $default_grid : $radio_grid; $params['tab_dependant'] = $tab_params['dependant']; $params['show_category'] = $tab_params['special'] == 'showall' ? 1 : 0; // this is advanced view -> show category name if ($special == 'showall' || $special == 'user') { $params['grid_name'] .= 'ShowAll'; } return $this->Application->ParseBlock($params, 1); } /** * Show CachedNavbar of current item primary category * * @param Array $params * @return string */ function CategoryName($params) { // show category cachednavbar of $object =& $this->getObject($params); $category_id = isset($params['cat_id']) ? $params['cat_id'] : $object->GetDBField('CategoryId'); $category_path = $this->Application->getCache('category_paths', $category_id); if ($category_path === false) { // not chached if ($category_id > 0) { $cached_navbar = $object->GetField('CachedNavbar'); if ($category_id == $object->GetDBField('ParentId')) { // parent category cached navbar is one element smaller, then current ones $cached_navbar = explode('&|&', $cached_navbar); array_pop($cached_navbar); $cached_navbar = implode('&|&', $cached_navbar); } else { // no relation with current category object -> query from db $language_id = (int)$this->Application->GetVar('m_lang'); if (!$language_id) { $language_id = 1; } $sql = 'SELECT l' . $language_id . '_CachedNavbar FROM ' . $object->TableName . ' WHERE ' . $object->IDField . ' = ' . $category_id; $cached_navbar = $this->Conn->GetOne($sql); } $cached_navbar = preg_replace('/^(Content&\|&|Content)/i', '', $cached_navbar); $category_path = trim($this->CategoryName( Array('cat_id' => 0) ).' > '.str_replace('&|&', ' > ', $cached_navbar), ' > '); } else { $category_path = $this->Application->Phrase( $this->Application->ConfigValue('Root_Name') ); } $this->Application->setCache('category_paths', $category_id, $category_path); } return $category_path; } // structure related /** * Returns page object based on requested params * * @param Array $params * @return PagesItem */ function &_getPage($params) { $page =& $this->Application->recallObject($this->Prefix . '.-virtual', null, $params); /* @var $page kDBItem */ // 1. load by given id $page_id = array_key_exists('page_id', $params) ? $params['page_id'] : false; if ($page_id) { if ($page_id != $page->GetID()) { // load if different $page->Load($page_id); } return $page; } // 2. load by template $template = array_key_exists('page', $params) ? $params['page'] : ''; if (!$template) { $template = $this->Application->GetVar('t'); } // different path in structure AND design template differes from requested template $structure_path_match = strtolower( $page->GetDBField('NamedParentPath') ) == strtolower('Content/' . $template); $design_match = $page->GetDBField('CachedTemplate') == $template; if (!$structure_path_match && !$design_match) { // Same sql like in "c:getPassedID". Load, when current page object doesn't match requested page object $themes_helper =& $this->Application->recallObject('ThemesHelper'); /* @var $themes_helper kThemesHelper */ $page_id = $themes_helper->getPageByTemplate($template); $page->Load($page_id); } return $page; } /** * Returns requested content block content of current or specified page * * @param Array $params * @return string */ function ContentBlock($params) { $num = getArrayValue($params, 'num'); if (!$num) { return 'NO CONTENT NUM SPECIFIED'; } $page =& $this->_getPage($params); /* @var $page kDBItem */ if (!$page->isLoaded()) { // page is not created yet => all blocks are empty return ''; } $page_id = $page->GetID(); $content =& $this->Application->recallObject('content.-block', null, Array ('skip_autoload' => true)); /* @var $content kDBItem */ $data = Array ('PageId' => $page_id, 'ContentNum' => $num); $content->Load($data); if (!$content->isLoaded()) { // bug: missing content blocks are created even if user have no SMS-management rights $content->SetFieldsFromHash($data); $content->Create(); } $edit_code_before = $edit_code_after = ''; if (EDITING_MODE == EDITING_MODE_CONTENT) { $bg_color = isset($params['bgcolor']) ? $params['bgcolor'] : '#ffffff'; $url_params = Array ( 'pass' => 'm,c,content', 'm_opener' => 'd', 'c_id' => $page->GetID(), 'content_id' => $content->GetID(), 'front' => 1, 'admin' => 1, '__URLENCODE__' => 1, '__NO_REWRITE__'=> 1, 'escape' => 1, 'index_file' => 'index.php', // 'bgcolor' => $bg_color, // '__FORCE_SID__' => 1 ); // link from Front-End to admin, don't remove "index.php" $edit_url = $this->Application->HREF('categories/edit_content', ADMIN_DIRECTORY, $url_params, 'index.php'); $edit_code_before = ' <div class="cms-edit-btn-container"> <div class="cms-edit-btn" onclick="$form_name=\'kf_cont_'.$content->GetID().'\'; std_edit_item(\'content\', \'categories/edit_content\');"> <div class="cms-btn-image"> <img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/content_mode.png" width="15" height="16" alt=""/> </div> <div class="cms-btn-text">' . $this->Application->Phrase('la_btn_EditContent', false, true) . ' '.(defined('DEBUG_MODE') && DEBUG_MODE ? " - #{$num}" : '').'</div> </div> <div class="cms-btn-content">'; $edit_form = '<form method="POST" style="display: inline; margin: 0px" name="kf_cont_'.$content->GetID().'" id="kf_cont_'.$content->GetID().'" action="'.$edit_url.'">'; $edit_form .= '<input type="hidden" name="c_id" value="'.$page->GetID().'"/>'; $edit_form .= '<input type="hidden" name="content_id" value="'.$content->GetID().'"/>'; $edit_form .= '<input type="hidden" name="front" value="1"/>'; $edit_form .= '<input type="hidden" name="bgcolor" value="'.$bg_color.'"/>'; $edit_form .= '<input type="hidden" name="m_lang" value="'.$this->Application->GetVar('m_lang').'"/>'; $edit_form .= '</form>'; $edit_code_after = '</div></div>'; if (array_key_exists('forms_later', $params) && $params['forms_later']) { $all_forms = $this->Application->GetVar('all_forms'); $this->Application->SetVar('all_forms', $all_forms . $edit_form); } else { $edit_code_after .= $edit_form; } } if ($this->Application->GetVar('_editor_preview_') == 1) { $data = $this->Application->RecallVar('_editor_preview_content_'); } else { $data = $content->GetField('Content'); } $data = $edit_code_before . $this->_transformContentBlockData($data, $params) . $edit_code_after; if ($data != '') { $this->Application->Parser->DataExists = true; } return $data; } /** * Apply all kinds of content block data transformations without rewriting ContentBlock tag * * @param string $data * @return string */ function _transformContentBlockData(&$data, $params) { return $data; } /** * Returns current page name or page based on page/page_id parameters * * @param Array $params * @return string * @todo Used? */ function PageName($params) { $page =& $this->_getPage($params); return $page->GetDBField('Name'); } /** * Returns current/given page information * * @param Array $params * @return string */ function PageInfo($params) { $page =& $this->_getPage($params); if ($params['type'] == 'index_tools') { $page_info = $page->GetDBField('IndexTools'); if ($page_info) { return $page_info; } else { if (PROTOCOL == 'https://') { return $this->Application->ConfigValue('cms_DefaultIndextoolsCode_SSL'); } else { return $this->Application->ConfigValue('cms_DefaultIndextoolsCode'); } } } switch ($params['type']) { case 'title': $db_field = 'Title'; break; case 'htmlhead_title': $db_field = 'Name'; break; case 'meta_title': $db_field = 'MetaTitle'; break; case 'meta_keywords': $db_field = 'MetaKeywords'; $cat_field = 'Keywords'; break; case 'meta_description': $db_field = 'MetaDescription'; $cat_field = 'Description'; break; default: return ''; } $default = isset($params['default']) ? $params['default'] : ''; $val = $page->GetField($db_field); if (!$default) { if ($this->Application->isModuleEnabled('In-Portal')) { if (!$val && ($params['type'] == 'meta_keywords' || $params['type'] == 'meta_description')) { // take category meta if it's not set for the page return $this->Application->ProcessParsedTag('c', 'Meta', Array('name' => $cat_field)); } } } if (isset($params['force_default']) && $params['force_default']) { return $default; } if (preg_match('/^_Auto:/', $val)) { $val = $default; /*if ($db_field == 'Title') { $page->SetDBField($db_field, $default); $page->Update(); }*/ } elseif ($page->GetID() == false) { return $default; } return $val; } /** * Includes admin css and js, that are required for cms usage on Front-Edn * * * @param Array $params * @return string */ function EditingScripts($params) { if ($this->Application->GetVar('admin_scripts_included') || !EDITING_MODE) { return ; } $this->Application->SetVar('admin_scripts_included', 1); $js_url = $this->Application->BaseURL() . 'core/admin_templates/js'; $ret = '<link rel="stylesheet" href="' . $js_url . '/jquery/thickbox/thickbox.css" type="text/css" media="screen"/>' . "\n"; $ret .= '<link rel="stylesheet" href="' . $js_url . '/../incs/cms.css" type="text/css" media="screen"/>' . "\n"; if (EDITING_MODE == EDITING_MODE_DESIGN) { $ret .= ' <style type="text/css" media="all"> div.movable-element .movable-header { cursor: move; } </style>'; } $ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/jquery.pack.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/jquery-ui.custom.min.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/is.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/application.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/script.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/thickbox/thickbox.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/template_manager.js"></script>' . "\n"; $ret .= '<script language="javascript">' . "\n"; $ret .= "TB.pathToImage = '" . $js_url . "/jquery/thickbox/loadingAnimation.gif';" . "\n"; $template = $this->Application->GetVar('t'); $theme_id = $this->Application->GetVar('m_theme'); $url_params = Array ('block' => '#BLOCK#', 'theme-file_event' => '#EVENT#', 'theme_id' => $theme_id, 'source' => $template, 'pass' => 'all,theme-file', 'front' => 1, 'm_opener' => 'd', '__NO_REWRITE__' => 1, 'no_amp' => 1); $edit_template_url = $this->Application->HREF('themes/template_edit', ADMIN_DIRECTORY, $url_params, 'index.php'); $url_params = Array ('theme-file_event' => 'OnSaveLayout', 'source' => $template, 'pass' => 'all,theme-file', '__NO_REWRITE__' => 1, 'no_amp' => 1); $save_layout_url = $this->Application->HREF('index', '', $url_params); $this_url = $this->Application->HREF('', '', Array ('editing_mode' => '#EDITING_MODE#', '__NO_REWRITE__' => 1, 'no_amp' => 1)); $ret .= "var aTemplateManager = new TemplateManager('" . $edit_template_url . "', '" . $this_url . "', '" . $save_layout_url . "', " . (int)EDITING_MODE . ");\n"; $ret .= "var main_title = '" . addslashes( $this->Application->ConfigValue('Site_Name') ) . "';" . "\n"; $use_popups = (int)$this->Application->ConfigValue('UsePopups'); $ret .= "var \$use_popups = " . ($use_popups > 0 ? 'true' : 'false') . ";\n"; $ret .= "var \$modal_windows = " . ($use_popups == 2 ? 'true' : 'false') . ";\n"; if (EDITING_MODE != EDITING_MODE_BROWSE) { $ret .= "var base_url = '" . $this->Application->BaseURL() . "';" . "\n"; $ret .= 'TB.closeHtml = \'<img src="' . $js_url . '/../img/close_window15.gif" width="15" height="15" style="border-width: 0px;" alt="close"/><br/>\';' . "\n"; $url_params = Array('m_theme' => '', 'pass' => 'm', 'm_opener' => 'r', '__NO_REWRITE__' => 1, 'no_amp' => 1); $browse_url = $this->Application->HREF('catalog/catalog', ADMIN_DIRECTORY, $url_params, 'index.php'); $browse_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $browse_url); $ret .= ' var topmost = window.top; topmost.document.title = document.title + \' - ' . addslashes($this->Application->Phrase('la_AdministrativeConsole', false)) . '\'; t = \''.$this->Application->GetVar('t').'\'; if (window.parent.frames["menu"] != undefined) { if ( $.isFunction(window.parent.frames["menu"].SyncActive) ) { window.parent.frames["menu"].SyncActive("' . $browse_url . '"); } } '; } $ret .= '</script>' . "\n"; if (EDITING_MODE != EDITING_MODE_BROWSE) { // add form, so admin scripts could work $ret .= '<form id="kernel_form" name="kernel_form" enctype="multipart/form-data" method="post" action="' . $browse_url . '"> <input type="hidden" name="MAX_FILE_SIZE" id="MAX_FILE_SIZE" value="' . MAX_UPLOAD_SIZE . '" /> <input type="hidden" name="sid" id="sid" value="' . $this->Application->GetSID() . '" /> </form>'; } return $ret; } /** * Prints "Edit Page" button on cms page * * @param Array $params * @return string */ function EditPage($params) { if (!EDITING_MODE) { return ''; } $display_mode = array_key_exists('mode', $params) ? $params['mode'] : false; $edit_code = ''; $page =& $this->_getPage($params); if (!$page->isLoaded() || (($display_mode != 'end') && (EDITING_MODE == EDITING_MODE_BROWSE))) { // when "EditingScripts" tag is not used, make sure, that scripts are also included return $this->EditingScripts($params); } // show "EditPage" button only for pages, that exists in structure if ($display_mode != 'end') { $edit_btn = ''; if (EDITING_MODE == EDITING_MODE_CONTENT) { $url_params = Array( 'pass' => 'm,c', 'm_opener' => 'd', 'c_id' => $page->GetID(), 'c_mode' => 't', 'c_event' => 'OnEdit', 'front' => 1, '__URLENCODE__' => 1, '__NO_REWRITE__'=> 1, 'escape' => 1, 'index_file' => 'index.php', ); $edit_url = $this->Application->HREF('categories/categories_edit', ADMIN_DIRECTORY, $url_params); $edit_btn .= ' <div class="cms-section-properties-btn"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . ' onmouseover="window.status=\''.$edit_url.'\'; return true" onclick="$form_name=\'kf_'.$page->GetID().'\'; std_edit_item(\'c\', \'categories/categories_edit\');"> <div class="cms-btn-image"> <img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/section_properties.png" width="15" height="16" alt=""/> </div> <div class="cms-btn-text">' . $this->Application->Phrase('la_btn_SectionProperties', false, true) . '</div> </div>' . "\n"; } elseif (EDITING_MODE == EDITING_MODE_DESIGN) { $url_params = Array( 'pass' => 'm,theme', 'm_opener' => 'd', 'theme_id' => $this->Application->GetVar('m_theme'), 'theme_mode' => 't', 'theme_event' => 'OnEdit', 'theme-file_id' => $this->_getThemeFileId(), 'front' => 1, '__URLENCODE__' => 1, '__NO_REWRITE__'=> 1, 'escape' => 1, 'index_file' => 'index.php', ); $edit_url = $this->Application->HREF('themes/file_edit', ADMIN_DIRECTORY, $url_params); $edit_btn .= ' <div class="cms-layout-btn-container"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . '> <div class="cms-save-layout-btn" onclick="aTemplateManager.saveLayout(); return false;"> <div class="cms-btn-image"> <img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/save_button.gif" width="16" height="16" alt=""/> </div> <div class="cms-btn-text">' . $this->Application->Phrase('la_btn_SaveChanges', false, true) . '</div> </div> <div class="cms-cancel-layout-btn" onclick="aTemplateManager.cancelLayout(); return false;"> <div class="cms-btn-image"> <img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/cancel_button.gif" width="16" height="16" alt=""/> </div> <div class="cms-btn-text">' . $this->Application->Phrase('la_btn_Cancel', false, true) . '</div> </div> </div> <div class="cms-section-properties-btn"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . ' onmouseover="window.status=\''.$edit_url.'\'; return true" onclick="$form_name=\'kf_'.$page->GetID().'\'; std_edit_item(\'theme\', \'themes/file_edit\');"> <div class="cms-btn-image"> <img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/section_properties.png" width="15" height="16" alt=""/> </div> <div class="cms-btn-text">' . $this->Application->Phrase('la_btn_SectionTemplate', false, true) . '</div> </div>' . "\n"; } if ($display_mode == 'start') { // button with border around the page $edit_code .= '<div class="cms-section-properties-btn-container">' . $edit_btn . '<div class="cms-btn-content">'; } else { // button without border around the page $edit_code .= $edit_btn; } } if ($display_mode == 'end') { // draw border around the page $edit_code .= '</div></div>'; } if ($display_mode != 'end') { $edit_code .= '<form method="POST" style="display: inline; margin: 0px" name="kf_'.$page->GetID().'" id="kf_'.$page->GetID().'" action="'.$edit_url.'"></form>'; // when "EditingScripts" tag is not used, make sure, that scripts are also included $edit_code .= $this->EditingScripts($params); } return $edit_code; } function _getThemeFileId() { $template = $this->Application->GetVar('t'); if (!$this->Application->TemplatesCache->TemplateExists($template) && !$this->Application->isAdmin) { $cms_handler =& $this->Application->recallObject($this->Prefix . '_EventHandler'); /* @var $cms_handler CategoriesEventHandler */ $template = ltrim($cms_handler->GetDesignTemplate(), '/'); } $file_path = dirname($template) == '.' ? '' : '/' . dirname($template); $file_name = basename($template); $sql = 'SELECT FileId FROM ' . TABLE_PREFIX . 'ThemeFiles WHERE (ThemeId = ' . (int)$this->Application->GetVar('m_theme') . ') AND (FilePath = ' . $this->Conn->qstr($file_path) . ') AND (FileName = ' . $this->Conn->qstr($file_name . '.tpl') . ')'; return $this->Conn->GetOne($sql); } /** * Builds site menu * * @param Array $params * @return string */ function CachedMenu($params) { $menu_helper =& $this->Application->recallObject('MenuHelper'); /* @var $menu_helper MenuHelper */ return $menu_helper->menuTag($this->getPrefixSpecial(), $params); } /** * Trick to allow some kind of output formatting when using CachedMenu tag * * @param Array $params * @return bool */ function SplitColumn($params) { return $this->Application->GetVar($params['i']) > ceil($params['total'] / $params['columns']); } /** * Returns direct children count of given category * * @param Array $params * @return int */ function HasSubCats($params) { $sql = 'SELECT COUNT(*) FROM ' . TABLE_PREFIX . 'Category WHERE ParentId = ' . $params['cat_id']; return $this->Conn->GetOne($sql); } /** * Prints sub-pages of given/current page. * * @param Array $params * @return string * @todo This could be reached by using "parent_cat_id" parameter. Only difference here is new block parameter "path". Need to rewrite. */ function PrintSubPages($params) { $list =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix.'_List', $params); /* @var $list kDBList */ $category_id = array_key_exists('category_id', $params) ? $params['category_id'] : $this->Application->GetVar('m_cat_id'); $list->addFilter('current_pages', TABLE_PREFIX . 'CategoryItems.CategoryId = ' . $category_id); $list->Query(); $list->GoFirst(); $o = ''; $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; while (!$list->EOL()) { $block_params['path'] = $list->GetDBField('Path'); $o .= $this->Application->ParseBlock($block_params, 1); $list->GoNext(); } return $o; } /** * Builds link for browsing current page on Front-End * * @param Array $params * @return string */ function PageBrowseLink($params) { $object =& $this->getObject($params); $themes_helper =& $this->Application->recallObject('ThemesHelper'); /* @var $themes_helper kThemesHelper */ + $site_config_helper =& $this->Application->recallObject('SiteConfigHelper'); + /* @var $site_config_helper SiteConfigHelper */ + + $settings = $site_config_helper->getSettings(); + $url_params = Array ( 'm_cat_id' => $object->GetID(), 'm_theme' => $themes_helper->getCurrentThemeId(), + 'editing_mode' => $settings['default_editing_mode'], 'pass' => 'm', 'admin' => 1, 'index_file' => 'index.php' ); + if ($this->Application->ConfigValue('UseModRewrite')) { + $url_params['__MOD_REWRITE__'] = 1; + } + return $this->Application->HREF($object->GetDBField('NamedParentPath'), '_FRONT_END_', $url_params); } /** * Builds link to cms page (used?) * * @param Array $params * @return string */ function ContentPageLink($params) { $object =& $this->getObject($params); $params['t'] = $object->GetDBField('NamedParentPath'); $params['m_cat_id'] = 0; return $this->Application->ProcessParsedTag('m', 'Link', $params); } /** * Prepares cms page description for search result page * * @param Array $params * @return string */ function SearchDescription($params) { $object =& $this->getObject($params); $desc = $object->GetField('MetaDescription'); if (!$desc) { $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'PageContent WHERE PageId = ' . $object->GetID() . ' AND ContentNum = 1'; $content = $this->Conn->GetRow($sql); if ($content['l'.$this->Application->GetVar('m_lang').'_Content']) { $desc = $content['l'.$this->Application->GetVar('m_lang').'_Content']; } else { $desc = $content['l'.$this->Application->GetDefaultLanguageId().'_Content']; } } return mb_substr($desc, 0, 300).(mb_strlen($desc) > 300 ? '...' : ''); } /** * Simplified version of "c:CategoryLink" for "c:PrintList" * * @param Array $params * @return string * @todo Used? Needs refactoring. */ function EnterCatLink($params) { $object =& $this->getObject($params); $url_params = Array ('pass' => 'm', 'm_cat_id' => $object->GetID()); return $this->Application->HREF($params['template'], '', $url_params); } /** * Simplified version of "c:CategoryPath", that do not use blocks for rendering * * @param Array $params * @return string * @todo Used? Maybe needs to be removed. */ function PagePath($params) { $object =& $this->getObject($params); $path = $object->GetField('CachedNavbar'); if ($path) { $items = explode('&|&', $path); array_shift($items); return implode(' -> ', $items); } return ''; } /** * Returns configuration variable value * * @param Array $params * @return string * @todo Needs to be replaced with "m:GetConfig" tag; Not used now (were used on structure_edit.tpl). */ function AllowManualFilenames($params) { return $this->Application->ConfigValue('ProjCMSAllowManualFilenames'); } /** * Draws path to current page (each page can be link to it) * * @param Array $params * @return string */ function CurrentPath($params) { $block_params = $this->prepareTagParams($params); $block_params['name'] = $block_params['render_as']; $object =& $this->Application->recallObject($this->Prefix); /* @var $object kDBItem */ $category_ids = explode('|', substr($object->GetDBField('ParentPath'), 1, -1)); $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); $language = (int)$this->Application->GetVar('m_lang'); if (!$language) { $language = 1; } $sql = 'SELECT l'.$language.'_Name AS Name, NamedParentPath FROM '.$table_name.' WHERE '.$id_field.' IN ('.implode(',', $category_ids).')'; $categories_data = $this->Conn->Query($sql); $ret = ''; foreach ($categories_data as $index => $category_data) { if ($category_data['Name'] == 'Content') { continue; } $block_params['title'] = $category_data['Name']; $block_params['template'] = preg_replace('/^Content\//i', '', $category_data['NamedParentPath']); $block_params['is_first'] = $index == 1; // because Content is 1st element $block_params['is_last'] = $index == count($categories_data) - 1; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } /** * Synonim to PrintList2 for "onlinestore" theme * * @param Array $params * @return string */ function ListPages($params) { return $this->PrintList2($params); } /** * Returns information about parser element locations in template * * @param Array $params * @return mixed */ function BlockInfo($params) { if (!EDITING_MODE) { return ''; } $template_helper =& $this->Application->recallObject('TemplateHelper'); /* @var $template_helper TemplateHelper */ return $template_helper->blockInfo( $params['name'] ); } /** * Hide all editing tabs except permission tab, when editing "Home" (ID = 0) category * * @param Array $params */ function ModifyUnitConfig($params) { $root_category = $this->Application->RecallVar('IsRootCategory_' . $this->Application->GetVar('m_wid')); if (!$root_category) { return ; } $edit_tab_presets = $this->Application->getUnitOption($this->Prefix, 'EditTabPresets'); $edit_tab_presets['Default'] = Array ( 'permissions' => $edit_tab_presets['Default']['permissions'], ); $this->Application->setUnitOption($this->Prefix, 'EditTabPresets', $edit_tab_presets); } /** * Prints catalog export templates * * @param Array $params * @return string */ function PrintCatalogExportTemplates($params) { $prefixes = explode(',', $params['prefixes']); $ret = Array (); foreach ($prefixes as $prefix) { if ($this->Application->prefixRegistred($prefix)) { $ret[$prefix] = $this->Application->getUnitOption($prefix, 'ModuleFolder') . '/export'; } } $json_helper =& $this->Application->recallObject('JSONHelper'); /* @var $json_helper JSONHelper */ return $json_helper->encode($ret); } /** * Checks, that "view in browse mode" functionality available * * @param Array $params * @return bool */ function BrowseModeAvailable($params) { $valid_special = $params['Special'] != 'user'; $not_selector = $this->Application->GetVar('type') != 'item_selector'; return $valid_special && $not_selector; } /** * Returns a link for editing product * * @param Array $params * @return string */ function ItemEditLink($params) { $object =& $this->getObject(); /* @var $object kDBList */ $edit_template = $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePath') . '/' . $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePrefix') . 'edit'; $url_params = Array ( 'm_opener' => 'd', $this->Prefix.'_mode' => 't', $this->Prefix.'_event' => 'OnEdit', $this->Prefix.'_id' => $object->GetID(), 'm_cat_id' => $object->GetDBField('ParentId'), 'pass' => 'all,'.$this->Prefix, 'no_pass_through' => 1, ); return $this->Application->HREF($edit_template,'', $url_params); } function RelevanceIndicator($params) { $object =& $this->getObject($params); $search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search'; $sql = 'SELECT Relevance FROM '.$search_results_table.' WHERE ResourceId = '.$object->GetDBField('ResourceId'); $percents_off = (int)(100 - (100 * $this->Conn->GetOne($sql))); $percents_off = ($percents_off < 0) ? 0 : $percents_off; if ($percents_off) { $params['percent_off'] = $percents_off; $params['percent_on'] = 100 - $percents_off; $params['name'] = $this->SelectParam($params, 'relevance_normal_render_as,block_relevance_normal'); } else { $params['name'] = $this->SelectParam($params, 'relevance_full_render_as,block_relevance_full'); } return $this->Application->ParseBlock($params); } } \ No newline at end of file Index: branches/5.0.x/core/units/helpers/mod_rewrite_helper.php =================================================================== --- branches/5.0.x/core/units/helpers/mod_rewrite_helper.php (revision 12970) +++ branches/5.0.x/core/units/helpers/mod_rewrite_helper.php (revision 12971) @@ -1,994 +1,994 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.org/license for copyright notices and details. */ defined('FULL_PATH') or die('restricted access!'); class kModRewriteHelper extends kHelper { /** * Holds a refererence to httpquery * * @var kHttpQuery */ var $HTTPQuery = null; /** * Parts found during url parsing * * @var Array */ var $_partsFound = Array (); /** * Category item prefix, that was found * * @var string */ var $_modulePrefix = false; /** * Template aliases for current theme * * @var Array */ var $_templateAliases = null; /** * Constructor of kModRewriteHelper class * * @return kModRewriteHelper */ function kModRewriteHelper() { parent::kHelper(); $this->HTTPQuery =& $this->Application->recallObject('HTTPQuery'); } function processRewriteURL() { $passed = Array (); $url = $this->HTTPQuery->Get('_mod_rw_url_'); if (substr($url, -5) == '.html') { $url = substr($url, 0, strlen($url) - 5); } $restored = false; $sql = 'SELECT Data, Cached FROM ' . TABLE_PREFIX . 'Cache WHERE VarName = "mod_rw_' . md5($url) . '"'; $cache = $this->Conn->GetRow($sql); if (false && $cache && $cache['Cached'] > 0) { // not used for now $cache = unserialize($cache['Data']); $vars = $cache['vars']; $passed = $cache['passed']; $restored = true; } else { $vars = $this->parseRewriteURL($url); $passed = $vars['pass']; // also used in bottom of this method unset($vars['pass']); $cache = Array ('vars' => $vars, 'passed' => $passed); $fields_hash = Array ( 'VarName' => 'mod_rw_' . md5($url), 'Data' => serialize($cache), 'Cached' => adodb_mktime(), ); $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE'); if (array_key_exists('t', $this->HTTPQuery->Post) && $this->HTTPQuery->Post['t']) { // template from POST overrides template from URL. $vars['t'] = $this->HTTPQuery->Post['t']; if (isset($vars['is_virtual']) && $vars['is_virtual']) { $vars['m_cat_id'] = 0; // this is virtual template category (for Proj-CMS) } } unset($vars['is_virtual']); } foreach ($vars as $name => $value) { $this->HTTPQuery->Set($name,$value); } // if ($restored) { $this->InitAll(); // } $this->HTTPQuery->finalizeParsing($passed); } function parseRewriteURL($url) { $sql = 'SELECT Data, Cached FROM ' . TABLE_PREFIX . 'Cache WHERE VarName = "mod_rw_' . md5($url) . '"'; $vars = $this->Conn->GetRow($sql); if (false && $vars && $vars['Cached'] > 0) { // not used for now $vars = unserialize($menu['Data']); return $vars; } $vars = Array ('pass' => Array ('m')); $url_parts = $url ? explode('/', trim(mb_strtolower($url, 'UTF-8'), '/')) : Array (); if (($this->HTTPQuery->Get('rewrite') == 'on') || !$url_parts) { $this->_setDefaultValues($vars); } if (!$url_parts) { $this->InitAll(); $vars['t'] = $this->HTTPQuery->getDefaultTemplate(''); return $vars; } else { $vars['t'] = ''; } $this->_parseLanguage($url_parts, $vars); $this->_parseTheme($url_parts, $vars); // http://site-url/<language>/<theme>/<category>[_<category_page>]/<template>/<module_page> // http://site-url/<language>/<theme>/<category>[_<category_page>]/<module_page> (category-based section template) // http://site-url/<language>/<theme>/<category>[_<category_page>]/<template>/<module_item> // http://site-url/<language>/<theme>/<category>[_<category_page>]/<module_item> (category-based detail template) // http://site-url/<language>/<theme>/<rl_injections>/<category>[_<category_page>]/<rl_part> (customized url) if ( $this->processRewriteListeners($url_parts, $vars) ) { return $vars; } if ($this->_parsePhisycalTemplate($url_parts, $vars)) { $this->_partsFound[] = 'parsePhisycalTemplate'; } if (($this->_modulePrefix === false) && in_array('parseCategory', $this->_partsFound)) { // no item found, but category found -> module index page foreach ($this->Application->RewriteListeners as $prefix => $listener) { // no idea what module we are talking about, so pass info form all modules $vars['pass'][] = $prefix; } return $vars; } if (!$this->_partsFound) { $not_found = $this->Application->ConfigValue('ErrorTemplate'); $vars['t'] = $not_found ? $not_found : 'error_notfound'; $themes_helper =& $this->Application->recallObject('ThemesHelper'); /* @var $themes_helper kThemesHelper */ $vars['m_cat_id'] = $themes_helper->getPageByTemplate($vars['t'], $vars['m_theme']); header('HTTP/1.0 404 Not Found'); } return $vars; } function InitAll() { $this->Application->VerifyLanguageId(); $this->Application->Phrases->Init('phrases'); $this->Application->VerifyThemeId(); } /** * Processes url using rewrite listeners * * @param Array $url_parts * @param Array $vars * @return bool */ function processRewriteListeners(&$url_parts, &$vars) { $this->initRewriteListeners(); $page_number = $this->_parsePage($url_parts, $vars); if ($page_number) { $this->_partsFound[] = 'parsePage'; } foreach ($this->Application->RewriteListeners as $prefix => $listener) { // set default page $vars[$prefix . '_Page'] = 1; // will override page in session in case, when none is given in url if ($page_number) { // page given in url - use it $vars[$prefix . '_id'] = 0; $vars[$prefix . '_Page'] = $page_number; } $listener_result = $listener[0]->$listener[1](REWRITE_MODE_PARSE, $prefix, $vars, $url_parts); if ($listener_result === false) { // will not proceed to other methods return true; } } // will proceed to other methods return false; } /** * Parses real template name from url * * @param Array $url_parts * @param Array $vars * @return bool */ function _parsePhisycalTemplate($url_parts, &$vars) { if (!$url_parts) { return false; } do { $template_path = implode('/', $url_parts); $physical_template = array_search($template_path, $this->Application->structureTemplateMapping); if ($physical_template !== false) { // replace menu template name with it's actual template name on disk list ($template_path) = explode(':', $physical_template, 2); } $t_parts['path'] = dirname($template_path) == '.' ? '' : '/' . dirname($template_path); $t_parts['file'] = basename($template_path); $sql = 'SELECT FileId FROM ' . TABLE_PREFIX . 'ThemeFiles WHERE (ThemeId = ' . $vars['m_theme'] . ') AND (FilePath = ' . $this->Conn->qstr($t_parts['path']) . ') AND (FileName = ' . $this->Conn->qstr($t_parts['file'] . '.tpl') . ')'; $template_found = $this->Conn->GetOne($sql); if (!$template_found) { array_shift($url_parts); } } while (!$template_found && $url_parts); if ($template_found) { $vars['t'] = $template_path; // 1. will damage actual category during category item review add process // 2. will use "use_section" parameter of "m_Link" tag to gain same effect // $themes_helper =& $this->Application->recallObject('ThemesHelper'); // /* @var $themes_helper kThemesHelper */ // // $vars['m_cat_id'] = $themes_helper->getPageByTemplate($template_path, $vars['m_theme']); return true; } return false; } /** * 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. */ function MainRewriteListener($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; } if ($this->_parseCategory($url_parts, $params)) { $this->_partsFound[] = 'parseCategory'; } return true; } /** * Build main part of every url * * @param string $prefix_special * @param Array $params * @param bool $keep_events * @return string */ function _buildMainUrl($prefix_special, &$params, $keep_events) { $ret = ''; list ($prefix) = explode('.', $prefix_special); $processed_params = $this->getProcessedParams($prefix_special, $params, $keep_events); if ($processed_params === false) { return ''; } // add language $default_language_id = $this->Application->GetDefaultLanguageId(); if ($processed_params['m_lang'] && ($processed_params['m_lang'] != $default_language_id)) { $language_name = $this->Application->getCache('language_names', $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', $processed_params['m_lang'], $language_name); } $ret .= $language_name . '/'; } // add theme - $default_theme_id = $this->Application->GetDefaultThemeId(); + $default_theme_id = $this->Application->GetDefaultThemeId(true); if ($processed_params['m_theme'] && ($processed_params['m_theme'] != $default_theme_id)) { $theme_name = $this->Application->getCache('theme_names', $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', $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->getFilename('c', $processed_params['m_cat_id']); 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/<template_path>" 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->getCache('category_designs', $processed_params['m_cat_id']) : ''; 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 if (($template == $category_template) || (mb_strtolower($template) == '__default__')) { // given template is also default template for this category or '__default__' given $params['pass_template'] = false; } if ($template && $params['pass_template']) { $ret .= $template . '/'; } return mb_strtolower( rtrim($ret, '/') ); } /** * Gets language part from url * * @param Array $url_parts * @param Array $vars * @return bool */ function _parseLanguage(&$url_parts, &$vars) { if (!$url_parts) { return false; } $url_part = reset($url_parts); $sql = 'SELECT LanguageId, IF(LOWER(PackName) = ' . $this->Conn->qstr($url_part) . ', 2, PrimaryLang) AS SortKey FROM ' . TABLE_PREFIX . 'Language WHERE Enabled = 1 ORDER BY SortKey DESC'; $language_info = $this->Conn->GetRow($sql); $this->Application->Phrases = new PhrasesCache(); if ($language_info && $language_info['LanguageId'] && $language_info['SortKey']) { // primary language will be selected in case, when $url_part doesn't match to other's language pack name // don't use next enabled language, when primary language is disabled $vars['m_lang'] = $language_info['LanguageId']; if ($language_info['SortKey'] == 2) { // language was found by pack name array_shift($url_parts); } return true; } return false; } /** * Gets theme part from url * * @param Array $url_parts * @param Array $vars * @return bool */ function _parseTheme(&$url_parts, &$vars) { if (!$url_parts) { return false; } $url_part = reset($url_parts); $sql = 'SELECT ThemeId, IF(LOWER(Name) = ' . $this->Conn->qstr($url_part) . ', 2, PrimaryTheme) AS SortKey, TemplateAliases FROM ' . TABLE_PREFIX . 'Theme WHERE Enabled = 1 ORDER BY SortKey DESC'; $theme_info = $this->Conn->GetRow($sql); if ($theme_info && $theme_info['ThemeId'] && $theme_info['SortKey']) { // primary theme will be selected in case, when $url_part doesn't match to other's theme name // don't use next enabled theme, when primary theme is disabled $vars['m_theme'] = $theme_info['ThemeId']; if ($theme_info['TemplateAliases']) { $this->_templateAliases = unserialize($theme_info['TemplateAliases']); } else { $this->_templateAliases = Array (); } if ($theme_info['SortKey'] == 2) { // theme was found by name array_shift($url_parts); } return true; } $vars['m_theme'] = 0; // required, because used later for category/template detection return false; } /** * Checks if whole url_parts matches a whole In-CMS page * * @param array $url_parts * @return boolean */ 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); if ($friendly) { $vars['m_cat_id'] = $friendly['CategoryId']; $vars['t'] = preg_replace('/^Content\//i', '', $friendly['NamedParentPath']); return true; } return false; } /** * Set's page (when found) to all modules * * @param Array $url_parts * @param Array $vars * @return string * * @todo Should find a way, how to determine what rewrite listerner page is it */ function _parsePage(&$url_parts, &$vars) { if (!$url_parts) { return false; } $page_number = end($url_parts); if (!is_numeric($page_number)) { return false; } array_pop($url_parts); return $page_number; } /** * Remove page numbers for all rewrite listeners * * @todo Should find a way, how to determine what rewrite listerner page is it */ function removePages() { foreach ($this->Application->RewriteListeners as $prefix => $listener) { $this->Application->DeleteVar($prefix . '_Page'); } } /** * Extracts category part from url * * @param Array $url_parts * @param Array $vars * @return bool */ 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'; do { $category_path = trim($category_path . '/' . $url_part, '/'); // bb_<topic_id> -> 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 Status IN (1,4) AND (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; $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; } /** * Builds/parses category item 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 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. */ function CategoryItemRewriteListener($rewrite_mode = REWRITE_MODE_BUILD, $prefix, &$params, &$url_parts, $keep_events = false) { static $parsed = false; if ($rewrite_mode == REWRITE_MODE_BUILD) { return $this->_buildCategoryItemUrl($prefix, $params, $keep_events); } if (!$parsed) { $this->_modulePrefix = $this->_parseCategoryItemUrl($url_parts, $params); if ($this->_modulePrefix !== false) { $params['pass'][] = $this->_modulePrefix; $this->_partsFound[] = 'parseCategoryItemUrl'; } $parsed = true; } return true; } /** * Build category teim part of url * * @param string $prefix_special * @param Array $params * @param bool $keep_events * @return string */ function _buildCategoryItemUrl($prefix_special, &$params, $keep_events) { $ret = ''; list ($prefix) = explode('.', $prefix_special); $processed_params = $this->getProcessedParams($prefix_special, $params, $keep_events); if ($processed_params === false) { return ''; } if ($processed_params[$prefix_special . '_id']) { // this allows to fill 3 cache records with one query (see this method for details) $category_id = array_key_exists('m_cat_id', $params) ? $params['m_cat_id'] : $this->Application->GetVar('m_cat_id'); $category_filename = $this->Application->getFilename('c', $category_id); // if template is also item template of category, then remove template $template = array_key_exists('t', $params) ? $params['t'] : false; $item_template = $this->GetItemTemplate($category_id, $prefix); if ($template == $item_template || strtolower($template) == '__default__') { // given template is also default template for this category item or '__default__' given $params['pass_template'] = false; } // get item's filename if ($prefix == 'bb') { $ret .= 'bb_' . $processed_params[$prefix_special . '_id'] . '/'; } else { $filename = $this->Application->getFilename($prefix, $processed_params[$prefix_special . '_id'], $category_id); if ($filename !== false) { $ret .= $filename . '/'; } } } else { if ($processed_params[$prefix_special . '_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 $params['pass_category'] = true; } else { $ret .= $processed_params[$prefix_special . '_Page'] . '/'; } } return mb_strtolower( rtrim($ret, '/') ); } /** * Sets template and id, corresponding to category item given in url * * @param Array $url_parts * @param Array $vars * @return bool|string */ function _parseCategoryItemUrl(&$url_parts, &$vars) { if (!$url_parts) { return false; } $item_filename = end($url_parts); if (is_numeric($item_filename)) { // this page, don't process here return false; } if (preg_match('/^bb_([\d]+)/', $item_filename, $regs)) { // process topics separatly, because they don't use item filenames array_pop($url_parts); return $this->_parseTopicUrl($regs[1], $vars); } // locating the item in CategoryItems by filename to detect its ItemPrefix and its category ParentPath $sql = 'SELECT ci.ItemResourceId, ci.ItemPrefix, c.ParentPath, ci.CategoryId FROM ' . TABLE_PREFIX . 'CategoryItems AS ci LEFT JOIN ' . TABLE_PREFIX . 'Category AS c ON c.CategoryId = ci.CategoryId WHERE (ci.CategoryId = ' . (int)$vars['m_cat_id'] . ') AND (ci.Filename = ' . $this->Conn->qstr($item_filename) . ')'; $cat_item = $this->Conn->GetRow($sql); if ($cat_item !== false) { // item found $module_prefix = $cat_item['ItemPrefix']; $item_template = $this->GetItemTemplate($cat_item, $module_prefix); // converting ResourceId to correpsonding Item id $module_config = $this->Application->getUnitOptions($module_prefix); $sql = 'SELECT ' . $module_config['IDField'] . ' FROM ' . $module_config['TableName'] . ' WHERE ResourceId = ' . $cat_item['ItemResourceId']; $item_id = $this->Conn->GetOne($sql); array_pop($url_parts); if ($item_id) { if ($item_template) { // when template is found in category -> set it $vars['t'] = $item_template; } // we have category item id $vars[$module_prefix . '_id'] = $item_id; return $module_prefix; } } return false; } /** * Set's template and topic id corresponding to topic given in url * * @param int $topic_id * @param Array $vars * @return string */ function _parseTopicUrl($topic_id, &$vars) { $sql = 'SELECT c.ParentPath, c.CategoryId FROM ' . TABLE_PREFIX . 'Category AS c WHERE c.CategoryId = ' . (int)$vars['m_cat_id']; $cat_item = $this->Conn->GetRow($sql); $item_template = $this->GetItemTemplate($cat_item, 'bb'); if ($item_template) { $vars['t'] = $item_template; } $vars['bb_id'] = $topic_id; return 'bb'; } /** * Returns enviroment variable values for given prefix (uses directly given params, when available) * * @param string $prefix_special * @param Array $params * @param bool $keep_events * @return Array */ function getProcessedParams($prefix_special, &$params, $keep_events) { list ($prefix) = explode('.', $prefix_special); $query_vars = $this->Application->getUnitOption($prefix, 'QueryString'); if (!$query_vars) { // given prefix doesn't use "env" variable to pass it's data return false; } $event_key = array_search('event', $query_vars); if ($event_key) { // pass through event of this prefix unset($query_vars[$event_key]); } if (array_key_exists($prefix_special . '_event', $params) && !$params[$prefix_special . '_event']) { // if empty event, then remove it from url unset( $params[$prefix_special . '_event'] ); } // if pass events is off and event is not implicity passed if (!$keep_events && !array_key_exists($prefix_special . '_event', $params)) { unset($params[$prefix_special . '_event']); // remove event from url if requested //otherwise it will use value from get_var } $processed_params = Array (); 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; $processed_params[$var_name] = array_key_exists($var_name, $params) ? $params[$var_name] : $this->Application->GetVar($var_name); if (array_key_exists($var_name, $params)) { unset($params[$var_name]); } } return $processed_params; } /** * Returns module item details template specified in given category custom field for given module prefix * * @param int|Array $category * @param string $module_prefix * @return string */ function GetItemTemplate($category, $module_prefix) { $cache_key = serialize($category) . '_' . $module_prefix; $cached_value = $this->Application->getCache(__CLASS__ . __FUNCTION__, $cache_key); if ($cached_value !== false) { return $cached_value; } if (!is_array($category)) { if ($category == 0) { $category = $this->Application->findModule('Var', $module_prefix, 'RootCat'); } $sql = 'SELECT c.ParentPath, c.CategoryId FROM ' . TABLE_PREFIX . 'Category AS c WHERE c.CategoryId = ' . $category; $category = $this->Conn->GetRow($sql); } $parent_path = implode(',',explode('|', substr($category['ParentPath'], 1, -1))); // item template is stored in module' system custom field - need to get that field Id $primary_lang = $this->Application->GetDefaultLanguageId(); $item_template_field_id = $this->getItemTemplateCustomField($module_prefix); // looking for item template through cats hierarchy sorted by parent path $query = ' SELECT ccd.l' . $primary_lang . '_cust_' . $item_template_field_id . ', FIND_IN_SET(c.CategoryId, ' . $this->Conn->qstr($parent_path) . ') AS Ord1, c.CategoryId, c.Name, ccd.l' . $primary_lang . '_cust_' . $item_template_field_id . ' FROM ' . TABLE_PREFIX . 'Category AS c LEFT JOIN ' . TABLE_PREFIX . 'CategoryCustomData AS ccd ON ccd.ResourceId = c.ResourceId WHERE c.CategoryId IN (' . $parent_path . ') AND ccd.l' . $primary_lang . '_cust_' . $item_template_field_id . ' != \'\' ORDER BY FIND_IN_SET(c.CategoryId, ' . $this->Conn->qstr($parent_path) . ') DESC'; $item_template = $this->Conn->GetOne($query); if (!isset($this->_templateAliases)) { // when empty url OR mod-rewrite disabled $themes_helper =& $this->Application->recallObject('ThemesHelper'); /* @var $themes_helper kThemesHelper */ $sql = 'SELECT TemplateAliases FROM ' . TABLE_PREFIX . 'Theme WHERE ThemeId = ' . (int)$themes_helper->getCurrentThemeId(); $template_aliases = $this->Conn->GetOne($sql); $this->_templateAliases = $template_aliases ? unserialize($template_aliases) : Array (); } if ($item_template && array_key_exists($item_template, $this->_templateAliases)) { $item_template = $this->_templateAliases[$item_template]; } $this->Application->setCache(__CLASS__ . __FUNCTION__, $cache_key, $item_template); return $item_template; } /** * Loads all registered rewrite listeners, so they could be quickly accessed later * */ function initRewriteListeners() { static $init_done = false; if ($init_done) { return ; } foreach ($this->Application->RewriteListeners as $prefix => $listener_data) { list ($listener_prefix, $listener_method) = explode(':', $listener_data['listener']); $listener =& $this->Application->recallObject($listener_prefix); $this->Application->RewriteListeners[$prefix] = Array (&$listener, $listener_method); } $init_done = true; } /** * Returns category custom field id, where given module prefix item template name is stored * * @param string $module_prefix * @return int */ function getItemTemplateCustomField($module_prefix) { $cached_value = $this->Application->getCache(__CLASS__ . __FUNCTION__, $module_prefix); if ($cached_value !== false) { return $cached_value; } $sql = 'SELECT CustomFieldId FROM ' . TABLE_PREFIX . 'CustomField WHERE FieldName = ' . $this->Conn->qstr($module_prefix . '_ItemTemplate'); $item_template_field_id = $this->Conn->GetOne($sql); $this->Application->setCache(__CLASS__ . __FUNCTION__, $module_prefix, $item_template_field_id); return $item_template_field_id; } /** * Sets default parsed values before actual url parsing * * @param Array $vars */ function _setDefaultValues(&$vars) { $defaults = Array ('m_cat_id' => 0, 'm_cat_page' => 1, 'm_opener' => 's', 't' => 'index'); foreach ($defaults as $default_key => $default_value) { // bug: null is never returned if ($this->HTTPQuery->Get($default_key) == null) { $vars[$default_key] = $default_value; } } } }