This commit is contained in:
2024-10-14 00:08:40 +02:00
parent dbfba56f66
commit 1462d52e13
4572 changed files with 2658864 additions and 0 deletions

View 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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View 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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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

View File

@@ -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

View File

@@ -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;

File diff suppressed because it is too large Load Diff