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