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::AdminDynamicField;
10
11use strict;
12use warnings;
13use utf8;
14
15our $ObjectManagerDisabled = 1;
16
17use Kernel::System::VariableCheck qw(:all);
18use Kernel::Language qw(Translatable);
19use Kernel::System::CheckItem;
20
21sub new {
22    my ( $Type, %Param ) = @_;
23
24    my $Self = {%Param};
25    bless( $Self, $Type );
26
27    return $Self;
28}
29
30sub Run {
31    my ( $Self, %Param ) = @_;
32
33    if ( $Self->{Subaction} eq 'DynamicFieldDelete' ) {
34
35        # challenge token check for write action
36        $Kernel::OM->Get('Kernel::Output::HTML::Layout')->ChallengeTokenCheck();
37
38        return $Self->_DynamicFieldDelete(
39            %Param,
40        );
41    }
42
43    return $Self->_ShowOverview(
44        %Param,
45        Action => 'Overview',
46    );
47}
48
49# AJAX sub-action
50sub _DynamicFieldDelete {
51    my ( $Self, %Param ) = @_;
52
53    my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
54    my $LogObject   = $Kernel::OM->Get('Kernel::System::Log');
55
56    my $Confirmed = $ParamObject->GetParam( Param => 'Confirmed' );
57
58    if ( !$Confirmed ) {
59        $LogObject->Log(
60            'Priority' => 'error',
61            'Message'  => "Need 'Confirmed'!",
62        );
63        return;
64    }
65
66    my $ID = $ParamObject->GetParam( Param => 'ID' );
67
68    my $DynamicFieldObject = $Kernel::OM->Get('Kernel::System::DynamicField');
69    my $DynamicFieldConfig = $DynamicFieldObject->DynamicFieldGet(
70        ID => $ID,
71    );
72
73    if ( !IsHashRefWithData($DynamicFieldConfig) ) {
74        $LogObject->Log(
75            'Priority' => 'error',
76            'Message'  => "Could not find DynamicField $ID!",
77        );
78        return;
79    }
80
81    if ( $DynamicFieldConfig->{InternalField} ) {
82        $LogObject->Log(
83            'Priority' => 'error',
84            'Message'  => "Could not delete internal DynamicField $ID!",
85        );
86        return;
87    }
88
89    my $ValuesDeleteSuccess = $Kernel::OM->Get('Kernel::System::DynamicField::Backend')->AllValuesDelete(
90        DynamicFieldConfig => $DynamicFieldConfig,
91        UserID             => $Self->{UserID},
92    );
93
94    my $Success;
95
96    if ($ValuesDeleteSuccess) {
97        $Success = $DynamicFieldObject->DynamicFieldDelete(
98            ID     => $ID,
99            UserID => $Self->{UserID},
100        );
101    }
102
103    return $Kernel::OM->Get('Kernel::Output::HTML::Layout')->Attachment(
104        ContentType => 'text/html',
105        Content     => $Success,
106        Type        => 'inline',
107        NoCache     => 1,
108    );
109}
110
111sub _ShowOverview {
112    my ( $Self, %Param ) = @_;
113
114    my $LayoutObject       = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
115    my $ConfigObject       = $Kernel::OM->Get('Kernel::Config');
116    my $DynamicFieldObject = $Kernel::OM->Get('Kernel::System::DynamicField');
117    my $FieldTypeConfig    = $ConfigObject->Get('DynamicFields::Driver');
118
119    my $Output = $LayoutObject->Header();
120    $Output .= $LayoutObject->NavigationBar();
121
122    # check for possible order collisions or gaps
123    my $OrderSuccess = $DynamicFieldObject->DynamicFieldOrderCheck();
124    if ( !$OrderSuccess ) {
125        return $Self->_DynamicFieldOrderReset(
126            %Param,
127        );
128    }
129
130    my $OTRSBusinessIsInstalled = $Kernel::OM->Get('Kernel::System::OTRSBusiness')->OTRSBusinessIsInstalled();
131
132    # call all needed template blocks
133    $LayoutObject->Block(
134        Name => 'Main',
135        Data => {
136            %Param,
137            OTRSBusinessIsInstalled => $OTRSBusinessIsInstalled,
138        }
139    );
140
141    my %FieldTypes;
142    my %FieldDialogs;
143
144    if ( !IsHashRefWithData($FieldTypeConfig) ) {
145        return $LayoutObject->ErrorScreen(
146            Message => Translatable('Fields configuration is not valid'),
147        );
148    }
149
150    # get the field types (backends) and its config dialogs
151    FIELDTYPE:
152    for my $FieldType ( sort keys %{$FieldTypeConfig} ) {
153
154        next FIELDTYPE if !$FieldTypeConfig->{$FieldType};
155        next FIELDTYPE if $FieldTypeConfig->{$FieldType}->{DisabledAdd};
156
157        # add the field type to the list
158        $FieldTypes{$FieldType} = $FieldTypeConfig->{$FieldType}->{DisplayName};
159
160        # get the config dialog
161        $FieldDialogs{$FieldType} =
162            $FieldTypeConfig->{$FieldType}->{ConfigDialog};
163    }
164
165    my $ObjectTypeConfig = $ConfigObject->Get('DynamicFields::ObjectType');
166
167    if ( !IsHashRefWithData($ObjectTypeConfig) ) {
168        return $LayoutObject->ErrorScreen(
169            Message => Translatable('Objects configuration is not valid'),
170        );
171    }
172
173    # make ObjectTypeConfig local variable to proper sorting
174    my %ObjectTypeConfig = %{$ObjectTypeConfig};
175
176    # cycle thought all objects to create the select add field selects
177    my @ObjectTypes;
178    OBJECTTYPE:
179    for my $ObjectType (
180        sort {
181            ( int $ObjectTypeConfig{$a}->{Prio} || 0 )
182                <=> ( int $ObjectTypeConfig{$b}->{Prio} || 0 )
183        } keys %ObjectTypeConfig
184        )
185    {
186        next OBJECTTYPE if !$ObjectTypeConfig->{$ObjectType};
187
188        my $SelectName = $ObjectType . 'DynamicField';
189
190        my @FieldList = map { { Key => $_, Value => $FieldTypes{$_} } } sort keys %FieldTypes;
191
192        for my $Field (@FieldList) {
193
194            if ( !$ConfigObject->Get("Frontend::Module")->{ $FieldDialogs{ $Field->{Key} } } ) {
195                $Field->{Disabled} = 1;
196            }
197        }
198
199        # Add disabled teaser options for OTRSBusiness dynamic fields.
200        if ( !$OTRSBusinessIsInstalled ) {
201            push @FieldList, {
202                Key      => 'Database',
203                Value    => $LayoutObject->{LanguageObject}->Translate( 'Database (%s)', 'OTRS Business Solution™' ),
204                Disabled => 1,
205            };
206            push @FieldList, {
207                Key   => 'Webservice',
208                Value => $LayoutObject->{LanguageObject}->Translate( 'Web service (%s)', 'OTRS Business Solution™' ),
209                Disabled => 1,
210            };
211            push @FieldList, {
212                Key => 'ContactWithData',
213                Value =>
214                    $LayoutObject->{LanguageObject}->Translate( 'Contact with data (%s)', 'OTRS Business Solution™' ),
215                Disabled => 1,
216            };
217        }
218
219        # create the Add Dynamic Field select
220        my $AddDynamicFieldStrg = $LayoutObject->BuildSelection(
221            Data          => \@FieldList,
222            Name          => $SelectName,
223            PossibleNone  => 1,
224            Translation   => 1,
225            Sort          => 'AlphanumericValue',
226            SelectedValue => '-',
227            Class         => 'Modernize W75pc',
228        );
229
230        my $ObjectTypeName = $Kernel::OM->Get('Kernel::Config')->Get('DynamicFields::ObjectType')
231            ->{$ObjectType}->{DisplayName} || $ObjectType;
232
233        push @ObjectTypes, $ObjectType;
234
235        # call ActionAddDynamicField block
236        $LayoutObject->Block(
237            Name => 'ActionAddDynamicField',
238            Data => {
239                %Param,
240                AddDynamicFieldStrg => $AddDynamicFieldStrg,
241                ObjectType          => $ObjectType,
242                ObjectTypeName      => $ObjectTypeName,
243                SelectName          => $SelectName,
244            },
245        );
246    }
247
248    # send data to JS
249    $LayoutObject->AddJSData(
250        Key   => 'ObjectTypes',
251        Value => \@ObjectTypes
252    );
253
254    # send data to JS
255    $LayoutObject->AddJSData(
256        Key   => 'DynamicFields',
257        Value => \%FieldDialogs
258    );
259
260    # call hint block
261    $LayoutObject->Block(
262        Name => 'Hint',
263        Data => \%Param,
264    );
265
266    # get dynamic fields list
267    my $DynamicFieldsList = $DynamicFieldObject->DynamicFieldList(
268        Valid => 0,
269    );
270
271    # print the list of dynamic fields
272    $Self->_DynamicFieldsListShow(
273        DynamicFields => $DynamicFieldsList,
274        Total         => scalar @{$DynamicFieldsList},
275    );
276
277    $Output .= $LayoutObject->Output(
278        TemplateFile => 'AdminDynamicField',
279        Data         => {
280            %Param,
281        },
282    );
283
284    $Output .= $LayoutObject->Footer();
285    return $Output;
286}
287
288sub _DynamicFieldsListShow {
289    my ( $Self, %Param ) = @_;
290
291    my $LayoutObject    = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
292    my $FieldTypeConfig = $Kernel::OM->Get('Kernel::Config')->Get('DynamicFields::Driver');
293
294    # check start option, if higher than fields available, set
295    # it to the last field page
296    my $StartHit = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'StartHit' ) || 1;
297
298    # get personal page shown count
299    my $PageShownPreferencesKey = 'AdminDynamicFieldsOverviewPageShown';
300    my $PageShown               = $Self->{$PageShownPreferencesKey} || 35;
301    my $Group                   = 'DynamicFieldsOverviewPageShown';
302
303    # get data selection
304    my %Data;
305    my $Config = $Kernel::OM->Get('Kernel::Config')->Get('PreferencesGroups');
306    if ( $Config && $Config->{$Group} && $Config->{$Group}->{Data} ) {
307        %Data = %{ $Config->{$Group}->{Data} };
308    }
309
310    # calculate max. shown per page
311    if ( $StartHit > $Param{Total} ) {
312        my $Pages = int( ( $Param{Total} / $PageShown ) + 0.99999 );
313        $StartHit = ( ( $Pages - 1 ) * $PageShown ) + 1;
314    }
315
316    # build nav bar
317    my $Limit   = $Param{Limit} || 20_000;
318    my %PageNav = $LayoutObject->PageNavBar(
319        Limit     => $Limit,
320        StartHit  => $StartHit,
321        PageShown => $PageShown,
322        AllHits   => $Param{Total} || 0,
323        Action    => 'Action=' . $LayoutObject->{Action},
324        Link      => $Param{LinkPage},
325        IDPrefix  => $LayoutObject->{Action},
326    );
327
328    # build shown dynamic fields per page
329    $Param{RequestedURL}    = "Action=$Self->{Action}";
330    $Param{Group}           = $Group;
331    $Param{PreferencesKey}  = $PageShownPreferencesKey;
332    $Param{PageShownString} = $LayoutObject->BuildSelection(
333        Name        => $PageShownPreferencesKey,
334        SelectedID  => $PageShown,
335        Translation => 0,
336        Data        => \%Data,
337        Sort        => 'NumericValue',
338        Class       => 'Modernize',
339    );
340
341    if (%PageNav) {
342        $LayoutObject->Block(
343            Name => 'OverviewNavBarPageNavBar',
344            Data => \%PageNav,
345        );
346
347        $LayoutObject->Block(
348            Name => 'ContextSettings',
349            Data => { %PageNav, %Param, },
350        );
351    }
352
353    # check if at least 1 dynamic field is registered in the system
354    if ( $Param{Total} ) {
355
356        # get dynamic fields details
357        my $Counter = 0;
358
359        DYNAMICFIELDID:
360        for my $DynamicFieldID ( @{ $Param{DynamicFields} } ) {
361            $Counter++;
362            if ( $Counter >= $StartHit && $Counter < ( $PageShown + $StartHit ) ) {
363
364                my $DynamicFieldData = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldGet(
365                    ID => $DynamicFieldID,
366                );
367                next DYNAMICFIELDID if !IsHashRefWithData($DynamicFieldData);
368
369                # convert ValidID to Validity string
370                my $Valid = $Kernel::OM->Get('Kernel::System::Valid')->ValidLookup(
371                    ValidID => $DynamicFieldData->{ValidID},
372                );
373
374                # get the object type display name
375                my $ObjectTypeName = $Kernel::OM->Get('Kernel::Config')->Get('DynamicFields::ObjectType')
376                    ->{ $DynamicFieldData->{ObjectType} }->{DisplayName}
377                    || $DynamicFieldData->{ObjectType};
378
379                # get the field type display name
380                my $FieldTypeName = $FieldTypeConfig->{ $DynamicFieldData->{FieldType} }->{DisplayName}
381                    || $DynamicFieldData->{FieldType};
382
383                # get the field backend dialog
384                my $ConfigDialog = $FieldTypeConfig->{ $DynamicFieldData->{FieldType} }->{ConfigDialog}
385                    || '';
386
387                # print each dynamic field row
388                $LayoutObject->Block(
389                    Name => 'DynamicFieldsRow',
390                    Data => {
391                        %{$DynamicFieldData},
392                        Valid          => $Valid,
393                        ConfigDialog   => $ConfigDialog,
394                        FieldTypeName  => $FieldTypeName,
395                        ObjectTypeName => $ObjectTypeName,
396                    },
397                );
398
399                # Internal fields can not be deleted.
400                if ( !$DynamicFieldData->{InternalField} ) {
401                    $LayoutObject->Block(
402                        Name => 'DeleteLink',
403                        Data => {
404                            %{$DynamicFieldData},
405                            Valid          => $Valid,
406                            ConfigDialog   => $ConfigDialog,
407                            FieldTypeName  => $FieldTypeName,
408                            ObjectTypeName => $ObjectTypeName,
409                        },
410                    );
411                }
412            }
413        }
414    }
415
416    # otherwise show a no data found message
417    else {
418        $LayoutObject->Block(
419            Name => 'NoDataFound',
420            Data => \%Param,
421        );
422    }
423
424    $LayoutObject->Block(
425        Name => 'MaxFieldOrder',
426        Data => {
427            MaxFieldOrder => scalar @{ $Param{DynamicFields} },
428        },
429    );
430
431    return;
432}
433
434sub _DynamicFieldOrderReset {
435    my ( $Self, %Param ) = @_;
436
437    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
438    my $ResetSuccess = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldOrderReset();
439
440    # show error message if the order reset was not successful
441    if ( !$ResetSuccess ) {
442        return $LayoutObject->ErrorScreen(
443            Message => Translatable(
444                'Could not reset Dynamic Field order properly, please check the error log for more details.'
445            ),
446        );
447    }
448
449    # redirect to main screen
450    return $LayoutObject->Redirect(
451        OP => "Action=AdminDynamicField",
452    );
453}
454
4551;
456