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