# --
# 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::GenericInterface::Operation::ConfigItem::Common;
use strict;
use warnings;
use MIME::Base64();
use Kernel::System::VariableCheck qw(:all);
our $ObjectManagerDisabled = 1;
=head1 NAME
Kernel::GenericInterface::Operation::ConfigItem::Common - Base class for all CI Operations
=head1 PUBLIC INTERFACE
=cut
=head2 Init()
initialize the operation by checking the web-service configuration
my $Return = $CommonObject->Init(
WebserviceID => 1,
);
$Return = {
Success => 1, # or 0 in case of failure,
ErrorMessage => 'Error Message',
}
=cut
sub Init {
my ( $Self, %Param ) = @_;
# check needed
if ( !$Param{WebserviceID} ) {
return {
Success => 0,
ErrorMessage => "Got no WebserviceID!",
};
}
# get webservice configuration
my $Webservice = $Kernel::OM->Get('Kernel::System::GenericInterface::Webservice')->WebserviceGet(
ID => $Param{WebserviceID},
);
if ( !IsHashRefWithData($Webservice) ) {
return {
Success => 0,
ErrorMessage =>
'Could not determine Web service configuration'
. ' in Kernel::GenericInterface::Operation::ConfigItem::Common::new()',
};
}
return {
Success => 1,
};
}
=head2 ValidateClass()
checks if the given Class is valid.
my $Sucess = $CommonObject->ValidateClass(
Class => 'some class',
);
returns
$Success = 1 # or 0
=cut
sub ValidateClass {
my ( $Self, %Param ) = @_;
# check needed stuff
return if !$Param{Class};
# check for Class sent
my $ItemDataRef = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemGet(
Class => 'ITSM::ConfigItem::Class',
Name => $Param{Class},
);
# return false if item data is empty
return if !IsHashRefWithData($ItemDataRef);
return 1;
}
=head2 ValidateDeplState()
checks if the given DeplState is valid.
my $Sucess = $CommonObject->ValidateDeplState(
DelpState => 'some DeplState',
);
returns
$Success = 1 # or 0
=cut
sub ValidateDeplState {
my ( $Self, %Param ) = @_;
# check needed stuff
return if !$Param{DeplState};
# check for Class sent
my $ItemDataRef = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemGet(
Class => 'ITSM::ConfigItem::DeploymentState',
Name => $Param{DeplState},
);
# return false if item data is empty
return if !IsHashRefWithData($ItemDataRef);
return 1;
}
=head2 ValidateInciState()
checks if the given InciState is valid.
my $Sucess = $CommonObject->ValidateInciState(
InciState => 'some InciState',
);
returns
$Success = 1 # or 0
=cut
sub ValidateInciState {
my ( $Self, %Param ) = @_;
# check needed stuff
return if !$Param{InciState};
# check for Class sent
my $ItemDataRef = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemGet(
Class => 'ITSM::Core::IncidentState',
Name => $Param{InciState},
);
# return false if item data is empty
return if !IsHashRefWithData($ItemDataRef);
return 1;
}
=head2 ValidateInputText()
checks if the given value is valid.
my $Sucess = $CommonObject->ValidateInputText(
Value => 'some value',
MaxLength => 123,
);
returns
$Success = 1 # or 0
=cut
sub ValidateInputText {
my ( $Self, %Param ) = @_;
# check length
if (
defined $Param{Input}->{MaxLength}
&& $Param{Input}->{MaxLength}
&& length $Param{Value} > $Param{Input}->{MaxLength}
)
{
return;
}
return 1;
}
=head2 ValidateInputDate()
checks if the given value is valid.
my $Sucess = $CommonObject->ValidateInputDate(
Value => '12/12/1977',
);
or
my $Sucess = $CommonObject->ValidateInputDate(
Value => '1977-12-12',
);
returns
$Success = 1 # or 0
=cut
sub ValidateInputDate {
my ( $Self, %Param ) = @_;
my $Value = $Param{Value};
# check and convert for date format like "05/18/2011"
if ( $Value =~ m{\A (\d{2}) / (\d{2}) / (\d{4}) \z}xms ) {
$Value = $3 . '-' . $1 . '-' . $2 . ' 00:00:00';
}
# check and convert for date format like "2011-05-18"
if ( $Value =~ m{\A (\d{4} - \d{2} - \d{2} \z) }xms ) {
$Value = $1 . ' 00:00:00';
}
# Convert the raw data to a system datetime object.
my $DateTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Value,
},
);
return if !$DateTimeObject;
return 1;
}
=head2 ValidateInputDateTime()
checks if the given value is valid.
my $Sucess = $CommonObject->ValidateInputDateTime(
Value => '12/12/1977 12:00:00',
);
or
my $Sucess = $CommonObject->ValidateInputDateTime(
Value => '1977-12-12 12:00:00',
);
returns
$Success = 1 # or 0
=cut
sub ValidateInputDateTime {
my ( $Self, %Param ) = @_;
my $Value = $Param{Value};
# check and convert for date format like "05/18/2011"
if ( $Value =~ m{\A (\d{2}) / (\d{2}) / (\d{4}) \z}xms ) {
$Value = $3 . '-' . $1 . '-' . $2 . ' 00:00:00';
}
elsif ( $Value =~ m{\A (\d{2}) / (\d{2}) / (\d{4}) (\d{2} : \d{2} : \d{2}) \z}xms ) {
$Value = $3 . '-' . $1 . '-' . $2 . $4;
}
# check and convert for date format like "2011-05-18"
if ( $Value =~ m{\A (\d{4} - \d{2} - \d{2} \z) }xms ) {
$Value = $1 . ' 00:00:00';
}
# Convert the raw data to a system datetime object.
my $DateTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Value,
},
);
return if !$DateTimeObject;
return 1;
}
=head2 ValidateInputInteger()
checks if the given value is valid.
my $Sucess = $CommonObject->ValidateInputInteger(
Value => 123,
);
returns
$Success = 1 # or 0
=cut
sub ValidateInputInteger {
my ( $Self, %Param ) = @_;
my $Value = $Param{Value};
return if !IsInteger($Value);
return if defined $Param{ValueMin} && $Value < $Param{ValueMin};
return if defined $Param{ValueMax} && $Value > $Param{ValueMax};
return 1;
}
=head2 ValidateInputGeneralCatalog()
checks if the given value is valid.
my $Sucess = $CommonObject->ValidateInputGeneralCatalog(
Value => 123,
Class => 'Some general catalog class'
);
returns
$Success = 1 # or 0
=cut
sub ValidateInputGeneralCatalog {
my ( $Self, %Param ) = @_;
my $Value = $Param{Value};
# get the values for the General catalog class
my $ItemList = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemList(
Class => $Param{Input}->{Class},
);
# create a lokup list
my %ItemListLookup = reverse %{$ItemList};
return if !$ItemListLookup{$Value};
return 1;
}
=head2 ValidateInputCustomer()
checks if the given value is valid.
my $Sucess = $CommonObject->ValidateInputCustomer(
Value => 'some customer login',
);
returns
$Success = 1 # or 0
=cut
sub ValidateInputCustomer {
my ( $Self, %Param ) = @_;
my $Value = $Param{Value};
return if !$Value;
my %CustomerData = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerUserDataGet(
User => $Param{Value},
);
# if customer is not registered in the database
return if !IsHashRefWithData( \%CustomerData );
# if ValidID is present, check if it is valid!
if ( defined $CustomerData{ValidID} ) {
# return false if customer is not valid
return
if $Kernel::OM->Get('Kernel::System::Valid')->ValidLookup( ValidID => $CustomerData{ValidID} ) ne 'valid';
}
return 1;
}
=head2 ValidateInputCustomerCompany()
checks if the given value is valid.
my $Sucess = $CommonObject->ValidateInputCustomerCompany(
Value => 'some customer company name',
);
returns
$Success = 1 # or 0
=cut
sub ValidateInputCustomerCompany {
my ( $Self, %Param ) = @_;
my $Value = $Param{Value};
return if !$Value;
my %CompanyList = $Kernel::OM->Get('Kernel::System::CustomerCompany')->CustomerCompanyList(
Limit => 0, # Display all Customer Companies
);
return if !$CompanyList{ $Param{Value} };
return 1;
}
=head2 ValidateMimeType()
checks if the given MimeType is valid.
my $Sucess = $CommonObject->ValidateMimeType(
MimeTypeID => 'some MimeType',
);
returns
$Success = 1 # or 0
=cut
sub ValidateMimeType {
my ( $Self, %Param ) = @_;
# check needed stuff
return if !$Param{MimeType};
return if $Param{MimeType} !~ m{\A\w+\/\w+\z};
return 1;
}
=head2 ValidateCharset()
checks if the given Charset is valid.
my $Sucess = $CommonObject->ValidateCharset(
Charset => 'some charset',
);
returns
$Success = 1 # or 0
=cut
sub ValidateCharset {
my ( $Self, %Param ) = @_;
# check needed stuff
return if !$Param{Charset};
my $CharsetList = $Self->_CharsetList();
return if !$CharsetList->{ $Param{Charset} };
return 1;
}
=head2 ReplaceInputDate()
replaces the user value with a system valid value.
my $NewValue = $CommonObject->ReplaceInputDate(
Value => '12/12/1977',
);
or
my $NewValue = $CommonObject->ReplaceInputDate(
Value => '1977-12-12',
);
returns
$NewValue = '1977-12-12',
=cut
sub ReplaceInputDate {
my ( $Self, %Param ) = @_;
my $Value = $Param{Value};
# check and convert for date format like "05/18/2011"
if ( $Value =~ m{\A (\d{2}) / (\d{2}) / (\d{4}) \z}xms ) {
$Value = $3 . '-' . $1 . '-' . $2 . ' 00:00:00';
}
# check and convert for date format like "2011-05-18"
if ( $Value =~ m{\A (\d{4} - \d{2} - \d{2} \z) }xms ) {
$Value = $1 . ' 00:00:00';
}
# Convert the raw data to a system datetime object.
my $DateTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Value,
},
);
return $DateTimeObject->Format( Format => '%F' );
}
=head2 ReplaceInputDateTime()
replaces the user value with a system valid value.
my $NewValue = $CommonObject->ReplaceInputDateTime(
Value => '12/12/1977 12:00:00',
);
or
my $NewValue = $CommonObject->ReplaceInputDateTime(
Value => '1977-12-12 12:00:00',
);
returns
$NewValue = '1977-12-12 12:00:00';
=cut
sub ReplaceInputDateTime {
my ( $Self, %Param ) = @_;
my $Value = $Param{Value};
# check and convert for date format like "05/18/2011"
if ( $Value =~ m{\A (\d{2}) / (\d{2}) / (\d{4}) \z}xms ) {
$Value = $3 . '-' . $1 . '-' . $2 . ' 00:00:00';
}
elsif ( $Value =~ m{\A (\d{2}) / (\d{2}) / (\d{4}) (\d{2} : \d{2} : \d{2}) \z}xms ) {
$Value = $3 . '-' . $1 . '-' . $2 . $4;
}
# check and convert for date format like "2011-05-18"
if ( $Value =~ m{\A (\d{4} - \d{2} - \d{2} \z) }xms ) {
$Value = $1 . ' 00:00:00';
}
# Convert the raw data to a system datetime object.
my $DateTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Value,
},
);
return $DateTimeObject->ToString();
}
=head2 ReplaceInputGeneralCatalog()
replaces the user value with a system valid value.
my $NewValue = $CommonObject->ReplaceInputGeneralCatalog(
Value => 'some value',
Class => 'Some general catalog class'
);
returns
$NewValue = 123
=cut
sub ReplaceInputGeneralCatalog {
my ( $Self, %Param ) = @_;
my $Value = $Param{Value};
# get the values for the General catalog class
my $ItemList = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemList(
Class => $Param{Input}->{Class},
);
# create a lokup list
my %ItemListLookup = reverse %{$ItemList};
return $ItemListLookup{$Value};
}
=head2 InvertReplaceInputDate()
replaces the system value with a user value.
my $NewValue = $CommonObject->InvertReplaceInputDate(
Value => '12-12-1977 00:00:00',
);
returns
$NewValue = '1977-12-12',
=cut
sub InvertReplaceInputDate {
my ( $Self, %Param ) = @_;
my $Value = $Param{Value};
$Value =~ s{\A (\d{4} - \d{2} - \d{2}) [ ] 00:00:00 \z}{$1}xms;
return $Value;
}
=head2 InvertReplaceInputGeneralCatalog()
replaces the system value with a user value.
my $NewValue = $CommonObject->InvertReplaceInputGeneralCatalog(
Value => 123,
Class => 'Some general catalog class'
);
returns
$NewValue = 'some value'
=cut
sub InvertReplaceInputGeneralCatalog {
my ( $Self, %Param ) = @_;
my $Value = $Param{Value};
# get the values for the General catalog class
my $ItemList = $Kernel::OM->Get('Kernel::System::GeneralCatalog')->ItemList(
Class => $Param{Input}->{Class},
);
# create a lokup list
return $ItemList->{$Value};
}
=head2 CreateAttachment()
creates a new attachment for the given ConfigItem.
my $Result = $CommonObject->CreateAttachment(
Content => $Data, # file content (Base64 encoded)
ContentType => 'some content type',
Filename => 'some filename',
ConfigItemID => 456,
UserID => 123,
);
returns
$Result = {
Success => 1, # if everything is ok
}
$Result = {
Success => 0,
ErrorMessage => 'Error description'
}
=cut
sub CreateAttachment {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Needed (qw(Attachment ConfigItemID UserID)) {
if ( !$Param{$Needed} ) {
return {
Success => 0,
ErrorMessage => "CreateAttachment() Got no $Needed!",
};
}
}
# write attachment
my $Success = $Kernel::OM->Get('Kernel::System::ITSMConfigItem')->ConfigItemAttachmentAdd(
%{ $Param{Attachment} },
ConfigItemID => $Param{ConfigItemID},
Content => MIME::Base64::decode_base64( $Param{Attachment}->{Content} ),
UserID => $Param{UserID},
);
return {
Success => $Success,
};
}
=head2 CheckXMLData()
checks if the given XMLData value are valid.
my $XMLDataCheck = $CommonObject->CheckXMLData(
Definition => $DefinitionArrayRef, # Config Item Definition ot just part of it
XMLData => $XMLDataHashRef,
Parent => 'some parent',
);
returns:
$XMLDataCheck = {
Success => 1, # if everything is OK
}
$XMLDataCheck = {
ErrorCode => 'Function.Error', # if error
ErrorMessage => 'Error description',
}
=cut
sub CheckXMLData {
my ( $Self, %Param ) = @_;
my $Definition = $Param{Definition};
my $XMLData = $Param{XMLData};
my $Parent = $Param{Parent} || '';
my $CheckValueResult;
for my $DefItem ( @{$Definition} ) {
my $ItemKey = $DefItem->{Key};
# check if at least one element should exist
if (
(
defined $DefItem->{CountMin}
&& $DefItem->{CountMin} >= 1
&& defined $DefItem->{Input}->{Required}
&& $DefItem->{Input}->{Required}
)
&& ( !defined $XMLData->{$ItemKey} || !$XMLData->{$ItemKey} )
)
{
return {
ErrorCode => "$Self->{OperationName}.MissingParameter",
ErrorMessage =>
"$Self->{OperationName}: ConfigItem->CIXMLData->$Parent$ItemKey parameter"
. " is missing!",
};
}
if ( ref $XMLData->{$ItemKey} eq 'ARRAY' ) {
for my $ArrayItem ( @{ $XMLData->{$ItemKey} } ) {
if ( ref $ArrayItem eq 'HASH' ) {
$CheckValueResult = $Self->_CheckValue(
Value => $ArrayItem->{$ItemKey},
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
if ( !$CheckValueResult->{Success} ) {
return $CheckValueResult;
}
}
elsif ( ref $ArrayItem eq '' ) {
$CheckValueResult = $Self->_CheckValue(
Value => $ArrayItem,
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
if ( !$CheckValueResult->{Success} ) {
return $CheckValueResult;
}
}
else {
return {
ErrorCode => "$Self->{OperationName}.InvalidParameter",
ErrorMessage =>
"$Self->{OperationName}: ConfigItem->CIXMLData->$Parent$ItemKey parameter"
. " is invalid!",
};
}
}
}
elsif ( ref $XMLData->{$ItemKey} eq 'HASH' ) {
$CheckValueResult = $Self->_CheckValue(
Value => $XMLData->{$ItemKey}->{$ItemKey},
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
if ( !$CheckValueResult->{Success} ) {
return $CheckValueResult;
}
}
else {
# only perform checks if item really exits in the XMLData
# CountNin checks was verified and passed before!, so it is safe to skip if needed
if ( $XMLData->{$ItemKey} ) {
$CheckValueResult = $Self->_CheckValue(
Value => $XMLData->{$ItemKey},
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
if ( !$CheckValueResult->{Success} ) {
return $CheckValueResult;
}
}
}
# check if exists more elements than the ones they should
if ( defined $DefItem->{CountMax} )
{
if (
ref $XMLData->{$ItemKey} eq 'ARRAY'
&& scalar @{ $XMLData->{$ItemKey} } > $DefItem->{CountMax}
)
{
return {
ErrorCode => "$Self->{OperationName}.InvalidParameter",
ErrorMessage =>
"$Self->{OperationName}: ConfigItem->CIXMLData->$Parent$ItemKey parameter"
. " repetitions is higher than the maxium value!",
};
}
}
# check if there is a sub and start recursion
if ( defined $DefItem->{Sub} ) {
if ( ref $XMLData->{$ItemKey} eq 'ARRAY' ) {
my $Counter = 0;
for my $ArrayItem ( @{ $XMLData->{$ItemKey} } ) {
# start recursion for each array item
my $XMLDataCheck = $Self->CheckXMLData(
Definition => $DefItem->{Sub},
XMLData => $ArrayItem,
Parent => $Parent . $ItemKey . "[$Counter]->",
);
if ( !$XMLDataCheck->{Success} ) {
return $XMLDataCheck;
}
$Counter++;
}
}
elsif ( ref $XMLData->{$ItemKey} eq 'HASH' ) {
# start recursion
my $XMLDataCheck = $Self->CheckXMLData(
Definition => $DefItem->{Sub},
XMLData => $XMLData->{$ItemKey},
Parent => $Parent . $ItemKey . '->',
);
if ( !$XMLDataCheck->{Success} ) {
return $XMLDataCheck;
}
}
else {
# start recusrsion
my $XMLDataCheck = $Self->CheckXMLData(
Definition => $DefItem->{Sub},
XMLData => {},
Parent => $Parent . $ItemKey . '->',
);
if ( !$XMLDataCheck->{Success} ) {
return $XMLDataCheck;
}
}
}
}
return {
Success => 1,
};
}
=head2 ReplaceXMLData()
replace the XMLData to one that uses internal values.
my $NewXMLData = $CommonObject->ReplaceXMLData(
Definition => $DefinitionArrayRef, # Config Item Definition ot just part of it
XMLData => $XMLDataHashRef,
Parent => 'some parent',
);
returns:
$NewXMLData = $XMLDataHashRef, # with replaced values
=cut
sub ReplaceXMLData {
my ( $Self, %Param ) = @_;
my $Definition = $Param{Definition};
my $XMLData = $Param{XMLData};
my $Parent = $Param{Parent} || '';
my $NewXMLData = $XMLData;
ITEM:
for my $DefItem ( @{$Definition} ) {
my $ItemKey = $DefItem->{Key};
my $NewValue;
if ( ref $XMLData->{$ItemKey} eq 'ARRAY' ) {
for my $ArrayItem ( @{ $XMLData->{$ItemKey} } ) {
if ( ref $ArrayItem eq 'HASH' ) {
# get the new value
$NewValue = $Self->_ReplaceValue(
Value => $ArrayItem->{$ItemKey},
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
# replace the value in the array
$ArrayItem->{$ItemKey} = $NewValue;
}
elsif ( ref $ArrayItem eq '' ) {
$NewValue = $Self->_ReplaceValue(
Value => $ArrayItem,
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
# replace the value in the array
$ArrayItem = $NewValue;
}
}
}
elsif ( ref $XMLData->{$ItemKey} eq 'HASH' ) {
$NewValue = $Self->_ReplaceValue(
Value => $XMLData->{$ItemKey}->{$ItemKey},
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
# replace the value in the hash
$XMLData->{$ItemKey}->{$ItemKey} = $NewValue;
}
else {
# only perform replace if item really exits in the XMLData
if ( $XMLData->{$ItemKey} ) {
$NewValue = $Self->_ReplaceValue(
Value => $XMLData->{$ItemKey},
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
# replace the root value
$XMLData->{$ItemKey} = $NewValue;
}
}
# replace value in the resulting XMLData
if ( $XMLData->{$ItemKey} ) {
$NewXMLData->{$ItemKey} = $XMLData->{$ItemKey};
}
# check if there is a sub and start recursion
if ( defined $DefItem->{Sub} ) {
if ( ref $XMLData->{$ItemKey} eq 'ARRAY' ) {
my $Counter = 0;
for my $ArrayItem ( @{ $XMLData->{$ItemKey} } ) {
# start recursion for each array item
my $NewXMLDataPart = $Self->ReplaceXMLData(
Definition => $DefItem->{Sub},
XMLData => $ArrayItem,
Parent => $Parent . $ItemKey . "[$Counter]->",
);
$NewXMLData->{$ItemKey}->[$Counter] = $NewXMLDataPart;
$Counter++;
}
}
elsif ( ref $XMLData->{$ItemKey} eq 'HASH' ) {
# start recursion
my $NewXMLDataPart = $Self->ReplaceXMLData(
Definition => $DefItem->{Sub},
XMLData => $XMLData->{$ItemKey},
Parent => $Parent . $ItemKey . '->',
);
$NewXMLData->{$ItemKey} = $NewXMLDataPart;
}
else {
if ( $XMLData->{$ItemKey} ) {
# start recusrsion
my $NewXMLDataPart = $Self->ReplaceXMLData(
Definition => $DefItem->{Sub},
XMLData => {},
Parent => $Parent . $ItemKey . '->',
);
$NewXMLData->{$ItemKey} = $NewXMLDataPart;
}
}
}
}
return $NewXMLData;
}
=head2 FormatXMLData()
Create a XMLData suitable for VersionAdd.
my $NewXMLData = $CommonObject->FormatXMLData(
XMLData => $XMLDataHashRef,
Child => 1, # or 0, optional
);
returns:
$NewXMLData = $XMLDataHashRef, # suitable for version add
=cut
sub FormatXMLData {
my ( $Self, %Param ) = @_;
my $XMLData = $Param{XMLData};
my $Child = $Param{Child};
my $NewXMLData;
for my $RootKey ( sort keys %{$XMLData} ) {
if ( ref $XMLData->{$RootKey} eq 'ARRAY' ) {
my @NewXMLParts;
$NewXMLParts[0] = undef;
for my $ArrayItem ( @{ $XMLData->{$RootKey} } ) {
if ( ref $ArrayItem eq 'HASH' ) {
# extract the root key from the hash and assign it to content key
my $Content = delete $ArrayItem->{$RootKey};
# start recursion
my $NewXMLDataPart = $Self->FormatXMLData(
XMLData => $ArrayItem,
Child => 1,
);
push @NewXMLParts, {
Content => $Content,
%{$NewXMLDataPart},
};
}
elsif ( ref $ArrayItem eq '' ) {
push @NewXMLParts, {
Content => $ArrayItem,
};
}
}
# assamble the final value from the parts array
$NewXMLData->{$RootKey} = \@NewXMLParts;
}
if ( ref $XMLData->{$RootKey} eq 'HASH' ) {
my @NewXMLParts;
$NewXMLParts[0] = undef;
# extract the root key from the hash and assign it to content key
my $Content = delete $XMLData->{$RootKey}->{$RootKey};
# start recursion
my $NewXMLDataPart = $Self->FormatXMLData(
XMLData => $XMLData->{$RootKey},
Child => 1,
);
push @NewXMLParts, {
Content => $Content,
%{$NewXMLDataPart},
};
# assamble the final value from the parts array
$NewXMLData->{$RootKey} = \@NewXMLParts;
}
elsif ( ref $XMLData->{$RootKey} eq '' ) {
$NewXMLData->{$RootKey} = [
undef,
{
Content => $XMLData->{$RootKey},
},
];
}
}
# return only the part on recursion
if ($Child) {
return $NewXMLData;
}
# return the complete XMLData as needed for version add
return [
undef,
{
Version => [
undef,
$NewXMLData
],
},
];
}
=head2 InvertFormatXMLData()
Creates a readable XMLData.
my $NewXMLData = $CommonObject->InvertFormatXMLData(
XMLData => $XMLDataHashRef,
);
returns:
$NewXMLData = $XMLDataHashRef, # suitable for version add
=cut
sub InvertFormatXMLData {
my ( $Self, %Param ) = @_;
my $XMLData = $Param{XMLData};
my $NewXMLData;
my $Content;
ROOTHASH:
for my $RootHash ( @{$XMLData} ) {
next ROOTHASH if !defined $RootHash;
delete $RootHash->{TagKey};
for my $RootHashKey ( sort keys %{$RootHash} ) {
if ( ref $RootHash->{$RootHashKey} eq 'ARRAY' ) {
if ( scalar @{ $RootHash->{$RootHashKey} } > 2 ) {
# we are on an array
my $Counter = 0;
ARRAYITEM:
for my $ArrayItem ( @{ $RootHash->{$RootHashKey} } ) {
next ARRAYITEM if !defined $ArrayItem;
delete $ArrayItem->{TagKey};
$Content = delete $ArrayItem->{Content} || '';
if ( scalar keys %{$ArrayItem} ) {
$NewXMLData->{$RootHashKey}->[$Counter]->{$RootHashKey} = $Content;
# start recursion
for my $ArrayItemKey ( sort keys %{$ArrayItem} ) {
my $NewXMLDataPart = $Self->InvertFormatXMLData(
XMLData => $ArrayItem->{$ArrayItemKey},
);
$NewXMLData->{$RootHashKey}->[$Counter]->{$ArrayItemKey} = $NewXMLDataPart;
}
}
else {
$NewXMLData->{$RootHashKey}->[$Counter] = $Content;
}
$Counter++;
}
}
else {
# we are on a hash or single value
ARRAYITEM:
for my $ArrayItem ( @{ $RootHash->{$RootHashKey} } ) {
next ARRAYITEM if !defined $ArrayItem;
delete $ArrayItem->{TagKey};
$Content = delete $ArrayItem->{Content} || '';
if ( scalar keys %{$ArrayItem} ) {
$NewXMLData->{$RootHashKey}->{$RootHashKey} = $Content;
# start recursion
for my $ArrayItemKey ( sort keys %{$ArrayItem} ) {
my $NewXMLDataPart = $Self->InvertFormatXMLData(
XMLData => $ArrayItem->{$ArrayItemKey},
);
$NewXMLData->{$RootHashKey}->{$ArrayItemKey} = $NewXMLDataPart;
}
}
else {
$NewXMLData->{$RootHashKey} = $Content;
}
}
}
}
# if we are on a final node
elsif ( ref $RootHash->{$RootHashKey} eq '' && $RootHashKey eq 'Content' ) {
$NewXMLData = $RootHash->{$RootHashKey};
}
}
}
return $NewXMLData;
}
=head2 InvertReplaceXMLData()
replace the XMLData to one that uses user values.
my $NewXMLData = $CommonObject->InvertReplaceXMLData(
Definition => $DefinitionArrayRef, # Config Item Definition ot just part of it
XMLData => $XMLDataHashRef,
Parent => 'some parent',
);
returns:
$NewXMLData = $XMLDataHashRef, # with replaced values
=cut
sub InvertReplaceXMLData {
my ( $Self, %Param ) = @_;
my $Definition = $Param{Definition};
my $XMLData = $Param{XMLData};
my $Parent = $Param{Parent} || '';
my $NewXMLData = $XMLData;
ITEM:
for my $DefItem ( @{$Definition} ) {
my $ItemKey = $DefItem->{Key};
my $NewValue;
if (
IsHashRefWithData($XMLData)
&& $XMLData->{$ItemKey}
&& ref $XMLData->{$ItemKey} eq 'ARRAY'
)
{
for my $ArrayItem ( @{ $XMLData->{$ItemKey} } ) {
if ( ref $ArrayItem eq 'HASH' ) {
# get the new value
$NewValue = $Self->_InvertReplaceValue(
Value => $ArrayItem->{$ItemKey},
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
# replace the value in the array
$ArrayItem->{$ItemKey} = $NewValue;
}
elsif ( ref $ArrayItem eq '' ) {
$NewValue = $Self->_InvertReplaceValue(
Value => $ArrayItem,
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
# replace the value in the array
$ArrayItem = $NewValue;
}
}
}
elsif (
IsHashRefWithData($XMLData)
&& $XMLData->{$ItemKey}
&& ref $XMLData->{$ItemKey} eq 'HASH'
)
{
$NewValue = $Self->_InvertReplaceValue(
Value => $XMLData->{$ItemKey}->{$ItemKey},
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
# replace the value in the hash
$XMLData->{$ItemKey}->{$ItemKey} = $NewValue;
}
else {
# only perform replace if item really exits in the XMLData
if ( IsHashRefWithData($XMLData) && $XMLData->{$ItemKey} ) {
$NewValue = $Self->_InvertReplaceValue(
Value => $XMLData->{$ItemKey},
Input => $DefItem->{Input},
ItemKey => $ItemKey,
Parent => $Parent,
);
# replace the root value
$XMLData->{$ItemKey} = $NewValue;
}
}
# replace value in the resulting XMLData
if ( IsHashRefWithData($XMLData) && $XMLData->{$ItemKey} ) {
$NewXMLData->{$ItemKey} = $XMLData->{$ItemKey};
}
# check if there is a sub and start recursion
if ( defined $DefItem->{Sub} ) {
if ( ref $XMLData->{$ItemKey} eq 'ARRAY' ) {
my $Counter = 0;
for my $ArrayItem ( @{ $XMLData->{$ItemKey} } ) {
# start recursion for each array item
my $NewXMLDataPart = $Self->InvertReplaceXMLData(
Definition => $DefItem->{Sub},
XMLData => $ArrayItem,
Parent => $Parent . $ItemKey . "[$Counter]->",
);
$NewXMLData->{$ItemKey}->[$Counter] = $NewXMLDataPart;
$Counter++;
}
}
elsif ( ref $XMLData->{$ItemKey} eq 'HASH' ) {
# start recursion
my $NewXMLDataPart = $Self->InvertReplaceXMLData(
Definition => $DefItem->{Sub},
XMLData => $XMLData->{$ItemKey},
Parent => $Parent . $ItemKey . '->',
);
$NewXMLData->{$ItemKey} = $NewXMLDataPart;
}
else {
if ( $XMLData->{$ItemKey} ) {
# start recusrsion
my $NewXMLDataPart = $Self->InvertReplaceXMLData(
Definition => $DefItem->{Sub},
XMLData => {},
Parent => $Parent . $ItemKey . '->',
);
$NewXMLData->{$ItemKey} = $NewXMLDataPart;
}
}
}
}
return $NewXMLData;
}
=head1 INTERNAL INTERFACE
=head2 _CharsetList()
returns a list of all available charsets.
my $CharsetList = $CommonObject->_CharsetList(
UserID => 123,
);
returns
$Success = {
#...
iso-8859-1 => 1,
iso-8859-15 => 1,
MacRoman => 1,
utf8 => 1,
#...
}
=cut
sub _CharsetList {
my ( $Self, %Param ) = @_;
# get charset array
use Encode;
my @CharsetList = Encode->encodings(":all");
my %CharsetHash;
# create a charset lookup table
for my $Charset (@CharsetList) {
$CharsetHash{$Charset} = 1;
}
return \%CharsetHash;
}
=head2 _CheckValue()
checks if the given value is valid.
my $ValueCheck = $CommonObject->_CheckValue(
Value => $Value # $Value could be a string, a time stamp,
# general catalog class name, or a integer
Input => $InputDefinitionHashRef, # The definition of the element input extracted
# from the Configuration Item definition for
# for each value
ItemKey => 'some key', # The name of the value as sent in the SOAP
# request
Parent => 'soem parent key->', # The name of the parent followed by -> or empty
# for root key items
);
returns:
$ValueCheck = {
Success => 1, # if everything is OK
}
$ValueCheck = {
ErrorCode => 'Function.Error', # if error
ErrorMessage => 'Error description',
}
=cut
sub _CheckValue {
my ( $Self, %Param ) = @_;
my $Parent = $Param{Parent};
my $ItemKey = $Param{ItemKey};
if (
defined $Param{Input}->{Required} && $Param{Input}->{Required} && !$Param{Value}
)
{
return {
ErrorCode => "$Self->{OperationName}.MissingParameter",
ErrorMessage =>
"$Self->{OperationName}: ConfigItem->CIXMLData->$Parent$ItemKey parameter value"
. " is required and is missing!",
};
}
if ( $Param{Input}->{Type} eq 'Text' || $Param{Input}->{Type} eq 'TextArea' ) {
# run Text validations
if ( !$Self->ValidateInputText(%Param) ) {
return {
ErrorCode => "$Self->{OperationName}.InvalidParameter",
ErrorMessage =>
"$Self->{OperationName}: ConfigItem->CIXMLData->$Parent$ItemKey parameter value"
. " excedes the maxium length!",
};
}
}
elsif ( $Param{Input}->{Type} eq 'Date' ) {
# run Date validations
if ( !$Self->ValidateInputDate(%Param) ) {
return {
ErrorCode => "$Self->{OperationName}.InvalidParameter",
ErrorMessage =>
"$Self->{OperationName}: ConfigItem->CIXMLData->$Parent$ItemKey parameter value"
. " is not a valid Date format!",
};
}
}
elsif ( $Param{Input}->{Type} eq 'DateTime' ) {
# run DateTime validations
if ( !$Self->ValidateInputDateTime(%Param) ) {
return {
ErrorCode => "$Self->{OperationName}.InvalidParameter",
ErrorMessage =>
"$Self->{OperationName}: ConfigItem->CIXMLData->$Parent$ItemKey parameter value"
. " is not a valid DateTime format!",
};
}
}
elsif ( $Param{Input}->{Type} eq 'Customer' ) {
# run Customer validations
if ( !$Self->ValidateInputCustomer(%Param) ) {
return {
ErrorCode => "$Self->{OperationName}.InvalidParameter",
ErrorMessage =>
"$Self->{OperationName}: ConfigItem->CIXMLData->$Parent$ItemKey parameter value"
. " is not a valid customer!",
};
}
}
elsif ( $Param{Input}->{Type} eq 'CustomerCompany' ) {
# run CustomerCompany validations
if ( !$Self->ValidateInputCustomerCompany(%Param) ) {
return {
ErrorCode => "$Self->{OperationName}.InvalidParameter",
ErrorMessage =>
"$Self->{OperationName}: ConfigItem->CIXMLData->$Parent$ItemKey parameter value"
. " is not a valid customer company!",
};
}
}
elsif ( $Param{Input}->{Type} eq 'Integer' ) {
# run Integer validations
if ( !$Self->ValidateInputInteger(%Param) ) {
return {
ErrorCode => "$Self->{OperationName}.InvalidParameter",
ErrorMessage =>
"$Self->{OperationName}: ConfigItem->CIXMLData->$Parent$ItemKey parameter value"
. " is not a valid Integer or out of range!",
};
}
}
elsif ( $Param{Input}->{Type} eq 'GeneralCatalog' ) {
# run General Catalog validations
if ( !$Self->ValidateInputGeneralCatalog(%Param) ) {
return {
ErrorCode => "$Self->{OperationName}.InvalidParameter",
ErrorMessage =>
"$Self->{OperationName}: ConfigItem->CIXMLData->$Parent$ItemKey parameter value"
. " is not a valid for General Catalog '$Param{Input}->{Class}'!",
};
}
}
else {
# The type is dummy, do nothing
}
return {
Success => 1,
};
}
=head2 _ReplaceValue()
replace user values with system ready values.
my $NewValue = $CommonObject->_ReplaceValue(
Value => $Value # $Value could be a string, a time stamp,
# general catalog class name, or a integer
Input => $InputDefinitionHashRef, # The definition of the element input extracted
# from the Configuration Item definition for
# for each value
# for root key items
);
returns:
$NewValue = $ANewValue
=cut
sub _ReplaceValue {
my ( $Self, %Param ) = @_;
# set the list of input types that needs to be replaced
my %ReplaceInputTypes = (
Date => 1,
DateTime => 1,
GeneralCatalog => 1,
);
if ( !$ReplaceInputTypes{ $Param{Input}->{Type} } ) {
return $Param{Value};
}
my $NewValue;
if ( $Param{Input}->{Type} eq 'Date' ) {
# run Date replace
$NewValue = $Self->ReplaceInputDate(%Param);
}
elsif ( $Param{Input}->{Type} eq 'DateTime' ) {
# run DateTime replace
$NewValue = $Self->ReplaceInputDateTime(%Param);
}
else {
# run General Catalog replace
$NewValue = $Self->ReplaceInputGeneralCatalog(%Param);
}
return $NewValue;
}
=head2 _InvertReplaceValue()
replace internal values with user values.
my $NewValue = $OperationObject->_InvertReplaceValue(
Value => $Value # $Value could be a string, a time stamp,
# general catalog class name, or a integer
Input => $InputDefinitionHashRef, # The definition of the element input extracted
# from the Configuration Item definition for
# for each value
# for root key items
);
returns:
$NewValue = $ANewValue
=cut
sub _InvertReplaceValue {
my ( $Self, %Param ) = @_;
# set the list of input types that needs to be replaced
my %ReplaceInputTypes = (
Date => 1,
GeneralCatalog => 1,
);
if ( !$ReplaceInputTypes{ $Param{Input}->{Type} } ) {
return $Param{Value};
}
my $NewValue;
if ( $Param{Input}->{Type} eq 'Date' ) {
# run Date replace
$NewValue = $Self->InvertReplaceInputDate(%Param);
}
else {
# run General Catalog replace
$NewValue = $Self->InvertReplaceInputGeneralCatalog(%Param);
}
return $NewValue;
}
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