diff --git a/Kernel/Modules/AgentReferenceSearch.pm b/Kernel/Modules/AgentReferenceSearch.pm index 706f36bc67..985ad375b5 100644 --- a/Kernel/Modules/AgentReferenceSearch.pm +++ b/Kernel/Modules/AgentReferenceSearch.pm @@ -108,6 +108,7 @@ sub Run { MaxResults => $MaxResults, UserID => 1, # TODO: what about Permission check ParamObject => $ParamObject, + LayoutObject => $LayoutObject, ); my @Results; diff --git a/Kernel/Modules/AgentTicketActionCommon.pm b/Kernel/Modules/AgentTicketActionCommon.pm index bad482d54e..0a7bcb74c4 100644 --- a/Kernel/Modules/AgentTicketActionCommon.pm +++ b/Kernel/Modules/AgentTicketActionCommon.pm @@ -172,12 +172,10 @@ sub new { } # get form id - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'FormID' ); - - # create form id - if ( !$Self->{FormID} ) { - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $Kernel::OM->Get('Kernel::System::Web::Request'), + LayoutObject => $Kernel::OM->Get('Kernel::Output::HTML::Layout'), + ); # methods which are used to determine the possible values of the standard fields $Self->{FieldMethods} = [ @@ -1302,8 +1300,8 @@ sub Run { ); } - # remove pre submitted attachments - $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); # delete hidden fields cache $Kernel::OM->Get('Kernel::System::Cache')->Delete( diff --git a/Kernel/Modules/AgentTicketCompose.pm b/Kernel/Modules/AgentTicketCompose.pm index 7c0ccdedf8..9c816c532c 100644 --- a/Kernel/Modules/AgentTicketCompose.pm +++ b/Kernel/Modules/AgentTicketCompose.pm @@ -103,12 +103,10 @@ sub new { } # get form id - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'FormID' ); - - # create form id - if ( !$Self->{FormID} ) { - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $Kernel::OM->Get('Kernel::System::Web::Request'), + LayoutObject => $Kernel::OM->Get('Kernel::Output::HTML::Layout'), + ); return $Self; } @@ -1155,8 +1153,8 @@ sub Run { CreateUserID => $Self->{UserID}, ); - # remove pre submited attachments - $UploadCacheObject->FormIDRemove( FormID => $GetParam{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); # If form was called based on a draft, # delete draft since its content has now been used. diff --git a/Kernel/Modules/AgentTicketEmail.pm b/Kernel/Modules/AgentTicketEmail.pm index 9468309718..29cc44fa3e 100644 --- a/Kernel/Modules/AgentTicketEmail.pm +++ b/Kernel/Modules/AgentTicketEmail.pm @@ -89,12 +89,10 @@ sub new { } # get form id - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'FormID' ); - - # create form id - if ( !$Self->{FormID} ) { - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $Kernel::OM->Get('Kernel::System::Web::Request'), + LayoutObject => $Kernel::OM->Get('Kernel::Output::HTML::Layout'), + ); # methods which are used to determine the possible values of the standard fields $Self->{FieldMethods} = [ @@ -2053,8 +2051,8 @@ sub Run { ); } - # remove pre-submitted attachments - $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); # delete hidden fields cache $Kernel::OM->Get('Kernel::System::Cache')->Delete( diff --git a/Kernel/Modules/AgentTicketEmailOutbound.pm b/Kernel/Modules/AgentTicketEmailOutbound.pm index 66bfe872a8..1eb63bdece 100644 --- a/Kernel/Modules/AgentTicketEmailOutbound.pm +++ b/Kernel/Modules/AgentTicketEmailOutbound.pm @@ -171,13 +171,19 @@ sub Run { NewStateID NewPriorityID TimeUnits IsVisibleForCustomer Title Body Subject NewQueueID Year Month Day Hour Minute NewOwnerID NewOwnerType OldOwnerID NewResponsibleID TypeID ServiceID SLAID Expand ReplyToArticle StandardTemplateID CreateArticle - FormID ElementChanged + ElementChanged ) ) { $GetParam{$Key} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => $Key ); } + # get form id + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $Kernel::OM->Get('Kernel::System::Web::Request'), + LayoutObject => $LayoutObject, + ); + my %Ticket = $TicketObject->TicketGet( TicketID => $Self->{TicketID} ); my $CustomerUser = $Ticket{CustomerUserID}; my $QueueID = $Ticket{QueueID}; @@ -1516,8 +1522,8 @@ sub SendEmail { } } - # remove pre-submitted attachments - $UploadCacheObject->FormIDRemove( FormID => $GetParam{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); # If form was called based on a draft, # delete draft since its content has now been used. diff --git a/Kernel/Modules/AgentTicketEmailResend.pm b/Kernel/Modules/AgentTicketEmailResend.pm index 896f5f94e1..5d618d2195 100644 --- a/Kernel/Modules/AgentTicketEmailResend.pm +++ b/Kernel/Modules/AgentTicketEmailResend.pm @@ -34,12 +34,10 @@ sub new { $Self->{Debug} = $Param{Debug} || 0; # Get form ID. - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'FormID' ); - - # Create new form ID. - if ( !$Self->{FormID} ) { - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $Kernel::OM->Get('Kernel::System::Web::Request'), + LayoutObject => $Kernel::OM->Get('Kernel::Output::HTML::Layout'), + ); return $Self; } @@ -679,8 +677,8 @@ sub Run { ); } - # Remove pre-submitted attachments. - $UploadCacheObject->FormIDRemove( FormID => $GetParam{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); # Load new URL in parent window and close popup. return $LayoutObject->PopupClose( diff --git a/Kernel/Modules/AgentTicketForward.pm b/Kernel/Modules/AgentTicketForward.pm index 86b6d55cdc..42070bfd36 100644 --- a/Kernel/Modules/AgentTicketForward.pm +++ b/Kernel/Modules/AgentTicketForward.pm @@ -110,7 +110,7 @@ sub new { for ( qw(To Cc Bcc Subject Body InReplyTo References ComposeStateID IsVisibleForCustomerPresent - IsVisibleForCustomer ArticleID TimeUnits Year Month Day Hour Minute FormID FormDraftID Title) + IsVisibleForCustomer ArticleID TimeUnits Year Month Day Hour Minute FormDraftID Title) ) { my $Value = $ParamObject->GetParam( Param => $_ ); @@ -124,10 +124,11 @@ sub new { # ACL compatibility translation $Self->{ACLCompatGetParam}->{NextStateID} = $Self->{GetParam}->{ComposeStateID}; - # create form id - if ( !$Self->{GetParam}->{FormID} ) { - $Self->{GetParam}->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + # Get form ID. + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $ParamObject, + LayoutObject => $Kernel::OM->Get('Kernel::Output::HTML::Layout'), + ); return $Self; } @@ -1415,8 +1416,8 @@ sub SendEmail { } } - # remove pre-submitted attachments - $UploadCacheObject->FormIDRemove( FormID => $GetParam{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); # If form was called based on a draft, # delete draft since its content has now been used. diff --git a/Kernel/Modules/AgentTicketMove.pm b/Kernel/Modules/AgentTicketMove.pm index c9fba257d9..cec62fc039 100644 --- a/Kernel/Modules/AgentTicketMove.pm +++ b/Kernel/Modules/AgentTicketMove.pm @@ -102,12 +102,10 @@ sub new { } # get form id - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'FormID' ); - - # create form id - if ( !$Self->{FormID} ) { - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $Kernel::OM->Get('Kernel::System::Web::Request'), + LayoutObject => $Kernel::OM->Get('Kernel::Output::HTML::Layout'), + ); return $Self; } @@ -1250,8 +1248,8 @@ sub Run { ); } - # remove pre-submitted attachments - $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); } # only set the dynamic fields if the new window was displayed (link), otherwise if ticket was diff --git a/Kernel/Modules/AgentTicketPhone.pm b/Kernel/Modules/AgentTicketPhone.pm index 1db6acacf4..6e4e65dae2 100644 --- a/Kernel/Modules/AgentTicketPhone.pm +++ b/Kernel/Modules/AgentTicketPhone.pm @@ -93,12 +93,10 @@ sub new { } # get form id - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'FormID' ); - - # create form id - if ( !$Self->{FormID} ) { - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $Kernel::OM->Get('Kernel::System::Web::Request'), + LayoutObject => $Kernel::OM->Get('Kernel::Output::HTML::Layout'), + ); # methods which are used to determine the possible values of the standard fields $Self->{FieldMethods} = [ @@ -1911,8 +1909,8 @@ sub Run { ); } - # remove pre submited attachments - $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); # delete hidden fields cache $Kernel::OM->Get('Kernel::System::Cache')->Delete( diff --git a/Kernel/Modules/AgentTicketPhoneCommon.pm b/Kernel/Modules/AgentTicketPhoneCommon.pm index fcb623a1d6..8d37532533 100644 --- a/Kernel/Modules/AgentTicketPhoneCommon.pm +++ b/Kernel/Modules/AgentTicketPhoneCommon.pm @@ -104,12 +104,10 @@ sub new { } # get form id - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'FormID' ); - - # create form id - if ( !$Self->{FormID} ) { - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $Kernel::OM->Get('Kernel::System::Web::Request'), + LayoutObject => $Kernel::OM->Get('Kernel::Output::HTML::Layout'), + ); return $Self; } @@ -978,8 +976,8 @@ sub Run { ); } - # remove pre submitted attachments - $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); # set dynamic fields # cycle through the activated Dynamic Fields for this screen diff --git a/Kernel/Modules/AgentTicketProcess.pm b/Kernel/Modules/AgentTicketProcess.pm index 81c65c88b6..20eb0d0764 100644 --- a/Kernel/Modules/AgentTicketProcess.pm +++ b/Kernel/Modules/AgentTicketProcess.pm @@ -353,12 +353,10 @@ sub Run { } # get form id - $Self->{FormID} = $ParamObject->GetParam( Param => 'FormID' ); - - # create form id - if ( !$Self->{FormID} ) { - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $ParamObject, + LayoutObject => $LayoutObject, + ); # if we have no subaction display the process list to start a new one if ( !$Self->{Subaction} ) { @@ -5526,8 +5524,8 @@ sub _StoreActivityDialog { ); } - # Remove pre submitted attachments. - $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); # time accounting if ( $Param{GetParam}->{TimeUnits} ) { diff --git a/Kernel/Modules/CustomerTicketMessage.pm b/Kernel/Modules/CustomerTicketMessage.pm index f3be3e012f..ec812783d1 100644 --- a/Kernel/Modules/CustomerTicketMessage.pm +++ b/Kernel/Modules/CustomerTicketMessage.pm @@ -99,12 +99,10 @@ sub new { } # get form id - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'FormID' ); - - # create form id - if ( !$Self->{FormID} ) { - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $Kernel::OM->Get('Kernel::System::Web::Request'), + LayoutObject => $Kernel::OM->Get('Kernel::Output::HTML::Layout'), + ); # methods which are used to determine the possible values of the standard fields $Self->{FieldMethods} = [ @@ -900,8 +898,8 @@ sub Run { # if no article has to be created clean up and return if ( !$VisibilityStd{Article} ) { - # remove pre submitted attachments - $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); # delete hidden fields cache $Kernel::OM->Get('Kernel::System::Cache')->Delete( diff --git a/Kernel/Modules/CustomerTicketProcess.pm b/Kernel/Modules/CustomerTicketProcess.pm index d47b7073c9..e58c430daf 100644 --- a/Kernel/Modules/CustomerTicketProcess.pm +++ b/Kernel/Modules/CustomerTicketProcess.pm @@ -147,12 +147,10 @@ sub Run { } # get form id - $Self->{FormID} = $ParamObject->GetParam( Param => 'FormID' ); - - # create form id - if ( !$Self->{FormID} ) { - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $ParamObject, + LayoutObject => $LayoutObject, + ); # if invalid process is detected on a ActivityDilog popup screen show an error message if ( @@ -3474,8 +3472,8 @@ sub _StoreActivityDialog { ); } - # remove pre submitted attachments - $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); } } diff --git a/Kernel/Modules/CustomerTicketZoom.pm b/Kernel/Modules/CustomerTicketZoom.pm index 11fd42f942..02916007e7 100644 --- a/Kernel/Modules/CustomerTicketZoom.pm +++ b/Kernel/Modules/CustomerTicketZoom.pm @@ -106,12 +106,10 @@ sub new { } # get form id - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'FormID' ); - - # create form id - if ( !$Self->{FormID} ) { - $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); - } + $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::FormCache')->PrepareFormID( + ParamObject => $Kernel::OM->Get('Kernel::System::Web::Request'), + LayoutObject => $Kernel::OM->Get('Kernel::Output::HTML::Layout'), + ); # methods which are used to determine the possible values of the standard fields $Self->{FieldMethods} = [ @@ -1254,8 +1252,8 @@ sub Run { } } - # remove pre submited attachments - $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} ); + # remove all form data + $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDRemove( FormID => $Self->{FormID} ); # delete hidden fields cache $Kernel::OM->Get('Kernel::System::Cache')->Delete( diff --git a/Kernel/System/DynamicField/Backend.pm b/Kernel/System/DynamicField/Backend.pm index ec5a06768b..f3d33acd87 100644 --- a/Kernel/System/DynamicField/Backend.pm +++ b/Kernel/System/DynamicField/Backend.pm @@ -38,6 +38,7 @@ our @ObjectDependencies = ( 'Kernel::System::DynamicFieldValue', 'Kernel::System::Log', 'Kernel::System::Main', + 'Kernel::System::Web::FormCache', ); =head1 NAME @@ -3025,6 +3026,7 @@ This is used in auto completion when searching for possible object IDs. MaxResults => $MaxResults, UserID => 1, ParamObject => $ParamObject, + LayoutObject => $LayoutObject, ); =cut @@ -3033,7 +3035,7 @@ sub SearchObjects { my ( $Self, %Param ) = @_; # check needed stuff - for my $Needed (qw(DynamicFieldConfig)) { + for my $Needed (qw(DynamicFieldConfig ParamObject LayoutObject)) { if ( !$Param{$Needed} ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', @@ -3048,7 +3050,17 @@ sub SearchObjects { my $DynamicFieldBackend = 'DynamicField' . $Param{DynamicFieldConfig}->{FieldType} . 'Object'; if ( $Self->{$DynamicFieldBackend}->can('SearchObjects') ) { - return $Self->{$DynamicFieldBackend}->SearchObjects(%Param); + my @ObjectIDs = $Self->{$DynamicFieldBackend}->SearchObjects(%Param); + + # store all possible values for this field and form id for later verification + $Kernel::OM->Get('Kernel::System::Web::FormCache')->SetFormData( + LayoutObject => $Param{LayoutObject}, + FormID => $Param{ParamObject}->GetParam( Param => 'FormID' ), + Key => 'PossibleValues_DynamicField_' . $Param{DynamicFieldConfig}{Name}, + Value => \@ObjectIDs, + ); + + return @ObjectIDs; } return; diff --git a/Kernel/System/DynamicField/Driver/BaseReference.pm b/Kernel/System/DynamicField/Driver/BaseReference.pm index f1ba20b89e..110fa589f6 100644 --- a/Kernel/System/DynamicField/Driver/BaseReference.pm +++ b/Kernel/System/DynamicField/Driver/BaseReference.pm @@ -36,9 +36,11 @@ use Kernel::System::VariableCheck qw(IsArrayRefWithData IsStringWithData); our @ObjectDependencies = ( 'Kernel::Config', + 'Kernel::Output::HTML::Layout', 'Kernel::System::DB', 'Kernel::System::DynamicFieldValue', 'Kernel::System::Log', + 'Kernel::System::Web::FormCache', ); =head1 NAME @@ -972,6 +974,17 @@ sub PossibleValuesGet { %Param, ); + # if we are in an edit mask, FormID and SessionID will be provided by the LayoutObject + # in this case we store the possible values for later verification + my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); + if ( $LayoutObject->{FormID} && $LayoutObject->{SessionID} ) { + $Kernel::OM->Get('Kernel::System::Web::FormCache')->SetFormData( + LayoutObject => $LayoutObject, + Key => 'PossibleValues_DynamicField_' . $Param{DynamicFieldConfig}{Name}, + Value => \@SearchResult, + ); + } + for my $ResultItem (@SearchResult) { my %ItemDescription = $Self->ObjectDescriptionGet( DynamicFieldConfig => $Param{DynamicFieldConfig}, diff --git a/Kernel/System/DynamicField/Driver/Lens.pm b/Kernel/System/DynamicField/Driver/Lens.pm index 85ff24e6c1..b7e5e444fa 100644 --- a/Kernel/System/DynamicField/Driver/Lens.pm +++ b/Kernel/System/DynamicField/Driver/Lens.pm @@ -35,11 +35,13 @@ use Kernel::Language qw(Translatable); our @ObjectDependencies = ( 'Kernel::Config', + 'Kernel::Output::HTML::Layout', 'Kernel::System::DB', 'Kernel::System::DynamicField', 'Kernel::System::DynamicField::Backend', 'Kernel::System::DynamicFieldValue', 'Kernel::System::Log', + 'Kernel::System::Web::FormCache', 'Kernel::System::Web::Request', ); @@ -640,8 +642,10 @@ sub GetFieldState { Behavior => 'IsACLReducible', ); + my $ReferenceID = $DFParam->{ $DynamicFieldConfig->{Config}{ReferenceDFName} } ? $DFParam->{ $DynamicFieldConfig->{Config}{ReferenceDFName} }[0] : undef; + # get the current value of the referenced attribute field if an object is referenced - if ( $DFParam->{ $DynamicFieldConfig->{Config}{ReferenceDFName} } ) { + if ($ReferenceID) { $AttributeFieldValue = $Self->ValueGet( DynamicFieldConfig => $DynamicFieldConfig, @@ -664,22 +668,39 @@ sub GetFieldState { ) ) { - # if this field is non ACL reducible, set the field values - if ( !$IsACLReducible ) { - return ( - NewValue => $AttributeFieldValue, - ); + my $ReferenceDFName = $DynamicFieldConfig->{Config}{ReferenceDFName}; + + # if the value would change, we need to verify that the user is really allowed + # to access the provided referenced object via this form + # this is the case if either the referenced object was shown via a search (1) + # or is currently stored for the edited ticket/ci/... (2) + my $LastSearchResults = $Kernel::OM->Get('Kernel::System::Web::FormCache')->GetFormData( + LayoutObject => $Kernel::OM->Get('Kernel::Output::HTML::Layout'), + Key => 'PossibleValues_' . $ReferenceDFName, + ); + + my $Allowed = 0; + if ($LastSearchResults) { + + # if a search has already been performed for this form id + $Allowed = ( grep { $_ eq $ReferenceID } $LastSearchResults->@* ) ? 1 : 0; + } + else { + # if no search has been performed yet, the database value for the referenced object is also valid + # TODO } - $Return{NewValue} = $AttributeFieldValue; + if ($Allowed) { + $Return{NewValue} = $AttributeFieldValue; - # already write the new value to DFParam, for possible values check further down - $DFParam->{"DynamicField_$DynamicFieldConfig->{Name}"} = $AttributeFieldValue; - } - else { - return () if !$IsACLReducible; + # already write the new value to DFParam, for possible values check further down + $DFParam->{"DynamicField_$DynamicFieldConfig->{Name}"} = $AttributeFieldValue; + } } + # if this field is non ACL reducible, set the field values + return %Return if !$IsACLReducible; + # get possible values if ACLReducible # this is what the FieldRestrictions object would do for other fields my $PossibleValues = $Self->PossibleValuesGet( diff --git a/Kernel/System/Web/FormCache.pm b/Kernel/System/Web/FormCache.pm new file mode 100644 index 0000000000..a509c5097d --- /dev/null +++ b/Kernel/System/Web/FormCache.pm @@ -0,0 +1,372 @@ +# -- +# OTOBO is a web-based ticketing system for service organisations. +# -- +# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/ +# Copyright (C) 2019-2024 Rother OSS GmbH, https://otobo.de/ +# -- +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later version. +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# -- + +package Kernel::System::Web::FormCache; + +use strict; +use warnings; +use utf8; + +# core modules +use MIME::Base64 qw(decode_base64 encode_base64); + +# CPAN modules + +# OTOBO modules +use Kernel::System::VariableCheck qw(IsHashRefWithData); + +our @ObjectDependencies = ( + 'Kernel::Config', + 'Kernel::System::DB', + 'Kernel::System::Encode', + 'Kernel::System::Log', + 'Kernel::System::Storable', + 'Kernel::System::Web::UploadCache', +); + +=head1 NAME + +Kernel::System::Web::FormCache - a cache which stores relevant form data + +=head1 DESCRIPTION + +All form data which has to be stored server side, except the upload cache. + +=head1 PUBLIC INTERFACE + +=head2 new() + +Don't use the constructor directly, use the ObjectManager instead: + + my $FormCacheObject = $Kernel::OM->Get('Kernel::System::Web::FormCache'); + +=cut + +sub new { + my ( $Type, %Param ) = @_; + + # allocate new hash for object + my $Self = {}; + bless( $Self, $Type ); + + return $Self; +} + +=head2 PrepareFormID() + +get the or create a Form ID and store it in the LayoutObject + + my $FormID = $FormCacheObject->PrepareFormID( + LayoutObject => $LayoutObject, + ParamObject => $ParamObject, + ); + +=cut + +sub PrepareFormID { + my ( $Self, %Param ) = @_; + + # check required params + for my $Needed (qw/LayoutObject ParamObject/) { + if ( !$Param{$Needed} ) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => "Need $Needed!", + ); + + return; + } + } + + # get form id or create a new one + my $FormID = $Param{ParamObject}->GetParam( Param => 'FormID' ) || $Self->FormIDCreate(); + + # store the FormID in the provided LayoutObject + $Param{LayoutObject}{FormID} = $FormID; + + return $FormID; +} + +=head2 GetFormData() + +get data for a specific Form ID provided by the LayoutObject + + $FormCacheObject->GetFormData( + LayoutObject => $LayoutObject, # must include SessionID and FormID + Key => 'PossibleValues_DynamicField_Name', # optional - return data of a specific key + ); + +=cut + +sub GetFormData { + my ( $Self, %Param ) = @_; + + # check required params + for my $Needed (qw/LayoutObject/) { + if ( !$Param{$Needed} ) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => "Need $Needed!", + ); + + return; + } + } + + if ( !$Param{LayoutObject}{FormID} || !$Param{LayoutObject}{SessionID} ) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => "Need FormID and SessionID in the LayoutObject!", + ); + + return; + } + + my $SessionID = $Param{LayoutObject}{SessionID}; + my $FormID = $Param{LayoutObject}{FormID}; + + if ( $Self->{Cache}{$SessionID}{$FormID} ) { + + return $Self->{Cache}{$SessionID}{$FormID}{ $Param{Key} } if $Param{Key}; + return $Self->{Cache}{$SessionID}{$FormID}; + } + + my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); + my $EncodeObject = $Kernel::OM->Get('Kernel::System::Encode'); + my $StorableObject = $Kernel::OM->Get('Kernel::System::Storable'); + + $DBObject->Prepare( + SQL => 'SELECT cache_key, cache_value, serialized FROM form_cache WHERE session_id = ? AND form_id = ?', + Bind => [ \$SessionID, \$FormID ], + ); + + my %FormData; + + ROW: + while ( my @Row = $DBObject->FetchrowArray() ) { + + # unserialized values can be handled directly + if ( !$Row[2] ) { + $FormData{ $Row[0] } = $Row[1]; + + next ROW; + } + + # deserialize the value + my $Value = eval { + $StorableObject->Deserialize( Data => decode_base64( $Row[1] ) ); + }; + + $EncodeObject->EncodeOutput( \$Value ); + + $FormData{ $Row[0] } = $Value; + } + + $Self->{Cache}{$SessionID}{$FormID} = \%FormData; + + return $FormData{ $Param{Key} } if $Param{Key}; + return \%FormData; +} + +=head2 SetFormData() + +set data for a specific Form ID provided by the LayoutObject + + $FormCacheObject->SetFormData( + LayoutObject => $LayoutObject, # must include SessionID + FormID => 123321, # optional, if not provided, directly, has to be included in the LayoutObject + Key => 'DynamicField_Name_PossibleValues', + Value => { ... }, # will delete data if undef or not provided + ); + +=cut + +sub SetFormData { + my ( $Self, %Param ) = @_; + + # check required params + for my $Needed (qw/LayoutObject Key/) { + if ( !$Param{$Needed} ) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => "Need $Needed!", + ); + + return; + } + } + + my $SessionID = $Param{LayoutObject}{SessionID}; + my $FormID = $Param{FormID} || $Param{LayoutObject}{FormID}; + + if ( !$FormID || !$SessionID ) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => "Need FormID and SessionID in the LayoutObject!", + ); + + return; + } + + $Self->{Cache}{$SessionID}{$FormID}{ $Param{Key} } = $Param{Value}; + $Self->{CacheUpdate}{$SessionID}{$FormID}{ $Param{Key} } = 1; + + return 1; +} + +=head2 FormIDCreate() + +create a new Form ID - usually this will be called by PrepareFormID() rather than directly + + my $FormID = $FormCacheObject->FormIDCreate(); + +=cut + +sub FormIDCreate { + + # return a new form id - this is also used by Web::UploadCache + return time() . '.' . rand(12341241); +} + +=head2 FormIDRemove() + +remove all data for a provided Form ID, including the Web::UploadCache + + $FormCacheObject->FormIDRemove( + FormID => 123456, # at least one of the following is required + SessionID => 654321, + LayoutObject => $LayoutObject, + ); + +=cut + +sub FormIDRemove { + my ( $Self, %Param ) = @_; + + if ( $Param{LayoutObject} ) { + $Param{SessionID} = $Param{LayoutObject}{SessionID} || $Param{SessionID}; + $Param{FormID} = $Param{LayoutObject}{FormID} || $Param{FormID}; + } + + if ( !$Param{SessionID} && !$Param{FormID} ) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => "Need at least one of form or session id!", + ); + + return; + } + + my @SQLWhere; + my @Bind; + + if ( $Param{SessionID} ) { + push @SQLWhere, 'session_id = ?'; + push @Bind, \$Param{SessionID}; + } + + if ( $Param{FormID} ) { + push @SQLWhere, 'form_id = ?'; + push @Bind, \$Param{FormID}; + } + + my $Success = $Kernel::OM->Get('Kernel::System::DB')->Do( + SQL => 'DELETE FROM form_cache WHERE' . join( ' AND ', @SQLWhere ), + Bind => \@Bind, + ); + + # clear the upload cache + return $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDRemove(%Param) && $Success; +} + +=head2 FormIDCleanUp() + +Remove all expired form cache data, _not_ including Web::UploadCache + + $FormCacheObject->FormIDCleanUp(); + +=cut + +sub FormIDCleanUp { + my ( $Self, %Param ) = @_; + + # TODO: delete from where create_time < ..., use sysconfig setting for storage time + + return 1; +} + +sub DESTROY { + my ( $Self, %Param ) = @_; + + return 1 if !$Self->{CacheUpdate}; + + # get objects + my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); + my $StorableObject = $Kernel::OM->Get('Kernel::System::Storable'); + + SESSIONID: + for my $SessionID ( keys $Self->{CacheUpdate}->%* ) { + next SESSIONID if !IsHashRefWithData( $Self->{CacheUpdate}{$SessionID} ); + + FORMID: + for my $FormID ( keys $Self->{CacheUpdate}{$SessionID}->%* ) { + next FORMID if !IsHashRefWithData( $Self->{CacheUpdate}{$SessionID}{$FormID} ); + + # extract session data to update + my $Data = $Self->{Cache}{$SessionID}{$FormID}; + + my @KeysToDelete; + my %DataToStore; + + KEY: + for my $Key ( $Self->{CacheUpdate}{$SessionID}{$FormID}->%* ) { + push @KeysToDelete, $Key; + + # undefined values will just be deleted + next KEY if !defined $Data->{$Key}; + + my $Serialized = 0; + my $Value = $Data->{$Key}; + if ( ref $Value ) { + $Value = encode_base64( + $StorableObject->Serialize( Data => $Value ) + ); + $Serialized = 1; + } + + push $DataToStore{Keys}->@*, $Key; + push $DataToStore{Values}->@*, $Value; + push $DataToStore{Serialized}->@*, $Serialized; + } + + # delete all changed keys + $DBObject->DoArray( + SQL => 'DELETE FROM form_cache WHERE session_id = ? AND form_id = ? AND cache_key = ?', + Bind => [ $SessionID, $FormID, \@KeysToDelete ], + ); + + # store all new data + $DBObject->DoArray( + SQL => 'INSERT INTO form_cache (session_id, form_id, cache_key, cache_value, serialized, create_time) VALUES (?, ?, ?, ?, ?, current_timestamp)', + Bind => [ $SessionID, $FormID, $DataToStore{Keys}, $DataToStore{Values}, $DataToStore{Serialized} ], + ); + } + } + + return 1; +} + +1; diff --git a/Kernel/System/Web/UploadCache.pm b/Kernel/System/Web/UploadCache.pm index cb222f6ff5..dfca3826fd 100644 --- a/Kernel/System/Web/UploadCache.pm +++ b/Kernel/System/Web/UploadCache.pm @@ -21,6 +21,7 @@ use warnings; our @ObjectDependencies = ( 'Kernel::Config', + 'Kernel::System::Web::FormCache', ); =head1 NAME @@ -60,7 +61,7 @@ sub new { =head2 FormIDCreate() -create a new Form ID +create a new Form ID - this method was moved to Web::FormCache my $FormID = $UploadCacheObject->FormIDCreate(); @@ -69,7 +70,7 @@ create a new Form ID sub FormIDCreate { my ( $Self, %Param ) = @_; - return $Self->{Backend}->FormIDCreate(%Param); + return $Kernel::OM->Get('Kernel::System::Web::FormCache')->FormIDCreate(%Param); } =head2 FormIDRemove() diff --git a/Kernel/System/Web/UploadCache/DB.pm b/Kernel/System/Web/UploadCache/DB.pm index 8d7fed8554..4f237754b6 100644 --- a/Kernel/System/Web/UploadCache/DB.pm +++ b/Kernel/System/Web/UploadCache/DB.pm @@ -44,13 +44,6 @@ sub new { return $Self; } -sub FormIDCreate { - my ( $Self, %Param ) = @_; - - # return requested form id - return time() . '.' . rand(12341241); -} - sub FormIDRemove { my ( $Self, %Param ) = @_; diff --git a/Kernel/System/Web/UploadCache/FS.pm b/Kernel/System/Web/UploadCache/FS.pm index 7584363d8e..1fd60e8aed 100644 --- a/Kernel/System/Web/UploadCache/FS.pm +++ b/Kernel/System/Web/UploadCache/FS.pm @@ -41,13 +41,6 @@ sub new { return $Self; } -sub FormIDCreate { - my ( $Self, %Param ) = @_; - - # return requested form id - return time() . '.' . rand(12341241); -} - sub FormIDRemove { my ( $Self, %Param ) = @_; diff --git a/scripts/DBUpdateTo11_0.pm b/scripts/DBUpdateTo11_0.pm index 9795e71621..a0466703fa 100644 --- a/scripts/DBUpdateTo11_0.pm +++ b/scripts/DBUpdateTo11_0.pm @@ -76,6 +76,10 @@ sub Run { Name => 'Add translation_item table.', Module => 'DBAddTranslationItem', }, + { + Name => 'Add form_cache table.', + Module => 'DBAddFormCacheTable', + }, ); TASK: diff --git a/scripts/DBUpdateTo11_0/DBAddFormCacheTable.pm b/scripts/DBUpdateTo11_0/DBAddFormCacheTable.pm new file mode 100644 index 0000000000..23c1e0cc75 --- /dev/null +++ b/scripts/DBUpdateTo11_0/DBAddFormCacheTable.pm @@ -0,0 +1,62 @@ +# -- +# OTOBO is a web-based ticketing system for service organisations. +# -- +# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/ +# Copyright (C) 2019-2024 Rother OSS GmbH, https://otobo.de/ +# -- +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later version. +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# -- + +package scripts::DBUpdateTo11_0::DBAddFormCacheTable; + +use strict; +use warnings; + +our @ObjectDependencies = ( + 'Kernel::System::DB', + 'Kernel::System::Log', +); + +=head1 NAME + +scripts::DBUpdateTo11_0::DBAddFormCacheTable + +=cut + +use parent qw(scripts::DBUpdateTo11_0::Base); + +sub Run { + my ( $Self, %Param ) = @_; + + my @XMLStrings = ( + + # form_cache + ' + + + + + + + + + + +
' + ); + + return if !$Self->ExecuteXMLDBArray( + XMLArray => \@XMLStrings, + ); + + return 1; +} + +1; diff --git a/scripts/database/otobo-schema.xml b/scripts/database/otobo-schema.xml index 743bf9de1a..56e6958481 100644 --- a/scripts/database/otobo-schema.xml +++ b/scripts/database/otobo-schema.xml @@ -1477,7 +1477,7 @@ - + @@ -1644,6 +1644,20 @@ + + + + + + + + + + + + +
+