# -- # 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::ProcessManagement::TransitionAction::Base; use strict; use warnings; use utf8; use Kernel::System::VariableCheck qw(:all); our @ObjectDependencies = ( 'Kernel::Config', 'Kernel::System::DynamicField', 'Kernel::System::DynamicField::Backend', 'Kernel::System::Encode', 'Kernel::System::HTMLUtils', 'Kernel::System::Log', 'Kernel::System::TemplateGenerator', 'Kernel::System::Ticket::Article', 'Kernel::System::User', ); sub _CheckParams { my ( $Self, %Param ) = @_; my $CommonMessage = $Param{CommonMessage}; for my $Needed ( qw(UserID Ticket ProcessEntityID ActivityEntityID TransitionEntityID TransitionActionEntityID Config ) ) { if ( !defined $Param{$Needed} ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', Message => "Need $Needed!", ); return; } } # Check if we have Ticket to deal with if ( !IsHashRefWithData( $Param{Ticket} ) ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', Message => $CommonMessage . "Ticket has no values!", ); return; } # Check if we have a ConfigHash if ( !IsHashRefWithData( $Param{Config} ) ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', Message => $CommonMessage . "Config has no values!", ); return; } return 1; } sub _OverrideUserID { my ( $Self, %Param ) = @_; if ( IsNumber( $Param{Config}->{UserID} ) ) { $Param{UserID} = $Param{Config}->{UserID}; delete $Param{Config}->{UserID}; } return $Param{UserID}; } sub _ReplaceTicketAttributes { my ( $Self, %Param ) = @_; # get needed objects my $DynamicFieldObject = $Kernel::OM->Get('Kernel::System::DynamicField'); my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend'); for my $Attribute ( sort keys %{ $Param{Config} } ) { # Replace ticket attributes such as # or # or # or . # is deprecated and should be removed in further versions of OTRS. my $Count = 0; REPLACEMENT: while ( $Param{Config}->{$Attribute} && $Param{Config}->{$Attribute} =~ m{}msxi && $Count++ < 1000 ) { my $TicketAttribute = $1; if ( $TicketAttribute =~ m{DynamicField_(\S+?)_Value} ) { my $DynamicFieldName = $1; my $DynamicFieldConfig = $DynamicFieldObject->DynamicFieldGet( Name => $DynamicFieldName, ); next REPLACEMENT if !$DynamicFieldConfig; # Get the display value for each dynamic field. my $DisplayValue = $DynamicFieldBackendObject->ValueLookup( DynamicFieldConfig => $DynamicFieldConfig, Key => $Param{Ticket}->{"DynamicField_$DynamicFieldName"}, ); my $DisplayValueStrg = $DynamicFieldBackendObject->ReadableValueRender( DynamicFieldConfig => $DynamicFieldConfig, Value => $DisplayValue, ); $Param{Config}->{$Attribute} =~ s{}{$DisplayValueStrg->{Value} // ''}ige; next REPLACEMENT; } elsif ( $TicketAttribute =~ m{DynamicField_(\S+)} ) { my $DynamicFieldName = $1; my $DynamicFieldConfig = $DynamicFieldObject->DynamicFieldGet( Name => $DynamicFieldName, ); next REPLACEMENT if !$DynamicFieldConfig; # Get the readable value (key) for each dynamic field. my $ValueStrg = $DynamicFieldBackendObject->ReadableValueRender( DynamicFieldConfig => $DynamicFieldConfig, Value => $Param{Ticket}->{"DynamicField_$DynamicFieldName"}, ); $Param{Config}->{$Attribute} =~ s{}{$ValueStrg->{Value} // ''}ige; next REPLACEMENT; } # if ticket value is scalar substitute all instances (as strings) # this will allow replacements for " {$TicketAttribute} ) { $Param{Config}->{$Attribute} =~ s{}{$Param{Ticket}->{$TicketAttribute} // ''}ige; } else { # if the vale is an array (e.g. a multiselect dynamic field) set the value directly # this unfortunately will not let a combination of values to be replaced $Param{Config}->{$Attribute} = $Param{Ticket}->{$TicketAttribute}; } } } return 1; } sub _ReplaceAdditionalAttributes { my ( $Self, %Param ) = @_; # get system default language my %User; if ( $Param{UserID} ) { %User = $Kernel::OM->Get('Kernel::System::User')->GetUserData( UserID => $Param{UserID}, ); } my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); my $DefaultLanguage = $ConfigObject->Get('DefaultLanguage') || 'en'; my $Language = $User{UserLanguage} || $DefaultLanguage; # get and store richtext information my $RichText = $ConfigObject->Get('Frontend::RichText'); # Determine if RichText (text/html) is used in the config as well. # If not, we have to deactivate it, otherwise HTML content and plain text are mixed up (see bug#13764). if ($RichText) { # Check for ContentType or MimeType. if ( ( IsStringWithData( $Param{Config}->{ContentType} ) && $Param{Config}->{ContentType} !~ m{text/html}i ) || ( IsStringWithData( $Param{Config}->{MimeType} ) && $Param{Config}->{MimeType} !~ m{text/html}i ) ) { $RichText = 0; } } my $ArticleObject = $Kernel::OM->Get('Kernel::System::Ticket::Article'); # get last customer article my @ArticleListCustomer = $ArticleObject->ArticleList( TicketID => $Param{Ticket}->{TicketID}, SenderType => 'customer', OnlyLast => 1, ); my %ArticleCustomer; if (@ArticleListCustomer) { %ArticleCustomer = $ArticleObject->BackendForArticle( %{ $ArticleListCustomer[0] } )->ArticleGet( %{ $ArticleListCustomer[0] }, DynamicFields => 0, ); } # get last agent article my @ArticleListAgent = $ArticleObject->ArticleList( TicketID => $Param{Ticket}->{TicketID}, SenderType => 'agent', OnlyLast => 1, ); my %ArticleAgent; if (@ArticleListAgent) { %ArticleAgent = $ArticleObject->BackendForArticle( %{ $ArticleListAgent[0] } )->ArticleGet( %{ $ArticleListAgent[0] }, DynamicFields => 0, ); } my $HTMLUtilsObject = $Kernel::OM->Get('Kernel::System::HTMLUtils'); # set the accounted time as part of the article information ARTICLEDATA: for my $ArticleData ( \%ArticleCustomer, \%ArticleAgent ) { next ARTICLEDATA if !$ArticleData->{ArticleID}; my $AccountedTime = $ArticleObject->ArticleAccountedTimeGet( ArticleID => $ArticleData->{ArticleID}, ); $ArticleData->{TimeUnit} = $AccountedTime; my $ArticleBackendObject = $ArticleObject->BackendForArticle( ArticleID => $ArticleData->{ArticleID}, TicketID => $Param{Ticket}->{TicketID}, ); # get richtext body for customer and agent article if ($RichText) { # check if there are HTML body attachments my %AttachmentIndexHTMLBody = $ArticleBackendObject->ArticleAttachmentIndex( ArticleID => $ArticleData->{ArticleID}, OnlyHTMLBody => 1, ); my @HTMLBodyAttachmentIDs = sort keys %AttachmentIndexHTMLBody; if ( $HTMLBodyAttachmentIDs[0] ) { my %AttachmentHTML = $ArticleBackendObject->ArticleAttachment( TicketID => $Param{Ticket}->{TicketID}, ArticleID => $ArticleData->{ArticleID}, FileID => $HTMLBodyAttachmentIDs[0], ); my $Charset = $AttachmentHTML{ContentType} || ''; $Charset =~ s/.+?charset=("|'|)(\w+)/$2/gi; $Charset =~ s/"|'//g; $Charset =~ s/(.+?);.*/$1/g; # convert html body to correct charset my $Body = $Kernel::OM->Get('Kernel::System::Encode')->Convert( Text => $AttachmentHTML{Content}, From => $Charset, To => 'utf-8', Check => 1, ); $Body = $HTMLUtilsObject->LinkQuote( String => $Body, ); $Body = $HTMLUtilsObject->DocumentStrip( String => $Body, ); $ArticleData->{Body} = $Body; } } } my $TemplateGeneratorObject = $Kernel::OM->Get('Kernel::System::TemplateGenerator'); # start replacing of OTRS smart tags for my $Attribute ( sort keys %{ $Param{Config} } ) { my $ConfigValue = $Param{Config}->{$Attribute}; if ( $ConfigValue && $ConfigValue =~ m{}smxi ) { if ($RichText) { $ConfigValue = $HTMLUtilsObject->ToHTML( String => $ConfigValue, ); } $ConfigValue = $TemplateGeneratorObject->_Replace( RichText => $RichText, Text => $ConfigValue, Data => \%ArticleCustomer, DataAgent => \%ArticleAgent, TicketData => $Param{Ticket}, UserID => $Param{UserID}, Language => $Language, ); if ($RichText) { $ConfigValue = $HTMLUtilsObject->ToAscii( String => $ConfigValue, ); # For body, create a completed html doc for correct displaying. if ( $Attribute eq 'Body' ) { $ConfigValue = $HTMLUtilsObject->DocumentComplete( String => $ConfigValue, Charset => 'utf-8', ); } } $Param{Config}->{$Attribute} = $ConfigValue; } } return 1; } sub _ConvertScalar2ArrayRef { my ( $Self, %Param ) = @_; my @Data = split /,/, $Param{Data}; # remove any possible heading and tailing white spaces for my $Item (@Data) { $Item =~ s{\A\s+}{}; $Item =~ s{\s+\z}{}; } return \@Data; } 1;