540 lines
17 KiB
Perl
540 lines
17 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::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<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
|