Attached Files |
symlink in menu.patch [^] (52,287 bytes) 2009-10-13 11:09
[Show Content]
Index: admin/system_presets/simple/categories_c.php
===================================================================
--- admin/system_presets/simple/categories_c.php (revision 12690)
+++ admin/system_presets/simple/categories_c.php (working copy)
@@ -40,12 +40,12 @@
// fields to hide
$hidden_fields = Array (
- 'CategoryId', /*'Type',*/ 'SymLinkCategoryId', /*'ParentId', 'Name', 'Filename', 'AutomaticFilename',*/
+ 'CategoryId', /*'Type', 'SymLinkCategoryId', 'ParentId', 'Name', 'Filename', 'AutomaticFilename',*/
/*'Description',*/ 'CreatedOn', 'EditorsPick', 'Status', /*'Priority', 'MetaKeywords', 'CachedDescendantCatsQty',
'CachedNavbar',*/ 'CreatedById', /*'ResourceId', 'ParentPath', 'TreeLeft', 'TreeRight', 'NamedParentPath',
'MetaDescription', 'HotItem',*/ 'NewItem', /*'PopItem', 'Modified', 'ModifiedById', 'CachedTemplate',*/
'Template', /*'UseExternalUrl', 'ExternalUrl',*/ 'UseMenuIconUrl', 'MenuIconUrl', 'Title', 'MenuTitle',
- /*'MetaTitle', 'IndexTools', 'IsIndex', 'IsMenu', 'IsSystem',*/ 'FormId', 'FormSubmittedTemplate',
+ /*'MetaTitle', 'IndexTools', 'IsMenu', 'IsSystem',*/ 'FormId', 'FormSubmittedTemplate',
/*'FriendlyURL', 'ThemeId'*/
);
@@ -56,7 +56,7 @@
);
$debug_only_fields = Array (
- 'Filename', 'AutomaticFilename', 'IsIndex',
+ 'Filename', 'AutomaticFilename', 'SymLinkCategoryId'
);
// fields to make required
Index: core/admin_templates/categories/categories_edit.tpl
===================================================================
--- core/admin_templates/categories/categories_edit.tpl (revision 12690)
+++ core/admin_templates/categories/categories_edit.tpl (working copy)
@@ -72,7 +72,7 @@
<inp2:m_RenderElement name="inp_edit_box" prefix="c" field="Filename" title="la_fld_Filename" size="70" /> <!-- la_fld_CategoryFilename -->
<inp2:m_RenderElement name="inp_edit_category" prefix="c" field="SymLinkCategoryId" title="la_fld_SymLinkCategoryId"/>
- <inp2:m_RenderElement name="subsection" prefix="c" fields="Title,MenuTitle,FriendlyURL,ParentId,Template,FormId,FormSubmittedTemplate,IsIndex,IsMenu" title="la_section_Page"/>
+ <inp2:m_RenderElement name="subsection" prefix="c" fields="Title,MenuTitle,FriendlyURL,ParentId,Template,FormId,FormSubmittedTemplate,IsMenu" title="la_section_Page"/>
<inp2:m_RenderElement name="inp_edit_box_ml" prefix="c" field="Title" title="!la_fld_PageContentTitle!" size="40"/>
<inp2:m_RenderElement name="inp_edit_box_ml" prefix="c" field="MenuTitle" title="!la_fld_PageMentTitle!" size="40"/>
@@ -91,7 +91,6 @@
<inp2:m_RenderElement name="inp_edit_options" prefix="c" field="FormId" title="!la_fld_Form!"/>
<inp2:m_RenderElement name="inp_edit_box" prefix="c" field="FormSubmittedTemplate" title="la_fld_FormSubmittedTemplate" size="60"/>
- <inp2:m_RenderElement name="inp_edit_options" prefix="c" field="IsIndex" title="la_fld_IsIndex"/>
<inp2:m_RenderElement name="inp_edit_radio" prefix="c" field="IsMenu" title="la_fld_MenuStatus"/>
<inp2:m_RenderElement name="subsection" prefix="c" fields="Status,NewItem,EditorsPick,Priority,UseMenuIconUrl,MenuIconUrl,UseExternalUrl,ExternalUrl,CreatedOn,MetaKeywords,MetaDescription,IndexTools" title="!la_section_Properties!"/>
Index: core/admin_templates/categories/xml/categories_list.tpl
===================================================================
--- core/admin_templates/categories/xml/categories_list.tpl (revision 12690)
+++ core/admin_templates/categories/xml/categories_list.tpl (working copy)
@@ -48,7 +48,7 @@
set_window_title( RemoveTranslationLink(document.getElementById('blue_bar').innerHTML, false).replace(/(<[^<]+>)/g, '') );
<inp2:m_DefineElement name="category_caption">
<span class="nav_current_item">
- <inp2:m_ifnot check="c_HomeCategory" equals_to="$cat_id">
+ <inp2:m_ifnot check="m_Param" name="is_first">
<inp2:m_param name="separator"/>
</inp2:m_ifnot>
<inp2:m_if check="m_ParamEquals" name="current" value="1" inverse="1">
Index: core/admin_templates/config/config_general.tpl
===================================================================
--- core/admin_templates/config/config_general.tpl (revision 12690)
+++ core/admin_templates/config/config_general.tpl (working copy)
@@ -100,7 +100,7 @@
</td>
<td>
<inp2:m_DefineElement name="category_caption">
- <inp2:m_ifnot check="c_HomeCategory" equals_to="$cat_id">
+ <inp2:m_ifnot check="m_Param" name="is_first">
<inp2:m_param name="separator"/>
</inp2:m_ifnot>
<inp2:m_param name="cat_name"/>
Index: core/admin_templates/incs/form_blocks.tpl
===================================================================
--- core/admin_templates/incs/form_blocks.tpl (revision 12690)
+++ core/admin_templates/incs/form_blocks.tpl (working copy)
@@ -576,9 +576,9 @@
<td class="control-cell">
<table cellpadding="0" cellspacing="0">
<tr>
- <td id="<inp2:{$prefix}_InputName field='$field'/>_path">
+ <td id="<inp2:{$prefix}_InputName field='$field'/>_path"<inp2:m_ifnot check="Field" name="$field" db="db"> style="display: none;"</inp2:m_ifnot>>
<inp2:m_DefineElement name="category_caption">
- <inp2:m_ifnot check="c_HomeCategory" equals_to="$cat_id">
+ <inp2:m_ifnot check="m_Param" name="is_first">
<inp2:m_param name="separator"/>
</inp2:m_ifnot>
<inp2:m_param name="cat_name"/>
@@ -593,14 +593,36 @@
<img src="img/icons/icon24_cat.gif" width="24" height="24" border="0"/>
</a>
- <a href="#" onclick="disable_category('<inp2:m_Param name='field'/>'); return false;"><inp2:m_Phrase name="la_Text_Disable"/></a>
+ <a href="#" id="<inp2:{$prefix}_InputName field='$field'/>_disable_link"<inp2:m_ifnot check="Field" name="$field" db="db"> style="display: none;"</inp2:m_ifnot>><inp2:m_Phrase name="la_Text_Disable"/></a>
<script type="text/javascript">
- function disable_category($field) {
- var $field = '<inp2:{$prefix}_InputName field="#FIELD_NAME#"/>'.replace('#FIELD_NAME#', $field);
- set_hidden_field($field, '');
- document.getElementById($field + '_path').style.display = 'none';
- }
+ function CategorySelector() {
+ }
+
+ CategorySelector.getField = function ($field) {
+ return jq('<inp2:{$prefix}_InputName field="#FIELD_NAME#"/>'.replace('#FIELD_NAME#', $field));
+ }
+
+ CategorySelector.disableCategory = function ($field) {
+ var $field_id = this.getField($field);
+
+ $('#' + $field_id).val('');
+ $('#' + $field_id + '_path, #' + $field_id + '_disable_link').hide();
+ }
+
+ $(document).ready(
+ function() {
+ var $field_id = CategorySelector.getField('<inp2:m_Param name="field" js_escape="1"/>');
+
+ $('#' + $field_id + '_disable_link').click(
+ function ($e) {
+ CategorySelector.disableCategory('<inp2:m_Param name="field" js_escape="1"/>');
+
+ return false;
+ }
+ );
+ }
+ );
</script>
</td>
</tr>
Index: core/admin_templates/tools/system_tools.tpl
===================================================================
--- core/admin_templates/tools/system_tools.tpl (revision 12690)
+++ core/admin_templates/tools/system_tools.tpl (working copy)
@@ -31,7 +31,7 @@
<table width="100%" border="0" cellspacing="0" cellpadding="4" class="bordered" id="config_table">
<inp2:m_RenderElement name="subsection" title="la_section_General"/>
<inp2:m_RenderElement name="service_elem" title="Reset mod_rewrite Cache" event_name="OnResetModRwCache"/>
- <inp2:m_RenderElement name="service_elem" title="Reset SMS Menu Cache" event_name="OnResetCMSMenuCache"/>
+ <inp2:m_RenderElement name="service_elem" title="Reset SMS Menu Cache" event_prefix="c" event_name="OnResetCMSMenuCache"/>
<inp2:m_RenderElement name="service_elem" title="Reset Sections Cache" event_name="OnResetSections"/>
<inp2:m_RenderElement name="service_elem" title="Reset Configs Cache" event_name="OnResetConfigsCache"/>
<inp2:m_RenderElement name="service_elem" title="Re-build Themes Files" event_name="OnRebuildThemes"/>
Index: core/install/english.lang
===================================================================
--- core/install/english.lang (revision 12690)
+++ core/install/english.lang (working copy)
@@ -32,7 +32,6 @@
<PHRASE Label="la_btn_Up" Module="Core" Type="1">VXA=</PHRASE>
<PHRASE Label="la_Cancel" Module="Core" Type="1">Q2FuY2Vs</PHRASE>
<PHRASE Label="la_category" Module="Core" Type="1">U2VjdGlvbg==</PHRASE>
- <PHRASE Label="la_CategoryIndex" Module="Core" Type="1">U2VjdGlvbiBJbmRleA==</PHRASE>
<PHRASE Label="la_category_daysnew_prompt" Module="Core" Type="1">TnVtYmVyIG9mIGRheXMgZm9yIGEgY2F0LiB0byBiZSBORVc=</PHRASE>
<PHRASE Label="la_category_metadesc" Module="Core" Type="1">RGVmYXVsdCBNRVRBIGRlc2NyaXB0aW9u</PHRASE>
<PHRASE Label="la_category_metakey" Module="Core" Type="1">RGVmYXVsdCBNRVRBIEtleXdvcmRz</PHRASE>
@@ -247,7 +246,6 @@
<PHRASE Label="la_config_YahooApplicationId" Module="Core" Type="1">WWFob28gQXBwbGljYXRpb25JZA==</PHRASE>
<PHRASE Label="la_ConfirmDeleteExportPreset" Module="Core" Type="1">QXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIGRlbGV0ZSBzZWxlY3RlZCBFeHBvcnQgUHJlc2V0Pw==</PHRASE>
<PHRASE Label="la_confirm_maintenance" Module="Core" Type="1">VGhlIHNlY3Rpb24gdHJlZSBtdXN0IGJlIHVwZGF0ZWQgdG8gcmVmbGVjdCB0aGUgbGF0ZXN0IGNoYW5nZXM=</PHRASE>
- <PHRASE Label="la_Container" Module="Core" Type="1">Q29udGFpbmVy</PHRASE>
<PHRASE Label="la_country_ABW" Module="Core" Type="1">QXJ1YmE=</PHRASE>
<PHRASE Label="la_country_AFG" Module="Core" Type="1">QWZnaGFuaXN0YW4=</PHRASE>
<PHRASE Label="la_country_AGO" Module="Core" Type="1">QW5nb2xh</PHRASE>
@@ -689,7 +687,6 @@
<PHRASE Label="la_fld_InstallModules" Module="Core" Type="1">SW5zdGFsbCBNb2R1bGVz</PHRASE>
<PHRASE Label="la_fld_InstallPhraseTypes" Module="Core" Type="1">SW5zdGFsbCBQaHJhc2UgVHlwZXM=</PHRASE>
<PHRASE Label="la_fld_IsBaseCategory" Module="Core" Type="1">VXNlIGN1cnJlbnQgc2VjdGlvbiBhcyByb290IGZvciB0aGUgZXhwb3J0</PHRASE>
- <PHRASE Label="la_fld_IsIndex" Module="Core" Type="1">SXMgSW5kZXggU2VjdGlvbg==</PHRASE>
<PHRASE Label="la_fld_IsPrimary" Module="Core" Type="1">UHJpbWFyeQ==</PHRASE>
<PHRASE Label="la_fld_IsRequired" Module="Core" Type="1">UmVxdWlyZWQ=</PHRASE>
<PHRASE Label="la_fld_IsSystem" Module="Core" Type="1">SXMgU3lzdGVt</PHRASE>
Index: core/install/install_schema.sql
===================================================================
--- core/install/install_schema.sql (revision 12690)
+++ core/install/install_schema.sql (working copy)
@@ -431,7 +431,6 @@
l5_MenuTitle varchar(255) NOT NULL DEFAULT '',
MetaTitle text,
IndexTools text,
- IsIndex tinyint(1) NOT NULL DEFAULT '0',
IsMenu tinyint(4) NOT NULL DEFAULT '1',
IsSystem tinyint(4) NOT NULL DEFAULT '0',
FormId int(11) DEFAULT NULL,
@@ -461,7 +460,6 @@
KEY `Status` (`Status`),
KEY CreatedOn (CreatedOn),
KEY EditorsPick (EditorsPick),
- KEY IsIndex (IsIndex),
KEY ThemeId (ThemeId)
);
Index: core/install/upgrades.php
===================================================================
--- core/install/upgrades.php (revision 12690)
+++ core/install/upgrades.php (working copy)
@@ -1195,4 +1195,41 @@
WHERE EventId IN (' . implode(',', $ids) . ')';
$this->Conn->Query($sql);
}
+
+ /**
+ * Transforms IsIndex field values to SymLinkCategoryId field
+ *
+ * @param string $mode when called mode {before, after)
+ */
+ function Upgrade_5_0_2($mode)
+ {
+ if ($mode == 'before') {
+// 0 - Regular, 1 - Category Index, 2 - Container
+
+ // get all categories, marked as category index
+ $sql = 'SELECT ParentPath, CategoryId
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE IsIndex = 1';
+ $category_indexes = $this->Conn->GetCol($sql, 'CategoryId');
+
+ foreach ($category_indexes as $category_id => $parent_path) {
+ $parent_path = explode('|', substr($parent_path, 1, -1));
+
+ // set symlink to $category_id for each category, marked as container in given category path
+ $sql = 'SELECT CategoryId
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE CategoryId IN (' . implode(',', $parent_path) . ') AND (IsIndex = 2)';
+ $category_containers = $this->Conn->GetCol($sql);
+
+ if ($category_containers) {
+ $sql = 'UPDATE ' . TABLE_PREFIX . 'Category
+ SET SymLinkCategoryId = ' . $category_id . '
+ WHERE CategoryId IN (' . implode(',', $category_containers) . ')';
+ $this->Conn->Query($sql);
+ }
+
+ }
+ }
+ }
+
}
\ No newline at end of file
Index: core/install/upgrades.sql
===================================================================
--- core/install/upgrades.sql (revision 12690)
+++ core/install/upgrades.sql (working copy)
@@ -1528,4 +1528,7 @@
CHANGE CachedTemplate CachedTemplate varchar(255) NOT NULL DEFAULT '',
CHANGE ThemeId ThemeId int(10) unsigned NOT NULL DEFAULT '0';
-ALTER TABLE UserSession CHANGE BrowserSignature BrowserSignature varchar(32) NOT NULL DEFAULT '';
\ No newline at end of file
+ALTER TABLE UserSession CHANGE BrowserSignature BrowserSignature varchar(32) NOT NULL DEFAULT '';
+ALTER TABLE Category DROP IsIndex;
+
+DELETE FROM Phrase WHERE Phrase IN ('la_CategoryIndex', 'la_Container', 'la_fld_IsIndex');
Index: core/kernel/application.php
===================================================================
--- core/kernel/application.php (revision 12690)
+++ core/kernel/application.php (working copy)
@@ -178,6 +178,13 @@
*/
var $TemplatesCache = null;
+ /**
+ * Physical template name mapping to their template names based on structure
+ *
+ * @var Array
+ */
+ var $structureTemplateMapping = Array ();
+
var $CompilationCache = array(); //used when compiling templates
var $CachedProcessors = array(); //used when running compiled templates
@@ -1310,11 +1317,29 @@
*/
function HREF($t, $prefix='', $params=null, $index_file=null)
{
- if(!$t) $t = $this->GetVar('t'); // moved from kMainTagProcessor->T()
+ static $theme_id = null;
+ if (!$t) {
+ $t = $this->GetVar('t'); // moved from kMainTagProcessor->T()
+ }
+
$t = preg_replace('/^Content\//i', '', $t);
+ if (!isset($theme_id)) {
+ $theme_id = $this->GetVar('m_theme');
+ }
+ if (substr($t, 0, 3) == 'id:') {
+ // link to structure page using it's id
+ $params['m_cat_id'] = substr($t, 3);
+ $t = $this->structureTemplateMapping[$t];
+ }
+
+ if (array_key_exists($t . ':' . $theme_id, $this->structureTemplateMapping)) {
+ // structure template corresponding to given physical template
+ $t = $this->structureTemplateMapping[$t . ':' . $theme_id];
+ }
+
/*if ($this->GetVar('skip_last_template')) {
$params['opener'] = 'p';
$this->SetVar('m_opener', 'p');
@@ -2008,6 +2033,17 @@
}
$this->Caches['ConfigVariables'] = $config_ids;
$this->ConfigCacheIds = $config_ids;
+
+ // get template mapping
+ $sql = 'SELECT Data
+ FROM ' . TABLE_PREFIX . 'Cache
+ WHERE VarName = "template_mapping"';
+ $template_mapping = $this->Conn->GetOne($sql);
+
+ if (!$this->Application->IsAdmin() && $template_mapping) {
+ // template mappings only for Front-End
+ $this->structureTemplateMapping = unserialize($template_mapping);
+ }
}
function UpdateCache()
Index: core/kernel/db/db_tag_processor.php
===================================================================
--- core/kernel/db/db_tag_processor.php (revision 12690)
+++ core/kernel/db/db_tag_processor.php (working copy)
@@ -670,11 +670,6 @@
*/
function prepareTagParams($tag_params = Array())
{
- /*if (isset($tag_params['list_name'])) {
- $list =& $this->GetList($tag_params);
- $this->Init($list->Prefix, $list->Special);
- }*/
-
$ret = $tag_params;
$ret['Prefix'] = $this->Prefix;
$ret['Special'] = $this->Special;
Index: core/kernel/kbase.php
===================================================================
--- core/kernel/kbase.php (revision 12690)
+++ core/kernel/kbase.php (working copy)
@@ -132,6 +132,27 @@
}
+ /**
+ * Append prefix and special to tag
+ * params (get them from tagname) like
+ * they were really passed as params
+ *
+ * @param string $prefix_special
+ * @param Array $tag_params
+ * @return Array
+ * @access protected
+ */
+ function prepareTagParams($prefix_special, $tag_params = Array())
+ {
+ $parts = explode('.', $prefix_special);
+
+ $ret = $tag_params;
+ $ret['Prefix'] = $parts[0];
+ $ret['Special'] = count($parts) > 1 ? $parts[1] : '';
+ $ret['PrefixSpecial'] = $prefix_special;
+
+ return $ret;
+ }
}
class kDBBase extends kBase {
Index: core/kernel/utility/debugger.php
===================================================================
--- core/kernel/utility/debugger.php (revision 12690)
+++ core/kernel/utility/debugger.php (working copy)
@@ -1427,7 +1427,7 @@
<select id="reset_cache" style="border: 1px solid #000000;">
<option value=""></option>
<option value="events[adm][OnResetModRwCache]">Reset mod_rewrite Cache</option>
- <option value="events[adm][OnResetCMSMenuCache]">Reset SMS Menu Cache</option>
+ <option value="events[c][OnResetCMSMenuCache]">Reset SMS Menu Cache</option>
<option value="events[adm][OnResetSections]">Reset Sections Cache</option>
<option value="events[adm][OnResetConfigsCache]">Reset Configs Cache</option>
<option value="events[adm][OnRebuildThemes]">Re-build Themes Files</option>
Index: core/units/admin/admin_events_handler.php
===================================================================
--- core/units/admin/admin_events_handler.php (revision 12690)
+++ core/units/admin/admin_events_handler.php (working copy)
@@ -43,9 +43,9 @@
$perm_value = null;
$system_events = Array (
- 'OnResetModRwCache', 'OnResetCMSMenuCache', 'OnResetSections',
- 'OnResetConfigsCache', 'OnDeleteCompiledTemplates', 'OnCompileTemplates',
- 'OnGenerateTableStructure', 'OnRebuildThemes', 'OnCheckPrefixConfig',
+ 'OnResetModRwCache', 'OnResetSections', 'OnResetConfigsCache',
+ 'OnDeleteCompiledTemplates', 'OnCompileTemplates', 'OnGenerateTableStructure',
+ 'OnRebuildThemes', 'OnCheckPrefixConfig',
);
if (in_array($event->Name, $system_events)) {
@@ -98,15 +98,6 @@
$this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName LIKE "mod_rw%"');
}
- function OnResetCMSMenuCache(&$event)
- {
- if ($this->Application->GetVar('ajax') == 'yes') {
- $event->status = erSTOP;
- }
-
- $this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName IN ("cms_menu", "StructureTree")');
- }
-
function OnResetSections(&$event)
{
if ($this->Application->GetVar('ajax') == 'yes') {
Index: core/units/categories/categories_config.php
===================================================================
--- core/units/categories/categories_config.php (revision 12690)
+++ core/units/categories/categories_config.php (working copy)
@@ -350,11 +350,6 @@
'MenuTitle' => Array ('type' => 'string', 'formatter' => 'kMultiLanguage', 'not_null' => 1, 'default' => ''),
'MetaTitle' => Array ('type' => 'string', 'default' => null),
'IndexTools' => Array ('type' => 'string', 'formatter' => 'kFormatter', 'using_fck' => 1, 'default' => null),
- 'IsIndex' =>
- Array (
- 'type' => 'int', 'not_null' => 1, 'default' => 0,
- 'formatter' => 'kOptionsFormatter', 'options' => Array (0 => 'la_Regular', 1 => 'la_CategoryIndex', 2 => 'la_Container'), 'use_phrases' => 1,
- ),
'IsMenu' => Array ('type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Show', 0 => 'la_Hide'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 1),
'IsSystem' => Array ('type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_System', 0 => 'la_text_User'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 0),
'FormId' => Array (
Index: core/units/categories/categories_event_handler.php
===================================================================
--- core/units/categories/categories_event_handler.php (revision 12690)
+++ core/units/categories/categories_event_handler.php (working copy)
@@ -62,6 +62,17 @@
*/
function CheckPermission(&$event)
{
+ if ($event->Name == 'OnResetCMSMenuCache') {
+ // events from "Tools -> System Tools" section are controlled via that section "edit" permission
+
+ $perm_helper =& $this->Application->recallObject('PermissionsHelper');
+ /* @var $perm_helper kPermissionsHelper */
+
+ $perm_value = $this->Application->CheckPermission('in-portal:service.edit');
+
+ return $perm_helper->finalizePermissionCheck($event, $perm_value);
+ }
+
if (!$this->Application->IsAdmin()) {
if ($event->Name == 'OnSetSortingDirect') {
// allow sorting on front event without view permission
@@ -469,6 +480,7 @@
$type_clauses['menu']['include'] = '%1$s.IsMenu = 1';
$type_clauses['menu']['except'] = '%1$s.IsMenu = 0';
+ $type_clauses['menu']['having_filter'] = false;
if (in_array('search', $types) || in_array('search', $except_types)) {
$event_mapping = Array (
@@ -600,7 +612,7 @@
$updater->OneStepRun();
}
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
$this->Application->RemoveVar('PermCache_UpdateRequired');
@@ -797,7 +809,7 @@
}
$this->Application->StoreVar('RefreshStructureTree', 1);
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
if ($is_editing) {
// 2. send email event to category owner, when it's status is changed (from admin)
@@ -1015,7 +1027,7 @@
$priority_helper->recalculatePriorities($event, 'ParentId = ' . $parent_id);
$this->Application->StoreVar('RefreshStructureTree', 1);
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
}
/**
@@ -1137,7 +1149,6 @@
$priority_helper =& $this->Application->recallObject('PriorityHelper');
/* @var $priority_helper kPriorityHelper */
-
if ($clipboard_data['cut']) {
$priority_helper->recalculatePriorities($event, 'ParentId = '.$source_category_id);
}
@@ -1158,7 +1169,7 @@
$event->redirect = 'categories/cache_updater';
}
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
$this->Application->StoreVar('RefreshStructureTree', 1);
}
}
@@ -1757,11 +1768,68 @@
*
* @param kEvent $event
*/
- function OnResetMenuCache(&$event)
+ function OnResetCMSMenuCache(&$event)
{
- $this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName IN ("cms_menu", "StructureTree")');
+ if ($this->Application->GetVar('ajax') == 'yes') {
+ $event->status = erSTOP;
+ }
+
+ $this->_resetMenuCache();
}
+ function _resetMenuCache()
+ {
+ // reset cms menu cache
+ $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache
+ WHERE VarName IN ("cms_menu", "StructureTree")';
+ $this->Conn->Query($sql);
+
+ // build structure template mapping
+ $sql = 'SELECT
+ IF(c.IsSystem, CONCAT(c.Template, ":", c.ThemeId), CONCAT("id:", c.CategoryId)) AS SrcTemplate,
+ LOWER(
+ IF(
+ c.SymLinkCategoryId IS NOT NULL,
+ (SELECT cc.NamedParentPath FROM ' . TABLE_PREFIX . 'Category AS cc WHERE cc.CategoryId = c.SymLinkCategoryId),
+ c.NamedParentPath
+ )
+ ) AS DstTemplate,
+ c.UseExternalUrl, c.ExternalUrl
+ FROM ' . TABLE_PREFIX . 'Category AS c
+ WHERE c.Status = ' . STATUS_ACTIVE;
+ $pages = $this->Conn->Query($sql, 'SrcTemplate');
+
+ $mapping = Array ();
+ $base_url = $this->Application->BaseURL();
+
+ foreach ($pages as $src_template => $page) {
+ // process external url, before placing in cache
+ if ($page['UseExternalUrl']) {
+ $external_url = $page['ExternalUrl'];
+
+ if (!preg_match('/^(.*?):\/\/(.*)$/', $external_url)) {
+ // url without protocol will be relative url to our site
+ $external_url = $base_url . $external_url;
+ }
+
+ $dst_template = 'external:' . $external_url;
+ }
+ else {
+ $dst_template = preg_replace('/^Content\//i', '', $page['DstTemplate']);
+ }
+
+ $mapping[$src_template] = $dst_template;
+ }
+
+ $fields_hash = Array (
+ 'VarName' => 'template_mapping',
+ 'Data' => serialize($mapping),
+ 'Cached' => adodb_mktime(),
+ );
+
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE');
+ }
+
/**
* Updates structure config
*
@@ -1946,7 +2014,7 @@
$updater->OneStepRun();
}
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
if ($error_count) {
// allow user to review error after structure page creation
@@ -1995,7 +2063,7 @@
$this->clearSelectedIDs($event);
$this->Application->StoreVar('RefreshStructureTree', 1);
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
}
/**
@@ -2010,7 +2078,7 @@
$parent_id = $this->Application->GetVar('m_cat_id');
$priority_helper->recalculatePriorities($event, 'ParentId = ' . $parent_id);
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
}
/**
Index: core/units/categories/categories_tag_processor.php
===================================================================
--- core/units/categories/categories_tag_processor.php (revision 12690)
+++ core/units/categories/categories_tag_processor.php (working copy)
@@ -14,20 +14,6 @@
class CategoriesTagProcessor extends kDBTagProcessor {
- /**
- * Cached version of site menu
- *
- * @var Array
- */
- var $Menu = null;
-
- /**
- * Parent path mapping used in CachedMenu tag
- *
- * @var Array
- */
- var $ParentPaths = Array ();
-
function SubCatCount($params)
{
$object =& $this->getObject($params);
@@ -224,34 +210,32 @@
return $ml_formatter->LangFieldName('Name');
}
+ /**
+ * Returns symlinked category for given category
+ *
+ * @param $category_id
+ */
function getCategorySymLink($category_id)
{
static $cache = null;
+ if (!$category_id) {
+ // don't bother to get symlink for "Home" category
+ return $category_id;
+ }
+
if (!isset($cache)) {
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
- $sql = 'SELECT SymLinkCategoryId, '.$id_field.'
- FROM '.$table_name.'
- WHERE SymLinkCategoryId IS NOT NULL';
+ // get symlinked categories, that are not yet deleted
+ $sql = 'SELECT c1.SymLinkCategoryId, c1.' . $id_field . '
+ FROM ' . $table_name . ' c1
+ JOIN ' . $table_name . ' c2 ON c1.SymLinkCategoryId = c2.' . $id_field;
$cache = $this->Conn->GetCol($sql, $id_field);
}
- if (isset($cache[$category_id])) {
-
- //check if sym. link category is valid
- $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.' = '.$cache[$category_id];
-
- $category_id = $this->Conn->GetOne($sql)? $cache[$category_id] : $category_id;
- }
-
- return $category_id;
+ return array_key_exists($category_id, $cache) ? $cache[$category_id] : $category_id;
}
function CategoryLink($params)
@@ -259,7 +243,7 @@
$category_id = getArrayValue($params, 'cat_id');
if ($category_id === false) {
- $category_id = $this->Application->GetVar($this->getPrefixSpecial().'_id');
+ $category_id = $this->Application->GetVar($this->getPrefixSpecial() . '_id');
}
if ("$category_id" == 'Root') {
@@ -269,7 +253,7 @@
$category_id = $this->Application->GetVar('m_cat_id');
}
- $category_id = $this->getCategorySymLink($category_id);
+ $category_id = $this->getCategorySymLink( (int)$category_id );
unset($params['cat_id'], $params['module']);
@@ -1564,119 +1548,6 @@
}
/**
- * Builds cached menu version
- *
- * @return Array
- */
- function _prepareMenu()
- {
- static $root_cat = null;
- static $root_path = null;
-
- if (!$root_cat) {
- $root_cat = $this->Application->ModuleInfo['Core']['RootCat'];
- $root_path = $this->Conn->GetOne('SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$root_cat);
- }
-
- if (!$this->Menu) {
- $menu = $this->Conn->GetRow('SELECT Data, Cached FROM '.TABLE_PREFIX.'Cache WHERE VarName = "cms_menu"');
- if ($menu && $menu['Cached'] > 0) {
- $menu = unserialize($menu['Data']);
- $this->ParentPaths = $menu['ParentPaths'];
- }
- else {
- $menu = $this->_altBuildMenuStructure(array('CategoryId' => $root_cat, 'ParentPath' => $root_path));
- $menu['ParentPaths'] = $this->ParentPaths;
- $this->Conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("cms_menu", '.$this->Conn->qstr(serialize($menu)).', '.adodb_mktime().')');
- }
- unset($menu['ParentPaths']);
- $this->Menu = $menu;
- }
-
- return Array ($this->Menu, $root_path);
- }
-
- /**
- * Returns category id based tag parameters
- *
- * @param Array $params
- * @return int
- */
- function _getCategoryId($params)
- {
- $cat = isset($params['category_id']) && $params['category_id'] != '' ? $params['category_id'] : $this->Application->GetVar('m_cat_id');
- if ("$cat" == 'parent') {
- $this_category =& $this->Application->recallObject('c');
- /* @var $this_category kDBItem */
-
- $cat = $this_category->GetDBField('ParentId');
- }
- else if ($cat == 0) {
- $cat = $this->Application->ModuleInfo['Core']['RootCat'];
- }
-
- return $cat;
- }
-
- /**
- * Prepares cms menu item block parameters
- *
- * @param Array $page
- * @param int $real_cat_id
- * @param string $root_path
- * @return Array
- */
- function _prepareMenuItem($page, $real_cat_id, $root_path)
- {
- static $language_id = null;
- static $primary_language_id = null;
-
- if (!isset($language_id)) {
- $language_id = $this->Application->GetVar('m_lang');
- $primary_language_id = $this->Application->GetDefaultLanguageId();
- }
-
- $title = $page['l'.$language_id.'_ItemName'] ? $page['l'.$language_id.'_ItemName'] : $page['l'.$primary_language_id.'_ItemName'];
- $active = false;
- $category_active = false;
-
- if ($page['ItemType'] == 'cat') {
- if ( isset($this->ParentPaths[$real_cat_id])) {
- $active = strpos($this->ParentPaths[$real_cat_id], $page['ParentPath']) !== false;
- }
- $category_active = $page['CategoryId'] == $real_cat_id;
- }
-
- if ($page['ItemType'] == 'cat_index') {
- $check_path = str_replace($root_path, '', $page['ParentPath']);
- $active = strpos($parent_path, $check_path) !== false;
- }
-
- if ($page['ItemType'] == 'page') {
- $active = $page['ItemPath'] == preg_replace('/^Content\//i', '', $this->Application->GetVar('t'));
- }
-
- $block_params = Array (
- 'title'=> $title,
- 'template'=> preg_replace('/^Content\//i', '', $page['ItemPath']),
- 'active'=>$active,
- 'category_active' => $category_active, // new
- 'parent_path'=>$page['ParentPath'],
- 'parent_id'=>$page['ParentId'],
- 'cat_id'=>$page['CategoryId'],
- 'is_index'=>$page['IsIndex'],
- 'item_type'=>$page['ItemType'],
- 'page_id'=>$page['ItemId'],
- 'has_sub_menu' => isset($page['sub_items']) && count($page['sub_items']) > 0,
- 'external_url' => $page['UseExternalUrl'] ? $page['ExternalUrl'] : false,
- 'menu_icon' => $page['UseMenuIconUrl'] ? $page['MenuIconUrl'] : false,
-
- );
-
- return $block_params;
- }
-
- /**
* Builds site menu
*
* @param Array $params
@@ -1684,77 +1555,13 @@
*/
function CachedMenu($params)
{
- list ($menu, $root_path) = $this->_prepareMenu();
- $cat = $this->_getCategoryId($params);
+ $menu_helper =& $this->Application->recallObject('MenuHelper');
+ /* @var $menu_helper MenuHelper */
- $parent_path = isset($this->ParentPaths[$cat]) ? $this->ParentPaths[$cat] : '';
- $parent_path = str_replace($root_path, '', $parent_path); //menu starts from module path
- $levels = explode('|',trim($parent_path,'|'));
- if ($levels[0] === '') $levels = array();
- if (isset($params['level']) && $params['level'] > count($levels)) return ;
-
- $level = max(isset($params['level']) ? $params['level']-1 : count($levels)-1, 0);
- $parent = isset($levels[$level]) ? $levels[$level] : 0;
-
- $cur_menu =& $menu;
- $menu_path = array_slice($levels, 0, $level+1);
- foreach ($menu_path as $elem) {
- $cur_menu =& $cur_menu['c'.$elem]['sub_items'];
- }
-
- $ret = '';
- $block_params = $this->prepareTagParams($params);
- $block_params['name'] = $params['render_as'];
-
- $this->Application->SetVar('cur_parent_path', $parent_path);
- $real_cat_id = $this->Application->GetVar('m_cat_id');
- if (is_array($cur_menu) && $cur_menu) {
- $cur_item = 1;
- $cur_menu = $this->_removeNonMenuItems($cur_menu);
- $block_params['total_items'] = count($cur_menu);
-
- foreach ($cur_menu as $page) {
- $block_params = array_merge_recursive2(
- $block_params,
- $this->_prepareMenuItem($page, $real_cat_id, $root_path)
- );
-
- $block_params['is_last'] = $cur_item == $block_params['total_items'];
- $block_params['is_first'] = $cur_item == 1;
-
- // bug #1: this breaks active section highlighting when 2 menu levels are printed on same page (both visible)
- // bug #2: people doesn't pass cat_id parameter to m_Link tags in their blocks, so this line helps them; when removed their links will lead to nowhere
- $this->Application->SetVar('m_cat_id', $page['CategoryId']);
-
- $ret .= $this->Application->ParseBlock($block_params, 1);
- $cur_item++;
- }
-
- $this->Application->SetVar('m_cat_id', $real_cat_id);
- }
-
- return $ret;
+ return $menu_helper->menuTag($this->getPrefixSpecial(), $params);
}
/**
- * Returns only items, that are visible in menu
- *
- * @param Array $menu
- * @return Array
- */
- function _removeNonMenuItems($menu)
- {
- foreach ($menu as $menu_index => $menu_item) {
- // $menu_index is in "cN" format, where N is category id
- if (!$menu_item['IsMenu']) {
- unset($menu[$menu_index]);
- }
- }
-
- return $menu;
- }
-
- /**
* Trick to allow some kind of output formatting when using CachedMenu tag
*
* @param Array $params
@@ -1852,97 +1659,6 @@
}
/**
- * Builds cache for children of given category (no matter, what menu status is)
- *
- * @param Array $parent
- * @return Array
- */
- function _altBuildMenuStructure($parent)
- {
- static $languages_count = null;
-
- if (!isset($languages_count)) {
- $sql = 'SELECT COUNT(*)
- FROM ' . TABLE_PREFIX . 'Language';
- $languages_count = ceil($this->Conn->GetOne($sql) / 5) * 5;
- }
-
- $items = Array ();
-
- $lang_part = '';
- for ($i = 1; $i <= $languages_count; $i++) {
-// $lang_part .= 'c.l' . $i . '_Name AS l' . $i . '_ItemName,' . "\n";
- $lang_part .= 'c.l' . $i . '_MenuTitle AS l' . $i . '_ItemName,' . "\n";
- }
-
- // Sub-categories from current category
- $query = 'SELECT
- c.CategoryId AS CategoryId,
- CONCAT(\'c\', c.CategoryId) AS ItemId,
- c.Priority AS ItemPriority,
- ' . $lang_part . '
- LOWER( IF(IsIndex = 2, (
- SELECT cc.NamedParentPath FROM ' . TABLE_PREFIX . 'Category AS cc
- WHERE
- cc.ParentId = c.CategoryId
- AND
- cc.Status IN (1,4)
- AND
- cc.IsIndex = 1
- ),
- c.NamedParentPath) ) AS ItemPath,
- 0 AS IsIndex,
- c.ParentPath AS ParentPath,
- c.ParentId As ParentId,
- \'cat\' AS ItemType,
- c.IsMenu, c.UseExternalUrl, c.ExternalUrl, c.UseMenuIconUrl, c.MenuIconUrl
- FROM ' . TABLE_PREFIX . 'Category AS c
- WHERE
- c.Status IN (1,4) AND
- #c.IsMenu = 1 AND
- c.ParentId = ' . $parent['CategoryId'];
- $items = array_merge($items, $this->Conn->Query($query, 'ItemId'));
-
- uasort($items, Array (&$this, '_menuSort'));
-
- $the_items = array();
- foreach ($items as $an_item) {
- $the_items[ $an_item['ItemId'] ] = $an_item;
- $this->ParentPaths[ $an_item['CategoryId'] ] = $an_item['ParentPath'];
- }
-
- $items = $the_items;
- foreach ($items as $key => $menu_item) {
- if ($menu_item['CategoryId'] == $parent['CategoryId']) {
- continue;
- }
-
- $sub_items = $this->_altBuildMenuStructure($menu_item);
- if ($sub_items) {
- $items[$key]['sub_items'] = $sub_items;
- }
- }
-
- return $items;
- }
-
- /**
- * Method for sorting pages by priority in decending order
- *
- * @param Array $a
- * @param Array $b
- * @return int
- */
- function _menuSort($a, $b)
- {
- if ($a['ItemPriority'] == $b['ItemPriority']) {
- return 0;
- }
-
- return ($a['ItemPriority'] < $b['ItemPriority']) ? 1 : -1; //descending
- }
-
- /**
* Prepares cms page description for search result page
*
* @param Array $params
Index: core/units/helpers/category_helper.php
===================================================================
--- core/units/helpers/category_helper.php (revision 12690)
+++ core/units/helpers/category_helper.php (working copy)
@@ -62,9 +62,16 @@
$block_params['no_editing'] = 1;
$block_params['category'] = 0;
$block_params['separator'] = $params['separator'];
- $current_template = $this->Application->GetVar('t');
$show_category = getArrayValue($params, 'show_category');
+ $current_template = $this->Application->GetVar('t');
+ $physical_template = array_search($current_template, $this->Application->structureTemplateMapping);
+
+ if ($physical_template !== false) {
+ // replace menu template name with it's actual template name on disk
+ list ($current_template) = explode(':', $physical_template, 2);
+ }
+
foreach ($navigation_parts as $template => $title) {
$block_params['template'] = $template;
Index: core/units/helpers/helpers_config.php
===================================================================
--- core/units/helpers/helpers_config.php (revision 12690)
+++ core/units/helpers/helpers_config.php (working copy)
@@ -50,6 +50,7 @@
Array ('pseudo' => 'LanguageImportHelper', 'class' => 'LanguageImportHelper', 'file' => 'language_import_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SkinHelper', 'class' => 'SkinHelper', 'file' => 'skin_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'SiteConfigHelper', 'pseudo' => 'SiteConfigHelper', 'file' => 'site_config_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('class' => 'MenuHelper', 'pseudo' => 'MenuHelper', 'file' => 'menu_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'InpCustomFieldsHelper', 'pseudo' => 'InpCustomFieldsHelper', 'file' => 'custom_fields_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'kCountryStatesHelper', 'pseudo' => 'CountryStatesHelper', 'file' => 'country_states_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Index: core/units/helpers/menu_helper.php
===================================================================
--- core/units/helpers/menu_helper.php (revision 0)
+++ core/units/helpers/menu_helper.php (revision 0)
@@ -0,0 +1,311 @@
+<?php
+
+ class MenuHelper extends kHelper {
+
+ /**
+ * Cached version of site menu
+ *
+ * @var Array
+ */
+ var $Menu = null;
+
+ /**
+ * Parent path mapping used in CachedMenu tag
+ *
+ * @var Array
+ */
+ var $parentPaths = Array ();
+
+ /**
+ * Builds site menu
+ *
+ * @param Array $params
+ * @return string
+ */
+ function menuTag($prefix_special, $params)
+ {
+ list ($menu, $root_path) = $this->_prepareMenu();
+ $cat = $this->_getCategoryId($params);
+
+ $parent_path = array_key_exists($cat, $this->parentPaths) ? $this->parentPaths[$cat] : '';
+ $parent_path = str_replace($root_path, '', $parent_path); // menu starts from module path
+
+ $levels = explode('|', trim($parent_path, '|'));
+
+ if ($levels[0] === '') {
+ $levels = Array ();
+ }
+
+ if (array_key_exists('level', $params) && $params['level'] > count($levels)) {
+ // current level is deeper, then requested level
+ return ;
+ }
+
+ $level = max(array_key_exists('level', $params) ? $params['level'] - 1 : count($levels) - 1, 0);
+ $parent = array_key_exists($level, $levels) ? $levels[$level] : 0;
+
+ $cur_menu =& $menu;
+ $menu_path = array_slice($levels, 0, $level + 1);
+
+ foreach ($menu_path as $elem) {
+ $cur_menu =& $cur_menu['c' . $elem]['sub_items'];
+ }
+
+ $block_params = $this->prepareTagParams($prefix_special, $params);
+ $block_params['name'] = $params['render_as'];
+
+ $this->Application->SetVar('cur_parent_path', $parent_path);
+ $real_cat_id = $this->Application->GetVar('m_cat_id');
+
+ if (!is_array($cur_menu) || !$cur_menu) {
+ // no menus on this level
+ return '';
+ }
+
+ $ret = '';
+ $cur_item = 1;
+ $cur_menu = $this->_removeNonMenuItems($cur_menu);
+ $block_params['total_items'] = count($cur_menu);
+
+ foreach ($cur_menu as $page) {
+ $block_params = array_merge_recursive2(
+ $block_params,
+ $this->_prepareMenuItem($page, $real_cat_id, $root_path)
+ );
+
+ $block_params['is_last'] = $cur_item == $block_params['total_items'];
+ $block_params['is_first'] = $cur_item == 1;
+
+ // bug #1: this breaks active section highlighting when 2 menu levels are printed on same page (both visible)
+ // bug #2: people doesn't pass cat_id parameter to m_Link tags in their blocks, so this line helps them; when removed their links will lead to nowhere
+ $this->Application->SetVar('m_cat_id', $page['CategoryId']);
+
+ $ret .= $this->Application->ParseBlock($block_params);
+ $cur_item++;
+ }
+
+ $this->Application->SetVar('m_cat_id', $real_cat_id);
+
+ return $ret;
+ }
+
+ /**
+ * Builds cached menu version
+ *
+ * @return Array
+ */
+ function _prepareMenu()
+ {
+ static $root_cat = null;
+ static $root_path = null;
+
+ if (!$root_cat) {
+ $root_cat = $this->Application->ModuleInfo['Core']['RootCat'];
+
+ $sql = 'SELECT ParentPath
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE CategoryId = ' . $root_cat;
+ $root_path = $this->Conn->GetOne($sql);
+ }
+
+ if (!$this->Menu) {
+ $menu = $this->Conn->GetRow('SELECT Data, Cached FROM '.TABLE_PREFIX.'Cache WHERE VarName = "cms_menu"');
+ if ($menu && $menu['Cached'] > 0) {
+ $menu = unserialize($menu['Data']);
+ $this->parentPaths = $menu['parentPaths'];
+ }
+ else {
+ $menu = $this->_altBuildMenuStructure(Array ('CategoryId' => $root_cat, 'ParentPath' => $root_path));
+ $menu['parentPaths'] = $this->parentPaths;
+
+ $this->Conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("cms_menu", '.$this->Conn->qstr(serialize($menu)).', '.adodb_mktime().')');
+ }
+
+ unset($menu['parentPaths']);
+ $this->Menu = $menu;
+ }
+
+ return Array ($this->Menu, $root_path);
+ }
+
+ /**
+ * Returns category id based tag parameters
+ *
+ * @param Array $params
+ * @return int
+ */
+ function _getCategoryId($params)
+ {
+ $cat = isset($params['category_id']) && $params['category_id'] != '' ? $params['category_id'] : $this->Application->GetVar('m_cat_id');
+ if ("$cat" == 'parent') {
+ $this_category =& $this->Application->recallObject('c');
+ /* @var $this_category kDBItem */
+
+ $cat = $this_category->GetDBField('ParentId');
+ }
+ elseif ($cat == 0) {
+ $cat = $this->Application->ModuleInfo['Core']['RootCat'];
+ }
+
+ return $cat;
+ }
+
+ /**
+ * Prepares cms menu item block parameters
+ *
+ * @param Array $page
+ * @param int $real_cat_id
+ * @param string $root_path
+ * @return Array
+ */
+ function _prepareMenuItem($page, $real_cat_id, $root_path)
+ {
+ static $language_id = null;
+ static $primary_language_id = null;
+
+ if (!isset($language_id)) {
+ $language_id = $this->Application->GetVar('m_lang');
+ $primary_language_id = $this->Application->GetDefaultLanguageId();
+ }
+
+ $active = $category_active = false;
+ $title = $page['l' . $language_id . '_ItemName'] ? $page['l' . $language_id . '_ItemName'] : $page['l' . $primary_language_id . '_ItemName'];
+
+ if ($page['ItemType'] == 'cat') {
+ if (array_key_exists($real_cat_id, $this->parentPaths)) {
+ $active = strpos($this->parentPaths[$real_cat_id], $page['ParentPath']) !== false;
+ }
+
+ $category_active = $page['CategoryId'] == $real_cat_id;
+ }
+
+ /*if ($page['ItemType'] == 'cat_index') {
+ $check_path = str_replace($root_path, '', $page['ParentPath']);
+ $active = strpos($parent_path, $check_path) !== false;
+ }
+
+ if ($page['ItemType'] == 'page') {
+ $active = $page['ItemPath'] == preg_replace('/^Content\//i', '', $this->Application->GetVar('t'));
+ }*/
+
+ $block_params = Array (
+ 'title' => $title,
+ 'template' => $page['ItemPath'],
+ 'active' => $active,
+ 'category_active' => $category_active, // new
+ 'parent_path' => $page['ParentPath'],
+ 'parent_id' => $page['ParentId'],
+ 'cat_id' => $page['CategoryId'],
+ 'item_type' => $page['ItemType'],
+ 'page_id' => $page['ItemId'],
+ 'has_sub_menu' => isset($page['sub_items']) && count($page['sub_items']) > 0,
+ 'external_url' => $page['UseExternalUrl'] ? $page['ExternalUrl'] : false, // for backward compatibility
+ 'menu_icon' => $page['UseMenuIconUrl'] ? $page['MenuIconUrl'] : false,
+ );
+
+ return $block_params;
+ }
+
+ /**
+ * Returns only items, that are visible in menu
+ *
+ * @param Array $menu
+ * @return Array
+ */
+ function _removeNonMenuItems($menu)
+ {
+ foreach ($menu as $menu_index => $menu_item) {
+ // $menu_index is in "cN" format, where N is category id
+ if (!$menu_item['IsMenu']) {
+ unset($menu[$menu_index]);
+ }
+ }
+
+ return $menu;
+ }
+
+ /**
+ * Builds cache for children of given category (no matter, what menu status is)
+ *
+ * @param Array $parent
+ * @return Array
+ */
+ function _altBuildMenuStructure($parent)
+ {
+ static $lang_part = null;
+
+ if (!isset($lang_part)) {
+ $sql = 'SELECT COUNT(*)
+ FROM ' . TABLE_PREFIX . 'Language';
+ $languages_count = ceil($this->Conn->GetOne($sql) / 5) * 5;
+
+ $lang_part = '';
+
+ for ($i = 1; $i <= $languages_count; $i++) {
+ $lang_part .= 'c.l' . $i . '_MenuTitle AS l' . $i . '_ItemName,' . "\n";
+ }
+ }
+
+ $items = Array ();
+
+ // Sub-categories from current category
+ $sql = 'SELECT
+ c.CategoryId AS CategoryId,
+ CONCAT(\'c\', c.CategoryId) AS ItemId,
+ c.Priority AS ItemPriority,
+ ' . $lang_part . '
+
+ IF(c.IsSystem, CONCAT(c.Template, ":", c.ThemeId), CONCAT("id:", c.CategoryId)) AS ItemPath,
+ c.ParentPath AS ParentPath,
+ c.ParentId As ParentId,
+ \'cat\' AS ItemType,
+ c.IsMenu, c.UseExternalUrl, c.ExternalUrl, c.UseMenuIconUrl, c.MenuIconUrl
+ FROM ' . TABLE_PREFIX . 'Category AS c
+ WHERE (c.Status = ' . STATUS_ACTIVE . ') AND (c.ParentId = ' . $parent['CategoryId'] . ')';
+ $items = array_merge($items, $this->Conn->Query($sql, 'ItemId'));
+
+ // sort menu items
+ uasort($items, Array (&$this, '_menuSort'));
+
+ // store menu items
+ $the_items = Array();
+ foreach ($items as $index => $an_item) {
+ $the_items[ $an_item['ItemId'] ] = $an_item;
+
+ $this->parentPaths[ $an_item['CategoryId'] ] = $an_item['ParentPath'];
+ }
+
+ // process submenus of each menu
+ $items = $the_items;
+ foreach ($items as $key => $menu_item) {
+ if ($menu_item['CategoryId'] == $parent['CategoryId']) {
+ // don't process myself - prevents recursion
+ continue;
+ }
+
+ $sub_items = $this->_altBuildMenuStructure($menu_item);
+
+ if ($sub_items) {
+ $items[$key]['sub_items'] = $sub_items;
+ }
+ }
+
+ return $items;
+ }
+
+ /**
+ * Method for sorting pages by priority in decending order
+ *
+ * @param Array $a
+ * @param Array $b
+ * @return int
+ */
+ function _menuSort($a, $b)
+ {
+ if ($a['ItemPriority'] == $b['ItemPriority']) {
+ return 0;
+ }
+
+ return ($a['ItemPriority'] < $b['ItemPriority']) ? 1 : -1; //descending
+ }
+ }
Index: core/units/helpers/mod_rewrite_helper.php
===================================================================
--- core/units/helpers/mod_rewrite_helper.php (revision 12690)
+++ core/units/helpers/mod_rewrite_helper.php (working copy)
@@ -584,7 +584,7 @@
$vars['m_cat_page'] = $rets[2];
}
- $sql = 'SELECT CategoryId, IsIndex, NamedParentPath
+ $sql = 'SELECT CategoryId, SymLinkCategoryId, NamedParentPath
FROM ' . TABLE_PREFIX . 'Category
WHERE Status IN (1,4) AND (LOWER(NamedParentPath) = ' . $this->Conn->qstr($category_path) . ') AND (ThemeId = ' . $vars['m_theme'] . ' OR ThemeId = 0)';
$category_info = $this->Conn->GetRow($sql);
@@ -597,15 +597,17 @@
} while ($category_info !== false && $url_part);
if ($last_category_info) {
- // IsIndex = 2 is a Container-only page, meaning it should go to index-page child
- if ($last_category_info['IsIndex'] == 2) {
+ // this category is symlink to other category, so use it's url instead
+ // (used in case if url prior to symlink adding was indexed by spider or was bookmarked)
+ if ($last_category_info['SymLinkCategoryId']) {
$sql = 'SELECT CategoryId, NamedParentPath
FROM ' . TABLE_PREFIX . 'Category
- WHERE (ParentId = ' . $last_category_info['CategoryId'] . ') AND (IsIndex = 1) AND (ThemeId = ' . $vars['m_theme'] . ' OR ThemeId = 0)';
+ WHERE (CategoryId = ' . $last_category_info['SymLinkCategoryId'] . ')';
$category_info = $this->Conn->GetRow($sql);
if ($category_info) {
- // when index sub-page is found use it, otherwise use container page
+ // web symlinked category was found use it
+ // TODO: maybe 302 redirect should be made to symlinked category url (all other url parts should stay)
$last_category_info = $category_info;
}
}
Index: core/units/structure/structure_config.php
===================================================================
--- core/units/structure/structure_config.php (revision 12690)
+++ core/units/structure/structure_config.php (working copy)
@@ -158,11 +158,6 @@
'MenuTitle' => Array('type' => 'string', 'formatter' => 'kMultiLanguage', 'not_null' => 1, 'default' => ''),
'MetaTitle' => Array('type' => 'string', 'default' => null),
'IndexTools' => Array('type' => 'string','default' => null),
- 'IsIndex' =>
- Array(
- 'type' => 'int','not_null' => 1, 'default' => 0,
- 'formatter' => 'kOptionsFormatter', 'options' => Array (0 => 'la_Regular', 1 => 'la_CategoryIndex', 2=>'la_Container'), 'use_phrases' => 1,
- ),
'IsMenu' => Array('type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Show', 0 => 'la_Hide'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 1),
'IsSystem' => Array('type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_System', 0 => 'la_Regular'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 0),
'FormId' => Array('type' => 'int', 'formatter' => 'kOptionsFormatter',
symlink_for_physical_templates_v2.patch [^] (51,763 bytes) 2009-10-25 14:47
[Show Content]
Index: admin/system_presets/simple/categories_c.php
===================================================================
--- admin/system_presets/simple/categories_c.php (revision 12778)
+++ admin/system_presets/simple/categories_c.php (working copy)
@@ -40,12 +40,12 @@
// fields to hide
$hidden_fields = Array (
- 'CategoryId', /*'Type',*/ 'SymLinkCategoryId', /*'ParentId', 'Name', 'Filename', 'AutomaticFilename',*/
+ 'CategoryId', /*'Type', 'SymLinkCategoryId', 'ParentId', 'Name', 'Filename', 'AutomaticFilename',*/
/*'Description',*/ 'CreatedOn', 'EditorsPick', 'Status', /*'Priority', 'MetaKeywords', 'CachedDescendantCatsQty',
'CachedNavbar',*/ 'CreatedById', /*'ResourceId', 'ParentPath', 'TreeLeft', 'TreeRight', 'NamedParentPath',
'MetaDescription', 'HotItem',*/ 'NewItem', /*'PopItem', 'Modified', 'ModifiedById', 'CachedTemplate',*/
'Template', /*'UseExternalUrl', 'ExternalUrl',*/ 'UseMenuIconUrl', 'MenuIconUrl', 'Title', 'MenuTitle',
- /*'MetaTitle', 'IndexTools', 'IsIndex', 'IsMenu', 'IsSystem',*/ 'FormId', 'FormSubmittedTemplate',
+ /*'MetaTitle', 'IndexTools', 'IsMenu', 'IsSystem',*/ 'FormId', 'FormSubmittedTemplate',
/*'FriendlyURL', 'ThemeId'*/
);
@@ -56,7 +56,7 @@
);
$debug_only_fields = Array (
- 'Filename', 'AutomaticFilename', 'IsIndex',
+ 'Filename', 'AutomaticFilename', 'SymLinkCategoryId'
);
// fields to make required
Index: core/admin_templates/categories/categories_edit.tpl
===================================================================
--- core/admin_templates/categories/categories_edit.tpl (revision 12775)
+++ core/admin_templates/categories/categories_edit.tpl (working copy)
@@ -72,7 +72,7 @@
<inp2:m_RenderElement name="inp_edit_box" prefix="c" field="Filename" title="la_fld_Filename" size="70" /> <!-- la_fld_CategoryFilename -->
<inp2:m_RenderElement name="inp_edit_category" prefix="c" field="SymLinkCategoryId" title="la_fld_SymLinkCategoryId"/>
- <inp2:m_RenderElement name="subsection" prefix="c" fields="Title,MenuTitle,FriendlyURL,ParentId,Template,FormId,FormSubmittedTemplate,IsIndex,IsMenu" title="la_section_Page"/>
+ <inp2:m_RenderElement name="subsection" prefix="c" fields="Title,MenuTitle,FriendlyURL,ParentId,Template,FormId,FormSubmittedTemplate,IsMenu" title="la_section_Page"/>
<inp2:m_RenderElement name="inp_edit_box_ml" prefix="c" field="Title" title="!la_fld_PageContentTitle!" size="40"/>
<inp2:m_RenderElement name="inp_edit_box_ml" prefix="c" field="MenuTitle" title="!la_fld_PageMentTitle!" size="40"/>
@@ -91,7 +91,6 @@
<inp2:m_RenderElement name="inp_edit_options" prefix="c" field="FormId" title="!la_fld_Form!"/>
<inp2:m_RenderElement name="inp_edit_box" prefix="c" field="FormSubmittedTemplate" title="la_fld_FormSubmittedTemplate" size="60"/>
- <inp2:m_RenderElement name="inp_edit_options" prefix="c" field="IsIndex" title="la_fld_IsIndex"/>
<inp2:m_RenderElement name="inp_edit_radio" prefix="c" field="IsMenu" title="la_fld_MenuStatus"/>
<inp2:m_RenderElement name="subsection" prefix="c" fields="Status,NewItem,EditorsPick,Priority,UseMenuIconUrl,MenuIconUrl,UseExternalUrl,ExternalUrl,CreatedOn,MetaKeywords,MetaDescription,IndexTools" title="!la_section_Properties!"/>
Index: core/admin_templates/config/config_general.tpl
===================================================================
--- core/admin_templates/config/config_general.tpl (revision 12775)
+++ core/admin_templates/config/config_general.tpl (working copy)
@@ -100,7 +100,7 @@
</td>
<td>
<inp2:m_DefineElement name="category_caption">
- <inp2:m_ifnot check="c_HomeCategory" equals_to="$cat_id">
+ <inp2:m_ifnot check="m_Param" name="is_first">
<inp2:m_param name="separator"/>
</inp2:m_ifnot>
<inp2:m_param name="cat_name"/>
Index: core/admin_templates/incs/form_blocks.tpl
===================================================================
--- core/admin_templates/incs/form_blocks.tpl (revision 12775)
+++ core/admin_templates/incs/form_blocks.tpl (working copy)
@@ -576,9 +576,9 @@
<td class="control-cell">
<table cellpadding="0" cellspacing="0">
<tr>
- <td id="<inp2:{$prefix}_InputName field='$field'/>_path">
+ <td id="<inp2:{$prefix}_InputName field='$field'/>_path"<inp2:m_ifnot check="Field" name="$field" db="db"> style="display: none;"</inp2:m_ifnot>>
<inp2:m_DefineElement name="category_caption">
- <inp2:m_ifnot check="c_HomeCategory" equals_to="$cat_id">
+ <inp2:m_ifnot check="m_Param" name="is_first">
<inp2:m_param name="separator"/>
</inp2:m_ifnot>
<inp2:m_param name="cat_name"/>
@@ -593,14 +593,36 @@
<img src="img/icons/icon24_cat.gif" width="24" height="24" border="0"/>
</a>
- <a href="#" onclick="disable_category('<inp2:m_Param name='field'/>'); return false;"><inp2:m_Phrase name="la_Text_Disable"/></a>
+ <a href="#" id="<inp2:{$prefix}_InputName field='$field'/>_disable_link"<inp2:m_ifnot check="Field" name="$field" db="db"> style="display: none;"</inp2:m_ifnot>><inp2:m_Phrase name="la_Text_Disable"/></a>
<script type="text/javascript">
- function disable_category($field) {
- var $field = '<inp2:{$prefix}_InputName field="#FIELD_NAME#"/>'.replace('#FIELD_NAME#', $field);
- set_hidden_field($field, '');
- document.getElementById($field + '_path').style.display = 'none';
- }
+ function CategorySelector() {
+ }
+
+ CategorySelector.getField = function ($field) {
+ return jq('<inp2:{$prefix}_InputName field="#FIELD_NAME#"/>'.replace('#FIELD_NAME#', $field));
+ }
+
+ CategorySelector.disableCategory = function ($field) {
+ var $field_id = this.getField($field);
+
+ $('#' + $field_id).val('');
+ $('#' + $field_id + '_path, #' + $field_id + '_disable_link').hide();
+ }
+
+ $(document).ready(
+ function() {
+ var $field_id = CategorySelector.getField('<inp2:m_Param name="field" js_escape="1"/>');
+
+ $('#' + $field_id + '_disable_link').click(
+ function ($e) {
+ CategorySelector.disableCategory('<inp2:m_Param name="field" js_escape="1"/>');
+
+ return false;
+ }
+ );
+ }
+ );
</script>
</td>
</tr>
Index: core/admin_templates/tools/system_tools.tpl
===================================================================
--- core/admin_templates/tools/system_tools.tpl (revision 12775)
+++ core/admin_templates/tools/system_tools.tpl (working copy)
@@ -31,7 +31,7 @@
<table width="100%" border="0" cellspacing="0" cellpadding="4" class="bordered" id="config_table">
<inp2:m_RenderElement name="subsection" title="la_section_General"/>
<inp2:m_RenderElement name="service_elem" title="Reset mod_rewrite Cache" event_name="OnResetModRwCache"/>
- <inp2:m_RenderElement name="service_elem" title="Reset SMS Menu Cache" event_name="OnResetCMSMenuCache"/>
+ <inp2:m_RenderElement name="service_elem" title="Reset SMS Menu Cache" event_prefix="c" event_name="OnResetCMSMenuCache"/>
<inp2:m_RenderElement name="service_elem" title="Reset Sections Cache" event_name="OnResetSections"/>
<inp2:m_RenderElement name="service_elem" title="Reset Configs Cache" event_name="OnResetConfigsCache"/>
<inp2:m_RenderElement name="service_elem" title="Re-build Themes Files" event_name="OnRebuildThemes"/>
Index: core/install.php
===================================================================
--- core/install.php (revision 12775)
+++ core/install.php (working copy)
@@ -961,7 +961,7 @@
}
foreach ($versions as $version) {
- $upgrade_method = 'Upgrade_'.str_replace('.', '_', $version);
+ $upgrade_method = 'Upgrade_'.str_replace(Array ('.', '-'), '_', $version);
if (method_exists($upgrade_object, $upgrade_method)) {
$upgrade_object->$upgrade_method($mode);
}
Index: core/install/english.lang
===================================================================
--- core/install/english.lang (revision 12775)
+++ core/install/english.lang (working copy)
@@ -32,7 +32,6 @@
<PHRASE Label="la_btn_Up" Module="Core" Type="1">VXA=</PHRASE>
<PHRASE Label="la_Cancel" Module="Core" Type="1">Q2FuY2Vs</PHRASE>
<PHRASE Label="la_category" Module="Core" Type="1">U2VjdGlvbg==</PHRASE>
- <PHRASE Label="la_CategoryIndex" Module="Core" Type="1">U2VjdGlvbiBJbmRleA==</PHRASE>
<PHRASE Label="la_category_daysnew_prompt" Module="Core" Type="1">TnVtYmVyIG9mIGRheXMgZm9yIGEgY2F0LiB0byBiZSBORVc=</PHRASE>
<PHRASE Label="la_category_metadesc" Module="Core" Type="1">RGVmYXVsdCBNRVRBIGRlc2NyaXB0aW9u</PHRASE>
<PHRASE Label="la_category_metakey" Module="Core" Type="1">RGVmYXVsdCBNRVRBIEtleXdvcmRz</PHRASE>
@@ -247,7 +246,6 @@
<PHRASE Label="la_config_YahooApplicationId" Module="Core" Type="1">WWFob28gQXBwbGljYXRpb25JZA==</PHRASE>
<PHRASE Label="la_ConfirmDeleteExportPreset" Module="Core" Type="1">QXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIGRlbGV0ZSBzZWxlY3RlZCBFeHBvcnQgUHJlc2V0Pw==</PHRASE>
<PHRASE Label="la_confirm_maintenance" Module="Core" Type="1">VGhlIHNlY3Rpb24gdHJlZSBtdXN0IGJlIHVwZGF0ZWQgdG8gcmVmbGVjdCB0aGUgbGF0ZXN0IGNoYW5nZXM=</PHRASE>
- <PHRASE Label="la_Container" Module="Core" Type="1">Q29udGFpbmVy</PHRASE>
<PHRASE Label="la_country_ABW" Module="Core" Type="1">QXJ1YmE=</PHRASE>
<PHRASE Label="la_country_AFG" Module="Core" Type="1">QWZnaGFuaXN0YW4=</PHRASE>
<PHRASE Label="la_country_AGO" Module="Core" Type="1">QW5nb2xh</PHRASE>
@@ -689,7 +687,6 @@
<PHRASE Label="la_fld_InstallModules" Module="Core" Type="1">SW5zdGFsbCBNb2R1bGVz</PHRASE>
<PHRASE Label="la_fld_InstallPhraseTypes" Module="Core" Type="1">SW5zdGFsbCBQaHJhc2UgVHlwZXM=</PHRASE>
<PHRASE Label="la_fld_IsBaseCategory" Module="Core" Type="1">VXNlIGN1cnJlbnQgc2VjdGlvbiBhcyByb290IGZvciB0aGUgZXhwb3J0</PHRASE>
- <PHRASE Label="la_fld_IsIndex" Module="Core" Type="1">SXMgSW5kZXggU2VjdGlvbg==</PHRASE>
<PHRASE Label="la_fld_IsPrimary" Module="Core" Type="1">UHJpbWFyeQ==</PHRASE>
<PHRASE Label="la_fld_IsRequired" Module="Core" Type="1">UmVxdWlyZWQ=</PHRASE>
<PHRASE Label="la_fld_IsSystem" Module="Core" Type="1">SXMgU3lzdGVt</PHRASE>
Index: core/install/install_schema.sql
===================================================================
--- core/install/install_schema.sql (revision 12775)
+++ core/install/install_schema.sql (working copy)
@@ -431,7 +431,6 @@
l5_MenuTitle varchar(255) NOT NULL DEFAULT '',
MetaTitle text,
IndexTools text,
- IsIndex tinyint(1) NOT NULL DEFAULT '0',
IsMenu tinyint(4) NOT NULL DEFAULT '1',
IsSystem tinyint(4) NOT NULL DEFAULT '0',
FormId int(11) DEFAULT NULL,
@@ -461,7 +460,6 @@
KEY `Status` (`Status`),
KEY CreatedOn (CreatedOn),
KEY EditorsPick (EditorsPick),
- KEY IsIndex (IsIndex),
KEY ThemeId (ThemeId)
);
Index: core/install/upgrades.php
===================================================================
--- core/install/upgrades.php (revision 12775)
+++ core/install/upgrades.php (working copy)
@@ -1195,4 +1195,41 @@
WHERE EventId IN (' . implode(',', $ids) . ')';
$this->Conn->Query($sql);
}
+
+ /**
+ * Transforms IsIndex field values to SymLinkCategoryId field
+ *
+ * @param string $mode when called mode {before, after)
+ */
+ function Upgrade_5_0_2_B2($mode)
+ {
+ if ($mode == 'before') {
+// 0 - Regular, 1 - Category Index, 2 - Container
+
+ // get all categories, marked as category index
+ $sql = 'SELECT ParentPath, CategoryId
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE IsIndex = 1';
+ $category_indexes = $this->Conn->GetCol($sql, 'CategoryId');
+
+ foreach ($category_indexes as $category_id => $parent_path) {
+ $parent_path = explode('|', substr($parent_path, 1, -1));
+
+ // set symlink to $category_id for each category, marked as container in given category path
+ $sql = 'SELECT CategoryId
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE CategoryId IN (' . implode(',', $parent_path) . ') AND (IsIndex = 2)';
+ $category_containers = $this->Conn->GetCol($sql);
+
+ if ($category_containers) {
+ $sql = 'UPDATE ' . TABLE_PREFIX . 'Category
+ SET SymLinkCategoryId = ' . $category_id . '
+ WHERE CategoryId IN (' . implode(',', $category_containers) . ')';
+ $this->Conn->Query($sql);
+ }
+
+ }
+ }
+ }
+
}
\ No newline at end of file
Index: core/install/upgrades.sql
===================================================================
--- core/install/upgrades.sql (revision 12775)
+++ core/install/upgrades.sql (working copy)
@@ -1595,4 +1595,8 @@
ALTER TABLE ItemFiles CHANGE CreatedOn CreatedOn INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE FormSubmissions CHANGE SubmissionTime SubmissionTime INT(11) NULL DEFAULT NULL;
ALTER TABLE SessionLogs CHANGE SessionStart SessionStart INT(11) NULL DEFAULT NULL;
-ALTER TABLE Visits CHANGE VisitDate VisitDate INT(10) UNSIGNED NULL DEFAULT NULL;
\ No newline at end of file
+ALTER TABLE Visits CHANGE VisitDate VisitDate INT(10) UNSIGNED NULL DEFAULT NULL;
+
+# ===== v 5.0.2-B2 =====
+ALTER TABLE Category DROP IsIndex;
+DELETE FROM Phrase WHERE Phrase IN ('la_CategoryIndex', 'la_Container', 'la_fld_IsIndex');
\ No newline at end of file
Index: core/kernel/application.php
===================================================================
--- core/kernel/application.php (revision 12775)
+++ core/kernel/application.php (working copy)
@@ -178,6 +178,13 @@
*/
var $TemplatesCache = null;
+ /**
+ * Physical template name mapping to their template names based on structure
+ *
+ * @var Array
+ */
+ var $structureTemplateMapping = Array ();
+
var $CompilationCache = array(); //used when compiling templates
var $CachedProcessors = array(); //used when running compiled templates
@@ -1336,6 +1343,12 @@
*/
function HREF($t, $prefix='', $params=null, $index_file=null)
{
+ static $theme_id = null;
+
+ if (!isset($theme_id)) {
+ $theme_id = $this->GetVar('m_theme');
+ }
+
if (!$t) {
$t = $this->GetVar('t'); // moved from kMainTagProcessor->T()
}
@@ -1346,6 +1359,17 @@
$t = substr($t, 0, strlen($t) - 4);
}
+ if (substr($t, 0, 3) == 'id:') {
+ // link to structure page using it's id
+ $params['m_cat_id'] = substr($t, 3);
+ $t = $this->structureTemplateMapping[$t];
+ }
+
+ if (array_key_exists($t . ':' . $theme_id, $this->structureTemplateMapping)) {
+ // structure template corresponding to given physical template
+ $t = $this->structureTemplateMapping[$t . ':' . $theme_id];
+ }
+
if ($this->isAdmin && $prefix == '') $prefix = ADMIN_DIRECTORY;
if ($this->isAdmin && $prefix == '_FRONT_END_') $prefix = '';
@@ -2034,6 +2058,17 @@
}
$this->Caches['ConfigVariables'] = $config_ids;
$this->ConfigCacheIds = $config_ids;
+
+ // get template mapping
+ $sql = 'SELECT Data
+ FROM ' . TABLE_PREFIX . 'Cache
+ WHERE VarName = "template_mapping"';
+ $template_mapping = $this->Conn->GetOne($sql);
+
+ if (!$this->isAdmin && $template_mapping) {
+ // template mappings only for Front-End
+ $this->structureTemplateMapping = unserialize($template_mapping);
+ }
}
function UpdateCache()
Index: core/kernel/db/db_tag_processor.php
===================================================================
--- core/kernel/db/db_tag_processor.php (revision 12775)
+++ core/kernel/db/db_tag_processor.php (working copy)
@@ -671,11 +671,6 @@
*/
function prepareTagParams($tag_params = Array())
{
- /*if (isset($tag_params['list_name'])) {
- $list =& $this->GetList($tag_params);
- $this->Init($list->Prefix, $list->Special);
- }*/
-
$ret = $tag_params;
$ret['Prefix'] = $this->Prefix;
$ret['Special'] = $this->Special;
Index: core/kernel/kbase.php
===================================================================
--- core/kernel/kbase.php (revision 12775)
+++ core/kernel/kbase.php (working copy)
@@ -132,6 +132,27 @@
}
+ /**
+ * Append prefix and special to tag
+ * params (get them from tagname) like
+ * they were really passed as params
+ *
+ * @param string $prefix_special
+ * @param Array $tag_params
+ * @return Array
+ * @access protected
+ */
+ function prepareTagParams($prefix_special, $tag_params = Array())
+ {
+ $parts = explode('.', $prefix_special);
+
+ $ret = $tag_params;
+ $ret['Prefix'] = $parts[0];
+ $ret['Special'] = count($parts) > 1 ? $parts[1] : '';
+ $ret['PrefixSpecial'] = $prefix_special;
+
+ return $ret;
+ }
}
class kDBBase extends kBase {
Index: core/units/admin/admin_events_handler.php
===================================================================
--- core/units/admin/admin_events_handler.php (revision 12775)
+++ core/units/admin/admin_events_handler.php (working copy)
@@ -43,9 +43,9 @@
$perm_value = null;
$system_events = Array (
- 'OnResetModRwCache', 'OnResetCMSMenuCache', 'OnResetSections',
- 'OnResetConfigsCache', 'OnDeleteCompiledTemplates', 'OnCompileTemplates',
- 'OnGenerateTableStructure', 'OnRebuildThemes', 'OnCheckPrefixConfig',
+ 'OnResetModRwCache', 'OnResetSections', 'OnResetConfigsCache',
+ 'OnDeleteCompiledTemplates', 'OnCompileTemplates', 'OnGenerateTableStructure',
+ 'OnRebuildThemes', 'OnCheckPrefixConfig',
);
if (in_array($event->Name, $system_events)) {
@@ -98,15 +98,6 @@
$this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName LIKE "mod_rw%"');
}
- function OnResetCMSMenuCache(&$event)
- {
- if ($this->Application->GetVar('ajax') == 'yes') {
- $event->status = erSTOP;
- }
-
- $this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName IN ("cms_menu", "StructureTree")');
- }
-
function OnResetSections(&$event)
{
if ($this->Application->GetVar('ajax') == 'yes') {
Index: core/units/categories/categories_config.php
===================================================================
--- core/units/categories/categories_config.php (revision 12775)
+++ core/units/categories/categories_config.php (working copy)
@@ -350,11 +350,6 @@
'MenuTitle' => Array ('type' => 'string', 'formatter' => 'kMultiLanguage', 'not_null' => 1, 'default' => ''),
'MetaTitle' => Array ('type' => 'string', 'default' => null),
'IndexTools' => Array ('type' => 'string', 'formatter' => 'kFormatter', 'using_fck' => 1, 'default' => null),
- 'IsIndex' =>
- Array (
- 'type' => 'int', 'not_null' => 1, 'default' => 0,
- 'formatter' => 'kOptionsFormatter', 'options' => Array (0 => 'la_Regular', 1 => 'la_CategoryIndex', 2 => 'la_Container'), 'use_phrases' => 1,
- ),
'IsMenu' => Array ('type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Show', 0 => 'la_Hide'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 1),
'IsSystem' => Array ('type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_System', 0 => 'la_text_User'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 0),
'FormId' => Array (
Index: core/units/categories/categories_event_handler.php
===================================================================
--- core/units/categories/categories_event_handler.php (revision 12775)
+++ core/units/categories/categories_event_handler.php (working copy)
@@ -62,6 +62,17 @@
*/
function CheckPermission(&$event)
{
+ if ($event->Name == 'OnResetCMSMenuCache') {
+ // events from "Tools -> System Tools" section are controlled via that section "edit" permission
+
+ $perm_helper =& $this->Application->recallObject('PermissionsHelper');
+ /* @var $perm_helper kPermissionsHelper */
+
+ $perm_value = $this->Application->CheckPermission('in-portal:service.edit');
+
+ return $perm_helper->finalizePermissionCheck($event, $perm_value);
+ }
+
if (!$this->Application->isAdmin) {
if ($event->Name == 'OnSetSortingDirect') {
// allow sorting on front event without view permission
@@ -469,6 +480,7 @@
$type_clauses['menu']['include'] = '%1$s.IsMenu = 1';
$type_clauses['menu']['except'] = '%1$s.IsMenu = 0';
+ $type_clauses['menu']['having_filter'] = false;
if (in_array('search', $types) || in_array('search', $except_types)) {
$event_mapping = Array (
@@ -600,7 +612,7 @@
$updater->OneStepRun();
}
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
$this->Application->RemoveVar('PermCache_UpdateRequired');
@@ -797,7 +809,7 @@
}
$this->Application->StoreVar('RefreshStructureTree', 1);
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
if ($is_editing) {
// 2. send email event to category owner, when it's status is changed (from admin)
@@ -1015,7 +1027,7 @@
$priority_helper->recalculatePriorities($event, 'ParentId = ' . $parent_id);
$this->Application->StoreVar('RefreshStructureTree', 1);
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
}
/**
@@ -1137,7 +1149,6 @@
$priority_helper =& $this->Application->recallObject('PriorityHelper');
/* @var $priority_helper kPriorityHelper */
-
if ($clipboard_data['cut']) {
$priority_helper->recalculatePriorities($event, 'ParentId = '.$source_category_id);
}
@@ -1158,7 +1169,7 @@
$event->redirect = 'categories/cache_updater';
}
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
$this->Application->StoreVar('RefreshStructureTree', 1);
}
}
@@ -1758,11 +1769,68 @@
*
* @param kEvent $event
*/
- function OnResetMenuCache(&$event)
+ function OnResetCMSMenuCache(&$event)
{
- $this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName IN ("cms_menu", "StructureTree")');
+ if ($this->Application->GetVar('ajax') == 'yes') {
+ $event->status = erSTOP;
+ }
+
+ $this->_resetMenuCache();
}
+ function _resetMenuCache()
+ {
+ // reset cms menu cache
+ $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache
+ WHERE VarName IN ("cms_menu", "StructureTree")';
+ $this->Conn->Query($sql);
+
+ // build structure template mapping
+ $sql = 'SELECT
+ IF(c.IsSystem, CONCAT(c.Template, ":", c.ThemeId), CONCAT("id:", c.CategoryId)) AS SrcTemplate,
+ LOWER(
+ IF(
+ c.SymLinkCategoryId IS NOT NULL,
+ (SELECT cc.NamedParentPath FROM ' . TABLE_PREFIX . 'Category AS cc WHERE cc.CategoryId = c.SymLinkCategoryId),
+ c.NamedParentPath
+ )
+ ) AS DstTemplate,
+ c.UseExternalUrl, c.ExternalUrl
+ FROM ' . TABLE_PREFIX . 'Category AS c
+ WHERE c.Status = ' . STATUS_ACTIVE;
+ $pages = $this->Conn->Query($sql, 'SrcTemplate');
+
+ $mapping = Array ();
+ $base_url = $this->Application->BaseURL();
+
+ foreach ($pages as $src_template => $page) {
+ // process external url, before placing in cache
+ if ($page['UseExternalUrl']) {
+ $external_url = $page['ExternalUrl'];
+
+ if (!preg_match('/^(.*?):\/\/(.*)$/', $external_url)) {
+ // url without protocol will be relative url to our site
+ $external_url = $base_url . $external_url;
+ }
+
+ $dst_template = 'external:' . $external_url;
+ }
+ else {
+ $dst_template = preg_replace('/^Content\//i', '', $page['DstTemplate']);
+ }
+
+ $mapping[$src_template] = $dst_template;
+ }
+
+ $fields_hash = Array (
+ 'VarName' => 'template_mapping',
+ 'Data' => serialize($mapping),
+ 'Cached' => adodb_mktime(),
+ );
+
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE');
+ }
+
/**
* Updates structure config
*
@@ -1948,7 +2016,7 @@
$updater->OneStepRun();
}
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
if ($error_count) {
// allow user to review error after structure page creation
@@ -1997,7 +2065,7 @@
$this->clearSelectedIDs($event);
$this->Application->StoreVar('RefreshStructureTree', 1);
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
}
/**
@@ -2012,7 +2080,7 @@
$parent_id = $this->Application->GetVar('m_cat_id');
$priority_helper->recalculatePriorities($event, 'ParentId = ' . $parent_id);
- $event->CallSubEvent('OnResetMenuCache');
+ $this->_resetMenuCache();
}
/**
Index: core/units/categories/categories_tag_processor.php
===================================================================
--- core/units/categories/categories_tag_processor.php (revision 12775)
+++ core/units/categories/categories_tag_processor.php (working copy)
@@ -14,20 +14,6 @@
class CategoriesTagProcessor extends kDBTagProcessor {
- /**
- * Cached version of site menu
- *
- * @var Array
- */
- var $Menu = null;
-
- /**
- * Parent path mapping used in CachedMenu tag
- *
- * @var Array
- */
- var $ParentPaths = Array ();
-
function SubCatCount($params)
{
$object =& $this->getObject($params);
@@ -227,34 +213,32 @@
return $ml_formatter->LangFieldName('Name');
}
+ /**
+ * Returns symlinked category for given category
+ *
+ * @param $category_id
+ */
function getCategorySymLink($category_id)
{
static $cache = null;
+ if (!$category_id) {
+ // don't bother to get symlink for "Home" category
+ return $category_id;
+ }
+
if (!isset($cache)) {
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
- $sql = 'SELECT SymLinkCategoryId, '.$id_field.'
- FROM '.$table_name.'
- WHERE SymLinkCategoryId IS NOT NULL';
+ // get symlinked categories, that are not yet deleted
+ $sql = 'SELECT c1.SymLinkCategoryId, c1.' . $id_field . '
+ FROM ' . $table_name . ' c1
+ JOIN ' . $table_name . ' c2 ON c1.SymLinkCategoryId = c2.' . $id_field;
$cache = $this->Conn->GetCol($sql, $id_field);
}
- if (isset($cache[$category_id])) {
-
- //check if sym. link category is valid
- $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.' = '.$cache[$category_id];
-
- $category_id = $this->Conn->GetOne($sql)? $cache[$category_id] : $category_id;
- }
-
- return $category_id;
+ return array_key_exists($category_id, $cache) ? $cache[$category_id] : $category_id;
}
function CategoryLink($params)
@@ -266,7 +250,7 @@
$category_id = getArrayValue($params, 'cat_id');
if ($category_id === false) {
- $category_id = $this->Application->GetVar($this->getPrefixSpecial().'_id');
+ $category_id = $this->Application->GetVar($this->getPrefixSpecial() . '_id');
}
if ("$category_id" == 'Root') {
@@ -276,7 +260,7 @@
$category_id = $this->Application->GetVar('m_cat_id');
}
- $category_id = $this->getCategorySymLink($category_id);
+ $category_id = $this->getCategorySymLink( (int)$category_id );
unset($params['cat_id'], $params['module']);
@@ -1556,119 +1540,6 @@
}
/**
- * Builds cached menu version
- *
- * @return Array
- */
- function _prepareMenu()
- {
- static $root_cat = null;
- static $root_path = null;
-
- if (!$root_cat) {
- $root_cat = $this->Application->ModuleInfo['Core']['RootCat'];
- $root_path = $this->Conn->GetOne('SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$root_cat);
- }
-
- if (!$this->Menu) {
- $menu = $this->Conn->GetRow('SELECT Data, Cached FROM '.TABLE_PREFIX.'Cache WHERE VarName = "cms_menu"');
- if ($menu && $menu['Cached'] > 0) {
- $menu = unserialize($menu['Data']);
- $this->ParentPaths = $menu['ParentPaths'];
- }
- else {
- $menu = $this->_altBuildMenuStructure(array('CategoryId' => $root_cat, 'ParentPath' => $root_path));
- $menu['ParentPaths'] = $this->ParentPaths;
- $this->Conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("cms_menu", '.$this->Conn->qstr(serialize($menu)).', '.adodb_mktime().')');
- }
- unset($menu['ParentPaths']);
- $this->Menu = $menu;
- }
-
- return Array ($this->Menu, $root_path);
- }
-
- /**
- * Returns category id based tag parameters
- *
- * @param Array $params
- * @return int
- */
- function _getCategoryId($params)
- {
- $cat = isset($params['category_id']) && $params['category_id'] != '' ? $params['category_id'] : $this->Application->GetVar('m_cat_id');
- if ("$cat" == 'parent') {
- $this_category =& $this->Application->recallObject('c');
- /* @var $this_category kDBItem */
-
- $cat = $this_category->GetDBField('ParentId');
- }
- else if ($cat == 0) {
- $cat = $this->Application->ModuleInfo['Core']['RootCat'];
- }
-
- return $cat;
- }
-
- /**
- * Prepares cms menu item block parameters
- *
- * @param Array $page
- * @param int $real_cat_id
- * @param string $root_path
- * @return Array
- */
- function _prepareMenuItem($page, $real_cat_id, $root_path)
- {
- static $language_id = null;
- static $primary_language_id = null;
-
- if (!isset($language_id)) {
- $language_id = $this->Application->GetVar('m_lang');
- $primary_language_id = $this->Application->GetDefaultLanguageId();
- }
-
- $title = $page['l'.$language_id.'_ItemName'] ? $page['l'.$language_id.'_ItemName'] : $page['l'.$primary_language_id.'_ItemName'];
- $active = false;
- $category_active = false;
-
- if ($page['ItemType'] == 'cat') {
- if ( isset($this->ParentPaths[$real_cat_id])) {
- $active = strpos($this->ParentPaths[$real_cat_id], $page['ParentPath']) !== false;
- }
- $category_active = $page['CategoryId'] == $real_cat_id;
- }
-
- if ($page['ItemType'] == 'cat_index') {
- $check_path = str_replace($root_path, '', $page['ParentPath']);
- $active = strpos($parent_path, $check_path) !== false;
- }
-
- if ($page['ItemType'] == 'page') {
- $active = $page['ItemPath'] == preg_replace('/^Content\//i', '', $this->Application->GetVar('t'));
- }
-
- $block_params = Array (
- 'title'=> $title,
- 'template'=> preg_replace('/^Content\//i', '', $page['ItemPath']),
- 'active'=>$active,
- 'category_active' => $category_active, // new
- 'parent_path'=>$page['ParentPath'],
- 'parent_id'=>$page['ParentId'],
- 'cat_id'=>$page['CategoryId'],
- 'is_index'=>$page['IsIndex'],
- 'item_type'=>$page['ItemType'],
- 'page_id'=>$page['ItemId'],
- 'has_sub_menu' => isset($page['sub_items']) && count($page['sub_items']) > 0,
- 'external_url' => $page['UseExternalUrl'] ? $page['ExternalUrl'] : false,
- 'menu_icon' => $page['UseMenuIconUrl'] ? $page['MenuIconUrl'] : false,
-
- );
-
- return $block_params;
- }
-
- /**
* Builds site menu
*
* @param Array $params
@@ -1676,77 +1547,13 @@
*/
function CachedMenu($params)
{
- list ($menu, $root_path) = $this->_prepareMenu();
- $cat = $this->_getCategoryId($params);
+ $menu_helper =& $this->Application->recallObject('MenuHelper');
+ /* @var $menu_helper MenuHelper */
- $parent_path = isset($this->ParentPaths[$cat]) ? $this->ParentPaths[$cat] : '';
- $parent_path = str_replace($root_path, '', $parent_path); //menu starts from module path
- $levels = explode('|',trim($parent_path,'|'));
- if ($levels[0] === '') $levels = array();
- if (isset($params['level']) && $params['level'] > count($levels)) return ;
-
- $level = max(isset($params['level']) ? $params['level']-1 : count($levels)-1, 0);
- $parent = isset($levels[$level]) ? $levels[$level] : 0;
-
- $cur_menu =& $menu;
- $menu_path = array_slice($levels, 0, $level+1);
- foreach ($menu_path as $elem) {
- $cur_menu =& $cur_menu['c'.$elem]['sub_items'];
- }
-
- $ret = '';
- $block_params = $this->prepareTagParams($params);
- $block_params['name'] = $params['render_as'];
-
- $this->Application->SetVar('cur_parent_path', $parent_path);
- $real_cat_id = $this->Application->GetVar('m_cat_id');
- if (is_array($cur_menu) && $cur_menu) {
- $cur_item = 1;
- $cur_menu = $this->_removeNonMenuItems($cur_menu);
- $block_params['total_items'] = count($cur_menu);
-
- foreach ($cur_menu as $page) {
- $block_params = array_merge_recursive2(
- $block_params,
- $this->_prepareMenuItem($page, $real_cat_id, $root_path)
- );
-
- $block_params['is_last'] = $cur_item == $block_params['total_items'];
- $block_params['is_first'] = $cur_item == 1;
-
- // bug #1: this breaks active section highlighting when 2 menu levels are printed on same page (both visible)
- // bug #2: people doesn't pass cat_id parameter to m_Link tags in their blocks, so this line helps them; when removed their links will lead to nowhere
- $this->Application->SetVar('m_cat_id', $page['CategoryId']);
-
- $ret .= $this->Application->ParseBlock($block_params, 1);
- $cur_item++;
- }
-
- $this->Application->SetVar('m_cat_id', $real_cat_id);
- }
-
- return $ret;
+ return $menu_helper->menuTag($this->getPrefixSpecial(), $params);
}
/**
- * Returns only items, that are visible in menu
- *
- * @param Array $menu
- * @return Array
- */
- function _removeNonMenuItems($menu)
- {
- foreach ($menu as $menu_index => $menu_item) {
- // $menu_index is in "cN" format, where N is category id
- if (!$menu_item['IsMenu']) {
- unset($menu[$menu_index]);
- }
- }
-
- return $menu;
- }
-
- /**
* Trick to allow some kind of output formatting when using CachedMenu tag
*
* @param Array $params
@@ -1844,97 +1651,6 @@
}
/**
- * Builds cache for children of given category (no matter, what menu status is)
- *
- * @param Array $parent
- * @return Array
- */
- function _altBuildMenuStructure($parent)
- {
- static $languages_count = null;
-
- if (!isset($languages_count)) {
- $sql = 'SELECT COUNT(*)
- FROM ' . TABLE_PREFIX . 'Language';
- $languages_count = ceil($this->Conn->GetOne($sql) / 5) * 5;
- }
-
- $items = Array ();
-
- $lang_part = '';
- for ($i = 1; $i <= $languages_count; $i++) {
-// $lang_part .= 'c.l' . $i . '_Name AS l' . $i . '_ItemName,' . "\n";
- $lang_part .= 'c.l' . $i . '_MenuTitle AS l' . $i . '_ItemName,' . "\n";
- }
-
- // Sub-categories from current category
- $query = 'SELECT
- c.CategoryId AS CategoryId,
- CONCAT(\'c\', c.CategoryId) AS ItemId,
- c.Priority AS ItemPriority,
- ' . $lang_part . '
- LOWER( IF(IsIndex = 2, (
- SELECT cc.NamedParentPath FROM ' . TABLE_PREFIX . 'Category AS cc
- WHERE
- cc.ParentId = c.CategoryId
- AND
- cc.Status IN (1,4)
- AND
- cc.IsIndex = 1
- ),
- c.NamedParentPath) ) AS ItemPath,
- 0 AS IsIndex,
- c.ParentPath AS ParentPath,
- c.ParentId As ParentId,
- \'cat\' AS ItemType,
- c.IsMenu, c.UseExternalUrl, c.ExternalUrl, c.UseMenuIconUrl, c.MenuIconUrl
- FROM ' . TABLE_PREFIX . 'Category AS c
- WHERE
- c.Status IN (1,4) AND
- #c.IsMenu = 1 AND
- c.ParentId = ' . $parent['CategoryId'];
- $items = array_merge($items, $this->Conn->Query($query, 'ItemId'));
-
- uasort($items, Array (&$this, '_menuSort'));
-
- $the_items = array();
- foreach ($items as $an_item) {
- $the_items[ $an_item['ItemId'] ] = $an_item;
- $this->ParentPaths[ $an_item['CategoryId'] ] = $an_item['ParentPath'];
- }
-
- $items = $the_items;
- foreach ($items as $key => $menu_item) {
- if ($menu_item['CategoryId'] == $parent['CategoryId']) {
- continue;
- }
-
- $sub_items = $this->_altBuildMenuStructure($menu_item);
- if ($sub_items) {
- $items[$key]['sub_items'] = $sub_items;
- }
- }
-
- return $items;
- }
-
- /**
- * Method for sorting pages by priority in decending order
- *
- * @param Array $a
- * @param Array $b
- * @return int
- */
- function _menuSort($a, $b)
- {
- if ($a['ItemPriority'] == $b['ItemPriority']) {
- return 0;
- }
-
- return ($a['ItemPriority'] < $b['ItemPriority']) ? 1 : -1; //descending
- }
-
- /**
* Prepares cms page description for search result page
*
* @param Array $params
Index: core/units/helpers/category_helper.php
===================================================================
--- core/units/helpers/category_helper.php (revision 12775)
+++ core/units/helpers/category_helper.php (working copy)
@@ -62,9 +62,16 @@
$block_params['no_editing'] = 1;
$block_params['category'] = 0;
$block_params['separator'] = $params['separator'];
- $current_template = $this->Application->GetVar('t');
$show_category = getArrayValue($params, 'show_category');
+ $current_template = $this->Application->GetVar('t');
+ $physical_template = array_search($current_template, $this->Application->structureTemplateMapping);
+
+ if ($physical_template !== false) {
+ // replace menu template name with it's actual template name on disk
+ list ($current_template) = explode(':', $physical_template, 2);
+ }
+
foreach ($navigation_parts as $template => $title) {
$block_params['template'] = $template;
Index: core/units/helpers/helpers_config.php
===================================================================
--- core/units/helpers/helpers_config.php (revision 12775)
+++ core/units/helpers/helpers_config.php (working copy)
@@ -50,6 +50,7 @@
Array ('pseudo' => 'LanguageImportHelper', 'class' => 'LanguageImportHelper', 'file' => 'language_import_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SkinHelper', 'class' => 'SkinHelper', 'file' => 'skin_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'SiteConfigHelper', 'pseudo' => 'SiteConfigHelper', 'file' => 'site_config_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('class' => 'MenuHelper', 'pseudo' => 'MenuHelper', 'file' => 'menu_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'InpCustomFieldsHelper', 'pseudo' => 'InpCustomFieldsHelper', 'file' => 'custom_fields_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'kCountryStatesHelper', 'pseudo' => 'CountryStatesHelper', 'file' => 'country_states_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Index: core/units/helpers/menu_helper.php
===================================================================
--- core/units/helpers/menu_helper.php (revision 0)
+++ core/units/helpers/menu_helper.php (revision 0)
@@ -0,0 +1,311 @@
+<?php
+
+ class MenuHelper extends kHelper {
+
+ /**
+ * Cached version of site menu
+ *
+ * @var Array
+ */
+ var $Menu = null;
+
+ /**
+ * Parent path mapping used in CachedMenu tag
+ *
+ * @var Array
+ */
+ var $parentPaths = Array ();
+
+ /**
+ * Builds site menu
+ *
+ * @param Array $params
+ * @return string
+ */
+ function menuTag($prefix_special, $params)
+ {
+ list ($menu, $root_path) = $this->_prepareMenu();
+ $cat = $this->_getCategoryId($params);
+
+ $parent_path = array_key_exists($cat, $this->parentPaths) ? $this->parentPaths[$cat] : '';
+ $parent_path = str_replace($root_path, '', $parent_path); // menu starts from module path
+
+ $levels = explode('|', trim($parent_path, '|'));
+
+ if ($levels[0] === '') {
+ $levels = Array ();
+ }
+
+ if (array_key_exists('level', $params) && $params['level'] > count($levels)) {
+ // current level is deeper, then requested level
+ return ;
+ }
+
+ $level = max(array_key_exists('level', $params) ? $params['level'] - 1 : count($levels) - 1, 0);
+ $parent = array_key_exists($level, $levels) ? $levels[$level] : 0;
+
+ $cur_menu =& $menu;
+ $menu_path = array_slice($levels, 0, $level + 1);
+
+ foreach ($menu_path as $elem) {
+ $cur_menu =& $cur_menu['c' . $elem]['sub_items'];
+ }
+
+ $block_params = $this->prepareTagParams($prefix_special, $params);
+ $block_params['name'] = $params['render_as'];
+
+ $this->Application->SetVar('cur_parent_path', $parent_path);
+ $real_cat_id = $this->Application->GetVar('m_cat_id');
+
+ if (!is_array($cur_menu) || !$cur_menu) {
+ // no menus on this level
+ return '';
+ }
+
+ $ret = '';
+ $cur_item = 1;
+ $cur_menu = $this->_removeNonMenuItems($cur_menu);
+ $block_params['total_items'] = count($cur_menu);
+
+ foreach ($cur_menu as $page) {
+ $block_params = array_merge_recursive2(
+ $block_params,
+ $this->_prepareMenuItem($page, $real_cat_id, $root_path)
+ );
+
+ $block_params['is_last'] = $cur_item == $block_params['total_items'];
+ $block_params['is_first'] = $cur_item == 1;
+
+ // bug #1: this breaks active section highlighting when 2 menu levels are printed on same page (both visible)
+ // bug #2: people doesn't pass cat_id parameter to m_Link tags in their blocks, so this line helps them; when removed their links will lead to nowhere
+ $this->Application->SetVar('m_cat_id', $page['CategoryId']);
+
+ $ret .= $this->Application->ParseBlock($block_params);
+ $cur_item++;
+ }
+
+ $this->Application->SetVar('m_cat_id', $real_cat_id);
+
+ return $ret;
+ }
+
+ /**
+ * Builds cached menu version
+ *
+ * @return Array
+ */
+ function _prepareMenu()
+ {
+ static $root_cat = null;
+ static $root_path = null;
+
+ if (!$root_cat) {
+ $root_cat = $this->Application->ModuleInfo['Core']['RootCat'];
+
+ $sql = 'SELECT ParentPath
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE CategoryId = ' . $root_cat;
+ $root_path = $this->Conn->GetOne($sql);
+ }
+
+ if (!$this->Menu) {
+ $menu = $this->Conn->GetRow('SELECT Data, Cached FROM '.TABLE_PREFIX.'Cache WHERE VarName = "cms_menu"');
+ if ($menu && $menu['Cached'] > 0) {
+ $menu = unserialize($menu['Data']);
+ $this->parentPaths = $menu['parentPaths'];
+ }
+ else {
+ $menu = $this->_altBuildMenuStructure(Array ('CategoryId' => $root_cat, 'ParentPath' => $root_path));
+ $menu['parentPaths'] = $this->parentPaths;
+
+ $this->Conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("cms_menu", '.$this->Conn->qstr(serialize($menu)).', '.adodb_mktime().')');
+ }
+
+ unset($menu['parentPaths']);
+ $this->Menu = $menu;
+ }
+
+ return Array ($this->Menu, $root_path);
+ }
+
+ /**
+ * Returns category id based tag parameters
+ *
+ * @param Array $params
+ * @return int
+ */
+ function _getCategoryId($params)
+ {
+ $cat = isset($params['category_id']) && $params['category_id'] != '' ? $params['category_id'] : $this->Application->GetVar('m_cat_id');
+ if ("$cat" == 'parent') {
+ $this_category =& $this->Application->recallObject('c');
+ /* @var $this_category kDBItem */
+
+ $cat = $this_category->GetDBField('ParentId');
+ }
+ elseif ($cat == 0) {
+ $cat = $this->Application->ModuleInfo['Core']['RootCat'];
+ }
+
+ return $cat;
+ }
+
+ /**
+ * Prepares cms menu item block parameters
+ *
+ * @param Array $page
+ * @param int $real_cat_id
+ * @param string $root_path
+ * @return Array
+ */
+ function _prepareMenuItem($page, $real_cat_id, $root_path)
+ {
+ static $language_id = null;
+ static $primary_language_id = null;
+
+ if (!isset($language_id)) {
+ $language_id = $this->Application->GetVar('m_lang');
+ $primary_language_id = $this->Application->GetDefaultLanguageId();
+ }
+
+ $active = $category_active = false;
+ $title = $page['l' . $language_id . '_ItemName'] ? $page['l' . $language_id . '_ItemName'] : $page['l' . $primary_language_id . '_ItemName'];
+
+ if ($page['ItemType'] == 'cat') {
+ if (array_key_exists($real_cat_id, $this->parentPaths)) {
+ $active = strpos($this->parentPaths[$real_cat_id], $page['ParentPath']) !== false;
+ }
+
+ $category_active = $page['CategoryId'] == $real_cat_id;
+ }
+
+ /*if ($page['ItemType'] == 'cat_index') {
+ $check_path = str_replace($root_path, '', $page['ParentPath']);
+ $active = strpos($parent_path, $check_path) !== false;
+ }
+
+ if ($page['ItemType'] == 'page') {
+ $active = $page['ItemPath'] == preg_replace('/^Content\//i', '', $this->Application->GetVar('t'));
+ }*/
+
+ $block_params = Array (
+ 'title' => $title,
+ 'template' => $page['ItemPath'],
+ 'active' => $active,
+ 'category_active' => $category_active, // new
+ 'parent_path' => $page['ParentPath'],
+ 'parent_id' => $page['ParentId'],
+ 'cat_id' => $page['CategoryId'],
+ 'item_type' => $page['ItemType'],
+ 'page_id' => $page['ItemId'],
+ 'has_sub_menu' => isset($page['sub_items']) && count($page['sub_items']) > 0,
+ 'external_url' => $page['UseExternalUrl'] ? $page['ExternalUrl'] : false, // for backward compatibility
+ 'menu_icon' => $page['UseMenuIconUrl'] ? $page['MenuIconUrl'] : false,
+ );
+
+ return $block_params;
+ }
+
+ /**
+ * Returns only items, that are visible in menu
+ *
+ * @param Array $menu
+ * @return Array
+ */
+ function _removeNonMenuItems($menu)
+ {
+ foreach ($menu as $menu_index => $menu_item) {
+ // $menu_index is in "cN" format, where N is category id
+ if (!$menu_item['IsMenu']) {
+ unset($menu[$menu_index]);
+ }
+ }
+
+ return $menu;
+ }
+
+ /**
+ * Builds cache for children of given category (no matter, what menu status is)
+ *
+ * @param Array $parent
+ * @return Array
+ */
+ function _altBuildMenuStructure($parent)
+ {
+ static $lang_part = null;
+
+ if (!isset($lang_part)) {
+ $sql = 'SELECT COUNT(*)
+ FROM ' . TABLE_PREFIX . 'Language';
+ $languages_count = ceil($this->Conn->GetOne($sql) / 5) * 5;
+
+ $lang_part = '';
+
+ for ($i = 1; $i <= $languages_count; $i++) {
+ $lang_part .= 'c.l' . $i . '_MenuTitle AS l' . $i . '_ItemName,' . "\n";
+ }
+ }
+
+ $items = Array ();
+
+ // Sub-categories from current category
+ $sql = 'SELECT
+ c.CategoryId AS CategoryId,
+ CONCAT(\'c\', c.CategoryId) AS ItemId,
+ c.Priority AS ItemPriority,
+ ' . $lang_part . '
+
+ IF(c.IsSystem, CONCAT(c.Template, ":", c.ThemeId), CONCAT("id:", c.CategoryId)) AS ItemPath,
+ c.ParentPath AS ParentPath,
+ c.ParentId As ParentId,
+ \'cat\' AS ItemType,
+ c.IsMenu, c.UseExternalUrl, c.ExternalUrl, c.UseMenuIconUrl, c.MenuIconUrl
+ FROM ' . TABLE_PREFIX . 'Category AS c
+ WHERE (c.Status = ' . STATUS_ACTIVE . ') AND (c.ParentId = ' . $parent['CategoryId'] . ')';
+ $items = array_merge($items, $this->Conn->Query($sql, 'ItemId'));
+
+ // sort menu items
+ uasort($items, Array (&$this, '_menuSort'));
+
+ // store menu items
+ $the_items = Array();
+ foreach ($items as $index => $an_item) {
+ $the_items[ $an_item['ItemId'] ] = $an_item;
+
+ $this->parentPaths[ $an_item['CategoryId'] ] = $an_item['ParentPath'];
+ }
+
+ // process submenus of each menu
+ $items = $the_items;
+ foreach ($items as $key => $menu_item) {
+ if ($menu_item['CategoryId'] == $parent['CategoryId']) {
+ // don't process myself - prevents recursion
+ continue;
+ }
+
+ $sub_items = $this->_altBuildMenuStructure($menu_item);
+
+ if ($sub_items) {
+ $items[$key]['sub_items'] = $sub_items;
+ }
+ }
+
+ return $items;
+ }
+
+ /**
+ * Method for sorting pages by priority in decending order
+ *
+ * @param Array $a
+ * @param Array $b
+ * @return int
+ */
+ function _menuSort($a, $b)
+ {
+ if ($a['ItemPriority'] == $b['ItemPriority']) {
+ return 0;
+ }
+
+ return ($a['ItemPriority'] < $b['ItemPriority']) ? 1 : -1; //descending
+ }
+ }
Index: core/units/helpers/mod_rewrite_helper.php
===================================================================
--- core/units/helpers/mod_rewrite_helper.php (revision 12775)
+++ core/units/helpers/mod_rewrite_helper.php (working copy)
@@ -349,6 +349,9 @@
if ($regs) {
$template = array_key_exists('t', $params) ? $params['t'] : false;
+ // when we have category, that matches one template and template name, that matches other template
+ // in result we have url, that will match to category, but not to template we need
+
if (strtolower($regs[1]) == strtolower($template)) {
// we could have category path like "Content/<template_path>" in this case remove template
$params['pass_template'] = false;
@@ -584,7 +587,7 @@
$vars['m_cat_page'] = $rets[2];
}
- $sql = 'SELECT CategoryId, IsIndex, NamedParentPath
+ $sql = 'SELECT CategoryId, SymLinkCategoryId, NamedParentPath
FROM ' . TABLE_PREFIX . 'Category
WHERE Status IN (1,4) AND (LOWER(NamedParentPath) = ' . $this->Conn->qstr($category_path) . ') AND (ThemeId = ' . $vars['m_theme'] . ' OR ThemeId = 0)';
$category_info = $this->Conn->GetRow($sql);
@@ -597,15 +600,17 @@
} while ($category_info !== false && $url_part);
if ($last_category_info) {
- // IsIndex = 2 is a Container-only page, meaning it should go to index-page child
- if ($last_category_info['IsIndex'] == 2) {
+ // this category is symlink to other category, so use it's url instead
+ // (used in case if url prior to symlink adding was indexed by spider or was bookmarked)
+ if ($last_category_info['SymLinkCategoryId']) {
$sql = 'SELECT CategoryId, NamedParentPath
FROM ' . TABLE_PREFIX . 'Category
- WHERE (ParentId = ' . $last_category_info['CategoryId'] . ') AND (IsIndex = 1) AND (ThemeId = ' . $vars['m_theme'] . ' OR ThemeId = 0)';
+ WHERE (CategoryId = ' . $last_category_info['SymLinkCategoryId'] . ')';
$category_info = $this->Conn->GetRow($sql);
if ($category_info) {
- // when index sub-page is found use it, otherwise use container page
+ // web symlinked category was found use it
+ // TODO: maybe 302 redirect should be made to symlinked category url (all other url parts should stay)
$last_category_info = $category_info;
}
}
Index: core/units/structure/structure_config.php
===================================================================
--- core/units/structure/structure_config.php (revision 12775)
+++ core/units/structure/structure_config.php (working copy)
@@ -158,11 +158,6 @@
'MenuTitle' => Array('type' => 'string', 'formatter' => 'kMultiLanguage', 'not_null' => 1, 'default' => ''),
'MetaTitle' => Array('type' => 'string', 'default' => null),
'IndexTools' => Array('type' => 'string','default' => null),
- 'IsIndex' =>
- Array(
- 'type' => 'int','not_null' => 1, 'default' => 0,
- 'formatter' => 'kOptionsFormatter', 'options' => Array (0 => 'la_Regular', 1 => 'la_CategoryIndex', 2=>'la_Container'), 'use_phrases' => 1,
- ),
'IsMenu' => Array('type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Show', 0 => 'la_Hide'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 1),
'IsSystem' => Array('type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_System', 0 => 'la_Regular'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 0),
'FormId' => Array('type' => 'int', 'formatter' => 'kOptionsFormatter',
|