init III
This commit is contained in:
531
Perl OTRS/Kernel/Modules/AdminGenericInterfaceMappingXSLT.pm
Normal file
531
Perl OTRS/Kernel/Modules/AdminGenericInterfaceMappingXSLT.pm
Normal file
@@ -0,0 +1,531 @@
|
||||
# --
|
||||
# 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::Modules::AdminGenericInterfaceMappingXSLT;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::System::VariableCheck qw(:all);
|
||||
use Kernel::Language qw(Translatable);
|
||||
|
||||
our $ObjectManagerDisabled = 1;
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
my $Self = {%Param};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# Set possible values handling strings.
|
||||
$Self->{EmptyString} = '_RegEx_EmptyString_Dont_Use_It_String_Please';
|
||||
$Self->{DeletedString} = '_RegEx_DeletedString_Dont_Use_It_String_Please';
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
sub Run {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
||||
|
||||
my $WebserviceID = $ParamObject->GetParam( Param => 'WebserviceID' ) || '';
|
||||
my $Operation = $ParamObject->GetParam( Param => 'Operation' ) || '';
|
||||
my $Invoker = $ParamObject->GetParam( Param => 'Invoker' ) || '';
|
||||
my $Direction = $ParamObject->GetParam( Param => 'Direction' ) || '';
|
||||
|
||||
my $CommunicationType = IsStringWithData($Operation) ? 'Provider' : 'Requester';
|
||||
my $ActionType = IsStringWithData($Operation) ? 'Operation' : 'Invoker';
|
||||
my $Action = $Operation || $Invoker;
|
||||
|
||||
# Set mapping direction for display.
|
||||
my $MappingDirection = $Direction eq 'MappingOutbound'
|
||||
? Translatable('XSLT Mapping for Outgoing Data')
|
||||
: Translatable('XSLT Mapping for Incoming Data');
|
||||
|
||||
# Get configured Actions.
|
||||
my $ActionsConfig = $Kernel::OM->Get('Kernel::Config')->Get( 'GenericInterface::' . $ActionType . '::Module' );
|
||||
|
||||
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
||||
|
||||
# Make sure required libraries (XML::LibXML and XML::LibXSLT) are installed.
|
||||
LIBREQUIRED:
|
||||
for my $LibRequired (qw(XML::LibXML XML::LibXSLT)) {
|
||||
my $LibFound = $Kernel::OM->Get('Kernel::System::Main')->Require(
|
||||
$LibRequired,
|
||||
);
|
||||
next LIBREQUIRED if $LibFound;
|
||||
|
||||
return $LayoutObject->ErrorScreen(
|
||||
Message => $LayoutObject->{LanguageObject}->Translate( 'Could not find required library %s', $LibRequired ),
|
||||
);
|
||||
}
|
||||
|
||||
# Check for valid action backend.
|
||||
if ( !IsHashRefWithData($ActionsConfig) ) {
|
||||
return $LayoutObject->ErrorScreen(
|
||||
Message => $LayoutObject->{LanguageObject}
|
||||
->Translate( 'Could not get registered configuration for action type %s', $ActionType ),
|
||||
);
|
||||
}
|
||||
|
||||
# Check for WebserviceID.
|
||||
if ( !$WebserviceID ) {
|
||||
return $LayoutObject->ErrorScreen(
|
||||
Message => Translatable('Need WebserviceID!'),
|
||||
);
|
||||
}
|
||||
|
||||
my $WebserviceObject = $Kernel::OM->Get('Kernel::System::GenericInterface::Webservice');
|
||||
|
||||
# Get web service con configuration.
|
||||
my $WebserviceData = $WebserviceObject->WebserviceGet( ID => $WebserviceID );
|
||||
|
||||
# Check for valid web service configuration.
|
||||
if ( !IsHashRefWithData($WebserviceData) ) {
|
||||
return $LayoutObject->ErrorScreen(
|
||||
Message =>
|
||||
$LayoutObject->{LanguageObject}->Translate( 'Could not get data for WebserviceID %s', $WebserviceID ),
|
||||
);
|
||||
}
|
||||
|
||||
# Get the action type (back-end),
|
||||
my $ActionBackend = $WebserviceData->{Config}->{$CommunicationType}->{$ActionType}->{$Action}->{'Type'};
|
||||
|
||||
# Check for valid action backend.
|
||||
if ( !$ActionBackend ) {
|
||||
return $LayoutObject->ErrorScreen(
|
||||
Message =>
|
||||
$LayoutObject->{LanguageObject}->Translate( 'Could not get backend for %s %s', $ActionType, $Action ),
|
||||
);
|
||||
}
|
||||
|
||||
# Get the configuration dialog for the action.
|
||||
my $ActionFrontendModule = $ActionsConfig->{$ActionBackend}->{'ConfigDialog'};
|
||||
|
||||
my $WebserviceName = $WebserviceData->{Name};
|
||||
|
||||
# ------------------------------------------------------------ #
|
||||
# sub-action Change: load web service and show edit screen
|
||||
# ------------------------------------------------------------ #
|
||||
if ( $Self->{Subaction} eq 'Change' ) {
|
||||
|
||||
# Recreate structure for edit.
|
||||
my %Mapping;
|
||||
my $MappingConfig = $WebserviceData->{Config}->{$CommunicationType}->
|
||||
{$ActionType}->{$Action}->{$Direction}->{Config};
|
||||
|
||||
$Mapping{Template} = $MappingConfig->{Template};
|
||||
$Mapping{DataInclude} = $MappingConfig->{DataInclude};
|
||||
$Mapping{PreRegExFilter} = $MappingConfig->{PreRegExFilter};
|
||||
$Mapping{PreRegExValueCounter} = $MappingConfig->{PreRegExValueCounter};
|
||||
$Mapping{PostRegExFilter} = $MappingConfig->{PostRegExFilter};
|
||||
$Mapping{PostRegExValueCounter} = $MappingConfig->{PostRegExValueCounter};
|
||||
|
||||
return $Self->_ShowEdit(
|
||||
%Param,
|
||||
WebserviceID => $WebserviceID,
|
||||
WebserviceName => $WebserviceName,
|
||||
WebserviceData => \%Mapping,
|
||||
Operation => $Operation,
|
||||
Invoker => $Invoker,
|
||||
Direction => $Direction,
|
||||
MappingDirection => $MappingDirection,
|
||||
CommunicationType => $CommunicationType,
|
||||
ActionType => $ActionType,
|
||||
Action => $Action,
|
||||
ActionFrontendModule => $ActionFrontendModule,
|
||||
Subaction => 'Change',
|
||||
);
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------ #
|
||||
# sub-action ChangeAction: write config and return to overview
|
||||
# ------------------------------------------------------------ #
|
||||
else {
|
||||
|
||||
# Challenge token check for write action.
|
||||
$LayoutObject->ChallengeTokenCheck();
|
||||
|
||||
# Get parameter from web browser.
|
||||
my $GetParam = $Self->_GetParams();
|
||||
|
||||
# If there is an error return to edit screen.
|
||||
if ( $GetParam->{Error} ) {
|
||||
return $Self->_ShowEdit(
|
||||
%Param,
|
||||
WebserviceID => $WebserviceID,
|
||||
WebserviceName => $WebserviceName,
|
||||
WebserviceData => $GetParam,
|
||||
Operation => $Operation,
|
||||
Invoker => $Invoker,
|
||||
Direction => $Direction,
|
||||
MappingDirection => $MappingDirection,
|
||||
CommunicationType => $CommunicationType,
|
||||
ActionType => $ActionType,
|
||||
Action => $Action,
|
||||
ActionFrontendModule => $ActionFrontendModule,
|
||||
Subaction => 'Change',
|
||||
);
|
||||
}
|
||||
|
||||
my %NewMapping;
|
||||
$NewMapping{Template} = $GetParam->{Template};
|
||||
$NewMapping{DataInclude} = $GetParam->{DataInclude};
|
||||
$NewMapping{PreRegExFilter} = $GetParam->{PreRegExFilter};
|
||||
$NewMapping{PreRegExValueCounter} = $GetParam->{PreRegExValueCounter};
|
||||
$NewMapping{PostRegExFilter} = $GetParam->{PostRegExFilter};
|
||||
$NewMapping{PostRegExValueCounter} = $GetParam->{PostRegExValueCounter};
|
||||
|
||||
# Set new mapping.
|
||||
$WebserviceData->{Config}->{$CommunicationType}->{$ActionType}->{$Action}->{$Direction}->{Config}
|
||||
= \%NewMapping;
|
||||
|
||||
# Otherwise save configuration and return to overview screen.
|
||||
my $Success = $WebserviceObject->WebserviceUpdate(
|
||||
ID => $WebserviceID,
|
||||
Name => $WebserviceData->{Name},
|
||||
Config => $WebserviceData->{Config},
|
||||
ValidID => $WebserviceData->{ValidID},
|
||||
UserID => $Self->{UserID},
|
||||
);
|
||||
|
||||
# Check for successful web service update.
|
||||
if ( !$Success ) {
|
||||
return $LayoutObject->ErrorScreen(
|
||||
Message => $LayoutObject->{LanguageObject}
|
||||
->Translate( 'Could not update configuration data for WebserviceID %s', $WebserviceID ),
|
||||
);
|
||||
}
|
||||
|
||||
# If the user would like to continue editing the invoker config, just redirect to the edit screen.
|
||||
my $RedirectURL;
|
||||
if (
|
||||
defined $ParamObject->GetParam( Param => 'ContinueAfterSave' )
|
||||
&& ( $ParamObject->GetParam( Param => 'ContinueAfterSave' ) eq '1' )
|
||||
)
|
||||
{
|
||||
|
||||
$RedirectURL =
|
||||
'Action='
|
||||
. $Self->{Action}
|
||||
. ';Subaction=Change;WebserviceID='
|
||||
. $WebserviceID
|
||||
. ";$ActionType="
|
||||
. $LayoutObject->LinkEncode($Action)
|
||||
. ';Direction='
|
||||
. $Direction
|
||||
. ';';
|
||||
}
|
||||
else {
|
||||
|
||||
# Otherwise return to overview.
|
||||
$RedirectURL =
|
||||
'Action='
|
||||
. $ActionFrontendModule
|
||||
. ';Subaction=Change;'
|
||||
. ";$ActionType="
|
||||
. $LayoutObject->LinkEncode($Action)
|
||||
. ';WebserviceID='
|
||||
. $WebserviceID
|
||||
. ';';
|
||||
}
|
||||
|
||||
return $LayoutObject->Redirect(
|
||||
OP => $RedirectURL,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
sub _ShowEdit {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# Set action for go back button.
|
||||
$Param{LowerCaseActionType} = lc $Param{ActionType};
|
||||
|
||||
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
||||
|
||||
my $Output = $LayoutObject->Header();
|
||||
$Output .= $LayoutObject->NavigationBar();
|
||||
|
||||
my $MappingConfig = $Param{WebserviceData};
|
||||
my %Error;
|
||||
if ( defined $Param{WebserviceData}->{Error} ) {
|
||||
%Error = %{ $Param{WebserviceData}->{Error} };
|
||||
}
|
||||
|
||||
# Add rich text editor config.
|
||||
if ( $LayoutObject->{BrowserRichText} ) {
|
||||
$LayoutObject->SetRichTextParameters(
|
||||
Data => {
|
||||
%Param,
|
||||
RichTextHeight => '600',
|
||||
RichTextWidth => '99%',
|
||||
RichTextType => 'CodeMirror',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
# Render pre regex filters.
|
||||
$Self->_RegExFiltersOutput(
|
||||
%{$MappingConfig},
|
||||
Type => 'Pre',
|
||||
);
|
||||
|
||||
my %DataIncludeOptionMap = (
|
||||
Requester => {
|
||||
MappingOutbound => [
|
||||
{
|
||||
Key => 'RequesterRequestInput',
|
||||
Value => Translatable('Outgoing request data before processing (RequesterRequestInput)'),
|
||||
},
|
||||
{
|
||||
Key => 'RequesterRequestPrepareOutput',
|
||||
Value => Translatable('Outgoing request data before mapping (RequesterRequestPrepareOutput)'),
|
||||
},
|
||||
],
|
||||
MappingInbound => [
|
||||
{
|
||||
Key => 'RequesterRequestInput',
|
||||
Value => Translatable('Outgoing request data before processing (RequesterRequestInput)'),
|
||||
},
|
||||
{
|
||||
Key => 'RequesterRequestPrepareOutput',
|
||||
Value => Translatable('Outgoing request data before mapping (RequesterRequestPrepareOutput)'),
|
||||
},
|
||||
{
|
||||
Key => 'RequesterRequestMapOutput',
|
||||
Value => Translatable('Outgoing request data after mapping (RequesterRequestMapOutput)'),
|
||||
},
|
||||
{
|
||||
Key => 'RequesterResponseInput',
|
||||
Value => Translatable('Incoming response data before mapping (RequesterResponseInput)'),
|
||||
},
|
||||
{
|
||||
Key => 'RequesterErrorHandlingOutput',
|
||||
Value =>
|
||||
Translatable('Outgoing error handler data after error handling (RequesterErrorHandlingOutput)'),
|
||||
},
|
||||
],
|
||||
},
|
||||
Provider => {
|
||||
MappingOutbound => [
|
||||
{
|
||||
Key => 'ProviderRequestInput',
|
||||
Value => Translatable('Incoming request data before mapping (ProviderRequestInput)'),
|
||||
},
|
||||
{
|
||||
Key => 'ProviderRequestMapOutput',
|
||||
Value => Translatable('Incoming request data after mapping (ProviderRequestMapOutput)'),
|
||||
},
|
||||
{
|
||||
Key => 'ProviderResponseInput',
|
||||
Value => Translatable('Outgoing response data before mapping (ProviderResponseInput)'),
|
||||
},
|
||||
{
|
||||
Key => 'ProviderErrorHandlingOutput',
|
||||
Value =>
|
||||
Translatable('Outgoing error handler data after error handling (ProviderErrorHandlingOutput)'),
|
||||
},
|
||||
],
|
||||
MappingInbound => [
|
||||
{
|
||||
Key => 'ProviderRequestInput',
|
||||
Value => Translatable('Incoming request data before mapping (ProviderRequestInput)'),
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
$Param{DataIncludeSelect} = $LayoutObject->BuildSelection(
|
||||
Data => $DataIncludeOptionMap{ $Param{CommunicationType} }->{ $Param{Direction} },
|
||||
Name => 'DataInclude',
|
||||
SelectedID => $MappingConfig->{DataInclude},
|
||||
PossibleNone => 1,
|
||||
Translation => 1,
|
||||
Multiple => 1,
|
||||
Class => 'Modernize W50pc',
|
||||
);
|
||||
|
||||
$LayoutObject->Block(
|
||||
Name => 'ConfigBlock',
|
||||
Data => {},
|
||||
);
|
||||
$LayoutObject->Block(
|
||||
Name => 'ConfigBlockTemplate',
|
||||
Data => {
|
||||
%Param,
|
||||
Template => $MappingConfig->{Template},
|
||||
TemplateError => $Error{Template} || '',
|
||||
},
|
||||
);
|
||||
|
||||
# Render post regex filters.
|
||||
$Self->_RegExFiltersOutput(
|
||||
%{$MappingConfig},
|
||||
Type => 'Post',
|
||||
);
|
||||
|
||||
$Output .= $LayoutObject->Output(
|
||||
TemplateFile => 'AdminGenericInterfaceMappingXSLT',
|
||||
Data => {
|
||||
%Param,
|
||||
},
|
||||
);
|
||||
|
||||
$Output .= $LayoutObject->Footer();
|
||||
return $Output;
|
||||
}
|
||||
|
||||
sub _GetParams {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $GetParam;
|
||||
|
||||
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
||||
|
||||
# Get parameters from web browser.
|
||||
$GetParam->{Template} = $ParamObject->GetParam( Param => 'Template' ) || '';
|
||||
my @DataInclude = $ParamObject->GetArray( Param => 'DataInclude' );
|
||||
$GetParam->{DataInclude} = \@DataInclude;
|
||||
|
||||
# Check validity.
|
||||
my $LibXML = XML::LibXML->new();
|
||||
my $LibXSLT = XML::LibXSLT->new();
|
||||
my ( $StyleDoc, $StyleSheet );
|
||||
eval {
|
||||
$StyleDoc = XML::LibXML->load_xml(
|
||||
string => $GetParam->{Template},
|
||||
no_cdata => 1,
|
||||
);
|
||||
};
|
||||
if ( !$StyleDoc ) {
|
||||
$GetParam->{Error}->{Template} = 'ServerError';
|
||||
}
|
||||
eval {
|
||||
my $LibXSLT = XML::LibXSLT->new();
|
||||
$StyleSheet = $LibXSLT->parse_stylesheet($StyleDoc);
|
||||
};
|
||||
if ( !$StyleSheet ) {
|
||||
$GetParam->{Error}->{Template} = 'ServerError';
|
||||
}
|
||||
|
||||
# Get RegEx params.
|
||||
my %RegExFilterConfig;
|
||||
TYPE:
|
||||
for my $Type (qw(Pre Post)) {
|
||||
my $ValueCounter = $ParamObject->GetParam( Param => $Type . 'ValueCounter' ) // 0;
|
||||
next TYPE if !$ValueCounter;
|
||||
|
||||
my $EmptyValueCounter = 0;
|
||||
my @RegExConfig;
|
||||
VALUEINDEX:
|
||||
for my $ValueIndex ( 1 .. $ValueCounter ) {
|
||||
my $Key = $ParamObject->GetParam( Param => $Type . 'Key' . '_' . $ValueIndex ) // '';
|
||||
|
||||
# Check if key was deleted by the user and skip it.
|
||||
next VALUEINDEX if $Key eq $Self->{DeletedString};
|
||||
|
||||
# Check if the original value is empty.
|
||||
if ( !IsStringWithData($Key) ) {
|
||||
|
||||
# Change the empty value to a predefined string.
|
||||
$Key = $Self->{EmptyString} . $EmptyValueCounter++;
|
||||
$GetParam->{Error}->{ $Type . 'RegExFilter' }->{$Key} = 1;
|
||||
}
|
||||
|
||||
push @RegExConfig, {
|
||||
Search => $Key,
|
||||
Replace => $ParamObject->GetParam( Param => $Type . 'Value' . '_' . $ValueIndex ) // '',
|
||||
};
|
||||
}
|
||||
|
||||
$GetParam->{ $Type . 'RegExFilter' } = \@RegExConfig;
|
||||
$GetParam->{ $Type . 'RegExValueCounter' } = scalar @RegExConfig;
|
||||
}
|
||||
|
||||
return $GetParam;
|
||||
}
|
||||
|
||||
sub _RegExFiltersOutput {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
||||
|
||||
my @RegExFilter;
|
||||
if ( IsArrayRefWithData( $Param{ $Param{Type} . 'RegExFilter' } ) ) {
|
||||
@RegExFilter = @{ $Param{ $Param{Type} . 'RegExFilter' } };
|
||||
}
|
||||
|
||||
$LayoutObject->Block(
|
||||
Name => 'ConfigBlock',
|
||||
Data => {},
|
||||
);
|
||||
$LayoutObject->Block(
|
||||
Name => 'ConfigBlockRegExFilter',
|
||||
Data => {
|
||||
Type => $Param{Type},
|
||||
ValueCounter => $Param{ $Param{Type} . 'RegExValueCounter' } // 0,
|
||||
DeletedString => $Self->{DeletedString},
|
||||
Collapsed => !@RegExFilter ? 'Collapsed' : undef,
|
||||
},
|
||||
);
|
||||
|
||||
# Create the possible values template.
|
||||
$LayoutObject->Block(
|
||||
Name => 'ValueTemplate',
|
||||
Data => {
|
||||
%Param,
|
||||
},
|
||||
);
|
||||
|
||||
return 1 if !@RegExFilter;
|
||||
|
||||
# Output the possible entries and errors within (if any).
|
||||
my $ValueCounter = 1;
|
||||
for my $RegEx (@RegExFilter) {
|
||||
|
||||
# Needed for server side validation.
|
||||
my $KeyError;
|
||||
my $KeyErrorStrg;
|
||||
|
||||
# To set the correct original value.
|
||||
my $KeyClone = $RegEx->{Search};
|
||||
|
||||
# Check for errors.
|
||||
if ( $Param{Error}->{ $Param{Type} . 'RegExFilter' }->{ $RegEx->{Search} } ) {
|
||||
|
||||
# If the original value was empty it has been changed in _GetParams to a predefined
|
||||
# string and need to be set to empty again.
|
||||
$KeyClone = '';
|
||||
|
||||
# Set the error class.
|
||||
$KeyError = 'ServerError';
|
||||
$KeyErrorStrg = Translatable('This field is required.');
|
||||
}
|
||||
|
||||
# Create a value map row.
|
||||
$LayoutObject->Block(
|
||||
Name => 'ValueRow',
|
||||
Data => {
|
||||
Type => $Param{Type},
|
||||
KeyError => $KeyError,
|
||||
KeyErrorStrg => $KeyErrorStrg || Translatable('This field is required.'),
|
||||
Key => $KeyClone,
|
||||
ValueCounter => $ValueCounter,
|
||||
Value => $RegEx->{Replace},
|
||||
},
|
||||
);
|
||||
}
|
||||
continue {
|
||||
++$ValueCounter;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
1;
|
||||
Reference in New Issue
Block a user