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::System::DynamicField::Driver::BaseSelect; 10 11use strict; 12use warnings; 13 14use Kernel::System::VariableCheck qw(:all); 15 16use parent qw(Kernel::System::DynamicField::Driver::Base); 17 18our @ObjectDependencies = ( 19 'Kernel::System::DB', 20 'Kernel::System::DynamicFieldValue', 21 'Kernel::System::Ticket::ColumnFilter', 22 'Kernel::System::Log', 23); 24 25=head1 NAME 26 27Kernel::System::DynamicField::Driver::BaseSelect - sub module of 28Kernel::System::DynamicField::Driver::Dropdown and 29Kernel::System::DynamicField::Driver::Multiselect 30 31=head1 DESCRIPTION 32 33Date common functions. 34 35=head1 PUBLIC INTERFACE 36 37=cut 38 39sub ValueGet { 40 my ( $Self, %Param ) = @_; 41 42 my $DFValue = $Kernel::OM->Get('Kernel::System::DynamicFieldValue')->ValueGet( 43 FieldID => $Param{DynamicFieldConfig}->{ID}, 44 ObjectID => $Param{ObjectID}, 45 ); 46 47 return if !$DFValue; 48 return if !IsArrayRefWithData($DFValue); 49 return if !IsHashRefWithData( $DFValue->[0] ); 50 51 return $DFValue->[0]->{ValueText}; 52} 53 54sub ValueSet { 55 my ( $Self, %Param ) = @_; 56 57 # check for valid possible values list 58 if ( !$Param{DynamicFieldConfig}->{Config}->{PossibleValues} ) { 59 $Kernel::OM->Get('Kernel::System::Log')->Log( 60 Priority => 'error', 61 Message => "Need PossibleValues in DynamicFieldConfig!", 62 ); 63 return; 64 } 65 66 my $Success = $Kernel::OM->Get('Kernel::System::DynamicFieldValue')->ValueSet( 67 FieldID => $Param{DynamicFieldConfig}->{ID}, 68 ObjectID => $Param{ObjectID}, 69 Value => [ 70 { 71 ValueText => $Param{Value}, 72 }, 73 ], 74 UserID => $Param{UserID}, 75 ); 76 77 return $Success; 78} 79 80sub ValueValidate { 81 my ( $Self, %Param ) = @_; 82 83 my $Success = $Kernel::OM->Get('Kernel::System::DynamicFieldValue')->ValueValidate( 84 Value => { 85 ValueText => $Param{Value}, 86 }, 87 UserID => $Param{UserID} 88 ); 89 90 return $Success; 91} 92 93sub SearchSQLGet { 94 my ( $Self, %Param ) = @_; 95 96 if ( $Param{Operator} eq 'Like' ) { 97 my $SQL = $Kernel::OM->Get('Kernel::System::DB')->QueryCondition( 98 Key => "$Param{TableAlias}.value_text", 99 Value => $Param{SearchTerm}, 100 ); 101 102 return $SQL; 103 } 104 105 my %Operators = ( 106 Equals => '=', 107 GreaterThan => '>', 108 GreaterThanEquals => '>=', 109 SmallerThan => '<', 110 SmallerThanEquals => '<=', 111 ); 112 113 if ( $Param{Operator} eq 'Empty' ) { 114 if ( $Param{SearchTerm} ) { 115 return " $Param{TableAlias}.value_text IS NULL OR $Param{TableAlias}.value_text = '' "; 116 } 117 else { 118 my $DatabaseType = $Kernel::OM->Get('Kernel::System::DB')->{'DB::Type'}; 119 if ( $DatabaseType eq 'oracle' ) { 120 return " $Param{TableAlias}.value_text IS NOT NULL "; 121 } 122 else { 123 return " $Param{TableAlias}.value_text <> '' "; 124 } 125 } 126 } 127 elsif ( !$Operators{ $Param{Operator} } ) { 128 $Kernel::OM->Get('Kernel::System::Log')->Log( 129 'Priority' => 'error', 130 'Message' => "Unsupported Operator $Param{Operator}", 131 ); 132 return; 133 } 134 135 my $SQL = " $Param{TableAlias}.value_text $Operators{ $Param{Operator} } '"; 136 $SQL .= $Kernel::OM->Get('Kernel::System::DB')->Quote( $Param{SearchTerm} ) . "' "; 137 return $SQL; 138} 139 140sub SearchSQLOrderFieldGet { 141 my ( $Self, %Param ) = @_; 142 143 return "$Param{TableAlias}.value_text"; 144} 145 146sub EditFieldRender { 147 my ( $Self, %Param ) = @_; 148 149 # take config from field config 150 my $FieldConfig = $Param{DynamicFieldConfig}->{Config}; 151 my $FieldName = 'DynamicField_' . $Param{DynamicFieldConfig}->{Name}; 152 my $FieldLabel = $Param{DynamicFieldConfig}->{Label}; 153 154 my $Value; 155 156 # set the field value or default 157 if ( $Param{UseDefaultValue} ) { 158 $Value = ( defined $FieldConfig->{DefaultValue} ? $FieldConfig->{DefaultValue} : '' ); 159 } 160 $Value = $Param{Value} // $Value; 161 162 # check if a value in a template (GenericAgent etc.) 163 # is configured for this dynamic field 164 if ( 165 IsHashRefWithData( $Param{Template} ) 166 && defined $Param{Template}->{$FieldName} 167 ) 168 { 169 $Value = $Param{Template}->{$FieldName}; 170 } 171 172 # extract the dynamic field value from the web request 173 my $FieldValue = $Self->EditFieldValueGet( 174 %Param, 175 ); 176 177 # set values from ParamObject if present 178 if ( defined $FieldValue ) { 179 $Value = $FieldValue; 180 } 181 182 # check and set class if necessary 183 my $FieldClass = 'DynamicFieldText Modernize'; 184 if ( defined $Param{Class} && $Param{Class} ne '' ) { 185 $FieldClass .= ' ' . $Param{Class}; 186 } 187 188 # set field as mandatory 189 if ( $Param{Mandatory} ) { 190 $FieldClass .= ' Validate_Required'; 191 } 192 193 # set error css class 194 if ( $Param{ServerError} ) { 195 $FieldClass .= ' ServerError'; 196 } 197 198 # set TreeView class 199 if ( $FieldConfig->{TreeView} ) { 200 $FieldClass .= ' DynamicFieldWithTreeView'; 201 } 202 203 # set PossibleValues, use PossibleValuesFilter if defined 204 my $PossibleValues = $Param{PossibleValuesFilter} // $Self->PossibleValuesGet(%Param); 205 206 my $Size = 1; 207 208 # TODO change ConfirmationNeeded parameter name to something more generic 209 210 # when ConfimationNeeded parameter is present (AdminGenericAgent) the filed should be displayed 211 # as an open list, because you might not want to change the value, otherwise a value will be 212 # selected 213 if ( $Param{ConfirmationNeeded} ) { 214 $Size = 5; 215 } 216 217 my $DataValues = $Self->BuildSelectionDataGet( 218 DynamicFieldConfig => $Param{DynamicFieldConfig}, 219 PossibleValues => $PossibleValues, 220 Value => $Value, 221 ); 222 223 my $HTMLString = $Param{LayoutObject}->BuildSelection( 224 Data => $DataValues || {}, 225 Name => $FieldName, 226 SelectedID => $Value, 227 Translation => $FieldConfig->{TranslatableValues} || 0, 228 Class => $FieldClass, 229 Size => $Size, 230 HTMLQuote => 1, 231 ); 232 233 if ( $FieldConfig->{TreeView} ) { 234 my $TreeSelectionMessage = $Param{LayoutObject}->{LanguageObject}->Translate("Show Tree Selection"); 235 $HTMLString 236 .= ' <a href="#" title="' 237 . $TreeSelectionMessage 238 . '" class="ShowTreeSelection"><span>' 239 . $TreeSelectionMessage . '</span><i class="fa fa-sitemap"></i></a>'; 240 } 241 242 if ( $Param{Mandatory} ) { 243 my $DivID = $FieldName . 'Error'; 244 245 my $FieldRequiredMessage = $Param{LayoutObject}->{LanguageObject}->Translate("This field is required."); 246 247 # for client side validation 248 $HTMLString .= <<"EOF"; 249 250<div id="$DivID" class="TooltipErrorMessage"> 251 <p> 252 $FieldRequiredMessage 253 </p> 254</div> 255EOF 256 } 257 258 if ( $Param{ServerError} ) { 259 260 my $ErrorMessage = $Param{ErrorMessage} || 'This field is required.'; 261 $ErrorMessage = $Param{LayoutObject}->{LanguageObject}->Translate($ErrorMessage); 262 my $DivID = $FieldName . 'ServerError'; 263 264 # for server side validation 265 $HTMLString .= <<"EOF"; 266 267<div id="$DivID" class="TooltipErrorMessage"> 268 <p> 269 $ErrorMessage 270 </p> 271</div> 272EOF 273 } 274 275 if ( $Param{AJAXUpdate} ) { 276 277 my $FieldSelector = '#' . $FieldName; 278 279 my $FieldsToUpdate = ''; 280 if ( IsArrayRefWithData( $Param{UpdatableFields} ) ) { 281 282 # Remove current field from updatable fields list 283 my @FieldsToUpdate = grep { $_ ne $FieldName } @{ $Param{UpdatableFields} }; 284 285 # quote all fields, put commas in between them 286 $FieldsToUpdate = join( ', ', map {"'$_'"} @FieldsToUpdate ); 287 } 288 289 # add js to call FormUpdate() 290 $Param{LayoutObject}->AddJSOnDocumentComplete( Code => <<"EOF"); 291\$('$FieldSelector').bind('change', function (Event) { 292 Core.AJAX.FormUpdate(\$(this).parents('form'), 'AJAXUpdate', '$FieldName', [ $FieldsToUpdate ]); 293}); 294Core.App.Subscribe('Event.AJAX.FormUpdate.Callback', function(Data) { 295 var FieldName = '$FieldName'; 296 if (Data[FieldName] && \$('#' + FieldName).hasClass('DynamicFieldWithTreeView')) { 297 Core.UI.TreeSelection.RestoreDynamicFieldTreeView(\$('#' + FieldName), Data[FieldName], '' , 1); 298 } 299}); 300EOF 301 } 302 303 # call EditLabelRender on the common Driver 304 my $LabelString = $Self->EditLabelRender( 305 %Param, 306 Mandatory => $Param{Mandatory} || '0', 307 FieldName => $FieldName, 308 ); 309 310 my $Data = { 311 Field => $HTMLString, 312 Label => $LabelString, 313 }; 314 315 return $Data; 316} 317 318sub EditFieldValueGet { 319 my ( $Self, %Param ) = @_; 320 321 my $FieldName = 'DynamicField_' . $Param{DynamicFieldConfig}->{Name}; 322 323 my $Value; 324 325 # check if there is a Template and retrieve the dynamic field value from there 326 if ( IsHashRefWithData( $Param{Template} ) && defined $Param{Template}->{$FieldName} ) { 327 $Value = $Param{Template}->{$FieldName}; 328 } 329 330 # otherwise get dynamic field value from the web request 331 elsif ( 332 defined $Param{ParamObject} 333 && ref $Param{ParamObject} eq 'Kernel::System::Web::Request' 334 ) 335 { 336 $Value = $Param{ParamObject}->GetParam( Param => $FieldName ); 337 } 338 339 if ( defined $Param{ReturnTemplateStructure} && $Param{ReturnTemplateStructure} eq 1 ) { 340 return { 341 $FieldName => $Value, 342 }; 343 } 344 345 # for this field the normal return an the ReturnValueStructure are the same 346 return $Value; 347} 348 349sub EditFieldValueValidate { 350 my ( $Self, %Param ) = @_; 351 352 # get the field value from the http request 353 my $Value = $Self->EditFieldValueGet( 354 DynamicFieldConfig => $Param{DynamicFieldConfig}, 355 ParamObject => $Param{ParamObject}, 356 357 # not necessary for this Driver but place it for consistency reasons 358 ReturnValueStructure => 1, 359 ); 360 361 my $ServerError; 362 my $ErrorMessage; 363 364 # perform necessary validations 365 if ( $Param{Mandatory} && !$Value ) { 366 return { 367 ServerError => 1, 368 }; 369 } 370 else { 371 372 # get possible values list 373 my $PossibleValues = $Param{DynamicFieldConfig}->{Config}->{PossibleValues}; 374 375 # overwrite possible values if PossibleValuesFilter 376 if ( defined $Param{PossibleValuesFilter} ) { 377 $PossibleValues = $Param{PossibleValuesFilter}; 378 } 379 380 # validate if value is in possible values list (but let pass empty values) 381 if ( $Value && !$PossibleValues->{$Value} ) { 382 $ServerError = 1; 383 $ErrorMessage = 'The field content is invalid'; 384 } 385 } 386 387 # create resulting structure 388 my $Result = { 389 ServerError => $ServerError, 390 ErrorMessage => $ErrorMessage, 391 }; 392 393 return $Result; 394} 395 396sub DisplayValueRender { 397 my ( $Self, %Param ) = @_; 398 399 # set HTMLOutput as default if not specified 400 if ( !defined $Param{HTMLOutput} ) { 401 $Param{HTMLOutput} = 1; 402 } 403 404 # get raw Value strings from field value 405 my $Value = defined $Param{Value} ? $Param{Value} : ''; 406 407 # get real value 408 if ( $Param{DynamicFieldConfig}->{Config}->{PossibleValues}->{$Value} ) { 409 410 # get readable value 411 $Value = $Param{DynamicFieldConfig}->{Config}->{PossibleValues}->{$Value}; 412 } 413 414 # check is needed to translate values 415 if ( $Param{DynamicFieldConfig}->{Config}->{TranslatableValues} ) { 416 417 # translate value 418 $Value = $Param{LayoutObject}->{LanguageObject}->Translate($Value); 419 } 420 421 # set title as value after update and before limit 422 my $Title = $Value; 423 424 # HTMLOutput transformations 425 if ( $Param{HTMLOutput} ) { 426 $Value = $Param{LayoutObject}->Ascii2Html( 427 Text => $Value, 428 Max => $Param{ValueMaxChars} || '', 429 ); 430 431 $Title = $Param{LayoutObject}->Ascii2Html( 432 Text => $Title, 433 Max => $Param{TitleMaxChars} || '', 434 ); 435 } 436 else { 437 if ( $Param{ValueMaxChars} && length($Value) > $Param{ValueMaxChars} ) { 438 $Value = substr( $Value, 0, $Param{ValueMaxChars} ) . '...'; 439 } 440 if ( $Param{TitleMaxChars} && length($Title) > $Param{TitleMaxChars} ) { 441 $Title = substr( $Title, 0, $Param{TitleMaxChars} ) . '...'; 442 } 443 } 444 445 # set field link from config 446 my $Link = $Param{DynamicFieldConfig}->{Config}->{Link} || ''; 447 my $LinkPreview = $Param{DynamicFieldConfig}->{Config}->{LinkPreview} || ''; 448 449 my $Data = { 450 Value => $Value, 451 Title => $Title, 452 Link => $Link, 453 LinkPreview => $LinkPreview, 454 }; 455 456 return $Data; 457} 458 459sub SearchFieldRender { 460 my ( $Self, %Param ) = @_; 461 462 # take config from field config 463 my $FieldConfig = $Param{DynamicFieldConfig}->{Config}; 464 my $FieldName = 'Search_DynamicField_' . $Param{DynamicFieldConfig}->{Name}; 465 my $FieldLabel = $Param{DynamicFieldConfig}->{Label}; 466 467 my $Value; 468 469 my @DefaultValue; 470 471 if ( defined $Param{DefaultValue} ) { 472 @DefaultValue = split /;/, $Param{DefaultValue}; 473 } 474 475 # set the field value 476 if (@DefaultValue) { 477 $Value = \@DefaultValue; 478 } 479 480 # get the field value, this function is always called after the profile is loaded 481 my $FieldValues = $Self->SearchFieldValueGet( 482 %Param, 483 ); 484 485 if ( defined $FieldValues ) { 486 $Value = $FieldValues; 487 } 488 489 # check and set class if necessary 490 my $FieldClass = 'DynamicFieldMultiSelect Modernize'; 491 492 # set TreeView class 493 if ( $FieldConfig->{TreeView} ) { 494 $FieldClass .= ' DynamicFieldWithTreeView'; 495 } 496 497 # set PossibleValues 498 my $SelectionData = $FieldConfig->{PossibleValues}; 499 500 # get historical values from database 501 my $HistoricalValues = $Self->HistoricalValuesGet(%Param); 502 503 # add historic values to current values (if they don't exist anymore) 504 if ( IsHashRefWithData($HistoricalValues) ) { 505 for my $Key ( sort keys %{$HistoricalValues} ) { 506 if ( !$SelectionData->{$Key} ) { 507 $SelectionData->{$Key} = $HistoricalValues->{$Key}; 508 } 509 } 510 } 511 512 # use PossibleValuesFilter if defined 513 $SelectionData = $Param{PossibleValuesFilter} // $SelectionData; 514 515 # check if $SelectionData differs from configured PossibleValues 516 # and show values which are not contained as disabled if TreeView => 1 517 if ( $FieldConfig->{TreeView} ) { 518 519 if ( keys %{ $FieldConfig->{PossibleValues} } != keys %{$SelectionData} ) { 520 521 my @Values; 522 for my $Key ( sort keys %{ $FieldConfig->{PossibleValues} } ) { 523 524 push @Values, { 525 Key => $Key, 526 Value => $FieldConfig->{PossibleValues}->{$Key}, 527 Disabled => ( defined $SelectionData->{$Key} ) ? 0 : 1, 528 }; 529 } 530 $SelectionData = \@Values; 531 } 532 } 533 534 my $HTMLString = $Param{LayoutObject}->BuildSelection( 535 Data => $SelectionData, 536 Name => $FieldName, 537 SelectedID => $Value, 538 Translation => $FieldConfig->{TranslatableValues} || 0, 539 PossibleNone => 0, 540 Class => $FieldClass, 541 Multiple => 1, 542 HTMLQuote => 1, 543 ); 544 545 if ( $FieldConfig->{TreeView} ) { 546 my $TreeSelectionMessage = $Param{LayoutObject}->{LanguageObject}->Translate("Show Tree Selection"); 547 $HTMLString 548 .= ' <a href="#" title="' 549 . $TreeSelectionMessage 550 . '" class="ShowTreeSelection"><span>' 551 . $TreeSelectionMessage . '</span><i class="fa fa-sitemap"></i></a>'; 552 } 553 554 # call EditLabelRender on the common Driver 555 my $LabelString = $Self->EditLabelRender( 556 %Param, 557 FieldName => $FieldName, 558 ); 559 560 my $Data = { 561 Field => $HTMLString, 562 Label => $LabelString, 563 }; 564 565 return $Data; 566} 567 568sub SearchFieldValueGet { 569 my ( $Self, %Param ) = @_; 570 571 my $Value; 572 573 # get dynamic field value from param object 574 if ( defined $Param{ParamObject} ) { 575 my @FieldValues = $Param{ParamObject}->GetArray( 576 Param => 'Search_DynamicField_' . $Param{DynamicFieldConfig}->{Name} 577 ); 578 579 $Value = \@FieldValues; 580 } 581 582 # otherwise get the value from the profile 583 elsif ( defined $Param{Profile} ) { 584 $Value = $Param{Profile}->{ 'Search_DynamicField_' . $Param{DynamicFieldConfig}->{Name} }; 585 } 586 else { 587 return; 588 } 589 590 if ( defined $Param{ReturnProfileStructure} && $Param{ReturnProfileStructure} eq 1 ) { 591 return { 592 'Search_DynamicField_' . $Param{DynamicFieldConfig}->{Name} => $Value, 593 }; 594 } 595 596 return $Value; 597} 598 599sub SearchFieldParameterBuild { 600 my ( $Self, %Param ) = @_; 601 602 # get field value 603 my $Value = $Self->SearchFieldValueGet(%Param); 604 605 my $DisplayValue; 606 607 if ( defined $Value && !$Value ) { 608 $DisplayValue = ''; 609 } 610 611 if ($Value) { 612 if ( ref $Value eq 'ARRAY' ) { 613 614 my @DisplayItemList; 615 for my $Item ( @{$Value} ) { 616 617 # set the display value 618 my $DisplayItem = $Param{DynamicFieldConfig}->{Config}->{PossibleValues}->{$Item} 619 || $Item; 620 621 # translate the value 622 if ( 623 $Param{DynamicFieldConfig}->{Config}->{TranslatableValues} 624 && defined $Param{LayoutObject} 625 ) 626 { 627 $DisplayItem = $Param{LayoutObject}->{LanguageObject}->Translate($DisplayItem); 628 } 629 630 push @DisplayItemList, $DisplayItem; 631 } 632 633 # combine different values into one string 634 $DisplayValue = join ' + ', @DisplayItemList; 635 } 636 else { 637 638 # set the display value 639 $DisplayValue = $Param{DynamicFieldConfig}->{Config}->{PossibleValues}->{$Value}; 640 641 # translate the value 642 if ( 643 $Param{DynamicFieldConfig}->{Config}->{TranslatableValues} 644 && defined $Param{LayoutObject} 645 ) 646 { 647 $DisplayValue = $Param{LayoutObject}->{LanguageObject}->Translate($DisplayValue); 648 } 649 } 650 } 651 652 # return search parameter structure 653 return { 654 Parameter => { 655 Equals => $Value, 656 }, 657 Display => $DisplayValue, 658 }; 659} 660 661sub StatsFieldParameterBuild { 662 my ( $Self, %Param ) = @_; 663 664 # set PossibleValues 665 my $Values = $Param{DynamicFieldConfig}->{Config}->{PossibleValues}; 666 667 # get historical values from database 668 my $HistoricalValues = $Kernel::OM->Get('Kernel::System::DynamicFieldValue')->HistoricalValueGet( 669 FieldID => $Param{DynamicFieldConfig}->{ID}, 670 ValueType => 'Text,', 671 ); 672 673 # add historic values to current values (if they don't exist anymore) 674 for my $Key ( sort keys %{$HistoricalValues} ) { 675 if ( !$Values->{$Key} ) { 676 $Values->{$Key} = $HistoricalValues->{$Key}; 677 } 678 } 679 680 # use PossibleValuesFilter if defined 681 $Values = $Param{PossibleValuesFilter} // $Values; 682 683 return { 684 Values => $Values, 685 Name => $Param{DynamicFieldConfig}->{Label}, 686 Element => 'DynamicField_' . $Param{DynamicFieldConfig}->{Name}, 687 TranslatableValues => $Param{DynamicFieldConfig}->{Config}->{TranslatableValues}, 688 Block => 'MultiSelectField', 689 }; 690} 691 692sub StatsSearchFieldParameterBuild { 693 my ( $Self, %Param ) = @_; 694 695 my $Operator = 'Equals'; 696 my $Value = $Param{Value}; 697 698 return { 699 $Operator => $Value, 700 }; 701} 702 703sub ReadableValueRender { 704 my ( $Self, %Param ) = @_; 705 706 my $Value = defined $Param{Value} ? $Param{Value} : ''; 707 708 # set title as value after update and before limit 709 my $Title = $Value; 710 711 # cut strings if needed 712 if ( $Param{ValueMaxChars} && length($Value) > $Param{ValueMaxChars} ) { 713 $Value = substr( $Value, 0, $Param{ValueMaxChars} ) . '...'; 714 } 715 if ( $Param{TitleMaxChars} && length($Title) > $Param{TitleMaxChars} ) { 716 $Title = substr( $Title, 0, $Param{TitleMaxChars} ) . '...'; 717 } 718 719 my $Data = { 720 Value => $Value, 721 Title => $Title, 722 }; 723 724 return $Data; 725} 726 727sub TemplateValueTypeGet { 728 my ( $Self, %Param ) = @_; 729 730 my $FieldName = 'DynamicField_' . $Param{DynamicFieldConfig}->{Name}; 731 732 # set the field types 733 my $EditValueType = 'SCALAR'; 734 my $SearchValueType = 'ARRAY'; 735 736 # return the correct structure 737 if ( $Param{FieldType} eq 'Edit' ) { 738 return { 739 $FieldName => $EditValueType, 740 }; 741 } 742 elsif ( $Param{FieldType} eq 'Search' ) { 743 return { 744 'Search_' . $FieldName => $SearchValueType, 745 }; 746 } 747 else { 748 return { 749 $FieldName => $EditValueType, 750 'Search_' . $FieldName => $SearchValueType, 751 }; 752 } 753} 754 755sub RandomValueSet { 756 my ( $Self, %Param ) = @_; 757 758 my $Value = int( rand(500) ); 759 760 my $Success = $Self->ValueSet( 761 %Param, 762 Value => $Value, 763 ); 764 765 if ( !$Success ) { 766 return { 767 Success => 0, 768 }; 769 } 770 return { 771 Success => 1, 772 Value => $Value, 773 }; 774} 775 776sub ObjectMatch { 777 my ( $Self, %Param ) = @_; 778 779 my $FieldName = 'DynamicField_' . $Param{DynamicFieldConfig}->{Name}; 780 781 # return false if field is not defined 782 return 0 if ( !defined $Param{ObjectAttributes}->{$FieldName} ); 783 784 # return false if not match 785 if ( $Param{ObjectAttributes}->{$FieldName} ne $Param{Value} ) { 786 return 0; 787 } 788 789 return 1; 790} 791 792sub HistoricalValuesGet { 793 my ( $Self, %Param ) = @_; 794 795 # get historical values from database 796 my $HistoricalValues = $Kernel::OM->Get('Kernel::System::DynamicFieldValue')->HistoricalValueGet( 797 FieldID => $Param{DynamicFieldConfig}->{ID}, 798 ValueType => 'Text', 799 ); 800 801 # return the historical values from database 802 return $HistoricalValues; 803} 804 805sub ValueLookup { 806 my ( $Self, %Param ) = @_; 807 808 my $Value = defined $Param{Key} ? $Param{Key} : ''; 809 810 # get real values 811 my $PossibleValues = $Param{DynamicFieldConfig}->{Config}->{PossibleValues}; 812 813 if ($Value) { 814 815 # check if there is a real value for this key (otherwise keep the key) 816 if ( $Param{DynamicFieldConfig}->{Config}->{PossibleValues}->{$Value} ) { 817 818 # get readable value 819 $Value = $Param{DynamicFieldConfig}->{Config}->{PossibleValues}->{$Value}; 820 821 # check if translation is possible 822 if ( 823 defined $Param{LanguageObject} 824 && $Param{DynamicFieldConfig}->{Config}->{TranslatableValues} 825 ) 826 { 827 828 # translate value 829 $Value = $Param{LanguageObject}->Translate($Value); 830 } 831 } 832 } 833 834 return $Value; 835} 836 837sub BuildSelectionDataGet { 838 my ( $Self, %Param ) = @_; 839 840 my $FieldConfig = $Param{DynamicFieldConfig}->{Config}; 841 my $FilteredPossibleValues = $Param{PossibleValues}; 842 843 # get the possible values again as it might or might not contain the possible none and it could 844 # also be overwritten 845 my $ConfigPossibleValues = $Self->PossibleValuesGet(%Param); 846 847 # check if $PossibleValues differs from configured PossibleValues 848 # and show values which are not contained as disabled if TreeView => 1 849 if ( $FieldConfig->{TreeView} ) { 850 851 if ( keys %{$ConfigPossibleValues} != keys %{$FilteredPossibleValues} ) { 852 853 # define variables to use later in the for loop 854 my @Values; 855 my $Parents; 856 my %DisabledElements; 857 my %ProcessedElements; 858 my $PosibleNoneSet; 859 860 # loop on all filtered possible values 861 for my $Key ( sort keys %{$FilteredPossibleValues} ) { 862 863 # special case for possible none 864 if ( !$Key && !$PosibleNoneSet && $FieldConfig->{PossibleNone} ) { 865 866 # add possible none 867 push @Values, { 868 Key => $Key, 869 Value => $ConfigPossibleValues->{$Key} || '-', 870 Selected => defined $Param{Value} || !$Param{Value} ? 1 : 0, 871 }; 872 } 873 874 # try to split its parents GrandParent::Parent::Son 875 my @Elements = split /::/, $Key; 876 877 # reset parents 878 $Parents = ''; 879 880 # get each element in the hierarchy 881 ELEMENT: 882 for my $Element (@Elements) { 883 884 # add its own parents for the complete name 885 my $ElementLongName = $Parents . $Element; 886 887 # set new parent (before skip already processed) 888 $Parents .= $Element . '::'; 889 890 # skip if already processed 891 next ELEMENT if $ProcessedElements{$ElementLongName}; 892 893 my $Disabled; 894 895 # check if element exists in the original data or if it is already marked 896 if ( 897 !defined $FilteredPossibleValues->{$ElementLongName} 898 && !$DisabledElements{$ElementLongName} 899 ) 900 { 901 902 # mark element as disabled 903 $DisabledElements{$ElementLongName} = 1; 904 905 # also set the disabled flag for current element to add 906 $Disabled = 1; 907 } 908 909 # set element as already processed 910 $ProcessedElements{$ElementLongName} = 1; 911 912 # check if the current element is the selected one 913 my $Selected; 914 if ( 915 defined $Param{Value} 916 && $Param{Value} 917 && $ElementLongName eq $Param{Value} 918 ) 919 { 920 $Selected = 1; 921 } 922 923 # add element to the new list of possible values (now including missing parents) 924 push @Values, { 925 Key => $ElementLongName, 926 Value => $ConfigPossibleValues->{$ElementLongName} || $ElementLongName, 927 Disabled => $Disabled, 928 Selected => $Selected, 929 }; 930 } 931 } 932 $FilteredPossibleValues = \@Values; 933 } 934 } 935 936 return $FilteredPossibleValues; 937} 938 939sub PossibleValuesGet { 940 my ( $Self, %Param ) = @_; 941 942 # to store the possible values 943 my %PossibleValues; 944 945 # set PossibleNone attribute 946 my $FieldPossibleNone; 947 if ( defined $Param{OverridePossibleNone} ) { 948 $FieldPossibleNone = $Param{OverridePossibleNone}; 949 } 950 else { 951 $FieldPossibleNone = $Param{DynamicFieldConfig}->{Config}->{PossibleNone} || 0; 952 } 953 954 # set none value if defined on field config 955 if ($FieldPossibleNone) { 956 %PossibleValues = ( '' => '-' ); 957 } 958 959 # set all other possible values if defined on field config 960 if ( IsHashRefWithData( $Param{DynamicFieldConfig}->{Config}->{PossibleValues} ) ) { 961 %PossibleValues = ( 962 %PossibleValues, 963 %{ $Param{DynamicFieldConfig}->{Config}->{PossibleValues} }, 964 ); 965 } 966 967 # return the possible values hash as a reference 968 return \%PossibleValues; 969} 970 971sub ColumnFilterValuesGet { 972 my ( $Self, %Param ) = @_; 973 974 # take config from field config 975 my $FieldConfig = $Param{DynamicFieldConfig}->{Config}; 976 977 # set PossibleValues 978 my $SelectionData = $FieldConfig->{PossibleValues}; 979 980 # get column filter values from database 981 my $ColumnFilterValues = $Kernel::OM->Get('Kernel::System::Ticket::ColumnFilter')->DynamicFieldFilterValuesGet( 982 TicketIDs => $Param{TicketIDs}, 983 FieldID => $Param{DynamicFieldConfig}->{ID}, 984 ValueType => 'Text', 985 ); 986 987 # get the display value if still exist in dynamic field configuration 988 for my $Key ( sort keys %{$ColumnFilterValues} ) { 989 if ( $SelectionData->{$Key} ) { 990 $ColumnFilterValues->{$Key} = $SelectionData->{$Key}; 991 } 992 } 993 994 if ( $FieldConfig->{TranslatableValues} ) { 995 996 # translate the value 997 for my $ValueKey ( sort keys %{$ColumnFilterValues} ) { 998 999 my $OriginalValueName = $ColumnFilterValues->{$ValueKey}; 1000 $ColumnFilterValues->{$ValueKey} = $Param{LayoutObject}->{LanguageObject}->Translate($OriginalValueName); 1001 } 1002 } 1003 1004 return $ColumnFilterValues; 1005} 1006 10071; 1008 1009=head1 TERMS AND CONDITIONS 1010 1011This software is part of the OTRS project (L<https://otrs.org/>). 1012 1013This software comes with ABSOLUTELY NO WARRANTY. For details, see 1014the enclosed file COPYING for license information (GPL). If you 1015did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>. 1016 1017=cut 1018