Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F804478
ChangeLogHelper.php
No One
Temporary
Actions
Download 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
Wed, Feb 26, 11:55 AM
Size
9 KB
Mime Type
text/x-php
Expires
Fri, Feb 28, 11:55 AM (19 h, 32 m)
Engine
blob
Format
Raw Data
Handle
577015
Attached To
rINP In-Portal
ChangeLogHelper.php
View Options
<?php
/**
* @version $Id: ChangeLogHelper.php 16824 2025-01-28 16:19:21Z alex $
* @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
);
}
}
Event Timeline
Log In to Comment