1# -- 2# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/ 3# -- 4# This software comes with ABSOLUTELY NO WARRANTY. For details, see 5# the enclosed file COPYING for license information (GPL). If you 6# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt. 7# -- 8 9package Kernel::Modules::CustomerTicketMessage; 10 11use strict; 12use warnings; 13 14our $ObjectManagerDisabled = 1; 15 16use Kernel::System::VariableCheck qw(:all); 17use Kernel::Language qw(Translatable); 18 19sub new { 20 my ( $Type, %Param ) = @_; 21 22 # allocate new hash for object 23 my $Self = {%Param}; 24 bless( $Self, $Type ); 25 26 # get form id 27 $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'FormID' ); 28 29 # create form id 30 if ( !$Self->{FormID} ) { 31 $Self->{FormID} = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate(); 32 } 33 34 return $Self; 35} 36 37sub Run { 38 my ( $Self, %Param ) = @_; 39 40 # get params 41 my %GetParam; 42 my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); 43 for my $Key (qw( Subject Body PriorityID TypeID ServiceID SLAID Expand Dest FromChatID)) { 44 $GetParam{$Key} = $ParamObject->GetParam( Param => $Key ); 45 } 46 47 # ACL compatibility translation 48 my %ACLCompatGetParam; 49 $ACLCompatGetParam{OwnerID} = $GetParam{NewUserID}; 50 51 # get Dynamic fields from ParamObject 52 my %DynamicFieldValues; 53 54 my $Config = $Kernel::OM->Get('Kernel::Config')->Get("Ticket::Frontend::$Self->{Action}"); 55 56 # get the dynamic fields for this screen 57 my $DynamicField = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet( 58 Valid => 1, 59 ObjectType => [ 'Ticket', 'Article' ], 60 FieldFilter => $Config->{DynamicField} || {}, 61 ); 62 63 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 64 my $BackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend'); 65 66 # reduce the dynamic fields to only the ones that are designed for customer interface 67 my @CustomerDynamicFields; 68 DYNAMICFIELD: 69 for my $DynamicFieldConfig ( @{$DynamicField} ) { 70 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 71 72 my $IsCustomerInterfaceCapable = $BackendObject->HasBehavior( 73 DynamicFieldConfig => $DynamicFieldConfig, 74 Behavior => 'IsCustomerInterfaceCapable', 75 ); 76 next DYNAMICFIELD if !$IsCustomerInterfaceCapable; 77 78 push @CustomerDynamicFields, $DynamicFieldConfig; 79 } 80 $DynamicField = \@CustomerDynamicFields; 81 82 # cycle trough the activated Dynamic Fields for this screen 83 DYNAMICFIELD: 84 for my $DynamicFieldConfig ( @{$DynamicField} ) { 85 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 86 87 # extract the dynamic field value from the web request 88 $DynamicFieldValues{ $DynamicFieldConfig->{Name} } = 89 $BackendObject->EditFieldValueGet( 90 DynamicFieldConfig => $DynamicFieldConfig, 91 ParamObject => $ParamObject, 92 LayoutObject => $LayoutObject, 93 ); 94 } 95 96 # convert dynamic field values into a structure for ACLs 97 my %DynamicFieldACLParameters; 98 DYNAMICFIELD: 99 for my $DynamicField ( sort keys %DynamicFieldValues ) { 100 next DYNAMICFIELD if !$DynamicField; 101 next DYNAMICFIELD if !$DynamicFieldValues{$DynamicField}; 102 103 $DynamicFieldACLParameters{ 'DynamicField_' . $DynamicField } = $DynamicFieldValues{$DynamicField}; 104 } 105 $GetParam{DynamicField} = \%DynamicFieldACLParameters; 106 107 my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket'); 108 my $QueueObject = $Kernel::OM->Get('Kernel::System::Queue'); 109 my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); 110 111 if ( $GetParam{FromChatID} ) { 112 if ( !$ConfigObject->Get('ChatEngine::Active') ) { 113 return $LayoutObject->FatalError( 114 Message => Translatable('Chat is not active.'), 115 ); 116 } 117 118 # Check chat participant 119 my %ChatParticipant = $Kernel::OM->Get('Kernel::System::Chat')->ChatParticipantCheck( 120 ChatID => $GetParam{FromChatID}, 121 ChatterType => 'Customer', 122 ChatterID => $Self->{UserID}, 123 ); 124 125 if ( !%ChatParticipant ) { 126 return $LayoutObject->FatalError( 127 Message => Translatable('No permission.'), 128 ); 129 } 130 } 131 132 if ( !$Self->{Subaction} ) { 133 134 #Get default Queue ID if none is set 135 my $QueueDefaultID; 136 if ( !$GetParam{Dest} && !$Param{ToSelected} ) { 137 my $QueueDefault = $Config->{'QueueDefault'} || ''; 138 if ($QueueDefault) { 139 $QueueDefaultID = $QueueObject->QueueLookup( Queue => $QueueDefault ); 140 if ($QueueDefaultID) { 141 $Param{ToSelected} = $QueueDefaultID . '||' . $QueueDefault; 142 } 143 $ACLCompatGetParam{QueueID} = $QueueDefaultID; 144 } 145 146 # warn if there is no (valid) default queue and the customer can't select one 147 elsif ( !$Config->{'Queue'} ) { 148 $LayoutObject->CustomerFatalError( 149 Message => $LayoutObject->{LanguageObject} 150 ->Translate( 'Check SysConfig setting for %s::QueueDefault.', $Self->{Action} ), 151 Comment => Translatable('Please contact the administrator.'), 152 ); 153 return; 154 } 155 } 156 elsif ( $GetParam{Dest} ) { 157 my ( $QueueIDParam, $QueueParam ) = split( /\|\|/, $GetParam{Dest} ); 158 my $QueueIDLookup = $QueueObject->QueueLookup( Queue => $QueueParam ); 159 if ( $QueueIDLookup && $QueueIDLookup eq $QueueIDParam ) { 160 my $CustomerPanelOwnSelection = $Kernel::OM->Get('Kernel::Config')->Get('CustomerPanelOwnSelection'); 161 if ( %{ $CustomerPanelOwnSelection // {} } ) { 162 $Param{ToSelected} = $QueueIDParam . '||' . $CustomerPanelOwnSelection->{$QueueParam}; 163 } 164 else { 165 $Param{ToSelected} = $GetParam{Dest}; 166 } 167 $ACLCompatGetParam{QueueID} = $QueueIDLookup; 168 } 169 } 170 171 # create html strings for all dynamic fields 172 my %DynamicFieldHTML; 173 174 # cycle trough the activated Dynamic Fields for this screen 175 DYNAMICFIELD: 176 for my $DynamicFieldConfig ( @{$DynamicField} ) { 177 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 178 179 my $PossibleValuesFilter; 180 181 my $IsACLReducible = $BackendObject->HasBehavior( 182 DynamicFieldConfig => $DynamicFieldConfig, 183 Behavior => 'IsACLReducible', 184 ); 185 186 if ($IsACLReducible) { 187 188 # get PossibleValues 189 my $PossibleValues = $BackendObject->PossibleValuesGet( 190 DynamicFieldConfig => $DynamicFieldConfig, 191 ); 192 193 # check if field has PossibleValues property in its configuration 194 if ( IsHashRefWithData($PossibleValues) ) { 195 196 # convert possible values key => value to key => key for ACLs using a Hash slice 197 my %AclData = %{$PossibleValues}; 198 @AclData{ keys %AclData } = keys %AclData; 199 200 # set possible values filter from ACLs 201 my $ACL = $TicketObject->TicketAcl( 202 %GetParam, 203 %ACLCompatGetParam, 204 Action => $Self->{Action}, 205 TicketID => $Self->{TicketID}, 206 ReturnType => 'Ticket', 207 ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name}, 208 Data => \%AclData, 209 CustomerUserID => $Self->{UserID}, 210 ); 211 if ($ACL) { 212 my %Filter = $TicketObject->TicketAclData(); 213 214 # convert Filer key => key back to key => value using map 215 %{$PossibleValuesFilter} = map { $_ => $PossibleValues->{$_} } 216 keys %Filter; 217 } 218 } 219 } 220 221 # get field html 222 $DynamicFieldHTML{ $DynamicFieldConfig->{Name} } = 223 $BackendObject->EditFieldRender( 224 DynamicFieldConfig => $DynamicFieldConfig, 225 PossibleValuesFilter => $PossibleValuesFilter, 226 Mandatory => 227 $Config->{DynamicField}->{ $DynamicFieldConfig->{Name} } == 2, 228 LayoutObject => $LayoutObject, 229 ParamObject => $ParamObject, 230 AJAXUpdate => 1, 231 UpdatableFields => $Self->_GetFieldsToUpdate(), 232 ); 233 } 234 235 # print form ... 236 my $Output = $LayoutObject->CustomerHeader(); 237 $Output .= $LayoutObject->CustomerNavigationBar(); 238 $Output .= $Self->_MaskNew( 239 %GetParam, 240 %ACLCompatGetParam, 241 ToSelected => $Param{ToSelected}, 242 DynamicFieldHTML => \%DynamicFieldHTML, 243 FromChatID => $GetParam{FromChatID} || '', 244 ); 245 $Output .= $LayoutObject->CustomerFooter(); 246 return $Output; 247 } 248 elsif ( $Self->{Subaction} eq 'StoreNew' ) { 249 250 my $ArticleObject = $Kernel::OM->Get('Kernel::System::Ticket::Article'); 251 my $ArticleBackendObject = $ArticleObject->BackendForChannel( ChannelName => 'Internal' ); 252 253 my $NextScreen = $Config->{NextScreenAfterNewTicket}; 254 my %Error; 255 256 # get destination queue 257 my $Dest = $ParamObject->GetParam( Param => 'Dest' ) || ''; 258 my ( $NewQueueID, $To ) = split( /\|\|/, $Dest ); 259 if ( !$To ) { 260 $NewQueueID = $ParamObject->GetParam( Param => 'NewQueueID' ) || ''; 261 $To = 'System'; 262 } 263 264 # fallback, if no destination is given 265 if ( !$NewQueueID ) { 266 my $Queue = $ParamObject->GetParam( Param => 'Queue' ) 267 || $Config->{'QueueDefault'} 268 || ''; 269 if ($Queue) { 270 my $QueueID = $QueueObject->QueueLookup( Queue => $Queue ); 271 $NewQueueID = $QueueID; 272 $To = $Queue; 273 } 274 } 275 276 $GetParam{NewQueueID} = $NewQueueID; 277 278 # use default if ticket type is not available in screen but activated on system 279 if ( $ConfigObject->Get('Ticket::Type') && !$Config->{'TicketType'} ) { 280 my %TypeList = reverse $TicketObject->TicketTypeList( 281 %Param, 282 Action => $Self->{Action}, 283 CustomerUserID => $Self->{UserID}, 284 ); 285 $GetParam{TypeID} = $TypeList{ $Config->{'TicketTypeDefault'} }; 286 if ( !$GetParam{TypeID} ) { 287 $LayoutObject->CustomerFatalError( 288 Message => 289 $LayoutObject->{LanguageObject} 290 ->Translate( 'Check SysConfig setting for %s::TicketTypeDefault.', $Self->{Action} ), 291 Comment => Translatable('Please contact the administrator.'), 292 ); 293 return; 294 } 295 } 296 297 my $UploadCacheObject = $Kernel::OM->Get('Kernel::System::Web::UploadCache'); 298 299 # get all attachments meta data 300 my @Attachments = $UploadCacheObject->FormIDGetAllFilesMeta( 301 FormID => $Self->{FormID}, 302 ); 303 304 # create html strings for all dynamic fields 305 my %DynamicFieldHTML; 306 307 # cycle trough the activated Dynamic Fields for this screen 308 DYNAMICFIELD: 309 for my $DynamicFieldConfig ( @{$DynamicField} ) { 310 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 311 312 my $PossibleValuesFilter; 313 314 my $IsACLReducible = $BackendObject->HasBehavior( 315 DynamicFieldConfig => $DynamicFieldConfig, 316 Behavior => 'IsACLReducible', 317 ); 318 319 if ($IsACLReducible) { 320 321 # get PossibleValues 322 my $PossibleValues = $BackendObject->PossibleValuesGet( 323 DynamicFieldConfig => $DynamicFieldConfig, 324 ); 325 326 # check if field has PossibleValues property in its configuration 327 if ( IsHashRefWithData($PossibleValues) ) { 328 329 # convert possible values key => value to key => key for ACLs using a Hash slice 330 my %AclData = %{$PossibleValues}; 331 @AclData{ keys %AclData } = keys %AclData; 332 333 # set possible values filter from ACLs 334 my $ACL = $TicketObject->TicketAcl( 335 %GetParam, 336 Action => $Self->{Action}, 337 TicketID => $Self->{TicketID}, 338 ReturnType => 'Ticket', 339 ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name}, 340 Data => \%AclData, 341 CustomerUserID => $Self->{UserID}, 342 ); 343 if ($ACL) { 344 my %Filter = $TicketObject->TicketAclData(); 345 346 # convert Filer key => key back to key => value using map 347 %{$PossibleValuesFilter} = map { $_ => $PossibleValues->{$_} } 348 keys %Filter; 349 } 350 } 351 } 352 353 my $ValidationResult; 354 355 # do not validate on attachment upload or GetParam Expand 356 if ( !$GetParam{Expand} ) { 357 358 $ValidationResult = $BackendObject->EditFieldValueValidate( 359 DynamicFieldConfig => $DynamicFieldConfig, 360 PossibleValuesFilter => $PossibleValuesFilter, 361 ParamObject => $ParamObject, 362 Mandatory => 363 $Config->{DynamicField}->{ $DynamicFieldConfig->{Name} } == 2, 364 ); 365 366 if ( !IsHashRefWithData($ValidationResult) ) { 367 my $Output = $LayoutObject->CustomerHeader( 368 Title => Translatable('Error'), 369 ); 370 $Output .= $LayoutObject->CustomerError( 371 Message => 372 $LayoutObject->{LanguageObject} 373 ->Translate( 'Could not perform validation on field %s!', $DynamicFieldConfig->{Label} ), 374 Comment => Translatable('Please contact the administrator.'), 375 ); 376 $Output .= $LayoutObject->CustomerFooter(); 377 return $Output; 378 } 379 380 # propagate validation error to the Error variable to be detected by the frontend 381 if ( $ValidationResult->{ServerError} ) { 382 $Error{ $DynamicFieldConfig->{Name} } = ' ServerError'; 383 } 384 } 385 386 # get field html 387 $DynamicFieldHTML{ $DynamicFieldConfig->{Name} } = 388 $BackendObject->EditFieldRender( 389 DynamicFieldConfig => $DynamicFieldConfig, 390 PossibleValuesFilter => $PossibleValuesFilter, 391 Mandatory => 392 $Config->{DynamicField}->{ $DynamicFieldConfig->{Name} } == 2, 393 ServerError => $ValidationResult->{ServerError} || '', 394 ErrorMessage => $ValidationResult->{ErrorMessage} || '', 395 LayoutObject => $LayoutObject, 396 ParamObject => $ParamObject, 397 AJAXUpdate => 1, 398 UpdatableFields => $Self->_GetFieldsToUpdate(), 399 ); 400 } 401 402 # rewrap body if no rich text is used 403 if ( $GetParam{Body} && !$LayoutObject->{BrowserRichText} ) { 404 $GetParam{Body} = $LayoutObject->WrapPlainText( 405 MaxCharacters => $ConfigObject->Get('Ticket::Frontend::TextAreaNote'), 406 PlainText => $GetParam{Body}, 407 ); 408 } 409 410 # if there is FromChatID, get related messages and prepend them to body 411 if ( $GetParam{FromChatID} ) { 412 my @ChatMessages = $Kernel::OM->Get('Kernel::System::Chat')->ChatMessageList( 413 ChatID => $GetParam{FromChatID}, 414 ); 415 416 for my $Message (@ChatMessages) { 417 $Message->{MessageText} = $LayoutObject->Ascii2Html( 418 Text => $Message->{MessageText}, 419 LinkFeature => 1, 420 ); 421 } 422 } 423 424 # check queue 425 if ( !$NewQueueID && !$GetParam{Expand} ) { 426 $Error{QueueInvalid} = 'ServerError'; 427 } 428 429 # prevent tamper with (Queue/Dest), see bug#9408 430 if ($NewQueueID) { 431 432 # get the original list of queues to display 433 my $Tos = $Self->_GetTos( 434 %GetParam, 435 %ACLCompatGetParam, 436 QueueID => $NewQueueID, 437 ); 438 439 # check if current selected QueueID exists in the list of queues,\ 440 # otherwise rise an error 441 if ( !$Tos->{$NewQueueID} ) { 442 443 # Check if queue is accessible by customer user (see bug#14886). 444 if ( $ConfigObject->Get('Ticket::Frontend::CustomerTicketMessage')->{Queue} == 0 ) { 445 $Error{QueueDisabled} = 'ServerError'; 446 } 447 else { 448 $Error{QueueInvalid} = 'ServerError'; 449 } 450 } 451 452 # set the correct queue name in $To if it was altered 453 if ( $To ne $Tos->{$NewQueueID} ) { 454 $To = $Tos->{$NewQueueID}; 455 } 456 } 457 458 # check subject 459 if ( !$GetParam{Subject} ) { 460 $Error{SubjectInvalid} = 'ServerError'; 461 } 462 463 # check body 464 if ( !$GetParam{Body} ) { 465 $Error{BodyInvalid} = 'ServerError'; 466 } 467 if ( $GetParam{Expand} ) { 468 %Error = (); 469 $Error{Expand} = 1; 470 } 471 472 # check mandatory service 473 if ( 474 $ConfigObject->Get('Ticket::Service') 475 && $Config->{Service} 476 && $Config->{ServiceMandatory} 477 && !$GetParam{ServiceID} 478 ) 479 { 480 $Error{'ServiceIDInvalid'} = 'ServerError'; 481 } 482 483 # check mandatory sla 484 if ( 485 $ConfigObject->Get('Ticket::Service') 486 && $Config->{SLA} 487 && $Config->{SLAMandatory} 488 && !$GetParam{SLAID} 489 ) 490 { 491 $Error{'SLAIDInvalid'} = 'ServerError'; 492 } 493 494 # check type 495 if ( 496 $ConfigObject->Get('Ticket::Type') 497 && !$GetParam{TypeID} 498 && !$GetParam{Expand} 499 ) 500 { 501 $Error{TypeIDInvalid} = 'ServerError'; 502 } 503 504 if (%Error) { 505 506 # html output 507 my $Output = $LayoutObject->CustomerHeader(); 508 if ( $Error{QueueDisabled} ) { 509 $Output .= $LayoutObject->Notify( 510 Priority => 'Error', 511 Info => Translatable("You don't have sufficient permissions for ticket creation in default queue."), 512 ); 513 } 514 $Output .= $LayoutObject->CustomerNavigationBar(); 515 $Output .= $Self->_MaskNew( 516 Attachments => \@Attachments, 517 %GetParam, 518 ToSelected => $Dest, 519 QueueID => $NewQueueID, 520 DynamicFieldHTML => \%DynamicFieldHTML, 521 Errors => \%Error, 522 ); 523 $Output .= $LayoutObject->CustomerFooter(); 524 return $Output; 525 } 526 527 # challenge token check for write action 528 $LayoutObject->ChallengeTokenCheck( Type => 'Customer' ); 529 530 # if customer is not allowed to set priority, set it to default 531 if ( !$Config->{Priority} ) { 532 $GetParam{PriorityID} = ''; 533 $GetParam{Priority} = $Config->{PriorityDefault}; 534 } 535 536 # create new ticket, do db insert 537 my $TicketID = $TicketObject->TicketCreate( 538 QueueID => $NewQueueID, 539 TypeID => $GetParam{TypeID}, 540 ServiceID => $GetParam{ServiceID}, 541 SLAID => $GetParam{SLAID}, 542 Title => $GetParam{Subject}, 543 PriorityID => $GetParam{PriorityID}, 544 Priority => $GetParam{Priority}, 545 Lock => 'unlock', 546 State => $Config->{StateDefault}, 547 CustomerID => $Self->{UserCustomerID}, 548 CustomerUser => $Self->{UserLogin}, 549 OwnerID => $ConfigObject->Get('CustomerPanelUserID'), 550 UserID => $ConfigObject->Get('CustomerPanelUserID'), 551 ); 552 553 # set ticket dynamic fields 554 # cycle trough the activated Dynamic Fields for this screen 555 DYNAMICFIELD: 556 for my $DynamicFieldConfig ( @{$DynamicField} ) { 557 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 558 next DYNAMICFIELD if $DynamicFieldConfig->{ObjectType} ne 'Ticket'; 559 560 # set the value 561 my $Success = $BackendObject->ValueSet( 562 DynamicFieldConfig => $DynamicFieldConfig, 563 ObjectID => $TicketID, 564 Value => $DynamicFieldValues{ $DynamicFieldConfig->{Name} }, 565 UserID => $ConfigObject->Get('CustomerPanelUserID'), 566 ); 567 } 568 569 my $MimeType = 'text/plain'; 570 if ( $LayoutObject->{BrowserRichText} ) { 571 $MimeType = 'text/html'; 572 573 # verify html document 574 $GetParam{Body} = $LayoutObject->RichTextDocumentComplete( 575 String => $GetParam{Body}, 576 ); 577 } 578 579 my $PlainBody = $GetParam{Body}; 580 581 if ( $LayoutObject->{BrowserRichText} ) { 582 $PlainBody = $LayoutObject->RichText2Ascii( String => $GetParam{Body} ); 583 } 584 585 # create article 586 my $FullName = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerName( 587 UserLogin => $Self->{UserLogin}, 588 ); 589 my $From = "\"$FullName\" <$Self->{UserEmail}>"; 590 my $ArticleID = $ArticleBackendObject->ArticleCreate( 591 TicketID => $TicketID, 592 IsVisibleForCustomer => 1, 593 SenderType => $Config->{SenderType}, 594 From => $From, 595 To => $To, 596 Subject => $GetParam{Subject}, 597 Body => $GetParam{Body}, 598 MimeType => $MimeType, 599 Charset => $LayoutObject->{UserCharset}, 600 UserID => $ConfigObject->Get('CustomerPanelUserID'), 601 HistoryType => $Config->{HistoryType}, 602 HistoryComment => $Config->{HistoryComment} || '%%', 603 AutoResponseType => ( $ConfigObject->Get('AutoResponseForWebTickets') ) 604 ? 'auto reply' 605 : '', 606 OrigHeader => { 607 From => $From, 608 To => $Self->{UserLogin}, 609 Subject => $GetParam{Subject}, 610 Body => $PlainBody, 611 }, 612 Queue => $QueueObject->QueueLookup( QueueID => $NewQueueID ), 613 ); 614 615 if ( !$ArticleID ) { 616 my $Output = $LayoutObject->CustomerHeader( 617 Title => Translatable('Error'), 618 ); 619 $Output .= $LayoutObject->CustomerError(); 620 $Output .= $LayoutObject->CustomerFooter(); 621 return $Output; 622 } 623 624 # set article dynamic fields 625 # cycle trough the activated Dynamic Fields for this screen 626 DYNAMICFIELD: 627 for my $DynamicFieldConfig ( @{$DynamicField} ) { 628 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 629 next DYNAMICFIELD if $DynamicFieldConfig->{ObjectType} ne 'Article'; 630 631 # set the value 632 my $Success = $BackendObject->ValueSet( 633 DynamicFieldConfig => $DynamicFieldConfig, 634 ObjectID => $ArticleID, 635 Value => $DynamicFieldValues{ $DynamicFieldConfig->{Name} }, 636 UserID => $ConfigObject->Get('CustomerPanelUserID'), 637 ); 638 } 639 640 # Permissions check were done earlier 641 if ( $GetParam{FromChatID} ) { 642 my $ChatObject = $Kernel::OM->Get('Kernel::System::Chat'); 643 my %Chat = $ChatObject->ChatGet( 644 ChatID => $GetParam{FromChatID}, 645 ); 646 my @ChatMessageList = $ChatObject->ChatMessageList( 647 ChatID => $GetParam{FromChatID}, 648 ); 649 my $ChatArticleID; 650 651 if (@ChatMessageList) { 652 for my $Message (@ChatMessageList) { 653 $Message->{MessageText} = $LayoutObject->Ascii2Html( 654 Text => $Message->{MessageText}, 655 LinkFeature => 1, 656 ); 657 } 658 659 my $ArticleChatBackend = $ArticleObject->BackendForChannel( ChannelName => 'Chat' ); 660 661 $ChatArticleID = $ArticleChatBackend->ArticleCreate( 662 TicketID => $TicketID, 663 SenderType => $Config->{SenderType}, 664 ChatMessageList => \@ChatMessageList, 665 IsVisibleForCustomer => 1, 666 UserID => $ConfigObject->Get('CustomerPanelUserID'), 667 HistoryType => $Config->{HistoryType}, 668 HistoryComment => $Config->{HistoryComment} || '%%', 669 ); 670 } 671 if ($ChatArticleID) { 672 $ChatObject->ChatDelete( 673 ChatID => $GetParam{FromChatID}, 674 ); 675 } 676 } 677 678 # get pre loaded attachment 679 my @AttachmentData = $UploadCacheObject->FormIDGetAllFilesData( 680 FormID => $Self->{FormID}, 681 ); 682 683 # get submitted attachment 684 my %UploadStuff = $ParamObject->GetUploadAll( 685 Param => 'file_upload', 686 ); 687 if (%UploadStuff) { 688 push @AttachmentData, \%UploadStuff; 689 } 690 691 # write attachments 692 ATTACHMENT: 693 for my $Attachment (@AttachmentData) { 694 695 # skip, deleted not used inline images 696 my $ContentID = $Attachment->{ContentID}; 697 if ( 698 $ContentID 699 && ( $Attachment->{ContentType} =~ /image/i ) 700 && ( $Attachment->{Disposition} eq 'inline' ) 701 ) 702 { 703 my $ContentIDHTMLQuote = $LayoutObject->Ascii2Html( 704 Text => $ContentID, 705 ); 706 707 # workaround for link encode of rich text editor, see bug#5053 708 my $ContentIDLinkEncode = $LayoutObject->LinkEncode($ContentID); 709 $GetParam{Body} =~ s/(ContentID=)$ContentIDLinkEncode/$1$ContentID/g; 710 711 # ignore attachment if not linked in body 712 next ATTACHMENT if $GetParam{Body} !~ /(\Q$ContentIDHTMLQuote\E|\Q$ContentID\E)/i; 713 } 714 715 # write existing file to backend 716 $ArticleBackendObject->ArticleWriteAttachment( 717 %{$Attachment}, 718 ArticleID => $ArticleID, 719 UserID => $ConfigObject->Get('CustomerPanelUserID'), 720 ); 721 } 722 723 # remove pre submitted attachments 724 $UploadCacheObject->FormIDRemove( FormID => $Self->{FormID} ); 725 726 # redirect 727 return $LayoutObject->Redirect( 728 OP => "Action=$NextScreen;TicketID=$TicketID", 729 ); 730 } 731 732 elsif ( $Self->{Subaction} eq 'AJAXUpdate' ) { 733 734 my $Dest = $ParamObject->GetParam( Param => 'Dest' ) || ''; 735 my $CustomerUser = $Self->{UserID}; 736 my $QueueID = ''; 737 if ( $Dest =~ /^(\d{1,100})\|\|.+?$/ ) { 738 $QueueID = $1; 739 } 740 741 # get list type 742 my $TreeView = 0; 743 if ( $ConfigObject->Get('Ticket::Frontend::ListType') eq 'tree' ) { 744 $TreeView = 1; 745 } 746 747 my $Tos = $Self->_GetTos( 748 %GetParam, 749 %ACLCompatGetParam, 750 QueueID => $QueueID, 751 ); 752 753 my $NewTos; 754 755 if ($Tos) { 756 TOs: 757 for my $KeyTo ( sort keys %{$Tos} ) { 758 next TOs if ( $Tos->{$KeyTo} eq '-' ); 759 $NewTos->{"$KeyTo||$Tos->{$KeyTo}"} = $Tos->{$KeyTo}; 760 } 761 } 762 my $Priorities = $Self->_GetPriorities( 763 %GetParam, 764 %ACLCompatGetParam, 765 CustomerUserID => $CustomerUser || '', 766 QueueID => $QueueID || 1, 767 ); 768 my $Services = $Self->_GetServices( 769 %GetParam, 770 %ACLCompatGetParam, 771 CustomerUserID => $CustomerUser || '', 772 QueueID => $QueueID || 1, 773 ); 774 my $SLAs = $Self->_GetSLAs( 775 %GetParam, 776 %ACLCompatGetParam, 777 CustomerUserID => $CustomerUser || '', 778 QueueID => $QueueID || 1, 779 Services => $Services, 780 ); 781 my $Types = $Self->_GetTypes( 782 %GetParam, 783 %ACLCompatGetParam, 784 CustomerUserID => $CustomerUser || '', 785 QueueID => $QueueID || 1, 786 ); 787 788 # update Dynamic Fields Possible Values via AJAX 789 my @DynamicFieldAJAX; 790 791 # cycle trough the activated Dynamic Fields for this screen 792 DYNAMICFIELD: 793 for my $DynamicFieldConfig ( @{$DynamicField} ) { 794 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 795 796 my $IsACLReducible = $BackendObject->HasBehavior( 797 DynamicFieldConfig => $DynamicFieldConfig, 798 Behavior => 'IsACLReducible', 799 ); 800 next DYNAMICFIELD if !$IsACLReducible; 801 802 my $PossibleValues = $BackendObject->PossibleValuesGet( 803 DynamicFieldConfig => $DynamicFieldConfig, 804 ); 805 806 # convert possible values key => value to key => key for ACLs using a Hash slice 807 my %AclData = %{$PossibleValues}; 808 @AclData{ keys %AclData } = keys %AclData; 809 810 # set possible values filter from ACLs 811 my $ACL = $TicketObject->TicketAcl( 812 %GetParam, 813 %ACLCompatGetParam, 814 Action => $Self->{Action}, 815 QueueID => $QueueID || 0, 816 ReturnType => 'Ticket', 817 ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name}, 818 Data => \%AclData, 819 CustomerUserID => $Self->{UserID}, 820 ); 821 if ($ACL) { 822 my %Filter = $TicketObject->TicketAclData(); 823 824 # convert Filer key => key back to key => value using map 825 %{$PossibleValues} = map { $_ => $PossibleValues->{$_} } keys %Filter; 826 } 827 828 my $DataValues = $BackendObject->BuildSelectionDataGet( 829 DynamicFieldConfig => $DynamicFieldConfig, 830 PossibleValues => $PossibleValues, 831 Value => $DynamicFieldValues{ $DynamicFieldConfig->{Name} }, 832 ) || $PossibleValues; 833 834 # add dynamic field to the list of fields to update 835 push( 836 @DynamicFieldAJAX, 837 { 838 Name => 'DynamicField_' . $DynamicFieldConfig->{Name}, 839 Data => $DataValues, 840 SelectedID => $DynamicFieldValues{ $DynamicFieldConfig->{Name} }, 841 Translation => $DynamicFieldConfig->{Config}->{TranslatableValues} || 0, 842 Max => 100, 843 } 844 ); 845 } 846 847 my $JSON = $LayoutObject->BuildSelectionJSON( 848 [ 849 { 850 Name => 'Dest', 851 Data => $NewTos, 852 SelectedID => $Dest, 853 Translation => 0, 854 PossibleNone => 1, 855 TreeView => $TreeView, 856 Max => 100, 857 }, 858 { 859 Name => 'PriorityID', 860 Data => $Priorities, 861 SelectedID => $GetParam{PriorityID}, 862 Translation => 1, 863 Max => 100, 864 }, 865 { 866 Name => 'ServiceID', 867 Data => $Services, 868 SelectedID => $GetParam{ServiceID}, 869 PossibleNone => 1, 870 Translation => 0, 871 TreeView => $TreeView, 872 Max => 100, 873 }, 874 { 875 Name => 'SLAID', 876 Data => $SLAs, 877 SelectedID => $GetParam{SLAID}, 878 PossibleNone => 1, 879 Translation => 0, 880 Max => 100, 881 }, 882 { 883 Name => 'TypeID', 884 Data => $Types, 885 SelectedID => $GetParam{TypeID}, 886 PossibleNone => 1, 887 Translation => 0, 888 Max => 100, 889 }, 890 @DynamicFieldAJAX, 891 ], 892 ); 893 return $LayoutObject->Attachment( 894 ContentType => 'application/json; charset=' . $LayoutObject->{Charset}, 895 Content => $JSON, 896 Type => 'inline', 897 NoCache => 1, 898 ); 899 } 900 else { 901 return $LayoutObject->ErrorScreen( 902 Message => Translatable('No Subaction!'), 903 Comment => Translatable('Please contact the administrator.'), 904 ); 905 } 906 907} 908 909sub _GetPriorities { 910 my ( $Self, %Param ) = @_; 911 912 # get priority 913 my %Priorities; 914 if ( $Param{QueueID} || $Param{TicketID} ) { 915 %Priorities = $Kernel::OM->Get('Kernel::System::Ticket')->TicketPriorityList( 916 %Param, 917 Action => $Self->{Action}, 918 CustomerUserID => $Self->{UserID}, 919 ); 920 } 921 return \%Priorities; 922} 923 924sub _GetTypes { 925 my ( $Self, %Param ) = @_; 926 927 # get type 928 my %Type; 929 if ( $Param{QueueID} || $Param{TicketID} ) { 930 %Type = $Kernel::OM->Get('Kernel::System::Ticket')->TicketTypeList( 931 %Param, 932 Action => $Self->{Action}, 933 CustomerUserID => $Self->{UserID}, 934 ); 935 } 936 return \%Type; 937} 938 939sub _GetServices { 940 my ( $Self, %Param ) = @_; 941 942 # get service 943 my %Service; 944 945 # check needed 946 return \%Service if !$Param{QueueID} && !$Param{TicketID}; 947 948 # get options for default services for unknown customers 949 my $DefaultServiceUnknownCustomer 950 = $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Service::Default::UnknownCustomer'); 951 952 # get service list 953 if ( $Param{CustomerUserID} || $DefaultServiceUnknownCustomer ) { 954 %Service = $Kernel::OM->Get('Kernel::System::Ticket')->TicketServiceList( 955 %Param, 956 Action => $Self->{Action}, 957 CustomerUserID => $Self->{UserID}, 958 ); 959 } 960 return \%Service; 961} 962 963sub _GetSLAs { 964 my ( $Self, %Param ) = @_; 965 966 # get sla 967 my %SLA; 968 if ( $Param{ServiceID} && $Param{Services} && %{ $Param{Services} } ) { 969 if ( $Param{Services}->{ $Param{ServiceID} } ) { 970 %SLA = $Kernel::OM->Get('Kernel::System::Ticket')->TicketSLAList( 971 %Param, 972 Action => $Self->{Action}, 973 CustomerUserID => $Self->{UserID}, 974 ); 975 } 976 } 977 return \%SLA; 978} 979 980sub _GetTos { 981 my ( $Self, %Param ) = @_; 982 983 # check own selection 984 my %NewTos = ( '', '-' ); 985 my $Module = $Kernel::OM->Get('Kernel::Config')->Get('CustomerPanel::NewTicketQueueSelectionModule') 986 || 'Kernel::Output::HTML::CustomerNewTicket::QueueSelectionGeneric'; 987 if ( $Kernel::OM->Get('Kernel::System::Main')->Require($Module) ) { 988 my $Object = $Module->new( 989 %{$Self}, 990 SystemAddress => $Kernel::OM->Get('Kernel::System::SystemAddress'), 991 Debug => $Self->{Debug}, 992 ); 993 994 # log loaded module 995 if ( $Self->{Debug} && $Self->{Debug} > 1 ) { 996 $Kernel::OM->Get('Kernel::System::Log')->Log( 997 Priority => 'debug', 998 Message => "Module: $Module loaded!", 999 ); 1000 } 1001 %NewTos = ( 1002 $Object->Run( 1003 Env => $Self, 1004 ACLParams => \%Param 1005 ), 1006 ( '', => '-' ) 1007 ); 1008 } 1009 else { 1010 return $Kernel::OM->Get('Kernel::Output::HTML::Layout')->FatalDie( 1011 Message => "Could not load $Module!", 1012 ); 1013 } 1014 1015 return \%NewTos; 1016} 1017 1018sub _MaskNew { 1019 my ( $Self, %Param ) = @_; 1020 1021 $Param{FormID} = $Self->{FormID}; 1022 $Param{Errors}->{QueueInvalid} = $Param{Errors}->{QueueInvalid} || ''; 1023 1024 my $DynamicFieldNames = $Self->_GetFieldsToUpdate( 1025 OnlyDynamicFields => 1, 1026 ); 1027 1028 my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); 1029 1030 # get list type 1031 my $TreeView = 0; 1032 if ( $ConfigObject->Get('Ticket::Frontend::ListType') eq 'tree' ) { 1033 $TreeView = 1; 1034 } 1035 1036 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 1037 my $Config = $Kernel::OM->Get('Kernel::Config')->Get("Ticket::Frontend::$Self->{Action}"); 1038 1039 if ( $Config->{Queue} ) { 1040 1041 # check own selection 1042 my %NewTos = ( '', '-' ); 1043 my $Module = $ConfigObject->Get('CustomerPanel::NewTicketQueueSelectionModule') 1044 || 'Kernel::Output::HTML::CustomerNewTicket::QueueSelectionGeneric'; 1045 if ( $Kernel::OM->Get('Kernel::System::Main')->Require($Module) ) { 1046 my $Object = $Module->new( 1047 %{$Self}, 1048 SystemAddress => $Kernel::OM->Get('Kernel::System::SystemAddress'), 1049 Debug => $Self->{Debug}, 1050 ); 1051 1052 # log loaded module 1053 if ( $Self->{Debug} && $Self->{Debug} > 1 ) { 1054 $Kernel::OM->Get('Kernel::System::Log')->Log( 1055 Priority => 'debug', 1056 Message => "Module: $Module loaded!", 1057 ); 1058 } 1059 %NewTos = ( 1060 $Object->Run( 1061 Env => $Self, 1062 ACLParams => \%Param 1063 ), 1064 ( '', => '-' ) 1065 ); 1066 } 1067 else { 1068 return $LayoutObject->FatalError(); 1069 } 1070 1071 # build to string 1072 if (%NewTos) { 1073 for ( sort keys %NewTos ) { 1074 $NewTos{"$_||$NewTos{$_}"} = $NewTos{$_}; 1075 delete $NewTos{$_}; 1076 } 1077 } 1078 $Param{ToStrg} = $LayoutObject->AgentQueueListOption( 1079 Data => \%NewTos, 1080 Multiple => 0, 1081 Size => 0, 1082 Name => 'Dest', 1083 Class => "Validate_Required Modernize " . $Param{Errors}->{QueueInvalid}, 1084 SelectedID => $Param{ToSelected} || $Param{QueueID}, 1085 TreeView => $TreeView, 1086 ); 1087 $LayoutObject->Block( 1088 Name => 'Queue', 1089 Data => { 1090 %Param, 1091 QueueInvalid => $Param{Errors}->{QueueInvalid}, 1092 }, 1093 ); 1094 1095 } 1096 1097 my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket'); 1098 1099 # get priority 1100 if ( $Config->{Priority} ) { 1101 my %Priorities = $TicketObject->TicketPriorityList( 1102 %Param, 1103 CustomerUserID => $Self->{UserID}, 1104 Action => $Self->{Action}, 1105 ); 1106 1107 # build priority string 1108 my %PrioritySelected; 1109 if ( $Param{PriorityID} ) { 1110 $PrioritySelected{SelectedID} = $Param{PriorityID}; 1111 } 1112 else { 1113 $PrioritySelected{SelectedValue} = $Config->{PriorityDefault} || '3 normal'; 1114 } 1115 $Param{PriorityStrg} = $LayoutObject->BuildSelection( 1116 Data => \%Priorities, 1117 Name => 'PriorityID', 1118 Class => 'Modernize', 1119 %PrioritySelected, 1120 ); 1121 $LayoutObject->Block( 1122 Name => 'Priority', 1123 Data => \%Param, 1124 ); 1125 } 1126 1127 # types 1128 if ( $ConfigObject->Get('Ticket::Type') && $Config->{'TicketType'} ) { 1129 my %Type = $TicketObject->TicketTypeList( 1130 %Param, 1131 Action => $Self->{Action}, 1132 CustomerUserID => $Self->{UserID}, 1133 ); 1134 1135 if ( $Config->{'TicketTypeDefault'} && !$Param{TypeID} ) { 1136 my %ReverseType = reverse %Type; 1137 $Param{TypeID} = $ReverseType{ $Config->{'TicketTypeDefault'} }; 1138 } 1139 1140 $Param{TypeStrg} = $LayoutObject->BuildSelection( 1141 Data => \%Type, 1142 Name => 'TypeID', 1143 SelectedID => $Param{TypeID}, 1144 PossibleNone => 1, 1145 Sort => 'AlphanumericValue', 1146 Translation => 0, 1147 Class => "Validate_Required Modernize " . ( $Param{Errors}->{TypeIDInvalid} || '' ), 1148 ); 1149 $LayoutObject->Block( 1150 Name => 'TicketType', 1151 Data => { 1152 %Param, 1153 TypeIDInvalid => $Param{Errors}->{TypeIDInvalid}, 1154 } 1155 ); 1156 } 1157 1158 # services 1159 if ( $ConfigObject->Get('Ticket::Service') && $Config->{Service} ) { 1160 my %Services; 1161 if ( $Param{QueueID} || $Param{TicketID} ) { 1162 %Services = $TicketObject->TicketServiceList( 1163 %Param, 1164 Action => $Self->{Action}, 1165 CustomerUserID => $Self->{UserID}, 1166 ); 1167 } 1168 1169 $Param{ServiceStrg} = $LayoutObject->BuildSelection( 1170 Data => \%Services, 1171 Name => 'ServiceID', 1172 SelectedID => $Param{ServiceID}, 1173 Class => 'Modernize ' 1174 . ( $Config->{ServiceMandatory} ? 'Validate_Required ' : '' ) 1175 . ( $Param{Errors}->{ServiceIDInvalid} || '' ), 1176 PossibleNone => 1, 1177 TreeView => $TreeView, 1178 Sort => 'TreeView', 1179 Translation => 0, 1180 Max => 200, 1181 ); 1182 $LayoutObject->Block( 1183 Name => 'TicketService', 1184 Data => { 1185 ServiceMandatory => $Config->{ServiceMandatory} || 0, 1186 %Param, 1187 }, 1188 ); 1189 1190 # reset previous ServiceID to reset SLA-List if no service is selected 1191 if ( !$Services{ $Param{ServiceID} || '' } ) { 1192 $Param{ServiceID} = ''; 1193 } 1194 my %SLA; 1195 if ( $Config->{SLA} ) { 1196 if ( $Param{ServiceID} ) { 1197 %SLA = $TicketObject->TicketSLAList( 1198 %Param, 1199 Action => $Self->{Action}, 1200 CustomerUserID => $Self->{UserID}, 1201 ); 1202 } 1203 1204 $Param{SLAStrg} = $LayoutObject->BuildSelection( 1205 Data => \%SLA, 1206 Name => 'SLAID', 1207 SelectedID => $Param{SLAID}, 1208 Class => 'Modernize ' 1209 . ( $Config->{SLAMandatory} ? 'Validate_Required ' : '' ) 1210 . ( $Param{Errors}->{SLAInvalid} || '' ), 1211 PossibleNone => 1, 1212 Sort => 'AlphanumericValue', 1213 Translation => 0, 1214 Max => 200, 1215 ); 1216 $LayoutObject->Block( 1217 Name => 'TicketSLA', 1218 Data => { 1219 SLAMandatory => $Config->{SLAMandatory} || 0, 1220 %Param, 1221 } 1222 ); 1223 } 1224 } 1225 1226 # prepare errors 1227 if ( $Param{Errors} ) { 1228 for ( sort keys %{ $Param{Errors} } ) { 1229 $Param{$_} = $Param{Errors}->{$_}; 1230 } 1231 } 1232 1233 # get the dynamic fields for this screen 1234 my $DynamicField = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet( 1235 Valid => 1, 1236 ObjectType => [ 'Ticket', 'Article' ], 1237 FieldFilter => $Config->{DynamicField} || {}, 1238 ); 1239 1240 # reduce the dynamic fields to only the ones that are designed for customer interface 1241 my @CustomerDynamicFields; 1242 DYNAMICFIELD: 1243 for my $DynamicFieldConfig ( @{$DynamicField} ) { 1244 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 1245 1246 my $IsCustomerInterfaceCapable = $Kernel::OM->Get('Kernel::System::DynamicField::Backend')->HasBehavior( 1247 DynamicFieldConfig => $DynamicFieldConfig, 1248 Behavior => 'IsCustomerInterfaceCapable', 1249 ); 1250 next DYNAMICFIELD if !$IsCustomerInterfaceCapable; 1251 1252 push @CustomerDynamicFields, $DynamicFieldConfig; 1253 } 1254 $DynamicField = \@CustomerDynamicFields; 1255 1256 # Dynamic fields 1257 # cycle trough the activated Dynamic Fields for this screen 1258 DYNAMICFIELD: 1259 for my $DynamicFieldConfig ( @{$DynamicField} ) { 1260 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 1261 1262 # skip fields that HTML could not be retrieved 1263 next DYNAMICFIELD if !IsHashRefWithData( 1264 $Param{DynamicFieldHTML}->{ $DynamicFieldConfig->{Name} } 1265 ); 1266 1267 # get the html strings form $Param 1268 my $DynamicFieldHTML = $Param{DynamicFieldHTML}->{ $DynamicFieldConfig->{Name} }; 1269 1270 $LayoutObject->Block( 1271 Name => 'DynamicField', 1272 Data => { 1273 Name => $DynamicFieldConfig->{Name}, 1274 Label => $DynamicFieldHTML->{Label}, 1275 Field => $DynamicFieldHTML->{Field}, 1276 }, 1277 ); 1278 1279 # example of dynamic fields order customization 1280 $LayoutObject->Block( 1281 Name => 'DynamicField_' . $DynamicFieldConfig->{Name}, 1282 Data => { 1283 Name => $DynamicFieldConfig->{Name}, 1284 Label => $DynamicFieldHTML->{Label}, 1285 Field => $DynamicFieldHTML->{Field}, 1286 }, 1287 ); 1288 } 1289 1290 # show attachments 1291 ATTACHMENT: 1292 for my $Attachment ( @{ $Param{Attachments} } ) { 1293 if ( 1294 $Attachment->{ContentID} 1295 && $LayoutObject->{BrowserRichText} 1296 && ( $Attachment->{ContentType} =~ /image/i ) 1297 && ( $Attachment->{Disposition} eq 'inline' ) 1298 ) 1299 { 1300 next ATTACHMENT; 1301 } 1302 1303 push @{ $Param{AttachmentList} }, $Attachment; 1304 } 1305 1306 # add rich text editor 1307 if ( $LayoutObject->{BrowserRichText} ) { 1308 1309 # use height/width defined for this screen 1310 $Param{RichTextHeight} = $Config->{RichTextHeight} || 0; 1311 $Param{RichTextWidth} = $Config->{RichTextWidth} || 0; 1312 1313 # set up customer rich text editor 1314 $LayoutObject->CustomerSetRichTextParameters( 1315 Data => \%Param, 1316 ); 1317 } 1318 1319 # Permissions have been checked before in Run() 1320 if ( $Param{FromChatID} ) { 1321 my @ChatMessages = $Kernel::OM->Get('Kernel::System::Chat')->ChatMessageList( 1322 ChatID => $Param{FromChatID}, 1323 ); 1324 1325 for my $Message (@ChatMessages) { 1326 $Message->{MessageText} = $LayoutObject->Ascii2Html( 1327 Text => $Message->{MessageText}, 1328 LinkFeature => 1, 1329 ); 1330 } 1331 1332 $LayoutObject->Block( 1333 Name => 'ChatArticlePreview', 1334 Data => { 1335 ChatMessages => \@ChatMessages, 1336 }, 1337 ); 1338 } 1339 1340 # send data to JS 1341 $LayoutObject->AddJSData( 1342 Key => 'DynamicFieldNames', 1343 Value => $DynamicFieldNames, 1344 ); 1345 1346 # get output back 1347 return $LayoutObject->Output( 1348 TemplateFile => 'CustomerTicketMessage', 1349 Data => \%Param, 1350 ); 1351} 1352 1353sub _GetFieldsToUpdate { 1354 my ( $Self, %Param ) = @_; 1355 1356 my @UpdatableFields; 1357 1358 # set the fields that can be updatable via AJAXUpdate 1359 if ( !$Param{OnlyDynamicFields} ) { 1360 @UpdatableFields = qw( Dest ServiceID SLAID PriorityID ); 1361 } 1362 1363 my $Config = $Kernel::OM->Get('Kernel::Config')->Get("Ticket::Frontend::$Self->{Action}"); 1364 1365 # get the dynamic fields for this screen 1366 my $DynamicField = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet( 1367 Valid => 1, 1368 ObjectType => [ 'Ticket', 'Article' ], 1369 FieldFilter => $Config->{DynamicField} || {}, 1370 ); 1371 1372 # cycle trough the activated Dynamic Fields for this screen 1373 DYNAMICFIELD: 1374 for my $DynamicFieldConfig ( @{$DynamicField} ) { 1375 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 1376 1377 my $IsACLReducible = $Kernel::OM->Get('Kernel::System::DynamicField::Backend')->HasBehavior( 1378 DynamicFieldConfig => $DynamicFieldConfig, 1379 Behavior => 'IsACLReducible', 1380 ); 1381 next DYNAMICFIELD if !$IsACLReducible; 1382 1383 push @UpdatableFields, 'DynamicField_' . $DynamicFieldConfig->{Name}; 1384 } 1385 1386 return \@UpdatableFields; 1387} 1388 13891; 1390