init III
This commit is contained in:
230
Perl OTRS/Kernel/GenericInterface/Operation/Common.pm
Normal file
230
Perl OTRS/Kernel/GenericInterface/Operation/Common.pm
Normal file
@@ -0,0 +1,230 @@
|
||||
# --
|
||||
# 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::Common;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::System::VariableCheck qw(:all);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::Common - Base class for all Operations
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 Auth()
|
||||
|
||||
performs user or customer user authorization
|
||||
|
||||
my ( $UserID, $UserType ) = $CommonObject->Auth(
|
||||
Data => {
|
||||
SessionID => 'AValidSessionIDValue' # the ID of the user session
|
||||
UserLogin => 'Agent', # if no SessionID is given UserLogin or
|
||||
# CustomerUserLogin is required
|
||||
CustomerUserLogin => 'Customer',
|
||||
Password => 'some password', # user password
|
||||
},
|
||||
);
|
||||
|
||||
returns
|
||||
|
||||
(
|
||||
1, # the UserID from login or session data
|
||||
'Agent', # || 'Customer', the UserType.
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub Auth {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $SessionID = $Param{Data}->{SessionID} || '';
|
||||
|
||||
# check if a valid SessionID is present
|
||||
if ($SessionID) {
|
||||
my $ValidSessionID;
|
||||
|
||||
# get session object
|
||||
my $SessionObject = $Kernel::OM->Get('Kernel::System::AuthSession');
|
||||
|
||||
if ($SessionID) {
|
||||
$ValidSessionID = $SessionObject->CheckSessionID( SessionID => $SessionID );
|
||||
}
|
||||
return 0 if !$ValidSessionID;
|
||||
|
||||
# get session data
|
||||
my %UserData = $SessionObject->GetSessionIDData(
|
||||
SessionID => $SessionID,
|
||||
);
|
||||
|
||||
# get UserID from SessionIDData
|
||||
if ( $UserData{UserID} && $UserData{UserType} ne 'Customer' ) {
|
||||
return ( $UserData{UserID}, $UserData{UserType} );
|
||||
}
|
||||
elsif ( $UserData{UserLogin} && $UserData{UserType} eq 'Customer' ) {
|
||||
|
||||
# if UserCustomerLogin
|
||||
return ( $UserData{UserLogin}, $UserData{UserType} );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( defined $Param{Data}->{UserLogin} && $Param{Data}->{UserLogin} ) {
|
||||
|
||||
my $UserID = $Self->_AuthUser(%Param);
|
||||
|
||||
# if UserLogin
|
||||
if ($UserID) {
|
||||
return ( $UserID, 'User' );
|
||||
}
|
||||
}
|
||||
elsif ( defined $Param{Data}->{CustomerUserLogin} && $Param{Data}->{CustomerUserLogin} ) {
|
||||
|
||||
my $CustomerUserID = $Self->_AuthCustomerUser(%Param);
|
||||
|
||||
# if UserCustomerLogin
|
||||
if ($CustomerUserID) {
|
||||
return ( $CustomerUserID, 'Customer' );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
=head2 ReturnError()
|
||||
|
||||
helper function to return an error message.
|
||||
|
||||
my $Return = $CommonObject->ReturnError(
|
||||
ErrorCode => Ticket.AccessDenied,
|
||||
ErrorMessage => 'You don't have rights to access this ticket',
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub ReturnError {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
$Self->{DebuggerObject}->Error(
|
||||
Summary => $Param{ErrorCode},
|
||||
Data => $Param{ErrorMessage},
|
||||
);
|
||||
|
||||
# return structure
|
||||
return {
|
||||
Success => 1,
|
||||
ErrorMessage => "$Param{ErrorCode}: $Param{ErrorMessage}",
|
||||
Data => {
|
||||
Error => {
|
||||
ErrorCode => $Param{ErrorCode},
|
||||
ErrorMessage => $Param{ErrorMessage},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
=begin Internal:
|
||||
|
||||
=head2 _AuthUser()
|
||||
|
||||
performs user authentication
|
||||
|
||||
my $UserID = $CommonObject->_AuthUser(
|
||||
UserLogin => 'Agent',
|
||||
Password => 'some password', # plain text password
|
||||
);
|
||||
|
||||
returns
|
||||
|
||||
$UserID = 1; # the UserID from login or session data
|
||||
|
||||
=cut
|
||||
|
||||
sub _AuthUser {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $ReturnData = 0;
|
||||
|
||||
# get params
|
||||
my $PostUser = $Param{Data}->{UserLogin} || '';
|
||||
my $PostPw = $Param{Data}->{Password} || '';
|
||||
|
||||
# check submitted data
|
||||
my $User = $Kernel::OM->Get('Kernel::System::Auth')->Auth(
|
||||
User => $PostUser,
|
||||
Pw => $PostPw,
|
||||
);
|
||||
|
||||
# login is valid
|
||||
if ($User) {
|
||||
|
||||
# get UserID
|
||||
my $UserID = $Kernel::OM->Get('Kernel::System::User')->UserLookup(
|
||||
UserLogin => $User,
|
||||
);
|
||||
$ReturnData = $UserID;
|
||||
}
|
||||
|
||||
return $ReturnData;
|
||||
}
|
||||
|
||||
=head2 _AuthCustomerUser()
|
||||
|
||||
performs customer user authentication
|
||||
|
||||
my $UserID = $CommonObject->_AuthCustomerUser(
|
||||
UserLogin => 'Agent',
|
||||
Password => 'some password', # plain text password
|
||||
);
|
||||
|
||||
returns
|
||||
|
||||
$UserID = 1; # the UserID from login or session data
|
||||
|
||||
=cut
|
||||
|
||||
sub _AuthCustomerUser {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $ReturnData = $Param{Data}->{CustomerUserLogin} || 0;
|
||||
|
||||
# get params
|
||||
my $PostUser = $Param{Data}->{CustomerUserLogin} || '';
|
||||
my $PostPw = $Param{Data}->{Password} || '';
|
||||
|
||||
# check submitted data
|
||||
my $User = $Kernel::OM->Get('Kernel::System::CustomerAuth')->Auth(
|
||||
User => $PostUser,
|
||||
Pw => $PostPw,
|
||||
);
|
||||
|
||||
# login is invalid
|
||||
if ( !$User ) {
|
||||
$ReturnData = 0;
|
||||
}
|
||||
|
||||
return $ReturnData;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=end Internal:
|
||||
|
||||
=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
|
||||
1649
Perl OTRS/Kernel/GenericInterface/Operation/ConfigItem/Common.pm
Normal file
1649
Perl OTRS/Kernel/GenericInterface/Operation/ConfigItem/Common.pm
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,707 @@
|
||||
# --
|
||||
# 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::ConfigItemCreate;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## nofilter(TidyAll::Plugin::OTRS::Migrations::OTRS6::SysConfig)
|
||||
|
||||
use Kernel::System::VariableCheck qw(:all);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
Kernel::GenericInterface::Operation::ConfigItem::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::ConfigItem::ConfigItemCreate - GenericInterface ConfigItem ConfigItemCreate Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# check needed objects
|
||||
for my $Needed (qw( DebuggerObject WebserviceID )) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!",
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
$Self->{OperationName} = 'ConfigItemCreate';
|
||||
|
||||
$Self->{Config} = $Kernel::OM->Get('Kernel::Config')->Get('GenericInterface::Operation::ConfigItemCreate');
|
||||
|
||||
$Self->{Config}->{DefaultValue} = 'Not Defined';
|
||||
|
||||
my $GeneralCatalogObject = $Kernel::OM->Get('Kernel::System::GeneralCatalog');
|
||||
|
||||
# get a list of all config item classes
|
||||
$Self->{ClassList} = $GeneralCatalogObject->ItemList(
|
||||
Class => 'ITSM::ConfigItem::Class',
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData( $Self->{ClassList} ) ) {
|
||||
return $Self->{DebuggerObject}->Error(
|
||||
Summary => 'Error when trying to get class listing of ITSM::ConfigItem::Class',
|
||||
);
|
||||
}
|
||||
|
||||
# get a list of all incistates
|
||||
$Self->{InciStateList} = $GeneralCatalogObject->ItemList(
|
||||
Class => 'ITSM::Core::IncidentState',
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData( $Self->{InciStateList} ) ) {
|
||||
return $Self->{DebuggerObject}->Error(
|
||||
Summary => 'Error when trying to get incident state listing of'
|
||||
. ' ITSM::Core::IncidentState',
|
||||
);
|
||||
}
|
||||
|
||||
# get a list of all deplstates
|
||||
$Self->{DeplStateList} = $GeneralCatalogObject->ItemList(
|
||||
Class => 'ITSM::ConfigItem::DeploymentState',
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData( $Self->{DeplStateList} ) ) {
|
||||
return $Self->{DebuggerObject}->Error(
|
||||
Summary => 'Error when trying to get incident state listing of'
|
||||
. ' ITSM::ConfigItem::DeploymentState',
|
||||
);
|
||||
}
|
||||
|
||||
# also provide the classlist in reversed form for easier reverse lookups
|
||||
my %ReverseClassList = reverse %{ $Self->{ClassList} };
|
||||
$Self->{ReverseClassList} = \%ReverseClassList;
|
||||
|
||||
# also provide the incistatelist in reversed form for easier reverse lookups
|
||||
my %ReverseInciStateList = reverse %{ $Self->{InciStateList} };
|
||||
$Self->{ReverseInciStateList} = \%ReverseInciStateList;
|
||||
|
||||
# also provide the deplstatelist in reversed form for easier reverse lookups
|
||||
my %ReverseDeplStateList = reverse %{ $Self->{DeplStateList} };
|
||||
$Self->{ReverseDeplStateList} = \%ReverseDeplStateList;
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform ConfigItemCreate Operation. This will return the created config item number.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => {
|
||||
UserLogin => 'some agent login', # UserLogin or SessionID is
|
||||
# required
|
||||
SessionID => 123,
|
||||
|
||||
Password => 'some password', # if UserLogin is sent then
|
||||
# Password is required
|
||||
ConfigItem => {
|
||||
Number => '111', # optional
|
||||
Class => 'Config Item Class',
|
||||
Name => 'The Name',
|
||||
DeplState => 'deployment state',
|
||||
InciState => 'incident state',
|
||||
CIXMLData => $ArrayHashRef, # it depends on the Configuration Item class and definition
|
||||
|
||||
Attachment => [
|
||||
{
|
||||
Content => 'content' # base64 encoded
|
||||
ContentType => 'some content type'
|
||||
Filename => 'some fine name'
|
||||
},
|
||||
# ...
|
||||
],
|
||||
#or
|
||||
#Attachment => {
|
||||
# Content => 'content'
|
||||
# ContentType => 'some content type'
|
||||
# Filename => 'some fine name'
|
||||
#},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # in case of error
|
||||
Data => { # result data payload after Operation
|
||||
ConfigItemID => 123, # Configuration Item ID number in OTRS::ITSM (Service desk system)
|
||||
Number => 2324454323322 # Configuration Item Number in OTRS::ITSM (Service desk system)
|
||||
Error => { # should not return errors
|
||||
ErrorCode => 'ConfigItemCreate.ErrorCode'
|
||||
ErrorMessage => 'Error Description'
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Result = $Self->Init(
|
||||
WebserviceID => $Self->{WebserviceID},
|
||||
);
|
||||
|
||||
if ( !$Result->{Success} ) {
|
||||
|
||||
$Self->ReturnError(
|
||||
ErrorCode => 'Webservice.InvalidConfiguration',
|
||||
ErrorMessage => $Result->{ErrorMessage},
|
||||
);
|
||||
}
|
||||
|
||||
# check needed stuff
|
||||
if (
|
||||
!$Param{Data}->{UserLogin}
|
||||
&& !$Param{Data}->{SessionID}
|
||||
)
|
||||
{
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: UserLogin or SessionID is required!",
|
||||
);
|
||||
}
|
||||
|
||||
if ( $Param{Data}->{UserLogin} ) {
|
||||
|
||||
if ( !$Param{Data}->{Password} )
|
||||
{
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: Password or SessionID is required!",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# authenticate user
|
||||
my ( $UserID, $UserType ) = $Self->Auth(%Param);
|
||||
|
||||
if ( !$UserID ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.AuthFail",
|
||||
ErrorMessage => "$Self->{OperationName}: User could not be authenticated!",
|
||||
);
|
||||
}
|
||||
|
||||
# check needed hashes
|
||||
for my $Needed (qw(ConfigItem)) {
|
||||
if ( !IsHashRefWithData( $Param{Data}->{$Needed} ) ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: $Needed parameter is missing or not valid!",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# isolate config item parameter
|
||||
my $ConfigItem = $Param{Data}->{ConfigItem};
|
||||
|
||||
# remove leading and trailing spaces
|
||||
for my $Attribute ( sort keys %{$ConfigItem} ) {
|
||||
if ( ref $Attribute ne 'HASH' && ref $Attribute ne 'ARRAY' ) {
|
||||
|
||||
#remove leading spaces
|
||||
$ConfigItem->{$Attribute} =~ s{\A\s+}{};
|
||||
|
||||
#remove trailing spaces
|
||||
$ConfigItem->{$Attribute} =~ s{\s+\z}{};
|
||||
}
|
||||
}
|
||||
|
||||
# CIXMLData is not mandatory, but it must be HashRef if exists.
|
||||
if ( defined $ConfigItem->{CIXMLData} ) {
|
||||
if ( !IsHashRefWithData( $ConfigItem->{CIXMLData} ) ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: ConfigItem->CIXMLData is missing or invalid!",
|
||||
);
|
||||
}
|
||||
|
||||
# Remove leading and trailing spaces for CIXMLData (must be HashRef).
|
||||
$Self->_CleanXMLData( XMLData => $ConfigItem->{CIXMLData} );
|
||||
}
|
||||
|
||||
# check ConfigItem attribute values
|
||||
my $ConfigItemCheck = $Self->_CheckConfigItem( ConfigItem => $ConfigItem );
|
||||
|
||||
if ( !$ConfigItemCheck->{Success} ) {
|
||||
return $Self->ReturnError( %{$ConfigItemCheck} );
|
||||
}
|
||||
|
||||
# check create permissions
|
||||
my $Permission = $Kernel::OM->Get('Kernel::System::ITSMConfigItem')->Permission(
|
||||
Scope => 'Class',
|
||||
ClassID => $Self->{ReverseClassList}->{ $ConfigItem->{Class} },
|
||||
UserID => $UserID,
|
||||
Type => $Self->{Config}->{Permission},
|
||||
);
|
||||
|
||||
if ( !$Permission ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.AccessDenied",
|
||||
ErrorMessage => "$Self->{OperationName}: Can not create configuration items!",
|
||||
);
|
||||
}
|
||||
|
||||
my $Attachment;
|
||||
my @AttachmentList;
|
||||
|
||||
if ( defined $Param{Data}->{ConfigItem}->{Attachment} ) {
|
||||
|
||||
# isolate Attachment parameter
|
||||
$Attachment = delete $Param{Data}->{ConfigItem}->{Attachment};
|
||||
|
||||
# homologate imput to array
|
||||
if ( IsHashRefWithData($Attachment) ) {
|
||||
push @AttachmentList, $Attachment;
|
||||
}
|
||||
elsif ( IsArrayRefWithData($Attachment) ) {
|
||||
@AttachmentList = @{$Attachment};
|
||||
}
|
||||
else {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: ConfigItem->Attachment parameter is invalid!",
|
||||
);
|
||||
}
|
||||
|
||||
# check Attachment internal structure
|
||||
for my $AttachmentItem (@AttachmentList) {
|
||||
if ( !IsHashRefWithData($AttachmentItem) ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: ConfigItem->Attachment parameter is invalid!",
|
||||
);
|
||||
}
|
||||
|
||||
# remove leading and trailing spaces
|
||||
for my $Attribute ( sort keys %{$AttachmentItem} ) {
|
||||
if ( ref $Attribute ne 'HASH' && ref $Attribute ne 'ARRAY' ) {
|
||||
|
||||
#remove leading spaces
|
||||
$AttachmentItem->{$Attribute} =~ s{\A\s+}{};
|
||||
|
||||
#remove trailing spaces
|
||||
$AttachmentItem->{$Attribute} =~ s{\s+\z}{};
|
||||
}
|
||||
}
|
||||
|
||||
# check Attachment attribute values
|
||||
my $AttachmentCheck = $Self->_CheckAttachment( Attachment => $AttachmentItem );
|
||||
|
||||
if ( !$AttachmentCheck->{Success} ) {
|
||||
return $Self->ReturnError( %{$AttachmentCheck} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $Self->_ConfigItemCreate(
|
||||
ConfigItem => $ConfigItem,
|
||||
AttachmentList => \@AttachmentList,
|
||||
UserID => $UserID,
|
||||
);
|
||||
}
|
||||
|
||||
=head1 INTERNAL INTERFACE
|
||||
|
||||
=head2 _CleanXMLData()
|
||||
|
||||
removed trailing and leading white spaces in the XMLData.
|
||||
|
||||
my $XMLDataClean = $OperationObject->_CleanXMLData(
|
||||
Definition => $DefinitionArrayRef, # Config Item Definition ot just part of it
|
||||
XMLData => $XMLDataHashRef,
|
||||
);
|
||||
|
||||
returns:
|
||||
|
||||
$XMLDataClean = {
|
||||
Success => 1, # if everything is OK
|
||||
}
|
||||
|
||||
$XMLDataClean = {
|
||||
ErrorCode => 'Function.Error', # if error
|
||||
ErrorMessage => 'Error description',
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub _CleanXMLData {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $XMLData = $Param{XMLData};
|
||||
|
||||
KEY:
|
||||
for my $Key ( sort keys %{$XMLData} ) {
|
||||
if ( ref $XMLData->{$Key} eq 'ARRAY' ) {
|
||||
ELEMENT:
|
||||
for my $Element ( @{ $XMLData->{$Key} } ) {
|
||||
if ( ref $Element eq 'HASH' ) {
|
||||
|
||||
# start recursion
|
||||
$Self->_CleanXMLData( XMLData => $Element );
|
||||
next ELEMENT;
|
||||
}
|
||||
elsif ( ref $Element eq '' ) {
|
||||
|
||||
#remove leading spaces
|
||||
$Element =~ s{\A\s+}{};
|
||||
|
||||
#remove trailing spaces
|
||||
$Element =~ s{\s+\z}{};
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ( ref $XMLData->{$Key} eq 'HASH' ) {
|
||||
|
||||
# start recursion
|
||||
$Self->_CleanXMLData( XMLData => $XMLData->{$Key} );
|
||||
next KEY;
|
||||
|
||||
}
|
||||
elsif ( ref $XMLData->{$Key} eq '' ) {
|
||||
|
||||
#remove leading spaces
|
||||
$XMLData->{$Key} =~ s{\A\s+}{};
|
||||
|
||||
#remove trailing spaces
|
||||
$XMLData->{$Key} =~ s{\s+\z}{};
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 _CheckConfigItem()
|
||||
|
||||
checks if the given config item parameters are valid.
|
||||
|
||||
my $ConfigItemCheck = $OperationObject->_CheckConfigItem(
|
||||
ConfigItem => $ConfigItem, # all config item parameters
|
||||
);
|
||||
|
||||
returns:
|
||||
|
||||
$ConfigItemCheck = {
|
||||
Success => 1, # if everything is OK
|
||||
}
|
||||
|
||||
$ConfigItemCheck = {
|
||||
ErrorCode => 'Function.Error', # if error
|
||||
ErrorMessage => 'Error description',
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub _CheckConfigItem {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $ConfigItem = $Param{ConfigItem};
|
||||
|
||||
# check config item internally
|
||||
for my $Needed (qw(Class Name DeplState InciState)) {
|
||||
if ( !$ConfigItem->{$Needed} ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: ConfigItem->$Needed parameter is missing!",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
# check ConfigItem->Class
|
||||
if ( !$Self->ValidateClass( %{$ConfigItem} ) ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: ConfigItem->Class parameter is invalid!",
|
||||
};
|
||||
}
|
||||
|
||||
# check ConfigItem->DeplState
|
||||
if ( !$Self->ValidateDeplState( %{$ConfigItem} ) ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: ConfigItem->DeplState parameter is invalid!",
|
||||
};
|
||||
}
|
||||
|
||||
# check ConfigItem->DeplState
|
||||
if ( !$Self->ValidateInciState( %{$ConfigItem} ) ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: ConfigItem->InciState parameter is invalid!",
|
||||
};
|
||||
}
|
||||
|
||||
# get last config item defintion
|
||||
my $DefinitionData = $Kernel::OM->Get('Kernel::System::ITSMConfigItem')->DefinitionGet(
|
||||
ClassID => $Self->{ReverseClassList}->{ $ConfigItem->{Class} },
|
||||
);
|
||||
|
||||
my $XMLDataCheckResult = $Self->CheckXMLData(
|
||||
Definition => $DefinitionData->{DefinitionRef},
|
||||
XMLData => $ConfigItem->{CIXMLData},
|
||||
);
|
||||
|
||||
if ( !$XMLDataCheckResult->{Success} ) {
|
||||
return $XMLDataCheckResult;
|
||||
}
|
||||
|
||||
# if everything is OK then return Success
|
||||
return {
|
||||
Success => 1,
|
||||
};
|
||||
}
|
||||
|
||||
=head2 _CheckAttachment()
|
||||
|
||||
checks if the given attachment parameter is valid.
|
||||
|
||||
my $AttachmentCheck = $OperationObject->_CheckAttachment(
|
||||
Attachment => $Attachment, # all attachment parameters
|
||||
);
|
||||
|
||||
returns:
|
||||
|
||||
$AttachmentCheck = {
|
||||
Success => 1, # if everething is OK
|
||||
}
|
||||
|
||||
$AttachmentCheck = {
|
||||
ErrorCode => 'Function.Error', # if error
|
||||
ErrorMessage => 'Error description',
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub _CheckAttachment {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Attachment = $Param{Attachment};
|
||||
|
||||
# check attachment item internally
|
||||
for my $Needed (qw(Content ContentType Filename)) {
|
||||
if ( !$Attachment->{$Needed} ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: Attachment->$Needed parameter is missing!",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
# check Article->ContentType
|
||||
if ( $Attachment->{ContentType} ) {
|
||||
|
||||
$Attachment->{ContentType} = lc $Attachment->{ContentType};
|
||||
|
||||
# check Charset part
|
||||
my $Charset = '';
|
||||
if ( $Attachment->{ContentType} =~ /charset=/i ) {
|
||||
$Charset = $Attachment->{ContentType};
|
||||
$Charset =~ s/.+?charset=("|'|)(\w+)/$2/gi;
|
||||
$Charset =~ s/"|'//g;
|
||||
$Charset =~ s/(.+?);.*/$1/g;
|
||||
}
|
||||
|
||||
if ( $Charset && !$Self->ValidateCharset( Charset => $Charset ) )
|
||||
{
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: Attachment->ContentType is invalid!",
|
||||
};
|
||||
}
|
||||
|
||||
# check MimeType part
|
||||
my $MimeType = '';
|
||||
if ( $Attachment->{ContentType} =~ /^(\w+\/\w+)/i ) {
|
||||
$MimeType = $1;
|
||||
$MimeType =~ s/"|'//g;
|
||||
}
|
||||
|
||||
if ( !$Self->ValidateMimeType( MimeType => $MimeType ) ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: Attachment->ContentType is invalid!",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
# if everything is OK then return Success
|
||||
return {
|
||||
Success => 1,
|
||||
};
|
||||
}
|
||||
|
||||
=head2 _ConfigItemCreate()
|
||||
|
||||
creates a configuration item with attachments if specified.
|
||||
|
||||
my $Response = $OperationObject->_ConfigItemCreate(
|
||||
ConfigItem => $ConfigItem, # all configuration item parameters
|
||||
AttachmentList => $Attachment, # a list of all attachments
|
||||
UserID => 123,
|
||||
);
|
||||
|
||||
returns:
|
||||
|
||||
$Response = {
|
||||
Success => 1, # if everething is OK
|
||||
Data => {
|
||||
ConfigItemID => 123,
|
||||
ConfigItemNumber => 'CN123',
|
||||
}
|
||||
}
|
||||
|
||||
$Response = {
|
||||
Success => 0, # if unexpected error
|
||||
ErrorMessage => "$Param{ErrorCode}: $Param{ErrorMessage}",
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub _ConfigItemCreate {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $ConfigItem = $Param{ConfigItem};
|
||||
my $AttachmentList = $Param{AttachmentList};
|
||||
|
||||
my $DeplStateID = $Self->{ReverseDeplStateList}->{ $ConfigItem->{DeplState} };
|
||||
my $InciStateID = $Self->{ReverseInciStateList}->{ $ConfigItem->{InciState} };
|
||||
|
||||
my $RawXMLData = $ConfigItem->{CIXMLData};
|
||||
|
||||
my $ConfigItemObject = $Kernel::OM->Get('Kernel::System::ITSMConfigItem');
|
||||
|
||||
# get last config item defintion
|
||||
my $DefinitionData = $ConfigItemObject->DefinitionGet(
|
||||
ClassID => $Self->{ReverseClassList}->{ $ConfigItem->{Class} },
|
||||
);
|
||||
|
||||
# replace date, date time, customer, company and general catalog values
|
||||
my $ReplacedXMLData = $Self->ReplaceXMLData(
|
||||
XMLData => $RawXMLData,
|
||||
Definition => $DefinitionData->{DefinitionRef},
|
||||
);
|
||||
|
||||
# create an XMLData structure suitable for VersionAdd
|
||||
my $XMLData = $Self->FormatXMLData(
|
||||
XMLData => $ReplacedXMLData,
|
||||
);
|
||||
|
||||
# create new config item
|
||||
my $ConfigItemID = $ConfigItemObject->ConfigItemAdd(
|
||||
Number => $ConfigItem->{Number},
|
||||
ClassID => $Self->{ReverseClassList}->{ $ConfigItem->{Class} },
|
||||
UserID => $Param{UserID},
|
||||
);
|
||||
|
||||
my $VersionID = $ConfigItemObject->VersionAdd(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
Name => $ConfigItem->{Name},
|
||||
DefinitionID => $DefinitionData->{DefinitionID},
|
||||
DeplStateID => $DeplStateID,
|
||||
InciStateID => $InciStateID,
|
||||
XMLData => $XMLData,
|
||||
UserID => $Param{UserID},
|
||||
);
|
||||
|
||||
if ( !$ConfigItemID && !$VersionID ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => 'Configuration Item could not be created, please contact the system'
|
||||
. 'administrator',
|
||||
};
|
||||
}
|
||||
|
||||
# set attachments
|
||||
if ( IsArrayRefWithData($AttachmentList) ) {
|
||||
|
||||
for my $Attachment ( @{$AttachmentList} ) {
|
||||
my $Result = $Self->CreateAttachment(
|
||||
Attachment => $Attachment,
|
||||
ConfigItemID => $ConfigItemID,
|
||||
UserID => $Param{UserID},
|
||||
);
|
||||
|
||||
if ( !$Result->{Success} ) {
|
||||
my $ErrorMessage =
|
||||
$Result->{ErrorMessage} || "Attachment could not be created, please contact"
|
||||
. " the system administrator";
|
||||
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => $ErrorMessage,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# get ConfigItem data
|
||||
my $ConfigItemData = $ConfigItemObject->ConfigItemGet(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData($ConfigItemData) ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => 'Could not get new configuration item information, please contact the'
|
||||
. ' system administrator',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
Success => 1,
|
||||
Data => {
|
||||
ConfigItemID => $ConfigItemID,
|
||||
Number => $ConfigItemData->{Number},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
@@ -0,0 +1,214 @@
|
||||
# --
|
||||
# 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::ConfigItemDelete;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use MIME::Base64;
|
||||
use Kernel::System::VariableCheck qw(:all);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
Kernel::GenericInterface::Operation::ConfigItem::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::ConfigItem::ConfigItemDelete - GenericInterface Configuration Item Delete Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# check needed objects
|
||||
for my $Needed (qw(DebuggerObject WebserviceID)) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!",
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
$Self->{OperationName} = 'ConfigItemDelete';
|
||||
|
||||
$Self->{Config} = $Kernel::OM->Get('Kernel::Config')->Get('GenericInterface::Operation::ConfigItemDelete');
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform ConfigItemDelete Operation. This function is able to return
|
||||
one or more ConfigItem entries in one call.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => {
|
||||
UserLogin => 'some agent login', # UserLogin or CustomerUserLogin or SessionID is
|
||||
# required
|
||||
CustomerUserLogin => 'some customer login',
|
||||
SessionID => 123,
|
||||
|
||||
Password => 'some password', # if UserLogin or customerUserLogin is sent then
|
||||
# Password is required
|
||||
ConfigItemID => '32,33', # required, could be coma separated IDs or an Array
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # in case of error
|
||||
Data => { # result data payload after Operation
|
||||
ConfigItemID => [123, 456], # Configuration Item IDs number in OTRS::ITSM (Service desk system)
|
||||
Error => { # should not return errors
|
||||
ErrorCode => 'ConfigItemDelete.ErrorCode'
|
||||
ErrorMessage => 'Error Description'
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Result = $Self->Init(
|
||||
WebserviceID => $Self->{WebserviceID},
|
||||
);
|
||||
|
||||
if ( !$Result->{Success} ) {
|
||||
$Self->ReturnError(
|
||||
ErrorCode => 'Webservice.InvalidConfiguration',
|
||||
ErrorMessage => $Result->{ErrorMessage},
|
||||
);
|
||||
}
|
||||
|
||||
my ( $UserID, $UserType ) = $Self->Auth(
|
||||
%Param
|
||||
);
|
||||
|
||||
if ( !$UserID ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => '$Self->{OperationName}.AuthFail',
|
||||
ErrorMessage => "$Self->{OperationName}: Authorization failing!",
|
||||
);
|
||||
}
|
||||
|
||||
# check needed stuff
|
||||
for my $Needed (qw(ConfigItemID)) {
|
||||
if ( !$Param{Data}->{$Needed} ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: $Needed parameter is missing!",
|
||||
);
|
||||
}
|
||||
}
|
||||
my $ErrorMessage = '';
|
||||
|
||||
# all needed variables
|
||||
my @ConfigItemIDs;
|
||||
if ( IsStringWithData( $Param{Data}->{ConfigItemID} ) ) {
|
||||
@ConfigItemIDs = split /\s*,\s*/, $Param{Data}->{ConfigItemID};
|
||||
}
|
||||
elsif ( IsArrayRefWithData( $Param{Data}->{ConfigItemID} ) ) {
|
||||
@ConfigItemIDs = @{ $Param{Data}->{ConfigItemID} };
|
||||
}
|
||||
else {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.WrongStructure",
|
||||
ErrorMessage => "$Self->{OperationName}: Structure for ConfigItemID is not correct!",
|
||||
);
|
||||
}
|
||||
|
||||
my $ConfigItemObject = $Kernel::OM->Get('Kernel::System::ITSMConfigItem');
|
||||
|
||||
my @DeletedConfigItemIDs;
|
||||
|
||||
# start ConfigItem loop
|
||||
CONFIGITEM:
|
||||
for my $ConfigItemID (@ConfigItemIDs) {
|
||||
|
||||
# check create permissions
|
||||
my $Permission = $ConfigItemObject->Permission(
|
||||
Scope => 'Item',
|
||||
ItemID => $ConfigItemID,
|
||||
UserID => $UserID,
|
||||
Type => $Self->{Config}->{Permission},
|
||||
);
|
||||
|
||||
if ( !$Permission ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.AccessDenied",
|
||||
ErrorMessage => "$Self->{OperationName}: Can not delete configuration item!",
|
||||
);
|
||||
}
|
||||
|
||||
# delete the configitem
|
||||
my $DeleteSuccess = $ConfigItemObject->ConfigItemDelete(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
UserID => $UserID,
|
||||
);
|
||||
|
||||
if ( !$DeleteSuccess ) {
|
||||
|
||||
$ErrorMessage = 'Could not delete ConfigItem ID ' . $ConfigItemID
|
||||
. ' in Kernel::GenericInterface::Operation::ConfigItem::ConfigItemDelete::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => '$Self->{OperationName}.DeleteError',
|
||||
ErrorMessage => "$Self->{OperationName}: $ErrorMessage",
|
||||
);
|
||||
}
|
||||
|
||||
push @DeletedConfigItemIDs, $ConfigItemID;
|
||||
|
||||
} # finish ConfigItem loop
|
||||
|
||||
if ( !IsArrayRefWithData( \@DeletedConfigItemIDs ) ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => 'Could not delete ConfigItems!',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
Success => 1,
|
||||
Data => {
|
||||
ConfigItemID => \@DeletedConfigItemIDs,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
@@ -0,0 +1,324 @@
|
||||
# --
|
||||
# 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::ConfigItemGet;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## nofilter(TidyAll::Plugin::OTRS::Migrations::OTRS6::SysConfig)
|
||||
|
||||
use MIME::Base64;
|
||||
use Kernel::System::VariableCheck qw(:all);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
Kernel::GenericInterface::Operation::ConfigItem::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::ConfigItem::ConfigItemGet - GenericInterface Configuration Item Get Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# check needed objects
|
||||
for my $Needed (qw( DebuggerObject WebserviceID )) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!",
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
$Self->{OperationName} = 'ConfigItemGet';
|
||||
|
||||
$Self->{Config} = $Kernel::OM->Get('Kernel::Config')->Get('GenericInterface::Operation::ConfigItemGet');
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform ConfigItemGet Operation. This function is able to return
|
||||
one or more ConfigItem entries in one call.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => {
|
||||
UserLogin => 'some agent login', # UserLogin or SessionID is
|
||||
SessionID => 123, # required
|
||||
Password => 'some password', # if UserLogin is sent then Password is required
|
||||
ConfigItemID => '32,33', # required, could be coma separated IDs or an Array
|
||||
Attachments => 1, # Optional, 1 as default. If it's set with the value 1,
|
||||
# attachments for articles will be included on ConfigItem data
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # In case of an error
|
||||
Data => {
|
||||
ConfigItem => [
|
||||
{
|
||||
|
||||
Number => '20101027000001',
|
||||
ConfigItemID => 123,
|
||||
Name => 'some name',
|
||||
Class => 'some class',
|
||||
VersionID => 123,
|
||||
LastVersionID => 123,
|
||||
DefinitionID => 123,
|
||||
InciState => 'some incident state',
|
||||
InciStateType => 'some incident state type',
|
||||
DeplState => 'some deployment state',
|
||||
DeplStateType => 'some deployment state type',
|
||||
CurInciState => 'some incident state',
|
||||
CurInciStateType => 'some incident state type',
|
||||
CurDeplState => 'some deployment state',
|
||||
CurDeplStateType => 'some deployment state type',
|
||||
CreateTime => '2010-10-27 20:15:00'
|
||||
CreateBy => 123,
|
||||
CIXMLData => $XMLDataHashRef,
|
||||
|
||||
Attachment => [
|
||||
{
|
||||
Content => "xxxx", # actual attachment contents, base64 enconded
|
||||
ContentType => "application/pdf",
|
||||
Filename => "StdAttachment-Test1.pdf",
|
||||
Filesize => "4.6 KBytes",
|
||||
Preferences => $PreferencesHashRef,
|
||||
},
|
||||
{
|
||||
# . . .
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
# . . .
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Result = $Self->Init(
|
||||
WebserviceID => $Self->{WebserviceID},
|
||||
);
|
||||
|
||||
if ( !$Result->{Success} ) {
|
||||
$Self->ReturnError(
|
||||
ErrorCode => 'Webservice.InvalidConfiguration',
|
||||
ErrorMessage => $Result->{ErrorMessage},
|
||||
);
|
||||
}
|
||||
|
||||
my ( $UserID, $UserType ) = $Self->Auth(
|
||||
%Param
|
||||
);
|
||||
|
||||
if ( !$UserID ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => '$Self->{OperationName}.AuthFail',
|
||||
ErrorMessage => "$Self->{OperationName}: Authorization failing!",
|
||||
);
|
||||
}
|
||||
|
||||
# check needed stuff
|
||||
for my $Needed (qw(ConfigItemID)) {
|
||||
if ( !$Param{Data}->{$Needed} ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: $Needed parameter is missing!",
|
||||
);
|
||||
}
|
||||
}
|
||||
my $ErrorMessage = '';
|
||||
|
||||
# all needed variables
|
||||
my @ConfigItemIDs;
|
||||
if ( IsStringWithData( $Param{Data}->{ConfigItemID} ) ) {
|
||||
@ConfigItemIDs = split( /,/, $Param{Data}->{ConfigItemID} );
|
||||
}
|
||||
elsif ( IsArrayRefWithData( $Param{Data}->{ConfigItemID} ) ) {
|
||||
@ConfigItemIDs = @{ $Param{Data}->{ConfigItemID} };
|
||||
}
|
||||
else {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.WrongStructure",
|
||||
ErrorMessage => "$Self->{OperationName}: Structure for ConfigItemID is not correct!",
|
||||
);
|
||||
}
|
||||
my $Attachments = $Param{Data}->{Attachments} || 0;
|
||||
my $ReturnData = {
|
||||
Success => 1,
|
||||
};
|
||||
|
||||
my @Item;
|
||||
|
||||
my $ConfigItemObject = $Kernel::OM->Get('Kernel::System::ITSMConfigItem');
|
||||
|
||||
# start ConfigItem loop
|
||||
CONFIGITEM:
|
||||
for my $ConfigItemID (@ConfigItemIDs) {
|
||||
|
||||
# check create permissions
|
||||
my $Permission = $ConfigItemObject->Permission(
|
||||
Scope => 'Item',
|
||||
ItemID => $ConfigItemID,
|
||||
UserID => $UserID,
|
||||
Type => $Self->{Config}->{Permission},
|
||||
);
|
||||
|
||||
if ( !$Permission ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.AccessDenied",
|
||||
ErrorMessage => "$Self->{OperationName}: Can not get configuration item!",
|
||||
);
|
||||
}
|
||||
|
||||
# get the ConfigItem entry
|
||||
my $ConfigItem = $ConfigItemObject->ConfigItemGet(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
UserID => $UserID,
|
||||
);
|
||||
|
||||
# get latest version
|
||||
my $Version = $ConfigItemObject->VersionGet(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
UserID => $UserID,
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData($Version) ) {
|
||||
|
||||
$ErrorMessage = 'Could not get ConfigItem data'
|
||||
. ' in Kernel::GenericInterface::Operation::ConfigItem::ConfigItemGet::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => '$Self->{OperationName}.InvalidParameter',
|
||||
ErrorMessage => "$Self->{OperationName}: $ErrorMessage",
|
||||
);
|
||||
}
|
||||
|
||||
# remove unneeded items
|
||||
delete $Version->{ClassID};
|
||||
delete $Version->{CurDeplStateID};
|
||||
delete $Version->{CurInciStateID};
|
||||
delete $Version->{DeplStateID};
|
||||
delete $Version->{InciStateID};
|
||||
delete $Version->{XMLDefinitionID};
|
||||
|
||||
my $Definition = delete $Version->{XMLDefinition};
|
||||
|
||||
my $FormatedXMLData = $Self->InvertFormatXMLData(
|
||||
XMLData => $Version->{XMLData}->[1]->{Version},
|
||||
);
|
||||
|
||||
my $ReplacedXMLData = $Self->InvertReplaceXMLData(
|
||||
XMLData => $FormatedXMLData,
|
||||
Definition => $Definition,
|
||||
);
|
||||
|
||||
$Version->{XMLData} = $ReplacedXMLData;
|
||||
|
||||
# rename XMLData since SOAP transport complains about XML prefix on names
|
||||
$Version->{CIXMLData} = delete $Version->{XMLData};
|
||||
|
||||
# set ConfigItem entry data
|
||||
my $ConfigItemBundle = $Version;
|
||||
|
||||
if ($Attachments) {
|
||||
|
||||
my @Attachments = $ConfigItemObject->ConfigItemAttachmentList(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
);
|
||||
|
||||
my @AttachmentDetails;
|
||||
ATTACHMENT:
|
||||
for my $Filename (@Attachments) {
|
||||
|
||||
next ATTACHMENT if !$Filename;
|
||||
|
||||
my $Attachment = $ConfigItemObject->ConfigItemAttachmentGet(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
Filename => $Filename,
|
||||
);
|
||||
|
||||
# next if not attachment
|
||||
next ATTACHMENT if !IsHashRefWithData($Attachment);
|
||||
|
||||
# convert content to base64
|
||||
$Attachment->{Content} = encode_base64( $Attachment->{Content} );
|
||||
push @AttachmentDetails, $Attachment;
|
||||
}
|
||||
|
||||
# set ConfigItem entry data
|
||||
$ConfigItemBundle->{Attachment} = '';
|
||||
if ( IsArrayRefWithData( \@AttachmentDetails ) ) {
|
||||
$ConfigItemBundle->{Attachment} = \@AttachmentDetails;
|
||||
}
|
||||
}
|
||||
|
||||
# add
|
||||
push @Item, $ConfigItemBundle;
|
||||
|
||||
} # finish ConfigItem loop
|
||||
|
||||
if ( !scalar @Item ) {
|
||||
$ErrorMessage = 'Could not get ConfigItem data'
|
||||
. ' in Kernel::GenericInterface::Operation::ConfigItem::ConfigItemGet::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => '$Self->{OperationName}.NoConfigItemData',
|
||||
ErrorMessage => "$Self->{OperationName}: $ErrorMessage",
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
# set ConfigItem data into return structure
|
||||
$ReturnData->{Data}->{ConfigItem} = '';
|
||||
if ( IsArrayRefWithData( \@Item ) ) {
|
||||
$ReturnData->{Data}->{ConfigItem} = \@Item;
|
||||
}
|
||||
|
||||
# return result
|
||||
return $ReturnData;
|
||||
}
|
||||
|
||||
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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,848 @@
|
||||
# --
|
||||
# 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::ConfigItemUpdate;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## nofilter(TidyAll::Plugin::OTRS::Migrations::OTRS6::SysConfig)
|
||||
|
||||
use Kernel::System::VariableCheck qw(:all);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
Kernel::GenericInterface::Operation::ConfigItem::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::ConfigItem::ConfigItemUpdate - GenericInterface ConfigItem ConfigItemUpdate Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# check needed objects
|
||||
for my $Needed (qw(DebuggerObject WebserviceID)) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!",
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
# define operation name
|
||||
$Self->{OperationName} = 'ConfigItemUpdate';
|
||||
|
||||
$Self->{Config} = $Kernel::OM->Get('Kernel::Config')->Get('GenericInterface::Operation::ConfigItemUpdate');
|
||||
|
||||
$Self->{Config}->{DefaultValue} = 'Not Defined';
|
||||
|
||||
my $GeneralCatalogObject = $Kernel::OM->Get('Kernel::System::GeneralCatalog');
|
||||
|
||||
# get a list of all config item classes
|
||||
$Self->{ClassList} = $GeneralCatalogObject->ItemList(
|
||||
Class => 'ITSM::ConfigItem::Class',
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData( $Self->{ClassList} ) ) {
|
||||
return $Self->{DebuggerObject}->Error(
|
||||
Summary => 'Error when trying to get class listing of ITSM::ConfigItem::Class',
|
||||
);
|
||||
}
|
||||
|
||||
# get a list of all incistates
|
||||
$Self->{InciStateList} = $GeneralCatalogObject->ItemList(
|
||||
Class => 'ITSM::Core::IncidentState',
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData( $Self->{InciStateList} ) ) {
|
||||
return $Self->{DebuggerObject}->Error(
|
||||
Summary => 'Error when trying to get incident state listing of'
|
||||
. ' ITSM::Core::IncidentState',
|
||||
);
|
||||
}
|
||||
|
||||
# get a list of all deplstates
|
||||
$Self->{DeplStateList} = $GeneralCatalogObject->ItemList(
|
||||
Class => 'ITSM::ConfigItem::DeploymentState',
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData( $Self->{DeplStateList} ) ) {
|
||||
return $Self->{DebuggerObject}->Error(
|
||||
Summary => 'Error when trying to get incident state listing of'
|
||||
. ' ITSM::ConfigItem::DeploymentState',
|
||||
);
|
||||
}
|
||||
|
||||
# also provide the classlist in reversed form for easier reverse lookups
|
||||
my %ReverseClassList = reverse %{ $Self->{ClassList} };
|
||||
$Self->{ReverseClassList} = \%ReverseClassList;
|
||||
|
||||
# also provide the incistatelist in reversed form for easier reverse lookups
|
||||
my %ReverseInciStateList = reverse %{ $Self->{InciStateList} };
|
||||
$Self->{ReverseInciStateList} = \%ReverseInciStateList;
|
||||
|
||||
# also provide the deplstatelist in reversed form for easier reverse lookups
|
||||
my %ReverseDeplStateList = reverse %{ $Self->{DeplStateList} };
|
||||
$Self->{ReverseDeplStateList} = \%ReverseDeplStateList;
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform ConfigItemUpdate Operation. This will return the updated config item number.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => {
|
||||
UserLogin => 'some agent login', # UserLogin or SessionID is
|
||||
SessionID => 123, # required
|
||||
|
||||
Password => 'some password', # if UserLogin is sent then Password is required
|
||||
|
||||
ReplaceExistingData => 0, # optional, 0 or 1, default 0
|
||||
# this will replace the existing XML data and attachments
|
||||
ConfigItemID => 123,
|
||||
|
||||
ConfigItem => {
|
||||
Class => 'Config Item Class',
|
||||
Name => 'The Name',
|
||||
DeplState => 'deployment state',
|
||||
InciState => 'incident state',
|
||||
CIXMLData => $ArrayHashRef, # it depends on the Configuration Item class and definition
|
||||
|
||||
Attachment => [
|
||||
{
|
||||
Content => 'content' # base64 encoded
|
||||
ContentType => 'some content type'
|
||||
Filename => 'some fine name'
|
||||
},
|
||||
# ...
|
||||
],
|
||||
# or
|
||||
#Attachment => {
|
||||
# Content => 'content'
|
||||
# ContentType => 'some content type'
|
||||
# Filename => 'some fine name'
|
||||
#},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # in case of error
|
||||
Data => { # result data payload after Operation
|
||||
ConfigItemID => 123, # Configuration Item ID number in OTRS::ITSM (Service desk system)
|
||||
Number => 2324454323322 # Configuration Item Number in OTRS::ITSM (Service desk system)
|
||||
Error => { # should not return errors
|
||||
ErrorCode => 'ConfigItemUpdate.ErrorCode'
|
||||
ErrorMessage => 'Error Description'
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Result = $Self->Init(
|
||||
WebserviceID => $Self->{WebserviceID},
|
||||
);
|
||||
|
||||
if ( !$Result->{Success} ) {
|
||||
$Self->ReturnError(
|
||||
ErrorCode => 'Webservice.InvalidConfiguration',
|
||||
ErrorMessage => $Result->{ErrorMessage},
|
||||
);
|
||||
}
|
||||
|
||||
# check needed stuff
|
||||
if (
|
||||
!$Param{Data}->{UserLogin}
|
||||
&& !$Param{Data}->{SessionID}
|
||||
)
|
||||
{
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: UserLogin or SessionID is required!",
|
||||
);
|
||||
}
|
||||
|
||||
if ( $Param{Data}->{UserLogin} ) {
|
||||
|
||||
if ( !$Param{Data}->{Password} )
|
||||
{
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: Password or SessionID is required!",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# authenticate user
|
||||
my ( $UserID, $UserType ) = $Self->Auth(%Param);
|
||||
|
||||
if ( !$UserID ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.AuthFail",
|
||||
ErrorMessage => "$Self->{OperationName}: User could not be authenticated!",
|
||||
);
|
||||
}
|
||||
|
||||
# check needed hashes
|
||||
for my $Needed (qw(ConfigItem)) {
|
||||
if ( !IsHashRefWithData( $Param{Data}->{$Needed} ) ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: $Needed parameter is missing or not valid!",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# check needed items
|
||||
for my $Needed (qw(ConfigItemID)) {
|
||||
if ( !IsPositiveInteger( $Param{Data}->{$Needed} ) ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: $Needed parameter is missing or not valid!",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# check for valid ConfigItemID
|
||||
my $ConfigItemID = $Param{Data}->{ConfigItemID};
|
||||
|
||||
# get config item object
|
||||
my $ConfigItemObject = $Kernel::OM->Get('Kernel::System::ITSMConfigItem');
|
||||
|
||||
# get ConfigItem data
|
||||
my $ConfigItemData = $ConfigItemObject->ConfigItemGet(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData($ConfigItemData) ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: ConfigItemID is invalid!",
|
||||
);
|
||||
}
|
||||
|
||||
# isolate config item parameter
|
||||
my $ConfigItem = $Param{Data}->{ConfigItem};
|
||||
|
||||
# remove leading and trailing spaces
|
||||
for my $Attribute ( sort keys %{$ConfigItem} ) {
|
||||
if ( ref $Attribute ne 'HASH' && ref $Attribute ne 'ARRAY' ) {
|
||||
|
||||
# remove leading spaces
|
||||
$ConfigItem->{$Attribute} =~ s{\A\s+}{};
|
||||
|
||||
# remove trailing spaces
|
||||
$ConfigItem->{$Attribute} =~ s{\s+\z}{};
|
||||
}
|
||||
}
|
||||
|
||||
# if the parameter ReplaceExistingData is set to 0 or if it is missing
|
||||
# then missing, empty or only partially defined CIXMLData parameter attributes are allowed
|
||||
# in this case the existing CIXMLData is used for the missing parts.
|
||||
# A missing (undefined) CIXMLData attribute has the same effect
|
||||
# the ReplaceExistingData parameter also influences if existing attachments should be replaced or kept
|
||||
if ( !$Param{Data}->{ReplaceExistingData} || !defined $ConfigItem->{CIXMLData} ) {
|
||||
|
||||
# set to empty hash reference if empty or not defined
|
||||
$ConfigItem->{CIXMLData} ||= {};
|
||||
|
||||
# CIXMLData must be a hash reference
|
||||
if ( ref $ConfigItem->{CIXMLData} ne 'HASH' ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: ConfigItem->CIXMLData is missing or invalid!",
|
||||
);
|
||||
}
|
||||
|
||||
# get latest version data from configitem
|
||||
my $Version = $ConfigItemObject->VersionGet(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
UserID => $UserID,
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData($Version) ) {
|
||||
|
||||
my $ErrorMessage = 'Could not get ConfigItem data'
|
||||
. ' in Kernel::GenericInterface::Operation::ConfigItem::ConfigItemUpdate::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => '$Self->{OperationName}.InvalidParameter',
|
||||
ErrorMessage => "$Self->{OperationName}: $ErrorMessage",
|
||||
);
|
||||
}
|
||||
|
||||
# remove unneeded items
|
||||
delete $Version->{ClassID};
|
||||
delete $Version->{CurDeplStateID};
|
||||
delete $Version->{CurInciStateID};
|
||||
delete $Version->{DeplStateID};
|
||||
delete $Version->{InciStateID};
|
||||
delete $Version->{XMLDefinitionID};
|
||||
|
||||
my $Definition = delete $Version->{XMLDefinition};
|
||||
|
||||
my $FormatedXMLData = $Self->InvertFormatXMLData(
|
||||
XMLData => $Version->{XMLData}->[1]->{Version},
|
||||
);
|
||||
|
||||
my $ReplacedXMLData = $Self->InvertReplaceXMLData(
|
||||
XMLData => $FormatedXMLData,
|
||||
Definition => $Definition,
|
||||
);
|
||||
|
||||
$Version->{XMLData} = $ReplacedXMLData;
|
||||
|
||||
# rename XMLData since SOAP transport complains about XML prefix on names
|
||||
$Version->{CIXMLData} = delete $Version->{XMLData};
|
||||
|
||||
# merge existing data and new data from parameters
|
||||
$ConfigItem->{CIXMLData} = {
|
||||
%{ $Version->{CIXMLData} },
|
||||
%{ $ConfigItem->{CIXMLData} },
|
||||
};
|
||||
}
|
||||
|
||||
if ( !IsHashRefWithData( $ConfigItem->{CIXMLData} ) ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: ConfigItem->CIXMLData is empty or invalid!",
|
||||
);
|
||||
}
|
||||
|
||||
# remove leading and trailing spaces for CIXMLData
|
||||
$Self->_CleanXMLData( XMLData => $ConfigItem->{CIXMLData} );
|
||||
|
||||
# check ConfigItem attribute values
|
||||
my $ConfigItemCheck = $Self->_CheckConfigItem( ConfigItem => $ConfigItem );
|
||||
|
||||
if ( !$ConfigItemCheck->{Success} ) {
|
||||
return $Self->ReturnError( %{$ConfigItemCheck} );
|
||||
}
|
||||
|
||||
# check update permissions
|
||||
my $Permission = $ConfigItemObject->Permission(
|
||||
Scope => 'Class',
|
||||
ClassID => $Self->{ReverseClassList}->{ $ConfigItem->{Class} },
|
||||
UserID => $UserID,
|
||||
Type => $Self->{Config}->{Permission},
|
||||
);
|
||||
|
||||
if ( !$Permission ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.AccessDenied",
|
||||
ErrorMessage => "$Self->{OperationName}: Can not update configuration items!",
|
||||
);
|
||||
}
|
||||
|
||||
# handle attachments
|
||||
my $Attachment;
|
||||
my @AttachmentList;
|
||||
|
||||
if ( defined $Param{Data}->{ConfigItem}->{Attachment} ) {
|
||||
|
||||
# isolate Attachment parameter
|
||||
$Attachment = delete $Param{Data}->{ConfigItem}->{Attachment};
|
||||
|
||||
# homologate imput to array
|
||||
if ( IsHashRefWithData($Attachment) ) {
|
||||
push @AttachmentList, $Attachment;
|
||||
}
|
||||
elsif ( IsArrayRefWithData($Attachment) ) {
|
||||
@AttachmentList = @{$Attachment};
|
||||
}
|
||||
else {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: ConfigItem->Attachment parameter is invalid!",
|
||||
);
|
||||
}
|
||||
|
||||
# check Attachment internal structure
|
||||
for my $AttachmentItem (@AttachmentList) {
|
||||
if ( !IsHashRefWithData($AttachmentItem) ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: ConfigItem->Attachment parameter is invalid!",
|
||||
);
|
||||
}
|
||||
|
||||
# remove leading and trailing spaces
|
||||
for my $Attribute ( sort keys %{$AttachmentItem} ) {
|
||||
if ( ref $Attribute ne 'HASH' && ref $Attribute ne 'ARRAY' ) {
|
||||
|
||||
#remove leading spaces
|
||||
$AttachmentItem->{$Attribute} =~ s{\A\s+}{};
|
||||
|
||||
#remove trailing spaces
|
||||
$AttachmentItem->{$Attribute} =~ s{\s+\z}{};
|
||||
}
|
||||
}
|
||||
|
||||
# check Attachment attribute values
|
||||
my $AttachmentCheck = $Self->_CheckAttachment( Attachment => $AttachmentItem );
|
||||
|
||||
if ( !$AttachmentCheck->{Success} ) {
|
||||
return $Self->ReturnError( %{$AttachmentCheck} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $Self->_ConfigItemUpdate(
|
||||
ConfigItem => $ConfigItem,
|
||||
ConfigItemID => $ConfigItemID,
|
||||
AttachmentList => \@AttachmentList,
|
||||
ReplaceExistingData => $Param{Data}->{ReplaceExistingData},
|
||||
UserID => $UserID,
|
||||
);
|
||||
}
|
||||
|
||||
=head1 INTERNAL INTERFACE
|
||||
|
||||
=head2 _CleanXMLData()
|
||||
|
||||
removed trailing and leading white spaces in the XMLData.
|
||||
|
||||
my $XMLDataClean = $OperationObject->_CleanXMLData(
|
||||
Definition => $DefinitionArrayRef, # Config Item Definition ot just part of it
|
||||
XMLData => $XMLDataHashRef,
|
||||
);
|
||||
|
||||
returns:
|
||||
|
||||
$XMLDataClean = {
|
||||
Success => 1, # if everything is OK
|
||||
}
|
||||
|
||||
$XMLDataClean = {
|
||||
ErrorCode => 'Function.Error', # if error
|
||||
ErrorMessage => 'Error description',
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub _CleanXMLData {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $XMLData = $Param{XMLData};
|
||||
|
||||
KEY:
|
||||
for my $Key ( sort keys %{$XMLData} ) {
|
||||
if ( ref $XMLData->{$Key} eq 'ARRAY' ) {
|
||||
ELEMENT:
|
||||
for my $Element ( @{ $XMLData->{$Key} } ) {
|
||||
if ( ref $Element eq 'HASH' ) {
|
||||
|
||||
# start recursion
|
||||
$Self->_CleanXMLData( XMLData => $Element );
|
||||
next ELEMENT;
|
||||
}
|
||||
elsif ( ref $Element eq '' ) {
|
||||
|
||||
#remove leading spaces
|
||||
$Element =~ s{\A\s+}{};
|
||||
|
||||
#remove trailing spaces
|
||||
$Element =~ s{\s+\z}{};
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ( ref $XMLData->{$Key} eq 'HASH' ) {
|
||||
|
||||
# start recursion
|
||||
$Self->_CleanXMLData( XMLData => $XMLData->{$Key} );
|
||||
next KEY;
|
||||
|
||||
}
|
||||
elsif ( ref $XMLData->{$Key} eq '' ) {
|
||||
|
||||
# TODO: Use StringClean function!
|
||||
|
||||
#remove leading spaces
|
||||
$XMLData->{$Key} =~ s{\A\s+}{};
|
||||
|
||||
#remove trailing spaces
|
||||
$XMLData->{$Key} =~ s{\s+\z}{};
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 _CheckConfigItem()
|
||||
|
||||
checks if the given config item parameters are valid.
|
||||
|
||||
my $ConfigItemCheck = $OperationObject->_CheckConfigItem(
|
||||
ConfigItem => $ConfigItem, # all config item parameters
|
||||
);
|
||||
|
||||
returns:
|
||||
|
||||
$ConfigItemCheck = {
|
||||
Success => 1, # if everything is OK
|
||||
}
|
||||
|
||||
$ConfigItemCheck = {
|
||||
ErrorCode => 'Function.Error', # if error
|
||||
ErrorMessage => 'Error description',
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub _CheckConfigItem {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $ConfigItem = $Param{ConfigItem};
|
||||
|
||||
# check config item internally
|
||||
for my $Needed (qw(Class Name DeplState InciState CIXMLData)) {
|
||||
if ( !$ConfigItem->{$Needed} ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: ConfigItem->$Needed parameter is missing!",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
# check ConfigItem->Class
|
||||
if ( !$Self->ValidateClass( %{$ConfigItem} ) ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: ConfigItem->Class parameter is invalid!",
|
||||
};
|
||||
}
|
||||
|
||||
# check ConfigItem->DeplState
|
||||
if ( !$Self->ValidateDeplState( %{$ConfigItem} ) ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: ConfigItem->DeplState parameter is invalid!",
|
||||
};
|
||||
}
|
||||
|
||||
# check ConfigItem->DeplState
|
||||
if ( !$Self->ValidateInciState( %{$ConfigItem} ) ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: ConfigItem->InciState parameter is invalid!",
|
||||
};
|
||||
}
|
||||
|
||||
# get last config item defintion
|
||||
my $DefinitionData = $Kernel::OM->Get('Kernel::System::ITSMConfigItem')->DefinitionGet(
|
||||
ClassID => $Self->{ReverseClassList}->{ $ConfigItem->{Class} },
|
||||
);
|
||||
|
||||
my $XMLDataCheckResult = $Self->CheckXMLData(
|
||||
Definition => $DefinitionData->{DefinitionRef},
|
||||
XMLData => $ConfigItem->{CIXMLData},
|
||||
);
|
||||
|
||||
if ( !$XMLDataCheckResult->{Success} ) {
|
||||
return $XMLDataCheckResult;
|
||||
}
|
||||
|
||||
# if everything is OK then return Success
|
||||
return {
|
||||
Success => 1,
|
||||
};
|
||||
}
|
||||
|
||||
=head2 _CheckAttachment()
|
||||
|
||||
checks if the given attachment parameter is valid.
|
||||
|
||||
my $AttachmentCheck = $OperationObject->_CheckAttachment(
|
||||
Attachment => $Attachment, # all attachment parameters
|
||||
);
|
||||
|
||||
returns:
|
||||
|
||||
$AttachmentCheck = {
|
||||
Success => 1, # if everething is OK
|
||||
}
|
||||
|
||||
$AttachmentCheck = {
|
||||
ErrorCode => 'Function.Error', # if error
|
||||
ErrorMessage => 'Error description',
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub _CheckAttachment {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Attachment = $Param{Attachment};
|
||||
|
||||
# check attachment item internally
|
||||
for my $Needed (qw(Content ContentType Filename)) {
|
||||
if ( !$Attachment->{$Needed} ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.MissingParameter",
|
||||
ErrorMessage =>
|
||||
"$Self->{OperationName}: Attachment->$Needed parameter is missing!",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
# check Article->ContentType
|
||||
if ( $Attachment->{ContentType} ) {
|
||||
|
||||
$Attachment->{ContentType} = lc $Attachment->{ContentType};
|
||||
|
||||
# check Charset part
|
||||
my $Charset = '';
|
||||
if ( $Attachment->{ContentType} =~ /charset=/i ) {
|
||||
$Charset = $Attachment->{ContentType};
|
||||
$Charset =~ s/.+?charset=("|'|)(\w+)/$2/gi;
|
||||
$Charset =~ s/"|'//g;
|
||||
$Charset =~ s/(.+?);.*/$1/g;
|
||||
}
|
||||
|
||||
if ( $Charset && !$Self->ValidateCharset( Charset => $Charset ) )
|
||||
{
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: Attachment->ContentType is invalid!",
|
||||
};
|
||||
}
|
||||
|
||||
# check MimeType part
|
||||
my $MimeType = '';
|
||||
if ( $Attachment->{ContentType} =~ /^(\w+\/\w+)/i ) {
|
||||
$MimeType = $1;
|
||||
$MimeType =~ s/"|'//g;
|
||||
}
|
||||
|
||||
if ( !$Self->ValidateMimeType( MimeType => $MimeType ) ) {
|
||||
return {
|
||||
ErrorCode => "$Self->{OperationName}.InvalidParameter",
|
||||
ErrorMessage => "$Self->{OperationName}: Attachment->ContentType is invalid!",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
# if everything is OK then return Success
|
||||
return {
|
||||
Success => 1,
|
||||
};
|
||||
}
|
||||
|
||||
=head2 _ConfigItemUpdate()
|
||||
|
||||
updates a configuration item with attachments if specified.
|
||||
|
||||
my $Response = $OperationObject->_ConfigItemUpdate(
|
||||
ConfigItemID => 123,
|
||||
ConfigItem => $ConfigItem, # all configuration item parameters
|
||||
AttachmentList => $Attachment, # a list of all attachments
|
||||
ReplaceExistingData => 0, # if the existing xml attributes and attachments should be replaced or kept
|
||||
UserID => 123,
|
||||
);
|
||||
|
||||
returns:
|
||||
|
||||
$Response = {
|
||||
Success => 1, # if everething is OK
|
||||
Data => {
|
||||
ConfigItemID => 123,
|
||||
ConfigItemNumber => 'CN123',
|
||||
}
|
||||
}
|
||||
|
||||
$Response = {
|
||||
Success => 0, # if unexpected error
|
||||
ErrorMessage => "$Param{ErrorCode}: $Param{ErrorMessage}",
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub _ConfigItemUpdate {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $ConfigItemID = $Param{ConfigItemID};
|
||||
my $ConfigItem = $Param{ConfigItem};
|
||||
my $AttachmentList = $Param{AttachmentList};
|
||||
|
||||
my $DeplStateID = $Self->{ReverseDeplStateList}->{ $ConfigItem->{DeplState} };
|
||||
my $InciStateID = $Self->{ReverseInciStateList}->{ $ConfigItem->{InciState} };
|
||||
|
||||
my $RawXMLData = $ConfigItem->{CIXMLData};
|
||||
|
||||
# get config item object
|
||||
my $ConfigItemObject = $Kernel::OM->Get('Kernel::System::ITSMConfigItem');
|
||||
|
||||
# get last config item defintion
|
||||
my $DefinitionData = $ConfigItemObject->DefinitionGet(
|
||||
ClassID => $Self->{ReverseClassList}->{ $ConfigItem->{Class} },
|
||||
);
|
||||
|
||||
# replace date, date time, customer, company and general catalog values
|
||||
my $ReplacedXMLData = $Self->ReplaceXMLData(
|
||||
XMLData => $RawXMLData,
|
||||
Definition => $DefinitionData->{DefinitionRef},
|
||||
);
|
||||
|
||||
# create an XMLData structure suitable for VersionAdd
|
||||
my $XMLData = $Self->FormatXMLData(
|
||||
XMLData => $ReplacedXMLData,
|
||||
);
|
||||
|
||||
# get the current config item version data
|
||||
my $CurrentVersion = $ConfigItemObject->VersionGet(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
UserID => $Param{UserID},
|
||||
);
|
||||
|
||||
my $VersionID = $ConfigItemObject->VersionAdd(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
Name => $ConfigItem->{Name},
|
||||
DefinitionID => $DefinitionData->{DefinitionID},
|
||||
DeplStateID => $DeplStateID,
|
||||
InciStateID => $InciStateID,
|
||||
XMLData => $XMLData,
|
||||
UserID => $Param{UserID},
|
||||
);
|
||||
|
||||
if ( !$VersionID ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => 'Configuration Item could not be updated, please contact the system'
|
||||
. 'administrator'
|
||||
};
|
||||
}
|
||||
|
||||
# get the version ID of the config item before the update
|
||||
my $CurrentVersionID = $CurrentVersion->{VersionID} || '';
|
||||
|
||||
# compare old version and new version IDs
|
||||
if ( $CurrentVersionID eq $VersionID ) {
|
||||
$Self->{DebuggerObject}->Notice(
|
||||
Summary => "$Self->{OperationName}: No change in configuration item version",
|
||||
Data => 'The internal structure of the configuration item was indentical to the last'
|
||||
. ' one, no update was performed',
|
||||
);
|
||||
}
|
||||
|
||||
# the ReplaceExistingData flag is set
|
||||
if ( $Param{ReplaceExistingData} ) {
|
||||
|
||||
# get a list of all attachments
|
||||
my @ExistingAttachments = $ConfigItemObject->ConfigItemAttachmentList(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
);
|
||||
|
||||
# delete all attachments of this config item
|
||||
FILENAME:
|
||||
for my $Filename (@ExistingAttachments) {
|
||||
|
||||
# delete the attachment
|
||||
my $DeletionSuccess = $ConfigItemObject->ConfigItemAttachmentDelete(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
Filename => $Filename,
|
||||
UserID => $Param{UserID},
|
||||
);
|
||||
|
||||
if ( !$DeletionSuccess ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Unknown problem when deleting attachment $Filename of ConfigItem "
|
||||
. "$ConfigItemID. Please check the VirtualFS backend for stale files!",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# set attachments
|
||||
if ( IsArrayRefWithData($AttachmentList) ) {
|
||||
|
||||
for my $Attachment ( @{$AttachmentList} ) {
|
||||
my $Result = $Self->CreateAttachment(
|
||||
Attachment => $Attachment,
|
||||
ConfigItemID => $ConfigItemID,
|
||||
UserID => $Param{UserID}
|
||||
);
|
||||
|
||||
if ( !$Result->{Success} ) {
|
||||
my $ErrorMessage = $Result->{ErrorMessage}
|
||||
|| "Attachment could not be created, please contact the system administrator";
|
||||
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => $ErrorMessage,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# get ConfigItem data
|
||||
my $ConfigItemData = $ConfigItemObject->ConfigItemGet(
|
||||
ConfigItemID => $ConfigItemID,
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData($ConfigItemData) ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => 'Could not get new configuration item information, please contact the system administrator',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
Success => 1,
|
||||
Data => {
|
||||
ConfigItemID => $ConfigItemID,
|
||||
Number => $ConfigItemData->{Number},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
130
Perl OTRS/Kernel/GenericInterface/Operation/FAQ/LanguageList.pm
Normal file
130
Perl OTRS/Kernel/GenericInterface/Operation/FAQ/LanguageList.pm
Normal file
@@ -0,0 +1,130 @@
|
||||
# --
|
||||
# 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::FAQ::LanguageList;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::System::VariableCheck qw(IsArrayRefWithData IsHashRefWithData IsStringWithData);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::FAQ::LanguageList - GenericInterface FAQ LanguageList Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
for my $Needed (qw( DebuggerObject WebserviceID )) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!"
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform LanguageList Operation. This will return the current FAQ Languages.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => {},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # In case of an error
|
||||
Data => { # result data payload after Operation
|
||||
Language => [
|
||||
{
|
||||
ID => 1,
|
||||
Name> 'en',
|
||||
},
|
||||
{
|
||||
ID => 2,
|
||||
Name> 'OneMoreLanguage',
|
||||
},
|
||||
# ...
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# Set UserID to root because in public interface there is no user.
|
||||
my %Languages = $Kernel::OM->Get('Kernel::System::FAQ')->LanguageList(
|
||||
UserID => 1,
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData( \%Languages ) ) {
|
||||
|
||||
my $ErrorMessage = 'Could not get language data'
|
||||
. ' in Kernel::GenericInterface::Operation::FAQ::LanguageList::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketList.NotLanguageData',
|
||||
ErrorMessage => "TicketList: $ErrorMessage",
|
||||
);
|
||||
}
|
||||
|
||||
my @LanguageList;
|
||||
for my $Key ( sort keys %Languages ) {
|
||||
my %Language = (
|
||||
ID => $Key,
|
||||
Name => $Languages{$Key},
|
||||
);
|
||||
push @LanguageList, {%Language};
|
||||
}
|
||||
|
||||
return {
|
||||
Success => 1,
|
||||
Data => {
|
||||
Language => \@LanguageList,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
@@ -0,0 +1,140 @@
|
||||
# --
|
||||
# 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::FAQ::PublicCategoryList;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::System::VariableCheck qw(IsArrayRefWithData IsHashRefWithData IsStringWithData);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::FAQ::PublicCategoryList - GenericInterface FAQ PublicCategoryList Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
for my $Needed (qw( DebuggerObject WebserviceID )) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!"
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform PublicCategoryList Operation. This will return the current FAQ Categories.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => {},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # In case of an error
|
||||
Data => { # result data payload after Operation
|
||||
Category => [
|
||||
{
|
||||
ID => 1,
|
||||
Name> 'Misc',
|
||||
},
|
||||
{
|
||||
ID => 2,
|
||||
Name> 'OneMoreCategory',
|
||||
},
|
||||
# ...
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# Set UserID to root because in public interface there is no user.
|
||||
my $CategoryTree = $Kernel::OM->Get('Kernel::System::FAQ')->GetPublicCategoriesLongNames(
|
||||
Valid => 1,
|
||||
Type => 'rw',
|
||||
UserID => 1,
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData($CategoryTree) ) {
|
||||
|
||||
my $ErrorMessage = 'Could not get category data'
|
||||
. ' in Kernel::GenericInterface::Operation::FAQ::PublicCategoryList::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'PublicCategoryList.NotCategoryData',
|
||||
ErrorMessage => "PublicCategoryList: $ErrorMessage",
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
my @PublicCategoryList;
|
||||
for my $Key ( sort( keys %{$CategoryTree} ) ) {
|
||||
my %Category = (
|
||||
ID => $Key,
|
||||
Name => $CategoryTree->{$Key},
|
||||
);
|
||||
push @PublicCategoryList, {%Category};
|
||||
}
|
||||
|
||||
# Prepare return data.
|
||||
my $ReturnData = {
|
||||
Success => 1,
|
||||
Data => {},
|
||||
};
|
||||
if ( scalar @PublicCategoryList > 1 ) {
|
||||
$ReturnData->{Data}->{Category} = \@PublicCategoryList;
|
||||
}
|
||||
else {
|
||||
$ReturnData->{Data}->{Category} = $PublicCategoryList[0];
|
||||
}
|
||||
|
||||
return $ReturnData;
|
||||
}
|
||||
|
||||
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
|
||||
305
Perl OTRS/Kernel/GenericInterface/Operation/FAQ/PublicFAQGet.pm
Normal file
305
Perl OTRS/Kernel/GenericInterface/Operation/FAQ/PublicFAQGet.pm
Normal file
@@ -0,0 +1,305 @@
|
||||
# --
|
||||
# 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::FAQ::PublicFAQGet;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use MIME::Base64;
|
||||
use Kernel::System::VariableCheck qw(IsArrayRefWithData IsHashRefWithData IsStringWithData);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::FAQ::PublicFAQGet - GenericInterface FAQ PublicFAQGet Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
for my $Needed (qw( DebuggerObject WebserviceID )) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!"
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform PublicFAQGet Operation. This will return a Public FAQ entry.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => {
|
||||
ItemID = '32,33',
|
||||
GetAttachmentContents = 1, # 0|1, defaults to 1
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # In case of an error
|
||||
Data => { # result data payload after Operation
|
||||
ItemID => [
|
||||
{
|
||||
ID => 32,
|
||||
ItemID => 32,
|
||||
FAQID => 32,
|
||||
Number => 100032,
|
||||
CategoryID => '2',
|
||||
CategoryName => 'CategoryA::CategoryB',
|
||||
CategoryShortName => 'CategoryB',
|
||||
LanguageID => 1,
|
||||
Language => 'en',
|
||||
Title => 'Article Title',
|
||||
Field1 => 'The Symptoms',
|
||||
Field2 => 'The Problem',
|
||||
Field3 => 'The Solution',
|
||||
Field4 => undef, # Not active by default
|
||||
Field5 => undef, # Not active by default
|
||||
Field6 => 'Comments',
|
||||
Approved => 1, # or 0
|
||||
Keywords => 'KeyWord1 KeyWord2',
|
||||
Votes => 0, # number of votes
|
||||
VoteResult => '0.00', # a number between 0.00 and 100.00
|
||||
StateID => 1,
|
||||
State => 'internal (agent)', # or 'external (customer)' or
|
||||
# 'public (all)'
|
||||
StateTypeID => 1,
|
||||
StateTypeName => 'internal', # or 'external' or 'public'
|
||||
CreatedBy => 1,
|
||||
Changed => '2011-01-05 21:53:50',
|
||||
ChangedBy => '1',
|
||||
Created => '2011-01-05 21:53:50',
|
||||
Name => '1294286030-31.1697297104732', # FAQ Article name or
|
||||
# systemtime + '-' + random number
|
||||
ContentType => 'text/html',
|
||||
Attachment => {
|
||||
{
|
||||
Filesize => '540286', # file size in bytes
|
||||
ContentType => 'image/jpeg',
|
||||
Filename => 'Error.jpg',
|
||||
Content => '...', # base64 content
|
||||
Inline => 0, # specify if is an inline attachment
|
||||
FileID => 34 # FileID for relation with rich text content
|
||||
},
|
||||
{
|
||||
Filesize => '540286', # file size in bytes
|
||||
ContentType => 'image/jpeg',
|
||||
Filename => 'Pencil.jpg',
|
||||
Content => '...', # base64 content
|
||||
Inline => 1, # specify if is an inline attachment
|
||||
FileID => 35 # FileID for relation with rich text content
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID => 33,
|
||||
ItemID => 33,
|
||||
FAQID => 33,
|
||||
Number => 100033,
|
||||
CategoryID => '3',
|
||||
CategoryName => 'CategoryD::CategoryE',
|
||||
CategoryShortName => 'CategoryE',
|
||||
LanguageID => 1,
|
||||
Language => 'en',
|
||||
Title => 'Article Title',
|
||||
Field1 => 'The Symptoms',
|
||||
Field2 => 'The Problem',
|
||||
Field3 => 'The Solution',
|
||||
Field4 => undef, # Not active by default
|
||||
Field5 => undef, # Not active by default
|
||||
Field6 => 'Comments',
|
||||
Approved => 1, # or 0
|
||||
Keywords => 'KeyWord1 KeyWord2',
|
||||
Votes => 0, # number of votes
|
||||
VoteResult => '0.00', # a number between 0.00 and 100.00
|
||||
StateID => 1,
|
||||
State => 'internal (agent)', # or 'external (customer)' or
|
||||
# 'public (all)'
|
||||
StateTypeID => 1,
|
||||
StateTypeName => 'internal', # or 'external' or 'public'
|
||||
CreatedBy => 1,
|
||||
Changed => '2011-01-05 21:53:50',
|
||||
ChangedBy => '1',
|
||||
Created => '2011-01-05 21:53:50',
|
||||
Name => '1294286030-31.1697297104732', # FAQ Article name or
|
||||
# systemtime + '-' + random number
|
||||
},
|
||||
# ...
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
if ( !$Param{Data}->{ItemID} ) {
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'PublicFAQGet.MissingParameter',
|
||||
ErrorMessage => "PublicFAQGet: Got no ItemID!",
|
||||
);
|
||||
}
|
||||
if ( !defined( $Param{Data}->{GetAttachmentContents} ) ) {
|
||||
$Param{Data}->{GetAttachmentContents} = 1;
|
||||
}
|
||||
|
||||
my $ErrorMessage = '';
|
||||
|
||||
my $ReturnData = {
|
||||
Success => 1,
|
||||
};
|
||||
|
||||
my @ItemIDs = split( /,/, $Param{Data}->{ItemID} );
|
||||
my @Item;
|
||||
|
||||
# Set UserID to root because in public interface there is no user.
|
||||
my $UserID = 1;
|
||||
|
||||
my $FAQObject = $Kernel::OM->Get('Kernel::System::FAQ');
|
||||
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
||||
|
||||
# Get public state types.
|
||||
my $InterfaceStates = $FAQObject->StateTypeList(
|
||||
Types => $ConfigObject->Get('FAQ::Public::StateTypes'),
|
||||
UserID => $UserID,
|
||||
);
|
||||
|
||||
for my $ItemID (@ItemIDs) {
|
||||
|
||||
my %FAQEntry = $FAQObject->FAQGet(
|
||||
ItemID => $ItemID,
|
||||
ItemFields => 1,
|
||||
UserID => $UserID,
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData( \%FAQEntry ) ) {
|
||||
|
||||
$ErrorMessage = 'Could not get FAQ data'
|
||||
. ' in Kernel::GenericInterface::Operation::FAQ::PublicFAQGet::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'PublicFAQGet.NotValidFAQID',
|
||||
ErrorMessage => "PublicFAQGet: $ErrorMessage",
|
||||
);
|
||||
}
|
||||
|
||||
# Check permissions.
|
||||
my $ApprovalSuccess = 1;
|
||||
if ( $ConfigObject->Get('FAQ::ApprovalRequired') ) {
|
||||
$ApprovalSuccess = $FAQEntry{Approved};
|
||||
}
|
||||
if ( !$ApprovalSuccess || !$InterfaceStates->{ $FAQEntry{StateTypeID} } ) {
|
||||
|
||||
$ErrorMessage = 'Could not get FAQ data'
|
||||
. ' in Kernel::GenericInterface::Operation::FAQ::PublicFAQGet::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'PublicFAQGet.AccessDenied',
|
||||
ErrorMessage => "PublicFAQGet: $ErrorMessage",
|
||||
);
|
||||
}
|
||||
|
||||
my @Index = $FAQObject->AttachmentIndex(
|
||||
ItemID => $ItemID,
|
||||
ShowInline => 1, # ( 0|1, default 1)
|
||||
UserID => $UserID,
|
||||
);
|
||||
|
||||
my %File;
|
||||
if ( IsArrayRefWithData( \@Index ) ) {
|
||||
|
||||
my @Attachments;
|
||||
for my $Attachment (@Index) {
|
||||
|
||||
if ( $Param{Data}->{GetAttachmentContents} ) {
|
||||
%File = $FAQObject->AttachmentGet(
|
||||
ItemID => $ItemID,
|
||||
FileID => $Attachment->{FileID},
|
||||
UserID => $UserID,
|
||||
);
|
||||
|
||||
# Convert content to base64.
|
||||
$File{Content} = encode_base64( $File{Content} );
|
||||
$File{Inline} = $Attachment->{Inline};
|
||||
$File{FileID} = $Attachment->{FileID};
|
||||
}
|
||||
else {
|
||||
%File = (
|
||||
Filename => $Attachment->{Filename},
|
||||
ContentType => $Attachment->{ContentType},
|
||||
Filesize => $Attachment->{Filesize},
|
||||
Content => '',
|
||||
Inline => $Attachment->{Inline},
|
||||
FileID => $Attachment->{FileID}
|
||||
);
|
||||
}
|
||||
push @Attachments, {%File};
|
||||
}
|
||||
|
||||
# Set FAQ entry data.
|
||||
$FAQEntry{Attachment} = \@Attachments;
|
||||
}
|
||||
|
||||
push @Item, \%FAQEntry;
|
||||
}
|
||||
|
||||
if ( !scalar @Item ) {
|
||||
$ErrorMessage = 'Could not get FAQ data'
|
||||
. ' in Kernel::GenericInterface::Operation::FAQ::PublicFAQGet::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'PublicFAQGet.NoFAQData',
|
||||
ErrorMessage => "PublicFAQGet: $ErrorMessage",
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
$ReturnData->{Data}->{FAQItem} = \@Item;
|
||||
|
||||
return $ReturnData;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -0,0 +1,216 @@
|
||||
# --
|
||||
# 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::FAQ::PublicFAQSearch;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use MIME::Base64;
|
||||
use Kernel::System::VariableCheck qw(IsArrayRefWithData IsHashRefWithData IsStringWithData);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::FAQ::PublicFAQSearch - GenericInterface FAQ PublicFAQSearch Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
for my $Needed (qw( DebuggerObject WebserviceID )) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!"
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform PublicFAQSearch Operation. This will return a list of public FAQ entries.
|
||||
|
||||
my @IDs = $OperationObject->Run(
|
||||
Data => {
|
||||
|
||||
Number => '*134*', # (optional)
|
||||
Title => '*some title*', # (optional)
|
||||
|
||||
# is searching in Number, Title, Keyword and Field1-6
|
||||
What => '*some text*', # (optional)
|
||||
|
||||
Keyword => '*webserver*', # (optional)
|
||||
LanguageIDs => [ 4, 5, 6 ], # (optional)
|
||||
CategoryIDs => [ 7, 8, 9 ], # (optional)
|
||||
|
||||
OrderBy => [ 'FAQID', 'Title' ], # (optional)
|
||||
|
||||
# Additional information for OrderBy:
|
||||
# The OrderByDirection can be specified for each OrderBy attribute.
|
||||
# The pairing is made by the array indexes.
|
||||
|
||||
OrderByDirection => 'Down', # (Down | Up) # (optional)
|
||||
# default: 'Down'
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # In case of an error
|
||||
Data => { # result data payload after Operation
|
||||
ID => [
|
||||
32,
|
||||
13,
|
||||
12,
|
||||
9,
|
||||
6,
|
||||
5,
|
||||
4,
|
||||
1,
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# Set SearchLimit on 0 because we need to get all entries.
|
||||
my $SearchLimit = 0;
|
||||
|
||||
my $Config = $Kernel::OM->Get('Kernel::Config')->Get("FAQ::Frontend::PublicFAQSearch");
|
||||
|
||||
my $SortBy = $Param{Data}->{OrderBy}
|
||||
|| $Config->{'SortBy::Default'}
|
||||
|| 'FAQID';
|
||||
|
||||
# The SortBy param could be an ARRAY an SCALAR or an empty value.
|
||||
if ( !IsArrayRefWithData($SortBy) && $SortBy ne '' ) {
|
||||
$SortBy = [$SortBy];
|
||||
}
|
||||
|
||||
my $OrderBy = $Param{Data}->{OrderByDirection}
|
||||
|| $Config->{'Order::Default'}
|
||||
|| 'Down';
|
||||
|
||||
my $CategoryIDs;
|
||||
|
||||
# The CategoryID param could be an ARRAY an SCALAR or an empty value.
|
||||
$Param{Data}->{CategoryIDs} = $Param{Data}->{CategoryIDs} || '';
|
||||
if ( !IsArrayRefWithData( $Param{Data}->{CategoryIDs} ) && $Param{Data}->{CategoryIDs} ne '' ) {
|
||||
$CategoryIDs = [ $Param{Data}->{CategoryIDs} ];
|
||||
}
|
||||
elsif ( $Param{Data}->{CategoryIDs} ne '' ) {
|
||||
$CategoryIDs = $Param{Data}->{CategoryIDs};
|
||||
}
|
||||
|
||||
my $LanguageIDs;
|
||||
|
||||
# The LanguageID param could be an ARRAY an SCALAR or an empty value.
|
||||
$Param{Data}->{LanguageIDs} = $Param{Data}->{LanguageIDs} || '';
|
||||
if ( !IsArrayRefWithData( $Param{Data}->{LanguageIDs} ) && $Param{Data}->{LanguageIDs} ne '' ) {
|
||||
$LanguageIDs = [ $Param{Data}->{LanguageIDs} ];
|
||||
}
|
||||
elsif ( $Param{Data}->{LanguageIDs} ne '' ) {
|
||||
$LanguageIDs = $Param{Data}->{LanguageIDs};
|
||||
}
|
||||
|
||||
my $FAQObject = $Kernel::OM->Get('Kernel::System::FAQ');
|
||||
|
||||
# Set UserID to root because in public interface there is no user.
|
||||
my $UserID = 1;
|
||||
|
||||
# Set default interface settings.
|
||||
my $Interface = $FAQObject->StateTypeGet(
|
||||
Name => 'public',
|
||||
UserID => $UserID,
|
||||
);
|
||||
my $InterfaceStates = $FAQObject->StateTypeList(
|
||||
Types => $Kernel::OM->Get('Kernel::Config')->Get('FAQ::Public::StateTypes'),
|
||||
UserID => $UserID,
|
||||
);
|
||||
|
||||
# Perform FAQ search.
|
||||
my @ViewableItemIDs = $FAQObject->FAQSearch(
|
||||
Number => $Param{Data}->{Number} || '',
|
||||
Title => $Param{Data}->{Title} || '',
|
||||
What => $Param{Data}->{What} || '',
|
||||
Keyword => $Param{Data}->{Keyword} || '',
|
||||
LanguageIDs => $LanguageIDs,
|
||||
CategoryIDs => $CategoryIDs,
|
||||
OrderBy => $SortBy,
|
||||
OrderByDirection => [$OrderBy],
|
||||
Limit => $SearchLimit,
|
||||
UserID => $UserID,
|
||||
States => $InterfaceStates,
|
||||
Interface => $Interface,
|
||||
);
|
||||
if ( !IsArrayRefWithData( \@ViewableItemIDs ) ) {
|
||||
|
||||
my $ErrorMessage = 'Could not get FAQ data'
|
||||
. ' in Kernel::GenericInterface::Operation::FAQ::PublicFAQSearch::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'PublicFAQSearch.NotFAQData',
|
||||
ErrorMessage => "PublicFAQSearch: $ErrorMessage",
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
# Prepare return data.
|
||||
my $ReturnData = {
|
||||
Data => {},
|
||||
Success => 1,
|
||||
};
|
||||
|
||||
# Set FAQ entry data.
|
||||
if ( scalar @ViewableItemIDs > 1 ) {
|
||||
$ReturnData->{Data}->{ID} = \@ViewableItemIDs;
|
||||
}
|
||||
else {
|
||||
$ReturnData->{Data}->{ID} = $ViewableItemIDs[0];
|
||||
}
|
||||
|
||||
return $ReturnData;
|
||||
}
|
||||
|
||||
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
|
||||
112
Perl OTRS/Kernel/GenericInterface/Operation/Session/Common.pm
Normal file
112
Perl OTRS/Kernel/GenericInterface/Operation/Session/Common.pm
Normal file
@@ -0,0 +1,112 @@
|
||||
# --
|
||||
# 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::Session::Common;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::System::VariableCheck qw(:all);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::Session::Common - Base class for Session Operations
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 CreateSessionID()
|
||||
|
||||
performs user authentication and return a new SessionID value
|
||||
|
||||
my $SessionID = $CommonObject->CreateSessionID(
|
||||
Data {
|
||||
UserLogin => 'Agent1',
|
||||
CustomerUserLogin => 'Customer1', # optional, provide UserLogin or
|
||||
# CustomerUserLogin
|
||||
Password => 'some password', # plain text password
|
||||
}
|
||||
);
|
||||
|
||||
Returns undef on failure or
|
||||
|
||||
$SessionID = 'AValidSessionIDValue'; # the new session id value
|
||||
|
||||
=cut
|
||||
|
||||
sub CreateSessionID {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $User;
|
||||
my %UserData;
|
||||
my $UserType;
|
||||
|
||||
# get params
|
||||
my $PostPw = $Param{Data}->{Password} || '';
|
||||
|
||||
if ( defined $Param{Data}->{UserLogin} && $Param{Data}->{UserLogin} ) {
|
||||
|
||||
# if UserLogin
|
||||
my $PostUser = $Param{Data}->{UserLogin} || '';
|
||||
|
||||
# check submitted data
|
||||
$User = $Kernel::OM->Get('Kernel::System::Auth')->Auth(
|
||||
User => $PostUser,
|
||||
Pw => $PostPw,
|
||||
);
|
||||
%UserData = $Kernel::OM->Get('Kernel::System::User')->GetUserData(
|
||||
User => $User,
|
||||
Valid => 1,
|
||||
);
|
||||
$UserType = 'User';
|
||||
}
|
||||
elsif ( defined $Param{Data}->{CustomerUserLogin} && $Param{Data}->{CustomerUserLogin} ) {
|
||||
|
||||
# if UserCustomerLogin
|
||||
my $PostUser = $Param{Data}->{CustomerUserLogin} || '';
|
||||
|
||||
# check submitted data
|
||||
$User = $Kernel::OM->Get('Kernel::System::CustomerAuth')->Auth(
|
||||
User => $PostUser,
|
||||
Pw => $PostPw,
|
||||
);
|
||||
%UserData = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerUserDataGet(
|
||||
User => $PostUser,
|
||||
Valid => 1,
|
||||
);
|
||||
$UserType = 'Customer';
|
||||
}
|
||||
|
||||
# login is invalid
|
||||
return if !$User;
|
||||
|
||||
# create new session id
|
||||
my $NewSessionID = $Kernel::OM->Get('Kernel::System::AuthSession')->CreateSessionID(
|
||||
%UserData,
|
||||
UserLastRequest => $Kernel::OM->Create('Kernel::System::DateTime')->ToEpoch(),
|
||||
UserType => $UserType,
|
||||
SessionSource => 'GenericInterface',
|
||||
);
|
||||
|
||||
return $NewSessionID if ($NewSessionID);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -0,0 +1,135 @@
|
||||
# --
|
||||
# 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::Session::SessionCreate;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::System::VariableCheck qw(IsStringWithData IsHashRefWithData);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
Kernel::GenericInterface::Operation::Session::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::Session::SessionCreate - GenericInterface Session Create Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# check needed objects
|
||||
for my $Needed (
|
||||
qw(DebuggerObject WebserviceID)
|
||||
)
|
||||
{
|
||||
if ( !$Param{$Needed} ) {
|
||||
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!"
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
Retrieve a new session id value.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => {
|
||||
UserLogin => 'Agent1',
|
||||
CustomerUserLogin => 'Customer1', # optional, provide UserLogin or CustomerUserLogin
|
||||
Password => 'some password', # plain text password
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # In case of an error
|
||||
Data => {
|
||||
SessionID => $SessionID,
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# check needed stuff
|
||||
if ( !IsHashRefWithData( $Param{Data} ) ) {
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'SessionCreate.MissingParameter',
|
||||
ErrorMessage => "SessionCreate: The request is empty!",
|
||||
);
|
||||
}
|
||||
|
||||
for my $Needed (qw( Password )) {
|
||||
if ( !$Param{Data}->{$Needed} ) {
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'SessionCreate.MissingParameter',
|
||||
ErrorMessage => "SessionCreate: $Needed parameter is missing!",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
my $SessionID = $Self->CreateSessionID(
|
||||
%Param,
|
||||
);
|
||||
|
||||
if ( !$SessionID ) {
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'SessionCreate.AuthFail',
|
||||
ErrorMessage => "SessionCreate: Authorization failing!",
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
Success => 1,
|
||||
Data => {
|
||||
SessionID => $SessionID,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
@@ -0,0 +1,165 @@
|
||||
# --
|
||||
# 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::Session::SessionGet;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::System::VariableCheck qw(IsStringWithData IsHashRefWithData);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
Kernel::GenericInterface::Operation::Session::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::Session::SessionGet - GenericInterface Session Get Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# check needed objects
|
||||
for my $Needed (
|
||||
qw(DebuggerObject WebserviceID)
|
||||
)
|
||||
{
|
||||
if ( !$Param{$Needed} ) {
|
||||
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!"
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
Get session information.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => {
|
||||
SessionID => '1234567890123456',
|
||||
},
|
||||
);
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # In case of an error
|
||||
Data => {
|
||||
UserSessionStart => '1293801801',
|
||||
UserRemoteAddr => '127.0.0.1',
|
||||
UserRemoteUserAgent => 'Some User Agent x.x',
|
||||
UserLastname => 'SomeLastName',
|
||||
UserFirstname => 'SomeFirstname',
|
||||
# and other preferences values
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
if ( !IsHashRefWithData( $Param{Data} ) ) {
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'SessionGet.MissingParameter',
|
||||
ErrorMessage => "SessionGet: The request is empty!",
|
||||
);
|
||||
}
|
||||
|
||||
if ( !$Param{Data}->{SessionID} ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'SessionGet.MissingParameter',
|
||||
ErrorMessage => "SessionGet: SessionID is missing!",
|
||||
);
|
||||
}
|
||||
|
||||
my $SessionObject = $Kernel::OM->Get('Kernel::System::AuthSession');
|
||||
|
||||
# Honor SessionCheckRemoteIP, SessionMaxIdleTime, etc.
|
||||
my $Valid = $SessionObject->CheckSessionID(
|
||||
SessionID => $Param{Data}->{SessionID},
|
||||
);
|
||||
if ( !$Valid ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'SessionGet.SessionInvalid',
|
||||
ErrorMessage => 'SessionGet: SessionID is Invalid!',
|
||||
);
|
||||
}
|
||||
|
||||
my %SessionDataRaw = $SessionObject->GetSessionIDData(
|
||||
SessionID => $Param{Data}->{SessionID},
|
||||
);
|
||||
|
||||
# Filter out some sensitive values
|
||||
delete $SessionDataRaw{UserPw};
|
||||
delete $SessionDataRaw{UserChallengeToken};
|
||||
|
||||
my $JSONObject = $Kernel::OM->Get('Kernel::System::JSON');
|
||||
|
||||
my @SessionData;
|
||||
for my $DataKey ( sort keys %SessionDataRaw ) {
|
||||
|
||||
my $Value = $SessionDataRaw{$DataKey};
|
||||
my %Data = (
|
||||
Key => $DataKey,
|
||||
Value => $Value,
|
||||
);
|
||||
|
||||
if ( ref $Value ) {
|
||||
$Data{Value} = $JSONObject->Encode(
|
||||
Data => $Value,
|
||||
SortKeys => 1,
|
||||
);
|
||||
$Data{Serialized} = 1;
|
||||
}
|
||||
|
||||
push @SessionData, \%Data;
|
||||
}
|
||||
|
||||
return {
|
||||
Success => 1,
|
||||
Data => {
|
||||
SessionData => \@SessionData,
|
||||
},
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
144
Perl OTRS/Kernel/GenericInterface/Operation/Test/Test.pm
Normal file
144
Perl OTRS/Kernel/GenericInterface/Operation/Test/Test.pm
Normal file
@@ -0,0 +1,144 @@
|
||||
# --
|
||||
# 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::Test::Test;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::System::VariableCheck qw(IsHashRefWithData);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::Test::Test - GenericInterface Operation Test backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# check needed objects
|
||||
for my $Needed (qw(DebuggerObject)) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!"
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform the selected test Operation. This will return the data that
|
||||
was handed to the function or return a variable data if 'TestError' and
|
||||
'ErrorData' params are sent.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => { # data payload before Operation
|
||||
...
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # in case of error
|
||||
Data => { # result data payload after Operation
|
||||
...
|
||||
},
|
||||
};
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => { # data payload before Operation
|
||||
TestError => 1,
|
||||
ErrorData => {
|
||||
...
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 0, # it always return 0
|
||||
ErrorMessage => 'Error message for error code: 1', # including the 'TestError' param
|
||||
Data => {
|
||||
ErrorData => { # same data was sent as
|
||||
# 'ErrorData' param
|
||||
|
||||
},
|
||||
...
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# check data - only accept undef or hash ref
|
||||
if ( defined $Param{Data} && ref $Param{Data} ne 'HASH' ) {
|
||||
|
||||
return $Self->{DebuggerObject}->Error(
|
||||
Summary => 'Got Data but it is not a hash ref in Operation Test backend)!'
|
||||
);
|
||||
}
|
||||
|
||||
if ( defined $Param{Data} && $Param{Data}->{TestError} ) {
|
||||
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Error message for error code: $Param{Data}->{TestError}",
|
||||
Data => {
|
||||
ErrorData => $Param{Data}->{ErrorData},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
# copy data
|
||||
my $ReturnData;
|
||||
|
||||
if ( ref $Param{Data} eq 'HASH' ) {
|
||||
$ReturnData = \%{ $Param{Data} };
|
||||
}
|
||||
else {
|
||||
$ReturnData = undef;
|
||||
}
|
||||
|
||||
# return result
|
||||
return {
|
||||
Success => 1,
|
||||
Data => $ReturnData,
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
1461
Perl OTRS/Kernel/GenericInterface/Operation/Ticket/Common.pm
Normal file
1461
Perl OTRS/Kernel/GenericInterface/Operation/Ticket/Common.pm
Normal file
File diff suppressed because it is too large
Load Diff
1730
Perl OTRS/Kernel/GenericInterface/Operation/Ticket/TicketCreate.pm
Normal file
1730
Perl OTRS/Kernel/GenericInterface/Operation/Ticket/TicketCreate.pm
Normal file
File diff suppressed because it is too large
Load Diff
568
Perl OTRS/Kernel/GenericInterface/Operation/Ticket/TicketGet.pm
Normal file
568
Perl OTRS/Kernel/GenericInterface/Operation/Ticket/TicketGet.pm
Normal file
@@ -0,0 +1,568 @@
|
||||
# --
|
||||
# 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::Ticket::TicketGet;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use MIME::Base64;
|
||||
|
||||
use Kernel::System::VariableCheck qw(IsArrayRefWithData IsHashRefWithData IsStringWithData);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
Kernel::GenericInterface::Operation::Ticket::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::Ticket::TicketGet - GenericInterface Ticket Get Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# check needed objects
|
||||
for my $Needed (qw(DebuggerObject WebserviceID)) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!",
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform TicketGet Operation. This function is able to return
|
||||
one or more ticket entries in one call.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => {
|
||||
UserLogin => 'some agent login', # UserLogin or CustomerUserLogin or SessionID is
|
||||
# required
|
||||
CustomerUserLogin => 'some customer login',
|
||||
SessionID => 123,
|
||||
|
||||
Password => 'some password', # if UserLogin or customerUserLogin is sent then
|
||||
# Password is required
|
||||
TicketID => '32,33', # required, could be coma separated IDs or an Array
|
||||
DynamicFields => 0, # Optional, 0 as default. Indicate if Dynamic Fields
|
||||
# should be included or not on the ticket content.
|
||||
Extended => 1, # Optional, 0 as default
|
||||
AllArticles => 1, # Optional, 0 as default. Set as 1 will include articles
|
||||
# for tickets.
|
||||
ArticleSenderType => [ $ArticleSenderType1, $ArticleSenderType2 ], # Optional, only requested article sender types
|
||||
ArticleOrder => 'DESC', # Optional, DESC,ASC - default is ASC
|
||||
ArticleLimit => 5, # Optional
|
||||
Attachments => 1, # Optional, 0 as default. If it's set with the value 1,
|
||||
# attachments for articles will be included on ticket data
|
||||
GetAttachmentContents = 1 # Optional, 1 as default. 0|1,
|
||||
HTMLBodyAsAttachment => 1 # Optional, If enabled the HTML body version of each article
|
||||
# is added to the attachments list
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # In case of an error
|
||||
Data => {
|
||||
Ticket => [
|
||||
{
|
||||
TicketNumber => '20101027000001',
|
||||
Title => 'some title',
|
||||
TicketID => 123,
|
||||
State => 'some state',
|
||||
StateID => 123,
|
||||
StateType => 'some state type',
|
||||
Priority => 'some priority',
|
||||
PriorityID => 123,
|
||||
Lock => 'lock',
|
||||
LockID => 123,
|
||||
Queue => 'some queue',
|
||||
QueueID => 123,
|
||||
CustomerID => 'customer_id_123',
|
||||
CustomerUserID => 'customer_user_id_123',
|
||||
Owner => 'some_owner_login',
|
||||
OwnerID => 123,
|
||||
Type => 'some ticket type',
|
||||
TypeID => 123,
|
||||
SLA => 'some sla',
|
||||
SLAID => 123,
|
||||
Service => 'some service',
|
||||
ServiceID => 123,
|
||||
Responsible => 'some_responsible_login',
|
||||
ResponsibleID => 123,
|
||||
Age => 3456,
|
||||
Created => '2010-10-27 20:15:00'
|
||||
CreateBy => 123,
|
||||
Changed => '2010-10-27 20:15:15',
|
||||
ChangeBy => 123,
|
||||
ArchiveFlag => 'y',
|
||||
|
||||
# If DynamicFields => 1 was passed, you'll get an entry like this for each dynamic field:
|
||||
DynamicField => [
|
||||
{
|
||||
Name => 'some name',
|
||||
Value => 'some value',
|
||||
},
|
||||
],
|
||||
|
||||
# (time stamps of expected escalations)
|
||||
EscalationResponseTime (unix time stamp of response time escalation)
|
||||
EscalationUpdateTime (unix time stamp of update time escalation)
|
||||
EscalationSolutionTime (unix time stamp of solution time escalation)
|
||||
|
||||
# (general escalation info of nearest escalation type)
|
||||
EscalationDestinationIn (escalation in e. g. 1h 4m)
|
||||
EscalationDestinationTime (date of escalation in unix time, e. g. 72193292)
|
||||
EscalationDestinationDate (date of escalation, e. g. "2009-02-14 18:00:00")
|
||||
EscalationTimeWorkingTime (seconds of working/service time till escalation, e. g. "1800")
|
||||
EscalationTime (seconds total till escalation of nearest escalation time type - response, update or solution time, e. g. "3600")
|
||||
|
||||
# (detailed escalation info about first response, update and solution time)
|
||||
FirstResponseTimeEscalation (if true, ticket is escalated)
|
||||
FirstResponseTimeNotification (if true, notify - x% of escalation has reached)
|
||||
FirstResponseTimeDestinationTime (date of escalation in unix time, e. g. 72193292)
|
||||
FirstResponseTimeDestinationDate (date of escalation, e. g. "2009-02-14 18:00:00")
|
||||
FirstResponseTimeWorkingTime (seconds of working/service time till escalation, e. g. "1800")
|
||||
FirstResponseTime (seconds total till escalation, e. g. "3600")
|
||||
|
||||
UpdateTimeEscalation (if true, ticket is escalated)
|
||||
UpdateTimeNotification (if true, notify - x% of escalation has reached)
|
||||
UpdateTimeDestinationTime (date of escalation in unix time, e. g. 72193292)
|
||||
UpdateTimeDestinationDate (date of escalation, e. g. "2009-02-14 18:00:00")
|
||||
UpdateTimeWorkingTime (seconds of working/service time till escalation, e. g. "1800")
|
||||
UpdateTime (seconds total till escalation, e. g. "3600")
|
||||
|
||||
SolutionTimeEscalation (if true, ticket is escalated)
|
||||
SolutionTimeNotification (if true, notify - x% of escalation has reached)
|
||||
SolutionTimeDestinationTime (date of escalation in unix time, e. g. 72193292)
|
||||
SolutionTimeDestinationDate (date of escalation, e. g. "2009-02-14 18:00:00")
|
||||
SolutionTimeWorkingTime (seconds of working/service time till escalation, e. g. "1800")
|
||||
SolutionTime (seconds total till escalation, e. g. "3600")
|
||||
|
||||
# if you use param Extended to get extended ticket attributes
|
||||
FirstResponse (timestamp of first response, first contact with customer)
|
||||
FirstResponseInMin (minutes till first response)
|
||||
FirstResponseDiffInMin (minutes till or over first response)
|
||||
|
||||
SolutionInMin (minutes till solution time)
|
||||
SolutionDiffInMin (minutes till or over solution time)
|
||||
|
||||
FirstLock (timestamp of first lock)
|
||||
|
||||
Article => [
|
||||
{
|
||||
ArticleID
|
||||
From
|
||||
To
|
||||
Cc
|
||||
Subject
|
||||
Body
|
||||
ReplyTo
|
||||
MessageID
|
||||
InReplyTo
|
||||
References
|
||||
SenderType
|
||||
SenderTypeID
|
||||
IsVisibleForCustomer
|
||||
ContentType
|
||||
Charset
|
||||
MimeType
|
||||
IncomingTime
|
||||
|
||||
# If DynamicFields => 1 was passed, you'll get an entry like this for each dynamic field:
|
||||
DynamicField => [
|
||||
{
|
||||
Name => 'some name',
|
||||
Value => 'some value',
|
||||
},
|
||||
],
|
||||
|
||||
Attachment => [
|
||||
{
|
||||
Content => "xxxx", # actual attachment contents, base64 enconded
|
||||
ContentAlternative => "",
|
||||
ContentID => "",
|
||||
ContentType => "application/pdf",
|
||||
FileID => 34,
|
||||
Filename => "StdAttachment-Test1.pdf",
|
||||
FilesizeRaw => 4722,
|
||||
},
|
||||
{
|
||||
# . . .
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
#. . .
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
#. . .
|
||||
},
|
||||
]
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Result = $Self->Init(
|
||||
WebserviceID => $Self->{WebserviceID},
|
||||
);
|
||||
|
||||
if ( !$Result->{Success} ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'Webservice.InvalidConfiguration',
|
||||
ErrorMessage => $Result->{ErrorMessage},
|
||||
);
|
||||
}
|
||||
|
||||
my ( $UserID, $UserType ) = $Self->Auth(
|
||||
%Param,
|
||||
);
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketGet.AuthFail',
|
||||
ErrorMessage => "TicketGet: Authorization failing!",
|
||||
) if !$UserID;
|
||||
|
||||
# check needed stuff
|
||||
for my $Needed (qw(TicketID)) {
|
||||
if ( !$Param{Data}->{$Needed} ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketGet.MissingParameter',
|
||||
ErrorMessage => "TicketGet: $Needed parameter is missing!",
|
||||
);
|
||||
}
|
||||
}
|
||||
my $ErrorMessage = '';
|
||||
|
||||
# all needed variables
|
||||
my @TicketIDs;
|
||||
if ( IsStringWithData( $Param{Data}->{TicketID} ) ) {
|
||||
@TicketIDs = split( /,/, $Param{Data}->{TicketID} );
|
||||
}
|
||||
elsif ( IsArrayRefWithData( $Param{Data}->{TicketID} ) ) {
|
||||
@TicketIDs = @{ $Param{Data}->{TicketID} };
|
||||
}
|
||||
else {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketGet.WrongStructure',
|
||||
ErrorMessage => "TicketGet: Structure for TicketID is not correct!",
|
||||
);
|
||||
}
|
||||
|
||||
# Get the list of article dynamic fields
|
||||
my $ArticleDynamicFieldList = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldList(
|
||||
ObjectType => 'Article',
|
||||
ResultType => 'HASH',
|
||||
);
|
||||
|
||||
# Crate a lookup list for easy search
|
||||
my %ArticleDynamicFieldLookup = reverse %{$ArticleDynamicFieldList};
|
||||
|
||||
TICKET:
|
||||
for my $TicketID (@TicketIDs) {
|
||||
|
||||
my $Access = $Self->CheckAccessPermissions(
|
||||
TicketID => $TicketID,
|
||||
UserID => $UserID,
|
||||
UserType => $UserType,
|
||||
);
|
||||
|
||||
next TICKET if $Access;
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketGet.AccessDenied',
|
||||
ErrorMessage => 'TicketGet: User does not have access to the ticket!',
|
||||
);
|
||||
}
|
||||
|
||||
my $DynamicFields = $Param{Data}->{DynamicFields} || 0;
|
||||
my $Extended = $Param{Data}->{Extended} || 0;
|
||||
my $AllArticles = $Param{Data}->{AllArticles} || 0;
|
||||
my $ArticleOrder = $Param{Data}->{ArticleOrder} || 'ASC';
|
||||
my $ArticleLimit = $Param{Data}->{ArticleLimit} || 0;
|
||||
my $Attachments = $Param{Data}->{Attachments} || 0;
|
||||
my $GetAttachmentContents = $Param{Data}->{GetAttachmentContents} // 1;
|
||||
|
||||
my $ReturnData = {
|
||||
Success => 1,
|
||||
};
|
||||
my @Item;
|
||||
|
||||
my $ArticleSenderType = '';
|
||||
if ( IsArrayRefWithData( $Param{Data}->{ArticleSenderType} ) ) {
|
||||
$ArticleSenderType = $Param{Data}->{ArticleSenderType};
|
||||
}
|
||||
elsif ( IsStringWithData( $Param{Data}->{ArticleSenderType} ) ) {
|
||||
$ArticleSenderType = [ $Param{Data}->{ArticleSenderType} ];
|
||||
}
|
||||
|
||||
# By default, do not include HTML body as attachment, unless it is explicitly requested.
|
||||
my %ExcludeAttachments = (
|
||||
ExcludePlainText => 1,
|
||||
ExcludeHTMLBody => $Param{Data}->{HTMLBodyAsAttachment} ? 0 : 1,
|
||||
);
|
||||
|
||||
# start ticket loop
|
||||
TICKET:
|
||||
for my $TicketID (@TicketIDs) {
|
||||
|
||||
my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
|
||||
|
||||
# get the Ticket entry
|
||||
my %TicketEntryRaw = $TicketObject->TicketGet(
|
||||
TicketID => $TicketID,
|
||||
DynamicFields => $DynamicFields,
|
||||
Extended => $Extended,
|
||||
UserID => $UserID,
|
||||
);
|
||||
|
||||
if ( !IsHashRefWithData( \%TicketEntryRaw ) ) {
|
||||
|
||||
$ErrorMessage = 'Could not get Ticket data'
|
||||
. ' in Kernel::GenericInterface::Operation::Ticket::TicketGet::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketGet.NotValidTicketID',
|
||||
ErrorMessage => "TicketGet: $ErrorMessage",
|
||||
);
|
||||
}
|
||||
|
||||
my %TicketEntry;
|
||||
my @DynamicFields;
|
||||
|
||||
# remove all dynamic fields from main ticket hash and set them into an array.
|
||||
ATTRIBUTE:
|
||||
for my $Attribute ( sort keys %TicketEntryRaw ) {
|
||||
|
||||
if ( $Attribute =~ m{\A DynamicField_(.*) \z}msx ) {
|
||||
push @DynamicFields, {
|
||||
Name => $1,
|
||||
Value => $TicketEntryRaw{$Attribute},
|
||||
};
|
||||
next ATTRIBUTE;
|
||||
}
|
||||
|
||||
$TicketEntry{$Attribute} = $TicketEntryRaw{$Attribute};
|
||||
}
|
||||
|
||||
$TicketEntry{TimeUnit} = $TicketObject->TicketAccountedTimeGet(
|
||||
TicketID => $TicketID,
|
||||
);
|
||||
|
||||
# add dynamic fields array into 'DynamicField' hash key if any
|
||||
if (@DynamicFields) {
|
||||
$TicketEntry{DynamicField} = \@DynamicFields;
|
||||
}
|
||||
|
||||
# set Ticket entry data
|
||||
my $TicketBundle = {
|
||||
%TicketEntry,
|
||||
};
|
||||
|
||||
if ( !$AllArticles ) {
|
||||
push @Item, $TicketBundle;
|
||||
next TICKET;
|
||||
}
|
||||
|
||||
my %ArticleListFilters;
|
||||
if ( $UserType eq 'Customer' ) {
|
||||
%ArticleListFilters = (
|
||||
IsVisibleForCustomer => 1,
|
||||
);
|
||||
}
|
||||
|
||||
my $ArticleObject = $Kernel::OM->Get('Kernel::System::Ticket::Article');
|
||||
|
||||
my @Articles;
|
||||
if ($ArticleSenderType) {
|
||||
for my $SenderType ( @{ $ArticleSenderType || [] } ) {
|
||||
my @ArticlesFiltered = $ArticleObject->ArticleList(
|
||||
TicketID => $TicketID,
|
||||
SenderType => $SenderType,
|
||||
%ArticleListFilters,
|
||||
);
|
||||
push @Articles, @ArticlesFiltered;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@Articles = $ArticleObject->ArticleList(
|
||||
TicketID => $TicketID,
|
||||
%ArticleListFilters,
|
||||
);
|
||||
}
|
||||
|
||||
# Modify ArticleLimit if it is greater then number of articles (see bug#14585).
|
||||
if ( $ArticleLimit > scalar @Articles ) {
|
||||
$ArticleLimit = scalar @Articles;
|
||||
}
|
||||
|
||||
# Set number of articles by ArticleLimit and ArticleOrder parameters.
|
||||
if ( IsArrayRefWithData( \@Articles ) && $ArticleLimit ) {
|
||||
if ( $ArticleOrder eq 'DESC' ) {
|
||||
@Articles = reverse @Articles;
|
||||
}
|
||||
@Articles = @Articles[ 0 .. ( $ArticleLimit - 1 ) ];
|
||||
}
|
||||
|
||||
# start article loop
|
||||
ARTICLE:
|
||||
for my $Article (@Articles) {
|
||||
|
||||
my $ArticleBackendObject = $ArticleObject->BackendForArticle( %{$Article} );
|
||||
|
||||
my %ArticleData = $ArticleBackendObject->ArticleGet(
|
||||
TicketID => $TicketID,
|
||||
ArticleID => $Article->{ArticleID},
|
||||
DynamicFields => $DynamicFields,
|
||||
);
|
||||
$Article = \%ArticleData;
|
||||
|
||||
next ARTICLE if !$Attachments;
|
||||
|
||||
# get attachment index (without attachments)
|
||||
my %AtmIndex = $ArticleBackendObject->ArticleAttachmentIndex(
|
||||
ArticleID => $Article->{ArticleID},
|
||||
%ExcludeAttachments,
|
||||
);
|
||||
|
||||
next ARTICLE if !IsHashRefWithData( \%AtmIndex );
|
||||
|
||||
my @Attachments;
|
||||
ATTACHMENT:
|
||||
for my $FileID ( sort keys %AtmIndex ) {
|
||||
next ATTACHMENT if !$FileID;
|
||||
my %Attachment = $ArticleBackendObject->ArticleAttachment(
|
||||
ArticleID => $Article->{ArticleID},
|
||||
FileID => $FileID, # as returned by ArticleAttachmentIndex
|
||||
);
|
||||
|
||||
next ATTACHMENT if !IsHashRefWithData( \%Attachment );
|
||||
|
||||
$Attachment{FileID} = $FileID;
|
||||
if ($GetAttachmentContents)
|
||||
{
|
||||
# convert content to base64, but prevent 76 chars brake, see bug#14500.
|
||||
$Attachment{Content} = encode_base64( $Attachment{Content}, '' );
|
||||
}
|
||||
else {
|
||||
# unset content
|
||||
$Attachment{Content} = '';
|
||||
$Attachment{ContentAlternative} = '';
|
||||
}
|
||||
push @Attachments, {%Attachment};
|
||||
}
|
||||
|
||||
# set Attachments data
|
||||
$Article->{Attachment} = \@Attachments;
|
||||
|
||||
} # finish article loop
|
||||
|
||||
# set Ticket entry data
|
||||
if (@Articles) {
|
||||
|
||||
my @ArticleBox;
|
||||
|
||||
for my $ArticleRaw (@Articles) {
|
||||
my %Article;
|
||||
my @ArticleDynamicFields;
|
||||
|
||||
# remove all dynamic fields from main article hash and set them into an array.
|
||||
ATTRIBUTE:
|
||||
for my $Attribute ( sort keys %{$ArticleRaw} ) {
|
||||
|
||||
if ( $Attribute =~ m{\A DynamicField_(.*) \z}msx ) {
|
||||
|
||||
# skip dynamic fields that are not article related
|
||||
# this is needed because ArticleGet() also returns ticket dynamic fields
|
||||
next ATTRIBUTE if ( !$ArticleDynamicFieldLookup{$1} );
|
||||
|
||||
push @ArticleDynamicFields, {
|
||||
Name => $1,
|
||||
Value => $ArticleRaw->{$Attribute},
|
||||
};
|
||||
next ATTRIBUTE;
|
||||
}
|
||||
|
||||
$Article{$Attribute} = $ArticleRaw->{$Attribute};
|
||||
}
|
||||
|
||||
$Article{TimeUnit} = $ArticleObject->ArticleAccountedTimeGet(
|
||||
ArticleID => $ArticleRaw->{ArticleID}
|
||||
);
|
||||
|
||||
# add dynamic fields array into 'DynamicField' hash key if any
|
||||
if (@ArticleDynamicFields) {
|
||||
$Article{DynamicField} = \@ArticleDynamicFields;
|
||||
}
|
||||
|
||||
push @ArticleBox, \%Article;
|
||||
}
|
||||
$TicketBundle->{Article} = \@ArticleBox;
|
||||
}
|
||||
|
||||
# add
|
||||
push @Item, $TicketBundle;
|
||||
} # finish ticket loop
|
||||
|
||||
if ( !scalar @Item ) {
|
||||
$ErrorMessage = 'Could not get Ticket data'
|
||||
. ' in Kernel::GenericInterface::Operation::Ticket::TicketGet::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketGet.NotTicketData',
|
||||
ErrorMessage => "TicketGet: $ErrorMessage",
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
# set ticket data into return structure
|
||||
$ReturnData->{Data}->{Ticket} = \@Item;
|
||||
|
||||
# return result
|
||||
return $ReturnData;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -0,0 +1,240 @@
|
||||
# --
|
||||
# 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::Ticket::TicketHistoryGet;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::System::VariableCheck qw(IsArrayRefWithData IsHashRefWithData IsStringWithData);
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
Kernel::GenericInterface::Operation::Ticket::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::Ticket::TicketHistoryGet - GenericInterface Ticket History Get Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# check needed objects
|
||||
for my $Needed (qw(DebuggerObject WebserviceID)) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!",
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform TicketHistoryGet Operation. This function is able to return
|
||||
one or more ticket entries in one call.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
Data => {
|
||||
UserLogin => 'some agent login', # UserLogin or SessionID is required
|
||||
SessionID => 123,
|
||||
Password => 'some password', # if UserLogin is sent then Password is required
|
||||
TicketID => '32,33', # required, could be coma separated IDs or an Array
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # In case of an error
|
||||
Data => {
|
||||
TicketHistory => [
|
||||
{
|
||||
TicketID => 123,
|
||||
History => [
|
||||
# ...
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Result = $Self->Init(
|
||||
WebserviceID => $Self->{WebserviceID},
|
||||
);
|
||||
|
||||
if ( !$Result->{Success} ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'Webservice.InvalidConfiguration',
|
||||
ErrorMessage => $Result->{ErrorMessage},
|
||||
);
|
||||
}
|
||||
|
||||
my ( $UserID, $UserType ) = $Self->Auth(
|
||||
%Param,
|
||||
);
|
||||
|
||||
if ( !$UserID ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketHistoryGet.AuthFail',
|
||||
ErrorMessage => "TicketHistoryGet: Authorization failing!",
|
||||
);
|
||||
}
|
||||
if ( $UserType ne 'User' ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketHistoryGet.AuthFail',
|
||||
ErrorMessage => "TicketHistoryGet: User needs to an Agent!",
|
||||
);
|
||||
}
|
||||
|
||||
for my $Needed (qw(TicketID)) {
|
||||
if ( !$Param{Data}->{$Needed} ) {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketHistoryGet.MissingParameter',
|
||||
ErrorMessage => "TicketHistoryGet: $Needed parameter is missing!",
|
||||
);
|
||||
}
|
||||
}
|
||||
my $ErrorMessage = '';
|
||||
|
||||
# All needed variables.
|
||||
my @TicketIDs;
|
||||
if ( IsStringWithData( $Param{Data}->{TicketID} ) ) {
|
||||
@TicketIDs = split( /,/, $Param{Data}->{TicketID} );
|
||||
}
|
||||
elsif ( IsArrayRefWithData( $Param{Data}->{TicketID} ) ) {
|
||||
@TicketIDs = @{ $Param{Data}->{TicketID} };
|
||||
}
|
||||
else {
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketHistoryGet.WrongStructure',
|
||||
ErrorMessage => "TicketHistoryGet: Structure for TicketID is not correct!",
|
||||
);
|
||||
}
|
||||
|
||||
TICKET:
|
||||
for my $TicketID (@TicketIDs) {
|
||||
|
||||
my $Access = $Self->CheckAccessPermissions(
|
||||
TicketID => $TicketID,
|
||||
UserID => $UserID,
|
||||
UserType => $UserType,
|
||||
);
|
||||
|
||||
next TICKET if $Access;
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketHistoryGet.AccessDenied',
|
||||
ErrorMessage => "TicketHistoryGet: User does not have access to the ticket $TicketID!",
|
||||
);
|
||||
}
|
||||
|
||||
my $ReturnData = {
|
||||
Success => 1,
|
||||
};
|
||||
|
||||
my @Histories;
|
||||
|
||||
my %SafeAttributes = (
|
||||
TicketID => 1,
|
||||
ArticleID => 1,
|
||||
Name => 1,
|
||||
CreateBy => 1,
|
||||
CreateTime => 1,
|
||||
HistoryType => 1,
|
||||
QueueID => 1,
|
||||
OwnerID => 1,
|
||||
PriorityID => 1,
|
||||
StateID => 1,
|
||||
HistoryTypeID => 1,
|
||||
TypeID => 1,
|
||||
);
|
||||
|
||||
# start ticket loop
|
||||
TICKET:
|
||||
for my $TicketID (@TicketIDs) {
|
||||
|
||||
# get ticket object
|
||||
my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
|
||||
|
||||
my @LinesRaw = $TicketObject->HistoryGet(
|
||||
TicketID => $TicketID,
|
||||
UserID => $UserID,
|
||||
);
|
||||
|
||||
my @Lines;
|
||||
for my $Line (@LinesRaw) {
|
||||
|
||||
my %Attributes;
|
||||
|
||||
ATTRIBUTE:
|
||||
for my $Attribute ( sort keys %{$Line} ) {
|
||||
next ATTRIBUTE if !$SafeAttributes{$Attribute};
|
||||
|
||||
$Attributes{$Attribute} = $Line->{$Attribute};
|
||||
}
|
||||
|
||||
push @Lines, \%Attributes;
|
||||
}
|
||||
|
||||
push @Histories, {
|
||||
TicketID => $TicketID,
|
||||
History => \@Lines,
|
||||
};
|
||||
}
|
||||
|
||||
if ( !scalar @Histories ) {
|
||||
$ErrorMessage = 'Could not get Ticket history data'
|
||||
. ' in Kernel::GenericInterface::Operation::Ticket::TicketHistoryGet::Run()';
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketHistoryGet.NotTicketData',
|
||||
ErrorMessage => "TicketHistoryGet: $ErrorMessage",
|
||||
);
|
||||
}
|
||||
|
||||
# set ticket data into return structure
|
||||
$ReturnData->{Data}->{TicketHistory} = \@Histories;
|
||||
|
||||
# return result
|
||||
return $ReturnData;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 TERMS AND CONDITIONS
|
||||
|
||||
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
|
||||
@@ -0,0 +1,848 @@
|
||||
# --
|
||||
# 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::Ticket::TicketSearch;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::System::VariableCheck qw( :all );
|
||||
|
||||
use parent qw(
|
||||
Kernel::GenericInterface::Operation::Common
|
||||
Kernel::GenericInterface::Operation::Ticket::Common
|
||||
);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::GenericInterface::Operation::Ticket::TicketSearch - GenericInterface Ticket Search Operation backend
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
usually, you want to create an instance of this
|
||||
by using Kernel::GenericInterface::Operation->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# check needed objects
|
||||
for my $Needed (qw(DebuggerObject WebserviceID)) {
|
||||
if ( !$Param{$Needed} ) {
|
||||
return {
|
||||
Success => 0,
|
||||
ErrorMessage => "Got no $Needed!",
|
||||
};
|
||||
}
|
||||
|
||||
$Self->{$Needed} = $Param{$Needed};
|
||||
}
|
||||
|
||||
# get config for this screen
|
||||
$Self->{Config} = $Kernel::OM->Get('Kernel::Config')->Get('GenericInterface::Operation::TicketSearch');
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
perform TicketSearch Operation. This will return a Ticket ID list.
|
||||
|
||||
my $Result = $OperationObject->Run(
|
||||
# ticket number (optional) as STRING or as ARRAYREF
|
||||
TicketNumber => '%123546%',
|
||||
TicketNumber => ['%123546%', '%123666%'],
|
||||
|
||||
# ticket title (optional) as STRING or as ARRAYREF
|
||||
Title => '%SomeText%',
|
||||
Title => ['%SomeTest1%', '%SomeTest2%'],
|
||||
|
||||
Queues => ['system queue', 'other queue'],
|
||||
QueueIDs => [1, 42, 512],
|
||||
|
||||
# use also sub queues of Queue|Queues in search
|
||||
UseSubQueues => 0,
|
||||
|
||||
# You can use types like normal, ...
|
||||
Types => ['normal', 'change', 'incident'],
|
||||
TypeIDs => [3, 4],
|
||||
|
||||
# You can use states like new, open, pending reminder, ...
|
||||
States => ['new', 'open'],
|
||||
StateIDs => [3, 4],
|
||||
|
||||
# (Open|Closed) tickets for all closed or open tickets.
|
||||
StateType => 'Open',
|
||||
|
||||
# You also can use real state types like new, open, closed,
|
||||
# pending reminder, pending auto, removed and merged.
|
||||
StateType => ['open', 'new'],
|
||||
StateTypeIDs => [1, 2, 3],
|
||||
|
||||
Priorities => ['1 very low', '2 low', '3 normal'],
|
||||
PriorityIDs => [1, 2, 3],
|
||||
|
||||
Services => ['Service A', 'Service B'],
|
||||
ServiceIDs => [1, 2, 3],
|
||||
|
||||
SLAs => ['SLA A', 'SLA B'],
|
||||
SLAIDs => [1, 2, 3],
|
||||
|
||||
Locks => ['unlock'],
|
||||
LockIDs => [1, 2, 3],
|
||||
|
||||
OwnerIDs => [1, 12, 455, 32]
|
||||
|
||||
ResponsibleIDs => [1, 12, 455, 32]
|
||||
|
||||
WatchUserIDs => [1, 12, 455, 32]
|
||||
|
||||
# CustomerID (optional) as STRING or as ARRAYREF
|
||||
CustomerID => '123',
|
||||
CustomerID => ['123', 'ABC'],
|
||||
|
||||
# CustomerUserLogin (optional) as STRING as ARRAYREF
|
||||
CustomerUserLogin => 'uid123',
|
||||
CustomerUserLogin => ['uid123', 'uid777'],
|
||||
|
||||
# create ticket properties (optional)
|
||||
CreatedUserIDs => [1, 12, 455, 32]
|
||||
CreatedTypes => ['normal', 'change', 'incident'],
|
||||
CreatedTypeIDs => [1, 2, 3],
|
||||
CreatedPriorities => ['1 very low', '2 low', '3 normal'],
|
||||
CreatedPriorityIDs => [1, 2, 3],
|
||||
CreatedStates => ['new', 'open'],
|
||||
CreatedStateIDs => [3, 4],
|
||||
CreatedQueues => ['system queue', 'other queue'],
|
||||
CreatedQueueIDs => [1, 42, 512],
|
||||
|
||||
# DynamicFields
|
||||
# At least one operator must be specified. Operators will be connected with AND,
|
||||
# values in an operator with OR.
|
||||
# You can also pass more than one argument to an operator: ['value1', 'value2']
|
||||
DynamicField_FieldNameX => {
|
||||
Empty => 1, # will return dynamic fields without a value
|
||||
# set to 0 to search fields with a value present.
|
||||
Equals => 123,
|
||||
Like => 'value*', # "equals" operator with wildcard support
|
||||
GreaterThan => '2001-01-01 01:01:01',
|
||||
GreaterThanEquals => '2001-01-01 01:01:01',
|
||||
SmallerThan => '2002-02-02 02:02:02',
|
||||
SmallerThanEquals => '2002-02-02 02:02:02',
|
||||
},
|
||||
|
||||
# article stuff (optional)
|
||||
MIMEBase_From => '%spam@example.com%',
|
||||
MIMEBase_To => '%service@example.com%',
|
||||
MIMEBase_Cc => '%client@example.com%',
|
||||
MIMEBase_Subject => '%VIRUS 32%',
|
||||
MIMEBase_Body => '%VIRUS 32%',
|
||||
|
||||
# attachment stuff (optional, applies only for ArticleStorageDB)
|
||||
AttachmentName => '%anyfile.txt%',
|
||||
|
||||
# use full article text index if configured (optional, default off)
|
||||
FullTextIndex => 1,
|
||||
|
||||
# article content search (AND or OR for From, To, Cc, Subject and Body) (optional)
|
||||
ContentSearch => 'AND',
|
||||
|
||||
# content conditions for From,To,Cc,Subject,Body
|
||||
# Title,CustomerID and CustomerUserLogin (all optional)
|
||||
ConditionInline => 1,
|
||||
|
||||
# articles created more than 60 minutes ago (article older than 60 minutes) (optional)
|
||||
ArticleCreateTimeOlderMinutes => 60,
|
||||
# articles created less than 120 minutes ago (article newer than 60 minutes) (optional)
|
||||
ArticleCreateTimeNewerMinutes => 120,
|
||||
|
||||
# articles with create time after ... (article newer than this date) (optional)
|
||||
ArticleCreateTimeNewerDate => '2006-01-09 00:00:01',
|
||||
# articles with created time before ... (article older than this date) (optional)
|
||||
ArticleCreateTimeOlderDate => '2006-01-19 23:59:59',
|
||||
|
||||
# tickets created more than 60 minutes ago (ticket older than 60 minutes) (optional)
|
||||
TicketCreateTimeOlderMinutes => 60,
|
||||
# tickets created less than 120 minutes ago (ticket newer than 120 minutes) (optional)
|
||||
TicketCreateTimeNewerMinutes => 120,
|
||||
|
||||
# tickets with create time after ... (ticket newer than this date) (optional)
|
||||
TicketCreateTimeNewerDate => '2006-01-09 00:00:01',
|
||||
# tickets with created time before ... (ticket older than this date) (optional)
|
||||
TicketCreateTimeOlderDate => '2006-01-19 23:59:59',
|
||||
|
||||
# ticket history entries that created more than 60 minutes ago (optional)
|
||||
TicketChangeTimeOlderMinutes => 60,
|
||||
# ticket history entries that created less than 120 minutes ago (optional)
|
||||
TicketChangeTimeNewerMinutes => 120,
|
||||
|
||||
# tickets changed more than 60 minutes ago (optional)
|
||||
TicketLastChangeTimeOlderMinutes => 60,
|
||||
# tickets changed less than 120 minutes ago (optional)
|
||||
TicketLastChangeTimeNewerMinutes => 120,
|
||||
|
||||
# tickets with changed time after ... (ticket changed newer than this date) (optional)
|
||||
TicketLastChangeTimeNewerDate => '2006-01-09 00:00:01',
|
||||
# tickets with changed time before ... (ticket changed older than this date) (optional)
|
||||
TicketLastChangeTimeOlderDate => '2006-01-19 23:59:59',
|
||||
|
||||
# ticket history entry create time after ... (ticket history entries newer than this date) (optional)
|
||||
TicketChangeTimeNewerDate => '2006-01-09 00:00:01',
|
||||
# ticket history entry create time before ... (ticket history entries older than this date) (optional)
|
||||
TicketChangeTimeOlderDate => '2006-01-19 23:59:59',
|
||||
|
||||
# tickets closed more than 60 minutes ago (optional)
|
||||
TicketCloseTimeOlderMinutes => 60,
|
||||
# tickets closed less than 120 minutes ago (optional)
|
||||
TicketCloseTimeNewerMinutes => 120,
|
||||
|
||||
# tickets with closed time after ... (ticket closed newer than this date) (optional)
|
||||
TicketCloseTimeNewerDate => '2006-01-09 00:00:01',
|
||||
# tickets with closed time before ... (ticket closed older than this date) (optional)
|
||||
TicketCloseTimeOlderDate => '2006-01-19 23:59:59',
|
||||
|
||||
# tickets with pending time of more than 60 minutes ago (optional)
|
||||
TicketPendingTimeOlderMinutes => 60,
|
||||
# tickets with pending time of less than 120 minutes ago (optional)
|
||||
TicketPendingTimeNewerMinutes => 120,
|
||||
|
||||
# tickets with pending time after ... (optional)
|
||||
TicketPendingTimeNewerDate => '2006-01-09 00:00:01',
|
||||
# tickets with pending time before ... (optional)
|
||||
TicketPendingTimeOlderDate => '2006-01-19 23:59:59',
|
||||
|
||||
# you can use all following escalation options with this four different ways of escalations
|
||||
# TicketEscalationTime...
|
||||
# TicketEscalationUpdateTime...
|
||||
# TicketEscalationResponseTime...
|
||||
# TicketEscalationSolutionTime...
|
||||
|
||||
# ticket escalation time of more than 60 minutes ago (optional)
|
||||
TicketEscalationTimeOlderMinutes => -60,
|
||||
# ticket escalation time of less than 120 minutes ago (optional)
|
||||
TicketEscalationTimeNewerMinutes => -120,
|
||||
|
||||
# tickets with escalation time after ... (optional)
|
||||
TicketEscalationTimeNewerDate => '2006-01-09 00:00:01',
|
||||
# tickets with escalation time before ... (optional)
|
||||
TicketEscalationTimeOlderDate => '2006-01-09 23:59:59',
|
||||
|
||||
# search in archive (optional, default is not to search in archived tickets)
|
||||
SearchInArchive => 'AllTickets', # 'AllTickets' (normal and archived) or 'ArchivedTickets' (only archived)
|
||||
|
||||
# OrderBy and SortBy (optional)
|
||||
OrderBy => 'Down', # Down|Up
|
||||
SortBy => 'Age', # Owner|Responsible|CustomerID|State|TicketNumber|Queue|Priority|Age|Type|Lock
|
||||
# Changed|Title|Service|SLA|PendingTime|EscalationTime
|
||||
# EscalationUpdateTime|EscalationResponseTime|EscalationSolutionTime
|
||||
# DynamicField_FieldNameX
|
||||
# TicketFreeTime1-6|TicketFreeKey1-16|TicketFreeText1-16
|
||||
|
||||
# OrderBy and SortBy as ARRAY for sub sorting (optional)
|
||||
OrderBy => ['Down', 'Up'],
|
||||
SortBy => ['Priority', 'Age'],
|
||||
},
|
||||
);
|
||||
|
||||
$Result = {
|
||||
Success => 1, # 0 or 1
|
||||
ErrorMessage => '', # In case of an error
|
||||
Data => {
|
||||
TicketID => [ 1, 2, 3, 4 ],
|
||||
},
|
||||
};
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Result = $Self->Init(
|
||||
WebserviceID => $Self->{WebserviceID},
|
||||
);
|
||||
|
||||
if ( !$Result->{Success} ) {
|
||||
$Self->ReturnError(
|
||||
ErrorCode => 'Webservice.InvalidConfiguration',
|
||||
ErrorMessage => $Result->{ErrorMessage},
|
||||
);
|
||||
}
|
||||
|
||||
my ( $UserID, $UserType ) = $Self->Auth(
|
||||
%Param,
|
||||
);
|
||||
|
||||
return $Self->ReturnError(
|
||||
ErrorCode => 'TicketSearch.AuthFail',
|
||||
ErrorMessage => "TicketSearch: Authorization failing!",
|
||||
) if !$UserID;
|
||||
|
||||
# all needed variables
|
||||
$Self->{SearchLimit} = $Param{Data}->{Limit}
|
||||
|| $Self->{Config}->{SearchLimit}
|
||||
|| 500;
|
||||
$Self->{SortBy} = $Param{Data}->{SortBy}
|
||||
|| $Self->{Config}->{'SortBy::Default'}
|
||||
|| 'Age';
|
||||
$Self->{OrderBy} = $Param{Data}->{OrderBy}
|
||||
|| $Self->{Config}->{'Order::Default'}
|
||||
|| 'Down';
|
||||
$Self->{FullTextIndex} = $Param{Data}->{FullTextIndex} || 0;
|
||||
|
||||
# get parameter from data
|
||||
my %GetParam = $Self->_GetParams( %{ $Param{Data} } );
|
||||
|
||||
# create time settings
|
||||
%GetParam = $Self->_CreateTimeSettings(%GetParam);
|
||||
|
||||
# get dynamic fields
|
||||
my %DynamicFieldSearchParameters = $Self->_GetDynamicFields( %{ $Param{Data} } );
|
||||
|
||||
# perform ticket search
|
||||
$UserType = ( $UserType eq 'Customer' ) ? 'CustomerUserID' : 'UserID';
|
||||
my @TicketIDs = $Kernel::OM->Get('Kernel::System::Ticket')->TicketSearch(
|
||||
%GetParam,
|
||||
%DynamicFieldSearchParameters,
|
||||
Result => 'ARRAY',
|
||||
SortBy => $Self->{SortBy},
|
||||
OrderBy => $Self->{OrderBy},
|
||||
Limit => $Self->{SearchLimit},
|
||||
$UserType => $UserID,
|
||||
ConditionInline => $Self->{Config}->{ExtendedSearchCondition},
|
||||
ContentSearchPrefix => '*',
|
||||
ContentSearchSuffix => '*',
|
||||
FullTextIndex => $Self->{FullTextIndex},
|
||||
);
|
||||
|
||||
if (@TicketIDs) {
|
||||
|
||||
return {
|
||||
Success => 1,
|
||||
Data => {
|
||||
TicketID => \@TicketIDs,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
# return result
|
||||
return {
|
||||
Success => 1,
|
||||
Data => {},
|
||||
};
|
||||
}
|
||||
|
||||
=begin Internal:
|
||||
|
||||
=head2 _GetParams()
|
||||
|
||||
get search parameters.
|
||||
|
||||
my %GetParam = _GetParams(
|
||||
%Params, # all ticket parameters
|
||||
);
|
||||
|
||||
returns:
|
||||
|
||||
%GetParam = {
|
||||
AllowedParams => 'WithContent', # return not empty parameters for search
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub _GetParams {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# get single params
|
||||
my %GetParam;
|
||||
|
||||
my %SearchableFields = $Kernel::OM->Get('Kernel::System::Ticket::Article')->ArticleSearchableFieldsList();
|
||||
|
||||
for my $Item (
|
||||
sort keys %SearchableFields,
|
||||
qw(
|
||||
Agent ResultForm TimeSearchType ChangeTimeSearchType LastChangeTimeSearchType CloseTimeSearchType UseSubQueues
|
||||
ArticleTimeSearchType SearchInArchive
|
||||
Fulltext ContentSearch ShownAttributes
|
||||
)
|
||||
)
|
||||
{
|
||||
|
||||
# get search string params (get submitted params)
|
||||
if ( IsStringWithData( $Param{$Item} ) ) {
|
||||
|
||||
$GetParam{$Item} = $Param{$Item};
|
||||
|
||||
# remove white space on the start and end
|
||||
$GetParam{$Item} =~ s/\s+$//g;
|
||||
$GetParam{$Item} =~ s/^\s+//g;
|
||||
}
|
||||
}
|
||||
|
||||
# get array params
|
||||
for my $Item (
|
||||
qw(TicketNumber TicketID Title
|
||||
StateIDs StateTypeIDs QueueIDs PriorityIDs OwnerIDs
|
||||
CreatedUserIDs WatchUserIDs ResponsibleIDs
|
||||
TypeIDs ServiceIDs SLAIDs LockIDs Queues Types States
|
||||
Priorities Services SLAs Locks
|
||||
CreatedTypes CreatedTypeIDs CreatedPriorities
|
||||
CreatedPriorityIDs CreatedStates CreatedStateIDs
|
||||
CreatedQueues CreatedQueueIDs StateType CustomerID
|
||||
CustomerUserLogin )
|
||||
)
|
||||
{
|
||||
|
||||
# get search array params
|
||||
my @Values;
|
||||
if ( IsArrayRefWithData( $Param{$Item} ) ) {
|
||||
@Values = @{ $Param{$Item} };
|
||||
}
|
||||
elsif ( IsStringWithData( $Param{$Item} ) ) {
|
||||
@Values = ( $Param{$Item} );
|
||||
}
|
||||
$GetParam{$Item} = \@Values if scalar @Values;
|
||||
}
|
||||
|
||||
# get escalation times
|
||||
my %EscalationTimes = (
|
||||
1 => '',
|
||||
2 => 'Update',
|
||||
3 => 'Response',
|
||||
4 => 'Solution',
|
||||
);
|
||||
|
||||
for my $Index ( sort keys %EscalationTimes ) {
|
||||
for my $PostFix (qw( OlderMinutes NewerMinutes NewerDate OlderDate )) {
|
||||
my $Item = 'TicketEscalation' . $EscalationTimes{$Index} . 'Time' . $PostFix;
|
||||
|
||||
# get search string params (get submitted params)
|
||||
if ( IsStringWithData( $Param{$Item} ) ) {
|
||||
$GetParam{$Item} = $Param{$Item};
|
||||
|
||||
# remove white space on the start and end
|
||||
$GetParam{$Item} =~ s/\s+$//g;
|
||||
$GetParam{$Item} =~ s/^\s+//g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my @Prefixes = (
|
||||
'TicketCreateTime',
|
||||
'TicketChangeTime',
|
||||
'TicketLastChangeTime',
|
||||
'TicketCloseTime',
|
||||
'TicketPendingTime',
|
||||
'ArticleCreateTime',
|
||||
);
|
||||
|
||||
my @Postfixes = (
|
||||
'Point',
|
||||
'PointFormat',
|
||||
'PointStart',
|
||||
'Start',
|
||||
'StartDay',
|
||||
'StartMonth',
|
||||
'StartYear',
|
||||
'Stop',
|
||||
'StopDay',
|
||||
'StopMonth',
|
||||
'StopYear',
|
||||
'OlderMinutes',
|
||||
'NewerMinutes',
|
||||
'OlderDate',
|
||||
'NewerDate',
|
||||
);
|
||||
|
||||
for my $Prefix (@Prefixes) {
|
||||
|
||||
# get search string params (get submitted params)
|
||||
if ( IsStringWithData( $Param{$Prefix} ) ) {
|
||||
$GetParam{$Prefix} = $Param{$Prefix};
|
||||
|
||||
# remove white space on the start and end
|
||||
$GetParam{$Prefix} =~ s/\s+$//g;
|
||||
$GetParam{$Prefix} =~ s/^\s+//g;
|
||||
}
|
||||
|
||||
for my $Postfix (@Postfixes) {
|
||||
my $Item = $Prefix . $Postfix;
|
||||
|
||||
# get search string params (get submitted params)
|
||||
if ( IsStringWithData( $Param{$Item} ) ) {
|
||||
$GetParam{$Item} = $Param{$Item};
|
||||
|
||||
# remove white space on the start and end
|
||||
$GetParam{$Item} =~ s/\s+$//g;
|
||||
$GetParam{$Item} =~ s/^\s+//g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return %GetParam;
|
||||
|
||||
}
|
||||
|
||||
=head2 _GetDynamicFields()
|
||||
|
||||
get search parameters.
|
||||
|
||||
my %DynamicFieldSearchParameters = _GetDynamicFields(
|
||||
%Params, # all ticket parameters
|
||||
);
|
||||
|
||||
returns:
|
||||
|
||||
%DynamicFieldSearchParameters = {
|
||||
'AllAllowedDF' => 'WithData', # return not empty parameters for search
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub _GetDynamicFields {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# dynamic fields search parameters for ticket search
|
||||
my %DynamicFieldSearchParameters;
|
||||
|
||||
# get single params
|
||||
my %AttributeLookup;
|
||||
|
||||
# get the dynamic fields for ticket object
|
||||
$Self->{DynamicField} = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet(
|
||||
Valid => 1,
|
||||
ObjectType => ['Ticket'],
|
||||
);
|
||||
|
||||
my %DynamicFieldsRaw;
|
||||
if ( $Param{DynamicField} ) {
|
||||
my %SearchParams;
|
||||
if ( IsHashRefWithData( $Param{DynamicField} ) ) {
|
||||
$DynamicFieldsRaw{ $Param{DynamicField}->{Name} } = $Param{DynamicField};
|
||||
}
|
||||
elsif ( IsArrayRefWithData( $Param{DynamicField} ) ) {
|
||||
%DynamicFieldsRaw = map { $_->{Name} => $_ } @{ $Param{DynamicField} };
|
||||
}
|
||||
else {
|
||||
return %DynamicFieldSearchParameters;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
# Compatibility with older versions of the web service.
|
||||
for my $ParameterName ( sort keys %Param ) {
|
||||
if ( $ParameterName =~ m{\A DynamicField_ ( [a-zA-Z\d]+ ) \z}xms ) {
|
||||
$DynamicFieldsRaw{$1} = $Param{$ParameterName};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# loop over the dynamic fields configured
|
||||
DYNAMICFIELD:
|
||||
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
|
||||
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
||||
next DYNAMICFIELD if !$DynamicFieldConfig->{Name};
|
||||
|
||||
# skip all fields that does not match with current field name
|
||||
next DYNAMICFIELD if !$DynamicFieldsRaw{ $DynamicFieldConfig->{Name} };
|
||||
|
||||
next DYNAMICFIELD if !IsHashRefWithData( $DynamicFieldsRaw{ $DynamicFieldConfig->{Name} } );
|
||||
|
||||
my %SearchOperators = %{ $DynamicFieldsRaw{ $DynamicFieldConfig->{Name} } };
|
||||
|
||||
delete $SearchOperators{Name};
|
||||
|
||||
# set search parameter
|
||||
$DynamicFieldSearchParameters{ 'DynamicField_' . $DynamicFieldConfig->{Name} } = \%SearchOperators;
|
||||
}
|
||||
|
||||
# allow free fields
|
||||
|
||||
return %DynamicFieldSearchParameters;
|
||||
|
||||
}
|
||||
|
||||
=head2 _CreateTimeSettings()
|
||||
|
||||
get search parameters.
|
||||
|
||||
my %GetParam = _CreateTimeSettings(
|
||||
%Params, # all ticket parameters
|
||||
);
|
||||
|
||||
returns:
|
||||
|
||||
%GetParam = {
|
||||
AllowedTimeSettings => 'WithData', # return not empty parameters for search
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub _CreateTimeSettings {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# get single params
|
||||
my %GetParam = %Param;
|
||||
|
||||
# get change time settings
|
||||
if ( !$GetParam{ChangeTimeSearchType} ) {
|
||||
|
||||
# do nothing on time stuff
|
||||
}
|
||||
elsif ( $GetParam{ChangeTimeSearchType} eq 'TimeSlot' ) {
|
||||
for (qw(Month Day)) {
|
||||
$GetParam{"TicketChangeTimeStart$_"} = sprintf( "%02d", $GetParam{"TicketChangeTimeStart$_"} );
|
||||
}
|
||||
for (qw(Month Day)) {
|
||||
$GetParam{"TicketChangeTimeStop$_"} = sprintf( "%02d", $GetParam{"TicketChangeTimeStop$_"} );
|
||||
}
|
||||
if (
|
||||
$GetParam{TicketChangeTimeStartDay}
|
||||
&& $GetParam{TicketChangeTimeStartMonth}
|
||||
&& $GetParam{TicketChangeTimeStartYear}
|
||||
)
|
||||
{
|
||||
$GetParam{TicketChangeTimeNewerDate} = $GetParam{TicketChangeTimeStartYear} . '-'
|
||||
. $GetParam{TicketChangeTimeStartMonth} . '-'
|
||||
. $GetParam{TicketChangeTimeStartDay}
|
||||
. ' 00:00:00';
|
||||
}
|
||||
if (
|
||||
$GetParam{TicketChangeTimeStopDay}
|
||||
&& $GetParam{TicketChangeTimeStopMonth}
|
||||
&& $GetParam{TicketChangeTimeStopYear}
|
||||
)
|
||||
{
|
||||
$GetParam{TicketChangeTimeOlderDate} = $GetParam{TicketChangeTimeStopYear} . '-'
|
||||
. $GetParam{TicketChangeTimeStopMonth} . '-'
|
||||
. $GetParam{TicketChangeTimeStopDay}
|
||||
. ' 23:59:59';
|
||||
}
|
||||
}
|
||||
elsif ( $GetParam{ChangeTimeSearchType} eq 'TimePoint' ) {
|
||||
if (
|
||||
$GetParam{TicketChangeTimePoint}
|
||||
&& $GetParam{TicketChangeTimePointStart}
|
||||
&& $GetParam{TicketChangeTimePointFormat}
|
||||
)
|
||||
{
|
||||
my $Time = 0;
|
||||
if ( $GetParam{TicketChangeTimePointFormat} eq 'minute' ) {
|
||||
$Time = $GetParam{TicketChangeTimePoint};
|
||||
}
|
||||
elsif ( $GetParam{TicketChangeTimePointFormat} eq 'hour' ) {
|
||||
$Time = $GetParam{TicketChangeTimePoint} * 60;
|
||||
}
|
||||
elsif ( $GetParam{TicketChangeTimePointFormat} eq 'day' ) {
|
||||
$Time = $GetParam{TicketChangeTimePoint} * 60 * 24;
|
||||
}
|
||||
elsif ( $GetParam{TicketChangeTimePointFormat} eq 'week' ) {
|
||||
$Time = $GetParam{TicketChangeTimePoint} * 60 * 24 * 7;
|
||||
}
|
||||
elsif ( $GetParam{TicketChangeTimePointFormat} eq 'month' ) {
|
||||
$Time = $GetParam{TicketChangeTimePoint} * 60 * 24 * 30;
|
||||
}
|
||||
elsif ( $GetParam{TicketChangeTimePointFormat} eq 'year' ) {
|
||||
$Time = $GetParam{TicketChangeTimePoint} * 60 * 24 * 365;
|
||||
}
|
||||
if ( $GetParam{TicketChangeTimePointStart} eq 'Before' ) {
|
||||
$GetParam{TicketChangeTimeOlderMinutes} = $Time;
|
||||
}
|
||||
else {
|
||||
$GetParam{TicketChangeTimeNewerMinutes} = $Time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# get last change time settings
|
||||
if ( !$GetParam{LastChangeTimeSearchType} ) {
|
||||
|
||||
# do nothing on time stuff
|
||||
}
|
||||
elsif ( $GetParam{LastChangeTimeSearchType} eq 'TimeSlot' ) {
|
||||
for (qw(Month Day)) {
|
||||
$GetParam{"TicketLastChangeTimeStart$_"} = sprintf( "%02d", $GetParam{"TicketLastChangeTimeStart$_"} );
|
||||
}
|
||||
for (qw(Month Day)) {
|
||||
$GetParam{"TicketLastChangeTimeStop$_"} = sprintf( "%02d", $GetParam{"TicketLastChangeTimeStop$_"} );
|
||||
}
|
||||
if (
|
||||
$GetParam{TicketLastChangeTimeStartDay}
|
||||
&& $GetParam{TicketLastChangeTimeStartMonth}
|
||||
&& $GetParam{TicketLastChangeTimeStartYear}
|
||||
)
|
||||
{
|
||||
$GetParam{TicketLastChangeTimeNewerDate} = $GetParam{TicketLastChangeTimeStartYear} . '-'
|
||||
. $GetParam{TicketLastChangeTimeStartMonth} . '-'
|
||||
. $GetParam{TicketLastChangeTimeStartDay}
|
||||
. ' 00:00:00';
|
||||
}
|
||||
if (
|
||||
$GetParam{TicketLastChangeTimeStopDay}
|
||||
&& $GetParam{TicketLastChangeTimeStopMonth}
|
||||
&& $GetParam{TicketLastChangeTimeStopYear}
|
||||
)
|
||||
{
|
||||
$GetParam{TicketLastChangeTimeOlderDate} = $GetParam{TicketLastChangeTimeStopYear} . '-'
|
||||
. $GetParam{TicketLastChangeTimeStopMonth} . '-'
|
||||
. $GetParam{TicketLastChangeTimeStopDay}
|
||||
. ' 23:59:59';
|
||||
}
|
||||
}
|
||||
elsif ( $GetParam{LastChangeTimeSearchType} eq 'TimePoint' ) {
|
||||
if (
|
||||
$GetParam{TicketLastChangeTimePoint}
|
||||
&& $GetParam{TicketLastChangeTimePointStart}
|
||||
&& $GetParam{TicketLastChangeTimePointFormat}
|
||||
)
|
||||
{
|
||||
my $Time = 0;
|
||||
if ( $GetParam{TicketLastChangeTimePointFormat} eq 'minute' ) {
|
||||
$Time = $GetParam{TicketLastChangeTimePoint};
|
||||
}
|
||||
elsif ( $GetParam{TicketLastChangeTimePointFormat} eq 'hour' ) {
|
||||
$Time = $GetParam{TicketLastChangeTimePoint} * 60;
|
||||
}
|
||||
elsif ( $GetParam{TicketLastChangeTimePointFormat} eq 'day' ) {
|
||||
$Time = $GetParam{TicketLastChangeTimePoint} * 60 * 24;
|
||||
}
|
||||
elsif ( $GetParam{TicketLastChangeTimePointFormat} eq 'week' ) {
|
||||
$Time = $GetParam{TicketLastChangeTimePoint} * 60 * 24 * 7;
|
||||
}
|
||||
elsif ( $GetParam{TicketLastChangeTimePointFormat} eq 'month' ) {
|
||||
$Time = $GetParam{TicketLastChangeTimePoint} * 60 * 24 * 30;
|
||||
}
|
||||
elsif ( $GetParam{TicketLastChangeTimePointFormat} eq 'year' ) {
|
||||
$Time = $GetParam{TicketLastChangeTimePoint} * 60 * 24 * 365;
|
||||
}
|
||||
if ( $GetParam{TicketLastChangeTimePointStart} eq 'Before' ) {
|
||||
$GetParam{TicketLastChangeTimeOlderMinutes} = $Time;
|
||||
}
|
||||
else {
|
||||
$GetParam{TicketLastChangeTimeNewerMinutes} = $Time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# get close time settings
|
||||
if ( !$GetParam{CloseTimeSearchType} ) {
|
||||
|
||||
# do nothing on time stuff
|
||||
}
|
||||
elsif ( $GetParam{CloseTimeSearchType} eq 'TimeSlot' ) {
|
||||
for (qw(Month Day)) {
|
||||
$GetParam{"TicketCloseTimeStart$_"} = sprintf( "%02d", $GetParam{"TicketCloseTimeStart$_"} );
|
||||
}
|
||||
for (qw(Month Day)) {
|
||||
$GetParam{"TicketCloseTimeStop$_"} = sprintf( "%02d", $GetParam{"TicketCloseTimeStop$_"} );
|
||||
}
|
||||
if (
|
||||
$GetParam{TicketCloseTimeStartDay}
|
||||
&& $GetParam{TicketCloseTimeStartMonth}
|
||||
&& $GetParam{TicketCloseTimeStartYear}
|
||||
)
|
||||
{
|
||||
$GetParam{TicketCloseTimeNewerDate} = $GetParam{TicketCloseTimeStartYear} . '-'
|
||||
. $GetParam{TicketCloseTimeStartMonth} . '-'
|
||||
. $GetParam{TicketCloseTimeStartDay}
|
||||
. ' 00:00:00';
|
||||
}
|
||||
if (
|
||||
$GetParam{TicketCloseTimeStopDay}
|
||||
&& $GetParam{TicketCloseTimeStopMonth}
|
||||
&& $GetParam{TicketCloseTimeStopYear}
|
||||
)
|
||||
{
|
||||
$GetParam{TicketCloseTimeOlderDate} = $GetParam{TicketCloseTimeStopYear} . '-'
|
||||
. $GetParam{TicketCloseTimeStopMonth} . '-'
|
||||
. $GetParam{TicketCloseTimeStopDay}
|
||||
. ' 23:59:59';
|
||||
}
|
||||
}
|
||||
elsif ( $GetParam{CloseTimeSearchType} eq 'TimePoint' ) {
|
||||
if (
|
||||
$GetParam{TicketCloseTimePoint}
|
||||
&& $GetParam{TicketCloseTimePointStart}
|
||||
&& $GetParam{TicketCloseTimePointFormat}
|
||||
)
|
||||
{
|
||||
my $Time = 0;
|
||||
if ( $GetParam{TicketCloseTimePointFormat} eq 'minute' ) {
|
||||
$Time = $GetParam{TicketCloseTimePoint};
|
||||
}
|
||||
elsif ( $GetParam{TicketCloseTimePointFormat} eq 'hour' ) {
|
||||
$Time = $GetParam{TicketCloseTimePoint} * 60;
|
||||
}
|
||||
elsif ( $GetParam{TicketCloseTimePointFormat} eq 'day' ) {
|
||||
$Time = $GetParam{TicketCloseTimePoint} * 60 * 24;
|
||||
}
|
||||
elsif ( $GetParam{TicketCloseTimePointFormat} eq 'week' ) {
|
||||
$Time = $GetParam{TicketCloseTimePoint} * 60 * 24 * 7;
|
||||
}
|
||||
elsif ( $GetParam{TicketCloseTimePointFormat} eq 'month' ) {
|
||||
$Time = $GetParam{TicketCloseTimePoint} * 60 * 24 * 30;
|
||||
}
|
||||
elsif ( $GetParam{TicketCloseTimePointFormat} eq 'year' ) {
|
||||
$Time = $GetParam{TicketCloseTimePoint} * 60 * 24 * 365;
|
||||
}
|
||||
if ( $GetParam{TicketCloseTimePointStart} eq 'Before' ) {
|
||||
$GetParam{TicketCloseTimeOlderMinutes} = $Time;
|
||||
}
|
||||
else {
|
||||
$GetParam{TicketCloseTimeNewerMinutes} = $Time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# prepare full text search
|
||||
if ( $GetParam{Fulltext} ) {
|
||||
$GetParam{ContentSearch} = 'OR';
|
||||
for (qw(From To Cc Subject Body)) {
|
||||
$GetParam{$_} = $GetParam{Fulltext};
|
||||
}
|
||||
}
|
||||
|
||||
# prepare archive flag
|
||||
if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::ArchiveSystem') ) {
|
||||
|
||||
$GetParam{SearchInArchive} ||= '';
|
||||
if ( $GetParam{SearchInArchive} eq 'AllTickets' ) {
|
||||
$GetParam{ArchiveFlags} = [ 'y', 'n' ];
|
||||
}
|
||||
elsif ( $GetParam{SearchInArchive} eq 'ArchivedTickets' ) {
|
||||
$GetParam{ArchiveFlags} = ['y'];
|
||||
}
|
||||
else {
|
||||
$GetParam{ArchiveFlags} = ['n'];
|
||||
}
|
||||
}
|
||||
|
||||
return %GetParam;
|
||||
}
|
||||
|
||||
=end Internal:
|
||||
|
||||
=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
|
||||
|
||||
1;
|
||||
2369
Perl OTRS/Kernel/GenericInterface/Operation/Ticket/TicketUpdate.pm
Normal file
2369
Perl OTRS/Kernel/GenericInterface/Operation/Ticket/TicketUpdate.pm
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user