Files
scripts/Perl OTRS/Kernel/System/SysConfig/Base/Framework.pm
2024-10-14 00:08:40 +02:00

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