Index: branches/5.2.x/core/units/helpers/helpers_config.php =================================================================== diff -u -r16533 -r16824 --- branches/5.2.x/core/units/helpers/helpers_config.php (.../helpers_config.php) (revision 16533) +++ branches/5.2.x/core/units/helpers/helpers_config.php (.../helpers_config.php) (revision 16824) @@ -1,6 +1,6 @@ 'AjaxFormHelper', 'class' => 'AjaxFormHelper', 'file' => 'ajax_form_helper.php', 'build_event' => ''), Array ('pseudo' => 'kCronHelper', 'class' => 'kCronHelper', 'file' => 'cron_helper.php', 'build_event' => ''), Array ('pseudo' => 'kUploadHelper', 'class' => 'kUploadHelper', 'file' => 'upload_helper.php', 'build_event' => ''), + Array ('pseudo' => 'ChangeLogHelper', 'class' => 'ChangeLogHelper', 'file' => 'ChangeLogHelper.php', 'build_event' => ''), ), ); Index: branches/5.2.x/core/kernel/db/dbitem.php =================================================================== diff -u -r16709 -r16824 --- branches/5.2.x/core/kernel/db/dbitem.php (.../dbitem.php) (revision 16709) +++ branches/5.2.x/core/kernel/db/dbitem.php (.../dbitem.php) (revision 16824) @@ -1,6 +1,6 @@ Conn->Query('UPDATE '.$this->TableName.' SET `'.$this->IDField.'` = '.$new_id.' WHERE `'.$this->IDField.'` = '.$this->GetID()); - if ($this->ShouldLogChanges(true)) { - // Updating TempId in ChangesLog, if changes are disabled - $ses_var_name = $this->Application->GetTopmostPrefix($this->Prefix) . '_changes_' . $this->Application->GetTopmostWid($this->Prefix); - $changes = $this->Application->RecallVar($ses_var_name); - $changes = $changes ? unserialize($changes) : Array (); - - if ($changes) { - foreach ($changes as $key => $rec) { - if ($rec['Prefix'] == $this->Prefix && $rec['ItemId'] == $this->GetID()) { - // change log for record, that's ID was just updated -> update in change log record too - $changes[$key]['ItemId'] = $new_id; - } - - if ($rec['MasterPrefix'] == $this->Prefix && $rec['MasterId'] == $this->GetID()) { - // master item id was changed - $changes[$key]['MasterId'] = $new_id; - } - - if (in_array($this->Prefix, $rec['ParentPrefix']) && $rec['ParentId'][$this->Prefix] == $this->GetID()) { - // change log record of given item's sub item -> update changed id's in dependent fields - $changes[$key]['ParentId'][$this->Prefix] = $new_id; - - if (array_key_exists('DependentFields', $rec)) { - // these are fields from table of $rec['Prefix'] table! - // when one of dependent fields goes into idfield of it's parent item, that was changed - $parent_table_key = $this->Application->getUnitOption($rec['Prefix'], 'ParentTableKey'); - $parent_table_key = is_array($parent_table_key) ? $parent_table_key[$this->Prefix] : $parent_table_key; - - if ($parent_table_key == $this->IDField) { - $foreign_key = $this->Application->getUnitOption($rec['Prefix'], 'ForeignKey'); - $foreign_key = is_array($foreign_key) ? $foreign_key[$this->Prefix] : $foreign_key; - - $changes[$key]['DependentFields'][$foreign_key] = $new_id; - } - } - } - } - } - - $this->Application->StoreVar($ses_var_name, serialize($changes)); + if ( $this->ShouldLogChanges(true) ) { + /** @var ChangeLogHelper $change_log_helper */ + $change_log_helper = $this->Application->recallObject('ChangeLogHelper'); + $change_log_helper->updateForeignKeys( + array('Prefix' => $this->Prefix, 'IdField' => $this->IDField), + $new_id, + $this->GetID(), + $this->Application->GetTopmostPrefix($this->Prefix) + ); } $old_id = $this->GetID(); @@ -1214,14 +1183,12 @@ $this->Application->StoreVar($main_prefix . '_modified', '1', true); // true for optional if ( $this->ShouldLogChanges(true) ) { - $this->LogChanges($main_prefix, $mode, $update_fields); + /** @var ChangeLogHelper $change_log_helper */ + $change_log_helper = $this->Application->recallObject('ChangeLogHelper'); + $change_log_helper->logChanges($this, $mode, $update_fields); - if (!$this->IsTempTable()) { - /** @var kDBEventHandler $handler */ - $handler = $this->Application->recallObject($this->Prefix . '_EventHandler'); - - $ses_var_name = $main_prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix); - $handler->SaveLoggedChanges($ses_var_name, $this->ShouldLogChanges()); + if ( !$this->IsTempTable() ) { + $change_log_helper->saveLoggedChanges($this->Prefix, $this->ShouldLogChanges()); } } } @@ -1242,97 +1209,6 @@ return $log_changes && !$this->Application->getUnitOption($this->Prefix, 'ForceDontLogChanges'); } - protected function LogChanges($main_prefix, $mode, $update_fields = null) - { - if ( !$mode ) { - return ; - } - - $ses_var_name = $main_prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix); - $changes = $this->Application->RecallVar($ses_var_name); - $changes = $changes ? unserialize($changes) : Array (); - - $fields_hash = Array ( - 'Prefix' => $this->Prefix, - 'ItemId' => $this->GetID(), - 'OccuredOn' => adodb_mktime(), - 'MasterPrefix' => $main_prefix, - 'Action' => $mode, - ); - - if ( $this->Prefix == $main_prefix ) { - // main item - $fields_hash['MasterId'] = $this->GetID(); - $fields_hash['ParentPrefix'] = Array ($main_prefix); - $fields_hash['ParentId'] = Array ($main_prefix => $this->GetID()); - } - else { - // sub item - // collect foreign key values (for serial reset) - $foreign_keys = $this->Application->getUnitOption($this->Prefix, 'ForeignKey', Array ()); - $dependent_fields = $fields_hash['ParentId'] = $fields_hash['ParentPrefix'] = Array (); - /** @var Array $foreign_keys */ - - if ( is_array($foreign_keys) ) { - foreach ($foreign_keys as $prefix => $field_name) { - $dependent_fields[$field_name] = $this->GetDBField($field_name); - $fields_hash['ParentPrefix'][] = $prefix; - $fields_hash['ParentId'][$prefix] = $this->getParentId($prefix); - } - } - else { - $dependent_fields[$foreign_keys] = $this->GetDBField($foreign_keys); - $fields_hash['ParentPrefix'] = Array ( $this->Application->getUnitOption($this->Prefix, 'ParentPrefix') ); - $fields_hash['ParentId'][ $fields_hash['ParentPrefix'][0] ] = $this->getParentId('auto'); - } - - $fields_hash['DependentFields'] = $dependent_fields; - - - // works only, when main item is present in url, when sub-item is changed - $master_id = $this->Application->GetVar($main_prefix . '_id'); - - if ( $master_id === false ) { - // works in case of we are not editing topmost item, when sub-item is created/updated/deleted - $master_id = $this->getParentId('auto', true); - } - - $fields_hash['MasterId'] = $master_id; - } - - switch ( $mode ) { - case ChangeLog::UPDATE: - $changed_fields = $this->GetChangedFields(); - - if ( $update_fields ) { - $changed_fields = array_intersect_key( - $changed_fields, - array_combine($update_fields, $update_fields) - ); - } - - $to_save = array_merge($this->GetTitleField(), $changed_fields); - break; - - case ChangeLog::CREATE: - $to_save = $this->GetTitleField(); - break; - - case ChangeLog::DELETE: - $to_save = array_merge($this->GetTitleField(), $this->GetRealFields()); - break; - - default: - $to_save = Array (); - break; - } - - $fields_hash['Changes'] = serialize($to_save); - $changes[] = $fields_hash; - - $this->Application->StoreVar($ses_var_name, serialize($changes)); - } - /** * Returns current item parent's ID * Index: branches/5.2.x/core/kernel/utility/temp_handler.php =================================================================== diff -u -r16797 -r16824 --- branches/5.2.x/core/kernel/utility/temp_handler.php (.../temp_handler.php) (revision 16797) +++ branches/5.2.x/core/kernel/utility/temp_handler.php (.../temp_handler.php) (revision 16824) @@ -1,6 +1,6 @@ changeLogHelper = $this->Application->recallObject('ChangeLogHelper'); + } + + /** * Sets new parent event to the object * * @param kEvent $event @@ -697,7 +714,7 @@ WHERE ' . $master['IdField'] . ' = 0'; $this->Conn->Query($query); - $this->UpdateChangeLogForeignKeys($master, $live_ids[$an_id], $an_id); + $this->changeLogHelper->updateForeignKeys($master, $live_ids[$an_id], $an_id, $this->Prefix); } } @@ -783,55 +800,9 @@ return $connection; } - function UpdateChangeLogForeignKeys($master, $live_id, $temp_id) - { - if ($live_id == $temp_id) { - return ; - } - - $prefix = $master['Prefix']; - $main_prefix = $this->Application->GetTopmostPrefix($prefix); - $ses_var_name = $main_prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix); - $changes = $this->Application->RecallVar($ses_var_name); - $changes = $changes ? unserialize($changes) : Array (); - - foreach ($changes as $key => $rec) { - if ($rec['Prefix'] == $prefix && $rec['ItemId'] == $temp_id) { - // main item change log record - $changes[$key]['ItemId'] = $live_id; - } - - if ($rec['MasterPrefix'] == $prefix && $rec['MasterId'] == $temp_id) { - // sub item change log record - $changes[$key]['MasterId'] = $live_id; - } - - if (in_array($prefix, $rec['ParentPrefix']) && $rec['ParentId'][$prefix] == $temp_id) { - // parent item change log record - $changes[$key]['ParentId'][$prefix] = $live_id; - - if (array_key_exists('DependentFields', $rec)) { - // these are fields from table of $rec['Prefix'] table! - // when one of dependent fields goes into idfield of it's parent item, that was changed - $parent_table_key = $this->Application->getUnitOption($rec['Prefix'], 'ParentTableKey'); - $parent_table_key = is_array($parent_table_key) ? $parent_table_key[$prefix] : $parent_table_key; - - if ($parent_table_key == $master['IdField']) { - $foreign_key = $this->Application->getUnitOption($rec['Prefix'], 'ForeignKey'); - $foreign_key = is_array($foreign_key) ? $foreign_key[$prefix] : $foreign_key; - - $changes[$key]['DependentFields'][$foreign_key] = $live_id; - } - } - } - } - - $this->Application->StoreVar($ses_var_name, serialize($changes)); - } - function UpdateForeignKeys($master, $live_id, $temp_id) { - $this->UpdateChangeLogForeignKeys($master, $live_id, $temp_id); + $this->changeLogHelper->updateForeignKeys($master, $live_id, $temp_id, $this->Prefix); foreach ($master['SubTables'] as $sub_table) { $foreign_key_field = is_array($sub_table['ForeignKey']) ? getArrayValue($sub_table, 'ForeignKey', $master['Prefix']) : $sub_table['ForeignKey']; Index: branches/5.2.x/core/kernel/db/db_event_handler.php =================================================================== diff -u -r16797 -r16824 --- branches/5.2.x/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 16797) +++ branches/5.2.x/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 16824) @@ -1,6 +1,6 @@ setPendingActions(null, true); - $changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix); - $this->Application->RemoveVar($changes_var_name); + /** @var ChangeLogHelper $change_log_helper */ + $change_log_helper = $this->Application->recallObject('ChangeLogHelper'); + $change_log_helper->forgetChanges($this->Prefix); /** @var kTempTablesHandler $temp_handler */ $temp_handler = $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler', Array ('parent_event' => $event)); @@ -1949,8 +1950,6 @@ /** @var kTempTablesHandler $temp_handler */ $temp_handler = $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler', Array ('parent_event' => $event)); - $changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix); - if ( !$this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) { $live_ids = $temp_handler->SaveEdit($event->getEventParam('master_ids') ? $event->getEventParam('master_ids') : Array ()); @@ -1969,7 +1968,9 @@ /** @var kDBItem $object */ $object = $event->getObject(); - $this->SaveLoggedChanges($changes_var_name, $object->ShouldLogChanges()); + /** @var ChangeLogHelper $change_log_helper */ + $change_log_helper = $this->Application->recallObject('ChangeLogHelper'); + $change_log_helper->saveLoggedChanges($this->Prefix, $object->ShouldLogChanges()); } else { $event->status = kEvent::erFAIL; @@ -1985,101 +1986,22 @@ } /** - * Saves changes made in temporary table to log + * Saves changes made in the temporary table to log. * - * @param string $changes_var_name - * @param bool $save - * @return void - * @access public + * @param string $changes_var_name Changes var name. + * @param boolean $save Save changes. + * + * @return void + * @deprecated 5.2.2-B3 + * @see ChangeLogHelper::saveLoggedChanges() */ public function SaveLoggedChanges($changes_var_name, $save = true) { - // 1. get changes, that were made - $changes = $this->Application->RecallVar($changes_var_name); - $changes = $changes ? unserialize($changes) : Array (); - $this->Application->RemoveVar($changes_var_name); + kUtil::deprecatedMethod(__METHOD__, '5.2.2-B3', 'ChangeLogHelper::saveLoggedChanges'); - if (!$changes) { - // no changes, skip processing - return ; - } - - // TODO: 2. optimize change log records (replace multiple changes to same record with one change record) - - $to_increment = Array (); - - // 3. collect serials to reset based on foreign keys - foreach ($changes as $index => $rec) { - if (array_key_exists('DependentFields', $rec)) { - - foreach ($rec['DependentFields'] as $field_name => $field_value) { - // will be "ci|ItemResourceId:345" - $to_increment[] = $rec['Prefix'] . '|' . $field_name . ':' . $field_value; - - // also reset sub-item prefix general serial - $to_increment[] = $rec['Prefix']; - } - - unset($changes[$index]['DependentFields']); - } - - unset($changes[$index]['ParentId'], $changes[$index]['ParentPrefix']); - } - - // 4. collect serials to reset based on changed ids - foreach ($changes as $change) { - $to_increment[] = $change['MasterPrefix'] . '|' . $change['MasterId']; - - if ($change['MasterPrefix'] != $change['Prefix']) { - // also reset sub-item prefix general serial - $to_increment[] = $change['Prefix']; - - // will be "ci|ItemResourceId" - $to_increment[] = $change['Prefix'] . '|' . $change['ItemId']; - } - } - - // 5. reset serials collected before - $to_increment = array_unique($to_increment); - $this->Application->incrementCacheSerial($this->Prefix); - - foreach ($to_increment as $to_increment_mixed) { - if (strpos($to_increment_mixed, '|') !== false) { - list ($to_increment_prefix, $to_increment_id) = explode('|', $to_increment_mixed, 2); - $this->Application->incrementCacheSerial($to_increment_prefix, $to_increment_id); - } - else { - $this->Application->incrementCacheSerial($to_increment_mixed); - } - } - - // save changes to database - $sesion_log_id = $this->Application->RecallVar('_SessionLogId_'); - - if (!$save || !$sesion_log_id) { - // saving changes to database disabled OR related session log missing - return ; - } - - $add_fields = Array ( - 'PortalUserId' => $this->Application->RecallVar('user_id'), - 'SessionLogId' => $sesion_log_id, - ); - - $change_log_table = $this->Application->getUnitOption('change-log', 'TableName'); - - foreach ($changes as $rec) { - $this->Conn->doInsert(array_merge($rec, $add_fields), $change_log_table); - } - - $this->Application->incrementCacheSerial('change-log'); - - $sql = 'UPDATE ' . $this->Application->getUnitOption('session-log', 'TableName') . ' - SET AffectedItems = AffectedItems + ' . count($changes) . ' - WHERE SessionLogId = ' . $sesion_log_id; - $this->Conn->Query($sql); - - $this->Application->incrementCacheSerial('session-log'); + /** @var ChangeLogHelper $change_log_helper */ + $change_log_helper = $this->Application->recallObject('ChangeLogHelper'); + $change_log_helper->saveLoggedChanges($this->Prefix, $save); } /** @@ -2100,8 +2022,9 @@ $this->Application->RemoveVar($event->getPrefixSpecial() . '_modified'); - $changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix); - $this->Application->RemoveVar($changes_var_name); + /** @var ChangeLogHelper $change_log_helper */ + $change_log_helper = $this->Application->recallObject('ChangeLogHelper'); + $change_log_helper->forgetChanges($this->Prefix); $event->SetRedirectParam('opener', 'u'); } @@ -2271,8 +2194,9 @@ $this->Application->SetVar($event->getPrefixSpecial() . '_id', 0); $this->Application->SetVar($event->getPrefixSpecial() . '_PreCreate', 1); - $changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix); - $this->Application->RemoveVar($changes_var_name); + /** @var ChangeLogHelper $change_log_helper */ + $change_log_helper = $this->Application->recallObject('ChangeLogHelper'); + $change_log_helper->forgetChanges($this->Prefix); $event->redirect = false; } Index: branches/5.2.x/core/units/helpers/ChangeLogHelper.php =================================================================== diff -u --- branches/5.2.x/core/units/helpers/ChangeLogHelper.php (revision 0) +++ branches/5.2.x/core/units/helpers/ChangeLogHelper.php (revision 16824) @@ -0,0 +1,316 @@ +getSessionVariableName($main_prefix, $main_prefix); + $this->Application->RemoveVar($ses_var_name); + } + + /** + * Updates the foreign keys in the changelog for a given table based on the provided identifiers. + * + * This method ensures that all references to the temporary ID in the changelog are updated to use + * the live ID, while considering dependencies and relationships between items. + * + * @param array $table_info Table info. + * @param integer $live_id Live ID. + * @param integer $temp_id Temp ID. + * @param string $caller_prefix Caller prefix. + * + * @return void + */ + public function updateForeignKeys(array $table_info, $live_id, $temp_id, $caller_prefix) + { + if ( $live_id == $temp_id ) { + return; + } + + $prefix = $table_info['Prefix']; + $main_prefix = $this->Application->GetTopmostPrefix($prefix); + + $ses_var_name = $this->getSessionVariableName($main_prefix, $caller_prefix); + $changes = $this->Application->RecallVar($ses_var_name); + $changes = $changes ? unserialize($changes) : array(); + + if ( !$changes ) { + return; + } + + foreach ( $changes as $key => $rec ) { + // The main item changelog record. + if ( $rec['Prefix'] == $prefix && $rec['ItemId'] == $temp_id ) { + $changes[$key]['ItemId'] = $live_id; + } + + // The subitem changelog record. + if ( $rec['MasterPrefix'] == $prefix && $rec['MasterId'] == $temp_id ) { + $changes[$key]['MasterId'] = $live_id; + } + + // The parent item changelog record. + if ( in_array($prefix, $rec['ParentPrefix']) && $rec['ParentId'][$prefix] == $temp_id ) { + $changes[$key]['ParentId'][$prefix] = $live_id; + + if ( array_key_exists('DependentFields', $rec) ) { + /* + * These are fields from the $rec['Prefix'] table! + * Used, when one of the dependent fields uses IdField of its changed parent item. + */ + $parent_table_key = $this->Application->getUnitOption($rec['Prefix'], 'ParentTableKey'); + $parent_table_key = is_array($parent_table_key) ? $parent_table_key[$prefix] : $parent_table_key; + + if ( $parent_table_key == $table_info['IdField'] ) { + $foreign_key = $this->Application->getUnitOption($rec['Prefix'], 'ForeignKey'); + $foreign_key = is_array($foreign_key) ? $foreign_key[$prefix] : $foreign_key; + + $changes[$key]['DependentFields'][$foreign_key] = $live_id; + } + } + } + } + + $this->Application->StoreVar($ses_var_name, serialize($changes)); + } + + /** + * Logs changes for a database item, tracking relevant details for create, update, or delete actions. + * + * @param kDBItem $object Object. + * @param integer $mode Mode (e.g., create, update, delete). + * @param array|null $update_fields Update fields. + * + * @return void + */ + public function logChanges(kDBItem $object, $mode, array $update_fields = null) + { + if ( !$mode ) { + return; + } + + $prefix = $object->Prefix; + $main_prefix = $this->Application->GetTopmostPrefix($prefix); + + $ses_var_name = $this->getSessionVariableName($main_prefix, $prefix); + $changes = $this->Application->RecallVar($ses_var_name); + $changes = $changes ? unserialize($changes) : array(); + + $fields_hash = array( + 'Prefix' => $prefix, + 'ItemId' => $object->GetID(), + 'OccuredOn' => adodb_mktime(), + 'MasterPrefix' => $main_prefix, + 'Action' => $mode, + ); + + if ( $prefix == $main_prefix ) { + // Main item. + $fields_hash['MasterId'] = $object->GetID(); + $fields_hash['ParentPrefix'] = array($main_prefix); + $fields_hash['ParentId'] = array($main_prefix => $object->GetID()); + } + else { + /* + * Subitem. + * Collect foreign key values (for serial reset). + */ + $foreign_keys = $this->Application->getUnitOption($prefix, 'ForeignKey', array()); + $dependent_fields = $fields_hash['ParentId'] = $fields_hash['ParentPrefix'] = array(); + /** @var Array $foreign_keys */ + + if ( is_array($foreign_keys) ) { + foreach ( $foreign_keys as $foreign_key_prefix => $foreign_key_field_name ) { + $dependent_fields[$foreign_key_field_name] = $object->GetDBField($foreign_key_field_name); + $fields_hash['ParentPrefix'][] = $foreign_key_prefix; + $fields_hash['ParentId'][$foreign_key_prefix] = $object->getParentId($foreign_key_prefix); + } + } + else { + $dependent_fields[$foreign_keys] = $object->GetDBField($foreign_keys); + $fields_hash['ParentPrefix'] = array( + $this->Application->getUnitOption($prefix, 'ParentPrefix'), + ); + $fields_hash['ParentId'][$fields_hash['ParentPrefix'][0]] = $object->getParentId('auto'); + } + + $fields_hash['DependentFields'] = $dependent_fields; + + // Works only when the main item is present in url when a subitem is changed. + $master_id = $this->Application->GetVar($main_prefix . '_id'); + + if ( $master_id === false ) { + // Works in case when we're not editing topmost item, when subitem is created/updated/deleted. + $master_id = $object->getParentId('auto', true); + } + + $fields_hash['MasterId'] = $master_id; + } + + switch ( $mode ) { + case ChangeLog::UPDATE: + $changed_fields = $object->GetChangedFields(); + + if ( $update_fields ) { + $changed_fields = array_intersect_key( + $changed_fields, + array_combine($update_fields, $update_fields) + ); + } + + $to_save = array_merge($object->GetTitleField(), $changed_fields); + break; + + case ChangeLog::CREATE: + $to_save = $object->GetTitleField(); + break; + + case ChangeLog::DELETE: + $to_save = array_merge($object->GetTitleField(), $object->GetRealFields()); + break; + + default: + $to_save = array(); + break; + } + + $fields_hash['Changes'] = serialize($to_save); + $changes[] = $fields_hash; + + $this->Application->StoreVar($ses_var_name, serialize($changes)); + } + + /** + * Saves changes made in the temporary table to log. + * + * @param string $prefix Prefix. + * @param boolean $save Save changes. + * + * @return void + */ + public function saveLoggedChanges($prefix, $save = true) + { + $main_prefix = $this->Application->GetTopmostPrefix($prefix); + + // 1. get changes that were made. + $ses_var_name = $this->getSessionVariableName($main_prefix, $prefix); + $changes = $this->Application->RecallVar($ses_var_name); + $changes = $changes ? unserialize($changes) : array(); + $this->Application->RemoveVar($ses_var_name); + + if ( !$changes ) { + // No changes, skip processing. + return; + } + + // TODO: 2. optimize change log records (replace multiple changes to same record with one change record). + $to_increment = array(); + + // 3. collect serials to reset based on foreign keys + foreach ( $changes as $index => $rec ) { + if ( array_key_exists('DependentFields', $rec) ) { + foreach ( $rec['DependentFields'] as $field_name => $field_value ) { + // Will be "ci|ItemResourceId:345". + $to_increment[] = $rec['Prefix'] . '|' . $field_name . ':' . $field_value; + + // Also reset sub-item prefix general serial. + $to_increment[] = $rec['Prefix']; + } + + unset($changes[$index]['DependentFields']); + } + + // Remove keys that don't have corresponding columns in the "ChangeLogs" database table. + unset($changes[$index]['ParentId'], $changes[$index]['ParentPrefix']); + } + + // 4. collect serials to reset based on changed ids + foreach ( $changes as $change ) { + $to_increment[] = $change['MasterPrefix'] . '|' . $change['MasterId']; + + if ( $change['MasterPrefix'] != $change['Prefix'] ) { + // Also reset sub-item prefix general serial. + $to_increment[] = $change['Prefix']; + + // Will be "ci|ItemResourceId". + $to_increment[] = $change['Prefix'] . '|' . $change['ItemId']; + } + } + + // 5. reset serials collected before + $to_increment = array_unique($to_increment); + $this->Application->incrementCacheSerial($prefix); + + foreach ( $to_increment as $to_increment_mixed ) { + if ( strpos($to_increment_mixed, '|') !== false ) { + list ($to_increment_prefix, $to_increment_id) = explode('|', $to_increment_mixed, 2); + $this->Application->incrementCacheSerial($to_increment_prefix, $to_increment_id); + } + else { + $this->Application->incrementCacheSerial($to_increment_mixed); + } + } + + // Save changes to a database. + $session_log_id = $this->Application->RecallVar('_SessionLogId_'); + + if ( !$save || !$session_log_id ) { + // Saving changes to database disabled OR related session log missing. + return; + } + + $add_fields = array( + 'PortalUserId' => $this->Application->RecallVar('user_id'), + 'SessionLogId' => $session_log_id, + ); + + $change_log_table = $this->Application->getUnitOption('change-log', 'TableName'); + + foreach ( $changes as $rec ) { + $this->Conn->doInsert(array_merge($rec, $add_fields), $change_log_table); + } + + $this->Application->incrementCacheSerial('change-log'); + + $sql = 'UPDATE ' . $this->Application->getUnitOption('session-log', 'TableName') . ' + SET AffectedItems = AffectedItems + ' . count($changes) . ' + WHERE SessionLogId = ' . $session_log_id; + $this->Conn->Query($sql); + + $this->Application->incrementCacheSerial('session-log'); + } + + /** + * Returns change log session variable name. + * + * @param string $main_prefix Main prefix. + * @param string $prefix Prefix. + * + * @return string + */ + protected function getSessionVariableName($main_prefix, $prefix) + { + return $main_prefix . '_changes_' . $this->Application->GetTopmostWid($prefix); + } + +}