Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F775807
D504.id1309.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
Thu, Feb 6, 6:36 AM
Size
27 KB
Mime Type
text/x-diff
Expires
Fri, Feb 7, 6:36 AM (14 h, 32 m)
Engine
blob
Format
Raw Data
Handle
558320
Attached To
D504: INP-1894 - Extract "Change Log" code to a central place
D504.id1309.diff
View Options
Index: branches/5.2.x/core/kernel/db/db_event_handler.php
===================================================================
--- branches/5.2.x/core/kernel/db/db_event_handler.php
+++ branches/5.2.x/core/kernel/db/db_event_handler.php
@@ -1909,8 +1909,9 @@
$object->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);
-
- 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);
+ kUtil::deprecatedMethod(__METHOD__, '5.2.2-B3', 'ChangeLogHelper::saveLoggedChanges');
- $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/kernel/db/dbitem.php
===================================================================
--- branches/5.2.x/core/kernel/db/dbitem.php
+++ branches/5.2.x/core/kernel/db/dbitem.php
@@ -1147,46 +1147,15 @@
$this->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);
-
- if (!$this->IsTempTable()) {
- /** @var kDBEventHandler $handler */
- $handler = $this->Application->recallObject($this->Prefix . '_EventHandler');
+ /** @var ChangeLogHelper $change_log_helper */
+ $change_log_helper = $this->Application->recallObject('ChangeLogHelper');
+ $change_log_helper->logChanges($this, $mode, $update_fields);
- $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
===================================================================
--- branches/5.2.x/core/kernel/utility/temp_handler.php
+++ branches/5.2.x/core/kernel/utility/temp_handler.php
@@ -74,6 +74,23 @@
protected $parentEvent = null;
/**
+ * Change Log helper.
+ *
+ * @var $changeLogHelper
+ */
+ protected $changeLogHelper;
+
+ /**
+ * Creates class instance.
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ $this->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/units/helpers/ChangeLogHelper.php
===================================================================
--- branches/5.2.x/core/units/helpers/ChangeLogHelper.php
+++ branches/5.2.x/core/units/helpers/ChangeLogHelper.php
@@ -0,0 +1,316 @@
+<?php
+/**
+* @version $Id$
+* @package In-Portal
+* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
+* @license GNU/GPL
+* In-Portal is Open Source software.
+* This means that this software may have been modified pursuant
+* the GNU General Public License, and as distributed it includes
+* or is derivative of works licensed under the GNU General Public License
+* or other free or open source software licenses.
+* See http://www.in-portal.org/license for copyright notices and details.
+*/
+
+class ChangeLogHelper extends kHelper
+{
+
+ /**
+ * Forgets changes.
+ *
+ * @param string $main_prefix Main prefix.
+ *
+ * @return void
+ */
+ public function forgetChanges($main_prefix)
+ {
+ $ses_var_name = $this->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);
+ }
+
+}
Index: branches/5.2.x/core/units/helpers/helpers_config.php
===================================================================
--- branches/5.2.x/core/units/helpers/helpers_config.php
+++ branches/5.2.x/core/units/helpers/helpers_config.php
@@ -78,5 +78,6 @@
Array ('pseudo' => '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' => ''),
),
);
Event Timeline
Log In to Comment