Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1046997
D256.id611.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Jun 29, 3:25 PM
Size
23 KB
Mime Type
text/x-diff
Expires
Mon, Jun 30, 3:25 PM (2 h, 49 m)
Engine
blob
Format
Raw Data
Handle
676926
Attached To
D256: INP-1325 - Perform intellectual cache update on category changes
D256.id611.diff
View Options
Index: core/install/install_data.sql
===================================================================
--- core/install/install_data.sql
+++ core/install/install_data.sql
@@ -12,7 +12,7 @@
INSERT INTO SystemSettings VALUES(DEFAULT, 'Catalog_PreselectModuleTab', '1', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_CatalogPreselectModuleTab', 'checkbox', NULL, NULL, 10.09, 0, 0, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'RecycleBinFolder', '', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_RecycleBinFolder', 'text', NULL, NULL, 10.10, 0, 0, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'CheckViewPermissionsInCatalog', '0', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_CheckViewPermissionsInCatalog', 'radio', NULL, '1=la_Yes||0=la_No', 10.11, 0, 1, 'hint:la_config_CheckViewPermissionsInCatalog');
-INSERT INTO SystemSettings VALUES(DEFAULT, 'CategoryPermissionRebuildMode', '3', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_CategoryPermissionRebuildMode', 'select', NULL, '1=la_opt_Manual||2=la_opt_Silent||3=la_opt_Automatic', 10.12, 0, 0, 'hint:la_config_CategoryPermissionRebuildMode');
+INSERT INTO SystemSettings VALUES(DEFAULT, 'CategoryPermissionRebuildMode', '1', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_CategoryPermissionRebuildMode', 'select', NULL, '1=la_opt_Manual||2=la_opt_Silent||3=la_opt_Automatic', 10.12, 0, 0, 'hint:la_config_CategoryPermissionRebuildMode');
INSERT INTO SystemSettings VALUES(DEFAULT, 'FilenameSpecialCharReplacement', '-', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_FilenameSpecialCharReplacement', 'select', NULL, '_=+_||-=+-', 10.13, 0, 0, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'Search_MinKeyword_Length', '3', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_Search_MinKeyword_Length', 'text', NULL, NULL, 10.14, 0, 0, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'ExcludeTemplateSectionsFromSearch', '0', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_ExcludeTemplateSectionsFromSearch', 'checkbox', '', '', 10.15, 0, 0, NULL);
Index: core/install/install_schema.sql
===================================================================
--- core/install/install_schema.sql
+++ core/install/install_schema.sql
@@ -518,6 +518,7 @@
ParentPath text,
TreeLeft bigint(20) NOT NULL DEFAULT '0',
TreeRight bigint(20) NOT NULL DEFAULT '0',
+ TreeLocked tinyint(4) NOT NULL DEFAULT '0',
NamedParentPath text,
NamedParentPathHash int(10) unsigned NOT NULL DEFAULT '0',
MetaDescription text,
@@ -592,7 +593,8 @@
KEY LiveRevisionNumber (LiveRevisionNumber),
KEY PromoBlockGroupId (PromoBlockGroupId),
KEY NamedParentPathHash (NamedParentPathHash),
- KEY CachedTemplateHash (CachedTemplateHash)
+ KEY CachedTemplateHash (CachedTemplateHash),
+ KEY IDX_TREELOCKED (TreeLocked)
);
CREATE TABLE CategoryCustomData (
Index: core/install/upgrades.sql
===================================================================
--- core/install/upgrades.sql
+++ core/install/upgrades.sql
@@ -2934,3 +2934,7 @@
WHERE TemplateName LIKE 'USER%';
UPDATE SystemSettings SET VariableValue = 1 WHERE VariableName = 'CSVExportEncoding';
+
+ALTER TABLE Categories ADD TreeLocked TINYINT(4) NOT NULL DEFAULT '0' AFTER TreeRight;
+ALTER TABLE Categories ADD INDEX IDX_TREELOCKED (TreeLocked);
+UPDATE SystemSettings SET VariableValue = 1 WHERE VariableName = 'CategoryPermissionRebuildMode';
Index: core/units/admin/admin_tag_processor.php
===================================================================
--- core/units/admin/admin_tag_processor.php
+++ core/units/admin/admin_tag_processor.php
@@ -582,7 +582,10 @@
if ( $global_mark || $local_mark ) {
$this->Application->RemoveVar('PermCache_UpdateRequired');
- $rebuild_mode = $this->Application->ConfigValue('CategoryPermissionRebuildMode');
+
+ /** @var CategoryHelper $category_helper */
+ $category_helper = $this->Application->recallObject('CategoryHelper');
+ $rebuild_mode = $category_helper->getCategoryPermissionRebuildMode();
if ( $rebuild_mode == CategoryPermissionRebuild::SILENT ) {
$updater = $this->Application->makeClass('kPermCacheUpdater');
Index: core/units/categories/cache_updater.php
===================================================================
--- core/units/categories/cache_updater.php
+++ core/units/categories/cache_updater.php
@@ -206,12 +206,20 @@
var $StrictPath = false;
/**
+ * Previous parent of strict category.
+ *
+ * @var integer
+ */
+ protected $StrictPathOldParentId;
+
+ /**
* Returns instance of perm cache updater
*
- * @param int $continuing
- * @param mixed $strict_path
+ * @param integer $continuing Continuing previous operation.
+ * @param string $strict_path Strict path limitation.
+ * @param integer $strict_path_old_parent_id Previous parent of strict category.
*/
- public function __construct($continuing = null, $strict_path = null)
+ public function __construct($continuing = null, $strict_path = null, $strict_path_old_parent_id = null)
{
parent::__construct();
@@ -221,6 +229,7 @@
}
$this->StrictPath = $strict_path;
+ $this->StrictPathOldParentId = $strict_path_old_parent_id;
}
// cache widely used values to speed up process
@@ -343,6 +352,11 @@
$this->Conn->Query($sql);
$this->clearData();
+ // Don't delete override, that is set exactly, during strict path processing.
+ if ( !$this->StrictPath ) {
+ $this->Application->RemoveVar('CategoryPermissionRebuildModeOverride');
+ }
+
$this->Application->incrementCacheSerial('c');
}
@@ -381,19 +395,22 @@
$this->iteration++;
}
- // start with first child if we haven't started yet
- if (!isset($data['current_child'])) $data['current_child'] = 0;
+ // Start with first child if we haven't started yet.
+ if ( !isset($data['current_child']) ) {
+ $data['current_child'] = 0;
+ }
- // if we have more children on CURRENT LEVEL
- if (isset($data['children'][$data['current_child']])) {
- if ($this->StrictPath) {
- while ( isset($data['children'][ $data['current_child'] ]) && !in_array($data['children'][ $data['current_child'] ], $this->StrictPath) ) {
- $data['current_child']++;
- continue;
- }
- if (!isset($data['children'][ $data['current_child'] ])) return false; //error
+ // Skip all children on CURRENT LEVEL that are not within StrictPath.
+ if ( $this->StrictPath && isset($data['children'][$data['current_child']]) ) {
+ while ( isset($data['children'][$data['current_child']]) && !in_array($data['children'][$data['current_child']], $this->StrictPath) ) {
+ $data['current_child']++;
+ continue;
}
- $next_data = Array();
+ }
+
+ // If we have more children on CURRENT LEVEL.
+ if ( isset($data['children'][$data['current_child']]) ) {
+ $next_data = array();
$next_data['titles'] = $data['titles'];
$next_data['parent_path'] = $data['parent_path'];
$next_data['named_path'] = $data['named_path'];
@@ -444,11 +461,77 @@
'CachedTemplate' => $data['template'], // actual template to use when category is visited
'CachedTemplateHash' => kUtil::crc32(mb_strtolower($data['template'])),
'CachedDescendantCatsQty' => $data['children_count'],
- 'TreeLeft' => $data['left'],
- 'TreeRight' => $data['right'],
);
- foreach ($this->languages as $language_id) {
+ if ( $this->StrictPath ) {
+ // Only do once per whole strict path.
+ $category_id = $data['current_id'];
+
+ if ( $category_id == end($this->StrictPath)
+ && is_numeric($this->StrictPathOldParentId)
+ && $this->StrictPathOldParentId > 0
+ ) {
+ $this->Conn->doUpdate(array('TreeLocked' => 0), TABLE_PREFIX . 'Categories', 'TRUE');
+
+ $new_parent_id = $this->StrictPath[count($this->StrictPath) - 2];
+
+ if ( $this->StrictPathOldParentId == 0 ) {
+ // New category.
+ $this->Conn->doUpdate(
+ array('TreeLocked' => 1),
+ TABLE_PREFIX . 'Categories',
+ 'CategoryId = ' . $category_id
+ );
+ $parent_tree_indexes = $this->Application->getTreeIndex($new_parent_id);
+ $this->addCreateTreeWindow($parent_tree_indexes['TreeLeft'], 1);
+ }
+ elseif ( $new_parent_id != $this->StrictPathOldParentId ) {
+ // Moved categories.
+ $tree_indexes = $this->Application->getTreeIndex($category_id);
+ $this->Conn->doUpdate(
+ array('TreeLocked' => 1),
+ TABLE_PREFIX . 'Categories',
+ 'TreeLeft BETWEEN ' . $tree_indexes['TreeLeft'] . ' AND ' . $tree_indexes['TreeRight']
+ );
+ $parent_tree_indexes = $this->Application->getTreeIndex($new_parent_id);
+ $this->addCreateTreeWindow($parent_tree_indexes['TreeLeft'], $data['children_count'] + 1);
+
+ // Increase/decrease moved tree indexes to fit within new parent tree indexes.
+ $tree_diff = ($parent_tree_indexes['TreeLeft'] + 1) - $tree_indexes['TreeLeft'];
+ $tree_diff_clause = ($tree_diff >= 0 ? '+' : '-') . ' ' . abs($tree_diff);
+
+ $sql = 'UPDATE ' . TABLE_PREFIX . 'Categories
+ SET TreeLeft = TreeLeft ' . $tree_diff_clause . ',
+ TreeRight = TreeRight ' . $tree_diff_clause . '
+ WHERE TreeLocked = 1';
+ $this->Conn->Query($sql);
+
+ $sql = 'SELECT CategoryId
+ FROM ' . TABLE_PREFIX . 'Categories
+ WHERE TreeLocked = 1';
+ $moved_categories = $this->Conn->GetColIterator($sql);
+
+ foreach ( $moved_categories as $moved_category_id ) {
+ $this->Application->incrementCacheSerial('c', $moved_category_id);
+ }
+
+ // Moved category has sub-categories.
+ if ( count($moved_categories) > 1 ) {
+ $this->Application->StoreVar(
+ 'CategoryPermissionRebuildModeOverride',
+ CategoryPermissionRebuild::AUTOMATIC
+ );
+ }
+ }
+ }
+ }
+ else {
+ // Is calculated correctly, only when doing full cache rebuild.
+ $fields_hash['TreeLeft'] = $data['left'];
+ $fields_hash['TreeRight'] = $data['right'];
+ }
+
+ foreach ( $this->languages as $language_id ) {
$fields_hash['l' . $language_id . '_CachedNavbar'] = implode('&|&', $data['titles'][$language_id]);
}
@@ -459,6 +542,43 @@
}
}
+ /**
+ * Creates window in TreeLeft/TreeRight for X categories.
+ *
+ * @param integer $tree_left Tree left.
+ * @param integer $sub_category_count Sub category count.
+ *
+ * @return void
+ */
+ protected function addCreateTreeWindow($tree_left, $sub_category_count)
+ {
+ // Use ">" in WHERE to avoid affecting direct parent.
+ $sql = 'SELECT CategoryId
+ FROM ' . TABLE_PREFIX . 'Categories
+ WHERE TreeLeft > ' . $tree_left . ' AND TreeLocked = 0';
+ $updated_categories = $this->Conn->GetCol($sql);
+
+ $sql = 'UPDATE ' . TABLE_PREFIX . 'Categories
+ SET TreeLeft = TreeLeft + ' . ($sub_category_count * 2) . '
+ WHERE TreeLeft > ' . $tree_left . ' AND TreeLocked = 0';
+ $this->Conn->Query($sql);
+
+ // Use ">=" in WHERE to affect direct parent.
+ $sql = 'SELECT CategoryId
+ FROM ' . TABLE_PREFIX . 'Categories
+ WHERE TreeRight >= ' . $tree_left . ' AND TreeLocked = 0';
+ $updated_categories = array_unique(array_merge($updated_categories, $this->Conn->GetCol($sql)));
+
+ $sql = 'UPDATE ' . TABLE_PREFIX . 'Categories
+ SET TreeRight = TreeRight + ' . ($sub_category_count * 2) . '
+ WHERE TreeRight >= ' . $tree_left . ' AND TreeLocked = 0';
+ $this->Conn->Query($sql);
+
+ foreach ( $updated_categories as $updated_category_id ) {
+ $this->Application->incrementCacheSerial('c', $updated_category_id);
+ }
+ }
+
function QueryTitle(&$data)
{
$category_id = $data['current_id'];
Index: core/units/categories/categories_event_handler.php
===================================================================
--- core/units/categories/categories_event_handler.php
+++ core/units/categories/categories_event_handler.php
@@ -739,24 +739,34 @@
$parent_path = false;
$object->Load($event->getEventParam('id'));
+ $old_parent_id = $object->GetDBField('ParentId');
+ $old_parent_path = $object->GetDBField('ParentPath');
if ( $event->getEventParam('temp_id') == 0 ) {
+ // Update path only for real categories (not including "Home" root category).
if ( $object->isLoaded() ) {
- // update path only for real categories (not including "Home" root category)
- $fields_hash = $object->buildParentBasedFields();
- $this->Conn->doUpdate($fields_hash, $object->TableName, 'CategoryId = ' . $object->GetID());
- $parent_path = $fields_hash['ParentPath'];
+ $old_parent_id = 0;
+ $this->refreshHierarchyFields($object, true);
+ $parent_path = $object->GetDBField('ParentPath');
}
}
else {
+ $parent_changed = $this->Application->GetVar($event->Prefix . '_parent_changed', array());
+
+ if ( isset($parent_changed[$object->GetID()]) ) {
+ $this->refreshHierarchyFields($object);
+ $old_parent_id = $parent_changed[$object->GetID()];
+ }
+
$parent_path = $object->GetDBField('ParentPath');
}
if ( $parent_path ) {
- $cache_updater = $this->Application->makeClass('kPermCacheUpdater', Array (null, $parent_path));
- /* @var $cache_updater kPermCacheUpdater */
+ $this->quickCategoryCacheRebuild($parent_path, $old_parent_id);
- $cache_updater->OneStepRun();
+ if ( strlen($old_parent_path) && $old_parent_path != $parent_path ) {
+ $this->quickCategoryCacheRebuild($this->removeLastFromPath($old_parent_path), null);
+ }
}
}
@@ -804,7 +814,18 @@
}
}
- // remember category filename change between temp and live records
+ // Change in these fields require full category cache rebuilding.
+ foreach ( array('Filename', 'Template') as $cached_field ) {
+ if ( $live_object->GetDBField($cached_field) != $temp_object->GetDBField($cached_field) ) {
+ $this->Application->StoreVar(
+ 'CategoryPermissionRebuildModeOverride',
+ CategoryPermissionRebuild::AUTOMATIC
+ );
+ break;
+ }
+ }
+
+ // Remember category filename change between temp and live records.
if ( $temp_object->GetDBField('Filename') != $live_object->GetDBField('Filename') ) {
$filename_changes = $this->Application->GetVar($event->Prefix . '_filename_changes', Array ());
@@ -815,6 +836,13 @@
$this->Application->SetVar($event->Prefix . '_filename_changes', $filename_changes);
}
+
+ // Remember category parent change between temp and live records.
+ if ( $temp_object->GetDBField('ParentId') != $live_object->GetDBField('ParentId') ) {
+ $parent_changed = $this->Application->GetVar($event->Prefix . '_parent_changed', array());
+ $parent_changed[$live_object->GetID()] = $live_object->GetDBField('ParentId');
+ $this->Application->SetVar($event->Prefix . '_parent_changed', $parent_changed);
+ }
}
/**
@@ -989,6 +1017,8 @@
$temp_handler->DeleteItems('system-event-subscription', '', $ids);
}
+
+ $this->quickCategoryCacheRebuild($this->removeLastFromPath($object->GetDBField('ParentPath')), null);
}
/**
@@ -1284,6 +1314,7 @@
{
$this->Application->StoreVar('PermCache_UpdateRequired', 1);
$this->Application->StoreVar('RefreshStructureTree', 1);
+ $this->_resetMenuCache();
}
/**
@@ -1487,11 +1518,6 @@
$object = $event->getObject();
/* @var $object kDBItem */
- $cache_updater = $this->Application->makeClass('kPermCacheUpdater', Array (null, $object->GetDBField('ParentPath')));
- /* @var $cache_updater kPermCacheUpdater */
-
- $cache_updater->OneStepRun();
-
$is_active = ($object->GetDBField('Status') == STATUS_ACTIVE);
$next_template = $is_active ? 'suggest_confirm_template' : 'suggest_pending_confirm_template';
@@ -2335,13 +2361,93 @@
{
parent::OnAfterItemCreate($event);
+ /** @var CategoriesItem $object */
$object = $event->getObject();
- /* @var $object CategoriesItem */
- // need to update path after category is created, so category is included in that path
- $fields_hash = $object->buildParentBasedFields();
- $this->Conn->doUpdate($fields_hash, $object->TableName, $object->IDField . ' = ' . $object->GetID());
- $object->SetDBFieldsFromHash($fields_hash);
+ // The hierarchy fields would be updated in "OnAfterCopyToLive" event.
+ if ( $object->IsTempTable() ) {
+ return;
+ }
+
+ $this->refreshHierarchyFields($object, true);
+ $this->quickCategoryCacheRebuild($object->GetDBField('ParentPath'), 0);
+ }
+
+ /**
+ * Occurs after updating item
+ *
+ * @param kEvent $event Event.
+ *
+ * @return void
+ */
+ protected function OnAfterItemUpdate(kEvent $event)
+ {
+ parent::OnAfterItemUpdate($event);
+
+ /** @var CategoriesItem $object */
+ $object = $event->getObject();
+
+ // The hierarchy fields would be updated in "OnAfterCopyToLive" event.
+ if ( $object->IsTempTable() || $object->GetDBField('ParentId') == $object->GetOriginalField('ParentId') ) {
+ return;
+ }
+
+ $this->refreshHierarchyFields($object);
+
+ $this->quickCategoryCacheRebuild($object->GetDBField('ParentPath'), $object->GetOriginalField('ParentId'));
+ $this->quickCategoryCacheRebuild($this->removeLastFromPath($object->GetOriginalField('ParentPath')), null);
+ }
+
+ /**
+ * Refreshes category hierarchy fields.
+ *
+ * @param CategoriesItem $category Category.
+ * @param boolean $including_tree_indexes Also calculate values for tree indexes.
+ *
+ * @return void
+ */
+ protected function refreshHierarchyFields(CategoriesItem $category, $including_tree_indexes = false)
+ {
+ $fields_hash = $category->buildParentBasedFields($including_tree_indexes);
+ $this->Conn->doUpdate(
+ $fields_hash,
+ $category->TableName,
+ $category->IDField . ' = ' . $category->GetID()
+ );
+ $category->SetDBFieldsFromHash($fields_hash);
+ }
+
+ /**
+ * Quickly rebuilds category cache for given path only.
+ *
+ * @param string $strict_path Strict path limitation.
+ * @param integer $strict_path_old_parent_id Previous parent of strict category.
+ *
+ * @return void
+ */
+ protected function quickCategoryCacheRebuild($strict_path, $strict_path_old_parent_id)
+ {
+ /** @var kPermCacheUpdater $cache_updater */
+ $cache_updater = $this->Application->makeClass(
+ 'kPermCacheUpdater',
+ array(null, $strict_path, $strict_path_old_parent_id)
+ );
+ $cache_updater->OneStepRun();
+ }
+
+ /**
+ * Removes last category from path.
+ *
+ * @param string $parent_path Parent path.
+ *
+ * @return string
+ */
+ protected function removeLastFromPath($parent_path)
+ {
+ $parent_path = explode('|', trim($parent_path, '|'));
+ array_pop($parent_path);
+
+ return '|' . implode('|', $parent_path) . '|';
}
/**
@@ -2379,7 +2485,10 @@
}
}
- if ( $this->Application->ConfigValue('CategoryPermissionRebuildMode') == CategoryPermissionRebuild::SILENT ) {
+ /** @var CategoryHelper $category_helper */
+ $category_helper = $this->Application->recallObject('CategoryHelper');
+
+ if ( $category_helper->getCategoryPermissionRebuildMode() == CategoryPermissionRebuild::SILENT ) {
$updater = $this->Application->makeClass('kPermCacheUpdater');
/* @var $updater kPermCacheUpdater */
Index: core/units/categories/categories_item.php
===================================================================
--- core/units/categories/categories_item.php
+++ core/units/categories/categories_item.php
@@ -16,13 +16,15 @@
class CategoriesItem extends kDBItem
{
+
/**
* Builds parent path for this category
*
- * @return Array
- * @access public
+ * @param boolean $including_tree_indexes Also calculate values for tree indexes.
+ *
+ * @return array
*/
- public function buildParentBasedFields()
+ public function buildParentBasedFields($including_tree_indexes = false)
{
static $parent_cache = Array (
0 => Array ('ParentPath' => '|', 'NamedParentPath' => '', 'CachedTemplate' => ''),
@@ -60,6 +62,12 @@
'CachedTemplateHash' => kUtil::crc32(mb_strtolower($cached_template)),
);
+ if ( $including_tree_indexes ) {
+ $tree_indexes = $this->Application->getTreeIndex($parent_id);
+ $ret['TreeLeft'] = $tree_indexes['TreeLeft'] + 1;
+ $ret['TreeRight'] = $tree_indexes['TreeLeft'] + 2;
+ }
+
$primary_language = $this->Application->GetDefaultLanguageId();
foreach ($languages as $language_id) {
@@ -286,4 +294,4 @@
} while ($res !== false);
$this->SetDBField($title_field, $new_name);
}
- }
\ No newline at end of file
+ }
Index: core/units/categories/categories_tag_processor.php
===================================================================
--- core/units/categories/categories_tag_processor.php
+++ core/units/categories/categories_tag_processor.php
@@ -512,10 +512,13 @@
$total_cats = (int)$this->Conn->GetOne('SELECT COUNT(*) FROM ' . TABLE_PREFIX . 'Categories');
if ( $continue === false ) {
- $rebuild_mode = $this->Application->ConfigValue('CategoryPermissionRebuildMode');
+ /** @var CategoryHelper $category_helper */
+ $category_helper = $this->Application->recallObject('CategoryHelper');
- if ( $rebuild_mode == CategoryPermissionRebuild::AUTOMATIC && $total_cats > CACHE_PERM_CHUNK_SIZE ) {
- // first step, if category count > CACHE_PERM_CHUNK_SIZE, then ask for cache update
+ if ( $category_helper->getCategoryPermissionRebuildMode() == CategoryPermissionRebuild::AUTOMATIC
+ && $total_cats > CACHE_PERM_CHUNK_SIZE
+ ) {
+ // First step, if category count > CACHE_PERM_CHUNK_SIZE, then ask for cache update.
return true;
}
Index: core/units/helpers/category_helper.php
===================================================================
--- core/units/helpers/category_helper.php
+++ core/units/helpers/category_helper.php
@@ -358,4 +358,21 @@
return $text;
}
+
+ /**
+ * Tells how category cache needs to be rebuilt.
+ *
+ * @return integer
+ */
+ public function getCategoryPermissionRebuildMode()
+ {
+ $rebuild_mode = $this->Application->RecallVar('CategoryPermissionRebuildModeOverride');
+
+ if ( $rebuild_mode !== false ) {
+ return $rebuild_mode;
+ }
+
+ return $this->Application->ConfigValue('CategoryPermissionRebuildMode');
+ }
+
}
Index: core/units/helpers/recursive_helper.php
===================================================================
--- core/units/helpers/recursive_helper.php
+++ core/units/helpers/recursive_helper.php
@@ -98,11 +98,18 @@
$child_categories = array_intersect($dest_parent_path, $category_ids); // get categories, then can't be moved
$category_ids = array_diff($category_ids, $child_categories); // remove them from movable categories list
- if ($category_ids) {
- $sql = 'UPDATE '.$table_name.'
- SET ParentId = '.$dest_category_id.'
- WHERE '.$id_field.' IN ('.implode(',', $category_ids).')';
- $this->Conn->Query($sql);
+ if ( $category_ids ) {
+ /** @var CategoriesItem $move_category */
+ $move_category = $this->Application->recallObject('c.move', null, array('skip_autoload' => true));
+
+ foreach ( $category_ids as $move_category_id ) {
+ $move_category->Load($move_category_id);
+
+ if ( $move_category->GetDBField('ParentId') != $dest_category_id ) {
+ $move_category->SetDBField('ParentId', $dest_category_id);
+ $move_category->Update();
+ }
+ }
}
}
@@ -224,4 +231,4 @@
return $cache[$category_id];
}
- }
\ No newline at end of file
+ }
Event Timeline
Log In to Comment