5653 lines
170 KiB
Perl
5653 lines
170 KiB
Perl
# --
|
|
# Copyright (C) 2001-2019 OTRS AG, https://otrs.com/
|
|
# --
|
|
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
|
|
# the enclosed file COPYING for license information (GPL). If you
|
|
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
|
|
# --
|
|
|
|
package Kernel::System::SysConfig::DB;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use MIME::Base64;
|
|
use Time::HiRes();
|
|
use utf8;
|
|
|
|
use Kernel::System::VariableCheck qw( :all );
|
|
|
|
our @ObjectDependencies = (
|
|
'Kernel::Config',
|
|
'Kernel::System::Cache',
|
|
'Kernel::System::DB',
|
|
'Kernel::System::Encode',
|
|
'Kernel::System::Log',
|
|
'Kernel::System::Main',
|
|
'Kernel::System::YAML',
|
|
);
|
|
|
|
=head1 NAME
|
|
|
|
Kernel::System::SysConfig::DB - Functions to manage system configuration settings interactions with the database.
|
|
|
|
=head1 PUBLIC INTERFACE
|
|
|
|
=head2 new()
|
|
|
|
Create an object. Do not use it directly, instead use:
|
|
|
|
use Kernel::System::ObjectManager;
|
|
local $Kernel::OM = Kernel::System::ObjectManager->new();
|
|
my $SysConfigDBObject = $Kernel::OM->Get('Kernel::System::SysConfig::DB');
|
|
|
|
=cut
|
|
|
|
sub new {
|
|
my ( $Type, %Param ) = @_;
|
|
|
|
# allocate new hash for object
|
|
my $Self = {};
|
|
bless( $Self, $Type );
|
|
|
|
$Self->{CacheTTL} = 24 * 3600 * 30; # 1 month
|
|
|
|
return $Self;
|
|
}
|
|
|
|
=head2 DefaultSettingAdd()
|
|
|
|
Add a new SysConfig default entry.
|
|
|
|
my $DefaultID = $SysConfigDBObject->DefaultSettingAdd(
|
|
Name => "ProductName", # (required)
|
|
Description => "Setting description", # (required)
|
|
Navigation => "ASimple::Path::Structure", # (required)
|
|
IsInvisible => 1, # (optional) 1 or 0, default 0
|
|
IsReadonly => 0, # (optional) 1 or 0, default 0
|
|
IsRequired => 1, # (optional) 1 or 0, default 0
|
|
IsValid => 1, # (optional) 1 or 0, default 0
|
|
HasConfigLevel => 200, # (optional) default 0
|
|
UserModificationPossible => 0, # (optional) 1 or 0, default 0
|
|
UserModificationActive => 0, # (optional) 1 or 0, default 0
|
|
UserPreferencesGroup => 'Some Group' # (optional)
|
|
XMLContentRaw => $XMLString, # (required) the setting XML structure as it is on the config file
|
|
XMLContentParsed => $XMLParsedToPerl, # (required) the setting XML structure converted into a Perl structure
|
|
XMLFilename => 'Framework.xml' # (required) the name of the XML file
|
|
EffectiveValue => $SettingEffectiveValue, # (required) the value as will be stored in the Perl configuration file
|
|
ExclusiveLockExpiryTime => '2017-02-01 12:23:13', # (optional) If not provided, method will calculate it.
|
|
UserID => 123,
|
|
NoCleanup => 0, # (optional) Default 0. If enabled, system WILL NOT DELETE CACHE. In this case, it must be done manually.
|
|
# USE IT CAREFULLY.
|
|
);
|
|
|
|
Returns:
|
|
|
|
my $DefaultID = 123; # false in case of an error
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingAdd {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Store params for further usage.
|
|
my %DefaultVersionParams = %Param;
|
|
|
|
for my $Key (
|
|
qw(Name Description Navigation XMLContentRaw XMLContentParsed XMLFilename EffectiveValue UserID)
|
|
)
|
|
{
|
|
if ( !defined $Param{$Key} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Key!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
my @DefaultSettings = $Self->DefaultSettingList(
|
|
IncludeInvisible => 1,
|
|
);
|
|
|
|
# Check duplicate name
|
|
my ($SettingData) = grep { $_->{Name} eq $Param{Name} } @DefaultSettings;
|
|
return if IsHashRefWithData($SettingData);
|
|
|
|
# Check config level.
|
|
$Param{HasConfigLevel} //= 0;
|
|
|
|
# The value should be a positive integer if defined.
|
|
if ( !IsPositiveInteger( $Param{HasConfigLevel} ) && $Param{HasConfigLevel} ne '0' ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "HasConfigLevel must be an integer!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# Check boolean parameters (0 as default value).
|
|
for my $Key (qw(IsInvisible IsReadonly IsRequired IsValid UserModificationPossible UserModificationActive)) {
|
|
$Param{$Key} = ( defined $Param{$Key} && $Param{$Key} ? 1 : 0 );
|
|
}
|
|
|
|
# Serialize data as string.
|
|
for my $Key (qw(XMLContentParsed EffectiveValue)) {
|
|
$Param{$Key} = $Kernel::OM->Get('Kernel::System::YAML')->Dump(
|
|
Data => $Param{$Key},
|
|
);
|
|
$DefaultVersionParams{$Key} = $Param{$Key};
|
|
}
|
|
|
|
# Set GuID.
|
|
$Param{ExclusiveLockGUID} //= 1;
|
|
|
|
# Set is dirty as enabled due it is a new setting.
|
|
$Param{IsDirty} = 1;
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Insert the default.
|
|
return if !$DBObject->Do(
|
|
SQL => '
|
|
INSERT INTO sysconfig_default
|
|
(name, description, navigation, is_invisible, is_readonly, is_required, is_valid, has_configlevel,
|
|
user_modification_possible, user_modification_active, user_preferences_group, xml_content_raw, xml_content_parsed, xml_filename, effective_value,
|
|
is_dirty, exclusive_lock_guid, create_time, create_by, change_time, change_by)
|
|
VALUES
|
|
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)',
|
|
Bind => [
|
|
\$Param{Name}, \$Param{Description}, \$Param{Navigation}, \$Param{IsInvisible},
|
|
\$Param{IsReadonly}, \$Param{IsRequired}, \$Param{IsValid}, \$Param{HasConfigLevel},
|
|
\$Param{UserModificationPossible}, \$Param{UserModificationActive}, \$Param{UserPreferencesGroup},
|
|
\$Param{XMLContentRaw}, \$Param{XMLContentParsed}, \$Param{XMLFilename}, \$Param{EffectiveValue},
|
|
\$Param{IsDirty}, \$Param{ExclusiveLockGUID}, \$Param{UserID}, \$Param{UserID},
|
|
],
|
|
);
|
|
|
|
# Get default ID.
|
|
$DBObject->Prepare(
|
|
SQL => 'SELECT id FROM sysconfig_default WHERE name = ?',
|
|
Bind => [ \$Param{Name} ],
|
|
Limit => 1,
|
|
);
|
|
|
|
my $DefaultID;
|
|
|
|
# Fetch the default setting ID.
|
|
ROW:
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
$DefaultID = $Row[0];
|
|
last ROW;
|
|
}
|
|
|
|
# Add default setting version.
|
|
my $DefaultVersionID = $Self->DefaultSettingVersionAdd(
|
|
DefaultID => $DefaultID,
|
|
%DefaultVersionParams,
|
|
NoVersionID => 1,
|
|
);
|
|
|
|
if ( !$Param{NoCleanup} ) {
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefault',
|
|
Key => 'DefaultSettingGet::' . $Param{Name},
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefaultListGet',
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefaultList',
|
|
Key => 'DefaultSettingList',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigNavigation',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigEntities',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigIsDirty',
|
|
);
|
|
}
|
|
|
|
# Return if not version inserted.
|
|
return if !$DefaultVersionID;
|
|
|
|
return $DefaultID;
|
|
}
|
|
|
|
=head2 DefaultSettingBulkAdd()
|
|
|
|
Add new SysConfig default entries.
|
|
|
|
my $Success = $SysConfigDBObject->DefaultSettingBulkAdd(
|
|
Settings => { # (required) Hash of settings
|
|
"ACL::CacheTTL" => {
|
|
"EffectiveValue" => "--- '3600'\n",
|
|
"XMLContentParsed" => {
|
|
"Description" => [
|
|
{
|
|
"Content" => "Cache time in ...",
|
|
"Translatable" => 1
|
|
},
|
|
],
|
|
"Name" => "ACL::CacheTTL",
|
|
"Navigation" => [
|
|
{
|
|
"Content" => "Core::Ticket::ACL"
|
|
},
|
|
],
|
|
"Required" => 1,
|
|
"Valid" => 1,
|
|
"Value" => [
|
|
{
|
|
"Item" => [
|
|
{
|
|
"Content" => 3600,
|
|
"ValueRegex" => "^\\d+\$",
|
|
"ValueType" => "String"
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
"XMLContentParsedYAML" => "---\nDescription:\n- Content: Cache...",
|
|
"XMLContentRaw" => "<Setting Name=\"ACL::CacheTTL\" Required=\"1\" ...",
|
|
"XMLFilename" => "Ticket.xml"
|
|
},
|
|
...
|
|
},
|
|
SettingList => [ # list of current settings in DB
|
|
{
|
|
DefaultID => '123',
|
|
Name => 'SettingName1',
|
|
IsDirty => 1,
|
|
ExclusiveLockGUID => 0,
|
|
},
|
|
# ...
|
|
],
|
|
UserID => 1, # (required) UserID
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingBulkAdd {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
for my $Needed (qw(Settings UserID)) {
|
|
if ( !$Param{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( ref $Param{Settings} ne 'HASH' ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Settings must be a hash!"
|
|
);
|
|
return;
|
|
}
|
|
|
|
$Param{SettingList} //= [];
|
|
if ( ref $Param{SettingList} ne 'ARRAY' ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "SettingList must be an array",
|
|
);
|
|
}
|
|
|
|
my @Data;
|
|
|
|
SETTINGNAME:
|
|
for my $SettingName ( sort keys %{ $Param{Settings} } ) {
|
|
|
|
my ($BasicData) = grep { $_->{Name} eq $SettingName } @{ $Param{SettingList} };
|
|
|
|
if ($BasicData) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "$SettingName should not exist!"
|
|
);
|
|
next SETTINGNAME;
|
|
}
|
|
|
|
# Gather data for all records.
|
|
push @Data, [
|
|
$SettingName,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{Description}->[0]->{Content} || '',
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{Navigation}->[0]->{Content} || '',
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{Invisible} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{ReadOnly} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{Required} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{Valid} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{ConfigLevel} || 100,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserModificationPossible} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserModificationActive} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserPreferencesGroup},
|
|
$Param{Settings}->{$SettingName}->{XMLContentRaw},
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsedYAML},
|
|
$Param{Settings}->{$SettingName}->{XMLFilename},
|
|
$Param{Settings}->{$SettingName}->{EffectiveValue},
|
|
1,
|
|
1,
|
|
'current_timestamp',
|
|
$Param{UserID},
|
|
'current_timestamp',
|
|
$Param{UserID},
|
|
];
|
|
}
|
|
|
|
return if !$Self->_BulkInsert(
|
|
Table => 'sysconfig_default',
|
|
Columns => [
|
|
'name',
|
|
'description',
|
|
'navigation',
|
|
'is_invisible',
|
|
'is_readonly',
|
|
'is_required',
|
|
'is_valid',
|
|
'has_configlevel',
|
|
'user_modification_possible',
|
|
'user_modification_active',
|
|
'user_preferences_group',
|
|
'xml_content_raw',
|
|
'xml_content_parsed',
|
|
'xml_filename',
|
|
'effective_value',
|
|
'is_dirty',
|
|
'exclusive_lock_guid',
|
|
'create_time',
|
|
'create_by',
|
|
'change_time',
|
|
'change_by'
|
|
],
|
|
Data => \@Data,
|
|
);
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefaultListGet',
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefaultList',
|
|
Key => 'DefaultSettingList',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigNavigation',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigEntities',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigIsDirty',
|
|
);
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 DefaultSettingVersionBulkAdd()
|
|
|
|
my $Success = $SysConfigDBObject->DefaultSettingVersionBulkAdd(
|
|
Settings => { # (required) Hash of settings
|
|
"ACL::CacheTTL" => {
|
|
"EffectiveValue" => "--- '3600'\n",
|
|
"XMLContentParsed" => {
|
|
"Description" => [
|
|
{
|
|
"Content" => "Cache time in ...",
|
|
"Translatable" => 1
|
|
},
|
|
],
|
|
"Name" => "ACL::CacheTTL",
|
|
"Navigation" => [
|
|
{
|
|
"Content" => "Core::Ticket::ACL"
|
|
},
|
|
],
|
|
"Required" => 1,
|
|
"Valid" => 1,
|
|
"Value" => [
|
|
{
|
|
"Item" => [
|
|
{
|
|
"Content" => 3600,
|
|
"ValueRegex" => "^\\d+\$",
|
|
"ValueType" => "String"
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
"XMLContentParsedYAML" => "---\nDescription:\n- Content: Cache...",
|
|
"XMLContentRaw" => "<Setting Name=\"ACL::CacheTTL\" Required=\"1\" ...",
|
|
"XMLFilename" => "Ticket.xml"
|
|
},
|
|
...
|
|
},
|
|
SettingList => [ # list of current settings in DB
|
|
{
|
|
DefaultID => '123',
|
|
Name => 'SettingName1',
|
|
IsDirty => 1,
|
|
ExclusiveLockGUID => 0,
|
|
},
|
|
# ...
|
|
],
|
|
UserID => 1, # (required) UserID
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingVersionBulkAdd {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Check needed stuff.
|
|
for my $Needed (qw(Settings SettingList UserID)) {
|
|
if ( !$Param{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( ref $Param{Settings} ne 'HASH' ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Settings must be a hash!"
|
|
);
|
|
return;
|
|
}
|
|
|
|
my @Data;
|
|
|
|
SETTINGNAME:
|
|
for my $SettingName ( sort keys %{ $Param{Settings} } ) {
|
|
|
|
my ($BasicData) = grep { $_->{Name} eq $SettingName } @{ $Param{SettingList} };
|
|
|
|
if ( !$BasicData || !$BasicData->{DefaultID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "DefaultID for $SettingName couldn't be determined, skipped!"
|
|
);
|
|
next SETTINGNAME;
|
|
}
|
|
|
|
# Gather data for all records.
|
|
push @Data, [
|
|
$BasicData->{DefaultID},
|
|
$SettingName,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{Description}->[0]->{Content} || '',
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{Navigation}->[0]->{Content} || '',
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{Invisible} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{ReadOnly} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{Required} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{Valid} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{ConfigLevel} || 100,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserModificationPossible} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserModificationActive} || 0,
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserPreferencesGroup},
|
|
$Param{Settings}->{$SettingName}->{XMLContentRaw},
|
|
$Param{Settings}->{$SettingName}->{XMLContentParsedYAML},
|
|
$Param{Settings}->{$SettingName}->{XMLFilename},
|
|
$Param{Settings}->{$SettingName}->{EffectiveValue},
|
|
'current_timestamp',
|
|
$Param{UserID},
|
|
'current_timestamp',
|
|
$Param{UserID},
|
|
];
|
|
}
|
|
|
|
return if !$Self->_BulkInsert(
|
|
Table => 'sysconfig_default_version',
|
|
Columns => [
|
|
'sysconfig_default_id',
|
|
'name',
|
|
'description',
|
|
'navigation',
|
|
'is_invisible',
|
|
'is_readonly',
|
|
'is_required',
|
|
'is_valid',
|
|
'has_configlevel',
|
|
'user_modification_possible',
|
|
'user_modification_active',
|
|
'user_preferences_group',
|
|
'xml_content_raw',
|
|
'xml_content_parsed',
|
|
'xml_filename',
|
|
'effective_value',
|
|
'create_time',
|
|
'create_by',
|
|
'change_time',
|
|
'change_by',
|
|
],
|
|
Data => \@Data,
|
|
);
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefaultVersion',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefaultVersionList',
|
|
);
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 DefaultSettingGet()
|
|
|
|
Get SysConfig default entry.
|
|
|
|
my %DefaultSetting = $SysConfigDBObject->DefaultSettingGet(
|
|
Name => "TheName", # (required) Setting name - prefered parameter.
|
|
# or
|
|
DefaultID => 4, # (required) DefaultID. Slightly slower execution.
|
|
NoCache => 0, # (optional) Default 0. If 1, cache will not be created.
|
|
);
|
|
|
|
Returns:
|
|
|
|
%DefaultSetting = (
|
|
DefaultID => "123",
|
|
Name => "ProductName",
|
|
Description => "Defines the name of the application ...",
|
|
Navigation => "ASimple::Path::Structure",
|
|
IsInvisible => 1, # 1 or 0
|
|
IsReadonly => 0, # 1 or 0
|
|
IsRequired => 1, # 1 or 0
|
|
IsValid => 1, # 1 or 0
|
|
HasConfigLevel => 200,
|
|
UserModificationPossible => 0, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
UserPreferencesGroup => 'Some Group',
|
|
XMLContentRaw => "The XML structure as it is on the config file",
|
|
XMLContentParsed => "XML parsed to Perl",
|
|
XMLFilename => "Framework.xml",
|
|
EffectiveValue => "Product 6",
|
|
IsDirty => 1, # 1 or 0
|
|
ExclusiveLockGUID => 'A32CHARACTERLONGSTRINGFORLOCKING',
|
|
ExclusiveLockUserID => 1,
|
|
ExclusiveLockExpiryTime => '2016-05-29 11:09:04',
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
CreateBy => 1,
|
|
ChangeTime => "2016-05-29 11:04:04",
|
|
ChangeBy => 1,
|
|
SettingUID => 'Default12320160529110404',
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DefaultID} && !$Param{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need DefaultID or Name!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $SettingName = $Param{Name};
|
|
|
|
if ( !$SettingName ) {
|
|
my %SettingData = $Self->DefaultSettingLookup(
|
|
DefaultID => $Param{DefaultID},
|
|
);
|
|
|
|
if ( !%SettingData || !$SettingData{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Setting with DefaultID = $Param{DefaultID} not found!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
$SettingName = $SettingData{Name};
|
|
}
|
|
|
|
my $CacheType = "SysConfigDefault";
|
|
my $CacheKey = "DefaultSettingGet::$SettingName";
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return %{$Cache} if ref $Cache eq 'HASH';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Get default from database.
|
|
return if !$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT id, name, description, navigation, is_invisible, is_readonly, is_required, is_valid, has_configlevel,
|
|
user_modification_possible, user_modification_active, user_preferences_group, xml_content_raw,
|
|
xml_content_parsed, xml_filename, effective_value, is_dirty, exclusive_lock_guid, exclusive_lock_user_id,
|
|
exclusive_lock_expiry_time, create_time, create_by, change_time, change_by
|
|
|
|
FROM sysconfig_default
|
|
WHERE name = ?',
|
|
Bind => [ \$SettingName ],
|
|
);
|
|
|
|
my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML');
|
|
|
|
my %DefaultSetting;
|
|
while ( my @Data = $DBObject->FetchrowArray() ) {
|
|
|
|
# De-serialize default data.
|
|
my $XMLContentParsed = $YAMLObject->Load( Data => $Data[13] );
|
|
my $EffectiveValue = $YAMLObject->Load( Data => $Data[15] );
|
|
|
|
my $TimeStamp = $Data[22];
|
|
$TimeStamp =~ s{:|-|[ ]}{}gmsx;
|
|
|
|
%DefaultSetting = (
|
|
DefaultID => $Data[0],
|
|
Name => $Data[1],
|
|
Description => $Data[2],
|
|
Navigation => $Data[3],
|
|
IsInvisible => $Data[4],
|
|
IsReadonly => $Data[5],
|
|
IsRequired => $Data[6],
|
|
IsValid => $Data[7],
|
|
HasConfigLevel => $Data[8],
|
|
UserModificationPossible => $Data[9],
|
|
UserModificationActive => $Data[10],
|
|
UserPreferencesGroup => $Data[11] || '',
|
|
XMLContentRaw => $Data[12],
|
|
XMLContentParsed => $XMLContentParsed,
|
|
XMLFilename => $Data[14],
|
|
EffectiveValue => $EffectiveValue,
|
|
IsDirty => $Data[16] ? 1 : 0,
|
|
ExclusiveLockGUID => $Data[17],
|
|
ExclusiveLockUserID => $Data[18],
|
|
ExclusiveLockExpiryTime => $Data[19],
|
|
CreateTime => $Data[20],
|
|
CreateBy => $Data[21],
|
|
ChangeTime => $Data[22],
|
|
ChangeBy => $Data[23],
|
|
SettingUID => "Default$Data[0]$TimeStamp",
|
|
);
|
|
}
|
|
|
|
if ( !$Param{NoCache} ) {
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \%DefaultSetting,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
}
|
|
|
|
return %DefaultSetting;
|
|
}
|
|
|
|
=head2 DefaultSettingLookup()
|
|
|
|
Default setting lookup.
|
|
|
|
my %Result = $SysConfigDBObject->DefaultSettingLookup(
|
|
Name => "TheName", # (required)
|
|
# or
|
|
DefaultID => 4, # (required)
|
|
);
|
|
|
|
Returns:
|
|
|
|
%Result = (
|
|
DefaultID => 4,
|
|
Name => 'TheName',
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingLookup {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Check needed stuff.
|
|
if ( !$Param{Name} && !$Param{DefaultID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need Name or DefaultID!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
my @Bind;
|
|
|
|
my $SQL = '
|
|
SELECT id, name
|
|
FROM sysconfig_default
|
|
WHERE
|
|
';
|
|
|
|
if ( $Param{Name} ) {
|
|
$SQL .= 'name = ? ';
|
|
push @Bind, \$Param{Name};
|
|
}
|
|
else {
|
|
$SQL .= "id = ? ";
|
|
push @Bind, \$Param{DefaultID};
|
|
}
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# db query
|
|
return if !$DBObject->Prepare(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
Limit => 1,
|
|
);
|
|
|
|
my %Result;
|
|
|
|
ROW:
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
$Result{DefaultID} = $Row[0];
|
|
$Result{Name} = $Row[1];
|
|
last ROW;
|
|
}
|
|
|
|
return %Result;
|
|
}
|
|
|
|
=head2 DefaultSettingDelete()
|
|
|
|
Delete a default setting from the database.
|
|
|
|
my $Success = $SysConfigDBObject->DefaultSettingDelete(
|
|
DefaultID => 123,
|
|
);
|
|
|
|
my $Success = $SysConfigDBObject->DefaultSettingDelete(
|
|
Name => 'Name',
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Success = 1; # or false in case of an error
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingDelete {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DefaultID} && !$Param{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need DefaultID or Name!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my %DefaultSetting = $Self->DefaultSettingGet(
|
|
DefaultID => $Param{DefaultID} || undef,
|
|
Name => $Param{Name} || undef,
|
|
);
|
|
return 1 if !IsHashRefWithData( \%DefaultSetting );
|
|
|
|
my $DefaultID = $DefaultSetting{DefaultID};
|
|
|
|
# Delete the entries in SysConfig default version.
|
|
my $DeleteDefaultVersion = $Self->DefaultSettingVersionDelete(
|
|
DefaultID => $DefaultID,
|
|
);
|
|
|
|
# Return if not version deleted.
|
|
return if !$DeleteDefaultVersion;
|
|
|
|
# Delete default from the list.
|
|
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
|
SQL => 'DELETE FROM sysconfig_default WHERE id = ?',
|
|
Bind => [ \$DefaultID ],
|
|
);
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefault',
|
|
Key => 'DefaultSettingGet::' . $DefaultSetting{Name},
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefaultListGet',
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefaultList',
|
|
Key => 'DefaultSettingList',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigNavigation',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigEntities',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigIsDirty',
|
|
);
|
|
|
|
# Clean cache for setting translations.
|
|
my %Languages = %{ $Kernel::OM->Get('Kernel::Config')->Get('DefaultUsedLanguages') };
|
|
for my $Language ( sort keys %Languages ) {
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfig',
|
|
Key => "SettingTranslatedGet::$Language" . "::$DefaultSetting{Name}",
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfig',
|
|
Key => "ConfigurationTranslatedGet::$Language",
|
|
);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 DefaultSettingUpdate()
|
|
|
|
Update SysConfig default entry.
|
|
|
|
my $Success = $SysConfigDBObject->DefaultSettingUpdate(
|
|
DefaultID => 123,
|
|
Name => "ProductName",
|
|
Description => "Defines the name of the application ...",
|
|
Navigation => "ASimple::Path::Structure",
|
|
IsInvisible => 1, # 1 or 0, optional, default 0
|
|
IsReadonly => 0, # 1 or 0, optional, default 0
|
|
IsRequired => 1, # 1 or 0, optional, default 0
|
|
IsValid => 1, # 1 or 0, optional, default 0
|
|
HasConfigLevel => 200, # optional, default 0
|
|
UserModificationPossible => 0, # 1 or 0, optional, default 0
|
|
UserModificationActive => 0, # 1 or 0, optional, default 0
|
|
UserPreferencesGroup => 'Some Group',
|
|
UserPreferencesGroup => 'Advanced', # optional
|
|
XMLContentRaw => $XMLString, # the XML structure as it is on the config file
|
|
XMLContentParsed => $XMLParsedToPerl,
|
|
XMLFilename => 'Framework.xml',
|
|
ExclusiveLockGUID => 1,
|
|
EffectiveValue => $SettingEffectiveValue,
|
|
UserID => 1,
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Success = 1; # or false in case of an error.
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingUpdate {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Store params for further usage.
|
|
my %DefaultVersionParams = %Param;
|
|
|
|
for my $Key (
|
|
qw(
|
|
DefaultID Name Description Navigation XMLContentRaw XMLContentParsed XMLFilename
|
|
ExclusiveLockGUID EffectiveValue UserID
|
|
)
|
|
)
|
|
{
|
|
if ( !defined $Param{$Key} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Key!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
# Get default setting
|
|
my %DefaultSetting = $Self->DefaultSettingGet(
|
|
DefaultID => $Param{DefaultID},
|
|
);
|
|
|
|
# Check if setting exists.
|
|
return if !IsHashRefWithData( \%DefaultSetting );
|
|
|
|
# Don't allow name changes, due this is consider a NEW setting.
|
|
return if $DefaultSetting{Name} ne $Param{Name};
|
|
|
|
# Check if the setting is locked by the current user.
|
|
return if !$Self->DefaultSettingIsLockedByUser(
|
|
%Param,
|
|
ExclusiveLockUserID => $Param{UserID},
|
|
);
|
|
|
|
# Check config level, set 0 as default value.
|
|
$Param{HasConfigLevel} //= 0;
|
|
|
|
if ( !IsPositiveInteger( $Param{HasConfigLevel} ) && $Param{HasConfigLevel} ne '0' ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "HasConfigLevel must be an integer!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
# Check boolean parameters, set 0 as default value.
|
|
for my $Key (qw(IsInvisible IsReadonly IsRequired IsValid UserModificationPossible UserModificationActive)) {
|
|
$Param{$Key} = ( defined $Param{$Key} && $Param{$Key} ? 1 : 0 );
|
|
}
|
|
|
|
# Check if we really need to update.
|
|
my $IsDifferent = 0;
|
|
for my $Key (
|
|
qw(
|
|
DefaultID Description Navigation IsInvisible HasConfigLevel XMLContentRaw
|
|
XMLContentParsed XMLFilename ExclusiveLockGUID EffectiveValue HasConfigLevel IsInvisible
|
|
IsReadonly IsRequired IsValid UserModificationPossible UserModificationActive UserPreferencesGroup
|
|
)
|
|
)
|
|
{
|
|
my $DataIsDifferent = DataIsDifferent(
|
|
Data1 => $Param{$Key},
|
|
Data2 => $DefaultSetting{$Key},
|
|
);
|
|
if ($DataIsDifferent) {
|
|
$IsDifferent = 1;
|
|
}
|
|
}
|
|
|
|
return 1 if !$IsDifferent;
|
|
|
|
# Serialize data as string.
|
|
for my $Key (qw(XMLContentParsed EffectiveValue)) {
|
|
$Param{$Key} = $Kernel::OM->Get('Kernel::System::YAML')->Dump(
|
|
Data => $Param{$Key},
|
|
);
|
|
$DefaultVersionParams{$Key} = $Param{$Key};
|
|
}
|
|
|
|
# Set is dirty value.
|
|
$Param{IsDirty} = 1;
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Insert the default.
|
|
return if !$DBObject->Do(
|
|
SQL => '
|
|
UPDATE sysconfig_default
|
|
SET description = ?, navigation = ?, is_invisible = ?, is_readonly = ?,
|
|
is_required = ?, is_valid = ?, has_configlevel = ?, user_modification_possible = ?, user_modification_active = ?,
|
|
user_preferences_group = ?, xml_content_raw = ?, xml_content_parsed = ?, xml_filename =?, effective_value = ?,
|
|
is_dirty = ?, change_time = current_timestamp, change_by = ?
|
|
WHERE id = ?',
|
|
Bind => [
|
|
\$Param{Description}, \$Param{Navigation}, \$Param{IsInvisible}, \$Param{IsReadonly},
|
|
\$Param{IsRequired}, \$Param{IsValid}, \$Param{HasConfigLevel}, \$Param{UserModificationPossible},
|
|
\$Param{UserModificationActive}, \$Param{UserPreferencesGroup}, \$Param{XMLContentRaw},
|
|
\$Param{XMLContentParsed},
|
|
\$Param{XMLFilename}, \$Param{EffectiveValue}, \$Param{IsDirty}, \$Param{UserID}, \$Param{DefaultID},
|
|
],
|
|
);
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefault',
|
|
Key => 'DefaultSettingGet::' . $DefaultSetting{Name},
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefaultListGet',
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefaultList',
|
|
Key => 'DefaultSettingList',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigNavigation',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigEntities',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigIsDirty',
|
|
);
|
|
|
|
# Clean cache for setting translations.
|
|
my %Languages = %{ $Kernel::OM->Get('Kernel::Config')->Get('DefaultUsedLanguages') };
|
|
for my $Language ( sort keys %Languages ) {
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfig',
|
|
Key => "SettingTranslatedGet::$Language" . "::$DefaultSetting{Name}",
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfig',
|
|
Key => "ConfigurationTranslatedGet::$Language",
|
|
);
|
|
}
|
|
|
|
# Add default setting version.
|
|
my $DefaultVersionID = $Self->DefaultSettingVersionAdd(
|
|
DefaultID => $Param{DefaultID},
|
|
%DefaultVersionParams,
|
|
NoVersionID => 1,
|
|
);
|
|
|
|
# Return if not version inserted.
|
|
return if !$DefaultVersionID;
|
|
|
|
# Unlock setting
|
|
my $IsUnlock = $Self->DefaultSettingUnlock(
|
|
DefaultID => $Param{DefaultID},
|
|
);
|
|
if ( !$IsUnlock ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Default setting with ID: $Param{DefaultID} was not possible to unlock!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 DefaultSettingSearch()
|
|
|
|
Search for settings which contains given term(Search) in the xml_content_raw column.
|
|
|
|
my @Result = $SysConfigDBObject->DefaultSettingSearch(
|
|
Search => 'Entity', # Search term
|
|
SearchType => 'XMLContent', # XMLContent or Metadata
|
|
CategoryFiles => ['Framework.xml', 'Ticket.xml', ], # (optional)
|
|
Valid => 0, # (optional) By default, system returns all Settings (valid and invalid)
|
|
# if set to 1, search only for valid,
|
|
# if set to 0, search also for invalid.
|
|
IncludeInvisible => 0, # (optional) Default 0
|
|
);
|
|
|
|
or
|
|
|
|
my @Result = $SysConfigDBObject->DefaultSettingSearch(
|
|
Search => ['Framework.xml' 'Ticket,xml'],
|
|
SearchType => 'Filename',
|
|
Valid => 1,
|
|
);
|
|
|
|
Returns:
|
|
|
|
@Result = (
|
|
'ACL::CacheTTL',
|
|
'ACLKeysLevel1Change',
|
|
...
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingSearch {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{Search} && !$Param{CategoryFiles} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need Search or CategoryFiles!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
if ( $Param{CategoryFiles} && !IsArrayRefWithData( $Param{CategoryFiles} ) ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "CategoryFiles is invalid!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
$Param{SearchType} //= 'XMLContent';
|
|
$Param{IncludeInvisible} //= 0;
|
|
|
|
my $Valid = 0;
|
|
if ( defined $Param{Valid} ) {
|
|
$Valid = $Param{Valid} ? 1 : 0;
|
|
}
|
|
|
|
my @Bind = ();
|
|
|
|
my $SQL = '
|
|
SELECT name
|
|
FROM sysconfig_default
|
|
WHERE 1 = 1';
|
|
|
|
if ($Valid) {
|
|
$SQL .= '
|
|
AND is_valid = ?';
|
|
push @Bind, \$Valid;
|
|
}
|
|
|
|
if ( !$Param{IncludeInvisible} ) {
|
|
$SQL .= '
|
|
AND is_invisible = ?';
|
|
push @Bind, \0;
|
|
}
|
|
|
|
my $Column = 'xml_content_raw';
|
|
|
|
if ( lc $Param{SearchType} eq 'metadata' ) {
|
|
$Column = [qw(name description navigation)];
|
|
}
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
if ( $Param{Search} ) {
|
|
my %QueryCondition = $DBObject->QueryCondition(
|
|
Key => $Column,
|
|
Value => $Param{Search},
|
|
SearchPrefix => "*",
|
|
SearchSuffix => "*",
|
|
BindMode => 1,
|
|
);
|
|
|
|
$SQL .= ' AND ' . $QueryCondition{SQL};
|
|
push @Bind, @{ $QueryCondition{Values} };
|
|
}
|
|
|
|
if ( $Param{CategoryFiles} ) {
|
|
|
|
@{ $Param{CategoryFiles} } = map {"($_)"} @{ $Param{CategoryFiles} };
|
|
$Param{CategoryFiles} = join 'OR', @{ $Param{CategoryFiles} };
|
|
|
|
my %QueryCondition = $DBObject->QueryCondition(
|
|
Key => 'xml_filename',
|
|
Value => $Param{CategoryFiles},
|
|
SearchPrefix => "",
|
|
SearchSuffix => "",
|
|
BindMode => 1,
|
|
);
|
|
|
|
$SQL .= ' AND ( ' . $QueryCondition{SQL} . ' )';
|
|
push @Bind, @{ $QueryCondition{Values} };
|
|
|
|
}
|
|
|
|
$SQL .= '
|
|
ORDER BY name asc';
|
|
|
|
# db query
|
|
return if !$DBObject->Prepare(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
);
|
|
|
|
my @Result;
|
|
|
|
ROW:
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
push @Result, $Row[0];
|
|
}
|
|
|
|
return @Result;
|
|
}
|
|
|
|
=head2 DefaultSettingListGet()
|
|
|
|
Get default setting list with complete data.
|
|
|
|
my @List = $SysConfigDBObject->DefaultSettingListGet(
|
|
IsInvisible => 1, # 1 or 0
|
|
IsReadonly => 0, # 1 or 0
|
|
IsRequired => 1, # 1 or 0
|
|
IsValid => 1, # 1 or 0
|
|
IsDirty => 1, # 1 or 0
|
|
HasConfigLevel => 0, # 1 or 0
|
|
UserModificationPossible => 0, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
UserPreferencesGroup => 'Some Group',
|
|
Navigation => 'ASimple::Path::Structure',
|
|
Locked => 1, # check for locked settings
|
|
Category => 'OTRS', # optional (requires CategoryFiles)
|
|
CategoryFiles => ['Framework.xml', 'Ticket.xml', ], # optional (requires Category)
|
|
NoCache => 0, # (optional) Default 0. If set, system will not generate cache.
|
|
);
|
|
|
|
Returns:
|
|
|
|
@List = (
|
|
{
|
|
DefaultID => 123,
|
|
Name => "ProductName",
|
|
Description => "Defines the name of the application ...",
|
|
Navigation => "ASimple::Path::Structure",
|
|
IsInvisible => 1,
|
|
IsReadonly => 0,
|
|
IsRequired => 1,
|
|
IsValid => 1,
|
|
HasConfigLevel => 200,
|
|
UserModificationPossible => 0, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
UserPreferencesGroup => 'Advanced', # optional
|
|
XMLContentRaw => "The XML structure as it is on the config file",
|
|
XMLContentParsed => "XML parsed to Perl",
|
|
XMLFilename => "Framework.xml",
|
|
EffectiveValue => "Product 6",
|
|
IsDirty => 1, # 1 or 0
|
|
ExclusiveLockGUID => 'A32CHARACTERLONGSTRINGFORLOCKING',
|
|
ExclusiveLockUserID => 1,
|
|
ExclusiveLockExpiryTime => '2016-05-29 11:09:04',
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
CreateBy => 1,
|
|
ChangeTime => "2016-05-29 11:04:04",
|
|
ChangeBy => 1,
|
|
SettingUID => 'Default4717141789',
|
|
},
|
|
{
|
|
DefaultID => 321,
|
|
Name => 'FieldName',
|
|
# ...
|
|
ChangeTime => '2011-01-01 01:01:01',
|
|
ChangeBy => 1,
|
|
SettingUID => 'Default4717141781',
|
|
},
|
|
# ...
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingListGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( $Param{Category} ) {
|
|
if ( !IsArrayRefWithData( $Param{CategoryFiles} ) ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "CategoryFiles are invalid!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
if ( $Param{CategoryFiles} && !$Param{Category} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need Category!",
|
|
);
|
|
}
|
|
|
|
# Define SQL filters to be used in the queries.
|
|
my %FieldFilters = (
|
|
IsInvisible => 'is_invisible',
|
|
IsReadonly => 'is_readonly',
|
|
IsRequired => 'is_required',
|
|
IsValid => 'is_valid',
|
|
IsDirty => 'is_dirty',
|
|
HasConfigLevel => 'has_configlevel',
|
|
UserModificationPossible => 'user_modification_possible',
|
|
UserModificationActive => 'user_modification_active',
|
|
UserPreferencesGroup => 'user_preferences_group',
|
|
Navigation => 'navigation',
|
|
);
|
|
|
|
my @Filters;
|
|
my @Bind;
|
|
|
|
my $CacheType = 'SysConfigDefaultListGet';
|
|
my $CacheKey = 'DefaultSettingListGet'; # this cache key gets more elements
|
|
|
|
# Check params have a default value.
|
|
for my $Key ( sort keys %FieldFilters ) {
|
|
if ( defined $Param{$Key} ) {
|
|
push @Filters, " $FieldFilters{$Key} = ? ";
|
|
push @Bind, \$Param{$Key};
|
|
|
|
$CacheKey .= "::$FieldFilters{$Key} = $Param{$Key}";
|
|
}
|
|
}
|
|
|
|
# Check for locked settings.
|
|
if ( $Param{Locked} ) {
|
|
push @Filters, " exclusive_lock_guid != '0' ";
|
|
$CacheKey .= "::exclusive_lock_guid != '0'";
|
|
}
|
|
|
|
# Check for categories.
|
|
if ( $Param{Category} ) {
|
|
$CacheKey .= "::Category=$Param{Category}";
|
|
}
|
|
|
|
my $SQLFilter = '';
|
|
|
|
# Loop over filters and set them on SQL and cache key.
|
|
if ( IsArrayRefWithData( \@Filters ) ) {
|
|
$SQLFilter = ' WHERE ' . join ' AND ', @Filters;
|
|
}
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
if ( $Param{Category} ) {
|
|
@{ $Param{CategoryFiles} } = map {"($_)"} @{ $Param{CategoryFiles} };
|
|
$Param{CategoryFiles} = join 'OR', @{ $Param{CategoryFiles} };
|
|
|
|
my %QueryCondition = $DBObject->QueryCondition(
|
|
Key => 'xml_filename',
|
|
Value => $Param{CategoryFiles},
|
|
SearchPrefix => "",
|
|
SearchSuffix => "",
|
|
BindMode => 1,
|
|
);
|
|
|
|
if ($SQLFilter) {
|
|
$SQLFilter .= ' AND ( ' . $QueryCondition{SQL} . ' )';
|
|
}
|
|
else {
|
|
$SQLFilter = ' WHERE ' . $QueryCondition{SQL};
|
|
}
|
|
|
|
push @Bind, @{ $QueryCondition{Values} };
|
|
}
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return @{$Cache} if ref $Cache eq 'ARRAY';
|
|
|
|
my $SQL = '
|
|
SELECT id, name, description, navigation, is_invisible, is_readonly, is_required, is_valid, has_configlevel,
|
|
user_modification_possible, user_modification_active, user_preferences_group, xml_content_raw,
|
|
xml_content_parsed, xml_filename, effective_value, is_dirty, exclusive_lock_guid, exclusive_lock_user_id,
|
|
exclusive_lock_expiry_time, create_time, create_by, change_time, change_by
|
|
FROM sysconfig_default';
|
|
|
|
$SQLFilter //= '';
|
|
|
|
$SQL .= $SQLFilter . ' ORDER BY id';
|
|
|
|
return if !$DBObject->Prepare(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
);
|
|
|
|
my @Data;
|
|
my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML');
|
|
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
|
|
# De-serialize default data.
|
|
my $XMLContentParsed = $YAMLObject->Load( Data => $Row[13] );
|
|
my $EffectiveValue = $YAMLObject->Load( Data => $Row[15] );
|
|
|
|
my $TimeStamp = $Row[22];
|
|
$TimeStamp =~ s{:|-|[ ]}{}gmsx;
|
|
|
|
my %DefaultSetting = (
|
|
DefaultID => $Row[0],
|
|
Name => $Row[1],
|
|
Description => $Row[2],
|
|
Navigation => $Row[3],
|
|
IsInvisible => $Row[4],
|
|
IsReadonly => $Row[5],
|
|
IsRequired => $Row[6],
|
|
IsValid => $Row[7],
|
|
HasConfigLevel => $Row[8],
|
|
UserModificationPossible => $Row[9],
|
|
UserModificationActive => $Row[10],
|
|
UserPreferencesGroup => $Row[11] || '',
|
|
XMLContentRaw => $Row[12],
|
|
XMLContentParsed => $XMLContentParsed,
|
|
XMLFilename => $Row[14],
|
|
EffectiveValue => $EffectiveValue,
|
|
IsDirty => $Row[16] ? 1 : 0,
|
|
ExclusiveLockGUID => $Row[17],
|
|
ExclusiveLockUserID => $Row[18],
|
|
ExclusiveLockExpiryTime => $Row[19],
|
|
CreateTime => $Row[20],
|
|
CreateBy => $Row[21],
|
|
ChangeTime => $Row[22],
|
|
ChangeBy => $Row[23],
|
|
SettingUID => "Default$Row[0]$TimeStamp",
|
|
);
|
|
push @Data, \%DefaultSetting;
|
|
}
|
|
|
|
if ( !$Param{NoCache} ) {
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \@Data,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
}
|
|
|
|
return @Data;
|
|
}
|
|
|
|
=head2 DefaultSettingList()
|
|
|
|
Get list of all settings.
|
|
|
|
my @DefaultSettings = $SysConfigDBObject->DefaultSettingList(
|
|
IncludeInvisible => 0, # (optional) Include invisible. Default 0.
|
|
IsDirty => 0, # (optional) Filter settings by IsDirty. If not provided, returns all settings.
|
|
Locked => 0, # (optional) Filter locked settings.
|
|
);
|
|
|
|
Returns:
|
|
|
|
@DefaultSettings = (
|
|
{
|
|
DefaultID => '123',
|
|
Name => 'SettingName1',
|
|
IsDirty => 1,
|
|
IsVisible => 1,
|
|
ExclusiveLockGUID => 0,
|
|
XMLFilename => 'Filename.xml',
|
|
},
|
|
{
|
|
DefaultID => '124',
|
|
Name => 'SettingName2',
|
|
IsDirty => 0,
|
|
IsVisible => 1,
|
|
ExclusiveLockGUID => 'fjewifjowj...',
|
|
XMLFilename => 'Filename.xml',
|
|
},
|
|
...
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingList {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $CacheType = 'SysConfigDefaultList';
|
|
my $CacheKey = 'DefaultSettingList';
|
|
|
|
$Param{IncludeInvisible} //= 0;
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
my @DataRaw;
|
|
if ( ref $Cache eq 'ARRAY' ) {
|
|
@DataRaw = @{$Cache};
|
|
}
|
|
|
|
if ( !@DataRaw ) {
|
|
|
|
# Start SQL statement.
|
|
my $SQL = '
|
|
SELECT id, name, is_dirty, exclusive_lock_guid, xml_content_raw, xml_filename, is_invisible
|
|
FROM sysconfig_default
|
|
ORDER BY id';
|
|
|
|
return if !$DBObject->Prepare(
|
|
SQL => $SQL,
|
|
);
|
|
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
push @DataRaw, {
|
|
DefaultID => $Row[0],
|
|
Name => $Row[1],
|
|
IsDirty => $Row[2],
|
|
ExclusiveLockGUID => $Row[3],
|
|
XMLContentRaw => $Row[4],
|
|
XMLFilename => $Row[5],
|
|
IsInvisible => $Row[6],
|
|
};
|
|
}
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \@DataRaw,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
}
|
|
|
|
# Copy DataRaw to prevent modifications to in memory cache.
|
|
my @Data = @DataRaw;
|
|
|
|
# filter
|
|
if ( defined $Param{IsDirty} ) {
|
|
@Data = grep { $_->{IsDirty} == $Param{IsDirty} } @Data;
|
|
}
|
|
if ( defined $Param{Locked} ) {
|
|
if ( $Param{Locked} ) {
|
|
|
|
# Filter only locked settings
|
|
@Data = grep { $_->{ExclusiveLockGUID} } @Data;
|
|
}
|
|
else {
|
|
# Filter only unlocked settings
|
|
@Data = grep { !$_->{ExclusiveLockGUID} } @Data;
|
|
}
|
|
}
|
|
|
|
if ( !$Param{IncludeInvisible} ) {
|
|
|
|
# Filter only those settings that are visible.
|
|
@Data = grep { !$_->{IsInvisible} } @Data;
|
|
}
|
|
|
|
return @Data;
|
|
}
|
|
|
|
=head2 DefaultSettingLock()
|
|
|
|
Lock Default setting(s) to the particular user.
|
|
|
|
my $ExclusiveLockGUID = $SysConfigDBObject->DefaultSettingLock(
|
|
DefaultID => 1, # the ID of the setting that needs to be locked
|
|
# or
|
|
Name => 'SettingName', # the Name of the setting that needs to be locked
|
|
# or
|
|
LockAll => 1, # system locks all settings.
|
|
Force => 1, # (optional) Force locking (do not check if it's already locked by another user). Default: 0.
|
|
UserID => 1, # (required)
|
|
);
|
|
|
|
Returns:
|
|
|
|
$ExclusiveLockGUID = 'azzHab72wIlAXDrxHexsI5aENsESxAO7'; # Setting locked
|
|
|
|
or
|
|
|
|
$ExclusiveLockGUID = undef; # Not locked
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingLock {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{UserID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need UserID!",
|
|
);
|
|
return;
|
|
}
|
|
if ( !$Param{DefaultID} && !$Param{Name} && !$Param{LockAll} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need DefaultID, Name or LockAll!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# Check if a deployment is locked, in that case it's not possible to lock a setting.
|
|
my $DeploymentLocked = $Self->DeploymentIsLocked();
|
|
|
|
if ($DeploymentLocked) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "It's not possible to lock a setting if a deployment is currently locked.",
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $Locked;
|
|
|
|
if ( !$Param{LockAll} ) {
|
|
|
|
# Check if it's already locked (skip if force is used).
|
|
$Locked = $Self->DefaultSettingIsLocked(
|
|
DefaultID => $Param{DefaultID},
|
|
Name => $Param{Name},
|
|
);
|
|
}
|
|
|
|
return if ( !$Param{Force} && $Locked );
|
|
|
|
# Check if setting can be locked(IsReadonly).
|
|
my %DefaultSetting;
|
|
if ( !$Param{LockAll} ) {
|
|
|
|
%DefaultSetting = $Self->DefaultSettingGet(%Param);
|
|
if ( $DefaultSetting{IsReadonly} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "It's not possible to lock readonly setting $DefaultSetting{Name}"
|
|
. " (UserID=$Param{UserID}!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
# Check correct length for ExclusiveLockGUID if defined.
|
|
if ( defined $Param{ExclusiveLockGUID} && length( $Param{ExclusiveLockGUID} ) != 32 ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "The ExclusiveLockGUID is invalid!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# Setting is not locked, generate or use a locking string.
|
|
my $ExclusiveLockGUID = $Param{ExclusiveLockGUID} || $Kernel::OM->Get('Kernel::System::Main')->GenerateRandomString(
|
|
Length => 32,
|
|
);
|
|
|
|
my $SettingExpireTimeMinutes = 5;
|
|
|
|
# Get current time.
|
|
my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
|
|
$DateTimeObject->Add(
|
|
Minutes => $SettingExpireTimeMinutes,
|
|
);
|
|
|
|
my $SQL = '
|
|
UPDATE sysconfig_default
|
|
SET
|
|
exclusive_lock_guid = ?,
|
|
exclusive_lock_user_id = ?,
|
|
exclusive_lock_expiry_time = ?
|
|
';
|
|
my $ExpiryTime = $DateTimeObject->ToString();
|
|
my @Bind = (
|
|
\$ExclusiveLockGUID, \$Param{UserID},
|
|
\$ExpiryTime,
|
|
);
|
|
|
|
if ( $Param{DefaultID} ) {
|
|
$SQL .= '
|
|
WHERE id = ?';
|
|
push @Bind, \$Param{DefaultID};
|
|
}
|
|
elsif ( $Param{Name} ) {
|
|
$SQL .= '
|
|
WHERE name = ?';
|
|
push @Bind, \$Param{Name};
|
|
}
|
|
|
|
# Add locking data to the setting record
|
|
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
);
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Check if there was cache for this type/key pair.
|
|
my $DefaultSettingListGet = $CacheObject->Get(
|
|
Type => 'SysConfigDefaultListGet',
|
|
Key => 'DefaultSettingListGet',
|
|
);
|
|
|
|
if ( $Param{LockAll} ) {
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefault',
|
|
);
|
|
}
|
|
else {
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefault',
|
|
Key => 'DefaultSettingGet::' . $DefaultSetting{Name},
|
|
);
|
|
}
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefaultListGet',
|
|
);
|
|
|
|
# Warm up the cache.
|
|
if ($DefaultSettingListGet) {
|
|
|
|
# Warm up existing cache.
|
|
|
|
if (%DefaultSetting) {
|
|
|
|
# Update one setting.
|
|
|
|
my $Index;
|
|
|
|
# Determine index of the element.
|
|
LOOPINDEX:
|
|
for my $LoopIndex ( 0 .. scalar @{$DefaultSettingListGet} - 1 ) {
|
|
next LOOPINDEX if $DefaultSettingListGet->[$LoopIndex]->{DefaultID} ne $DefaultSetting{DefaultID};
|
|
|
|
$Index = $LoopIndex;
|
|
last LOOPINDEX;
|
|
}
|
|
|
|
# Update value.
|
|
$DefaultSettingListGet->[$Index] = {
|
|
%{ $DefaultSettingListGet->[$Index] },
|
|
ExclusiveLockExpiryTime => $ExpiryTime,
|
|
ExclusiveLockGUID => $ExclusiveLockGUID,
|
|
ExclusiveLockUserID => $Param{UserID},
|
|
};
|
|
}
|
|
else {
|
|
# Update all settings.
|
|
for my $Index ( 0 .. scalar @{$DefaultSettingListGet} - 1 ) {
|
|
$DefaultSettingListGet->[$Index] = {
|
|
%{ $DefaultSettingListGet->[$Index] },
|
|
ExclusiveLockExpiryTime => $ExpiryTime,
|
|
ExclusiveLockGUID => $ExclusiveLockGUID,
|
|
ExclusiveLockUserID => $Param{UserID},
|
|
};
|
|
}
|
|
}
|
|
|
|
# Set new cache value.
|
|
$CacheObject->Set(
|
|
Type => 'SysConfigDefaultListGet',
|
|
Key => 'DefaultSettingListGet',
|
|
Value => $DefaultSettingListGet,
|
|
TTL => $Self->{CacheTTL},
|
|
CacheInBackend => 0,
|
|
);
|
|
}
|
|
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefaultList',
|
|
Key => 'DefaultSettingList',
|
|
);
|
|
|
|
return $ExclusiveLockGUID;
|
|
}
|
|
|
|
=head2 DefaultSettingIsLocked()
|
|
|
|
Check if particular Default Setting is locked.
|
|
|
|
my $Locked = $SysConfigDBObject->DefaultSettingIsLocked(
|
|
DefaultID => 1, # the ID of the setting that needs to be checked
|
|
# or
|
|
Name => 'SettingName', # the Name of the setting that needs to be checked
|
|
GetLockUserID => 1, # optional, it will return the ExclusiveLockUserID in case it exist
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Locked = 1; # Locked
|
|
or
|
|
$Locked = 123 # The UserID
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingIsLocked {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DefaultID} && !$Param{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need DefaultID or Name!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
my %DefaultSetting = $Self->DefaultSettingGet(
|
|
DefaultID => $Param{DefaultID},
|
|
Name => $Param{Name},
|
|
);
|
|
|
|
# The setting is not available, user can't update it anyways
|
|
return 0 if !%DefaultSetting;
|
|
|
|
# Check if it's locked.
|
|
return 0 if !$DefaultSetting{ExclusiveLockExpiryTime};
|
|
|
|
my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
|
|
|
|
# Setting was locked, check if lock has expired.
|
|
my $LockedDateTimeObject = $Kernel::OM->Create(
|
|
'Kernel::System::DateTime',
|
|
ObjectParams => {
|
|
String => $DefaultSetting{ExclusiveLockExpiryTime},
|
|
},
|
|
);
|
|
|
|
my $Locked = $LockedDateTimeObject > $DateTimeObject ? 1 : 0;
|
|
|
|
# Remove locking if lock time is expired.
|
|
if ( !$Locked ) {
|
|
$Self->DefaultSettingUnlock( DefaultID => $Param{DefaultID} );
|
|
}
|
|
|
|
# Check if retrieve the ExclusiveLockUserID is needed
|
|
elsif ( $Param{GetLockUserID} ) {
|
|
$Locked = $DefaultSetting{ExclusiveLockUserID};
|
|
}
|
|
|
|
return $Locked;
|
|
}
|
|
|
|
=head2 DefaultSettingIsLockedByUser()
|
|
|
|
Check if particular Default Setting is locked.
|
|
|
|
my $LockedByUser = $SysConfigDBObject->DefaultSettingIsLockedByUser(
|
|
DefaultID => 1, # the ID of the setting that needs to be checked
|
|
# or
|
|
Name => 'SettingName', # the name of the setting that needs to be checked
|
|
ExclusiveLockUserID => 2, # the user should have locked the setting
|
|
ExclusiveLockGUID => 'AGUIDSTRING', # the GUID used to locking the setting
|
|
);
|
|
|
|
Returns:
|
|
|
|
$LockedByUser = 1;
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingIsLockedByUser {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
for my $Needed (qw(ExclusiveLockUserID ExclusiveLockGUID)) {
|
|
if ( !$Param{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
if ( !$Param{DefaultID} && !$Param{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need DefaultID or Name!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
return if !IsStringWithData( $Param{ExclusiveLockGUID} );
|
|
|
|
# Get default setting.
|
|
my %DefaultSetting = $Self->DefaultSettingGet(
|
|
DefaultID => $Param{DefaultID},
|
|
Name => $Param{Name},
|
|
);
|
|
|
|
# Check if setting exists.
|
|
return if !IsHashRefWithData( \%DefaultSetting );
|
|
|
|
# Check ExclusiveLockUserID
|
|
return if !$DefaultSetting{ExclusiveLockUserID};
|
|
return if $DefaultSetting{ExclusiveLockUserID} ne $Param{ExclusiveLockUserID};
|
|
|
|
# Check ExclusiveLockGUID.
|
|
return if !$DefaultSetting{ExclusiveLockGUID};
|
|
return if $DefaultSetting{ExclusiveLockGUID} ne $Param{ExclusiveLockGUID};
|
|
|
|
my $ExclusiveLockGUID = $DefaultSetting{ExclusiveLockGUID};
|
|
|
|
# Setting was locked, check if lock has expired.
|
|
my $CurrentDateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
|
|
|
|
my $LockedDateTimeObject = $Kernel::OM->Create(
|
|
'Kernel::System::DateTime',
|
|
ObjectParams => {
|
|
String => $DefaultSetting{ExclusiveLockExpiryTime},
|
|
},
|
|
);
|
|
|
|
my $Locked = $LockedDateTimeObject > $CurrentDateTimeObject ? 1 : 0;
|
|
|
|
# Extend locking time if the settings was already locked for this user but the time was expired.
|
|
if ( !$Locked ) {
|
|
|
|
$ExclusiveLockGUID = $Self->DefaultSettingLock(
|
|
UserID => $Param{ExclusiveLockUserID},
|
|
DefaultID => $Param{DefaultID},
|
|
Name => $Param{Name},
|
|
ExclusiveLockGUID => $Param{ExclusiveLockGUID},
|
|
);
|
|
}
|
|
|
|
return 1 if $ExclusiveLockGUID;
|
|
return;
|
|
}
|
|
|
|
=head2 DefaultSettingUnlock()
|
|
|
|
Unlock particular or all Default Setting(s).
|
|
|
|
my $Success = $SysConfigDBObject->DefaultSettingUnlock(
|
|
DefaultID => 1, # the ID of the setting that needs to be unlocked
|
|
# or
|
|
Name => 'SettingName', # the name of the setting that needs to be locked
|
|
# or
|
|
UnlockAll => 1, # unlock all settings
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Success = 1;
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingUnlock {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DefaultID} && !$Param{Name} && !$Param{UnlockAll} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need DefaultID, Name or UnlockAll!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
my @SettingsLocked;
|
|
|
|
my %DefaultSetting;
|
|
if ( $Param{UnlockAll} ) {
|
|
|
|
# Get locked settings only.
|
|
@SettingsLocked = $Self->DefaultSettingList(
|
|
Locked => 1,
|
|
);
|
|
|
|
# all settings are unlocked already
|
|
return 1 if !@SettingsLocked;
|
|
}
|
|
else {
|
|
%DefaultSetting = $Self->DefaultSettingGet(
|
|
%Param,
|
|
NoCache => 1,
|
|
);
|
|
return if !%DefaultSetting;
|
|
|
|
push @SettingsLocked, \%DefaultSetting;
|
|
}
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
my $SQL = '
|
|
UPDATE sysconfig_default
|
|
SET
|
|
exclusive_lock_guid = ?,
|
|
exclusive_lock_user_id = ?,
|
|
exclusive_lock_expiry_time = ?
|
|
WHERE
|
|
';
|
|
|
|
my @Bind = ( \0, \undef, \undef );
|
|
if ( $Param{DefaultID} ) {
|
|
$SQL .= '
|
|
id = ?';
|
|
push @Bind, \$Param{DefaultID};
|
|
}
|
|
elsif ( $Param{Name} ) {
|
|
$SQL .= '
|
|
name = ?';
|
|
push @Bind, \$Param{Name};
|
|
}
|
|
else {
|
|
# UnlockAll
|
|
|
|
$SQL .= '
|
|
exclusive_lock_guid != ? ';
|
|
push @Bind, \0;
|
|
}
|
|
|
|
# Remove locking from setting record.
|
|
return if !$DBObject->Do(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
);
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Check if there was cache for this type/key pair.
|
|
my $DefaultSettingListGet = $CacheObject->Get(
|
|
Type => 'SysConfigDefaultListGet',
|
|
Key => 'DefaultSettingListGet',
|
|
);
|
|
|
|
for my $Setting (@SettingsLocked) {
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefault',
|
|
Key => 'DefaultSettingGet::' . $Setting->{Name},
|
|
);
|
|
}
|
|
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefaultListGet',
|
|
);
|
|
|
|
# Warm up the cache.
|
|
if ($DefaultSettingListGet) {
|
|
|
|
# Warm up existing cache.
|
|
|
|
if (%DefaultSetting) {
|
|
|
|
# Update one setting.
|
|
|
|
my $Index;
|
|
|
|
# Determine index of the element.
|
|
LOOPINDEX:
|
|
for my $LoopIndex ( 0 .. scalar @{$DefaultSettingListGet} - 1 ) {
|
|
next LOOPINDEX if $DefaultSettingListGet->[$LoopIndex]->{DefaultID} ne $DefaultSetting{DefaultID};
|
|
|
|
$Index = $LoopIndex;
|
|
last LOOPINDEX;
|
|
}
|
|
|
|
# Update value.
|
|
$DefaultSettingListGet->[$Index] = {
|
|
%{ $DefaultSettingListGet->[$Index] },
|
|
ExclusiveLockExpiryTime => undef,
|
|
ExclusiveLockGUID => 0,
|
|
ExclusiveLockUserID => undef,
|
|
};
|
|
}
|
|
else {
|
|
# Update all settings.
|
|
for my $Index ( 0 .. scalar @{$DefaultSettingListGet} - 1 ) {
|
|
$DefaultSettingListGet->[$Index] = {
|
|
%{ $DefaultSettingListGet->[$Index] },
|
|
ExclusiveLockExpiryTime => undef,
|
|
ExclusiveLockGUID => 0,
|
|
ExclusiveLockUserID => undef,
|
|
};
|
|
}
|
|
}
|
|
|
|
# Set new cache value.
|
|
$CacheObject->Set(
|
|
Type => 'SysConfigDefaultListGet',
|
|
Key => 'DefaultSettingListGet',
|
|
Value => $DefaultSettingListGet,
|
|
TTL => $Self->{CacheTTL},
|
|
CacheInBackend => 0,
|
|
);
|
|
}
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefaultList',
|
|
Key => 'DefaultSettingList',
|
|
);
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 DefaultSettingDirtyCleanUp()
|
|
|
|
Removes the IsDirty flag from default settings.
|
|
|
|
my $Success = $SysConfigDBObject->DefaultSettingDirtyCleanUp(
|
|
AllSettings => 0, # (default 0) Reset all dirty settings.
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Success = 1; # or false in case of an error
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingDirtyCleanUp {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my @DirtySettings;
|
|
if ( !$Param{AllSettings} ) {
|
|
@DirtySettings = $Self->DefaultSettingList(
|
|
IsDirty => 1,
|
|
);
|
|
}
|
|
|
|
# Remove is dirty flag for default settings.
|
|
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
|
SQL => '
|
|
UPDATE sysconfig_default
|
|
SET is_dirty = 0
|
|
WHERE is_dirty = 1',
|
|
);
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Check if there was cache for this type/key pair.
|
|
my $DefaultSettingListGet = $CacheObject->Get(
|
|
Type => 'SysConfigDefaultListGet',
|
|
Key => 'DefaultSettingListGet',
|
|
);
|
|
|
|
if ( $Param{AllSettings} ) {
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefault',
|
|
);
|
|
}
|
|
else {
|
|
for my $Setting (@DirtySettings) {
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefault',
|
|
Key => 'DefaultSettingGet::' . $Setting->{Name},
|
|
);
|
|
}
|
|
}
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefaultListGet',
|
|
);
|
|
|
|
# Warm up the cache.
|
|
if ($DefaultSettingListGet) {
|
|
|
|
# Warm up existing cache.
|
|
|
|
# Update all settings.
|
|
for my $Index ( 0 .. scalar @{$DefaultSettingListGet} - 1 ) {
|
|
$DefaultSettingListGet->[$Index]->{IsDirty} = 0;
|
|
}
|
|
|
|
# Set new cache value.
|
|
$CacheObject->Set(
|
|
Type => 'SysConfigDefaultListGet',
|
|
Key => 'DefaultSettingListGet',
|
|
Value => $DefaultSettingListGet,
|
|
TTL => $Self->{CacheTTL},
|
|
CacheInBackend => 0,
|
|
);
|
|
}
|
|
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigDefaultList',
|
|
Key => 'DefaultSettingList',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigIsDirty',
|
|
);
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 DefaultSettingVersionAdd()
|
|
|
|
Add a new SysConfig default version entry.
|
|
|
|
my $DefaultVersionID = $SysConfigDBObject->DefaultSettingVersionAdd(
|
|
DefaultID => 456,
|
|
Name => "ProductName",
|
|
Description => "Defines the name of the application ...",
|
|
Navigation => "ASimple::Path::Structure",
|
|
IsInvisible => 1, # 1 or 0, optional, default 0
|
|
IsReadonly => 0, # 1 or 0, optional, default 0
|
|
IsRequired => 1, # 1 or 0, optional, default 0
|
|
IsValid => 1, # 1 or 0, optional, default 0
|
|
HasConfigLevel => 200, # optional, default 0
|
|
UserModificationPossible => 0, # 1 or 0, optional, default 0
|
|
UserModificationActive => 0, # 1 or 0, optional, default 0
|
|
UserPreferencesGroup => 'Advanced', # optional
|
|
XMLContentRaw => $XMLString, # the XML structure as it is on the config file
|
|
XMLContentParsed => $XMLParsedToPerl, # the setting XML structure converted into YAML
|
|
XMLFilename => 'Framework.xml' # the name of the XML file
|
|
EffectiveValue => $YAMLEffectiveValue, # YAML EffectiveValue
|
|
UserID => 1,
|
|
NoCleanup => 0, # (optional) Default 0. If enabled, system WILL NOT DELETE CACHE. In this case, it must be done manually.
|
|
# USE IT CAREFULLY.
|
|
NoVersionID => 1, # 1 or 0, optional, default 0, prevents the return of DefaultVersionID and returns only 1 in case of success.
|
|
);
|
|
|
|
Returns:
|
|
|
|
my $DefaultVersionID = 123; # false in case of an error
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingVersionAdd {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
for my $Key (
|
|
qw(DefaultID Name Description Navigation XMLContentRaw XMLContentParsed XMLFilename EffectiveValue UserID)
|
|
)
|
|
{
|
|
if ( !defined $Param{$Key} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Key!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
# Check config level.
|
|
$Param{HasConfigLevel} //= 0;
|
|
|
|
if ( !IsPositiveInteger( $Param{HasConfigLevel} ) && $Param{HasConfigLevel} ne '0' ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "HasConfigLevel must be an integer!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
# Check boolean parameters, set 0 as default value.
|
|
for my $Key (qw(IsInvisible IsReadonly IsRequired IsValid UserModificationPossible UserModificationActive)) {
|
|
$Param{$Key} = ( defined $Param{$Key} && $Param{$Key} ? 1 : 0 );
|
|
}
|
|
if ( $Param{EffectiveValue} eq "/usr/bin/gpg/mod" ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need!"
|
|
);
|
|
}
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Insert the default.
|
|
return if !$DBObject->Do(
|
|
SQL => '
|
|
INSERT INTO sysconfig_default_version
|
|
(sysconfig_default_id, name, description, navigation, is_invisible, is_readonly, is_required, is_valid,
|
|
has_configlevel, user_modification_possible, user_modification_active, user_preferences_group,
|
|
xml_content_raw, xml_content_parsed, xml_filename, effective_value, create_time, create_by,
|
|
change_time, change_by)
|
|
VALUES
|
|
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)',
|
|
Bind => [
|
|
\$Param{DefaultID}, \$Param{Name}, \$Param{Description}, \$Param{Navigation},
|
|
\$Param{IsInvisible}, \$Param{IsReadonly}, \$Param{IsRequired}, \$Param{IsValid}, \$Param{HasConfigLevel},
|
|
\$Param{UserModificationPossible}, \$Param{UserModificationActive}, \$Param{UserPreferencesGroup},
|
|
\$Param{XMLContentRaw}, \$Param{XMLContentParsed}, \$Param{XMLFilename}, \$Param{EffectiveValue},
|
|
\$Param{UserID}, \$Param{UserID},
|
|
],
|
|
);
|
|
|
|
# Get default version ID.
|
|
$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT id
|
|
FROM sysconfig_default_version
|
|
WHERE sysconfig_default_id = ? AND name = ?
|
|
ORDER BY id DESC
|
|
',
|
|
Bind => [ \$Param{DefaultID}, \$Param{Name} ],
|
|
Limit => 1,
|
|
);
|
|
|
|
# Fetch the default setting ID
|
|
my $DefaultVersionID;
|
|
|
|
if ( $Param{NoVersionID} ) {
|
|
$DefaultVersionID = 1;
|
|
}
|
|
else {
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
$DefaultVersionID = $Row[0];
|
|
}
|
|
}
|
|
if ( !$Param{NoCleanup} ) {
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefaultVersion',
|
|
);
|
|
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigDefaultVersionList',
|
|
);
|
|
}
|
|
|
|
return $DefaultVersionID;
|
|
}
|
|
|
|
=head2 DefaultSettingVersionGet()
|
|
|
|
Get SysConfig default version entry.
|
|
|
|
my %DefaultSettingVersion = $SysConfigDBObject->DefaultSettingVersionGet(
|
|
DefaultVersionID => 123,
|
|
);
|
|
|
|
Returns:
|
|
|
|
%DefaultSettingVersion = (
|
|
DefaultVersionID => 123,
|
|
DefaultID => 456,
|
|
Name => "ProductName",
|
|
Description => "Defines the name of the application ...",
|
|
Navigation => "ASimple::Path::Structure",
|
|
IsInvisible => 1, # 1 or 0
|
|
IsReadonly => 0, # 1 or 0
|
|
IsRequired => 1, # 1 or 0
|
|
IsValid => 1, # 1 or 0
|
|
HasConfigLevel => 200,
|
|
UserModificationPossible => 0, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
UsePreferencesGroup => 'Advanced', # optional
|
|
XMLContentRaw => "The XML structure as it is on the config file",
|
|
XMLContentParsed => "XML parsed to Perl",
|
|
XMLFilename => 'Framework.xml',
|
|
EffectiveValue => "Product 6",
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
CreateBy => 44,
|
|
ChangeTime => "2016-05-29 11:04:04",
|
|
ChangeBy => 88,
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingVersionGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DefaultVersionID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need DefaultVersionID!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $FieldName;
|
|
my $FieldValue;
|
|
|
|
if ( $Param{DefaultVersionID} ) {
|
|
|
|
# Set DefaultID as filter.
|
|
$FieldName = 'id';
|
|
$FieldValue = $Param{DefaultVersionID};
|
|
}
|
|
elsif ( $Param{Name} ) {
|
|
|
|
# Set Name as filter
|
|
$FieldName = 'name';
|
|
$FieldValue = $Param{Name};
|
|
}
|
|
|
|
my $CacheType = "SysConfigDefaultVersion";
|
|
my $CacheKey = 'DefaultSettingVersionGet::' . $FieldName . '::' . $FieldValue;
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return %{$Cache} if ref $Cache eq 'HASH';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Get default from database.
|
|
return if !$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT id, sysconfig_default_id, name, description, navigation, is_invisible, is_readonly, is_required,
|
|
is_valid, has_configlevel, user_modification_possible, user_modification_active, user_preferences_group,
|
|
xml_content_raw, xml_content_parsed, xml_filename, effective_value, create_time, create_by,
|
|
change_time, change_by
|
|
FROM sysconfig_default_version
|
|
WHERE ' . $FieldName . ' = ?',
|
|
Bind => [ \$FieldValue ],
|
|
);
|
|
|
|
my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML');
|
|
|
|
my %DefaultSettingVersion;
|
|
while ( my @Data = $DBObject->FetchrowArray() ) {
|
|
|
|
# De-serialize default data.
|
|
my $XMLContentParsed = $YAMLObject->Load( Data => $Data[14] );
|
|
my $EffectiveValue = $YAMLObject->Load( Data => $Data[16] );
|
|
|
|
%DefaultSettingVersion = (
|
|
DefaultVersionID => $Data[0],
|
|
DefaultID => $Data[1],
|
|
Name => $Data[2],
|
|
Description => $Data[3],
|
|
Navigation => $Data[4],
|
|
IsInvisible => $Data[5],
|
|
IsReadonly => $Data[6],
|
|
IsRequired => $Data[7],
|
|
IsValid => $Data[8],
|
|
HasConfigLevel => $Data[9],
|
|
UserModificationPossible => $Data[10],
|
|
UserModificationActive => $Data[11],
|
|
UserPreferencesGroup => $Data[12] || '',
|
|
XMLContentRaw => $Data[13],
|
|
XMLContentParsed => $XMLContentParsed,
|
|
XMLFilename => $Data[15],
|
|
EffectiveValue => $EffectiveValue,
|
|
CreateTime => $Data[17],
|
|
CreateBy => $Data[18],
|
|
ChangeTime => $Data[19],
|
|
ChangeBy => $Data[20],
|
|
);
|
|
}
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \%DefaultSettingVersion,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return %DefaultSettingVersion;
|
|
}
|
|
|
|
=head2 DefaultSettingVersionDelete()
|
|
|
|
Delete a default setting version from list based on default version ID or default ID.
|
|
|
|
my $Success = $SysConfigDBObject->DefaultSettingVersionDelete(
|
|
DefaultVersionID => 123,
|
|
);
|
|
|
|
or
|
|
|
|
my $Success = $SysConfigDBObject->DefaultSettingVersionDelete(
|
|
DefaultID => 45,
|
|
);
|
|
|
|
or
|
|
|
|
my $Success = $SysConfigDBObject->DefaultSettingVersionDelete(
|
|
Name => 'AnyName',
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Success = 1; # or false in case of an error
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingVersionDelete {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DefaultVersionID} && !$Param{DefaultID} && !$Param{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need ID, DefaultID or Name!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $FieldName;
|
|
my $FieldValue;
|
|
|
|
if ( $Param{DefaultVersionID} ) {
|
|
|
|
# Set conditions for id.
|
|
$FieldName = 'id';
|
|
$FieldValue = $Param{DefaultVersionID};
|
|
}
|
|
elsif ( $Param{DefaultID} ) {
|
|
|
|
# Set conditions for default id.
|
|
$FieldName = 'sysconfig_default_id';
|
|
$FieldValue = $Param{DefaultID};
|
|
}
|
|
elsif ( $Param{Name} ) {
|
|
|
|
# Set conditions for name.
|
|
$FieldName = 'name';
|
|
$FieldValue = $Param{Name};
|
|
|
|
}
|
|
|
|
# Delete default from the list.
|
|
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
|
SQL => 'DELETE FROM sysconfig_default_version WHERE ' . $FieldName . ' = ?',
|
|
Bind => [ \$FieldValue ],
|
|
);
|
|
|
|
if ( !$Param{DefaultVersionID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Cache')->CleanUp(
|
|
Type => 'SysConfigDefaultVersion',
|
|
);
|
|
}
|
|
else {
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigDefaultVersion',
|
|
Key => 'DefaultSettingVersionGet::id::' . $Param{DefaultVersionID},
|
|
);
|
|
}
|
|
|
|
$Kernel::OM->Get('Kernel::System::Cache')->CleanUp(
|
|
Type => 'SysConfigDefaultVersionList',
|
|
);
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 DefaultSettingVersionGetLast()
|
|
|
|
Get last deployment.
|
|
|
|
my %DefaultSettingVersionGetLast = $SysConfigDBObject->DefaultSettingVersionGetLast(
|
|
DefaultID => 456,
|
|
);
|
|
|
|
Returns:
|
|
|
|
|
|
%DefaultSettingVersion = (
|
|
DefaultVersionID => 123,
|
|
DefaultID => 456,
|
|
Name => "ProductName",
|
|
Description => "Defines the name of the application ...",
|
|
Navigation => "ASimple::Path::Structure",
|
|
IsInvisible => 1, # 1 or 0
|
|
IsReadonly => 0, # 1 or 0
|
|
IsRequired => 1, # 1 or 0
|
|
IsValid => 1, # 1 or 0
|
|
HasConfigLevel => 200,
|
|
UserModificationPossible => 0, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
UsePreferencesGroup => 'Advanced', # optional
|
|
XMLContentRaw => "The XML structure as it is on the config file",
|
|
XMLContentParsed => "XML parsed to Perl",
|
|
XMLFilename => 'Framework.xml',
|
|
EffectiveValue => "Product 6",
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
ChangeTime => "2016-05-29 11:04:04",
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingVersionGetLast {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DefaultID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need DefaultID!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $CacheType = 'SysConfigDefaultVersion';
|
|
my $CacheKey = 'DefaultSettingVersionGetLast::' . $Param{DefaultID};
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return %{$Cache} if ref $Cache eq 'HASH';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
return if !$DBObject->Prepare(
|
|
SQL => 'SELECT MAX(id) FROM sysconfig_default_version WHERE sysconfig_default_id = ?',
|
|
Bind => [ \$Param{DefaultID} ],
|
|
);
|
|
|
|
my $DefaultVersionID;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
$DefaultVersionID = $Row[0];
|
|
}
|
|
|
|
return if !$DefaultVersionID;
|
|
|
|
my %DefaultSettingVersion = $Self->DefaultSettingVersionGet(
|
|
DefaultVersionID => $DefaultVersionID,
|
|
);
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \%DefaultSettingVersion,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return %DefaultSettingVersion;
|
|
}
|
|
|
|
=head2 DefaultSettingVersionListGet()
|
|
|
|
Get version setting list with complete data.
|
|
|
|
my @List = $SysConfigDBObject->DefaultSettingVersionListGet(
|
|
Name => 'SettingName', # optional
|
|
# or
|
|
DefaultID => 123, # optional
|
|
);
|
|
|
|
Returns:
|
|
|
|
@List = (
|
|
{
|
|
DefaultVersionID => 123,
|
|
DefaultID => 456,
|
|
Name => "ProductName",
|
|
Description => "Defines the name of the application ...",
|
|
Navigation => "ASimple::Path::Structure",
|
|
IsInvisible => 1, # 1 or 0
|
|
IsReadonly => 0, # 1 or 0
|
|
IsRequired => 1, # 1 or 0
|
|
IsValid => 1, # 1 or 0
|
|
HasConfigLevel => 200,
|
|
UserModificationPossible => 0, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
UserPreferencesGroup => 'Advanced', # optional
|
|
XMLContentRaw => "The XML structure as it is on the config file",
|
|
XMLContentParsed => "XML parsed to Perl",
|
|
XMLFilename => 'Framework.xml',
|
|
EffectiveValue => "Product 6",
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
ChangeTime => "2016-05-29 11:04:04",
|
|
},
|
|
{
|
|
DefaultVersionID => 321,
|
|
DefaultID => 890,
|
|
Name => 'FieldName',
|
|
# ...
|
|
CreateTime => '2010-09-11 10:08:00',
|
|
ChangeTime => '2011-01-01 01:01:01',
|
|
},
|
|
# ...
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DefaultSettingVersionListGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DefaultID} && !$Param{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need DefaultID or Name!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $FieldName;
|
|
my $FieldValue;
|
|
my $FieldCache;
|
|
|
|
if ( $Param{DefaultID} ) {
|
|
|
|
# Set conditions for default id.
|
|
$FieldName = 'sysconfig_default_id';
|
|
$FieldValue = $Param{DefaultID};
|
|
$FieldCache = "DefaultID::$Param{DefaultID}";
|
|
}
|
|
elsif ( $Param{Name} ) {
|
|
|
|
# Set conditions for name.
|
|
$FieldName = 'name';
|
|
$FieldValue = $Param{Name};
|
|
$FieldCache = "Name::$Param{Name}";
|
|
}
|
|
|
|
# Set filters on SQL and cache key.
|
|
my $SQLFilter = "WHERE $FieldName = '$FieldValue' ";
|
|
|
|
my $CacheType = 'SysConfigDefaultVersionList';
|
|
my $CacheKey = 'DefaultSettingVersionList::' . $FieldCache;
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return @{$Cache} if ref $Cache eq 'ARRAY';
|
|
|
|
# Start SQL statement.
|
|
my $SQL = 'SELECT id, name FROM sysconfig_default_version ' . $SQLFilter . ' ORDER BY id DESC';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
my @Data;
|
|
return if !$DBObject->Prepare( SQL => $SQL );
|
|
|
|
my @DefaultVersionIDs;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
push @DefaultVersionIDs, $Row[0];
|
|
}
|
|
|
|
# Get default settings.
|
|
for my $ItemID (@DefaultVersionIDs) {
|
|
|
|
my %DefaultSetting = $Self->DefaultSettingVersionGet(
|
|
DefaultVersionID => $ItemID,
|
|
);
|
|
push @Data, \%DefaultSetting;
|
|
}
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \@Data,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return @Data;
|
|
}
|
|
|
|
=head2 ModifiedSettingAdd()
|
|
|
|
Add a new SysConfig modified entry.
|
|
|
|
my $ModifiedID = $SysConfigDBObject->ModifiedSettingAdd(
|
|
DefaultID => 456,
|
|
Name => "ProductName",
|
|
IsValid => 1, # 1 or 0, optional (uses the value from DefaultSetting if not defined)
|
|
UserModificationPossible => 0, # 1 or 0, optional (uses the value from DefaultSetting if not defined)
|
|
UserModificationActive => 0, # 1 or 0, optional (uses the value from DefaultSetting if not defined)
|
|
ResetToDefault => 0, # 1 or 0, optional, modified 0
|
|
EffectiveValue => $SettingEffectiveValue,
|
|
TargetUserID => 2, # Optional, ID of the user for which the modified setting is meant,
|
|
# leave it undef for global changes.
|
|
ExclusiveLockGUID => $LockingString, # the GUID used to lock the setting
|
|
DeploymentExclusiveLockGUID => $LockingString, # the GUID used to lock the deployment (in case of deployment failure)
|
|
UserID => 1,
|
|
);
|
|
|
|
Returns:
|
|
|
|
my $ModifiedID = 123; # false in case of an error
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingAdd {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Store params for further usage.
|
|
my %ModifiedVersionParams = %Param;
|
|
|
|
for my $Key (qw(DefaultID Name UserID)) {
|
|
if ( !defined $Param{$Key} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Key!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !$Param{TargetUserID} && !$Param{ExclusiveLockGUID} && !$Param{DeploymentExclusiveLockGUID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need ExclusiveLockGUID or DeploymentExclusiveLockGUID!",
|
|
);
|
|
}
|
|
|
|
# Check duplicate name (with same TargetUserID).
|
|
my %ModifiedSetting = $Self->ModifiedSettingGet(
|
|
Name => $Param{Name},
|
|
TargetUserID => $Param{TargetUserID},
|
|
);
|
|
|
|
if (%ModifiedSetting) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "There is already a modified setting for this user (or global)!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# Check duplicate name.
|
|
my %DefaultSetting = $Self->DefaultSettingGet(
|
|
DefaultID => $Param{DefaultID},
|
|
);
|
|
|
|
if ( !%DefaultSetting ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "DefaultID is invalid!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
if ( $Param{Name} ne $DefaultSetting{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Name doesn't match ('$Param{Name}')! It should be '$DefaultSetting{Name}'.",
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
# Check we have not UserModificationActive if we have TargetUserID they are exclusive.
|
|
if ( defined $Param{UserModificationActive} && $Param{TargetUserID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Could not set UserModificationActive on a user setting!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
# Update params with DefaultSetting if not defined.
|
|
for my $Attribute (qw(UserModificationActive IsValid)) {
|
|
$Param{$Attribute} //= $DefaultSetting{$Attribute};
|
|
$Param{$Attribute} = $Param{$Attribute} ? 1 : 0;
|
|
}
|
|
|
|
# Is possible to disable UserModificationActive just if it is enabled on default.
|
|
if ( !$DefaultSetting{UserModificationPossible} && $Param{UserModificationActive} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Could not UserModificationActive if default setting prohibits!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
# Serialize data as string.
|
|
$Param{EffectiveValue} = $Kernel::OM->Get('Kernel::System::YAML')->Dump(
|
|
Data => $Param{EffectiveValue},
|
|
);
|
|
|
|
# Set is dirty as enabled due it is a new setting.
|
|
my $IsDirty = 1;
|
|
|
|
$Param{ResetToDefault} = $Param{ResetToDefault} ? 1 : 0;
|
|
|
|
# Default should be locked.
|
|
my $LockedByUser = 1;
|
|
if ( !$Param{TargetUserID} ) {
|
|
$LockedByUser = $Self->DefaultSettingIsLockedByUser(
|
|
DefaultID => $Param{DefaultID},
|
|
ExclusiveLockUserID => $Param{UserID},
|
|
ExclusiveLockGUID => $Param{ExclusiveLockGUID},
|
|
);
|
|
}
|
|
|
|
# Check if we are on a deployment and a deleted value needs to be restored due an error
|
|
if ( !$LockedByUser && $Param{DeploymentExclusiveLockGUID} ) {
|
|
$LockedByUser = $Self->DeploymentIsLockedByUser(
|
|
ExclusiveLockGUID => $Param{DeploymentExclusiveLockGUID},
|
|
UserID => $Param{UserID},
|
|
);
|
|
}
|
|
|
|
if ( !$LockedByUser ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Default setting is not locked to this user!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Insert the modified.
|
|
return if !$DBObject->Do(
|
|
SQL => '
|
|
INSERT INTO sysconfig_modified
|
|
(sysconfig_default_id, name, user_id, is_valid, user_modification_active,
|
|
effective_value, is_dirty, reset_to_default, create_time, create_by, change_time, change_by)
|
|
VALUES
|
|
(?, ?, ?, ?, ?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)',
|
|
Bind => [
|
|
\$Param{DefaultID}, \$Param{Name}, \$Param{TargetUserID}, \$Param{IsValid},
|
|
\$Param{UserModificationActive}, \$Param{EffectiveValue},
|
|
\$IsDirty, \$Param{ResetToDefault}, \$Param{UserID}, \$Param{UserID},
|
|
],
|
|
);
|
|
|
|
my $SQLSelect = 'SELECT id, effective_value FROM sysconfig_modified
|
|
WHERE sysconfig_default_id = ?
|
|
AND name = ?
|
|
AND is_dirty = ? ';
|
|
|
|
my @BindSelect = ( \$Param{DefaultID}, \$Param{Name}, \$IsDirty );
|
|
|
|
if ( $Param{TargetUserID} ) {
|
|
$SQLSelect .= "AND user_id = ? ";
|
|
push @BindSelect, \$Param{TargetUserID};
|
|
}
|
|
else {
|
|
$SQLSelect .= "AND user_id IS NULL ";
|
|
}
|
|
|
|
# Get modified ID.
|
|
$DBObject->Prepare(
|
|
SQL => $SQLSelect,
|
|
Bind => \@BindSelect,
|
|
Limit => 1,
|
|
);
|
|
|
|
# Fetch the modified setting ID.
|
|
my $ModifiedSettingID;
|
|
|
|
ROW:
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
next ROW if $Row[1] ne $Param{EffectiveValue};
|
|
$ModifiedSettingID = $Row[0];
|
|
}
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigModified',
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigModifiedList',
|
|
Key => 'ModifiedSettingList',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigNavigation',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigEntities',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigIsDirty',
|
|
);
|
|
|
|
# Clean cache for setting translations.
|
|
my %Languages = %{ $Kernel::OM->Get('Kernel::Config')->Get('DefaultUsedLanguages') };
|
|
for my $Language ( sort keys %Languages ) {
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfig',
|
|
Key => "SettingTranslatedGet::$Language" . "::$Param{Name}",
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfig',
|
|
Key => "ConfigurationTranslatedGet::$Language",
|
|
);
|
|
}
|
|
|
|
# Unlock the setting.
|
|
my $IsUnlock = $Self->DefaultSettingUnlock(
|
|
DefaultID => $Param{DefaultID},
|
|
);
|
|
if ( !$IsUnlock ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Default setting with ID: $Param{DefaultID} was not possible to unlock!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
return $ModifiedSettingID;
|
|
}
|
|
|
|
=head2 ModifiedSettingGet()
|
|
|
|
Get SysConfig modified value.
|
|
|
|
my %ModifiedSetting = $SysConfigDBObject->ModifiedSettingGet(
|
|
ModifiedID => 123, # ModifiedID or NAME are required.
|
|
Name => 'Setting::Name',
|
|
TargetUserID => 2, # The ID of the user for which the modified setting is meant,
|
|
# exclusive with IsGlobal.
|
|
IsGlobal => 1, # Define a search for settings don't belong an user,
|
|
# exclusive with TargetUserID.
|
|
);
|
|
|
|
Returns:
|
|
|
|
%ModifiedSetting = (
|
|
ModifiedID => "123",
|
|
DefaultID => 456,
|
|
Name => "ProductName",
|
|
IsGlobal => 1, # 1 or 0, optional
|
|
IsValid => 1, # 1 or 0, optional, modified 0
|
|
IsDirty => 1, # 1 or 0, optional, modified 0
|
|
ResetToDefault => 1, # 1 or 0, optional, modified 0
|
|
UserModificationActive => 0, # 1 or 0, optional, modified 0
|
|
EffectiveValue => $SettingEffectiveValue,
|
|
TargetUserID => 2, # ID of the user for which the modified setting is meant
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
CreateBy => 1,
|
|
ChangeTime => "2016-05-29 11:04:04",
|
|
ChangeBy => 1,
|
|
SettingUID => 'Modified12320160529110404',
|
|
);
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{ModifiedID} && !$Param{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need ModifiedID or Name!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $FieldName;
|
|
my $FieldValue;
|
|
|
|
if ( $Param{ModifiedID} ) {
|
|
|
|
# Set DefaultID as filter.
|
|
$FieldName = 'id';
|
|
$FieldValue = $Param{ModifiedID};
|
|
}
|
|
elsif ( $Param{Name} ) {
|
|
|
|
# Set Name as filter.
|
|
$FieldName = 'name';
|
|
$FieldValue = $Param{Name};
|
|
}
|
|
|
|
# IsGlobal and TargetUserID are exclusive each other.
|
|
if ( defined $Param{IsGlobal} && defined $Param{TargetUserID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Use IsGlobal and TargetUserID at the same time is not allowed!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# Check optional settings.
|
|
for my $Item (qw(IsGlobal TargetUserID)) {
|
|
$Param{$Item} //= 0;
|
|
}
|
|
|
|
# Ff not defined TargetUserID it should be global.
|
|
if ( !$Param{TargetUserID} && $FieldName eq 'name' ) {
|
|
$Param{IsGlobal} = 1;
|
|
}
|
|
|
|
my $SQLExtra = '';
|
|
my @Bind = ( \$FieldValue );
|
|
|
|
# In case of global search user value is needed as null.
|
|
if ( $Param{IsGlobal} ) {
|
|
$SQLExtra = '
|
|
AND user_id IS NULL';
|
|
}
|
|
|
|
# Otherwise check effective user id.
|
|
elsif ( $Param{TargetUserID} ) {
|
|
$SQLExtra = "
|
|
AND user_id = ? ";
|
|
push @Bind, \$Param{TargetUserID};
|
|
}
|
|
|
|
my $CacheType = "SysConfigModified";
|
|
my $CacheKey = 'ModifiedSettingGet::' # this cache key gets more elements
|
|
. $FieldName . '::'
|
|
. $FieldValue . '::'
|
|
. $Param{IsGlobal} . '::'
|
|
. $Param{TargetUserID};
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return %{$Cache} if ref $Cache eq 'HASH';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
my $SQL = '
|
|
SELECT id, sysconfig_default_id, name, user_id, is_valid, user_modification_active,
|
|
effective_value, is_dirty, reset_to_default, create_time, create_by, change_time, change_by
|
|
FROM sysconfig_modified
|
|
WHERE';
|
|
|
|
$SQL .= ' ' . $FieldName . ' = ?' . $SQLExtra;
|
|
|
|
$SQL .= '
|
|
ORDER BY id DESC';
|
|
|
|
# Get modified from database.
|
|
return if !$DBObject->Prepare(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
);
|
|
|
|
my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML');
|
|
|
|
my %ModifiedSetting;
|
|
while ( my @Data = $DBObject->FetchrowArray() ) {
|
|
|
|
# De-serialize modified data.
|
|
my $EffectiveValue = $YAMLObject->Load( Data => $Data[6] );
|
|
|
|
my $TimeStamp = $Data[11];
|
|
$TimeStamp =~ s{:|-|[ ]}{}gmsx;
|
|
|
|
%ModifiedSetting = (
|
|
ModifiedID => $Data[0],
|
|
DefaultID => $Data[1],
|
|
Name => $Data[2],
|
|
TargetUserID => $Data[3],
|
|
IsValid => $Data[4],
|
|
UserModificationActive => $Data[5],
|
|
EffectiveValue => $EffectiveValue,
|
|
IsDirty => $Data[7] ? 1 : 0,
|
|
ResetToDefault => $Data[8] ? 1 : 0,
|
|
CreateTime => $Data[9],
|
|
CreateBy => $Data[10],
|
|
ChangeTime => $Data[11],
|
|
ChangeBy => $Data[12],
|
|
SettingUID => "Modified$Data[0]$TimeStamp",
|
|
);
|
|
}
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \%ModifiedSetting,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return %ModifiedSetting;
|
|
}
|
|
|
|
=head2 ModifiedSettingListGet()
|
|
|
|
Get modified setting list with complete data.
|
|
|
|
my @List = $SysConfigDBObject->ModifiedSettingListGet(
|
|
IsInvisible => 1, # 1 or 0
|
|
IsReadonly => 0, # 1 or 0
|
|
IsRequired => 1, # 1 or 0
|
|
IsValid => 1, # 1 or 0
|
|
IsDirty => 1, # 1 or 0
|
|
ResetToDefault => 1, # 1 or 0
|
|
TargetUserID => 2, # the ID of the user for which the modified setting is meant,
|
|
# exclusive with IsGlobal.
|
|
IsGlobal => 1, # Define a search for settings don't belong an user,
|
|
# exclusive with TargetUserID.
|
|
HasConfigLevel => 0, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
Name => 'ACL::CacheTTL', # setting name
|
|
ChangeBy => 123,
|
|
);
|
|
|
|
Returns:
|
|
|
|
@List = (
|
|
{
|
|
ModifiedID => 123,
|
|
Name => "ProductName",
|
|
Description => "Defines the name of the application ...",
|
|
Navigation => "ASimple::Path::Structure",
|
|
IsInvisible => 1,
|
|
IsReadonly => 0,
|
|
IsRequired => 1,
|
|
IsValid => 1,
|
|
ResetToDefault => 1, # 1 or 0
|
|
HasConfigLevel => 200,
|
|
UserModificationActive => 0, # 1 or 0
|
|
XMLContentRaw => "The XML structure as it is on the config file",
|
|
XMLContentParsed => "XML parsed to Perl",
|
|
EffectiveValue => "Product 6",
|
|
IsDirty => 1, # 1 or 0
|
|
ExclusiveLockGUID => 'A32CHARACTERLONGSTRINGFORLOCKING',
|
|
ExclusiveLockUserID => 1,
|
|
ExclusiveLockExpiryTime => '2016-05-29 11:09:04',
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
ChangeTime => "2016-05-29 11:04:04",
|
|
},
|
|
{
|
|
ModifiedID => 321,
|
|
Name => 'FieldName',
|
|
# ...
|
|
CreateTime => '2010-09-11 10:08:00',
|
|
ChangeTime => '2011-01-01 01:01:01',
|
|
},
|
|
# ...
|
|
);
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingListGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# IsGlobal and TargetUserID are exclusive each other.
|
|
if ( defined $Param{IsGlobal} && defined $Param{TargetUserID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Use IsGlobal and TargetUserID at the same time is not allowed!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
my @Filters;
|
|
my @Bind;
|
|
|
|
my $CacheType = 'SysConfigModifiedList';
|
|
my $CacheKey = 'ModifiedSettingList';
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
my @DataRaw;
|
|
|
|
if ( ref $Cache eq 'ARRAY' ) {
|
|
@DataRaw = @{$Cache};
|
|
}
|
|
else {
|
|
my $SQL = '
|
|
SELECT id, sysconfig_default_id, name, user_id, is_valid, user_modification_active,
|
|
effective_value, is_dirty, reset_to_default, create_time, create_by, change_time, change_by
|
|
FROM sysconfig_modified';
|
|
|
|
$SQL .= ' ORDER BY id';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Get modified from database.
|
|
return if !$DBObject->Prepare(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
);
|
|
|
|
my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML');
|
|
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
|
|
# De-serialize modified data.
|
|
my $EffectiveValue = $YAMLObject->Load( Data => $Row[6] );
|
|
|
|
my $TimeStamp = $Row[11];
|
|
$TimeStamp =~ s{:|-|[ ]}{}gmsx;
|
|
|
|
my %ModifiedSetting = (
|
|
ModifiedID => $Row[0],
|
|
DefaultID => $Row[1],
|
|
Name => $Row[2],
|
|
TargetUserID => $Row[3],
|
|
IsValid => $Row[4],
|
|
UserModificationActive => $Row[5],
|
|
EffectiveValue => $EffectiveValue,
|
|
IsDirty => $Row[7] ? 1 : 0,
|
|
ResetToDefault => $Row[8] ? 1 : 0,
|
|
CreateTime => $Row[9],
|
|
CreateBy => $Row[10],
|
|
ChangeTime => $Row[11],
|
|
ChangeBy => $Row[12],
|
|
SettingUID => "Modified$Row[0]$TimeStamp",
|
|
);
|
|
|
|
push @DataRaw, \%ModifiedSetting;
|
|
}
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \@DataRaw,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
}
|
|
|
|
# Copy DataRaw to prevent modifications to in memory cache.
|
|
my @Data = @DataRaw;
|
|
|
|
if ( defined $Param{IsInvisible} ) {
|
|
@Data = grep { $_->{IsInvisible} eq $Param{IsInvisible} } @Data;
|
|
}
|
|
if ( defined $Param{IsReadonly} ) {
|
|
@Data = grep { $_->{IsReadonly} eq $Param{IsReadonly} } @Data;
|
|
}
|
|
if ( defined $Param{IsRequired} ) {
|
|
@Data = grep { $_->{IsRequired} eq $Param{IsRequired} } @Data;
|
|
}
|
|
if ( defined $Param{IsValid} ) {
|
|
@Data = grep { $_->{IsValid} eq $Param{IsValid} } @Data;
|
|
}
|
|
if ( defined $Param{IsDirty} ) {
|
|
@Data = grep { $_->{IsDirty} eq $Param{IsDirty} } @Data;
|
|
}
|
|
if ( defined $Param{HasConfigLevel} ) {
|
|
@Data = grep { $_->{HasConfigLevel} eq $Param{HasConfigLevel} } @Data;
|
|
}
|
|
if ( defined $Param{UserModificationActive} ) {
|
|
@Data = grep { $_->{UserModificationActive} eq $Param{UserModificationActive} } @Data;
|
|
}
|
|
if ( defined $Param{Name} ) {
|
|
@Data = grep { $_->{Name} eq $Param{Name} } @Data;
|
|
}
|
|
if ( defined $Param{TargetUserID} ) {
|
|
@Data = grep { $_->{TargetUserID} && $_->{TargetUserID} eq $Param{TargetUserID} } @Data;
|
|
}
|
|
if ( defined $Param{ChangeBy} ) {
|
|
@Data = grep { $_->{ChangeBy} eq $Param{ChangeBy} } @Data;
|
|
}
|
|
if ( defined $Param{Locked} ) {
|
|
if ( $Param{Locked} ) {
|
|
@Data = grep { $_->{ExclusiveLockGUID} } @Data;
|
|
}
|
|
else {
|
|
@Data = grep { !$_->{ExclusiveLockGUID} } @Data;
|
|
}
|
|
}
|
|
if ( $Param{IsGlobal} ) {
|
|
@Data = grep { !$_->{TargetUserID} } @Data;
|
|
}
|
|
|
|
return @Data;
|
|
}
|
|
|
|
=head2 ModifiedSettingDelete()
|
|
|
|
Delete a modified setting from list.
|
|
|
|
my $Success = $SysConfigDBObject->ModifiedSettingDelete(
|
|
ModifiedID => 123,
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Success = 1; # or false in case of an error
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingDelete {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{ModifiedID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need ModifiedID!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my %ModifiedSetting = $Self->ModifiedSettingGet(
|
|
ModifiedID => $Param{ModifiedID},
|
|
);
|
|
|
|
return if !IsHashRefWithData( \%ModifiedSetting );
|
|
|
|
# Delete modified from the list.
|
|
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
|
SQL => 'DELETE FROM sysconfig_modified WHERE id = ?',
|
|
Bind => [ \$Param{ModifiedID} ],
|
|
);
|
|
|
|
for my $Item (qw(0 1)) {
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigModified',
|
|
Key => 'ModifiedSettingGet::id::'
|
|
. $ModifiedSetting{ModifiedID} . '::'
|
|
. $Item . '::0',
|
|
);
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigModified',
|
|
Key => 'ModifiedSettingGet::name::'
|
|
. $ModifiedSetting{Name} . '::'
|
|
. $Item . '::0',
|
|
);
|
|
}
|
|
|
|
if ( $ModifiedSetting{TargetUserID} ) {
|
|
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigModified',
|
|
Key => 'ModifiedSettingGet::id::'
|
|
. $ModifiedSetting{ModifiedID} . '::0::'
|
|
. $ModifiedSetting{TargetUserID},
|
|
);
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigModified',
|
|
Key => 'ModifiedSettingGet::name::'
|
|
. $ModifiedSetting{Name} . '::0::'
|
|
. $ModifiedSetting{TargetUserID},
|
|
);
|
|
}
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigModifiedList',
|
|
Key => 'ModifiedSettingList',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigNavigation',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigEntities',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigIsDirty',
|
|
);
|
|
|
|
# Clean cache for setting translations.
|
|
my %Languages = %{ $Kernel::OM->Get('Kernel::Config')->Get('DefaultUsedLanguages') };
|
|
for my $Language ( sort keys %Languages ) {
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfig',
|
|
Key => "SettingTranslatedGet::$Language" . "::$ModifiedSetting{Name}",
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfig',
|
|
Key => "ConfigurationTranslatedGet::$Language",
|
|
);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 ModifiedSettingUpdate()
|
|
|
|
Update SysConfig modified.
|
|
|
|
my $Success = $SysConfigDBObject->ModifiedSettingUpdate(
|
|
ModifiedID => 123, # (required)
|
|
DefaultID => 456, # (required)
|
|
Name => "ProductName", # (required)
|
|
IsValid => 1, # (optional) 1 or 0, optional (uses the value from DefaultSetting if not defined)
|
|
IsDirty => 1, # (optional) Default 1.
|
|
ResetToDefault => 1, # (optional), default 0
|
|
UserModificationActive => 1, # (optional) 1 or 0 (uses the value from DefaultSetting if not defined)
|
|
EffectiveValue => $SettingEffectiveValue,
|
|
TargetUserID => 2, # (optional), ID of the user for which the modified setting is meant,
|
|
# leave it undef for global changes.
|
|
ExclusiveLockGUID => $LockingString, # the GUID used to locking the setting
|
|
UserID => 1, # (required)
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Success = 1; # or false in case of an error
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingUpdate {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Store params for further usage.
|
|
my %ModifiedVersionParams = %Param;
|
|
|
|
for my $Key (qw(ModifiedID DefaultID Name EffectiveValue UserID)) {
|
|
if ( !defined $Param{$Key} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Key!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
# Set is dirty to 1 if not defined.
|
|
$Param{IsDirty} //= 1;
|
|
|
|
# Get modified setting.
|
|
my %ModifiedSetting = $Self->ModifiedSettingGet(
|
|
ModifiedID => $Param{ModifiedID},
|
|
);
|
|
|
|
# Check if we really need to update.
|
|
my $IsDifferent = 0;
|
|
for my $Key (qw(ModifiedID DefaultID Name IsValid EffectiveValue UserModificationActive)) {
|
|
my $DataIsDifferent = DataIsDifferent(
|
|
Data1 => $Param{$Key},
|
|
Data2 => $ModifiedSetting{$Key},
|
|
);
|
|
if ($DataIsDifferent) {
|
|
$IsDifferent = 1;
|
|
}
|
|
}
|
|
|
|
if ( $ModifiedSetting{IsDirty} != $Param{IsDirty} ) {
|
|
$IsDifferent = 1;
|
|
}
|
|
|
|
return 1 if !$IsDifferent;
|
|
|
|
# Retrieve default setting.
|
|
my %DefaultSetting = $Self->DefaultSettingGet(
|
|
DefaultID => $Param{DefaultID},
|
|
);
|
|
|
|
if ( !%DefaultSetting ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "DefaultID is invalid!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
if ( $Param{Name} ne $DefaultSetting{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Name is Invalid!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
# Check we have not UserModificationActive if we have TargetUserID they are exclusive
|
|
if ( defined $Param{UserModificationActive} && $Param{TargetUserID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Could not set UserModificationActive on a user setting!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# Update params with DefaultSetting if not defined.
|
|
for my $Attribute (qw(UserModificationActive IsValid)) {
|
|
$Param{$Attribute} //= $DefaultSetting{$Attribute};
|
|
$Param{$Attribute} = $Param{$Attribute} ? 1 : 0;
|
|
}
|
|
|
|
# Is possible to disable UserModificationActive just if it is enabled on default.
|
|
if ( !$DefaultSetting{UserModificationPossible} && $Param{UserModificationActive} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Could not UserModificationActive if default setting prohibits!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# Serialize data as string.
|
|
$Param{EffectiveValue} = $Kernel::OM->Get('Kernel::System::YAML')->Dump(
|
|
Data => $Param{EffectiveValue},
|
|
);
|
|
|
|
$Param{ResetToDefault} = $Param{ResetToDefault} ? 1 : 0;
|
|
|
|
# Default should be locked.
|
|
my $LockedByUser = 1;
|
|
if ( !$Param{UserID} ) {
|
|
$LockedByUser = $Self->DefaultSettingIsLockedByUser(
|
|
DefaultID => $Param{DefaultID},
|
|
ExclusiveLockUserID => $Param{UserID},
|
|
ExclusiveLockGUID => $Param{ExclusiveLockGUID},
|
|
);
|
|
}
|
|
|
|
if ( !$LockedByUser ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Default setting is not locked to this user!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Insert the modified.
|
|
return if !$DBObject->Do(
|
|
SQL => '
|
|
UPDATE sysconfig_modified
|
|
SET sysconfig_default_id = ?, name = ?, is_valid = ?, user_modification_active = ?,
|
|
effective_value = ?, is_dirty = ?, reset_to_default = ?, change_time = current_timestamp, change_by = ?
|
|
WHERE id = ?',
|
|
Bind => [
|
|
\$Param{DefaultID}, \$Param{Name}, \$Param{IsValid}, \$Param{UserModificationActive},
|
|
\$Param{EffectiveValue}, \$Param{IsDirty}, \$Param{ResetToDefault},
|
|
\$Param{UserID}, \$Param{ModifiedID},
|
|
],
|
|
);
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigModified',
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigModifiedList',
|
|
Key => 'ModifiedSettingList',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigNavigation',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigEntities',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigIsDirty',
|
|
);
|
|
|
|
# Clean cache for setting translations.
|
|
my %Languages = %{ $Kernel::OM->Get('Kernel::Config')->Get('DefaultUsedLanguages') };
|
|
for my $Language ( sort keys %Languages ) {
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfig',
|
|
Key => "SettingTranslatedGet::$Language" . "::$Param{Name}",
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfig',
|
|
Key => "ConfigurationTranslatedGet::$Language",
|
|
);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 ModifiedSettingDirtyCleanUp()
|
|
|
|
Removes the IsDirty flag from modified settings.
|
|
|
|
my $Success = $SysConfigDBObject->ModifiedSettingDirtyCleanUp(
|
|
TargetUserID => 123, # (optional)
|
|
ModifiedIDs => [ # (optional) applies to only this list of settings
|
|
123,
|
|
456,
|
|
],
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Success = 1; # or false in case of an error
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingDirtyCleanUp {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( defined $Param{TargetUserID} && !IsPositiveInteger( $Param{TargetUserID} ) ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "TargetUserID is invalid",
|
|
);
|
|
return;
|
|
}
|
|
|
|
if ( defined $Param{ModifiedIDs} && !IsArrayRefWithData( $Param{ModifiedIDs} ) ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "ModifiedIDs is invalid",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# Define common SQL.
|
|
my $SQL = '
|
|
UPDATE sysconfig_modified
|
|
SET is_dirty = 0
|
|
WHERE is_dirty = 1';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
if ( $Param{ModifiedIDs} ) {
|
|
|
|
my $ModifiedIDsStrg = join ',', map { $DBObject->Quote( $_, 'Integer' ) } @{ $Param{ModifiedIDs} };
|
|
|
|
$SQL .= "
|
|
AND id IN ($ModifiedIDsStrg)";
|
|
}
|
|
|
|
my @Bind;
|
|
|
|
# Define user condition.
|
|
my $UserCondition = '
|
|
AND user_id IS NULL';
|
|
if ( $Param{TargetUserID} ) {
|
|
$UserCondition = '
|
|
AND user_id = ?';
|
|
push @Bind, \$Param{TargetUserID};
|
|
}
|
|
|
|
# Remove is dirty flag for modified settings.
|
|
return if !$DBObject->Do(
|
|
SQL => $SQL . $UserCondition,
|
|
Bind => \@Bind,
|
|
);
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigModified',
|
|
);
|
|
$CacheObject->Delete(
|
|
Type => 'SysConfigModifiedList',
|
|
Key => 'ModifiedSettingList',
|
|
);
|
|
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigModifiedVersion',
|
|
);
|
|
$CacheObject->CleanUp(
|
|
Type => 'SysConfigIsDirty',
|
|
);
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 ModifiedSettingVersionAdd()
|
|
|
|
Add a new SysConfig modified version entry.
|
|
|
|
my $ModifiedVersionID = $SysConfigDBObject->ModifiedSettingVersionAdd(
|
|
DefaultVersionID => 456,
|
|
Name => "ProductName",
|
|
IsValid => 1, # 1 or 0, optional, optional 0
|
|
UserModificationActive => 0, # 1 or 0, optional, optional 0
|
|
TargetUserID => 2, # The ID of the user for which the modified setting is meant,
|
|
# leave it undef for global changes.
|
|
EffectiveValue => $SettingEffectiveValue, # the value as will be stored in the Perl configuration file
|
|
DeploymentTimeStamp => '2015-12-12 12:00:00', # unique timestamp per deployment
|
|
ResetToDefault => 1, # optional, default 0
|
|
UserID => 1,
|
|
);
|
|
|
|
Returns:
|
|
|
|
my $ModifiedVersionID = 123; # false in case of an error
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingVersionAdd {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
for my $Key (
|
|
qw(DefaultVersionID Name EffectiveValue DeploymentTimeStamp UserID)
|
|
)
|
|
{
|
|
if ( !defined $Param{$Key} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Key!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
# Check boolean parameters, set 0 as default value).
|
|
for my $Key (qw(IsValid UserModificationActive ResetToDefault)) {
|
|
$Param{$Key} = ( defined $Param{$Key} && $Param{$Key} ? 1 : 0 );
|
|
}
|
|
|
|
# Serialize data as string.
|
|
$Param{EffectiveValue} = $Kernel::OM->Get('Kernel::System::YAML')->Dump(
|
|
Data => $Param{EffectiveValue},
|
|
);
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Insert the modified.
|
|
return if !$DBObject->Do(
|
|
SQL => '
|
|
INSERT INTO sysconfig_modified_version
|
|
(sysconfig_default_version_id, name, user_id, is_valid, reset_to_default,
|
|
user_modification_active, effective_value, create_time, create_by,
|
|
change_time, change_by)
|
|
VALUES
|
|
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
|
Bind => [
|
|
\$Param{DefaultVersionID}, \$Param{Name}, \$Param{TargetUserID}, \$Param{IsValid},
|
|
\$Param{ResetToDefault}, \$Param{UserModificationActive},
|
|
\$Param{EffectiveValue}, \$Param{DeploymentTimeStamp}, \$Param{UserID},
|
|
\$Param{DeploymentTimeStamp}, \$Param{UserID},
|
|
],
|
|
);
|
|
|
|
# Get modified ID.
|
|
$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT id
|
|
FROM sysconfig_modified_version
|
|
WHERE sysconfig_default_version_id =?
|
|
AND name = ?
|
|
ORDER BY id DESC',
|
|
Bind => [ \$Param{DefaultVersionID}, \$Param{Name} ],
|
|
Limit => 1,
|
|
);
|
|
|
|
# Fetch the modified setting ID
|
|
my $ModifiedVersionID;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
$ModifiedVersionID = $Row[0];
|
|
}
|
|
|
|
$Kernel::OM->Get('Kernel::System::Cache')->CleanUp(
|
|
Type => 'SysConfigModifiedVersion',
|
|
);
|
|
$Kernel::OM->Get('Kernel::System::Cache')->CleanUp(
|
|
Type => 'SysConfigModifiedVersionList',
|
|
);
|
|
|
|
return $ModifiedVersionID;
|
|
}
|
|
|
|
=head2 ModifiedSettingVersionGet()
|
|
|
|
Get SysConfig modified version entry.
|
|
|
|
my %ModifiedSettingVersion = $SysConfigDBObject->ModifiedSettingVersionGet(
|
|
ModifiedVersionID => 123,
|
|
);
|
|
|
|
Returns:
|
|
|
|
%ModifiedSetting = (
|
|
ModifiedVersionID => 123,
|
|
DefaultVersionID => 456,
|
|
Name => "ProductName",
|
|
TargetUserID => 123,
|
|
IsValid => 1, # 1 or 0
|
|
ResetToDefault => 1, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
EffectiveValue => "Product 6",
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
ChangeTime => "2016-05-29 11:04:04",
|
|
);
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingVersionGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{ModifiedVersionID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need ModifiedVersionID!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $CacheType = "SysConfigModifiedVersion";
|
|
my $CacheKey = 'ModifiedSettingVersionGet::' . $Param{ModifiedVersionID};
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return %{$Cache} if ref $Cache eq 'HASH';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Get modified from database.
|
|
return if !$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT smv.id, smv.sysconfig_default_version_id, sdv.sysconfig_default_id, sm.id,
|
|
smv.name, smv.user_id,
|
|
smv.is_valid, smv.reset_to_default, smv.user_modification_active, smv.effective_value,
|
|
smv.create_time, smv.change_time
|
|
FROM sysconfig_modified_version smv
|
|
LEFT JOIN sysconfig_default_version sdv
|
|
ON smv.sysconfig_default_version_id = sdv.id
|
|
LEFT JOIN sysconfig_modified sm
|
|
ON sdv.sysconfig_default_id = sm.sysconfig_default_id
|
|
WHERE smv.id = ?',
|
|
Bind => [ \$Param{ModifiedVersionID} ],
|
|
);
|
|
|
|
my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML');
|
|
|
|
my %ModifiedSettingVersion;
|
|
while ( my @Data = $DBObject->FetchrowArray() ) {
|
|
|
|
# De-serialize modified data.
|
|
my $EffectiveValue = $YAMLObject->Load( Data => $Data[9] );
|
|
|
|
%ModifiedSettingVersion = (
|
|
ModifiedVersionID => $Data[0],
|
|
DefaultVersionID => $Data[1],
|
|
DefaultID => $Data[2],
|
|
ModifiedID => $Data[3],
|
|
Name => $Data[4],
|
|
TargetUserID => $Data[5],
|
|
IsValid => $Data[6],
|
|
ResetToDefault => $Data[7] ? 1 : 0,
|
|
UserModificationActive => $Data[8],
|
|
EffectiveValue => $EffectiveValue,
|
|
DeploymentTimeStamp => $Data[10],
|
|
CreateTime => $Data[10],
|
|
ChangeTime => $Data[11],
|
|
);
|
|
}
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \%ModifiedSettingVersion,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return %ModifiedSettingVersion;
|
|
}
|
|
|
|
=head2 ModifiedSettingVersionListGet()
|
|
|
|
Get version setting list with complete data.
|
|
|
|
my @List = $SysConfigDBObject->ModifiedSettingVersionListGet(
|
|
Name => 1, # optional
|
|
DefaultVersionID => 230, # optional
|
|
);
|
|
|
|
Returns:
|
|
|
|
@List = (
|
|
{
|
|
ModifiedVersionID => 123,
|
|
ModifiedID => 456,
|
|
Name => "ProductName",
|
|
TargetUserID => 78,
|
|
IsValid => 1, # 1 or 0
|
|
ResetToDefault => 1, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
EffectiveValue => "Product 6",
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
ChangeTime => "2016-05-29 11:04:04",
|
|
},
|
|
{
|
|
ModifiedVersionID => 789,
|
|
ModifiedID => 579,
|
|
Name => "ADifferentProductName",
|
|
TargetUserID => 909,
|
|
IsValid => 1, # 1 or 0
|
|
ResetToDefault => 1, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
. . .
|
|
},
|
|
# ...
|
|
);
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingVersionListGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DefaultVersionID} && !$Param{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need DefaultVersionID or Name!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $FieldName;
|
|
my $FieldValue;
|
|
my $FieldCache;
|
|
|
|
if ( $Param{DefaultVersionID} ) {
|
|
|
|
# Set conditions for modified ID.
|
|
$FieldName = 'sysconfig_default_version_id';
|
|
$FieldValue = $Param{DefaultVersionID};
|
|
$FieldCache = 'DefaultVersionID';
|
|
}
|
|
elsif ( $Param{Name} ) {
|
|
|
|
# Set conditions for name.
|
|
$FieldName = 'name';
|
|
$FieldValue = $Param{Name};
|
|
$FieldCache = 'Name';
|
|
}
|
|
|
|
# Loop over filters and set them on SQL and cache key.
|
|
my $SQLFilter = "WHERE $FieldName = '$FieldValue' ";
|
|
|
|
my $CacheType = 'SysConfigModifiedVersionList';
|
|
my $CacheKey = 'ModifiedSettingVersionList::' . $FieldCache . '=' . $FieldValue;
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return @{$Cache} if ref $Cache eq 'ARRAY';
|
|
|
|
# Start SQL statement.
|
|
my $SQL = '
|
|
SELECT id, name
|
|
FROM sysconfig_modified_version';
|
|
|
|
$SQL .= ' ' . $SQLFilter . ' ORDER BY id DESC';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
my @Data;
|
|
return if !$DBObject->Prepare(
|
|
SQL => $SQL,
|
|
);
|
|
|
|
my @ModifiedVersionIDs;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
push @ModifiedVersionIDs, $Row[0];
|
|
}
|
|
|
|
# Get modified settings.
|
|
ITEMID:
|
|
for my $ItemID (@ModifiedVersionIDs) {
|
|
|
|
my %ModifiedSetting = $Self->ModifiedSettingVersionGet(
|
|
ModifiedVersionID => $ItemID,
|
|
);
|
|
|
|
next ITEMID if !%ModifiedSetting;
|
|
|
|
push @Data, \%ModifiedSetting;
|
|
}
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \@Data,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return @Data;
|
|
}
|
|
|
|
=head2 ModifiedSettingVersionGetLast()
|
|
|
|
Get last deployment.
|
|
|
|
my %ModifiedSettingVersion = $SysConfigDBObject->ModifiedSettingVersionGetLast(
|
|
Name => 'ProductName',
|
|
);
|
|
|
|
Returns:
|
|
|
|
%ModifiedSettingVersion = (
|
|
DefaultVersionID => 123,
|
|
ModifiedID => 456,
|
|
Name => "ProductName",
|
|
TargetUserID => 45,
|
|
IsValid => 1, # 1 or 0
|
|
ResetToDefault => 1, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
EffectiveValue => "Product 6",
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
ChangeTime => "2016-05-29 11:04:04",
|
|
);
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingVersionGetLast {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need Name!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $CacheType = 'SysConfigModifiedVersion';
|
|
my $CacheKey = 'ModifiedSettingVersionGetLast::' . $Param{Name};
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return %{$Cache} if ref $Cache eq 'HASH';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
return if !$DBObject->Prepare(
|
|
SQL => 'SELECT MAX(id) FROM sysconfig_modified_version WHERE name = ?',
|
|
Bind => [ \$Param{Name} ],
|
|
);
|
|
|
|
my $ModifiedVersionID;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
|
|
$ModifiedVersionID = $Row[0];
|
|
}
|
|
|
|
return if !$ModifiedVersionID;
|
|
|
|
my %ModifiedSetting = $Self->ModifiedSettingVersionGet(
|
|
ModifiedVersionID => $ModifiedVersionID,
|
|
);
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \%ModifiedSetting,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return %ModifiedSetting;
|
|
}
|
|
|
|
=head2 ModifiedSettingVersionListGetLast()
|
|
|
|
Get a list of the last deployed version of each modified SysConfig setting
|
|
|
|
my @List = $SysConfigDBObject->ModifiedSettingVersionListGetLast();
|
|
|
|
Returns:
|
|
|
|
@List = (
|
|
{
|
|
ModifiedVersionID => 123,
|
|
ModifiedID => 456,
|
|
Name => "ProductName",
|
|
TargetUserID => 78,
|
|
IsValid => 1, # 1 or 0
|
|
ResetToDefault => 1, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
EffectiveValue => "Product 6",
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
ChangeTime => "2016-05-29 11:04:04",
|
|
},
|
|
{
|
|
ModifiedVersionID => 789,
|
|
ModifiedID => 579,
|
|
Name => "ADifferentProductName",
|
|
TargetUserID => 909,
|
|
IsValid => 1, # 1 or 0
|
|
ResetToDefault => 1, # 1 or 0
|
|
UserModificationActive => 0, # 1 or 0
|
|
. . .
|
|
},
|
|
# ...
|
|
);
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingVersionListGetLast {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $CacheType = 'SysConfigModifiedVersionList';
|
|
my $CacheKey = 'ModifiedSettingVersionListGetLast';
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return @{$Cache} if ref $Cache eq 'ARRAY';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
my @Data;
|
|
return if !$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT MAX(id), sysconfig_default_version_id
|
|
FROM sysconfig_modified_version
|
|
GROUP BY sysconfig_default_version_id
|
|
ORDER BY sysconfig_default_version_id ASC'
|
|
);
|
|
|
|
my @ModifiedVersionIDs;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
push @ModifiedVersionIDs, $Row[0];
|
|
}
|
|
|
|
# Get modified settings.
|
|
for my $ItemID (@ModifiedVersionIDs) {
|
|
|
|
my %ModifiedSetting = $Self->ModifiedSettingVersionGet(
|
|
ModifiedVersionID => $ItemID,
|
|
);
|
|
push @Data, \%ModifiedSetting;
|
|
}
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \@Data,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return @Data;
|
|
}
|
|
|
|
=head2 ModifiedSettingVersionDelete()
|
|
|
|
Delete a modified setting version from list based on modified version ID or modified ID.
|
|
|
|
my $Success = $SysConfigDBObject->ModifiedSettingVersionDelete(
|
|
ModifiedVersionID => 123,
|
|
);
|
|
|
|
or
|
|
|
|
my $Success = $SysConfigDBObject->ModifiedSettingVersionDelete(
|
|
ModifiedID => 45,
|
|
);
|
|
|
|
or
|
|
|
|
my $Success = $SysConfigDBObject->ModifiedSettingVersionDelete(
|
|
Name => 'AnyName',
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Success = 1; # or false in case of an error
|
|
|
|
=cut
|
|
|
|
sub ModifiedSettingVersionDelete {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{ModifiedVersionID} && !$Param{ModifiedID} && !$Param{Name} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need ID, ModifiedID or Name!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $FieldName;
|
|
my $FieldValue;
|
|
|
|
if ( $Param{ModifiedVersionID} ) {
|
|
|
|
# Set conditions for ID.
|
|
$FieldName = 'id';
|
|
$FieldValue = $Param{ModifiedVersionID};
|
|
}
|
|
elsif ( $Param{DefaultVersionID} ) {
|
|
|
|
# Set conditions for default version id.
|
|
$FieldName = 'sysconfig_default_version_id';
|
|
$FieldValue = $Param{DefaultVersionID};
|
|
}
|
|
elsif ( $Param{Name} ) {
|
|
|
|
# Set conditions for name.
|
|
$FieldName = 'name';
|
|
$FieldValue = $Param{Name};
|
|
|
|
}
|
|
|
|
# Delete modified from the list.
|
|
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
|
SQL => 'DELETE FROM sysconfig_modified_version WHERE ' . $FieldName . ' = ?',
|
|
Bind => [ \$FieldValue ],
|
|
);
|
|
|
|
if ( $FieldName eq 'id' ) {
|
|
|
|
my %ModifiedVersionSetting = $Self->ModifiedSettingVersionGet(
|
|
ModifiedVersionID => $FieldValue,
|
|
|
|
);
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigModifiedVersion',
|
|
Key => 'ModifiedSettingVersionGet::' . $FieldValue,
|
|
);
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigModifiedVersion',
|
|
Key => 'ModifiedSettingVersionGetLast::' . $ModifiedVersionSetting{DefaultVersionID},
|
|
);
|
|
}
|
|
else {
|
|
|
|
$Kernel::OM->Get('Kernel::System::Cache')->CleanUp(
|
|
Type => 'SysConfigModifiedVersion',
|
|
);
|
|
}
|
|
|
|
$Kernel::OM->Get('Kernel::System::Cache')->CleanUp(
|
|
Type => 'SysConfigModifiedVersionList',
|
|
);
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 ConfigurationIsDirty()
|
|
|
|
Check if there are not deployed changes on system configuration.
|
|
|
|
my $Result = $SysConfigDBObject->ConfigurationIsDirty(
|
|
UserID => 123, # optional, the user that changes a modified setting
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Result = 1; # or 0 if configuration is not dirty.
|
|
|
|
=cut
|
|
|
|
sub ConfigurationIsDirty {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $CacheType = 'SysConfigIsDirty';
|
|
my $CacheKey = 'IsDirty';
|
|
|
|
if ( $Param{UserID} ) {
|
|
$CacheKey .= "::UserID=$Param{UserID}";
|
|
}
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return ${$Cache} if ref $Cache eq 'SCALAR';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
my $SQL = '
|
|
SELECT sd.id
|
|
FROM sysconfig_default sd
|
|
LEFT OUTER JOIN sysconfig_modified sm ON sm.name = sd.name
|
|
WHERE ';
|
|
|
|
my $SQLWhere = 'sd.is_dirty = 1 OR (sm.user_id IS NULL AND sm.is_dirty = 1)';
|
|
|
|
my @Bind;
|
|
if ( $Param{UserID} ) {
|
|
$SQLWhere = 'sd.is_dirty = 1 OR (sm.user_id IS NULL AND sm.is_dirty = 1 AND sm.change_by = ? )';
|
|
push @Bind, \$Param{UserID};
|
|
}
|
|
|
|
$SQL .= $SQLWhere;
|
|
|
|
return if !$DBObject->Prepare(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
Limit => 1,
|
|
);
|
|
|
|
my $Result;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
$Result = 1;
|
|
}
|
|
|
|
$Result //= '0';
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \$Result,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return $Result;
|
|
}
|
|
|
|
=head2 DeploymentAdd()
|
|
|
|
Adds a new deployment.
|
|
|
|
my $DeploymentID = $SysConfigDBObject->DeploymentAdd(
|
|
Comments => 'Some Comments', # optional
|
|
EffectiveValueStrg => $EffectiveValuesStrgRef, # string reference with the value of all settings,
|
|
# to be stored in a Perl cache file
|
|
TargetUserID => 123, # to deploy only user specific settings
|
|
ExclusiveLockGUID => $LockingString, # the GUID used to locking the deployment,
|
|
# not needed if TargetUserID is used
|
|
DeploymentTimeStamp => '1977-12-12 12:00:00',
|
|
UserID => 123,
|
|
);
|
|
|
|
Returns:
|
|
|
|
$DeploymentID = 123; # or false in case of an error
|
|
|
|
=cut
|
|
|
|
sub DeploymentAdd {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
for my $Key (qw(UserID DeploymentTimeStamp)) {
|
|
if ( !$Param{$Key} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Key!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !defined $Param{EffectiveValueStrg} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need EffectiveValueStrg!"
|
|
);
|
|
return;
|
|
}
|
|
|
|
if ( !$Param{TargetUserID} && !$Param{ExclusiveLockGUID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need ExclusiveLockGUID",
|
|
);
|
|
}
|
|
|
|
if ( ref $Param{EffectiveValueStrg} ne 'SCALAR' || !IsStringWithData( ${ $Param{EffectiveValueStrg} } ) ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "EffectiveValueStrg is invalid!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
if ( exists $Param{TargetUserID} && !$Param{TargetUserID} ) {
|
|
delete $Param{TargetUserID};
|
|
}
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
my @UserDeploymentIDs;
|
|
if ( $Param{TargetUserID} ) {
|
|
|
|
# Remember previous user deployments.
|
|
return if !$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT id
|
|
FROM sysconfig_deployment
|
|
WHERE user_id = ?',
|
|
Bind => [ \$Param{TargetUserID}, ],
|
|
);
|
|
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
push @UserDeploymentIDs, $Row[0];
|
|
}
|
|
}
|
|
else {
|
|
my $ExclusiveLockGUID = $Self->DeploymentIsLockedByUser(
|
|
ExclusiveLockGUID => $Param{ExclusiveLockGUID},
|
|
UserID => $Param{UserID},
|
|
);
|
|
|
|
if ( !$ExclusiveLockGUID ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Deployment is not locked to this user!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
my $UID = 'OTRSInvalid-' . $Self->_GetUID();
|
|
|
|
# Create a deployment record without the real comments.
|
|
return if !$DBObject->Do(
|
|
SQL => '
|
|
INSERT INTO sysconfig_deployment
|
|
(comments, effective_value, user_id, create_time, create_by)
|
|
VALUES
|
|
(?, ?, ?, ?, ?)',
|
|
Bind => [
|
|
\$UID, \${ $Param{EffectiveValueStrg} }, \$Param{TargetUserID}, \$Param{DeploymentTimeStamp},
|
|
\$Param{UserID},
|
|
],
|
|
);
|
|
|
|
# Get deployment ID.
|
|
my $SQL = '
|
|
SELECT id
|
|
FROM sysconfig_deployment
|
|
WHERE comments = ?
|
|
AND create_by = ?';
|
|
|
|
my @Bind = ( \$UID, \$Param{UserID} );
|
|
|
|
if ( $Param{TargetUserID} ) {
|
|
$SQL .= '
|
|
AND user_id = ?
|
|
';
|
|
push @Bind, \$Param{TargetUserID};
|
|
}
|
|
else {
|
|
$SQL .= '
|
|
AND user_id IS NULL
|
|
';
|
|
}
|
|
|
|
$SQL .= '
|
|
ORDER BY id DESC';
|
|
|
|
return if !$DBObject->Prepare(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
Limit => 1,
|
|
);
|
|
|
|
# Fetch the deployment ID.
|
|
my $DeploymentID;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
$DeploymentID = $Row[0];
|
|
}
|
|
|
|
my $CurrentDeploymentIDStr = 'CurrentDeploymentID';
|
|
if ( $Param{TargetUserID} ) {
|
|
$CurrentDeploymentIDStr = 'CurrentUserDeploymentID';
|
|
}
|
|
|
|
# Add the deployment ID to the values
|
|
${ $Param{EffectiveValueStrg} }
|
|
=~ s{( \s+ my [ ] \(\$File, [ ] \$Self\) [ ] = [ ] \@_; \s+ )}{$1\$Self->{'$CurrentDeploymentIDStr'} = '$DeploymentID';\n}msx;
|
|
|
|
# Set the real deployment value.
|
|
return if !$DBObject->Do(
|
|
SQL => '
|
|
Update sysconfig_deployment
|
|
SET comments = ?, effective_value = ?
|
|
WHERE id = ?',
|
|
Bind => [
|
|
\$Param{Comments}, \${ $Param{EffectiveValueStrg} }, \$DeploymentID,
|
|
],
|
|
);
|
|
|
|
# Remove previous user deployments (if any).
|
|
for my $DeploymentID (@UserDeploymentIDs) {
|
|
$Self->DeploymentDelete(
|
|
DeploymentID => $DeploymentID,
|
|
);
|
|
}
|
|
|
|
if ( $Param{TargetUserID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigDeployment',
|
|
Key => 'DeploymentUserList',
|
|
);
|
|
}
|
|
else {
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigDeployment',
|
|
Key => 'DeploymentList',
|
|
);
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigDeployment',
|
|
Key => 'DeploymentGetLast',
|
|
);
|
|
}
|
|
|
|
return $DeploymentID;
|
|
}
|
|
|
|
=head2 DeploymentGet()
|
|
|
|
Gets deployment information.
|
|
|
|
my %Deployment = $SysConfigDBObject->DeploymentGet(
|
|
DeploymentID => 123,
|
|
Valid => 1, # optional (this is deprecated and will be removed in next mayor release).
|
|
);
|
|
|
|
Returns:
|
|
|
|
%Deployment = (
|
|
DeploymentID => 123,
|
|
Comments => 'Some Comments',
|
|
EffectiveValueStrg => $SettingEffectiveValues, # string with the value of all settings,
|
|
# as seen in the Perl configuration file.
|
|
TargetUserID => 123, # optional (only in case of user specific deployments).
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
CreateBy => 123,
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DeploymentGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DeploymentID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need DeploymentID!",
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
my $CacheType = "SysConfigDeployment";
|
|
my $CacheKey = 'DeploymentGet::DeploymentID::' . $Param{DeploymentID};
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return %{$Cache} if ref $Cache eq 'HASH';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Get deployment from database.
|
|
return if !$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT id, comments, effective_value, user_id, create_time, create_by
|
|
FROM sysconfig_deployment
|
|
WHERE id = ?',
|
|
Bind => [ \$Param{DeploymentID} ],
|
|
);
|
|
|
|
my %Deployment;
|
|
while ( my @Data = $DBObject->FetchrowArray() ) {
|
|
|
|
%Deployment = (
|
|
DeploymentID => $Data[0],
|
|
Comments => $Data[1],
|
|
EffectiveValueStrg => $Data[2],
|
|
TargetUserID => $Data[3],
|
|
CreateTime => $Data[4],
|
|
CreateBy => $Data[5],
|
|
);
|
|
}
|
|
|
|
return if !%Deployment;
|
|
|
|
my $Valid = defined $Param{Valid} ? $Param{Valid} : 1;
|
|
|
|
if ( $Deployment{EffectiveValueStrg} eq 'Invalid' && $Valid ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "The Deployment $Param{DeploymentID} is invalid!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
$CacheObject->Set(
|
|
Type => $CacheType,
|
|
Key => $CacheKey,
|
|
Value => \%Deployment,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return %Deployment;
|
|
}
|
|
|
|
=head2 DeploymentListGet()
|
|
|
|
Get global deployment list with complete data.
|
|
|
|
my @List = $SysConfigDBObject->DeploymentListGet();
|
|
|
|
Returns:
|
|
|
|
@List = (
|
|
{
|
|
DeploymentID => 123,
|
|
Comments => 'Some Comments',
|
|
EffectiveValueStrg => $SettingEffectiveValues, # String with the value of all settings,
|
|
# as seen in the Perl configuration file.
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
CreateBy => 123,
|
|
},
|
|
{
|
|
DeploymentID => 456,
|
|
Comments => 'Some Comments',
|
|
EffectiveValueStrg => $SettingEffectiveValues2, # String with the value of all settings,
|
|
# as seen in the Perl configuration file.
|
|
CreateTime => "2016-05-29 12:00:01",
|
|
CreateBy => 123,
|
|
},
|
|
# ...
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DeploymentListGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $CacheKey = 'DeploymentList';
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => 'SysConfigDeployment',
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return @{$Cache} if ref $Cache eq 'ARRAY';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
my @Data;
|
|
return if !$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT id
|
|
FROM sysconfig_deployment
|
|
WHERE user_id IS NULL
|
|
ORDER BY id DESC',
|
|
);
|
|
|
|
my @DeploymentIDs;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
push @DeploymentIDs, $Row[0];
|
|
}
|
|
|
|
# Get deployments.
|
|
for my $ItemID (@DeploymentIDs) {
|
|
|
|
my %Deployment = $Self->DeploymentGet(
|
|
DeploymentID => $ItemID,
|
|
);
|
|
push @Data, \%Deployment;
|
|
}
|
|
|
|
$CacheObject->Set(
|
|
Type => 'SysConfigDeployment',
|
|
Key => $CacheKey,
|
|
Value => \@Data,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return @Data;
|
|
}
|
|
|
|
=head2 DeploymentUserList()
|
|
|
|
Get DeploymentID -> UserID list of all user deployments.
|
|
|
|
my %List = $SysConfigDBObject->DeploymentUserList();
|
|
|
|
Returns:
|
|
%List = {
|
|
9876 => 123,
|
|
5432 => 456,
|
|
# ...
|
|
};
|
|
|
|
=cut
|
|
|
|
sub DeploymentUserList {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $CacheKey = 'DeploymentUserList';
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => 'SysConfigDeployment',
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return @{$Cache} if ref $Cache eq 'HASH';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
my @Data;
|
|
return if !$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT id, user_id
|
|
FROM sysconfig_deployment
|
|
WHERE user_id IS NOT NULL
|
|
ORDER BY id DESC',
|
|
);
|
|
|
|
my %Data;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
$Data{ $Row[0] } = $Row[1];
|
|
}
|
|
|
|
$CacheObject->Set(
|
|
Type => 'SysConfigDeployment',
|
|
Key => $CacheKey,
|
|
Value => \@Data,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return %Data;
|
|
}
|
|
|
|
=head2 DeploymentGetLast()
|
|
|
|
Get last global deployment.
|
|
|
|
my %Deployment = $SysConfigDBObject->DeploymentGetLast();
|
|
|
|
Returns:
|
|
|
|
%Deployment = (
|
|
DeploymentID => 123,
|
|
Comments => 'Some Comments',
|
|
EffectiveValueStrg => $SettingEffectiveValues, # String with the value of all settings,
|
|
# as seen in the Perl configuration file.
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
CreateBy => 123,
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DeploymentGetLast {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $CacheKey = 'DeploymentGetLast';
|
|
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
# Return cache.
|
|
my $Cache = $CacheObject->Get(
|
|
Type => 'SysConfigDeployment',
|
|
Key => $CacheKey,
|
|
);
|
|
|
|
return %{$Cache} if ref $Cache eq 'HASH';
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
my $DeploymentID;
|
|
return if !$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT MAX(id)
|
|
FROM sysconfig_deployment
|
|
WHERE user_id IS NULL',
|
|
);
|
|
|
|
my @DeploymentID;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
$DeploymentID = $Row[0];
|
|
}
|
|
|
|
return if !$DeploymentID;
|
|
|
|
my %Deployment = $Self->DeploymentGet(
|
|
DeploymentID => $DeploymentID,
|
|
);
|
|
|
|
$CacheObject->Set(
|
|
Type => 'SysConfigDeployment',
|
|
Key => $CacheKey,
|
|
Value => \%Deployment,
|
|
TTL => $Self->{CacheTTL},
|
|
);
|
|
|
|
return %Deployment;
|
|
}
|
|
|
|
=head2 DeploymentDelete()
|
|
|
|
Delete a deployment from the database.
|
|
|
|
my $Success = $SysConfigDBObject->DeploymentDelete(
|
|
DeploymentID => 123,
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Success = 1; # or false in case of an error
|
|
|
|
=cut
|
|
|
|
sub DeploymentDelete {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DeploymentID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need DeploymentID!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my %Deployment = $Self->DeploymentGet(
|
|
DeploymentID => $Param{DeploymentID},
|
|
Valid => 0,
|
|
);
|
|
|
|
return 1 if !%Deployment;
|
|
|
|
# Delete deployment from the data base.
|
|
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
|
SQL => 'DELETE FROM sysconfig_deployment WHERE id = ?',
|
|
Bind => [ \$Param{DeploymentID} ],
|
|
);
|
|
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigDeployment',
|
|
Key => 'DeploymentGet::DeploymentID::' . $Param{DeploymentID},
|
|
);
|
|
|
|
if ( $Deployment{TargetUserID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigDeployment',
|
|
Key => 'DeploymentUserList',
|
|
);
|
|
}
|
|
else {
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigDeployment',
|
|
Key => 'DeploymentList',
|
|
);
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Delete(
|
|
Type => 'SysConfigDeployment',
|
|
Key => 'DeploymentGetLast',
|
|
);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 DeploymentLock()
|
|
|
|
Lock global deployment to a particular user.
|
|
|
|
my $ExclusiveLockGUID = $SysConfigDBObject->DeploymentLock(
|
|
UserID => 123,
|
|
ExclusiveLockGUID => $LockingString, # optional (if specific GUID is needed)
|
|
Force => 1, # Optional, locks the deployment even if is already
|
|
# locked to another user, also removes locks for
|
|
# all settings.
|
|
);
|
|
|
|
Returns:
|
|
|
|
$ExclusiveLockGUID = 'SomeLockingString'; # or false in case of an error or already locked
|
|
|
|
=cut
|
|
|
|
sub DeploymentLock {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{UserID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need UserID!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
|
|
|
|
# It's not possible to lock a deployment if a setting is locked on a valid time.
|
|
my @LockedList;
|
|
if ( $Param{Force} ) {
|
|
|
|
my $Success = $Self->DefaultSettingUnlock(
|
|
UnlockAll => 1,
|
|
);
|
|
}
|
|
else {
|
|
@LockedList = $Self->DefaultSettingListGet(
|
|
Locked => 1,
|
|
);
|
|
}
|
|
|
|
# Get current time.
|
|
my $CurrentDateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
|
|
|
|
if ( IsArrayRefWithData( \@LockedList ) ) {
|
|
LOCKED:
|
|
for my $Locked (@LockedList) {
|
|
|
|
next LOCKED if $Locked->{ExclusiveLockUserID} ne $Param{UserID};
|
|
|
|
my $LockedDateTimeObject = $Kernel::OM->Create(
|
|
'Kernel::System::DateTime',
|
|
ObjectParams => {
|
|
String => $Locked->{ExclusiveLockExpiryTime},
|
|
},
|
|
);
|
|
|
|
my $IsLocked = $LockedDateTimeObject > $CurrentDateTimeObject ? 1 : 0;
|
|
|
|
if ($IsLocked) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message =>
|
|
"It's not possible to lock a deployment if a setting is currently locked ($Locked->{Name}).",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( defined $Param{ExclusiveLockGUID} && length $Param{ExclusiveLockGUID} != 32 ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "ExclusiveLockGUID is invalid",
|
|
);
|
|
return;
|
|
}
|
|
|
|
if ( $Param{Force} ) {
|
|
my $Success = $Self->DeploymentUnlock(
|
|
All => 1,
|
|
);
|
|
}
|
|
|
|
# Check if it's already locked.
|
|
return if $Self->DeploymentIsLocked();
|
|
|
|
# If its not locked use or create a new locking string.
|
|
my $ExclusiveLockGUID = $Param{ExclusiveLockGUID} || $Kernel::OM->Get('Kernel::System::Main')->GenerateRandomString(
|
|
Length => 32,
|
|
);
|
|
|
|
my $DeploymentExpireTimeMinutes = 5;
|
|
|
|
# Set expire time.
|
|
$DateTimeObject->Add(
|
|
Minutes => $DeploymentExpireTimeMinutes,
|
|
);
|
|
my $ExpiryTime = $DateTimeObject->ToString();
|
|
|
|
my $SQL = '
|
|
INSERT INTO sysconfig_deployment_lock
|
|
( exclusive_lock_guid, exclusive_lock_user_id, exclusive_lock_expiry_time )
|
|
VALUES
|
|
( ?, ?, ? )';
|
|
|
|
my @Bind = (
|
|
\$ExclusiveLockGUID, \$Param{UserID},
|
|
\$ExpiryTime,
|
|
);
|
|
|
|
# Create db record.
|
|
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
);
|
|
|
|
return $ExclusiveLockGUID;
|
|
}
|
|
|
|
=head2 DeploymentIsLocked()
|
|
|
|
Check if global deployment is locked.
|
|
|
|
my $Locked = $SysConfigDBObject->DeploymentIsLocked();
|
|
|
|
Returns:
|
|
|
|
$Locked = 1; # or false if it is not locked
|
|
|
|
=cut
|
|
|
|
sub DeploymentIsLocked {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Get deployment lock from the DB.
|
|
my %DeploymentLock = $Self->_DeploymentLockGet();
|
|
|
|
# Return no lock if there is no locking information.
|
|
return if !%DeploymentLock;
|
|
|
|
# Return no lock if there is no lock expiry time.
|
|
return if !$DeploymentLock{ExclusiveLockExpiryTime};
|
|
|
|
# Deployment was locked, check if lock has expired.
|
|
|
|
# Get current time.
|
|
my $CurrentDateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
|
|
|
|
my $LockedDateTimeObject = $Kernel::OM->Create(
|
|
'Kernel::System::DateTime',
|
|
ObjectParams => {
|
|
String => $DeploymentLock{ExclusiveLockExpiryTime},
|
|
},
|
|
);
|
|
|
|
my $Locked = $LockedDateTimeObject > $CurrentDateTimeObject ? 1 : 0;
|
|
|
|
if ( !$Locked ) {
|
|
$Self->DeploymentUnlock(
|
|
All => 1,
|
|
);
|
|
}
|
|
|
|
return $Locked;
|
|
}
|
|
|
|
=head2 DeploymentIsLockedByUser()
|
|
|
|
Check if global deployment is locked for a determined user.
|
|
|
|
my $LockedByUser = $SysConfigDBObject->DeploymentIsLockedByUser(
|
|
ExclusiveLockGUID => $LockingString, # the GUID used to locking the deployment
|
|
UserID => 123, # the user should have locked the deployment
|
|
);
|
|
|
|
Returns:
|
|
|
|
$LockedByUser = 'SomeLockingString'; # or false in case of not locked
|
|
|
|
=cut
|
|
|
|
sub DeploymentIsLockedByUser {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Check needed stuff.
|
|
for my $Needed (qw(UserID ExclusiveLockGUID)) {
|
|
if ( !$Param{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
return if !IsStringWithData( $Param{ExclusiveLockGUID} );
|
|
|
|
# ExclusiveLockGUID should not be 0
|
|
return if !$Param{ExclusiveLockGUID};
|
|
|
|
# Get deployment lock from the DB.
|
|
my %DeploymentLock = $Self->_DeploymentLockGet();
|
|
|
|
# Return no lock if there is no locking information.
|
|
return if !%DeploymentLock;
|
|
|
|
# Return no lock if there is no lock expiry time.
|
|
return if !$DeploymentLock{ExclusiveLockExpiryTime};
|
|
|
|
# Check ExclusiveLockUserID
|
|
return if $DeploymentLock{ExclusiveLockUserID} ne $Param{UserID};
|
|
|
|
# Check ExclusiveLockGUID
|
|
return if !$DeploymentLock{ExclusiveLockGUID};
|
|
return if $DeploymentLock{ExclusiveLockGUID} ne $Param{ExclusiveLockGUID};
|
|
|
|
my $ExclusiveLockGUID = $DeploymentLock{ExclusiveLockGUID};
|
|
|
|
# If deployment was locked, check if lock has expired.
|
|
my $CurrentDateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
|
|
|
|
my $LockedDateTimeObject = $Kernel::OM->Create(
|
|
'Kernel::System::DateTime',
|
|
ObjectParams => {
|
|
String => $DeploymentLock{ExclusiveLockExpiryTime},
|
|
},
|
|
);
|
|
|
|
my $Locked = $LockedDateTimeObject > $CurrentDateTimeObject ? 1 : 0;
|
|
|
|
# Extend the time if it was already locked for the user but time has been expired
|
|
if ( !$Locked ) {
|
|
$ExclusiveLockGUID = $Self->DeploymentLock(
|
|
UserID => $Param{UserID},
|
|
ExclusiveLockGUID => $Param{ExclusiveLockGUID},
|
|
);
|
|
|
|
return if !$ExclusiveLockGUID;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 DeploymentModifiedVersionList()
|
|
|
|
Return a list of modified versions for a global deployment based on the deployment time. Limited
|
|
to a particular deployment or including also all previous deployments
|
|
|
|
my %ModifiedVersionList = $SysConfigDBObject->DeploymentModifiedVersionList(
|
|
DeploymentID => 123, # the deployment id
|
|
Mode => 'Equals' # (optional) default 'Equals'
|
|
# Equals: only the settings from the given deployment
|
|
# GreaterThan: only the settings after the given deployment
|
|
# GreaterThanEquals: includes the settings of the given deployment and after
|
|
# SmallerThan: only the settings before the given deployment
|
|
# SmallerThanEquals: includes the settings of the given deployment and before
|
|
);
|
|
|
|
Returns:
|
|
|
|
%ModifiedVersionIDs = (
|
|
123 => 'Setting1',
|
|
124 => 'Setting2',
|
|
125 => 'Setting3'
|
|
);
|
|
|
|
=cut
|
|
|
|
sub DeploymentModifiedVersionList {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
if ( !$Param{DeploymentID} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need DeploymentID!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $Mode = $Param{Mode} // 'Equals';
|
|
my %ModeMapping = (
|
|
Equals => '=',
|
|
GreaterThan => '>',
|
|
GreaterThanEquals => '>=',
|
|
SmallerThan => '<',
|
|
SmallerThanEquals => '<=',
|
|
);
|
|
if ( !$ModeMapping{$Mode} ) {
|
|
$Self->{LogObject}->Log(
|
|
Priority => 'error',
|
|
Message => "Mode $Mode is invalid!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
my %Deployment = $Self->DeploymentGet(
|
|
DeploymentID => $Param{DeploymentID},
|
|
);
|
|
return if !IsHashRefWithData( \%Deployment );
|
|
return if $Deployment{TargetUserID};
|
|
|
|
my $CreateTime = $Deployment{CreateTime} || '';
|
|
return if !$CreateTime;
|
|
|
|
my $SQL = "
|
|
SELECT max(smv.id) id, smv.name
|
|
FROM sysconfig_modified_version smv
|
|
WHERE smv.create_time $ModeMapping{$Mode} ?
|
|
GROUP BY smv.name";
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
return if !$DBObject->Prepare(
|
|
SQL => $SQL,
|
|
Bind => [ \$CreateTime, ]
|
|
);
|
|
|
|
my %ModifiedVersionList;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
$ModifiedVersionList{ $Row[0] } = $Row[1];
|
|
}
|
|
|
|
return %ModifiedVersionList;
|
|
|
|
}
|
|
|
|
=head2 DeploymentUnlock()
|
|
|
|
Unlock global deployment.
|
|
|
|
my $Success = $SysConfigDBObject->DeploymentUnlock(
|
|
ExclusiveLockGUID => '12ad34f21b',
|
|
UserID => 123,
|
|
);
|
|
|
|
or
|
|
|
|
my $Success = $SysConfigDBObject->DeploymentUnlock(
|
|
All => 1,
|
|
);
|
|
|
|
Returns:
|
|
|
|
$Success = 1; # or false in case of an error
|
|
|
|
=cut
|
|
|
|
sub DeploymentUnlock {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Check needed
|
|
if ( !$Param{ExclusiveLockGUID} && !$Param{UserID} && !$Param{All} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'All or ExclusiveLockGUID and UserID are needed!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
if ( ( $Param{ExclusiveLockGUID} && !$Param{UserID} ) || ( $Param{UserID} && !$Param{ExclusiveLockGUID} ) ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'ExclusiveLockGUID and UserID are needed!',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $SQL = 'DELETE FROM sysconfig_deployment_lock';
|
|
my @Bind;
|
|
|
|
if ( $Param{ExclusiveLockGUID} ) {
|
|
$SQL .= '
|
|
WHERE exclusive_lock_guid = ?
|
|
AND exclusive_lock_user_id = ?';
|
|
|
|
@Bind = ( \$Param{ExclusiveLockGUID}, \$Param{UserID} );
|
|
}
|
|
|
|
# Update db record.
|
|
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
);
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 DeploymentListCleanup()
|
|
|
|
Removes invalid deployments from the database.
|
|
|
|
my $Success = $SysConfigDBObject->DeploymentListCleanup( );
|
|
|
|
Returns:
|
|
|
|
$Success = 1; # Returns 1 if all records are valid (or all invalid was removed)
|
|
# Returns -1 if there is an invalid deployment that could be in adding process
|
|
# Returns false in case of an error
|
|
|
|
=cut
|
|
|
|
sub DeploymentListCleanup {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
return if !$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT id, create_time
|
|
FROM sysconfig_deployment
|
|
WHERE effective_value LIKE \'Invalid%\'
|
|
OR comments LIKE \'OTRSInvalid-%\'
|
|
ORDER BY id DESC',
|
|
);
|
|
|
|
my @Deployments;
|
|
while ( my @Row = $DBObject->FetchrowArray() ) {
|
|
my %Deployment = (
|
|
DeploymentID => $Row[0],
|
|
CreateTime => $Row[1],
|
|
);
|
|
push @Deployments, \%Deployment;
|
|
}
|
|
|
|
my $Success = 1;
|
|
my $CurrentDateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
|
|
|
|
DEPLOYMENT:
|
|
for my $Deployment (@Deployments) {
|
|
|
|
my $DeploymentDateTimeObject = $Kernel::OM->Create(
|
|
'Kernel::System::DateTime',
|
|
ObjectParams => {
|
|
String => $Deployment->{CreateTime},
|
|
},
|
|
);
|
|
|
|
my $Delta = $CurrentDateTimeObject->Delta( DateTimeObject => $DeploymentDateTimeObject );
|
|
|
|
# Remove deployment only if it is old (more than 20 secs)
|
|
if ( $DeploymentDateTimeObject < $CurrentDateTimeObject && $Delta >= 20 ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Deployment $Deployment->{DeploymentID} is invalid and will be removed!",
|
|
);
|
|
my $DeleteSuccess = $Self->DeploymentDelete(
|
|
DeploymentID => $Deployment->{DeploymentID},
|
|
);
|
|
if ( !$DeleteSuccess ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Could not delete deployment $Deployment->{DeploymentID}",
|
|
);
|
|
$Success = 0;
|
|
}
|
|
last DEPLOYMENT;
|
|
}
|
|
|
|
# Otherwise just log that there is something wrong with the deployment but do not remove it
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Deployment $Deployment->{DeploymentID} seams to be invalid or its not fully updated",
|
|
);
|
|
$Success = -1;
|
|
}
|
|
|
|
return $Success;
|
|
}
|
|
|
|
=head1 PRIVATE INTERFACE
|
|
|
|
=head2 _DeploymentLockGet()
|
|
|
|
Get deployment lock entry.
|
|
|
|
my %DeploymentLock = $SysConfigDBObject->_DeploymentLockGet();
|
|
|
|
Returns:
|
|
|
|
%DeploymentLock = (
|
|
DeploymentLoclID => "123",
|
|
ExclusiveLockGUID => $LockingString,
|
|
ExclusiveLockUserID => 1,
|
|
ExclusiveLockExpiryTime => '2016-05-29 11:09:04',
|
|
CreateTime => "2016-05-29 11:04:04",
|
|
);
|
|
|
|
=cut
|
|
|
|
sub _DeploymentLockGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Get deployment lock from the DB.
|
|
return if !$DBObject->Prepare(
|
|
SQL => '
|
|
SELECT id, exclusive_lock_guid, exclusive_lock_user_id, exclusive_lock_expiry_time
|
|
FROM sysconfig_deployment_lock
|
|
ORDER BY exclusive_lock_expiry_time DESC',
|
|
Limit => 1,
|
|
);
|
|
|
|
my %DeploymentLock;
|
|
while ( my @Data = $DBObject->FetchrowArray() ) {
|
|
$DeploymentLock{ID} = $Data[0];
|
|
$DeploymentLock{ExclusiveLockGUID} = $Data[1];
|
|
$DeploymentLock{ExclusiveLockUserID} = $Data[2];
|
|
$DeploymentLock{ExclusiveLockExpiryTime} = $Data[3];
|
|
}
|
|
|
|
return %DeploymentLock;
|
|
}
|
|
|
|
=head2 _BulkInsert()
|
|
|
|
Add batch entries to the DB into a given table.
|
|
|
|
my $Success = $SysConfigDBObject->_BulkInsert(
|
|
Table => 'table_name', # (required) Table name
|
|
Columns => [ # (required) Array of column names
|
|
'column_name',
|
|
...
|
|
],
|
|
Data => [ # (required) AoA with data
|
|
[
|
|
'record 1',
|
|
'record 2',
|
|
],
|
|
[
|
|
...
|
|
],
|
|
...
|
|
],
|
|
);
|
|
|
|
=cut
|
|
|
|
sub _BulkInsert {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
for my $Needed (qw(Table)) {
|
|
if ( !$Param{$Needed} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need $Needed!",
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
for my $Parameter (qw(Columns Data)) {
|
|
if ( !IsArrayRefWithData( $Param{Columns} ) ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "$Parameter must be not empty array!"
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Get the database type.
|
|
my $DBType = $DBObject->GetDatabaseFunction('Type');
|
|
|
|
# Define database specific SQL for the multi-line inserts.
|
|
my %DatabaseSQL;
|
|
|
|
my $Columns = join( ',', @{ $Param{Columns} } );
|
|
|
|
# Check the first array in Data and create Mask (current_timestamp is always on same place in array).
|
|
my @Mask = map {
|
|
( $_ && $_ eq 'current_timestamp' )
|
|
? 'current_timestamp' : '?'
|
|
} @{ $Param{Data}->[0] };
|
|
|
|
my $MaskedValues = join( ',', @Mask );
|
|
|
|
if ( $DBType eq 'oracle' ) {
|
|
|
|
%DatabaseSQL = (
|
|
Start => 'INSERT ALL ',
|
|
FirstLine => "
|
|
INTO $Param{Table} ($Columns)
|
|
VALUES ( $MaskedValues ) ",
|
|
NextLine => "
|
|
INTO $Param{Table} (
|
|
$Columns
|
|
)
|
|
VALUES ( $MaskedValues ) ",
|
|
End => 'SELECT * FROM DUAL',
|
|
);
|
|
}
|
|
else {
|
|
%DatabaseSQL = (
|
|
Start => "
|
|
INSERT INTO $Param{Table} (
|
|
$Columns
|
|
)",
|
|
FirstLine => "VALUES ( $MaskedValues )",
|
|
NextLine => ", ( $MaskedValues ) ",
|
|
End => '',
|
|
);
|
|
}
|
|
|
|
my $SQL = '';
|
|
my @Bind;
|
|
|
|
my $Count = 0;
|
|
|
|
RECORD:
|
|
for my $Entry ( @{ $Param{Data} } ) {
|
|
|
|
$Count++;
|
|
|
|
if ( !IsArrayRefWithData($Entry) ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Data contains empty array, skipped!"
|
|
);
|
|
next RECORD;
|
|
}
|
|
|
|
if ( scalar @{$Entry} != scalar @{ $Param{Columns} } ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Array size doesn't match Columns size, skipped!"
|
|
);
|
|
my $Col = scalar @{ $Param{Columns} };
|
|
next RECORD;
|
|
}
|
|
|
|
# Now the article entry is validated and can be added to sql.
|
|
if ( !$SQL ) {
|
|
$SQL = $DatabaseSQL{Start} . $DatabaseSQL{FirstLine};
|
|
}
|
|
else {
|
|
$SQL .= $DatabaseSQL{NextLine};
|
|
}
|
|
|
|
BIND:
|
|
for my $Item ( @{$Entry} ) {
|
|
|
|
next BIND if ( $Item && $Item eq 'current_timestamp' ); # Already included in the SQL part.
|
|
|
|
push @Bind, \$Item;
|
|
}
|
|
|
|
# Check the length of the SQL string
|
|
# (some databases only accept SQL strings up to 4k,
|
|
# so we want to stay safe here with just 3500 bytes).
|
|
if ( length $SQL > 3500 || $Count == scalar @{ $Param{Data} } ) {
|
|
|
|
# Add the end line to sql string.
|
|
$SQL .= $DatabaseSQL{End};
|
|
|
|
# Insert multiple entries.
|
|
return if !$DBObject->Do(
|
|
SQL => $SQL,
|
|
Bind => \@Bind,
|
|
);
|
|
|
|
# Reset the SQL string and the Bind array.
|
|
$SQL = '';
|
|
@Bind = ();
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
=head2 _GetUID()
|
|
|
|
Generates a unique identifier.
|
|
|
|
my $UID = $TicketNumberObject->_GetUID();
|
|
|
|
Returns:
|
|
|
|
my $UID = 14906327941360ed8455f125d0450277;
|
|
|
|
=cut
|
|
|
|
sub _GetUID {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $NodeID = $Kernel::OM->Get('Kernel::Config')->Get('NodeID') || 1;
|
|
my ( $Seconds, $Microseconds ) = Time::HiRes::gettimeofday();
|
|
my $ProcessID = $$;
|
|
|
|
my $CounterUID = $ProcessID . $Seconds . $Microseconds . $NodeID;
|
|
|
|
my $RandomString = $Kernel::OM->Get('Kernel::System::Main')->GenerateRandomString(
|
|
Length => 32 - length $CounterUID,
|
|
Dictionary => [ 0 .. 9, 'a' .. 'f' ], # hexadecimal
|
|
);
|
|
|
|
$CounterUID .= $RandomString;
|
|
|
|
return $CounterUID;
|
|
}
|
|
|
|
1;
|
|
|
|
=head1 TERMS AND CONDITIONS
|
|
|
|
This software is part of the OTRS project (L<https://otrs.org/>).
|
|
|
|
This software comes with ABSOLUTELY NO WARRANTY. For details, see
|
|
the enclosed file COPYING for license information (GPL). If you
|
|
did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>.
|
|
|
|
=cut
|