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::AdminState;
10
11use strict;
12use warnings;
13
14use Kernel::System::VariableCheck qw(:all);
15use Kernel::Language qw(Translatable);
16
17our $ObjectManagerDisabled = 1;
18
19sub new {
20    my ( $Type, %Param ) = @_;
21
22    # allocate new hash for object
23    my $Self = {%Param};
24    bless( $Self, $Type );
25
26    return $Self;
27}
28
29sub Run {
30    my ( $Self, %Param ) = @_;
31
32    # Store last entity screen.
33    $Kernel::OM->Get('Kernel::System::AuthSession')->UpdateSessionID(
34        SessionID => $Self->{SessionID},
35        Key       => 'LastScreenEntity',
36        Value     => $Self->{RequestedURL},
37    );
38
39    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
40    my $ParamObject  = $Kernel::OM->Get('Kernel::System::Web::Request');
41    my $StateObject  = $Kernel::OM->Get('Kernel::System::State');
42
43    # ------------------------------------------------------------ #
44    # change
45    # ------------------------------------------------------------ #
46    if ( $Self->{Subaction} eq 'Change' ) {
47        my $ID     = $ParamObject->GetParam( Param => 'ID' ) || '';
48        my %Data   = $StateObject->StateGet( ID => $ID );
49        my $Output = $LayoutObject->Header();
50        $Output .= $LayoutObject->NavigationBar();
51        $Self->_Edit(
52            Action => 'Change',
53            %Data,
54        );
55        $Output .= $LayoutObject->Output(
56            TemplateFile => 'AdminState',
57            Data         => \%Param,
58        );
59        $Output .= $LayoutObject->Footer();
60        return $Output;
61    }
62
63    # ------------------------------------------------------------ #
64    # change action
65    # ------------------------------------------------------------ #
66    elsif ( $Self->{Subaction} eq 'ChangeAction' ) {
67
68        # challenge token check for write action
69        $LayoutObject->ChallengeTokenCheck();
70
71        my ( %GetParam, %Errors );
72        for my $Parameter (qw(ID Name TypeID Comment ValidID)) {
73            $GetParam{$Parameter} = $ParamObject->GetParam( Param => $Parameter ) || '';
74        }
75
76        # check needed data
77        for my $Needed (qw(Name ValidID TypeID)) {
78            if ( !$GetParam{$Needed} ) {
79                $Errors{ $Needed . 'Invalid' } = 'ServerError';
80            }
81        }
82        my %StateData = $StateObject->StateGet( ID => $GetParam{ID} );
83
84        # Check if state is present in SysConfig setting
85        my $UpdateEntity    = $ParamObject->GetParam( Param => 'UpdateEntity' ) || '';
86        my $SysConfigObject = $Kernel::OM->Get('Kernel::System::SysConfig');
87        my %StateOldData    = %StateData;
88        my @IsStateInSysConfig;
89        @IsStateInSysConfig = $SysConfigObject->ConfigurationEntityCheck(
90            EntityType => 'State',
91            EntityName => $StateData{Name},
92        );
93        if (@IsStateInSysConfig) {
94
95            # An entity present in SysConfig couldn't be invalidated.
96            if (
97                $Kernel::OM->Get('Kernel::System::Valid')->ValidLookup( ValidID => $GetParam{ValidID} )
98                ne 'valid'
99                )
100            {
101                $Errors{ValidIDInvalid}         = 'ServerError';
102                $Errors{ValidOptionServerError} = 'InSetting';
103            }
104
105            # In case changing name an authorization (UpdateEntity) should be send
106            elsif ( $StateData{Name} ne $GetParam{Name} && !$UpdateEntity ) {
107                $Errors{NameInvalid}              = 'ServerError';
108                $Errors{InSettingNameServerError} = 'InSetting';
109            }
110
111            # Check if it has at least one valid state.
112        }
113        else {
114            my @MergeStateList = $StateObject->StateGetStatesByType(
115                StateType => ['merged'],
116                Result    => 'ID',
117            );
118
119            if (
120                scalar @MergeStateList == 1
121                && $MergeStateList[0] eq $GetParam{ID}
122                && $Kernel::OM->Get('Kernel::System::Valid')->ValidLookup( ValidID => $GetParam{ValidID} ) ne 'valid'
123                )
124            {
125                $Errors{ValidIDInvalid}         = 'ServerError';
126                $Errors{ValidOptionServerError} = 'MergeError';
127            }
128        }
129
130        # if no errors occurred
131        if ( !%Errors ) {
132
133            # update the state data
134            my $UpdateSuccess = $StateObject->StateUpdate(
135                %GetParam,
136                UserID => $Self->{UserID},
137            );
138
139            if ($UpdateSuccess) {
140
141                if (
142                    @IsStateInSysConfig
143                    && $StateOldData{Name} ne $GetParam{Name}
144                    && $UpdateEntity
145                    )
146                {
147                    SETTING:
148                    for my $SettingName (@IsStateInSysConfig) {
149
150                        my %Setting = $SysConfigObject->SettingGet(
151                            Name => $SettingName,
152                        );
153
154                        next SETTING if !IsHashRefWithData( \%Setting );
155
156                        $Setting{EffectiveValue} =~ s/$StateOldData{Name}/$GetParam{Name}/g;
157
158                        my $ExclusiveLockGUID = $SysConfigObject->SettingLock(
159                            Name   => $Setting{Name},
160                            Force  => 1,
161                            UserID => $Self->{UserID}
162                        );
163                        $Setting{ExclusiveLockGUID} = $ExclusiveLockGUID;
164
165                        my %UpdateSuccess = $SysConfigObject->SettingUpdate(
166                            %Setting,
167                            UserID => $Self->{UserID},
168                        );
169                    }
170
171                    $SysConfigObject->ConfigurationDeploy(
172                        Comments      => "State name change",
173                        DirtySettings => \@IsStateInSysConfig,
174                        UserID        => $Self->{UserID},
175                        Force         => 1,
176                    );
177                }
178
179                # if the user would like to continue editing the state, just redirect to the edit screen
180                if (
181                    defined $ParamObject->GetParam( Param => 'ContinueAfterSave' )
182                    && ( $ParamObject->GetParam( Param => 'ContinueAfterSave' ) eq '1' )
183                    )
184                {
185                    my $ID = $ParamObject->GetParam( Param => 'ID' ) || '';
186                    return $LayoutObject->Redirect( OP => "Action=$Self->{Action};Subaction=Change;ID=$ID" );
187                }
188                else {
189
190                    # otherwise return to overview
191                    return $LayoutObject->Redirect( OP => "Action=$Self->{Action}" );
192                }
193            }
194        }
195
196        # something has gone wrong
197        my $Output = $LayoutObject->Header();
198        $Output .= $LayoutObject->NavigationBar();
199        $Output .= $LayoutObject->Notify( Priority => 'Error' );
200        $Self->_Edit(
201            Action => 'Change',
202            Errors => \%Errors,
203            %GetParam,
204        );
205        $Output .= $LayoutObject->Output(
206            TemplateFile => 'AdminState',
207            Data         => \%Param,
208        );
209        $Output .= $LayoutObject->Footer();
210        return $Output;
211    }
212
213    # ------------------------------------------------------------ #
214    # add
215    # ------------------------------------------------------------ #
216    elsif ( $Self->{Subaction} eq 'Add' ) {
217        my %GetParam;
218        $GetParam{Name} = $ParamObject->GetParam( Param => 'Name' );
219        my $Output = $LayoutObject->Header();
220        $Output .= $LayoutObject->NavigationBar();
221        $Self->_Edit(
222            Action => 'Add',
223            %GetParam,
224        );
225        $Output .= $LayoutObject->Output(
226            TemplateFile => 'AdminState',
227            Data         => \%Param,
228        );
229        $Output .= $LayoutObject->Footer();
230        return $Output;
231    }
232
233    # ------------------------------------------------------------ #
234    # add action
235    # ------------------------------------------------------------ #
236    elsif ( $Self->{Subaction} eq 'AddAction' ) {
237
238        # challenge token check for write action
239        $LayoutObject->ChallengeTokenCheck();
240
241        my ( %GetParam, %Errors );
242        for my $Parameter (qw(ID TypeID Name Comment ValidID)) {
243            $GetParam{$Parameter} = $ParamObject->GetParam( Param => $Parameter ) || '';
244        }
245
246        # check needed data
247        for my $Needed (qw(Name ValidID TypeID)) {
248            if ( !$GetParam{$Needed} ) {
249                $Errors{ $Needed . 'Invalid' } = 'ServerError';
250            }
251        }
252
253        my @MergeStateList = $StateObject->StateGetStatesByType(
254            StateType => ['merged'],
255            Result    => 'ID',
256        );
257        if (
258            !@MergeStateList
259            && $Kernel::OM->Get('Kernel::System::Valid')->ValidLookup( ValidID => $GetParam{ValidID} ) ne 'valid'
260            && $StateObject->StateTypeLookup( StateTypeID => $GetParam{TypeID} ) eq 'merged'
261            )
262        {
263            $Errors{ValidIDInvalid}         = 'ServerError';
264            $Errors{ValidOptionServerError} = 'MergeError';
265        }
266
267        # if no errors occurred
268        if ( !%Errors ) {
269
270            # add state
271            my $StateID = $StateObject->StateAdd(
272                %GetParam,
273                UserID => $Self->{UserID},
274            );
275            if ($StateID) {
276                $Self->_Overview();
277                my $Output = $LayoutObject->Header();
278                $Output .= $LayoutObject->NavigationBar();
279                $Output .= $LayoutObject->Notify( Info => Translatable('State added!') );
280                $Output .= $LayoutObject->Output(
281                    TemplateFile => 'AdminState',
282                    Data         => \%Param,
283                );
284                $Output .= $LayoutObject->Footer();
285                return $Output;
286            }
287        }
288
289        # something has gone wrong
290        my $Output = $LayoutObject->Header();
291        $Output .= $LayoutObject->NavigationBar();
292        $Output .= $LayoutObject->Notify( Priority => 'Error' );
293        $Self->_Edit(
294            Action => 'Add',
295            Errors => \%Errors,
296            %GetParam,
297        );
298        $Output .= $LayoutObject->Output(
299            TemplateFile => 'AdminState',
300            Data         => \%Param,
301        );
302        $Output .= $LayoutObject->Footer();
303        return $Output;
304    }
305
306    # ------------------------------------------------------------
307    # overview
308    # ------------------------------------------------------------
309    else {
310        $Self->_Overview();
311        my $Output = $LayoutObject->Header();
312        $Output .= $LayoutObject->NavigationBar();
313        $Output .= $LayoutObject->Output(
314            TemplateFile => 'AdminState',
315            Data         => \%Param,
316        );
317        $Output .= $LayoutObject->Footer();
318        return $Output;
319    }
320
321}
322
323sub _Edit {
324    my ( $Self, %Param ) = @_;
325
326    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
327    my $StateObject  = $Kernel::OM->Get('Kernel::System::State');
328
329    $LayoutObject->Block(
330        Name => 'Overview',
331        Data => \%Param,
332    );
333
334    $LayoutObject->Block( Name => 'ActionList' );
335    $LayoutObject->Block( Name => 'ActionOverview' );
336
337    # get valid list
338    my %ValidList        = $Kernel::OM->Get('Kernel::System::Valid')->ValidList();
339    my %ValidListReverse = reverse %ValidList;
340
341    $Param{ValidOption} = $LayoutObject->BuildSelection(
342        Data       => \%ValidList,
343        Name       => 'ValidID',
344        SelectedID => $Param{ValidID} || $ValidListReverse{valid},
345        Class      => 'Modernize Validate_Required ' . ( $Param{Errors}->{'ValidIDInvalid'} || '' ),
346    );
347    $Param{StateTypeOption} = $LayoutObject->BuildSelection(
348        Data       => { $StateObject->StateTypeList( UserID => 1 ), },
349        Name       => 'TypeID',
350        SelectedID => $Param{TypeID},
351        Class      => 'Modernize Validate_Required ' . ( $Param{Errors}->{'TypeIDInvalid'} || '' ),
352    );
353    $LayoutObject->Block(
354        Name => 'OverviewUpdate',
355        Data => {
356            %Param,
357            %{ $Param{Errors} },
358        },
359    );
360
361    # Several error messages can be used for Name.
362    $Param{Errors}->{InSettingNameServerError} //= 'Required';
363    $LayoutObject->Block(
364        Name => $Param{Errors}->{InSettingNameServerError} . 'NameServerError',
365    );
366
367    # Several error messages can be used for Valid option.
368    $Param{Errors}->{ValidOptionServerError} //= 'Required';
369    $LayoutObject->Block(
370        Name => $Param{Errors}->{ValidOptionServerError} . 'ValidOptionServerError',
371    );
372
373    if ( $Param{ID} ) {
374
375        my $StateName = $Kernel::OM->Get('Kernel::System::State')->StateLookup(
376            StateID => $Param{ID},
377        );
378
379        # Add warning in case the Type belongs a SysConfig setting.
380        my $SysConfigObject = $Kernel::OM->Get('Kernel::System::SysConfig');
381
382        # In case dirty setting, disable form.
383        my $IsDirtyConfig = 0;
384        my @IsDirtyResult = $SysConfigObject->ConfigurationDirtySettingsList();
385        my %IsDirtyList   = map { $_ => 1 } @IsDirtyResult;
386
387        my @IsStateInSysConfig = $SysConfigObject->ConfigurationEntityCheck(
388            EntityType => 'State',
389            EntityName => $StateName // '',
390        );
391        if (@IsStateInSysConfig) {
392            $LayoutObject->Block(
393                Name => 'StateInSysConfig',
394                Data => {
395                    OldName => $StateName,
396                },
397            );
398            for my $SettingName (@IsStateInSysConfig) {
399                $LayoutObject->Block(
400                    Name => 'StateInSysConfigRow',
401                    Data => {
402                        SettingName => $SettingName,
403                    },
404                );
405
406                # Verify if dirty setting.
407                if ( $IsDirtyList{$SettingName} ) {
408                    $IsDirtyConfig = 1;
409                }
410            }
411        }
412
413        if ($IsDirtyConfig) {
414            $LayoutObject->Block(
415                Name => 'StateInSysConfigDirty',
416            );
417        }
418    }
419
420    return 1;
421}
422
423sub _Overview {
424    my ( $Self, %Param ) = @_;
425
426    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
427
428    $LayoutObject->Block(
429        Name => 'Overview',
430        Data => \%Param,
431    );
432
433    $LayoutObject->Block( Name => 'ActionList' );
434    $LayoutObject->Block( Name => 'ActionAdd' );
435    $LayoutObject->Block( Name => 'Filter' );
436
437    $LayoutObject->Block(
438        Name => 'OverviewResult',
439        Data => \%Param,
440    );
441
442    my $StateObject = $Kernel::OM->Get('Kernel::System::State');
443    my %List        = $StateObject->StateList(
444        UserID => 1,
445        Valid  => 0,
446    );
447
448    # if there are any states, they are shown
449    if (%List) {
450
451        # get valid list
452        my %ValidList = $Kernel::OM->Get('Kernel::System::Valid')->ValidList();
453
454        for my $ListKey ( sort { lc $List{$a} cmp lc $List{$b} } keys %List ) {
455
456            my %Data = $StateObject->StateGet( ID => $ListKey );
457            $LayoutObject->Block(
458                Name => 'OverviewResultRow',
459                Data => {
460                    Valid => $ValidList{ $Data{ValidID} },
461                    %Data,
462                },
463            );
464        }
465    }
466
467    # otherwise a no data found msg is displayed
468    else {
469        $LayoutObject->Block(
470            Name => 'NoDataFoundMsg',
471            Data => {},
472        );
473    }
474    return 1;
475}
476
4771;
478