Index: branches/5.2.x/core/units/categories/categories_tag_processor.php =================================================================== --- branches/5.2.x/core/units/categories/categories_tag_processor.php (revision 16689) +++ branches/5.2.x/core/units/categories/categories_tag_processor.php (revision 16690) @@ -1,2310 +1,2309 @@ 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) { /** @var kCountHelper $count_helper */ $count_helper = $this->Application->recallObject('CountHelper'); $today_only = isset($params['today']) && $params['today']; return $count_helper->CategoryCount($today_only); } function IsNew($params) { /** @var kDBItem $object */ $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) { /** @var kDBItem $object */ $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] : ''; } /** @var kDBList $object */ $object = $this->getObject($params); 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) { /** @var kDBItem $object */ $object = $this->getObject($params); $ci_table = $this->Application->getUnitOption('ci', 'TableName'); $module_prefixes = implode(',', $this->Conn->qstrArray($this->_getModulePrefixes())); $sql = 'SELECT COUNT(*) FROM ' . $object->TableName . ' c JOIN ' . $ci_table . ' ci ON c.CategoryId = ci.CategoryId WHERE (c.TreeLeft BETWEEN ' . $object->GetDBField('TreeLeft') . ' AND ' . $object->GetDBField('TreeRight') . ') AND (ci.ItemPrefix IN (' . $module_prefixes . '))'; return $this->Conn->GetOne($sql); } function _getModulePrefixes() { $ret = Array (); foreach ($this->Application->ModuleInfo as $module_info) { $ret[] = $module_info['Var']; } return array_unique($ret); } 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) { /** @var kNavigationBar $navigation_bar */ $navigation_bar = $this->Application->recallObject('kNavigationBar'); return $navigation_bar->build($params); } /** * Shows category path to specified category * * @param Array $params * @return string */ function FieldCategoryPath($params) { /** @var kDBItem $object */ $object = $this->getObject($params); $field = $this->SelectParam($params, 'name,field'); $category_id = $object->GetDBField($field); if ($category_id) { $params['cat_id'] = $category_id; /** @var kNavigationBar $navigation_bar */ $navigation_bar = $this->Application->recallObject('kNavigationBar'); return $navigation_bar->build($params); } return ''; } function CurrentCategoryName($params) { /** @var kDBList $cat_object */ $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() { /** @var kMultiLanguage $ml_formatter */ $ml_formatter = $this->Application->recallObject('kMultiLanguage'); return $ml_formatter->LangFieldName('Name'); } /** * Returns symlinked category for given category * * @param int $category_id * @return int */ 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']); } $virtual_template = $this->Application->getVirtualPageTemplate($category_id); if ( ($virtual_template !== false) && preg_match('/external:(.*)/', $virtual_template, $rets) ) { // external url (return here, instead of always replacing $params['t'] for kApplication::HREF to find it) 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($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->GetRecordsCount() == 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 CategoriesItem $object */ $meta_type = $params['name']; if ($object->isLoaded()) { // 1. get module prefix by current category /** @var CategoryHelper $category_helper */ $category_helper = $this->Application->recallObject('CategoryHelper'); $category_path = explode('|', substr($object->GetDBField('ParentPath'), 1, -1)); $module_info = $category_helper->getCategoryModule($params, $category_path); if ( $module_info ) { // 2. get item template by current category & module prefix /** @var kRewriteUrlProcessor $rewrite_processor */ $rewrite_processor = $this->Application->recallObject('kRewriteUrlProcessor'); $category_params = Array ( 'CategoryId' => $object->GetID(), 'ParentPath' => $object->GetDBField('ParentPath'), ); $item_template = $rewrite_processor->GetItemTemplate($category_params, $module_info['Var']); if ($this->Application->GetVar('t') == $item_template) { // we are located on item's details page /** @var kCatDBItem $item */ $item = $this->Application->recallObject($module_info['Var']); // 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->processQueryString($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 = $this->Application->getBaseCategory(); $category_id = $this->Application->GetVar('m_cat_id'); if ($category_id != $parent_id) { $sql = 'SELECT ParentId FROM ' . $this->Application->getUnitOption($this->Prefix, 'TableName') . ' WHERE ' . $this->Application->getUnitOption($this->Prefix, 'IDField') . ' = ' . $category_id; $parent_id = $this->Conn->GetOne($sql); } return $parent_id; } function InitCacheUpdater($params) { kUtil::safeDefine('CACHE_PERM_CHUNK_SIZE', 30); $continue = $this->Application->GetVar('continue'); $total_cats = (int)$this->Conn->GetOne('SELECT COUNT(*) FROM ' . TABLE_PREFIX . 'Categories'); if ( $continue === false ) { $rebuild_mode = $this->Application->ConfigValue('CategoryPermissionRebuildMode'); if ( $rebuild_mode == CategoryPermissionRebuild::AUTOMATIC && $total_cats > CACHE_PERM_CHUNK_SIZE ) { // first step, if category count > CACHE_PERM_CHUNK_SIZE, then ask for cache update return true; } // if we don't have to ask, then assume user selected "Yes" in permcache update dialog $continue = 1; } /** @var kPermCacheUpdater $updater */ $updater = $this->Application->makeClass('kPermCacheUpdater', Array ($continue)); 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 proceeded 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->HandleEvent(new kEvent('c:OnResetCMSMenuCache')); $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 * @access protected */ protected function SaveWarning($params) { if ( $this->Prefix == 'st' ) { // don't use this method for other prefixes then Categories, 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); } return $temp_tables && $modified ? 1 : 0; } /** * 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) { /** @var CategoriesItem $object */ $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); return $object->GetRecordsCount(false) != $object->GetRecordsCount() ? $object->GetRecordsCount().' / '.$object->GetRecordsCount(false) : $object->GetRecordsCount(); } 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 . 'Categories 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 = isset($params['template']) ? $params['template'] : ''; if ( $template ) { // when using from "c:CachedMenu" tag $sql = 'SELECT ParentPath FROM ' . TABLE_PREFIX . 'Categories 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'); } /** @var CategoriesItem $category */ $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) { /** @var kPermissionsHelper $perm_helper */ $perm_helper = $this->Application->recallObject('PermissionsHelper'); $params['raise_warnings'] = 0; /** @var kDBItem $object */ $object = $this->getObject($params); $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 . 'Categories 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 . 'Categories'; } $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) ) { /** @var LanguagesItem $lang */ $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) { /** @var kDBList $object */ $object = $this->getObject($params); $params['cat_id'] = $object->GetID(); /** @var kCountHelper $count_helper */ $count_helper = $this->Application->recallObject('CountHelper'); 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) { /** @var kDBList $object */ $object = $this->getObject($params); $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; } /** * Builds link to a category in the Admin Tree. * * @param array $params Tag params. * * @return string */ protected function AdminTreeLink(array $params) { $params['direct_link'] = 1; $params['pass'] = 'm'; $params['m_opener'] = 'r'; if ( $this->Application->ConfigValue('Catalog_PreselectModuleTab') ) { $module_prefix = $this->GetModulePrefix($params); if ( $module_prefix ) { $params['anchor'] = 'tab-' . $module_prefix; } } return $this->CategoryLink($params); } /** * Returns module prefix based on root category for given * * @param Array $params * @return string */ function GetModulePrefix($params) { /** @var kDBItem $object */ $object = $this->getObject($params); $parent_path = explode('|', substr($object->GetDBField('ParentPath'), 1, -1)); /** @var CategoryHelper $category_helper */ $category_helper = $this->Application->recallObject('CategoryHelper'); $module_info = $category_helper->getCategoryModule($params, $parent_path); return $module_info ? $module_info['Var'] : 'c'; } 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 * @access protected */ protected function SpellingSuggestions($params) { $keywords = $this->Application->unescapeRequestVariable(trim($this->Application->GetVar('keywords'))); if ( !$keywords ) { return ''; } // 1. try to get already cached suggestion $cache_key = 'search.suggestion[%SpellingDictionarySerial%]:' . $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 /** @var kCurlHelper $curl_helper */ $curl_helper = $this->Application->recallObject('CurlHelper'); $curl_helper->SetRequestData(array( 'appid' => $this->Application->ConfigValue('YahooApplicationId'), 'query' => $keywords, )); $xml_data = $curl_helper->Send('http://search.yahooapis.com/WebSearchService/V1/spellingSuggestion'); /** @var kXMLHelper $xml_helper */ $xml_helper = $this->Application->recallObject('kXMLHelper'); /** @var kXMLNode $root_node */ $root_node =& $xml_helper->Parse($xml_data); /** @var kXMLNode $result */ $result = $root_node->FindChild('RESULT'); 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 /** @var kDBItem $object */ $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 CategoriesItem */ function &_getPage($params) { /** @var kDBItem $page */ $page = $this->Application->recallObject($this->Prefix . '.' . $this->_getPageSpecial($params), null, $params); // 1. load by given id $page_id = array_key_exists('page_id', $params) ? $params['page_id'] : 0; 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 differs from requested template $structure_path_match = mb_strtolower($page->GetDBField('NamedParentPath')) == mb_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 /** @var kThemesHelper $themes_helper */ $themes_helper = $this->Application->recallObject('ThemesHelper'); $page_id = $themes_helper->getPageByTemplate($template); $page->Load($page_id); } return $page; } /** * Returns unique special for each used page * * @param Array $params * @return string * @access protected */ protected function _getPageSpecial($params) { $ret = Array (); $page_id = array_key_exists('page_id', $params) ? $params['page_id'] : 0; $template = array_key_exists('page', $params) ? $params['page'] : ''; if ( $page_id ) { $ret[] = 'page_id=' . $page_id; } if ( $template ) { $ret[] = 'page=' . $template; } return $ret ? '-virtual-' . kUtil::crc32(serialize($ret)) : '-virtual'; } /** * Returns requested content block content of current or specified page * * @param Array $params * @return string */ function ContentBlock($params) { $num = getArrayValue($params, 'num'); if ( !$num ) { $name = getArrayValue($params, 'name'); if ( $name ) { $num = kUtil::crc32($name); } } if ( !$num ) { return 'NO CONTENT NUM SPECIFIED'; } /** @var kDBItem $page */ $page =& $this->_getPage($params); if ( !$page->isLoaded() ) { // page is not created yet => all blocks are empty return ''; } /** @var PageHelper $page_helper */ $page_helper = $this->Application->recallObject('PageHelper'); /** @var kDBItem $content */ $content = $this->Application->recallObject('content.-block', null, Array ('skip_autoload' => true)); if ( !$page_helper->loadContentBlock($content, $page, $num) && EDITING_MODE ) { $page_helper->createNewContentBlock($page->GetID(), $num); $page_helper->loadContentBlock($content, $page, $num); } $edit_code_before = $edit_code_after = ''; $inline_editing = isset($params['mode']) && $params['mode'] == 'inline'; if ( EDITING_MODE == EDITING_MODE_CONTENT ) { if ( $inline_editing ) { $params['name'] = 'content_block_' . $num; $editing_hint = $this->Application->Phrase('la_hint_ClickToEdit', false, true); $edit_code_before = '
'; $edit_code_after = '
' . $this->FCKEditor($params); } else { $button_code = $this->Application->ProcessParsedTag($content->getPrefixSpecial(), 'AdminEditButton', $params); $edit_code_before = '
' . $button_code . '
'; $edit_code_after = '
'; } } if ( $this->Application->GetVar('_editor_preview_') == 1 ) { $data = $this->Application->RecallVar('_editor_preview_content_'); } elseif ( EDITING_MODE == EDITING_MODE_CONTENT && $inline_editing ) { // don't use formatter, that replaced "@@ID@@" links $content->SetFieldOption('Content', 'using_fck', false); $data = $content->GetField('Content'); $content->SetFieldOption('Content', 'using_fck', true); } else { // use formatter, that replaced "@@ID@@" links $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 * @param Array $params * @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': // TODO: rename column to SectionTitle $db_field = 'Name'; // "Section Title" - title to show on page (e.g. in

tag) break; case 'htmlhead_title': // TODO: rename column to HtmlTitle $db_field = 'Title'; // "Title (on Page)" - in html tag break; case 'meta_title': $db_field = 'MetaTitle'; break; case 'menu_title': $db_field = 'MenuTitle'; // "Title (Menu Item)" - in menu and navigation bar 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->prefixRegistred('c') ) { 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 * @access protected */ protected 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'; /** @var MinifyHelper $minify_helper */ $minify_helper = $this->Application->recallObject('MinifyHelper'); $to_compress = Array ( $js_url . '/jquery/thickbox/thickbox.css', $js_url . '/../incs/cms.css', $js_url . '/../img/toolbar/toolbar-sprite.css', ); $css_compressed = $minify_helper->CompressScriptTag(Array ('files' => implode('|', $to_compress), 'templates_base' => $js_url . '/../')); $ret = '<link rel="stylesheet" href="' . $css_compressed . '" type="text/css" media="screen"/>' . "\n"; $ret .= ' <!--[if IE]> <link rel="stylesheet" href="' . $js_url . '/../incs/cms_ie.css' . '" type="text/css" media="screen"/> <![endif]-->'; 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-1.9.1.min.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/jquery-ui-1.10.3.custom.min.js"></script>' . "\n"; $to_compress = Array ( $js_url . '/is.js', $js_url . '/application.js', $js_url . '/script.js', $js_url . '/toolbar.js', $js_url . '/jquery/thickbox/thickbox.js', $js_url . '/template_manager.js', ); $js_compressed = $minify_helper->CompressScriptTag( Array ('files' => implode('|', $to_compress)) ); $ret .= '<script type="text/javascript" src="' . $js_compressed . '"></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); $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); $save_layout_url = $this->Application->HREF('index', '', $url_params); $url_params = Array ('content_event' => 'OnSaveContentBlock', 'pass' => 'all,content', '__NO_REWRITE__' => 1, 'no_amp' => 1); $save_content_url = $this->Application->HREF('index', ADMIN_DIRECTORY, $url_params, 'index.php'); $page =& $this->_getPage($params); /** @var PageHelper $page_helper */ $page_helper = $this->Application->recallObject('PageHelper'); $class_params = Array ( 'languagePrefix' => 'l' . $this->Application->GetVar('m_lang') . '_', 'pageId' => $page->GetID(), 'pageInfo' => $page->isLoaded() ? $page_helper->getPageInfo( $page->GetID() ) : Array (), 'editUrl' => $edit_template_url, 'browseUrl' => $this->Application->HREF('', '', Array ('editing_mode' => '#EDITING_MODE#', '__NO_REWRITE__' => 1)), 'saveLayoutUrl' => $save_layout_url, 'saveContentUrl' => $save_content_url, 'editingMode' => (int)EDITING_MODE, ); $site_name = strip_tags($this->Application->ConfigValue('Site_Name')); $ret .= "var aTemplateManager = new TemplateManager(" . json_encode($class_params) . ");\n"; $ret .= "var main_title = '" . kUtil::escape($site_name, kUtil::ESCAPE_JS) . "';" . "\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 $visible_toolbar_buttons = true' . ";\n"; $ret .= 'var $use_toolbarlabels = ' . ($this->Application->ConfigValue('UseToolbarLabels') ? 'true' : 'false') . ";\n";; $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); $browse_url = $this->Application->HREF('catalog/catalog', ADMIN_DIRECTORY, $url_params, 'index.php'); $browse_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $browse_url); $admin_title = strip_tags($this->Application->Phrase('la_AdministrativeConsole', false)); $ret .= ' set_window_title(document.title + \' - ' . kUtil::escape($admin_title, kUtil::ESCAPE_JS) . '\'); 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 ( $this->Application->GetVar('preview') ) { // prevents draft preview function to replace last template in session and break page/content block editing process $this->Application->SetVar('skip_last_template', 1); } if (!EDITING_MODE) { return ''; } $display_mode = array_key_exists('mode', $params) ? $params['mode'] : false; unset($params['mode']); $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 = $edit_url = ''; if ( EDITING_MODE == EDITING_MODE_CONTENT ) { $item_prefix = isset($params['item_prefix']) ? $params['item_prefix'] : ''; unset($params['item_prefix']); + $default_params = array( + 'button_icon' => 'section_properties.png', + 'button_class' => 'cms-section-properties-btn', + 'button_title' => 'la_btn_SectionProperties', + ); + + $params = array_merge($default_params, $params); + if ( $item_prefix ) { $params['button_class'] = 'cms-section-properties-btn'; $edit_btn = $this->Application->ProcessParsedTag($item_prefix, 'AdminEditButton', $params) . "\n"; } else { $edit_btn = $this->AdminEditButton($params) . "\n"; // "st" object must be loaded before this } } 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, '__NO_REWRITE__'=> 1, 'index_file' => 'index.php', ); $edit_url = $this->Application->HREF('themes/file_edit', ADMIN_DIRECTORY, $url_params); $button1_icon = $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/save_button.gif'; $button1_title = $this->Application->Phrase('la_btn_SaveChanges', false, true); $button1_code = '<button style="background-image: url(' . $button1_icon . '); onclick="aTemplateManager.saveLayout(); return false;" class="cms-btn-new cms-save-layout-btn">' . $button1_title . '</button>'; $button2_icon = $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/cancel_button.gif'; $button2_title = $this->Application->Phrase('la_btn_Cancel', false, true); $button2_code = '<button style="background-image: url(' . $button2_icon . '); onclick="aTemplateManager.cancelLayout(); return false;" class="cms-btn-new cms-cancel-layout-btn">' . $button2_title . '</button>'; $button3_icon = $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/section_properties.png'; $button3_title = $this->Application->Phrase('la_btn_SectionTemplate', false, true); $button3_code = '<button style="background-image: url(' . $button3_icon . ');' . ($display_mode === false ? ' margin: 0px;' : '') . '" onclick="$form_name=\'kf_'.$page->GetID().'\'; std_edit_item(\'theme\', \'themes/file_edit\');" class="cms-btn-new cms-section-properties-btn">' . $button3_title . '</button>'; $edit_btn .= '<div class="cms-layout-btn-container"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . '>' . $button1_code . $button2_code . '</div>' . $button3_code . "\n"; } if ( $display_mode == 'start' ) { // button with border around the page if ( EDITING_MODE == EDITING_MODE_CONTENT ) { $tabs = "\n" . str_repeat("\t", 9); $base_url = $this->Application->BaseURL(); $toolbar_hidden = $this->Application->GetVar('toolbar_hidden'); $edit_code .= ' <div> <div id="cms-editing-notice"> <div class="top"> <a href="#" id="cms-close-editing-notice"></a> <span prev_editors=""></span> </div> <div class="bottom"></div> </div> <div id="cms-revision-dropdown"> <div class="top"></div> <div class="bottom"></div> </div> </div>'; if ( $this->Application->ConfigValue('EnablePageContentRevisionControl') ) { $edit_code .= '<div id="cms-revision-toolbar-layer"' . ($toolbar_hidden ? ' style="top: -56px;"' : '') . '> <div id="cms-revision-toolbar"> <script type="text/javascript"> var a_toolbar = new ToolBar(undefined, undefined, "' . $base_url . '#MODULE#/admin_templates/img/"); ' . $this->toolbarButton('select', 'la_ToolTip_Save', $tabs) . $this->toolbarButton('delete', 'la_ToolTip_Discard', $tabs) . $tabs . 'a_toolbar.AddButton( new ToolBarSeparator("sep1") );'; if ( $this->Application->CheckAdminPermission('CATEGORY.REVISION.MODERATE', 0) ) { $edit_code .= $this->toolbarButton('approve', 'la_ToolTip_Publish', $tabs) . $this->toolbarButton('decline', 'la_ToolTip_Decline', $tabs) . $tabs . 'a_toolbar.AddButton( new ToolBarSeparator("sep2") );'; } $edit_code .= $this->toolbarButton('preview', 'la_ToolTip_Preview', $tabs); if ( $this->Application->CheckAdminPermission('CATEGORY.REVISION.HISTORY.VIEW', 0) ) { $edit_code .= $this->toolbarButton('history', 'la_ToolTip_History', $tabs); } $edit_code .= $tabs . 'a_toolbar.Render();' . "\n"; /** @var kDBItem $revision */ $revision = $this->Application->recallObject('page-revision.current'); /** @var PageHelper $page_helper */ $page_helper = $this->Application->recallObject('PageHelper'); foreach ( $page_helper->getToolbarButtonsState($revision) as $toolbar_button => $is_enabled ) { $edit_code .= $tabs . 'a_toolbar.SetEnabled("' . $toolbar_button . '", ' . json_encode($is_enabled) . ');'; } $publishing_tools = $this->Application->Phrase('la_btn_PublishingTools', false, true); $edit_code .= substr($tabs, 0, -1) . '</script> <div id="cms-current-revision-info"> <span class="revision-title"></span> <div class="draft-saved"></div> </div> <a href="#" id="cms-close-toolbar"></a> <div class="cms-clear"></div> </div> <a href="#" id="cms-toggle-revision-toolbar"' . ($toolbar_hidden ? '' : ' class="opened"') . '><span>' . $publishing_tools . '</span></a> </div>' . "\n"; } } $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') { if ( EDITING_MODE == EDITING_MODE_CONTENT ) { $url_params = Array( 'pass' => 'm', 'm_opener' => 'd', 'm_cat_id' => $page->GetID(), '__NO_REWRITE__'=> 1, 'front' => 1, 'index_file' => 'index.php', ); $revision = $this->Application->GetVar('revision'); if ( $revision ) { $url_params['revision'] = $revision; } $page_admin_url = $this->Application->HREF('', ADMIN_DIRECTORY, $url_params); $edit_code .= '<form method="POST" style="display: inline; margin: 0px" name="kf_revisions_'.$page->GetID().'" id="kf_revisions_'.$page->GetID().'" action="' . $page_admin_url . '"> <input type="hidden" name="revision" value="' . $this->Application->GetVar('revision', 0) . '"/> </form>'; } if ( $edit_url ) { $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 toolbarButton($name, $title, $tabs) { $action = 'function() { aTemplateManager.revisionToolbarClick("' . $name . '"); }'; $phrase = kUtil::escape($this->Application->Phrase($title, false, true), kUtil::ESCAPE_HTML . '+' . kUtil::ESCAPE_JS); return $tabs . 'a_toolbar.AddButton(new ToolBarButton("' . $name . '", "' . $phrase . '", ' . $action . '));'; } function _getThemeFileId() { $template = $this->Application->GetVar('t'); if (!$this->Application->TemplatesCache->TemplateExists($template) && !$this->Application->isAdmin) { /** @var CategoriesEventHandler $cms_handler */ $cms_handler = $this->Application->recallObject($this->Prefix . '_EventHandler'); $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); } /** * Creates a button for editing item in Admin Console * * @param Array $params * @return string * @access protected */ protected function AdminEditButton($params) { if ( EDITING_MODE != EDITING_MODE_CONTENT ) { return ''; } - /** @var kDBItem $object */ - $object = $this->getObject($params); - $params['item_prefix'] = 'c'; - if ( $this->Prefix == 'st' ) { - $params['button_icon'] = 'section_properties.png'; - $params['button_class'] = 'cms-section-properties-btn'; - $params['button_title'] = 'la_btn_SectionProperties'; - } - return parent::AdminEditButton($params); } /** * Builds site menu * * @param Array $params * @return string */ function CachedMenu($params) { /** @var MenuHelper $menu_helper */ $menu_helper = $this->Application->recallObject('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 . 'Categories 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) { /** @var kDBList $list */ $list = $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix.'_List', $params); $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) { /** @var kDBItem $object */ $object = $this->getObject($params); /** @var kThemesHelper $themes_helper */ $themes_helper = $this->Application->recallObject('ThemesHelper'); /** @var SiteConfigHelper $site_config_helper */ $site_config_helper = $this->Application->recallObject('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, ); if ($this->Application->ConfigValue('UseModRewrite')) { $url_params['__MOD_REWRITE__'] = 1; } else { $url_params['index_file'] = 'index.php'; } return $this->Application->HREF($object->GetDBField('NamedParentPath'), '_FRONT_END_', $url_params); } /** * Builds a link for securely accessing a page later (even if it will not be publicly accessible) * * @param Array $params * @return string * @access protected */ protected function DirectLink($params) { /** @var kDBItem $object */ $object = $this->getObject($params); /** @var kThemesHelper $themes_helper */ $themes_helper = $this->Application->recallObject('ThemesHelper'); $url_params = Array ( 'm_cat_id' => $object->GetID(), 'm_theme' => $themes_helper->getCurrentThemeId(), 'pass' => 'm', 'authkey' => $object->GetDBField('DirectLinkAuthKey'), '__SSL__' => 0, '__NO_SID__' => 0, ); if ($this->Application->ConfigValue('UseModRewrite')) { $url_params['__MOD_REWRITE__'] = 1; } else { $url_params['index_file'] = 'index.php'; } return $this->Application->HREF($object->GetDBField('NamedParentPath'), '_FRONT_END_', $url_params); } /** * Builds link to category as a cms page * * @param Array $params * @return string */ function ContentPageLink($params) { /** @var kDBItem $object */ $object = $this->getObject($params); $params['t'] = mb_strtolower($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']; /** @var kDBItem $object */ $object = $this->Application->recallObject($this->Prefix); $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 ''; } /** @var TemplateHelper $template_helper */ $template_helper = $this->Application->recallObject('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'; } } /** @var JSONHelper $json_helper */ $json_helper = $this->Application->recallObject('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) { /** @var kDBList $object */ $object = $this->getObject($params); $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) { /** @var kDBItem $object */ $object = $this->getObject($params); /** @var kSearchHelper $search_helper */ $search_helper = $this->Application->recallObject('SearchHelper'); $search_results_table = $search_helper->getSearchTable(); $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 { /** @var kDBItem $object */ $object = $this->getObject($params); /** @var kPermissionsHelper $perm_helper */ $perm_helper = $this->Application->recallObject('PermissionsHelper'); $perm_prefix = $this->Application->getUnitOption($this->Prefix, 'PermItemPrefix'); $categories = $perm_helper->getPermissionCategories($perm_prefix . '.' . ($object->IsNewItem() ? 'ADD' : 'MODIFY')); } /** @var JSONHelper $json_helper */ $json_helper = $this->Application->recallObject('JSONHelper'); return $json_helper->encode($categories); } function PageEditable($params) { if ($this->Application->isDebugMode()) { return true; } /** @var kDBItem $object */ $object = $this->getObject($params); return !$object->GetDBField('Protected'); } /** * Returns element for "__item__" navigation bar part * * @param Array $params * @return string * @access protected */ protected function CategoryItemElement($params) { /** @var CategoryHelper $category_helper */ $category_helper = $this->Application->recallObject('CategoryHelper'); /** @var kNavigationBar $navigation_bar */ $navigation_bar = $this->Application->recallObject('kNavigationBar'); $category_id = isset($params['cat_id']) ? $params['cat_id'] : $this->Application->GetVar('m_cat_id'); $parent_path = explode('|', substr($navigation_bar->getParentPath($category_id), 1, -1)); array_shift($parent_path); // remove "Content" category $module_info = $category_helper->getCategoryModule($params, $parent_path); if ( !$module_info ) { return ''; } $module_prefix = $module_info['Var']; /** @var kCatDBItem $object */ $object = $this->Application->recallObject($module_prefix); $title_field = $this->Application->getUnitOption($module_prefix, 'TitleField'); $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; $block_params['title'] = $object->GetField($title_field); $block_params['prefix'] = $module_prefix; return $this->Application->ParseBlock($block_params); } }