# --
# 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::Base::Framework;
use strict;
use warnings;
use Kernel::System::VariableCheck qw(:all);
our @ObjectDependencies = (
'Kernel::System::Log',
'Kernel::System::Main',
'Kernel::System::Storable',
);
=head1 NAME
Kernel::System::SysConfig::Base::Framework - Base class for system configuration.
=head1 PUBLIC INTERFACE
=head2 SettingModifiedXMLContentParsedGet()
Returns perl structure for modified setting.
my $Result = $SysConfigObject->SettingModifiedXMLContentParsedGet(
ModifiedSetting => {
EffectiveValue => 'Scalar value updated'
},
DefaultSetting => {
XMLContentParsed => {
Value => [
{
'Item' => [
{
'Content' => "Scalar value",
},
],
},
],
},
},
);
Returns:
$Result = [
{
'Item' => [
{
'Content' => "Scalar value updated",
},
],
},
];
=cut
sub SettingModifiedXMLContentParsedGet {
my ( $Self, %Param ) = @_;
for my $Needed (qw(DefaultSetting ModifiedSetting)) {
if ( !$Param{$Needed} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Needed!"
);
return;
}
}
my $Result = $Param{DefaultSetting}->{XMLContentParsed};
$Result = $Self->_ModifiedValueCalculate(
Value => $Result->{Value},
EffectiveValue => $Param{ModifiedSetting}->{EffectiveValue},
);
return $Result;
}
=head1 PRIVATE INTERFACE
=head2 _ModifiedValueCalculate()
Recursive helper for SettingModifiedXMLContentParsedGet().
my $Result = $SysConfigObject->_ModifiedValueCalculate(
'EffectiveValue' => 'Scalar value updated', # (optional) new effective value
'Value' => [ # (required) the XMLContentParsed value from Defaults
{
'Item' => [
{
'Content' => 'Scalar value',
},
],
},
],
);
Returns:
$Result = [
{
'Item' => [
{
'Content' => 'Scalar value updated'
},
],
},
];
=cut
sub _ModifiedValueCalculate {
my ( $Self, %Param ) = @_;
for my $Needed (qw(Value)) {
if ( !$Param{$Needed} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Needed!"
);
return;
}
}
my %Objects;
if ( $Param{Objects} ) {
%Objects = %{ $Param{Objects} };
}
my @SkipParameters = (
'Hash',
'Array',
'Item',
'Content',
'Key',
);
my $Result;
my $ValueType;
# Check if additional parameters are provided.
if ( IsHashRefWithData( $Param{Parameters} ) && $Param{Value}->[0]->{Item} ) {
for my $Parameter ( sort keys %{ $Param{Parameters} } ) {
$Result->[0]->{Item}->[0]->{$Parameter} = $Param{Parameters}->{$Parameter};
}
}
if (
$Param{Value}->[0]->{Item}
&& $Param{Value}->[0]->{Item}->[0]->{ValueType}
)
{
$ValueType = $Param{Value}->[0]->{Item}->[0]->{ValueType};
}
if ( $Param{ValueType} ) {
$ValueType = $Param{ValueType};
}
if ($ValueType) {
if ( !$Objects{$ValueType} ) {
# Make sure the ValueType backed is present and is syntactically correct.
my $Loaded = $Kernel::OM->Get('Kernel::System::Main')->Require(
"Kernel::System::SysConfig::ValueType::$ValueType",
);
return $Result if !$Loaded;
# Create object instance.
$Objects{$ValueType} = $Kernel::OM->Get(
"Kernel::System::SysConfig::ValueType::$ValueType",
);
}
$Result = $Objects{$ValueType}->ModifiedValueGet(%Param);
# Get all additional parameters (defined as attributes in XML).
if ( IsHashRefWithData( $Param{Value}->[0]->{Item}->[0] ) ) {
PARAMETER:
for my $Parameter ( sort keys %{ $Param{Value}->[0]->{Item}->[0] } ) {
next PARAMETER if grep { $_ eq $Parameter } @SkipParameters;
# Skip already defined values.
next PARAMETER if $Result->[0]->{Item}->[0]->{$Parameter};
$Result->[0]->{Item}->[0]->{$Parameter} =
$Param{Value}->[0]->{Item}->[0]->{$Parameter};
}
}
}
elsif ( ref $Param{EffectiveValue} eq 'ARRAY' ) {
# Create basic structure.
$Result = [
{
'Array' => [
{
'Item' => [],
},
],
},
];
my $DefaultItem = $Param{Value}->[0]->{Array}->[0]->{DefaultItem};
if ( $Param{Value}->[0]->{Array}->[0]->{MinItems} ) {
$Result->[0]->{Array}->[0]->{MinItems} = $Param{Value}->[0]->{Array}->[0]->{MinItems};
}
if ( $Param{Value}->[0]->{Array}->[0]->{MaxItems} ) {
$Result->[0]->{Array}->[0]->{MaxItems} = $Param{Value}->[0]->{Array}->[0]->{MaxItems};
}
my %Attributes;
if (
$DefaultItem
&& ref $DefaultItem eq 'ARRAY'
&& scalar @{$DefaultItem}
&& ref $DefaultItem->[0] eq 'HASH'
)
{
# Get additional attributes
ATTRIBUTE:
for my $Attribute ( sort keys %{ $DefaultItem->[0] } ) {
next ATTRIBUTE if grep { $Attribute eq $_ } qw(Hash Array Item Content);
$Attributes{$Attribute} = $DefaultItem->[0]->{$Attribute};
}
}
for my $Index ( 0 .. scalar @{ $Param{EffectiveValue} } - 1 ) {
if (
$DefaultItem
&& $DefaultItem->[0]->{ValueType}
&& $Param{Value}->[0]->{Array}->[0]->{Item}
)
{
# It's Item with defined ValueType.
my $ItemData = $Kernel::OM->Get('Kernel::System::Storable')->Clone(
Data => $DefaultItem,
);
my $Value = $Self->_ModifiedValueCalculate(
Value => [
{
Item => $ItemData,
},
],
EffectiveValue => $Param{EffectiveValue}->[$Index],
ValueType => $Param{Value}->[0]->{Array}->[0]->{ValueType},
Objects => \%Objects,
);
push @{ $Result->[0]->{Array}->[0]->{Item} }, $Value->[0];
}
elsif (
$DefaultItem
&& ( $DefaultItem->[0]->{Array} || $DefaultItem->[0]->{Hash} )
)
{
# It's complex structure (AoA or AoH), continue recursion.
my $StructureType = $DefaultItem->[0]->{Array} ? 'Array' : 'Hash';
$Param{Value}->[0]->{Array}->[0]->{Item}->[0]->{$StructureType}->[0]->{DefaultItem} =
$DefaultItem->[0]->{$StructureType}->[0]->{DefaultItem};
my $Value = $Self->_ModifiedValueCalculate(
Value => $Param{Value}->[0]->{Array}->[0]->{Item},
EffectiveValue => $Param{EffectiveValue}->[$Index],
Objects => \%Objects,
);
push @{ $Result->[0]->{Array}->[0]->{Item} }, $Value->[0];
}
else {
if ( IsArrayRefWithData( $Param{EffectiveValue}->[$Index] ) ) {
for my $ArrayItem ( @{ $Param{EffectiveValue}->[$Index] } ) {
push @{ $Result->[0]->{Array}->[0]->{Item} }, {
%Attributes,
Content => $ArrayItem,
};
}
}
else {
# This is a string value.
push @{ $Result->[0]->{Array}->[0]->{Item} }, {
%Attributes,
Content => $Param{EffectiveValue}->[$Index],
};
}
}
}
}
elsif ( ref $Param{EffectiveValue} eq 'HASH' ) {
# Create basic structure.
$Result = [
{
'Hash' => [
{
'Item' => [],
},
],
}
];
if ( $Param{Value}->[0]->{Hash}->[0]->{MinItems} ) {
$Result->[0]->{Hash}->[0]->{MinItems} = $Param{Value}->[0]->{Hash}->[0]->{MinItems};
}
if ( $Param{Value}->[0]->{Hash}->[0]->{MaxItems} ) {
$Result->[0]->{Hash}->[0]->{MaxItems} = $Param{Value}->[0]->{Hash}->[0]->{MaxItems};
}
my $DefaultItem;
my %Attributes;
for my $Key ( sort keys %{ $Param{EffectiveValue} } ) {
%Attributes = ();
$DefaultItem = $Param{Value}->[0]->{Hash}->[0]->{DefaultItem};
if ( $Param{Value}->[0]->{Hash}->[0]->{Item} ) {
my @ItemWithSameKey = grep { $Key eq ( $Param{Value}->[0]->{Hash}->[0]->{Item}->[$_]->{Key} || '' ) }
0 .. scalar @{ $Param{Value}->[0]->{Hash}->[0]->{Item} } - 1;
if ( scalar @ItemWithSameKey ) {
if (
$DefaultItem
&& !$Param{Value}->[0]->{Hash}->[0]->{Item}->[ $ItemWithSameKey[0] ]->{ValueType}
&& $DefaultItem->[0]->{ValueType}
)
{
# update hash
for my $DefaultKey (
sort keys %{ $Param{Value}->[0]->{Hash}->[0]->{Item}->[ $ItemWithSameKey[0] ] }
)
{
$DefaultItem->[0]->{$DefaultKey}
= $Param{Value}->[0]->{Hash}->[0]->{Item}->[ $ItemWithSameKey[0] ]->{$DefaultKey};
}
}
else {
$DefaultItem = [
$Param{Value}->[0]->{Hash}->[0]->{Item}->[ $ItemWithSameKey[0] ],
];
}
}
}
if (
$DefaultItem
&& ref $DefaultItem eq 'ARRAY'
&& scalar @{$DefaultItem}
&& ref $DefaultItem->[0] eq 'HASH'
)
{
# Get additional attributes
ATTRIBUTE:
for my $Attribute ( sort keys %{ $DefaultItem->[0] } ) {
next ATTRIBUTE if grep { $Attribute eq $_ } qw(Hash Array Content Key);
if ( $Attribute eq 'Item' ) {
if (
!$DefaultItem->[0]->{Item}->[0]->{ValueType}
|| $DefaultItem->[0]->{Item}->[0]->{ValueType} ne 'Option'
)
{
next ATTRIBUTE;
}
}
$Attributes{$Attribute} = $DefaultItem->[0]->{$Attribute};
}
}
if (
$DefaultItem
&& !$DefaultItem->[0]->{Content}
&& $Param{Value}->[0]->{Hash}->[0]->{Item}
&& scalar @{ $Param{Value}->[0]->{Hash}->[0]->{Item} }
&& $Param{Value}->[0]->{Hash}->[0]->{Item}->[0]->{Item}
)
{
# It's Item with defined ValueType.
my $ItemData = $Kernel::OM->Get('Kernel::System::Storable')->Clone(
Data => $DefaultItem,
);
ATTRIBUTE:
for my $Attribute ( sort keys %Attributes ) {
next ATTRIBUTE if defined $ItemData->[0]->{$Attribute};
$ItemData->[0]->{$Attribute} = $Attributes{$Attribute};
}
if (
!$ItemData->[0]->{Item}
|| ( $ItemData->[0]->{Item} && !$ItemData->[0]->{Item}->[0]->{ValueType} )
)
{
$ItemData->[0]->{ValueType} //= 'String';
}
my $Value = $Self->_ModifiedValueCalculate(
Value => $ItemData,
EffectiveValue => $Param{EffectiveValue}->{$Key},
ValueType => $DefaultItem->[0]->{ValueType},
Objects => \%Objects,
);
$Value->[0]->{Key} = $Key;
push @{ $Result->[0]->{Hash}->[0]->{Item} }, $Value->[0];
}
elsif (
$DefaultItem
&& ( $DefaultItem->[0]->{Array} || $DefaultItem->[0]->{Hash} )
)
{
# It's complex structure (HoA or HoH), continue recursion.
my $StructureType = $DefaultItem->[0]->{Array} ? 'Array' : 'Hash';
my ($SubValue)
= grep { defined $_->{Key} && $_->{Key} eq $Key } @{ $Param{Value}->[0]->{Hash}->[0]->{Item} };
if (
$Param{Value}->[0]->{Hash}->[0]->{DefaultItem}
&& $Param{Value}->[0]->{Hash}->[0]->{DefaultItem}->[0]->{$StructureType}
)
{
$SubValue->{$StructureType}->[0]->{DefaultItem} =
$Param{Value}->[0]->{Hash}->[0]->{DefaultItem}->[0]->{$StructureType}->[0]->{DefaultItem};
}
my $Value = $Self->_ModifiedValueCalculate(
Value => [$SubValue],
EffectiveValue => $Param{EffectiveValue}->{$Key},
Objects => \%Objects,
);
$Value->[0]->{Key} = $Key;
if ( $SubValue->{$StructureType}->[0]->{DefaultItem} ) {
$Value->[0]->{$StructureType}->[0]->{DefaultItem} = $SubValue->{$StructureType}->[0]->{DefaultItem};
}
push @{ $Result->[0]->{Hash}->[0]->{Item} }, $Value->[0];
}
else {
# This is a scaler value.
my $ValueAttribute = "Content"; # by default
my $ValueType = $Attributes{ValueType};
if ($ValueType) {
if ( !$Objects{$ValueType} ) {
# Make sure the ValueType backed is present and is syntactically correct.
my $Loaded = $Kernel::OM->Get('Kernel::System::Main')->Require(
"Kernel::System::SysConfig::ValueType::$ValueType",
);
if ($Loaded) {
# Create object instance.
$Objects{$ValueType} = $Kernel::OM->Get(
"Kernel::System::SysConfig::ValueType::$ValueType",
);
}
}
$ValueAttribute = $Objects{$ValueType}->ValueAttributeGet();
}
push @{ $Result->[0]->{Hash}->[0]->{Item} }, {
%Attributes,
Key => $Key,
$ValueAttribute => $Param{EffectiveValue}->{$Key},
};
}
}
}
else {
# This is a scaler value.
$Result = [
{
Item => [
{
Content => $Param{EffectiveValue},
},
],
},
];
# Get all additional parameters (defined as attributes in XML).
if ( IsHashRefWithData( $Param{Value}->[0]->{Item}->[0] ) ) {
PARAMETER:
for my $Parameter ( sort keys %{ $Param{Value}->[0]->{Item}->[0] } ) {
next PARAMETER if grep { $_ eq $Parameter } @SkipParameters;
$Result->[0]->{Item}->[0]->{$Parameter} =
$Param{Value}->[0]->{Item}->[0]->{$Parameter};
}
}
}
return $Result;
}
1;
=head1 TERMS AND CONDITIONS
This software is part of the OTRS project (L).
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.
=cut