# --
# 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::AgentITSMChangeConditionEdit;
use strict;
use warnings;
use Kernel::Language qw(Translatable);
our $ObjectManagerDisabled = 1;
sub new {
my ( $Type, %Param ) = @_;
# allocate new hash for object
my $Self = {%Param};
bless( $Self, $Type );
return $Self;
}
sub Run {
my ( $Self, %Param ) = @_;
# get param object
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
# store needed parameters in %GetParam
my %GetParam;
for my $ParamName (
qw(
ChangeID ConditionID Name Comment ExpressionConjunction ValidID DeleteExpressionID DeleteActionID
Save AddAction AddExpression NewExpression NewAction ElementChanged UpdateDivName)
)
{
$GetParam{$ParamName} = $ParamObject->GetParam( Param => $ParamName );
}
# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# check needed stuff
for my $Needed (qw(ChangeID ConditionID)) {
if ( !$GetParam{$Needed} ) {
$LayoutObject->ErrorScreen(
Message => $LayoutObject->{LanguageObject}->Translate( 'No %s is given!', $Needed ),
Comment => Translatable('Please contact the administrator.'),
);
return;
}
}
# get change object
my $ChangeObject = $Kernel::OM->Get('Kernel::System::ITSMChange');
# get config of frontend module
$Self->{Config} = $Kernel::OM->Get('Kernel::Config')->Get("ITSMChange::Frontend::$Self->{Action}");
# check permissions
my $Access = $ChangeObject->Permission(
Type => $Self->{Config}->{Permission},
Action => $Self->{Action},
ChangeID => $GetParam{ChangeID},
UserID => $Self->{UserID},
);
# error screen
if ( !$Access ) {
return $LayoutObject->NoPermission(
Message => $LayoutObject->{LanguageObject}->Translate(
'You need %s permissions!', $Self->{Config}->{Permission}
),
WithHeader => 'yes',
);
}
# get change data
my $ChangeData = $ChangeObject->ChangeGet(
ChangeID => $GetParam{ChangeID},
UserID => $Self->{UserID},
);
# check if change exists
if ( !$ChangeData ) {
return $LayoutObject->ErrorScreen(
Message =>
$LayoutObject->{LanguageObject}->Translate( 'Change "%s" not found in database!', $GetParam{ChangeID} ),
Comment => Translatable('Please contact the administrator.'),
);
}
# get valid object
my $ValidObject = $Kernel::OM->Get('Kernel::System::Valid');
# get valid list
my %ValidList = $ValidObject->ValidList();
my $ExpressionIDsRef = [];
my $ActionIDsRef = [];
# get condition object
my $ConditionObject = $Kernel::OM->Get('Kernel::System::ITSMChange::ITSMCondition');
# only get expression list and action list if condition exists already
if ( $GetParam{ConditionID} ne 'NEW' ) {
# get all expression ids for the given condition id
$ExpressionIDsRef = $ConditionObject->ExpressionList(
ConditionID => $GetParam{ConditionID},
UserID => $Self->{UserID},
);
# get all action ids for the given condition id
$ActionIDsRef = $ConditionObject->ActionList(
ConditionID => $GetParam{ConditionID},
UserID => $Self->{UserID},
);
}
# Remember the reason why saving was not attempted.
# These entries are the names of the dtl validation error blocks.
my @ValidationErrors;
# ---------------------------------------------------------------- #
# condition save (also add/delete expression and add/delete action)
# ---------------------------------------------------------------- #
if ( $Self->{Subaction} eq 'Save' ) {
# update only if ConditionName is given
if ( !$GetParam{Name} ) {
$Param{InvalidName} = 'ServerError';
push @ValidationErrors, 'InvalidName';
}
# check if condition name is already used
else {
# check if condition name exists already for this change
my $ConditionID = $ConditionObject->ConditionLookup(
Name => $GetParam{Name},
ChangeID => $GetParam{ChangeID},
);
# it is only an error if another condition of this change uses this name
# changing the name of a condition is still possible
if ( $ConditionID && ( $GetParam{ConditionID} ne $ConditionID ) ) {
$Param{DuplicateName} = 'ServerError';
push @ValidationErrors, 'DuplicateName';
}
}
# if all passed data is valid
if ( !@ValidationErrors ) {
# add a new condition
if ( $GetParam{ConditionID} eq 'NEW' ) {
# create a new condition
$GetParam{ConditionID} = $ConditionObject->ConditionAdd(
ChangeID => $GetParam{ChangeID},
Name => $GetParam{Name},
ExpressionConjunction => $GetParam{ExpressionConjunction},
Comment => $GetParam{Comment},
ValidID => $GetParam{ValidID},
UserID => $Self->{UserID},
);
# check error
if ( !$GetParam{ConditionID} ) {
$LayoutObject->ErrorScreen(
Message => Translatable('Could not create new condition!'),
Comment => Translatable('Please contact the administrator.'),
);
return;
}
}
# update an existing condition
else {
# update the condition
my $Success = $ConditionObject->ConditionUpdate(
ConditionID => $GetParam{ConditionID},
Name => $GetParam{Name},
ExpressionConjunction => $GetParam{ExpressionConjunction},
Comment => $GetParam{Comment},
ValidID => $GetParam{ValidID},
UserID => $Self->{UserID},
);
# check error
if ( !$Success ) {
$LayoutObject->ErrorScreen(
Message => $LayoutObject->{LanguageObject}->Translate(
'Could not update ConditionID %s!', $GetParam{ConditionID}
),
Comment => Translatable('Please contact the administrator.'),
);
return;
}
}
# save all existing expression fields
for my $ExpressionID ( @{$ExpressionIDsRef} ) {
# get expression fields
my %ExpressionData;
for my $Field (qw(ObjectID Selector AttributeID OperatorID CompareValue)) {
$ExpressionData{$Field} = $ParamObject->GetParam(
Param => 'ExpressionID-' . $ExpressionID . '-' . $Field,
);
}
# check if existing expression is complete
# (all required fields must be filled, CompareValue can be empty)
my $FieldsOk = 1;
FIELD:
for my $Field (qw(ObjectID Selector AttributeID OperatorID)) {
# new expression is not complete
if ( !$ExpressionData{$Field} ) {
$FieldsOk = 0;
last FIELD;
}
}
# update existing expression only if all fields are complete
if ($FieldsOk) {
# update the expression
my $Success = $ConditionObject->ExpressionUpdate(
ExpressionID => $ExpressionID,
ObjectID => $ExpressionData{ObjectID},
AttributeID => $ExpressionData{AttributeID},
OperatorID => $ExpressionData{OperatorID},
Selector => $ExpressionData{Selector},
CompareValue => defined $ExpressionData{CompareValue}
? $ExpressionData{CompareValue}
: '',
UserID => $Self->{UserID},
);
# check error
if ( !$Success ) {
return $LayoutObject->ErrorScreen(
Message => $LayoutObject->{LanguageObject}->Translate(
'Could not update ExpressionID %s!', $ExpressionID
),
Comment => Translatable('Please contact the administrator.'),
);
}
}
}
# get new expression fields
my %ExpressionData;
for my $Field (qw(ObjectID Selector AttributeID OperatorID CompareValue)) {
$ExpressionData{$Field} = $ParamObject->GetParam(
Param => 'ExpressionID-NEW-' . $Field,
);
}
# check if new expression is complete
# (all required fields must be filled, CompareValue can be empty)
my $FieldsOk = 1;
FIELD:
for my $Field (qw(ObjectID Selector AttributeID OperatorID)) {
# new expression is not complete
if ( !$ExpressionData{$Field} ) {
$FieldsOk = 0;
last FIELD;
}
}
# add new expression
if ($FieldsOk) {
# add new expression
my $ExpressionID = $ConditionObject->ExpressionAdd(
ConditionID => $GetParam{ConditionID},
ObjectID => $ExpressionData{ObjectID},
AttributeID => $ExpressionData{AttributeID},
OperatorID => $ExpressionData{OperatorID},
Selector => $ExpressionData{Selector},
CompareValue => defined $ExpressionData{CompareValue}
? $ExpressionData{CompareValue}
: '',
UserID => $Self->{UserID},
);
# check error
if ( !$ExpressionID ) {
return $LayoutObject->ErrorScreen(
Message => Translatable('Could not add new Expression!'),
Comment => Translatable('Please contact the administrator.'),
);
}
}
# save all existing action fields
for my $ActionID ( @{$ActionIDsRef} ) {
# get action fields
my %ActionData;
for my $Field (qw(ObjectID Selector AttributeID OperatorID ActionValue)) {
$ActionData{$Field} = $ParamObject->GetParam(
Param => 'ActionID-' . $ActionID . '-' . $Field,
);
}
# check if existing action is complete
# (all required fields must be filled, ActionValue can be empty)
my $FieldsOk = 1;
FIELD:
for my $Field (qw(ObjectID Selector AttributeID OperatorID)) {
# new action is not complete
if ( !$ActionData{$Field} ) {
$FieldsOk = 0;
last FIELD;
}
}
# update existing action only if all fields are complete
if ($FieldsOk) {
# update the action
my $Success = $ConditionObject->ActionUpdate(
ActionID => $ActionID,
ObjectID => $ActionData{ObjectID},
AttributeID => $ActionData{AttributeID},
OperatorID => $ActionData{OperatorID},
Selector => $ActionData{Selector},
ActionValue => $ActionData{ActionValue} || '',
UserID => $Self->{UserID},
);
# check error
if ( !$Success ) {
return $LayoutObject->ErrorScreen(
Message => $LayoutObject->{LanguageObject}
->Translate( 'Could not update ActionID %s!', $ActionID ),
Comment => Translatable('Please contact the administrator.'),
);
}
}
}
# get new action fields
my %ActionData;
for my $Field (qw(ObjectID Selector AttributeID OperatorID ActionValue)) {
$ActionData{$Field} = $ParamObject->GetParam(
Param => 'ActionID-NEW-' . $Field,
);
}
# check if new action is complete
# (all required fields must be filled, ActionValue can be empty)
$FieldsOk = 1;
FIELD:
for my $Field (qw(ObjectID Selector AttributeID OperatorID)) {
# new action is not complete
if ( !$ActionData{$Field} ) {
$FieldsOk = 0;
last FIELD;
}
}
# add new action
if ($FieldsOk) {
# add new action
my $ActionID = $ConditionObject->ActionAdd(
ConditionID => $GetParam{ConditionID},
ObjectID => $ActionData{ObjectID},
AttributeID => $ActionData{AttributeID},
OperatorID => $ActionData{OperatorID},
Selector => $ActionData{Selector},
ActionValue => $ActionData{ActionValue} || '',
UserID => $Self->{UserID},
);
# check error
if ( !$ActionID ) {
return $LayoutObject->ErrorScreen(
Message => Translatable('Could not add new Action!'),
Comment => Translatable('Please contact the administrator.'),
);
}
}
# just the save button was pressed, redirect to condition overview
if ( $GetParam{Save} ) {
return $LayoutObject->Redirect(
OP => "Action=AgentITSMChangeCondition;ChangeID=$GetParam{ChangeID}",
);
}
# expression add button was pressed
elsif ( $GetParam{AddExpression} ) {
# show the edit view again, but now with a new empty expression line
return $LayoutObject->Redirect(
OP => "Action=AgentITSMChangeConditionEdit;ChangeID=$GetParam{ChangeID};"
. "ConditionID=$GetParam{ConditionID};NewExpression=1",
);
}
# action add button was pressed
elsif ( $GetParam{AddAction} ) {
# show the edit view again, but now with a new empty action line
return $LayoutObject->Redirect(
OP => "Action=AgentITSMChangeConditionEdit;ChangeID=$GetParam{ChangeID};"
. "ConditionID=$GetParam{ConditionID};NewAction=1",
);
}
# check if an expression should be deleted
if ( $GetParam{DeleteExpressionID} && $GetParam{DeleteExpressionID} ne 'NEW' ) {
# delete the expression
my $Success = $ConditionObject->ExpressionDelete(
ExpressionID => $GetParam{DeleteExpressionID},
UserID => $Self->{UserID},
);
# check error
if ( !$Success ) {
return $LayoutObject->ErrorScreen(
Message => $LayoutObject->{LanguageObject}->Translate(
'Could not delete ExpressionID %s!', $GetParam{DeleteExpressionID}
),
Comment => Translatable('Please contact the administrator.'),
);
}
# show the edit view again
return $LayoutObject->Redirect(
OP => "Action=AgentITSMChangeConditionEdit;ChangeID=$GetParam{ChangeID};"
. "ConditionID=$GetParam{ConditionID}",
);
}
# check if an action should be deleted
if ( $GetParam{DeleteActionID} && $GetParam{DeleteActionID} ne 'NEW' ) {
# delete the action
my $Success = $ConditionObject->ActionDelete(
ActionID => $GetParam{DeleteActionID},
UserID => $Self->{UserID},
);
# check error
if ( !$Success ) {
return $LayoutObject->ErrorScreen(
Message => $LayoutObject->{LanguageObject}->Translate(
'Could not delete ActionID %s!', $GetParam{DeleteActionID}
),
Comment => Translatable('Please contact the administrator.'),
);
}
# show the edit view again
return $LayoutObject->Redirect(
OP => "Action=AgentITSMChangeConditionEdit;ChangeID=$GetParam{ChangeID};"
. "ConditionID=$GetParam{ConditionID}",
);
}
# show the edit view again
return $LayoutObject->Redirect(
OP => "Action=AgentITSMChangeConditionEdit;ChangeID=$GetParam{ChangeID};"
. "ConditionID=$GetParam{ConditionID}",
);
}
}
# ------------------------------------------------------------ #
# handle AJAXUpdate (change the content of dropdownlists)
# ------------------------------------------------------------ #
elsif ( $Self->{Subaction} eq 'AJAXUpdate' ) {
# to store the JSON output
my $JSON;
# expression or action field was changed
if ( $GetParam{ElementChanged} =~ m{ \A ( ExpressionID | ActionID ) - ( \d+ | NEW ) }xms )
{
# get id name of the involved element ( 'ExpressionID' or 'ActionID' )
my $IDName = $1;
# get id of the involved element
my $ID = $2;
# get value field name
my $ValueFieldName;
if ( $IDName eq 'ExpressionID' ) {
$ValueFieldName = 'CompareValue';
}
elsif ( $IDName eq 'ActionID' ) {
$ValueFieldName = 'ActionValue';
}
# get expression or action fields
for my $Field (qw(ObjectID Selector AttributeID OperatorID CompareValue ActionValue)) {
$GetParam{$Field} = $ParamObject->GetParam(
Param => $IDName . '-' . $ID . '-' . $Field,
);
}
# get object selection list
my $ObjectList = $Self->_GetObjectSelection();
# get selector selection list
my $SelectorList = $Self->_GetSelectorSelection(
ObjectID => $GetParam{ObjectID},
ConditionID => $GetParam{ConditionID},
$IDName => $ID,
);
# get attribute selection list
my $AttributeList = $Self->_GetAttributeSelection(
ObjectID => $GetParam{ObjectID},
Selector => $GetParam{Selector},
$IDName => $ID,
);
# get operator selection list
my $OperatorList = $Self->_GetOperatorSelection(
ObjectID => $GetParam{ObjectID},
AttributeID => $GetParam{AttributeID},
$IDName => $ID,
);
# add an empty selector selection if no list is available or nothing is selected
my $PossibleNoneSelector = 0;
if (
!$SelectorList
|| !ref $SelectorList eq 'HASH'
|| !%{$SelectorList}
|| $GetParam{ElementChanged} eq $IDName . '-' . $ID . '-ObjectID'
)
{
$PossibleNoneSelector = 1;
}
# add an empty attribute selection if no list is available or nothing is selected
my $PossibleNoneAttributeID = 0;
if (
!$AttributeList
|| !ref $AttributeList eq 'HASH'
|| !%{$AttributeList}
|| $GetParam{ElementChanged} eq $IDName . '-' . $ID . '-ObjectID'
|| $GetParam{ElementChanged} eq $IDName . '-' . $ID . '-Selector'
)
{
$PossibleNoneAttributeID = 1;
}
# add an empty operator selection if no list is available or nothing is selected
my $PossibleNoneOperatorID = 0;
if (
!$OperatorList
|| !ref $OperatorList eq 'HASH'
|| !%{$OperatorList}
|| $GetParam{ElementChanged} eq $IDName . '-' . $ID . '-ObjectID'
|| $GetParam{ElementChanged} eq $IDName . '-' . $ID . '-Selector'
|| $GetParam{ElementChanged} eq $IDName . '-' . $ID . '-AttributeID'
)
{
$PossibleNoneOperatorID = 1;
}
# if object was changed, reset the attribute and operator list
if ( $GetParam{ElementChanged} eq $IDName . '-' . $ID . '-ObjectID' ) {
$AttributeList = {};
$OperatorList = {};
}
# build json
$JSON = $LayoutObject->BuildSelectionJSON(
[
{
Name => $IDName . '-' . $ID . '-ObjectID',
Data => $ObjectList,
SelectedID => $GetParam{ObjectID},
PossibleNone => 0,
Translation => 1,
Max => 100,
},
{
Name => $IDName . '-' . $ID . '-Selector',
Data => $SelectorList,
SelectedID => $PossibleNoneSelector ? '' : $GetParam{Selector},
PossibleNone => $PossibleNoneSelector,
Translation => 1,
Max => 100,
},
{
Name => $IDName . '-' . $ID . '-AttributeID',
Data => $AttributeList,
SelectedID => $GetParam{AttributeID} || '',
PossibleNone => $PossibleNoneAttributeID,
Translation => 1,
Max => 100,
},
{
Name => $IDName . '-' . $ID . '-OperatorID',
Data => $OperatorList,
SelectedID => $GetParam{OperatorID} || '',
PossibleNone => $PossibleNoneOperatorID,
Translation => 1,
Max => 100,
},
],
);
}
# return json
return $LayoutObject->Attachment(
ContentType => 'application/json; charset=' . $LayoutObject->{Charset},
Content => $JSON,
Type => 'inline',
NoCache => 1,
);
}
# ------------------------------------------------------------------------------------- #
# handle AJAXUpdate (replace the field type, e.g. replace a text field with a selection
# ------------------------------------------------------------------------------------- #
elsif ( $Self->{Subaction} eq 'AJAXContentUpdate' ) {
# to store the HTML string which is returned to the browser
my $HTMLString;
# expression or action field was changed
if ( $GetParam{ElementChanged} =~ m{ \A ( ExpressionID | ActionID ) \- ( \d+ | NEW ) }xms )
{
# get id name of the involved element ( 'ExpressionID' or 'ActionID' )
my $IDName = $1;
# get id of the involved element
my $ID = $2;
# get value field name
my $ValueFieldName;
if ( $IDName eq 'ExpressionID' ) {
$ValueFieldName = 'CompareValue';
}
elsif ( $IDName eq 'ActionID' ) {
$ValueFieldName = 'ActionValue';
}
# get expression or action fields
for my $Field (qw(ObjectID Selector AttributeID OperatorID CompareValue ActionValue)) {
$GetParam{$Field} = $ParamObject->GetParam(
Param => $IDName . '-' . $ID . '-' . $Field,
);
}
# get compare value field type
my $FieldType = $Self->_GetCompareValueFieldType(%GetParam);
# build CompareValue selection
if ( $FieldType eq 'Selection' ) {
# get compare value selection list
my $CompareValueList = $Self->_GetCompareValueSelection(%GetParam);
# add an empty selection if no list is available or nothing is selected
my $PossibleNone = 0;
if (
$Param{PossibleNone}
|| !$Param{$ValueFieldName}
|| !$CompareValueList
|| ( ref $CompareValueList eq 'HASH' && !%{$CompareValueList} )
|| ( ref $CompareValueList eq 'ARRAY' && !@{$CompareValueList} )
)
{
$PossibleNone = 1;
}
# generate ValueOptionString
$HTMLString = $LayoutObject->BuildSelection(
Data => $CompareValueList,
Name => $IDName . '-' . $ID . '-' . $ValueFieldName,
SelectedID => $GetParam{$ValueFieldName},
PossibleNone => $PossibleNone,
Translation => 1,
);
}
# build text input field
elsif ( $FieldType eq 'Text' ) {
# build an empty input field
$HTMLString = ''
. '';
}
# show error for unknown field type
else {
$HTMLString = ''
. $LayoutObject->{LanguageObject}->Translate( 'Error: Unknown field type "%s"!', $FieldType )
. '';
}
}
# return HTML
return $LayoutObject->Attachment(
ContentType => 'text/html',
Charset => $LayoutObject->{UserCharset},
Content => $HTMLString,
Type => 'inline',
NoCache => 1,
);
}
# ------------------------------------------------------------ #
# condition edit view
# ------------------------------------------------------------ #
my %ConditionData;
# get ConditionID
$ConditionData{ConditionID} = $GetParam{ConditionID};
# if this is an existing condition
if ( $ConditionData{ConditionID} ne 'NEW' ) {
# get condition data
my $Condition = $ConditionObject->ConditionGet(
ConditionID => $ConditionData{ConditionID},
UserID => $Self->{UserID},
);
# check if the condition belongs to the given change
if ( $Condition->{ChangeID} ne $GetParam{ChangeID} ) {
return $LayoutObject->ErrorScreen(
Message => $LayoutObject->{LanguageObject}->Translate(
'ConditionID %s does not belong to the given ChangeID %s!',
$ConditionData{ConditionID},
$GetParam{ChangeID}
),
Comment => Translatable('Please contact the administrator.'),
);
}
# add data from condition
%ConditionData = ( %ConditionData, %{$Condition} );
# show existing expressions
$Self->_ExpressionOverview(
%{$ChangeData},
%ConditionData,
ExpressionIDs => $ExpressionIDsRef,
NewExpression => $GetParam{NewExpression},
);
# show existing actions
$Self->_ActionOverview(
%{$ChangeData},
%ConditionData,
ActionIDs => $ActionIDsRef,
NewAction => $GetParam{NewAction},
);
}
else {
$LayoutObject->Block( Name => 'ExpressionOverviewRowNoData' );
$LayoutObject->Block( Name => 'ActionOverviewRowNoData' );
}
# get expression conjunction from condition
if ( !$GetParam{ExpressionConjunction} ) {
$GetParam{ExpressionConjunction} = $ConditionData{ExpressionConjunction} || '';
}
# set radio buttons for expression conjunction
if ( $GetParam{ExpressionConjunction} eq 'all' ) {
$ConditionData{allselected} = 'checked="checked"';
}
else {
$ConditionData{anyselected} = 'checked="checked"';
}
# output header
my $Output = $LayoutObject->Header( Type => 'Small' );
# generate ValidOptionString
$ConditionData{ValidOptionString} = $LayoutObject->BuildSelection(
Data => \%ValidList,
Name => 'ValidID',
SelectedID => $ConditionData{ValidID} || ( $ValidObject->ValidIDsGet() )[0],
Sort => 'NumericKey',
Translation => 1,
Class => 'Modernize',
);
# add the validation error messages
for my $BlockName (@ValidationErrors) {
$LayoutObject->Block(
Name => $BlockName,
Data => {
%GetParam,
},
);
}
# generate output
$Output .= $LayoutObject->Output(
TemplateFile => 'AgentITSMChangeConditionEdit',
Data => {
%Param,
%{$ChangeData},
%ConditionData,
},
);
$Output .= $LayoutObject->Footer(
Type => 'Small',
);
return $Output;
}
# show existing expressions
sub _ExpressionOverview {
my ( $Self, %Param ) = @_;
return if !$Param{ExpressionIDs};
return if ref $Param{ExpressionIDs} ne 'ARRAY';
my @ExpressionIDs = @{ $Param{ExpressionIDs} };
# also show a new empty expression line
if ( $Param{NewExpression} ) {
push @ExpressionIDs, 'NEW';
}
# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
if ( !@ExpressionIDs ) {
$LayoutObject->Block( Name => 'ExpressionOverviewRowNoData' );
return;
}
EXPRESSIONID:
for my $ExpressionID ( sort { $a cmp $b } @ExpressionIDs ) {
# to store the date of an expression
my $ExpressionData = {};
# set expression id to 'NEW' for further function calls
if ( $ExpressionID eq 'NEW' ) {
$ExpressionData->{ExpressionID} = $ExpressionID;
}
# get data for an existing expression
else {
# get condition data
$ExpressionData = $Kernel::OM->Get('Kernel::System::ITSMChange::ITSMCondition')->ExpressionGet(
ExpressionID => $ExpressionID,
UserID => $Self->{UserID},
);
next EXPRESSIONID if !$ExpressionData;
}
# output overview row
$LayoutObject->Block(
Name => 'ExpressionOverviewRow',
Data => {
%Param,
%{$ExpressionData},
},
);
# show object selection
$Self->_ShowObjectSelection(
%Param,
%{$ExpressionData},
);
# show selecor selection
$Self->_ShowSelectorSelection(
%Param,
%{$ExpressionData},
);
# show attribute selection
$Self->_ShowAttributeSelection(
%Param,
%{$ExpressionData},
);
# show operator selection
$Self->_ShowOperatorSelection(
%Param,
%{$ExpressionData},
);
# show compare value field
$Self->_ShowCompareValueField(
%Param,
%{$ExpressionData},
);
}
return 1;
}
# show existing actions
sub _ActionOverview {
my ( $Self, %Param ) = @_;
return if !$Param{ActionIDs};
return if ref $Param{ActionIDs} ne 'ARRAY';
my @ActionIDs = @{ $Param{ActionIDs} };
# also show a new empty action line
if ( $Param{NewAction} ) {
push @ActionIDs, 'NEW';
}
# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
if ( !@ActionIDs ) {
$LayoutObject->Block( Name => 'ActionOverviewRowNoData' );
return;
}
ActionID:
for my $ActionID ( sort { $a cmp $b } @ActionIDs ) {
# to store the date of an action
my $ActionData = {};
# set action id to 'NEW' for further function calls
if ( $ActionID eq 'NEW' ) {
$ActionData->{ActionID} = $ActionID;
}
# get data for an existing action
else {
# get condition data
$ActionData = $Kernel::OM->Get('Kernel::System::ITSMChange::ITSMCondition')->ActionGet(
ActionID => $ActionID,
UserID => $Self->{UserID},
);
next ActionID if !$ActionData;
}
# output overview row
$LayoutObject->Block(
Name => 'ActionOverviewRow',
Data => {
%Param,
%{$ActionData},
},
);
# show object selection
$Self->_ShowObjectSelection(
%Param,
%{$ActionData},
);
# show selecor selection
$Self->_ShowSelectorSelection(
%Param,
%{$ActionData},
);
# show attribute selection
$Self->_ShowAttributeSelection(
%Param,
%{$ActionData},
);
# show operator selection
$Self->_ShowOperatorSelection(
%Param,
%{$ActionData},
);
# show compare value field
$Self->_ShowCompareValueField(
%Param,
%{$ActionData},
);
}
return 1;
}
# show object dropdown field
sub _ShowObjectSelection {
my ( $Self, %Param ) = @_;
# get object selection list
my $ObjectList = $Self->_GetObjectSelection(%Param);
# add an empty selection if no list is available or nothing is selected
my $PossibleNone = 0;
if (
!$ObjectList
|| !ref $ObjectList eq 'HASH'
|| !%{$ObjectList}
|| !$Param{ObjectID}
)
{
$PossibleNone = 1;
}
# name of the div that should be updated
my $UpdateDivName;
# id name of the involved element ( 'ExpressionID' or 'ActionID' )
my $IDName;
# block name for the output layout block
my $BlockName;
# for expression elements
if ( $Param{ExpressionID} ) {
$UpdateDivName = "ExpressionID-$Param{ExpressionID}-CompareValue-Div";
$IDName = 'ExpressionID';
$BlockName = 'ExpressionOverviewRowElementObject';
}
# for action elements
elsif ( $Param{ActionID} ) {
$UpdateDivName = "ActionID-$Param{ActionID}-ActionValue-Div";
$IDName = 'ActionID';
$BlockName = 'ActionOverviewRowElementObject';
}
# parameters for ajax
$Param{ObjectOptionName} = $IDName . '-' . $Param{$IDName} . '-ObjectID';
$Param{IDName} = $IDName;
# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# generate ObjectOptionString
my $ObjectOptionString = $LayoutObject->BuildSelection(
Data => $ObjectList,
Name => $Param{ObjectOptionName},
SelectedID => $Param{ObjectID},
PossibleNone => $PossibleNone,
Translation => 1,
);
# output object selection
$LayoutObject->Block(
Name => $BlockName,
Data => {
%Param,
ObjectOptionString => $ObjectOptionString,
},
);
return 1;
}
# show selector dropdown field
sub _ShowSelectorSelection {
my ( $Self, %Param ) = @_;
# get selector selection list
my $SelectorList = $Self->_GetSelectorSelection(%Param);
# add an empty selection if no list is available or nothing is selected
my $PossibleNone = 0;
if (
!$SelectorList
|| !ref $SelectorList eq 'HASH'
|| !%{$SelectorList}
|| !$Param{Selector}
)
{
$PossibleNone = 1;
}
# id name of the involved element ( 'ExpressionID' or 'ActionID' )
my $IDName;
# block name for the output layout block
my $BlockName;
# for expression elements
if ( $Param{ExpressionID} ) {
$IDName = 'ExpressionID';
$BlockName = 'ExpressionOverviewRowElementSelector';
}
# for action elements
elsif ( $Param{ActionID} ) {
$IDName = 'ActionID';
$BlockName = 'ActionOverviewRowElementSelector';
}
# parameters for ajax
$Param{ObjectOptionName} = $IDName . '-' . $Param{$IDName} . '-Selector';
$Param{IDName} = $IDName;
# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# generate SelectorOptionString
my $SelectorOptionString = $LayoutObject->BuildSelection(
Data => $SelectorList,
Name => $Param{ObjectOptionName},
SelectedID => $Param{Selector},
PossibleNone => $PossibleNone,
Translation => 1,
);
# output selector selection
$LayoutObject->Block(
Name => $BlockName,
Data => {
%Param,
SelectorOptionString => $SelectorOptionString,
},
);
return 1;
}
# show attribute dropdown field
sub _ShowAttributeSelection {
my ( $Self, %Param ) = @_;
# name of the div that should be updated
my $UpdateDivName;
# id name of the involved element ( 'ExpressionID' or 'ActionID' )
my $IDName;
# block name for the output layout block
my $BlockName;
# name of the value field ( CompareValue or ActionValue )
my $ValueFieldName;
# for expression elements
if ( $Param{ExpressionID} ) {
$UpdateDivName = "ExpressionID-$Param{ExpressionID}-CompareValue-Div";
$IDName = 'ExpressionID';
$BlockName = 'ExpressionOverviewRowElementAttribute';
$ValueFieldName = 'CompareValue';
}
# for action elements
elsif ( $Param{ActionID} ) {
$UpdateDivName = "ActionID-$Param{ActionID}-ActionValue-Div";
$IDName = 'ActionID';
$BlockName = 'ActionOverviewRowElementAttribute';
$ValueFieldName = 'ActionValue';
}
# get attribute selection list
my $AttributeList = $Self->_GetAttributeSelection(
ObjectID => $Param{ObjectID},
Selector => $Param{Selector},
$IDName => $Param{$IDName},
);
# add an empty selection if no list is available or nothing is selected
my $PossibleNone = 0;
if (
!$AttributeList
|| !ref $AttributeList eq 'HASH'
|| !%{$AttributeList}
|| !$Param{AttributeID}
)
{
$PossibleNone = 1;
}
# parameters for ajax
$Param{ObjectOptionName} = $IDName . '-' . $Param{$IDName} . '-AttributeID';
$Param{IDName} = $IDName;
# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# generate AttributeOptionString
my $AttributeOptionString = $LayoutObject->BuildSelection(
Data => $AttributeList,
Name => $Param{ObjectOptionName},
SelectedID => $Param{AttributeID},
PossibleNone => $PossibleNone,
Translation => 1,
);
# output attribute selection
$LayoutObject->Block(
Name => $BlockName,
Data => {
%Param,
AttributeOptionString => $AttributeOptionString,
},
);
return 1;
}
# show operator dropdown field
sub _ShowOperatorSelection {
my ( $Self, %Param ) = @_;
# id name of the involved element ( 'ExpressionID' or 'ActionID' )
my $IDName;
# block name for the output layout block
my $BlockName;
# for expression elements
if ( $Param{ExpressionID} ) {
$IDName = 'ExpressionID';
$BlockName = 'ExpressionOverviewRowElementOperator';
}
# for action elements
elsif ( $Param{ActionID} ) {
$IDName = 'ActionID';
$BlockName = 'ActionOverviewRowElementOperator';
}
# get operator selection list
my $OperatorList = $Self->_GetOperatorSelection(
ObjectID => $Param{ObjectID},
AttributeID => $Param{AttributeID},
$IDName => $Param{$IDName},
);
# add an empty selection if no list is available or nothing is selected
my $PossibleNone = 0;
if (
!$OperatorList
|| !ref $OperatorList eq 'HASH'
|| !%{$OperatorList}
|| !$Param{OperatorID}
)
{
$PossibleNone = 1;
}
# parameters for ajax
$Param{ObjectOptionName} = $IDName . '-' . $Param{$IDName} . '-OperatorID';
$Param{IDName} = $IDName;
# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# generate OperatorOptionString
my $OperatorOptionString = $LayoutObject->BuildSelection(
Data => $OperatorList,
Name => $Param{ObjectOptionName},
SelectedID => $Param{OperatorID},
PossibleNone => $PossibleNone,
Translation => 1,
);
# output operator selection
$LayoutObject->Block(
Name => $BlockName,
Data => {
%Param,
OperatorOptionString => $OperatorOptionString,
},
);
return 1;
}
# show compare value field
sub _ShowCompareValueField {
my ( $Self, %Param ) = @_;
# get compare value field type
my $FieldType = $Self->_GetCompareValueFieldType(%Param);
# id name of the involved element ( 'ExpressionID' or 'ActionID' )
my $IDName;
# block names for the output layout block
my $BlockNameText;
my $BlockNameSelection;
my $ValueFieldName;
# for expression elements
if ( $Param{ExpressionID} ) {
$IDName = 'ExpressionID';
$BlockNameText = 'ExpressionOverviewRowElementCompareValueText';
$BlockNameSelection = 'ExpressionOverviewRowElementCompareValueSelection';
$ValueFieldName = 'CompareValue';
}
# for action elements
elsif ( $Param{ActionID} ) {
$IDName = 'ActionID';
$BlockNameText = 'ActionOverviewRowElementActionValueText';
$BlockNameSelection = 'ActionOverviewRowElementActionValueSelection';
$ValueFieldName = 'ActionValue';
}
# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# compare value is a text field
if ( $FieldType eq 'Text' ) {
$LayoutObject->Block(
Name => $BlockNameText,
Data => {
%Param,
},
);
}
# compare value is a selection field
elsif ( $FieldType eq 'Selection' ) {
# get compare value selection list
my $CompareValueList = $Self->_GetCompareValueSelection(%Param);
my $AttributeName;
if ( $Param{AttributeID} ) {
# lookup attribute name
$AttributeName = $Kernel::OM->Get('Kernel::System::ITSMChange::ITSMCondition')->AttributeLookup(
AttributeID => $Param{AttributeID},
);
}
# add an empty selection if no list is available or nothing is selected
# or the list is the workorder agent list
my $PossibleNone = 0;
if (
$Param{PossibleNone}
|| !$Param{$ValueFieldName}
|| !$CompareValueList
|| ( ref $CompareValueList eq 'HASH' && !%{$CompareValueList} )
|| ( ref $CompareValueList eq 'ARRAY' && !@{$CompareValueList} )
|| (
$ValueFieldName eq 'ActionValue'
&& $AttributeName
&& $AttributeName eq 'WorkOrderAgentID'
)
)
{
$PossibleNone = 1;
}
# generate ValueOptionString
my $ValueOptionString = $LayoutObject->BuildSelection(
Data => $CompareValueList,
Name => $IDName . '-' . $Param{$IDName} . '-' . $ValueFieldName,
SelectedID => $Param{$ValueFieldName},
PossibleNone => $PossibleNone,
Translation => 1,
);
# output selection
$LayoutObject->Block(
Name => $BlockNameSelection,
Data => {
%Param,
ValueOptionString => $ValueOptionString,
},
);
}
# compare value is a date field
elsif ( $FieldType eq 'Date' ) {
# TODO : Implement date selection later!
}
# compare value is an autocomplete field
elsif ( $FieldType eq 'Autocomplete' ) {
# TODO : Implement autocomplete selection later!
}
# show empty block if field type is unknown
else {
# output empty block
$LayoutObject->Block(
Name => $BlockNameSelection,
Data => {
%Param,
},
);
}
return 1;
}
# get compare value field type
sub _GetCompareValueFieldType {
my ( $Self, %Param ) = @_;
# set default field type
my $FieldType = 'Selection';
# if an attribute is set
if ( $Param{AttributeID} ) {
# get condition object
my $ConditionObject = $Kernel::OM->Get('Kernel::System::ITSMChange::ITSMCondition');
# lookup attribute name
my $AttributeName = $ConditionObject->AttributeLookup(
AttributeID => $Param{AttributeID},
);
# check error
if ( !$AttributeName ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "AttributeID $Param{AttributeID} does not exist!",
);
return;
}
# get the field type
$FieldType = $ConditionObject->ConditionCompareValueFieldType(
ObjectID => $Param{ObjectID},
AttributeID => $Param{AttributeID},
UserID => $Self->{UserID},
);
return if !$FieldType;
}
# Workaround for not yet implemented field types
# TODO: implement these field types later!
if ( $FieldType eq 'Date' ) {
$FieldType = 'Text';
}
elsif ( $FieldType eq 'Autocomplete' ) {
$FieldType = 'Selection';
}
return $FieldType;
}
# get object dropdown field data
sub _GetObjectSelection {
my ( $Self, %Param ) = @_;
# get object list
my $ObjectList = $Kernel::OM->Get('Kernel::System::ITSMChange::ITSMCondition')->ObjectList(
UserID => $Self->{UserID},
);
return $ObjectList;
}
# get selector dropdown field data
sub _GetSelectorSelection {
my ( $Self, %Param ) = @_;
my $SelectorList = {};
# if an object is set
if ( $Param{ObjectID} ) {
# get selector list
$SelectorList = $Kernel::OM->Get('Kernel::System::ITSMChange::ITSMCondition')->ObjectSelectorList(
ObjectID => $Param{ObjectID},
ConditionID => $Param{ConditionID},
ExpressionID => $Param{ExpressionID},
ActionID => $Param{ActionID},
UserID => $Self->{UserID},
);
}
return $SelectorList;
}
# get attribute selection list data
sub _GetAttributeSelection {
my ( $Self, %Param ) = @_;
# to store the attriutes
my %Attributes;
# if a selector is set
if ( $Param{Selector} ) {
# get condition object
my $ConditionObject = $Kernel::OM->Get('Kernel::System::ITSMChange::ITSMCondition');
# get list of all attributes
my $AllAttributes = $ConditionObject->AttributeList(
UserID => $Self->{UserID},
);
# lookup object name
my $ObjectName = $ConditionObject->ObjectLookup(
ObjectID => $Param{ObjectID},
);
# check error
if ( !$ObjectName ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "ObjectID $Param{ObjectID} does not exist!",
);
return;
}
# get object attribute mapping from sysconfig
my $ObjectAttributeMapping;
# get config object
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
# get mapping config for expressions or actions
if ( $Param{ExpressionID} ) {
$ObjectAttributeMapping = $ConfigObject->Get(
$ObjectName . '::Mapping::Expression::Object::Attribute',
);
}
elsif ( $Param{ActionID} ) {
$ObjectAttributeMapping = $ConfigObject->Get(
$ObjectName . '::Mapping::Action::Object::Attribute',
);
}
# get the list of dynamic fields (change or workorder)
my $DynamicFields = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet(
Valid => 0,
ObjectType => $ObjectName,
);
# build a lookup hash for all dynamic fields for this object (change or workorder)
my %DynamicFieldName;
for my $DynamicField ( @{$DynamicFields} ) {
$DynamicFieldName{ $DynamicField->{Name} } = 1;
}
# get the valid attributes for the given object
ATTRIBUTEID:
for my $AttributeID ( sort keys %{$AllAttributes} ) {
# check if attribute is in the mapping
if ( $ObjectAttributeMapping->{ $AllAttributes->{$AttributeID} } ) {
$Attributes{$AttributeID} = $AllAttributes->{$AttributeID};
}
else {
# get attribute name
my $AttributeName = $AllAttributes->{$AttributeID};
# check if the attribute is a dynamic field and dynamic fields should be used as attributes
next ATTRIBUTEID if !$ObjectAttributeMapping->{DynamicField};
next ATTRIBUTEID if $AttributeName !~ m{ \A DynamicField_ (\w+) }xms;
# remove the prefix 'DynamicField_' from dynamic fields for nicer display
my $AttributeWithoutPrefix = $1;
# check if it is a dynamic field for the correct object
next ATTRIBUTEID if !$DynamicFieldName{$AttributeWithoutPrefix};
# add the dynamic field to attribute list
$Attributes{$AttributeID} = $AttributeWithoutPrefix;
}
}
for my $Attribute ( values %Attributes ) {
# remove 'ID' at the end of the attribute name for nicer display
$Attribute =~ s{ ID \z }{}xms;
}
}
return \%Attributes;
}
# get operator list data
sub _GetOperatorSelection {
my ( $Self, %Param ) = @_;
# to store the operators
my %Operators;
# if an atribute is set
if ( $Param{AttributeID} ) {
# get condition object
my $ConditionObject = $Kernel::OM->Get('Kernel::System::ITSMChange::ITSMCondition');
# lookup object name
my $ObjectName = $ConditionObject->ObjectLookup(
ObjectID => $Param{ObjectID},
);
# get log object
my $LogObject = $Kernel::OM->Get('Kernel::System::Log');
# check error
if ( !$ObjectName ) {
$LogObject->Log(
Priority => 'error',
Message => "ObjectID $Param{ObjectID} does not exist!",
);
return;
}
# lookup attribute name
my $AttributeName = $ConditionObject->AttributeLookup(
AttributeID => $Param{AttributeID},
);
# check error
if ( !$AttributeName ) {
$LogObject->Log(
Priority => 'error',
Message => "AttributeID $Param{AttributeID} does not exist!",
);
return;
}
# get list of all operators
my $AllOperators = $ConditionObject->OperatorList(
UserID => $Self->{UserID},
);
# get attribute operator mapping from sysconfig
my $MappingConfig;
# get config object
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
# get mapping config for expressions or actions
if ( $Param{ExpressionID} ) {
$MappingConfig = $ConfigObject->Get(
$ObjectName . '::Mapping::Expression::Attribute::Operator'
);
}
elsif ( $Param{ActionID} ) {
$MappingConfig = $ConfigObject->Get(
$ObjectName . '::Mapping::Action::Attribute::Operator'
);
}
# remove the name part of the dynamic field and replace only with the string "DynamicField"
$AttributeName =~ s{ \A DynamicField_ (\w+) }{DynamicField}xms;
my $AttributeOperatorMapping;
if ($MappingConfig) {
$AttributeOperatorMapping = $MappingConfig->{$AttributeName} || {};
}
# get allowed operators for the given attribute
OPERATORID:
for my $OperatorID ( sort keys %{$AllOperators} ) {
# get operator name
my $OperatorName = $AllOperators->{$OperatorID};
# check if operator is allowed for this attribute
next OPERATORID if !$AttributeOperatorMapping->{$OperatorName};
# remember the operator
$Operators{$OperatorID} = $OperatorName;
}
}
return \%Operators;
}
# get compare value list
sub _GetCompareValueSelection {
my ( $Self, %Param ) = @_;
# to store the compare value list
my $CompareValueList = {};
# if an attribute is set
if ( $Param{AttributeID} ) {
# get condition object
my $ConditionObject = $Kernel::OM->Get('Kernel::System::ITSMChange::ITSMCondition');
# lookup attribute name
my $AttributeName = $ConditionObject->AttributeLookup(
AttributeID => $Param{AttributeID},
);
# check error
if ( !$AttributeName ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "AttributeID $Param{AttributeID} does not exist!",
);
return;
}
# get compare value list
$CompareValueList = $ConditionObject->ObjectCompareValueList(
ObjectID => $Param{ObjectID},
AttributeName => $AttributeName,
UserID => $Self->{UserID},
);
}
return $CompareValueList;
}
1;