Index: branches/RC/core/units/categories/categories_tag_processor.php =================================================================== diff -u -r11368 -r11495 --- branches/RC/core/units/categories/categories_tag_processor.php (.../categories_tag_processor.php) (revision 11368) +++ branches/RC/core/units/categories/categories_tag_processor.php (.../categories_tag_processor.php) (revision 11495) @@ -2,6 +2,20 @@ class CategoriesTagProcessor extends kDBTagProcessor { + /** + * Cached version of site menu + * + * @var Array + */ + var $Menu = null; + + /** + * Parent path mapping used in CachedMenu tag + * + * @var Array + */ + var $ParentPaths = Array (); + function SubCatCount($params) { $object =& $this->getObject($params); @@ -62,16 +76,20 @@ return parent::ItemIcon($params); } - $object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params); - $status = $object->GetDBField('Status'); - if($status == 1) - { - $ret = $object->GetDBField('IsNew') ? 'icon16_cat_new.gif' : 'icon16_cat.gif'; + $object =& $this->getObject($params); + if ($object->GetDBField('IsMenu')) { + $status = $object->GetDBField('Status'); + if ($status == 1) { + $ret = $object->GetDBField('IsNew') ? 'icon16_cat_new.gif' : 'icon16_folder.gif'; + } + else { + $ret = $status ? 'icon16_cat_pending.gif' : 'icon16_cat_disabled.gif'; + } } - else - { - $ret = $status ? 'icon16_cat_pending.gif' : 'icon16_cat_disabled.gif'; + else { + $ret = 'icon16_folder-red.gif'; } + return $ret; } @@ -156,6 +174,18 @@ 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'); @@ -179,7 +209,7 @@ if (isset($cache[$category_id])) { //check if sym. link category is valid - $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); + $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); $sql = 'SELECT '.$id_field.' @@ -196,25 +226,25 @@ { $category_id = getArrayValue($params, 'cat_id'); - if ($category_id === false) { - $category_id = $this->Application->GetVar($this->getPrefixSpecial().'_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'); - } + 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($category_id); + $category_id = $this->getCategorySymLink($category_id); - unset($params['cat_id'], $params['module']); + 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); + $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); + return $this->Application->ProcessParsedTag('m', 't', $params); } function CategoryList($params) @@ -252,7 +282,7 @@ function Meta($params) { - $object =& $this->Application->recallObject($this->Prefix.'.-item'); + $object =& $this->Application->recallObject($this->Prefix); // .'.-item' /* @var $object CategoriesItem */ $meta_type = $params['name']; @@ -272,8 +302,8 @@ /* @var $mod_rewrite_helper kModRewriteHelper */ $category_params = Array ( - 'CategoryId' => $object->GetID(), - 'ParentPath' => $object->GetDBField('ParentPath'), + 'CategoryId' => $object->GetID(), + 'ParentPath' => $object->GetDBField('ParentPath'), ); $item_template = $mod_rewrite_helper->GetItemTemplate($category_params, $module_info['Var']); @@ -335,6 +365,7 @@ // because there can be many category lists on same page $list_unique_key .= $parent_cat_id; } + if ($list_unique_key == '') { return parent::BuildListSpecial($params); } @@ -368,8 +399,10 @@ $wid = $this->Application->GetVar('m_wid'); list($index_file, $env) = explode('|', $this->Application->RecallVar(rtrim('last_template_'.$wid, '_')), 2); - $this->Application->SetVar(ENV_VAR_NAME, str_replace('%5C', '\\', $env)); - $this->Application->HttpQuery->processQueryString(); + $vars = $this->Application->HttpQuery->processQueryString( str_replace('%5C', '\\', $env) ); + foreach ($vars as $var_name => $var_value) { + $this->Application->SetVar($var_name, $var_value); + } // update required fields $this->Application->SetVar('m_cat_id', $category_id); @@ -518,6 +551,19 @@ return $object->IsRoot(); } + /** + * Used for disabling "Home" and "Up" buttons in category list + * + * @param Array $params + * @return bool + */ + function ModuleRootCategory($params) + { + $root_category = $this->Application->findModule('Name', 'Proj-CMS', 'RootCat'); + + return $this->Application->GetVar('m_cat_id') == $root_category; + } + function CatalogItemCount($params) { $object =& $this->GetList($params); @@ -570,28 +616,56 @@ 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) { - $cat_id = isset($params['cat_id']) && $params['cat_id'] ? $params['cat_id'] : false; - if ($cat_id === false) { - // category not supplied -> get current from PrintList - $cat_id = $this->Application->GetVar($this->getPrefixSpecial().'_id'); - $current_cat =& $this->getObject($params); + static $current_path = null; + + if (!isset($current_path)) { + $sql = 'SELECT ParentPath + FROM ' . TABLE_PREFIX . 'Category + WHERE CategoryId = ' . $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 { - if ("$cat_id" == 'Root') { - $cat_id = $this->Application->findModule('Name', $params['module'], 'RootCat'); + $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); } - $current_cat =& $this->Application->recallObject($this->Prefix.'.-c'.$cat_id, $this->Prefix, Array ('skip_autoload' => true)); - $current_cat->Load($cat_id); - } + 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'); + } - $current_path = $current_cat->GetDBField('ParentPath'); - static $parent_path = null; - if (!isset($parent_path)) { - $parent_path = $this->Conn->GetOne('SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$this->Application->GetVar('m_cat_id')); + $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($parent_path, $current_path) !== false; + + return strpos($current_path, $test_path) !== false; } /** @@ -632,36 +706,36 @@ */ function LastUpdated($params) { - $category_id = $this->Application->GetVar('m_cat_id'); - $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); + $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 + $sql = 'SELECT TreeLeft, TreeRight FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$category_id; - $tree_info = $this->Conn->GetRow($sql); + $tree_info = $this->Conn->GetRow($sql); - $sql = 'SELECT MAX(c.Modified) AS ModDate, MAX(c.CreatedOn) AS NewDate + $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 ''; - } + $row_data = $this->Conn->GetRow($sql); + if (!$row_data) { + return ''; + } - $date = $row_data[ $row_data['NewDate'] > $row_data['ModDate'] ? 'NewDate' : 'ModDate' ]; + $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)) { + // 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 @@ -826,8 +900,8 @@ if (is_object($result)) { // webservice responded -> save in local database $fields_hash = Array ( - 'MisspelledWord' => $keywords, - 'SuggestedCorrection' => $result->Data, + 'MisspelledWord' => $keywords, + 'SuggestedCorrection' => $result->Data, ); $this->Conn->doInsert($fields_hash, $table_name); @@ -852,14 +926,6 @@ return $this->Application->ProcessParsedTag('m', 'Link', $params); } - function PageBrowseLink($params) - { - $object =& $this->Application->recallObject( $this->getPrefixSpecial(), $this->Prefix, $params ); - $template = $object->GetDBField('NamedParentPath'); - $url_params = Array('admin' => 1, 'pass' => 'm', 'index_file' => 'index.php'); - return $this->Application->HREF($template,'_FRONT_END_', $url_params); - } - function InitCatalogTab($params) { $tab_params['mode'] = $this->Application->GetVar('tm'); // single/multi selection possible @@ -917,6 +983,868 @@ } 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'); + } + + if (strtolower($page->GetDBField('NamedParentPath')) != strtolower('Content/'.$template)) { + // load, when used page object doesn't match requested page object + $page->Load('Content/'.$template, 'NamedParentPath'); + } + + 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(); + + $data = Array ('PageId' => $page_id, 'ContentNum' => $num); + $content =& $this->Application->recallObject('content.-block', null, Array ('skip_autoload' => true)); + /* @var $content kDBItem */ + + $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 = ''; + if (EDITING_MODE == EDITING_MODE_CMS) { + $bg_color = isset($params['bgcolor']) ? $params['bgcolor'] : '#ffffff'; + $url_params = Array ( + 'pass' => 'm,st,content', + 'm_opener' => 'd', + 'st_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 + ); + + if (isset($params['float'])) { + $pos_float = 'position: relative; float: '.$params['float'].';'; + } + else { + $pos_float = 'width: auto; position: absolute;'; + } + + // link from Front-End to admin, don't remove "index.php" + $edit_url = $this->Application->HREF('in-edit/pages/content_edit', ADMIN_DIRECTORY, $url_params, 'index.php'); + $button_css = 'font-family: Arial, Verdana; font-size: 9pt; '.$pos_float.' z-index: 99; background-color: #F7C300; color: #CE0031; border: 1px solid #CE0031; padding: 1px 10px 1px 10px; cursor: pointer;'; + $edit_code = '
Edit
'; + + if (isset($params['forms_later']) && $params['forms_later']) { + $tmp = $edit_code; + $edit_code = ''; + } + $edit_code .= '
'; + $edit_code .= ''; + $edit_code .= ''; + $edit_code .= ''; + $edit_code .= ''; + $edit_code .= ''; + $edit_code .= '
'; + if (isset($params['forms_later']) && $params['forms_later']) { + $all_forms = $this->Application->GetVar('all_forms'); + $all_forms .= $edit_code; + $this->Application->SetVar('all_forms', $all_forms); + $edit_code = $tmp; + } + } + + if ($this->Application->GetVar('_editor_preview_') == 1) { + $data = $this->Application->RecallVar('_editor_preview_content_'); + } else { + $data = $content->GetField('Content'); + } + + return $edit_code . $this->_replacePageIds($data); + } + + /** + * Replace links like "@@ID@@" to actual template names in given text + * + * @param string $text + * @return string + */ + function _replacePageIds($text) + { + if (!preg_match_all('/@@(\\d+)@@/', $text, $regs)) { + return $text; + } + + $page_ids = $regs[1]; + + $sql = 'SELECT NamedParentPath, CategoryId + FROM ' . TABLE_PREFIX . 'Category + WHERE CategoryId IN (' . implode(',', $page_ids) . ')'; + + $templates = $this->Conn->GetCol($sql, 'CategoryId'); + + foreach ($page_ids as $page_id) { + $text = preg_replace('/@@' . $page_id . '@@/', $this->Application->HREF($templates[$page_id], '', Array ('pass' => 'm')), $text); + } + + return $text; + } + + /** + * 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; + } + + /** + * Prints "Edit Page" button on cms page + * + * @param Array $params + * @return string + */ + function EditPage($params) + { + if (!EDITING_MODE) { + return ''; + } + + $page =& $this->_getPage($params); + + $url_params = Array( + 'pass' => 'm,st', + 'm_opener' => 'd', + 'st_id' => $page->GetID(), + 'st_mode' => 't', + // 'st_event' => 'OnEdit', + 'front' => 1, + '__URLENCODE__' => 1, + '__NO_REWRITE__'=> 1, + 'escape' => 1, + 'index_file' => 'index.php', + ); + + $edit_url = $this->Application->HREF('proj-cms/structure/structure_edit', '/admin', $url_params); + $button_css = 'position: absolute; z-index: 1; top: 1; left 1; font-family: Arial, Verdana; font-size: 9px; background-color: #F7C300; color: #CE0031; border: 1px solid #CE0031; width: auto; padding: 2px 10px 2px 10px; cursor: pointer;'; + $edit_code = '
Page Properties'; + $title = $this->PageInfo(array('type' => 'htmlhead_title')); + + $edit_code .= '
'; + $edit_code .= ''; + $edit_code .= ''; + $edit_code .= '
'; + + if (!$this->Application->GetVar('admin_scripts_included')) { + $this->Application->SetVar('admin_script_included', 1); + $edit_code .= ''; + $edit_code .= ''; + $edit_code .= ''; + $edit_code .= ''; + } + + /*$browse_url = $this->Application->HREF('index', '/admin', array('m_cat_id'=>1,'m_theme'=>'','admin' => 1, 'pass' => 'm', 'm_opener' => 'r'), '../index.php'); + + $edit_code .= ' +
'."\n";*/ + + $edit_code .= ''."\n"; + + return $edit_code; + } + + /** + * Builds cached menu version + * + * @return Array + */ + function _prepareMenu() + { + static $root_cat = null; + static $root_path = null; + + if (!$root_cat) { + $root_cat = $this->Application->ModuleInfo['Proj-CMS']['RootCat']; + $root_path = $this->Conn->GetOne('SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$root_cat); + } + + if (!$this->Menu) { + $menu = $this->Conn->GetRow('SELECT Data, Cached FROM '.TABLE_PREFIX.'Cache WHERE VarName = "cms_menu"'); + if ($menu && $menu['Cached'] > 0) { + $menu = unserialize($menu['Data']); + $this->ParentPaths = $menu['ParentPaths']; + } + else { + $menu = $this->_altBuildMenuStructure(array('CategoryId' => $root_cat, 'ParentPath' => $root_path)); + $menu['ParentPaths'] = $this->ParentPaths; + $this->Conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("cms_menu", '.$this->Conn->qstr(serialize($menu)).', '.adodb_mktime().')'); + } + unset($menu['ParentPaths']); + $this->Menu = $menu; + } + + return Array ($this->Menu, $root_path); + } + + /** + * Returns category id based tag parameters + * + * @param Array $params + * @return int + */ + function _getCategoryId($params) + { + $cat = isset($params['category_id']) && $params['category_id'] != '' ? $params['category_id'] : $this->Application->GetVar('m_cat_id'); + if ("$cat" == 'parent') { + $this_category =& $this->Application->recallObject('c'); + /* @var $this_category kDBItem */ + + $cat = $this_category->GetDBField('ParentId'); + } + else if ($cat == 0) { + $cat = $this->Application->ModuleInfo['Proj-CMS']['RootCat']; + } + + return $cat; + } + + /** + * Prepares cms menu item block parameters + * + * @param Array $page + * @param int $real_cat_id + * @param string $root_path + * @return Array + */ + function _prepareMenuItem($page, $real_cat_id, $root_path) + { + static $language_id = null; + static $primary_language_id = null; + + if (!isset($language_id)) { + $language_id = $this->Application->GetVar('m_lang'); + $primary_language_id = $this->Application->GetDefaultLanguageId(); + } + + $title = $page['l'.$language_id.'_ItemName'] ? $page['l'.$language_id.'_ItemName'] : $page['l'.$primary_language_id.'_ItemName']; + $active = false; + $category_active = false; + + if ($page['ItemType'] == 'cat') { + if ( isset($this->ParentPaths[$real_cat_id])) { + $active = strpos($this->ParentPaths[$real_cat_id], $page['ParentPath']) !== false; + } + $category_active = $page['CategoryId'] == $real_cat_id; + } + + if ($page['ItemType'] == 'cat_index') { + $check_path = str_replace($root_path, '', $page['ParentPath']); + $active = strpos($parent_path, $check_path) !== false; + } + + if ($page['ItemType'] == 'page') { + $active = $page['ItemPath'] == preg_replace('/^Content\//', '', $this->Application->GetVar('t')); + } + + $block_params = Array ( + 'title'=> $title, + 'template'=> preg_replace('/^Content\//', '', $page['ItemPath']), + 'active'=>$active, + 'category_active' => $category_active, // new + 'parent_path'=>$page['ParentPath'], + 'parent_id'=>$page['ParentId'], + 'cat_id'=>$page['CategoryId'], + 'is_index'=>$page['IsIndex'], + 'item_type'=>$page['ItemType'], + 'page_id'=>$page['ItemId'], + 'has_sub_menu' => isset($page['sub_items']) && count($page['sub_items']) > 0, + 'external_url' => $page['UseExternalUrl'] ? $page['ExternalUrl'] : false, + 'menu_icon' => $page['UseMenuIconUrl'] ? $page['MenuIconUrl'] : false, + + ); + + return $block_params; + } + + /** + * Builds site menu + * + * @param Array $params + * @return string + */ + function CachedMenu($params) + { + list ($menu, $root_path) = $this->_prepareMenu(); + $cat = $this->_getCategoryId($params); + + $parent_path = isset($this->ParentPaths[$cat]) ? $this->ParentPaths[$cat] : ''; + $parent_path = str_replace($root_path, '', $parent_path); //menu starts from module path + $levels = explode('|',trim($parent_path,'|')); + if ($levels[0] === '') $levels = array(); + if (isset($params['level']) && $params['level'] > count($levels)) return ; + + $level = max(isset($params['level']) ? $params['level']-1 : count($levels)-1, 0); + $parent = isset($levels[$level]) ? $levels[$level] : 0; + + $cur_menu =& $menu; + $menu_path = array_slice($levels, 0, $level+1); + foreach ($menu_path as $elem) { + $cur_menu =& $cur_menu['c'.$elem]['sub_items']; + } + + $ret = ''; + $block_params = $this->prepareTagParams($params); + $block_params['name'] = $params['render_as']; + + $this->Application->SetVar('cur_parent_path', $parent_path); + $real_cat_id = $this->Application->GetVar('m_cat_id'); + if (is_array($cur_menu) && $cur_menu) { + $cur_item = 1; + $cur_menu = $this->_removeNonMenuItems($cur_menu); + $block_params['total_items'] = count($cur_menu); + + foreach ($cur_menu as $page) { + $block_params = array_merge_recursive2( + $block_params, + $this->_prepareMenuItem($page, $real_cat_id, $root_path) + ); + + $block_params['is_last'] = $cur_item == $block_params['total_items']; + $block_params['is_first'] = $cur_item == 1; + + // bug #1: this breaks active section highlighting when 2 menu levels are printed on same page (both visible) + // bug #2: people doesn't pass cat_id parameter to m_Link tags in their blocks, so this line helps them; when removed their links will lead to nowhere + $this->Application->SetVar('m_cat_id', $page['CategoryId']); + + $ret .= $this->Application->ParseBlock($block_params, 1); + $cur_item++; + } + + $this->Application->SetVar('m_cat_id', $real_cat_id); + } + + return $ret; + } + + /** + * Returns only items, that are visible in menu + * + * @param Array $menu + * @return Array + */ + function _removeNonMenuItems($menu) + { + foreach ($menu as $menu_index => $menu_item) { + // $menu_index is in "cN" format, where N is category id + if (!$menu_item['IsMenu']) { + unset($menu[$menu_index]); + } + } + + return $menu; + } + + /** + * 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); + + $template = $object->GetDBField('NamedParentPath'); + $url_params = Array ('admin' => 1, 'pass' => 'm', 'index_file' => 'index.php'); + + return $this->Application->HREF($template, '_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); + } + + /** + * Builds cache for children of given category (no matter, what menu status is) + * + * @param Array $parent + * @return Array + */ + function _altBuildMenuStructure($parent) + { + static $languages_count = null; + + if (!isset($languages_count)) { + $sql = 'SELECT COUNT(*) + FROM ' . TABLE_PREFIX . 'Language'; + $languages_count = ceil($this->Conn->GetOne($sql) / 5) * 5; + } + + $items = Array (); + + $lang_part = ''; + for ($i = 1; $i <= $languages_count; $i++) { + $lang_part .= 'c.l' . $i . '_Name AS l' . $i . '_ItemName,' . "\n"; + // $lang_part .= 'p.l' . $i . '_MenuTitle AS l' . $i . '_ItemName,' . "\n"; + } + + // Sub-categories from current category + $query = 'SELECT + c.CategoryId AS CategoryId, + CONCAT(\'c\', c.CategoryId) AS ItemId, + c.Priority AS ItemPriority, + ' . $lang_part . ' + IF(IsIndex = 2, ( + SELECT cc.NamedParentPath FROM ' . TABLE_PREFIX . 'Category AS cc + WHERE + cc.ParentId = c.CategoryId + AND + cc.Status IN (1,4) + AND + cc.IsIndex = 1 + ), + c.NamedParentPath) AS ItemPath, + 0 AS IsIndex, + c.ParentPath AS ParentPath, + c.ParentId As ParentId, + \'cat\' AS ItemType, + c.IsMenu, c.UseExternalUrl, c.ExternalUrl, c.UseMenuIconUrl, c.MenuIconUrl + FROM ' . TABLE_PREFIX . 'Category AS c + WHERE + c.Status IN (1,4) AND + #c.IsMenu = 1 AND + c.ParentId = ' . $parent['CategoryId']; + $items = array_merge($items, $this->Conn->Query($query, 'ItemId')); + + uasort($items, Array (&$this, '_menuSort')); + + $the_items = array(); + foreach ($items as $an_item) { + $the_items[ $an_item['ItemId'] ] = $an_item; + $this->ParentPaths[ $an_item['CategoryId'] ] = $an_item['ParentPath']; + } + + $items = $the_items; + foreach ($items as $key => $menu_item) { + if ($menu_item['CategoryId'] == $parent['CategoryId']) { + continue; + } + + $sub_items = $this->_altBuildMenuStructure($menu_item); + if ($sub_items) { + $items[$key]['sub_items'] = $sub_items; + } + } + + return $items; + } + + /** + * Method for sorting pages by priority in decending order + * + * @param Array $a + * @param Array $b + * @return int + */ + function _menuSort($a, $b) + { + if ($a['ItemPriority'] == $b['ItemPriority']) { + return 0; + } + + return ($a['ItemPriority'] < $b['ItemPriority']) ? 1 : -1; //descending + } + + /** + * 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 + */ + 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 = $this->Application->GetVar('m_lang'); + + $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\//', '', $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'] ); + } + + /** + * Returns formatted title for template editor + * + * @param Array $params + * @return string + */ + function TemplateEditorTitle($params) + { + if (!EDITING_MODE) { + return ''; + } + + $text = $this->Application->Phrase($params['phrase']); + + $template_helper =& $this->Application->recallObject('TemplateHelper'); + /* @var $template_helper TemplateHelper */ + + $text = sprintf($text, $template_helper->blockInfo(template_file), $template_helper->blockInfo('start_pos'), $template_helper->blockInfo('end_pos')); + + + return $text; + } + } ?> \ No newline at end of file