Files
scripts/Perl OTRS/Kernel/System/ITSMChange/Template.pm
2024-10-14 00:08:40 +02:00

1291 lines
36 KiB
Perl

# --
# Copyright (C) 2001-2019 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --
package Kernel::System::ITSMChange::Template;
use strict;
use warnings;
## nofilter(TidyAll::Plugin::OTRS::Perl::Dumper)
use Data::Dumper;
use Kernel::System::EventHandler;
use vars qw(@ISA);
our @ObjectDependencies = (
'Kernel::System::DB',
'Kernel::System::Log',
'Kernel::System::Valid',
);
=head1 NAME
Kernel::System::ITSMChange::Template - template lib
=head1 PUBLIC INTERFACE
=head2 new()
Create an object.
use Kernel::System::ObjectManager;
local $Kernel::OM = Kernel::System::ObjectManager->new();
my $TemplateObject = $Kernel::OM->Get('Kernel::System::ITSMChange::Template');
=cut
sub new {
my ( $Type, %Param ) = @_;
# allocate new hash for object
my $Self = {};
bless( $Self, $Type );
# set the debug flag
$Self->{Debug} = $Param{Debug} || 0;
@ISA = (
'Kernel::System::EventHandler',
);
# init of event handler
$Self->EventHandlerInit(
Config => 'ITSMTemplate::EventModule',
);
return $Self;
}
=head2 TemplateAdd()
Add a new template.
my $TemplateID = $TemplateObject->TemplateAdd(
Name => 'The template name',
Content => '[{ ChangeAdd => { ... } }]', # a serialized change, workorder, ...
Comment => 'A comment', # (optional)
TemplateType => 'ITSMChange', # alternatively: TemplateTypeID
TemplateTypeID => 1, # alternatively: TemplateType
ValidID => 1,
UserID => 1,
);
=cut
sub TemplateAdd {
my ( $Self, %Param ) = @_;
# check that not both TemplateType and TemplateTypeID are given
if ( $Param{TemplateType} && $Param{TemplateTypeID} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need either TemplateType OR TemplateTypeID - not both!',
);
return;
}
# when the template type is given, then look up the ID
if ( $Param{TemplateType} ) {
$Param{TemplateTypeID} = $Self->TemplateTypeLookup(
TemplateType => $Param{TemplateType},
);
}
# check needed stuff
for my $Argument (qw(Content Name TemplateTypeID ValidID UserID)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
# check whether a template with this name and type already exists
return if !$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => 'SELECT id FROM change_template WHERE name = ? AND type_id = ?',
Bind => [ \$Param{Name}, \$Param{TemplateTypeID} ],
Limit => 1,
);
# fetch the result
my $TemplateID;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$TemplateID = $Row[0];
}
# a template with this name exists already
if ($TemplateID) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message =>
"A template with the name '$Param{Name}' and the type '$Param{TemplateTypeID}' already exists!",
);
return;
}
# trigger TemplateAddPre-Event
$Self->EventHandler(
Event => 'TemplateAddPre',
Data => {
%Param,
},
UserID => $Param{UserID},
);
# add new template to database
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
SQL => 'INSERT INTO change_template '
. '(name, comments, content, type_id, valid_id, '
. 'create_time, create_by, change_time, change_by) '
. 'VALUES (?, ?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)',
Bind => [
\$Param{Name}, \$Param{Comment}, \$Param{Content}, \$Param{TemplateTypeID},
\$Param{ValidID}, \$Param{UserID}, \$Param{UserID},
],
);
# prepare SQL statement
return if !$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => 'SELECT id FROM change_template WHERE name = ? AND type_id = ?',
Bind => [ \$Param{Name}, \$Param{TemplateTypeID} ],
Limit => 1,
);
# fetch the result
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$TemplateID = $Row[0];
}
# check if template could be added
if ( !$TemplateID ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'TemplateAdd() failed!',
);
return;
}
# trigger TemplateAddPost-Event
$Self->EventHandler(
Event => 'TemplateAddPost',
Data => {
%Param,
TemplateID => $TemplateID,
},
UserID => $Param{UserID},
);
# TODO: all attachments in the template should be copied
# in the virtual fs. Otherwise it could happen that an
# attachment is deleted after template creation and therefore
# no longer available.
return $TemplateID;
}
=head2 TemplateUpdate()
Update a template.
my $Success = $TemplateObject->TemplateUpdate(
TemplateID => 1234,
Name => 'The template name', # (optional)
Comment => 'A comment', # (optional)
Content => '[{ ChangeAdd => { ... } }]', # (optional) a serialized change, workorder, ...
ValidID => 1, # (optional)
TypeID => 1, # (optional)
UserID => 1,
);
=cut
sub TemplateUpdate {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(TemplateID UserID)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
# trigger TemplateUpdatePre-Event
$Self->EventHandler(
Event => 'TemplateUpdatePre',
Data => {
%Param,
},
UserID => $Param{UserID},
);
# get template data
my $TemplateData = $Self->TemplateGet(
TemplateID => $Param{TemplateID},
UserID => $Param{UserID},
);
# map update attributes to column names
my %Attribute = (
Name => 'name',
Comment => 'comments',
Content => 'content',
ValidID => 'valid_id',
TypeID => 'type_id',
);
# build SQL to update template
my $SQL = 'UPDATE change_template SET ';
my @Bind;
ATTRIBUTE:
for my $Attribute ( sort keys %Attribute ) {
# preserve the old value, when the column isn't in function parameters
next ATTRIBUTE if !exists $Param{$Attribute};
# param checking has already been done, so this is safe
$SQL .= "$Attribute{$Attribute} = ?, ";
push @Bind, \$Param{$Attribute};
}
# add change time and change user
$SQL .= 'change_time = current_timestamp, change_by = ? ';
push @Bind, \$Param{UserID};
# set matching of SQL statement
$SQL .= 'WHERE id = ?';
push @Bind, \$Param{TemplateID};
# update template
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
SQL => $SQL,
Bind => \@Bind,
);
# trigger TemplateUpdatePost-Event
$Self->EventHandler(
Event => 'TemplateUpdatePost',
Data => {
OldTemplateData => $TemplateData,
%Param,
},
UserID => $Param{UserID},
);
# TODO: all attachments in the template should be copied
# in the virtual fs. Otherwise it could happen that an
# attachment is deleted after template creation and therefore
# no longer available.
return 1;
}
=head2 TemplateGet()
Returns a hash reference of the template data for a given TemplateID.
my $TemplateData = $TemplateObject->TemplateGet(
TemplateID => 123,
UserID => 1,
);
The returned hash reference contains following elements:
$TemplateData{TemplateID}
$TemplateData{Name}
$TemplateData{Comment}
$TemplateData{Content}
$TemplateData{TypeID}
$TemplateData{Type}
$TemplateData{ValidID}
$TemplateData{CreateTime}
$TemplateData{CreateBy}
$TemplateData{ChangeTime}
$TemplateData{ChangeBy}
=cut
sub TemplateGet {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(TemplateID UserID)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
# prepare SQL statement
return if !$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => 'SELECT ct.id, ct.name, comments, content, type_id, ctt.name, '
. 'ct.valid_id, ct.create_time, ct.create_by, ct.change_time, ct.change_by '
. 'FROM change_template ct, change_template_type ctt '
. 'WHERE ct.type_id = ctt.id AND ct.id = ?',
Bind => [ \$Param{TemplateID} ],
Limit => 1,
);
# fetch the result
my %TemplateData;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$TemplateData{TemplateID} = $Row[0];
$TemplateData{Name} = $Row[1];
$TemplateData{Comment} = $Row[2];
$TemplateData{Content} = $Row[3];
$TemplateData{TypeID} = $Row[4];
$TemplateData{Type} = $Row[5];
$TemplateData{ValidID} = $Row[6];
$TemplateData{CreateTime} = $Row[7];
$TemplateData{CreateBy} = $Row[8];
$TemplateData{ChangeTime} = $Row[9];
$TemplateData{ChangeBy} = $Row[10];
}
# check error
if ( !%TemplateData ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "TemplateID $Param{TemplateID} does not exist!",
);
return;
}
# cleanup time stamps (some databases are using e. g. 2008-02-25 22:03:00.000000)
TIMEFIELD:
for my $Timefield ( 'CreateTime', 'ChangeTime', ) {
next TIMEFIELD if !$TemplateData{$Timefield};
$TemplateData{$Timefield}
=~ s{ \A ( \d\d\d\d - \d\d - \d\d \s \d\d:\d\d:\d\d ) \. .+? \z }{$1}xms;
}
return \%TemplateData;
}
=head2 TemplateList()
return a hashref of all templates
my $Templates = $TemplateObject->TemplateList(
Valid => 0, # (optional) default 1 (0|1)
CommentLength => 15, # (optional) default 0
TemplateType => 'ITSMChange' # (optional) or TemplateType
TemplateTypeID => 1, # (optional) or TemplateTypeID
UserID => 1,
);
returns
$Templates = {
1 => 'my template',
3 => 'your template name',
};
If parameter C<CommentLength> is passed, an excerpt (of the passed length)
of the comment is appended to the template name.
If the parameter C<TemplateType> or C<TemplateTypeID> is passed, then the
list of templates is restricted to the given type.
=cut
sub TemplateList {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(UserID)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
# check that not both TemplateType and TemplateTypeID are given
if ( $Param{TemplateType} && $Param{TemplateTypeID} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need either TemplateType OR TemplateTypeID - not both!',
);
return;
}
# when the template type is given, then look up the ID
if ( $Param{TemplateType} ) {
$Param{TemplateTypeID} = $Self->TemplateTypeLookup(
TemplateType => $Param{TemplateType},
);
}
# check valid param
if ( !defined $Param{Valid} ) {
$Param{Valid} = 1;
}
# define SQL statement
my $SQL = 'SELECT id, name, comments FROM change_template ';
my @SQLWhere; # assemble the conditions used in the WHERE clause
my @SQLBind;
# restrict by template type
if ( $Param{TemplateTypeID} ) {
push @SQLWhere, "type_id = ?";
push @SQLBind, \$Param{TemplateTypeID};
}
# get only valid template ids
if ( $Param{Valid} ) {
my @ValidIDs = $Kernel::OM->Get('Kernel::System::Valid')->ValidIDsGet();
my $ValidIDString = join ', ', @ValidIDs;
push @SQLWhere, "valid_id IN ( $ValidIDString )";
}
# append the WHERE-clause
if (@SQLWhere) {
$SQL .= 'WHERE ';
$SQL .= join ' AND ', map {"( $_ )"} @SQLWhere;
$SQL .= ' ';
}
# prepare SQL statement
return if !$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => $SQL,
Bind => \@SQLBind,
);
# fetch the result
my %Templates;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$Templates{ $Row[0] } = [ $Row[1], $Row[2] ];
}
for my $Key ( sort keys %Templates ) {
my ( $Name, $Comment ) = @{ $Templates{$Key} };
my $CommentAppend = '';
if ( $Param{CommentLength} && $Comment ) {
my $Length = $Param{CommentLength} > length $Comment
? length $Comment
: $Param{CommentLength};
my $Ellipsis = $Param{CommentLength} > length $Comment
? ''
: '...';
$Comment = substr $Comment, 0, $Length;
$CommentAppend = ' (' . $Comment . $Ellipsis . ')';
}
$Templates{$Key} = $Name . $CommentAppend;
}
return \%Templates;
}
=head2 TemplateSearch()
Returns either a list, as an arrayref, or a count of found template ids.
The count of results is returned when the parameter C<Result => 'COUNT'> is passed.
The search criteria are logically AND connected.
When a list is passed as C<criterium>, the individual members are OR connected.
When an undef or a reference to an empty array is passed, then the search C<criterium>
is ignored.
my $TemplateIDsRef = $TemplateObject->TemplateSearch(
Name => 'Sample template', # (optional)
Comment => 'just an example', # (optional)
TemplateTypeIDs => [ 11, 12 ], # (optional)
TemplateTypes => [ 'ITSMChange', 'CAB' ], # (optional)
CreateBy => [ 5, 2, 3 ], # (optional)
ChangeBy => [ 3, 2, 1 ], # (optional)
# templates with created time after ...
CreateTimeNewerDate => '2006-01-09 00:00:01', # (optional)
# templates with created time before then ....
CreateTimeOlderDate => '2006-01-19 23:59:59', # (optional)
# templates with changed time after ...
ChangeTimeNewerDate => '2006-01-09 00:00:01', # (optional)
# templates with changed time before then ....
ChangeTimeOlderDate => '2006-01-19 23:59:59', # (optional)
OrderBy => [ 'TemplateID', 'Name' ], # (optional)
# ignored when the result type is 'COUNT'
# default: [ 'TemplateID' ],
# (TemplateID, Name, Comment, TemplateTypeID,
# CreateTime, CreateBy, ChangeTime, ChangeBy)
# Additional information for OrderBy:
# The OrderByDirection can be specified for each OrderBy attribute.
# The pairing is made by the array indices.
OrderByDirection => [ 'Down', 'Up' ], # (optional)
# ignored when the result type is 'COUNT'
# default: [ 'Down' ]
# (Down | Up)
UsingWildcards => 1, # (optional)
# (0 | 1) default 1
Result => 'ARRAY' || 'COUNT', # (optional)
# default: ARRAY, returns an array of template ids
# COUNT returns a scalar with the number of found templates
Limit => 100, # (optional)
# ignored when the result type is 'COUNT'
UserID => 1,
);
=cut
sub TemplateSearch {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{UserID} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need UserID!',
);
return;
}
# verify that all passed array parameters contain an arrayref
ARGUMENT:
for my $Argument (
qw(
OrderBy
OrderByDirection
TemplateTypes
TemplateTypeIDs
CreateBy
ChangeBy
)
)
{
if ( !defined $Param{$Argument} ) {
$Param{$Argument} ||= [];
next ARGUMENT;
}
if ( ref $Param{$Argument} ne 'ARRAY' ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "$Argument must be an array reference!",
);
return;
}
}
my @SQLWhere; # assemble the conditions used in the WHERE clause
# define order table
my %OrderByTable = (
TemplateID => 't.id',
Name => 't.name',
Comment => 't.comments',
TemplateTypeID => 't.type_id',
ValidID => 't.valid_id',
CreateTime => 't.create_time',
CreateBy => 't.create_by',
ChangeTime => 't.change_time',
ChangeBy => 't.change_by',
);
# check if OrderBy contains only unique valid values
my %OrderBySeen;
for my $OrderBy ( @{ $Param{OrderBy} } ) {
if ( !$OrderBy || !$OrderByTable{$OrderBy} || $OrderBySeen{$OrderBy} ) {
# found an error
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "OrderBy contains invalid value '$OrderBy' "
. 'or the value is used more than once!',
);
return;
}
# remember the value to check if it appears more than once
$OrderBySeen{$OrderBy} = 1;
}
# check if OrderByDirection array contains only 'Up' or 'Down'
DIRECTION:
for my $Direction ( @{ $Param{OrderByDirection} } ) {
# only 'Up' or 'Down' allowed
next DIRECTION if $Direction eq 'Up';
next DIRECTION if $Direction eq 'Down';
# found an error
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "OrderByDirection can only contain 'Up' or 'Down'!",
);
return;
}
# set default values
if ( !defined $Param{UsingWildcards} ) {
$Param{UsingWildcards} = 1;
}
# set the default behaviour for the return type
my $Result = $Param{Result} || 'ARRAY';
# check whether the given TemplateTypeIDs are all valid
return if !$Self->_CheckTemplateTypeIDs(
TemplateTypeIDs => $Param{TemplateTypeIDs},
UserID => $Param{UserID},
);
# look up and thus check the TemplateTypes
for my $Type ( @{ $Param{TemplateTypes} } ) {
# get the ID for the name
my $TypeID = $Self->TemplateTypeLookup(
TemplateType => $Type,
);
# check whether the ID was found, whether the name exists
if ( !$TypeID ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "The template type '$Type' is not known!",
);
return;
}
push @{ $Param{TemplateTypeIDs} }, $TypeID;
}
# add string params to the WHERE clause
my %StringParams = (
Name => 't.name',
Comment => 't.comments',
);
# add string params to sql-where-array
STRINGPARAM:
for my $StringParam ( sort keys %StringParams ) {
# check string params for useful values, the string '0' is allowed
next STRINGPARAM if !exists $Param{$StringParam};
next STRINGPARAM if !defined $Param{$StringParam};
next STRINGPARAM if $Param{$StringParam} eq '';
# quote
$Param{$StringParam} = $Kernel::OM->Get('Kernel::System::DB')->Quote( $Param{$StringParam} );
# wildcards are used
if ( $Param{UsingWildcards} ) {
# get like escape string needed for some databases (e.g. oracle)
my $LikeEscapeString = $Kernel::OM->Get('Kernel::System::DB')->GetDatabaseFunction('LikeEscapeString');
# Quote
$Param{$StringParam} = $Kernel::OM->Get('Kernel::System::DB')->Quote( $Param{$StringParam}, 'Like' );
# replace * with %
$Param{$StringParam} =~ s{ \*+ }{%}xmsg;
# do not use string params which contain only %
next STRINGPARAM if $Param{$StringParam} =~ m{ \A %* \z }xms;
push @SQLWhere,
"LOWER($StringParams{$StringParam}) LIKE LOWER('$Param{$StringParam}') $LikeEscapeString";
}
# no wildcards are used
else {
push @SQLWhere,
"LOWER($StringParams{$StringParam}) = LOWER('$Param{$StringParam}')";
}
}
# set array params
my %ArrayParams = (
TemplateTypeIDs => 't.type_id',
CreateBy => 't.create_by',
ChangeBy => 't.change_by',
);
# add array params to sql-where-array
ARRAYPARAM:
for my $ArrayParam ( sort keys %ArrayParams ) {
# ignore empty lists
next ARRAYPARAM if !@{ $Param{$ArrayParam} };
# quote as integer
for my $OneParam ( @{ $Param{$ArrayParam} } ) {
$OneParam = $Kernel::OM->Get('Kernel::System::DB')->Quote( $OneParam, 'Integer' );
}
# create string
my $InString = join ', ', @{ $Param{$ArrayParam} };
push @SQLWhere, "$ArrayParams{$ArrayParam} IN ($InString)";
}
# check the time params and add them to the WHERE clause of the SELECT-Statement
my %TimeParams = (
CreateTimeNewerDate => 't.create_time >=',
CreateTimeOlderDate => 't.create_time <=',
ChangeTimeNewerDate => 't.change_time >=',
ChangeTimeOlderDate => 't.change_time <=',
);
TIMEPARAM:
for my $TimeParam ( sort keys %TimeParams ) {
next TIMEPARAM if !$Param{$TimeParam};
if ( $Param{$TimeParam} !~ m{ \A \d\d\d\d-\d\d-\d\d \s \d\d:\d\d:\d\d \z }xms ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "The parameter $TimeParam has an invalid date format!",
);
return;
}
# quote
$Param{$TimeParam} = $Kernel::OM->Get('Kernel::System::DB')->Quote( $Param{$TimeParam} );
push @SQLWhere, "$TimeParams{$TimeParam} '$Param{$TimeParam}'";
}
# delete the OrderBy parameter when the result type is 'COUNT'
if ( $Result eq 'COUNT' ) {
$Param{OrderBy} = [];
}
# assemble the ORDER BY clause
my @SQLOrderBy;
my $Count = 0;
for my $OrderBy ( @{ $Param{OrderBy} } ) {
# set the default order direction
my $Direction = 'DESC';
# add the given order direction
if ( $Param{OrderByDirection}->[$Count] ) {
if ( $Param{OrderByDirection}->[$Count] eq 'Up' ) {
$Direction = 'ASC';
}
elsif ( $Param{OrderByDirection}->[$Count] eq 'Down' ) {
$Direction = 'DESC';
}
}
# add SQL
push @SQLOrderBy, "$OrderByTable{$OrderBy} $Direction";
}
continue {
$Count++;
}
# if there is a possibility that the ordering is not determined
# we add an descending ordering by id
if ( !grep { $_ eq 'TemplateID' } ( @{ $Param{OrderBy} } ) ) {
push @SQLOrderBy, "$OrderByTable{TemplateID} DESC";
}
# assemble the SQL query
my $SQL = 'SELECT t.id FROM change_template t ';
# modify SQL when the result type is 'COUNT'.
# There is no 'GROUP BY' SQL-clause, therefore COUNT(c.id) always give the wanted count
if ( $Result eq 'COUNT' ) {
$SQL = 'SELECT COUNT(t.id) FROM change_template t ';
@SQLOrderBy = ();
}
# add the WHERE clause
if (@SQLWhere) {
$SQL .= 'WHERE ';
$SQL .= join ' AND ', map {"( $_ )"} @SQLWhere;
$SQL .= ' ';
}
# add the ORDER BY clause
if (@SQLOrderBy) {
$SQL .= 'ORDER BY ';
$SQL .= join ', ', @SQLOrderBy;
$SQL .= ' ';
}
# ignore the parameter 'Limit' when result type is 'COUNT'
if ( $Result eq 'COUNT' ) {
$Param{Limit} = 1;
}
# ask database
return if !$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => $SQL,
Limit => $Param{Limit},
);
# fetch the result
my @IDs;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
push @IDs, $Row[0];
}
# return the count as scalar
return $IDs[0] if $Result eq 'COUNT';
return \@IDs;
}
=head2 TemplateDelete()
Delete a template.
my $Success = $TemplateObject->TemplateDelete(
TemplateID => 123,
UserID => 1,
);
=cut
sub TemplateDelete {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(TemplateID UserID)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
# trigger TemplateDeletePre-Event
$Self->EventHandler(
Event => 'TemplateDeletePre',
Data => {
%Param,
},
UserID => $Param{UserID},
);
# get template data
my $TemplateData = $Self->TemplateGet(
TemplateID => $Param{TemplateID},
UserID => $Param{UserID},
);
# delete template from database
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
SQL => 'DELETE FROM change_template WHERE id = ?',
Bind => [ \$Param{TemplateID} ],
);
# trigger TemplateDeletePost-Event
$Self->EventHandler(
Event => 'TemplateDeletePost',
Data => {
OldTemplateData => $TemplateData,
%Param,
},
UserID => $Param{UserID},
);
return 1;
}
=head2 TemplateTypeLookup()
Return the template type id when the template type name is passed.
Return the template type name when the template type id is passed.
When no template type id or template type name is found, then the
undefined value is returned.
my $TypeID = $TemplateObject->TemplateTypeLookup(
TemplateType => 'my template type name',
);
my $TxpeName = $TemplateObject->TemplateTypeLookup(
TemplateTypeID => 42,
);
=cut
sub TemplateTypeLookup {
my ( $Self, %Param ) = @_;
# the template type id or the template type name must be passed
if ( !$Param{TemplateTypeID} && !$Param{TemplateType} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need the TemplateTypeID or the TemplateType!',
);
return;
}
# only one of template id and template name can be passed
if ( $Param{TemplateTypeID} && $Param{TemplateType} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need either the TemplateType or the TemplateTemplateID, not both!',
);
return;
}
# get type id
if ( $Param{TemplateType} ) {
return if !$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => 'SELECT id FROM change_template_type WHERE name = ?',
Bind => [ \$Param{TemplateType} ],
Limit => 1,
);
my $TypeID;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$TypeID = $Row[0];
}
return $TypeID;
}
# get type name
elsif ( $Param{TemplateTypeID} ) {
return if !$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => 'SELECT name FROM change_template_type WHERE id = ?',
Bind => [ \$Param{TemplateTypeID} ],
Limit => 1,
);
my $TypeName;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$TypeName = $Row[0];
}
return $TypeName;
}
return;
}
=head2 TemplateSerialize()
This method is in fact a dispatcher for different template types.
Currently ITSMChangeManagement supports these template types:
ITSMChange
ITSMWorkOrder
CAB
ITSMCondition
The method returns a data structure, serialized with Data::Dumper.
my $ChangeTemplate = $TemplateObject->TemplateSerialize(
TemplateType => 'ITSMChange',
StateReset => 1, # (optional) reset to default state
UserID => 1,
# other options needed depending on the template type
ChangeID => 123,
);
=cut
sub TemplateSerialize {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{UserID} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need UserID!',
);
return;
}
# the template type id or the template type name must be passed
if ( !$Param{TemplateTypeID} && !$Param{TemplateType} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need the TemplateTypeID or the TemplateType!',
);
return;
}
# only one of template type name and template type id can be passed
if ( $Param{TemplateType} && $Param{TemplateTypeID} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need either the TemplateTypeID or the TemplateType, not both!',
);
return;
}
my $TemplateType = $Param{TemplateType};
if ( $Param{TemplateTypeID} ) {
$TemplateType = $Self->TemplateTypeLookup(
TemplateTypeID => $Param{TemplateTypeID},
);
}
# what types of templates are supported and what subroutines do the serialization
my $BackendObject = $Kernel::OM->Get( 'Kernel::System::ITSMChange::Template::' . $TemplateType );
return if !$BackendObject;
my $SerializedData = $BackendObject->Serialize(
%Param,
);
return $SerializedData;
}
=head2 TemplateDeSerialize()
This method deserializes the template content. It returns the
ID of the "main" element that was created based on the template.
my $ElementID = $TemplateObject->TemplateDeSerialize(
TemplateID => 123,
UserID => 1,
);
=cut
sub TemplateDeSerialize {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(UserID TemplateID)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
# get template
my $Template = $Self->TemplateGet(
%Param,
);
return if !$Template;
# get the Perl datastructure
my $TemplateContent = $Template->{Content};
my $VAR1;
return if !eval "\$VAR1 = $TemplateContent; 1;"; ## no critic
return if !$VAR1;
return if ref $VAR1 ne 'HASH';
# create entities defined by the template
my %Info = $Self->_CreateTemplateElements(
%Param,
Template => $VAR1,
);
return $Info{ID};
}
=head1 PRIVATE INTERFACE
=head2 _CreateTemplateElements()
This method dispatches the elements creation. It calls the subroutine
that belongs to the given type (e.g. ChangeAdd). After that it
invokes itself for all the children of the main element.
This method returns the ID of the main element.
my $ElementID = $TemplateObject->_CreateTemplateElements(
Template => {
ChangeAdd => { ... },
Children => [
{
WorkOrderAdd => { ... },
Children => [ ... ],
},
{
WorkOrderAdd => { ... },
Children => [ ... ],
},
],
},
# any other parameters can follow
)
=cut
sub _CreateTemplateElements {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(Template)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
# get children
my $Children = delete $Param{Template}->{Children};
$Children ||= [];
# dispatch table
my %Method2Object = (
ChangeAdd => 'ITSMChange',
WorkOrderAdd => 'ITSMWorkOrder',
CABAdd => 'CAB',
ConditionAdd => 'ITSMCondition',
AttachmentAdd => 'Parent',
ExpressionAdd => 'Parent',
ActionAdd => 'Parent',
LinkAdd => 'Parent',
);
# get action
my ( $Method, $Data ) = each %{ $Param{Template} };
my $Type = $Method2Object{$Method};
my $BackendObject;
if ( $Type eq 'Parent' ) {
$BackendObject = $Kernel::OM->Get( 'Kernel::System::ITSMChange::Template::' . $Param{Parent} );
}
else {
$BackendObject = $Kernel::OM->Get( 'Kernel::System::ITSMChange::Template::' . $Type );
}
return if !$BackendObject;
# create parent element
my %ParentReturn = $BackendObject->DeSerialize(
%Param,
Data => $Data,
Type => $Type,
Method => $Method,
);
return if !%ParentReturn;
my %SiblingsInfo;
# create child elements
# prevent new number calculation for workorders,
# as the original number will be used
for my $Child ( @{$Children} ) {
my %ChildInfo = $Self->_CreateTemplateElements(
%Param,
%SiblingsInfo,
%ParentReturn,
Template => $Child,
Parent => $Type,
Method => $Method,
NoNumberCalc => 1,
);
# save info for next sibling
for my $Key ( sort keys %ChildInfo ) {
$SiblingsInfo{$Key} = $ChildInfo{$Key};
}
}
return %ParentReturn;
}
=head2 _CheckTemplateTypeIDs()
check whether the given template type ids are all valid
my $Ok = $TemplateObject->_CheckTemplateTypeIDs(
TemplateTypeIDs => [ 2, 500 ],
UserID => 1,
);
=cut
sub _CheckTemplateTypeIDs {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(TemplateTypeIDs UserID)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
if ( ref $Param{TemplateTypeIDs} ne 'ARRAY' ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'The param TemplateTypeIDs must be an ARRAY reference!',
);
return;
}
# check if TemplateTypeIDs can be looked up
for my $TypeID ( @{ $Param{TemplateTypeIDs} } ) {
my $Type = $Self->TemplateTypeLookup(
TemplateTypeID => $TypeID,
);
if ( !$Type ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "The type id $TypeID is not valid!",
);
return;
}
}
return 1;
}
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