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']; $icon_prefix = array_key_exists('icon_prefix', $params)? $params['icon_prefix'] : 'icon16_'; 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('ThemeId') > 0) { if (!$object->GetDBField('IsMenu')) { return $icon_prefix . 'section_menuhidden_system.png'; } return $icon_prefix . 'section_system.png'; } $status = $object->GetDBField('Status'); if ($status == STATUS_DISABLED) { return $icon_prefix . 'section_disabled.png'; } if (!$object->GetDBField('IsMenu')) { return $icon_prefix . 'section_menuhidden.png'; } if ($status == STATUS_PENDING) { return $icon_prefix . 'section_pending.png'; } if ($object->GetDBField('IsNew') && ($icon_prefix == 'icon16_')) { return $icon_prefix . 'section_new.png'; // show gris icon only in grids } return $icon_prefix . 'section.png'; } function ItemCount($params) { $object =& $this->getObject($params); /* @var $object kDBItem */ $ci_table = $this->Application->getUnitOption('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) { if (!$category_id) { // don't bother to get symlink for "Home" category return $category_id; } $cache_key = 'category_symlinks[%CSerial%]'; $cache = $this->Application->getCache($cache_key); if ($cache === false) { $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); // get symlinked categories, that are not yet deleted $this->Conn->nextQueryCachable = true; $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); $this->Application->setCache($cache_key, $cache); } 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'); } if (!array_key_exists('direct_link', $params) || !$params['direct_link']) { $category_id = $this->getCategorySymLink( (int)$category_id ); } else { unset($params['direct_link']); } if ( isset($this->Application->structureTemplateMapping['id:' . $category_id]) && preg_match('/external:(.*)/', $this->Application->structureTemplateMapping['id:' . $category_id], $rets) ) { // external url return $rets[1]; } 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, update left tree and redirect $updater->SaveData(); $this->Application->RemoveVar('PermCache_UpdateRequired'); $this->Application->StoreVar('RefreshStructureTree', 1); $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) { return $this->Application->getBaseCategory(); } /** * 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->Application->getBaseCategory(); } 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, , 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); } /** * 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 = (int)$this->Application->GetVar('m_cat_id'); $local = array_key_exists('local', $params) && ($category_id > 0) ? $params['local'] : false; $serial_name = $this->Application->incrementCacheSerial('c', $local ? $category_id : null, false); $cache_key = 'category_last_updated[%' . $serial_name . '%]'; $row_data = $this->Application->getCache($cache_key); if ($row_data === false) { if ($local && ($category_id > 0)) { // scan only current category & it's children list ($tree_left, $tree_right) = $this->Application->getTreeIndex($category_id); $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate FROM ' . TABLE_PREFIX . 'Category WHERE TreeLeft BETWEEN ' . $tree_left . ' AND ' . $tree_right; } else { // scan all categories in system $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate FROM ' . TABLE_PREFIX . 'Category'; } $this->Conn->nextQueryCachable = true; $row_data = $this->Conn->GetRow($sql); $this->Application->setCache($cache_key, $row_data); } 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) { $params['m_cat_page'] = $this->Application->GetVar($this->getPrefixSpecial() . '_Page'); return parent::PageLink($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 $cache_key = 'search.suggestion[%SpellingDictionary%]:' . $keywords; $suggestion = $this->Application->getCache($cache_key); if ($suggestion !== false) { return $suggestion; } $table_name = $this->Application->getUnitOption('spelling-dictionary', 'TableName'); // 2. search suggestion in database $this->Conn->nextQueryCachable = true; $sql = 'SELECT SuggestedCorrection FROM ' . $table_name . ' WHERE MisspelledWord = ' . $this->Conn->qstr($keywords); $suggestion = $this->Conn->GetOne($sql); if ($suggestion !== false) { $this->Application->setCache($cache_key, $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($cache_key, $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'; } // use $pass_params to be able to pass 'tab_init' parameter from m_ModuleInclude tag 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'); $cache_key = 'category_paths[%CIDSerial:' . $category_id . '%][%PhrasesSerial%][Adm:' . (int)$this->Application->isAdmin . ']'; $category_path = $this->Application->getCache($cache_key); 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->isAdmin ? 'la_' : 'lu_') . 'rootcategory_name'); } $this->Application->setCache($cache_key, $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 = '
' . $this->Application->Phrase('la_btn_EditContent', false, true) . ' '.(defined('DEBUG_MODE') && DEBUG_MODE ? " - #{$num}" : '').'
'; $edit_form = '
'; $edit_form .= ''; $edit_form .= ''; $edit_form .= ''; $edit_form .= ''; $edit_form .= ''; $edit_form .= '
'; $edit_code_after = '
'; 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); switch ($params['type']) { case 'title': $db_field = 'Title'; break; case 'htmlhead_title': $db_field = 'Name'; break; case 'meta_title': $db_field = 'MetaTitle'; break; case 'menu_title': $db_field = 'MenuTitle'; break; case 'meta_keywords': $db_field = 'MetaKeywords'; $cat_field = 'Keywords'; break; case 'meta_description': $db_field = 'MetaDescription'; $cat_field = 'Description'; break; case 'tracking': case 'index_tools': if (!EDITING_MODE) { $tracking = $page->GetDBField('IndexTools'); return $tracking ? $tracking : $this->Application->ConfigValue('cms_DefaultTrackingCode'); } // no break here on purpose 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'; $minify_helper =& $this->Application->recallObject('MinifyHelper'); /* @var $minify_helper MinifyHelper */ $to_compress = Array ( $js_url . '/jquery/thickbox/thickbox.css', $js_url . '/../incs/cms.css', ); $css_compressed = $minify_helper->CompressScriptTag( Array ('files' => implode('|', $to_compress)) ); $ret = '' . "\n"; if (EDITING_MODE == EDITING_MODE_DESIGN) { $ret .= ' '; } $ret .= '' . "\n"; $ret .= '' . "\n"; $to_compress = Array ( $js_url . '/is.js', $js_url . '/application.js', $js_url . '/script.js', $js_url . '/jquery/thickbox/thickbox.js', $js_url . '/template_manager.js', ); $js_compressed = $minify_helper->CompressScriptTag( Array ('files' => implode('|', $to_compress)) ); $ret .= '' . "\n"; $ret .= '' . "\n"; if (EDITING_MODE != EDITING_MODE_BROWSE) { // add form, so admin scripts could work $ret .= '
'; } 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, 'index_file' => 'index.php', ); $edit_url = $this->Application->HREF('categories/categories_edit', ADMIN_DIRECTORY, $url_params); $edit_btn .= '
' . $this->Application->Phrase('la_btn_SectionProperties', false, true) . '
' . "\n"; } elseif (EDITING_MODE == EDITING_MODE_DESIGN) { $url_params = Array( 'pass' => 'm,theme,theme-file', '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, 'index_file' => 'index.php', ); $edit_url = $this->Application->HREF('themes/file_edit', ADMIN_DIRECTORY, $url_params); $edit_btn .= '
' . $this->Application->Phrase('la_btn_SaveChanges', false, true) . '
' . $this->Application->Phrase('la_btn_Cancel', false, true) . '
' . $this->Application->Phrase('la_btn_SectionTemplate', false, true) . '
' . "\n"; } if ($display_mode == 'start') { // button with border around the page $edit_code .= '
' . $edit_btn . '
'; } else { // button without border around the page $edit_code .= $edit_btn; } } if ($display_mode == 'end') { // draw border around the page $edit_code .= '
'; } if ($display_mode != 'end') { $edit_code .= '
'; // 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); $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)) { $module_path = $this->Application->getUnitOption($prefix, 'ModuleFolder') . '/'; $module_name = $this->Application->findModule('Path', $module_path, 'Name'); $ret[$prefix] = mb_strtolower($module_name) . '/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); } /** * Returns list of categories, that have category add/edit permission * * @param Array $params * @return string */ function AllowedCategoriesJSON($params) { if ($this->Application->RecallVar('user_id') == USER_ROOT) { $categories = true; } else { $object =& $this->getObject($params); /* @var $object kDBItem */ $perm_helper =& $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ $perm_prefix = $this->Application->getUnitOption($this->Prefix, 'PermItemPrefix'); $categories = $perm_helper->getPermissionCategories($perm_prefix . '.' . ($object->IsNewItem() ? 'ADD' : 'MODIFY')); } $json_helper =& $this->Application->recallObject('JSONHelper'); /* @var $json_helper JSONHelper */ return $json_helper->encode($categories); } function PageEditable($params) { if ($this->Application->isDebugMode()) { return true; } $object =& $this->getObject($params); /* @var $object kDBItem */ return !$object->GetDBField('Protected'); } }