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