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::SysConfig::DB; 10 11use strict; 12use warnings; 13 14use MIME::Base64; 15use Time::HiRes(); 16use utf8; 17 18use Kernel::System::VariableCheck qw( :all ); 19 20our @ObjectDependencies = ( 21 'Kernel::Config', 22 'Kernel::System::Cache', 23 'Kernel::System::DB', 24 'Kernel::System::Encode', 25 'Kernel::System::Log', 26 'Kernel::System::Main', 27 'Kernel::System::YAML', 28); 29 30=head1 NAME 31 32Kernel::System::SysConfig::DB - Functions to manage system configuration settings interactions with the database. 33 34=head1 PUBLIC INTERFACE 35 36=head2 new() 37 38Create an object. Do not use it directly, instead use: 39 40 use Kernel::System::ObjectManager; 41 local $Kernel::OM = Kernel::System::ObjectManager->new(); 42 my $SysConfigDBObject = $Kernel::OM->Get('Kernel::System::SysConfig::DB'); 43 44=cut 45 46sub new { 47 my ( $Type, %Param ) = @_; 48 49 # allocate new hash for object 50 my $Self = {}; 51 bless( $Self, $Type ); 52 53 $Self->{CacheTTL} = 24 * 3600 * 30; # 1 month 54 55 return $Self; 56} 57 58=head2 DefaultSettingAdd() 59 60Add a new SysConfig default entry. 61 62 my $DefaultID = $SysConfigDBObject->DefaultSettingAdd( 63 Name => "ProductName", # (required) 64 Description => "Setting description", # (required) 65 Navigation => "ASimple::Path::Structure", # (required) 66 IsInvisible => 1, # (optional) 1 or 0, default 0 67 IsReadonly => 0, # (optional) 1 or 0, default 0 68 IsRequired => 1, # (optional) 1 or 0, default 0 69 IsValid => 1, # (optional) 1 or 0, default 0 70 HasConfigLevel => 200, # (optional) default 0 71 UserModificationPossible => 0, # (optional) 1 or 0, default 0 72 UserModificationActive => 0, # (optional) 1 or 0, default 0 73 UserPreferencesGroup => 'Some Group' # (optional) 74 XMLContentRaw => $XMLString, # (required) the setting XML structure as it is on the config file 75 XMLContentParsed => $XMLParsedToPerl, # (required) the setting XML structure converted into a Perl structure 76 XMLFilename => 'Framework.xml' # (required) the name of the XML file 77 EffectiveValue => $SettingEffectiveValue, # (required) the value as will be stored in the Perl configuration file 78 ExclusiveLockExpiryTime => '2017-02-01 12:23:13', # (optional) If not provided, method will calculate it. 79 UserID => 123, 80 NoCleanup => 0, # (optional) Default 0. If enabled, system WILL NOT DELETE CACHE. In this case, it must be done manually. 81 # USE IT CAREFULLY. 82 ); 83 84Returns: 85 86 my $DefaultID = 123; # false in case of an error 87 88=cut 89 90sub DefaultSettingAdd { 91 my ( $Self, %Param ) = @_; 92 93 # Store params for further usage. 94 my %DefaultVersionParams = %Param; 95 96 for my $Key ( 97 qw(Name Description Navigation XMLContentRaw XMLContentParsed XMLFilename EffectiveValue UserID) 98 ) 99 { 100 if ( !defined $Param{$Key} ) { 101 $Kernel::OM->Get('Kernel::System::Log')->Log( 102 Priority => 'error', 103 Message => "Need $Key!", 104 ); 105 106 return; 107 } 108 } 109 110 my @DefaultSettings = $Self->DefaultSettingList( 111 IncludeInvisible => 1, 112 ); 113 114 # Check duplicate name 115 my ($SettingData) = grep { $_->{Name} eq $Param{Name} } @DefaultSettings; 116 return if IsHashRefWithData($SettingData); 117 118 # Check config level. 119 $Param{HasConfigLevel} //= 0; 120 121 # The value should be a positive integer if defined. 122 if ( !IsPositiveInteger( $Param{HasConfigLevel} ) && $Param{HasConfigLevel} ne '0' ) { 123 $Kernel::OM->Get('Kernel::System::Log')->Log( 124 Priority => 'error', 125 Message => "HasConfigLevel must be an integer!", 126 ); 127 return; 128 } 129 130 # Check boolean parameters (0 as default value). 131 for my $Key (qw(IsInvisible IsReadonly IsRequired IsValid UserModificationPossible UserModificationActive)) { 132 $Param{$Key} = ( defined $Param{$Key} && $Param{$Key} ? 1 : 0 ); 133 } 134 135 # Serialize data as string. 136 for my $Key (qw(XMLContentParsed EffectiveValue)) { 137 $Param{$Key} = $Kernel::OM->Get('Kernel::System::YAML')->Dump( 138 Data => $Param{$Key}, 139 ); 140 $DefaultVersionParams{$Key} = $Param{$Key}; 141 } 142 143 # Set GuID. 144 $Param{ExclusiveLockGUID} //= 1; 145 146 # Set is dirty as enabled due it is a new setting. 147 $Param{IsDirty} = 1; 148 149 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 150 151 # Insert the default. 152 return if !$DBObject->Do( 153 SQL => ' 154 INSERT INTO sysconfig_default 155 (name, description, navigation, is_invisible, is_readonly, is_required, is_valid, has_configlevel, 156 user_modification_possible, user_modification_active, user_preferences_group, xml_content_raw, xml_content_parsed, xml_filename, effective_value, 157 is_dirty, exclusive_lock_guid, create_time, create_by, change_time, change_by) 158 VALUES 159 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)', 160 Bind => [ 161 \$Param{Name}, \$Param{Description}, \$Param{Navigation}, \$Param{IsInvisible}, 162 \$Param{IsReadonly}, \$Param{IsRequired}, \$Param{IsValid}, \$Param{HasConfigLevel}, 163 \$Param{UserModificationPossible}, \$Param{UserModificationActive}, \$Param{UserPreferencesGroup}, 164 \$Param{XMLContentRaw}, \$Param{XMLContentParsed}, \$Param{XMLFilename}, \$Param{EffectiveValue}, 165 \$Param{IsDirty}, \$Param{ExclusiveLockGUID}, \$Param{UserID}, \$Param{UserID}, 166 ], 167 ); 168 169 # Get default ID. 170 $DBObject->Prepare( 171 SQL => 'SELECT id FROM sysconfig_default WHERE name = ?', 172 Bind => [ \$Param{Name} ], 173 Limit => 1, 174 ); 175 176 my $DefaultID; 177 178 # Fetch the default setting ID. 179 ROW: 180 while ( my @Row = $DBObject->FetchrowArray() ) { 181 $DefaultID = $Row[0]; 182 last ROW; 183 } 184 185 # Add default setting version. 186 my $DefaultVersionID = $Self->DefaultSettingVersionAdd( 187 DefaultID => $DefaultID, 188 %DefaultVersionParams, 189 NoVersionID => 1, 190 ); 191 192 if ( !$Param{NoCleanup} ) { 193 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 194 $CacheObject->Delete( 195 Type => 'SysConfigDefault', 196 Key => 'DefaultSettingGet::' . $Param{Name}, 197 ); 198 $CacheObject->CleanUp( 199 Type => 'SysConfigDefaultListGet', 200 ); 201 $CacheObject->Delete( 202 Type => 'SysConfigDefaultList', 203 Key => 'DefaultSettingList', 204 ); 205 $CacheObject->CleanUp( 206 Type => 'SysConfigNavigation', 207 ); 208 $CacheObject->CleanUp( 209 Type => 'SysConfigEntities', 210 ); 211 $CacheObject->CleanUp( 212 Type => 'SysConfigIsDirty', 213 ); 214 } 215 216 # Return if not version inserted. 217 return if !$DefaultVersionID; 218 219 return $DefaultID; 220} 221 222=head2 DefaultSettingBulkAdd() 223 224Add new SysConfig default entries. 225 226 my $Success = $SysConfigDBObject->DefaultSettingBulkAdd( 227 Settings => { # (required) Hash of settings 228 "ACL::CacheTTL" => { 229 "EffectiveValue" => "--- '3600'\n", 230 "XMLContentParsed" => { 231 "Description" => [ 232 { 233 "Content" => "Cache time in ...", 234 "Translatable" => 1 235 }, 236 ], 237 "Name" => "ACL::CacheTTL", 238 "Navigation" => [ 239 { 240 "Content" => "Core::Ticket::ACL" 241 }, 242 ], 243 "Required" => 1, 244 "Valid" => 1, 245 "Value" => [ 246 { 247 "Item" => [ 248 { 249 "Content" => 3600, 250 "ValueRegex" => "^\\d+\$", 251 "ValueType" => "String" 252 }, 253 ], 254 }, 255 ], 256 }, 257 "XMLContentParsedYAML" => "---\nDescription:\n- Content: Cache...", 258 "XMLContentRaw" => "<Setting Name=\"ACL::CacheTTL\" Required=\"1\" ...", 259 "XMLFilename" => "Ticket.xml" 260 }, 261 ... 262 }, 263 SettingList => [ # list of current settings in DB 264 { 265 DefaultID => '123', 266 Name => 'SettingName1', 267 IsDirty => 1, 268 ExclusiveLockGUID => 0, 269 }, 270 # ... 271 ], 272 UserID => 1, # (required) UserID 273 ); 274 275=cut 276 277sub DefaultSettingBulkAdd { 278 my ( $Self, %Param ) = @_; 279 280 for my $Needed (qw(Settings UserID)) { 281 if ( !$Param{$Needed} ) { 282 $Kernel::OM->Get('Kernel::System::Log')->Log( 283 Priority => 'error', 284 Message => "Need $Needed!", 285 ); 286 return; 287 } 288 } 289 290 if ( ref $Param{Settings} ne 'HASH' ) { 291 $Kernel::OM->Get('Kernel::System::Log')->Log( 292 Priority => 'error', 293 Message => "Settings must be a hash!" 294 ); 295 return; 296 } 297 298 $Param{SettingList} //= []; 299 if ( ref $Param{SettingList} ne 'ARRAY' ) { 300 $Kernel::OM->Get('Kernel::System::Log')->Log( 301 Priority => 'error', 302 Message => "SettingList must be an array", 303 ); 304 } 305 306 my @Data; 307 308 SETTINGNAME: 309 for my $SettingName ( sort keys %{ $Param{Settings} } ) { 310 311 my ($BasicData) = grep { $_->{Name} eq $SettingName } @{ $Param{SettingList} }; 312 313 if ($BasicData) { 314 $Kernel::OM->Get('Kernel::System::Log')->Log( 315 Priority => 'error', 316 Message => "$SettingName should not exist!" 317 ); 318 next SETTINGNAME; 319 } 320 321 # Gather data for all records. 322 push @Data, [ 323 $SettingName, 324 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{Description}->[0]->{Content} || '', 325 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{Navigation}->[0]->{Content} || '', 326 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{Invisible} || 0, 327 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{ReadOnly} || 0, 328 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{Required} || 0, 329 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{Valid} || 0, 330 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{ConfigLevel} || 100, 331 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserModificationPossible} || 0, 332 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserModificationActive} || 0, 333 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserPreferencesGroup}, 334 $Param{Settings}->{$SettingName}->{XMLContentRaw}, 335 $Param{Settings}->{$SettingName}->{XMLContentParsedYAML}, 336 $Param{Settings}->{$SettingName}->{XMLFilename}, 337 $Param{Settings}->{$SettingName}->{EffectiveValue}, 338 1, 339 1, 340 'current_timestamp', 341 $Param{UserID}, 342 'current_timestamp', 343 $Param{UserID}, 344 ]; 345 } 346 347 return if !$Self->_BulkInsert( 348 Table => 'sysconfig_default', 349 Columns => [ 350 'name', 351 'description', 352 'navigation', 353 'is_invisible', 354 'is_readonly', 355 'is_required', 356 'is_valid', 357 'has_configlevel', 358 'user_modification_possible', 359 'user_modification_active', 360 'user_preferences_group', 361 'xml_content_raw', 362 'xml_content_parsed', 363 'xml_filename', 364 'effective_value', 365 'is_dirty', 366 'exclusive_lock_guid', 367 'create_time', 368 'create_by', 369 'change_time', 370 'change_by' 371 ], 372 Data => \@Data, 373 ); 374 375 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 376 377 $CacheObject->CleanUp( 378 Type => 'SysConfigDefaultListGet', 379 ); 380 $CacheObject->Delete( 381 Type => 'SysConfigDefaultList', 382 Key => 'DefaultSettingList', 383 ); 384 $CacheObject->CleanUp( 385 Type => 'SysConfigNavigation', 386 ); 387 $CacheObject->CleanUp( 388 Type => 'SysConfigEntities', 389 ); 390 $CacheObject->CleanUp( 391 Type => 'SysConfigIsDirty', 392 ); 393 394 return 1; 395} 396 397=head2 DefaultSettingVersionBulkAdd() 398 399 my $Success = $SysConfigDBObject->DefaultSettingVersionBulkAdd( 400 Settings => { # (required) Hash of settings 401 "ACL::CacheTTL" => { 402 "EffectiveValue" => "--- '3600'\n", 403 "XMLContentParsed" => { 404 "Description" => [ 405 { 406 "Content" => "Cache time in ...", 407 "Translatable" => 1 408 }, 409 ], 410 "Name" => "ACL::CacheTTL", 411 "Navigation" => [ 412 { 413 "Content" => "Core::Ticket::ACL" 414 }, 415 ], 416 "Required" => 1, 417 "Valid" => 1, 418 "Value" => [ 419 { 420 "Item" => [ 421 { 422 "Content" => 3600, 423 "ValueRegex" => "^\\d+\$", 424 "ValueType" => "String" 425 }, 426 ], 427 }, 428 ], 429 }, 430 "XMLContentParsedYAML" => "---\nDescription:\n- Content: Cache...", 431 "XMLContentRaw" => "<Setting Name=\"ACL::CacheTTL\" Required=\"1\" ...", 432 "XMLFilename" => "Ticket.xml" 433 }, 434 ... 435 }, 436 SettingList => [ # list of current settings in DB 437 { 438 DefaultID => '123', 439 Name => 'SettingName1', 440 IsDirty => 1, 441 ExclusiveLockGUID => 0, 442 }, 443 # ... 444 ], 445 UserID => 1, # (required) UserID 446 ); 447 448=cut 449 450sub DefaultSettingVersionBulkAdd { 451 my ( $Self, %Param ) = @_; 452 453 # Check needed stuff. 454 for my $Needed (qw(Settings SettingList UserID)) { 455 if ( !$Param{$Needed} ) { 456 $Kernel::OM->Get('Kernel::System::Log')->Log( 457 Priority => 'error', 458 Message => "Need $Needed!", 459 ); 460 return; 461 } 462 } 463 464 if ( ref $Param{Settings} ne 'HASH' ) { 465 $Kernel::OM->Get('Kernel::System::Log')->Log( 466 Priority => 'error', 467 Message => "Settings must be a hash!" 468 ); 469 return; 470 } 471 472 my @Data; 473 474 SETTINGNAME: 475 for my $SettingName ( sort keys %{ $Param{Settings} } ) { 476 477 my ($BasicData) = grep { $_->{Name} eq $SettingName } @{ $Param{SettingList} }; 478 479 if ( !$BasicData || !$BasicData->{DefaultID} ) { 480 $Kernel::OM->Get('Kernel::System::Log')->Log( 481 Priority => 'error', 482 Message => "DefaultID for $SettingName couldn't be determined, skipped!" 483 ); 484 next SETTINGNAME; 485 } 486 487 # Gather data for all records. 488 push @Data, [ 489 $BasicData->{DefaultID}, 490 $SettingName, 491 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{Description}->[0]->{Content} || '', 492 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{Navigation}->[0]->{Content} || '', 493 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{Invisible} || 0, 494 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{ReadOnly} || 0, 495 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{Required} || 0, 496 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{Valid} || 0, 497 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{ConfigLevel} || 100, 498 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserModificationPossible} || 0, 499 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserModificationActive} || 0, 500 $Param{Settings}->{$SettingName}->{XMLContentParsed}->{UserPreferencesGroup}, 501 $Param{Settings}->{$SettingName}->{XMLContentRaw}, 502 $Param{Settings}->{$SettingName}->{XMLContentParsedYAML}, 503 $Param{Settings}->{$SettingName}->{XMLFilename}, 504 $Param{Settings}->{$SettingName}->{EffectiveValue}, 505 'current_timestamp', 506 $Param{UserID}, 507 'current_timestamp', 508 $Param{UserID}, 509 ]; 510 } 511 512 return if !$Self->_BulkInsert( 513 Table => 'sysconfig_default_version', 514 Columns => [ 515 'sysconfig_default_id', 516 'name', 517 'description', 518 'navigation', 519 'is_invisible', 520 'is_readonly', 521 'is_required', 522 'is_valid', 523 'has_configlevel', 524 'user_modification_possible', 525 'user_modification_active', 526 'user_preferences_group', 527 'xml_content_raw', 528 'xml_content_parsed', 529 'xml_filename', 530 'effective_value', 531 'create_time', 532 'create_by', 533 'change_time', 534 'change_by', 535 ], 536 Data => \@Data, 537 ); 538 539 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 540 541 $CacheObject->CleanUp( 542 Type => 'SysConfigDefaultVersion', 543 ); 544 $CacheObject->CleanUp( 545 Type => 'SysConfigDefaultVersionList', 546 ); 547 548 return 1; 549} 550 551=head2 DefaultSettingGet() 552 553Get SysConfig default entry. 554 555 my %DefaultSetting = $SysConfigDBObject->DefaultSettingGet( 556 Name => "TheName", # (required) Setting name - prefered parameter. 557 # or 558 DefaultID => 4, # (required) DefaultID. Slightly slower execution. 559 NoCache => 0, # (optional) Default 0. If 1, cache will not be created. 560 ); 561 562Returns: 563 564 %DefaultSetting = ( 565 DefaultID => "123", 566 Name => "ProductName", 567 Description => "Defines the name of the application ...", 568 Navigation => "ASimple::Path::Structure", 569 IsInvisible => 1, # 1 or 0 570 IsReadonly => 0, # 1 or 0 571 IsRequired => 1, # 1 or 0 572 IsValid => 1, # 1 or 0 573 HasConfigLevel => 200, 574 UserModificationPossible => 0, # 1 or 0 575 UserModificationActive => 0, # 1 or 0 576 UserPreferencesGroup => 'Some Group', 577 XMLContentRaw => "The XML structure as it is on the config file", 578 XMLContentParsed => "XML parsed to Perl", 579 XMLFilename => "Framework.xml", 580 EffectiveValue => "Product 6", 581 IsDirty => 1, # 1 or 0 582 ExclusiveLockGUID => 'A32CHARACTERLONGSTRINGFORLOCKING', 583 ExclusiveLockUserID => 1, 584 ExclusiveLockExpiryTime => '2016-05-29 11:09:04', 585 CreateTime => "2016-05-29 11:04:04", 586 CreateBy => 1, 587 ChangeTime => "2016-05-29 11:04:04", 588 ChangeBy => 1, 589 SettingUID => 'Default12320160529110404', 590 ); 591 592=cut 593 594sub DefaultSettingGet { 595 my ( $Self, %Param ) = @_; 596 597 if ( !$Param{DefaultID} && !$Param{Name} ) { 598 $Kernel::OM->Get('Kernel::System::Log')->Log( 599 Priority => 'error', 600 Message => 'Need DefaultID or Name!', 601 ); 602 return; 603 } 604 605 my $SettingName = $Param{Name}; 606 607 if ( !$SettingName ) { 608 my %SettingData = $Self->DefaultSettingLookup( 609 DefaultID => $Param{DefaultID}, 610 ); 611 612 if ( !%SettingData || !$SettingData{Name} ) { 613 $Kernel::OM->Get('Kernel::System::Log')->Log( 614 Priority => 'error', 615 Message => "Setting with DefaultID = $Param{DefaultID} not found!", 616 ); 617 618 return; 619 } 620 621 $SettingName = $SettingData{Name}; 622 } 623 624 my $CacheType = "SysConfigDefault"; 625 my $CacheKey = "DefaultSettingGet::$SettingName"; 626 627 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 628 629 # Return cache. 630 my $Cache = $CacheObject->Get( 631 Type => $CacheType, 632 Key => $CacheKey, 633 ); 634 635 return %{$Cache} if ref $Cache eq 'HASH'; 636 637 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 638 639 # Get default from database. 640 return if !$DBObject->Prepare( 641 SQL => ' 642 SELECT id, name, description, navigation, is_invisible, is_readonly, is_required, is_valid, has_configlevel, 643 user_modification_possible, user_modification_active, user_preferences_group, xml_content_raw, 644 xml_content_parsed, xml_filename, effective_value, is_dirty, exclusive_lock_guid, exclusive_lock_user_id, 645 exclusive_lock_expiry_time, create_time, create_by, change_time, change_by 646 647 FROM sysconfig_default 648 WHERE name = ?', 649 Bind => [ \$SettingName ], 650 ); 651 652 my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML'); 653 654 my %DefaultSetting; 655 while ( my @Data = $DBObject->FetchrowArray() ) { 656 657 # De-serialize default data. 658 my $XMLContentParsed = $YAMLObject->Load( Data => $Data[13] ); 659 my $EffectiveValue = $YAMLObject->Load( Data => $Data[15] ); 660 661 my $TimeStamp = $Data[22]; 662 $TimeStamp =~ s{:|-|[ ]}{}gmsx; 663 664 %DefaultSetting = ( 665 DefaultID => $Data[0], 666 Name => $Data[1], 667 Description => $Data[2], 668 Navigation => $Data[3], 669 IsInvisible => $Data[4], 670 IsReadonly => $Data[5], 671 IsRequired => $Data[6], 672 IsValid => $Data[7], 673 HasConfigLevel => $Data[8], 674 UserModificationPossible => $Data[9], 675 UserModificationActive => $Data[10], 676 UserPreferencesGroup => $Data[11] || '', 677 XMLContentRaw => $Data[12], 678 XMLContentParsed => $XMLContentParsed, 679 XMLFilename => $Data[14], 680 EffectiveValue => $EffectiveValue, 681 IsDirty => $Data[16] ? 1 : 0, 682 ExclusiveLockGUID => $Data[17], 683 ExclusiveLockUserID => $Data[18], 684 ExclusiveLockExpiryTime => $Data[19], 685 CreateTime => $Data[20], 686 CreateBy => $Data[21], 687 ChangeTime => $Data[22], 688 ChangeBy => $Data[23], 689 SettingUID => "Default$Data[0]$TimeStamp", 690 ); 691 } 692 693 if ( !$Param{NoCache} ) { 694 $CacheObject->Set( 695 Type => $CacheType, 696 Key => $CacheKey, 697 Value => \%DefaultSetting, 698 TTL => $Self->{CacheTTL}, 699 ); 700 } 701 702 return %DefaultSetting; 703} 704 705=head2 DefaultSettingLookup() 706 707Default setting lookup. 708 709 my %Result = $SysConfigDBObject->DefaultSettingLookup( 710 Name => "TheName", # (required) 711 # or 712 DefaultID => 4, # (required) 713 ); 714 715Returns: 716 717 %Result = ( 718 DefaultID => 4, 719 Name => 'TheName', 720 ); 721 722=cut 723 724sub DefaultSettingLookup { 725 my ( $Self, %Param ) = @_; 726 727 # Check needed stuff. 728 if ( !$Param{Name} && !$Param{DefaultID} ) { 729 $Kernel::OM->Get('Kernel::System::Log')->Log( 730 Priority => 'error', 731 Message => "Need Name or DefaultID!", 732 ); 733 return; 734 } 735 736 my @Bind; 737 738 my $SQL = ' 739 SELECT id, name 740 FROM sysconfig_default 741 WHERE 742 '; 743 744 if ( $Param{Name} ) { 745 $SQL .= 'name = ? '; 746 push @Bind, \$Param{Name}; 747 } 748 else { 749 $SQL .= "id = ? "; 750 push @Bind, \$Param{DefaultID}; 751 } 752 753 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 754 755 # db query 756 return if !$DBObject->Prepare( 757 SQL => $SQL, 758 Bind => \@Bind, 759 Limit => 1, 760 ); 761 762 my %Result; 763 764 ROW: 765 while ( my @Row = $DBObject->FetchrowArray() ) { 766 $Result{DefaultID} = $Row[0]; 767 $Result{Name} = $Row[1]; 768 last ROW; 769 } 770 771 return %Result; 772} 773 774=head2 DefaultSettingDelete() 775 776Delete a default setting from the database. 777 778 my $Success = $SysConfigDBObject->DefaultSettingDelete( 779 DefaultID => 123, 780 ); 781 782 my $Success = $SysConfigDBObject->DefaultSettingDelete( 783 Name => 'Name', 784 ); 785 786Returns: 787 788 $Success = 1; # or false in case of an error 789 790=cut 791 792sub DefaultSettingDelete { 793 my ( $Self, %Param ) = @_; 794 795 if ( !$Param{DefaultID} && !$Param{Name} ) { 796 $Kernel::OM->Get('Kernel::System::Log')->Log( 797 Priority => 'error', 798 Message => 'Need DefaultID or Name!', 799 ); 800 return; 801 } 802 803 my %DefaultSetting = $Self->DefaultSettingGet( 804 DefaultID => $Param{DefaultID} || undef, 805 Name => $Param{Name} || undef, 806 ); 807 return 1 if !IsHashRefWithData( \%DefaultSetting ); 808 809 my $DefaultID = $DefaultSetting{DefaultID}; 810 811 # Delete the entries in SysConfig default version. 812 my $DeleteDefaultVersion = $Self->DefaultSettingVersionDelete( 813 DefaultID => $DefaultID, 814 ); 815 816 # Return if not version deleted. 817 return if !$DeleteDefaultVersion; 818 819 # Delete default from the list. 820 return if !$Kernel::OM->Get('Kernel::System::DB')->Do( 821 SQL => 'DELETE FROM sysconfig_default WHERE id = ?', 822 Bind => [ \$DefaultID ], 823 ); 824 825 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 826 827 $CacheObject->Delete( 828 Type => 'SysConfigDefault', 829 Key => 'DefaultSettingGet::' . $DefaultSetting{Name}, 830 ); 831 $CacheObject->CleanUp( 832 Type => 'SysConfigDefaultListGet', 833 ); 834 $CacheObject->Delete( 835 Type => 'SysConfigDefaultList', 836 Key => 'DefaultSettingList', 837 ); 838 $CacheObject->CleanUp( 839 Type => 'SysConfigNavigation', 840 ); 841 $CacheObject->CleanUp( 842 Type => 'SysConfigEntities', 843 ); 844 $CacheObject->CleanUp( 845 Type => 'SysConfigIsDirty', 846 ); 847 848 # Clean cache for setting translations. 849 my %Languages = %{ $Kernel::OM->Get('Kernel::Config')->Get('DefaultUsedLanguages') }; 850 for my $Language ( sort keys %Languages ) { 851 $CacheObject->Delete( 852 Type => 'SysConfig', 853 Key => "SettingTranslatedGet::$Language" . "::$DefaultSetting{Name}", 854 ); 855 $CacheObject->Delete( 856 Type => 'SysConfig', 857 Key => "ConfigurationTranslatedGet::$Language", 858 ); 859 } 860 861 return 1; 862} 863 864=head2 DefaultSettingUpdate() 865 866Update SysConfig default entry. 867 868 my $Success = $SysConfigDBObject->DefaultSettingUpdate( 869 DefaultID => 123, 870 Name => "ProductName", 871 Description => "Defines the name of the application ...", 872 Navigation => "ASimple::Path::Structure", 873 IsInvisible => 1, # 1 or 0, optional, default 0 874 IsReadonly => 0, # 1 or 0, optional, default 0 875 IsRequired => 1, # 1 or 0, optional, default 0 876 IsValid => 1, # 1 or 0, optional, default 0 877 HasConfigLevel => 200, # optional, default 0 878 UserModificationPossible => 0, # 1 or 0, optional, default 0 879 UserModificationActive => 0, # 1 or 0, optional, default 0 880 UserPreferencesGroup => 'Some Group', 881 UserPreferencesGroup => 'Advanced', # optional 882 XMLContentRaw => $XMLString, # the XML structure as it is on the config file 883 XMLContentParsed => $XMLParsedToPerl, 884 XMLFilename => 'Framework.xml', 885 ExclusiveLockGUID => 1, 886 EffectiveValue => $SettingEffectiveValue, 887 UserID => 1, 888 ); 889 890Returns: 891 892 $Success = 1; # or false in case of an error. 893 894=cut 895 896sub DefaultSettingUpdate { 897 my ( $Self, %Param ) = @_; 898 899 # Store params for further usage. 900 my %DefaultVersionParams = %Param; 901 902 for my $Key ( 903 qw( 904 DefaultID Name Description Navigation XMLContentRaw XMLContentParsed XMLFilename 905 ExclusiveLockGUID EffectiveValue UserID 906 ) 907 ) 908 { 909 if ( !defined $Param{$Key} ) { 910 $Kernel::OM->Get('Kernel::System::Log')->Log( 911 Priority => 'error', 912 Message => "Need $Key!", 913 ); 914 915 return; 916 } 917 } 918 919 # Get default setting 920 my %DefaultSetting = $Self->DefaultSettingGet( 921 DefaultID => $Param{DefaultID}, 922 ); 923 924 # Check if setting exists. 925 return if !IsHashRefWithData( \%DefaultSetting ); 926 927 # Don't allow name changes, due this is consider a NEW setting. 928 return if $DefaultSetting{Name} ne $Param{Name}; 929 930 # Check if the setting is locked by the current user. 931 return if !$Self->DefaultSettingIsLockedByUser( 932 %Param, 933 ExclusiveLockUserID => $Param{UserID}, 934 ); 935 936 # Check config level, set 0 as default value. 937 $Param{HasConfigLevel} //= 0; 938 939 if ( !IsPositiveInteger( $Param{HasConfigLevel} ) && $Param{HasConfigLevel} ne '0' ) { 940 $Kernel::OM->Get('Kernel::System::Log')->Log( 941 Priority => 'error', 942 Message => "HasConfigLevel must be an integer!", 943 ); 944 945 return; 946 } 947 948 # Check boolean parameters, set 0 as default value. 949 for my $Key (qw(IsInvisible IsReadonly IsRequired IsValid UserModificationPossible UserModificationActive)) { 950 $Param{$Key} = ( defined $Param{$Key} && $Param{$Key} ? 1 : 0 ); 951 } 952 953 # Check if we really need to update. 954 my $IsDifferent = 0; 955 for my $Key ( 956 qw( 957 DefaultID Description Navigation IsInvisible HasConfigLevel XMLContentRaw 958 XMLContentParsed XMLFilename ExclusiveLockGUID EffectiveValue HasConfigLevel IsInvisible 959 IsReadonly IsRequired IsValid UserModificationPossible UserModificationActive UserPreferencesGroup 960 ) 961 ) 962 { 963 my $DataIsDifferent = DataIsDifferent( 964 Data1 => $Param{$Key}, 965 Data2 => $DefaultSetting{$Key}, 966 ); 967 if ($DataIsDifferent) { 968 $IsDifferent = 1; 969 } 970 } 971 972 return 1 if !$IsDifferent; 973 974 # Serialize data as string. 975 for my $Key (qw(XMLContentParsed EffectiveValue)) { 976 $Param{$Key} = $Kernel::OM->Get('Kernel::System::YAML')->Dump( 977 Data => $Param{$Key}, 978 ); 979 $DefaultVersionParams{$Key} = $Param{$Key}; 980 } 981 982 # Set is dirty value. 983 $Param{IsDirty} = 1; 984 985 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 986 987 # Insert the default. 988 return if !$DBObject->Do( 989 SQL => ' 990 UPDATE sysconfig_default 991 SET description = ?, navigation = ?, is_invisible = ?, is_readonly = ?, 992 is_required = ?, is_valid = ?, has_configlevel = ?, user_modification_possible = ?, user_modification_active = ?, 993 user_preferences_group = ?, xml_content_raw = ?, xml_content_parsed = ?, xml_filename =?, effective_value = ?, 994 is_dirty = ?, change_time = current_timestamp, change_by = ? 995 WHERE id = ?', 996 Bind => [ 997 \$Param{Description}, \$Param{Navigation}, \$Param{IsInvisible}, \$Param{IsReadonly}, 998 \$Param{IsRequired}, \$Param{IsValid}, \$Param{HasConfigLevel}, \$Param{UserModificationPossible}, 999 \$Param{UserModificationActive}, \$Param{UserPreferencesGroup}, \$Param{XMLContentRaw}, 1000 \$Param{XMLContentParsed}, 1001 \$Param{XMLFilename}, \$Param{EffectiveValue}, \$Param{IsDirty}, \$Param{UserID}, \$Param{DefaultID}, 1002 ], 1003 ); 1004 1005 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 1006 1007 $CacheObject->Delete( 1008 Type => 'SysConfigDefault', 1009 Key => 'DefaultSettingGet::' . $DefaultSetting{Name}, 1010 ); 1011 $CacheObject->CleanUp( 1012 Type => 'SysConfigDefaultListGet', 1013 ); 1014 $CacheObject->Delete( 1015 Type => 'SysConfigDefaultList', 1016 Key => 'DefaultSettingList', 1017 ); 1018 $CacheObject->CleanUp( 1019 Type => 'SysConfigNavigation', 1020 ); 1021 $CacheObject->CleanUp( 1022 Type => 'SysConfigEntities', 1023 ); 1024 $CacheObject->CleanUp( 1025 Type => 'SysConfigIsDirty', 1026 ); 1027 1028 # Clean cache for setting translations. 1029 my %Languages = %{ $Kernel::OM->Get('Kernel::Config')->Get('DefaultUsedLanguages') }; 1030 for my $Language ( sort keys %Languages ) { 1031 $CacheObject->Delete( 1032 Type => 'SysConfig', 1033 Key => "SettingTranslatedGet::$Language" . "::$DefaultSetting{Name}", 1034 ); 1035 $CacheObject->Delete( 1036 Type => 'SysConfig', 1037 Key => "ConfigurationTranslatedGet::$Language", 1038 ); 1039 } 1040 1041 # Add default setting version. 1042 my $DefaultVersionID = $Self->DefaultSettingVersionAdd( 1043 DefaultID => $Param{DefaultID}, 1044 %DefaultVersionParams, 1045 NoVersionID => 1, 1046 ); 1047 1048 # Return if not version inserted. 1049 return if !$DefaultVersionID; 1050 1051 # Unlock setting 1052 my $IsUnlock = $Self->DefaultSettingUnlock( 1053 DefaultID => $Param{DefaultID}, 1054 ); 1055 if ( !$IsUnlock ) { 1056 $Kernel::OM->Get('Kernel::System::Log')->Log( 1057 Priority => 'error', 1058 Message => "Default setting with ID: $Param{DefaultID} was not possible to unlock!", 1059 ); 1060 return; 1061 } 1062 1063 return 1; 1064} 1065 1066=head2 DefaultSettingSearch() 1067 1068Search for settings which contains given term(Search) in the xml_content_raw column. 1069 1070 my @Result = $SysConfigDBObject->DefaultSettingSearch( 1071 Search => 'Entity', # Search term 1072 SearchType => 'XMLContent', # XMLContent or Metadata 1073 CategoryFiles => ['Framework.xml', 'Ticket.xml', ], # (optional) 1074 Valid => 0, # (optional) By default, system returns all Settings (valid and invalid) 1075 # if set to 1, search only for valid, 1076 # if set to 0, search also for invalid. 1077 IncludeInvisible => 0, # (optional) Default 0 1078 ); 1079 1080or 1081 1082 my @Result = $SysConfigDBObject->DefaultSettingSearch( 1083 Search => ['Framework.xml' 'Ticket,xml'], 1084 SearchType => 'Filename', 1085 Valid => 1, 1086 ); 1087 1088Returns: 1089 1090 @Result = ( 1091 'ACL::CacheTTL', 1092 'ACLKeysLevel1Change', 1093 ... 1094 ); 1095 1096=cut 1097 1098sub DefaultSettingSearch { 1099 my ( $Self, %Param ) = @_; 1100 1101 if ( !$Param{Search} && !$Param{CategoryFiles} ) { 1102 $Kernel::OM->Get('Kernel::System::Log')->Log( 1103 Priority => 'error', 1104 Message => "Need Search or CategoryFiles!", 1105 ); 1106 return; 1107 } 1108 1109 if ( $Param{CategoryFiles} && !IsArrayRefWithData( $Param{CategoryFiles} ) ) { 1110 $Kernel::OM->Get('Kernel::System::Log')->Log( 1111 Priority => 'error', 1112 Message => "CategoryFiles is invalid!", 1113 ); 1114 return; 1115 } 1116 1117 $Param{SearchType} //= 'XMLContent'; 1118 $Param{IncludeInvisible} //= 0; 1119 1120 my $Valid = 0; 1121 if ( defined $Param{Valid} ) { 1122 $Valid = $Param{Valid} ? 1 : 0; 1123 } 1124 1125 my @Bind = (); 1126 1127 my $SQL = ' 1128 SELECT name 1129 FROM sysconfig_default 1130 WHERE 1 = 1'; 1131 1132 if ($Valid) { 1133 $SQL .= ' 1134 AND is_valid = ?'; 1135 push @Bind, \$Valid; 1136 } 1137 1138 if ( !$Param{IncludeInvisible} ) { 1139 $SQL .= ' 1140 AND is_invisible = ?'; 1141 push @Bind, \0; 1142 } 1143 1144 my $Column = 'xml_content_raw'; 1145 1146 if ( lc $Param{SearchType} eq 'metadata' ) { 1147 $Column = [qw(name description navigation)]; 1148 } 1149 1150 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 1151 1152 if ( $Param{Search} ) { 1153 my %QueryCondition = $DBObject->QueryCondition( 1154 Key => $Column, 1155 Value => $Param{Search}, 1156 SearchPrefix => "*", 1157 SearchSuffix => "*", 1158 BindMode => 1, 1159 ); 1160 1161 $SQL .= ' AND ' . $QueryCondition{SQL}; 1162 push @Bind, @{ $QueryCondition{Values} }; 1163 } 1164 1165 if ( $Param{CategoryFiles} ) { 1166 1167 @{ $Param{CategoryFiles} } = map {"($_)"} @{ $Param{CategoryFiles} }; 1168 $Param{CategoryFiles} = join 'OR', @{ $Param{CategoryFiles} }; 1169 1170 my %QueryCondition = $DBObject->QueryCondition( 1171 Key => 'xml_filename', 1172 Value => $Param{CategoryFiles}, 1173 SearchPrefix => "", 1174 SearchSuffix => "", 1175 BindMode => 1, 1176 ); 1177 1178 $SQL .= ' AND ( ' . $QueryCondition{SQL} . ' )'; 1179 push @Bind, @{ $QueryCondition{Values} }; 1180 1181 } 1182 1183 $SQL .= ' 1184 ORDER BY name asc'; 1185 1186 # db query 1187 return if !$DBObject->Prepare( 1188 SQL => $SQL, 1189 Bind => \@Bind, 1190 ); 1191 1192 my @Result; 1193 1194 ROW: 1195 while ( my @Row = $DBObject->FetchrowArray() ) { 1196 push @Result, $Row[0]; 1197 } 1198 1199 return @Result; 1200} 1201 1202=head2 DefaultSettingListGet() 1203 1204Get default setting list with complete data. 1205 1206 my @List = $SysConfigDBObject->DefaultSettingListGet( 1207 IsInvisible => 1, # 1 or 0 1208 IsReadonly => 0, # 1 or 0 1209 IsRequired => 1, # 1 or 0 1210 IsValid => 1, # 1 or 0 1211 IsDirty => 1, # 1 or 0 1212 HasConfigLevel => 0, # 1 or 0 1213 UserModificationPossible => 0, # 1 or 0 1214 UserModificationActive => 0, # 1 or 0 1215 UserPreferencesGroup => 'Some Group', 1216 Navigation => 'ASimple::Path::Structure', 1217 Locked => 1, # check for locked settings 1218 Category => 'OTRS', # optional (requires CategoryFiles) 1219 CategoryFiles => ['Framework.xml', 'Ticket.xml', ], # optional (requires Category) 1220 NoCache => 0, # (optional) Default 0. If set, system will not generate cache. 1221 ); 1222 1223Returns: 1224 1225 @List = ( 1226 { 1227 DefaultID => 123, 1228 Name => "ProductName", 1229 Description => "Defines the name of the application ...", 1230 Navigation => "ASimple::Path::Structure", 1231 IsInvisible => 1, 1232 IsReadonly => 0, 1233 IsRequired => 1, 1234 IsValid => 1, 1235 HasConfigLevel => 200, 1236 UserModificationPossible => 0, # 1 or 0 1237 UserModificationActive => 0, # 1 or 0 1238 UserPreferencesGroup => 'Advanced', # optional 1239 XMLContentRaw => "The XML structure as it is on the config file", 1240 XMLContentParsed => "XML parsed to Perl", 1241 XMLFilename => "Framework.xml", 1242 EffectiveValue => "Product 6", 1243 IsDirty => 1, # 1 or 0 1244 ExclusiveLockGUID => 'A32CHARACTERLONGSTRINGFORLOCKING', 1245 ExclusiveLockUserID => 1, 1246 ExclusiveLockExpiryTime => '2016-05-29 11:09:04', 1247 CreateTime => "2016-05-29 11:04:04", 1248 CreateBy => 1, 1249 ChangeTime => "2016-05-29 11:04:04", 1250 ChangeBy => 1, 1251 SettingUID => 'Default4717141789', 1252 }, 1253 { 1254 DefaultID => 321, 1255 Name => 'FieldName', 1256 # ... 1257 ChangeTime => '2011-01-01 01:01:01', 1258 ChangeBy => 1, 1259 SettingUID => 'Default4717141781', 1260 }, 1261 # ... 1262 ); 1263 1264=cut 1265 1266sub DefaultSettingListGet { 1267 my ( $Self, %Param ) = @_; 1268 1269 if ( $Param{Category} ) { 1270 if ( !IsArrayRefWithData( $Param{CategoryFiles} ) ) { 1271 $Kernel::OM->Get('Kernel::System::Log')->Log( 1272 Priority => 'error', 1273 Message => "CategoryFiles are invalid!", 1274 ); 1275 return; 1276 } 1277 } 1278 if ( $Param{CategoryFiles} && !$Param{Category} ) { 1279 $Kernel::OM->Get('Kernel::System::Log')->Log( 1280 Priority => 'error', 1281 Message => "Need Category!", 1282 ); 1283 } 1284 1285 # Define SQL filters to be used in the queries. 1286 my %FieldFilters = ( 1287 IsInvisible => 'is_invisible', 1288 IsReadonly => 'is_readonly', 1289 IsRequired => 'is_required', 1290 IsValid => 'is_valid', 1291 IsDirty => 'is_dirty', 1292 HasConfigLevel => 'has_configlevel', 1293 UserModificationPossible => 'user_modification_possible', 1294 UserModificationActive => 'user_modification_active', 1295 UserPreferencesGroup => 'user_preferences_group', 1296 Navigation => 'navigation', 1297 ); 1298 1299 my @Filters; 1300 my @Bind; 1301 1302 my $CacheType = 'SysConfigDefaultListGet'; 1303 my $CacheKey = 'DefaultSettingListGet'; # this cache key gets more elements 1304 1305 # Check params have a default value. 1306 for my $Key ( sort keys %FieldFilters ) { 1307 if ( defined $Param{$Key} ) { 1308 push @Filters, " $FieldFilters{$Key} = ? "; 1309 push @Bind, \$Param{$Key}; 1310 1311 $CacheKey .= "::$FieldFilters{$Key} = $Param{$Key}"; 1312 } 1313 } 1314 1315 # Check for locked settings. 1316 if ( $Param{Locked} ) { 1317 push @Filters, " exclusive_lock_guid != '0' "; 1318 $CacheKey .= "::exclusive_lock_guid != '0'"; 1319 } 1320 1321 # Check for categories. 1322 if ( $Param{Category} ) { 1323 $CacheKey .= "::Category=$Param{Category}"; 1324 } 1325 1326 my $SQLFilter = ''; 1327 1328 # Loop over filters and set them on SQL and cache key. 1329 if ( IsArrayRefWithData( \@Filters ) ) { 1330 $SQLFilter = ' WHERE ' . join ' AND ', @Filters; 1331 } 1332 1333 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 1334 1335 if ( $Param{Category} ) { 1336 @{ $Param{CategoryFiles} } = map {"($_)"} @{ $Param{CategoryFiles} }; 1337 $Param{CategoryFiles} = join 'OR', @{ $Param{CategoryFiles} }; 1338 1339 my %QueryCondition = $DBObject->QueryCondition( 1340 Key => 'xml_filename', 1341 Value => $Param{CategoryFiles}, 1342 SearchPrefix => "", 1343 SearchSuffix => "", 1344 BindMode => 1, 1345 ); 1346 1347 if ($SQLFilter) { 1348 $SQLFilter .= ' AND ( ' . $QueryCondition{SQL} . ' )'; 1349 } 1350 else { 1351 $SQLFilter = ' WHERE ' . $QueryCondition{SQL}; 1352 } 1353 1354 push @Bind, @{ $QueryCondition{Values} }; 1355 } 1356 1357 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 1358 1359 # Return cache. 1360 my $Cache = $CacheObject->Get( 1361 Type => $CacheType, 1362 Key => $CacheKey, 1363 ); 1364 1365 return @{$Cache} if ref $Cache eq 'ARRAY'; 1366 1367 my $SQL = ' 1368 SELECT id, name, description, navigation, is_invisible, is_readonly, is_required, is_valid, has_configlevel, 1369 user_modification_possible, user_modification_active, user_preferences_group, xml_content_raw, 1370 xml_content_parsed, xml_filename, effective_value, is_dirty, exclusive_lock_guid, exclusive_lock_user_id, 1371 exclusive_lock_expiry_time, create_time, create_by, change_time, change_by 1372 FROM sysconfig_default'; 1373 1374 $SQLFilter //= ''; 1375 1376 $SQL .= $SQLFilter . ' ORDER BY id'; 1377 1378 return if !$DBObject->Prepare( 1379 SQL => $SQL, 1380 Bind => \@Bind, 1381 ); 1382 1383 my @Data; 1384 my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML'); 1385 1386 while ( my @Row = $DBObject->FetchrowArray() ) { 1387 1388 # De-serialize default data. 1389 my $XMLContentParsed = $YAMLObject->Load( Data => $Row[13] ); 1390 my $EffectiveValue = $YAMLObject->Load( Data => $Row[15] ); 1391 1392 my $TimeStamp = $Row[22]; 1393 $TimeStamp =~ s{:|-|[ ]}{}gmsx; 1394 1395 my %DefaultSetting = ( 1396 DefaultID => $Row[0], 1397 Name => $Row[1], 1398 Description => $Row[2], 1399 Navigation => $Row[3], 1400 IsInvisible => $Row[4], 1401 IsReadonly => $Row[5], 1402 IsRequired => $Row[6], 1403 IsValid => $Row[7], 1404 HasConfigLevel => $Row[8], 1405 UserModificationPossible => $Row[9], 1406 UserModificationActive => $Row[10], 1407 UserPreferencesGroup => $Row[11] || '', 1408 XMLContentRaw => $Row[12], 1409 XMLContentParsed => $XMLContentParsed, 1410 XMLFilename => $Row[14], 1411 EffectiveValue => $EffectiveValue, 1412 IsDirty => $Row[16] ? 1 : 0, 1413 ExclusiveLockGUID => $Row[17], 1414 ExclusiveLockUserID => $Row[18], 1415 ExclusiveLockExpiryTime => $Row[19], 1416 CreateTime => $Row[20], 1417 CreateBy => $Row[21], 1418 ChangeTime => $Row[22], 1419 ChangeBy => $Row[23], 1420 SettingUID => "Default$Row[0]$TimeStamp", 1421 ); 1422 push @Data, \%DefaultSetting; 1423 } 1424 1425 if ( !$Param{NoCache} ) { 1426 $CacheObject->Set( 1427 Type => $CacheType, 1428 Key => $CacheKey, 1429 Value => \@Data, 1430 TTL => $Self->{CacheTTL}, 1431 ); 1432 } 1433 1434 return @Data; 1435} 1436 1437=head2 DefaultSettingList() 1438 1439Get list of all settings. 1440 1441 my @DefaultSettings = $SysConfigDBObject->DefaultSettingList( 1442 IncludeInvisible => 0, # (optional) Include invisible. Default 0. 1443 IsDirty => 0, # (optional) Filter settings by IsDirty. If not provided, returns all settings. 1444 Locked => 0, # (optional) Filter locked settings. 1445 ); 1446 1447Returns: 1448 1449 @DefaultSettings = ( 1450 { 1451 DefaultID => '123', 1452 Name => 'SettingName1', 1453 IsDirty => 1, 1454 IsVisible => 1, 1455 ExclusiveLockGUID => 0, 1456 XMLFilename => 'Filename.xml', 1457 }, 1458 { 1459 DefaultID => '124', 1460 Name => 'SettingName2', 1461 IsDirty => 0, 1462 IsVisible => 1, 1463 ExclusiveLockGUID => 'fjewifjowj...', 1464 XMLFilename => 'Filename.xml', 1465 }, 1466 ... 1467 ); 1468 1469=cut 1470 1471sub DefaultSettingList { 1472 my ( $Self, %Param ) = @_; 1473 1474 my $CacheType = 'SysConfigDefaultList'; 1475 my $CacheKey = 'DefaultSettingList'; 1476 1477 $Param{IncludeInvisible} //= 0; 1478 1479 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 1480 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 1481 1482 # Return cache. 1483 my $Cache = $CacheObject->Get( 1484 Type => $CacheType, 1485 Key => $CacheKey, 1486 ); 1487 1488 my @DataRaw; 1489 if ( ref $Cache eq 'ARRAY' ) { 1490 @DataRaw = @{$Cache}; 1491 } 1492 1493 if ( !@DataRaw ) { 1494 1495 # Start SQL statement. 1496 my $SQL = ' 1497 SELECT id, name, is_dirty, exclusive_lock_guid, xml_content_raw, xml_filename, is_invisible 1498 FROM sysconfig_default 1499 ORDER BY id'; 1500 1501 return if !$DBObject->Prepare( 1502 SQL => $SQL, 1503 ); 1504 1505 while ( my @Row = $DBObject->FetchrowArray() ) { 1506 push @DataRaw, { 1507 DefaultID => $Row[0], 1508 Name => $Row[1], 1509 IsDirty => $Row[2], 1510 ExclusiveLockGUID => $Row[3], 1511 XMLContentRaw => $Row[4], 1512 XMLFilename => $Row[5], 1513 IsInvisible => $Row[6], 1514 }; 1515 } 1516 1517 $CacheObject->Set( 1518 Type => $CacheType, 1519 Key => $CacheKey, 1520 Value => \@DataRaw, 1521 TTL => $Self->{CacheTTL}, 1522 ); 1523 } 1524 1525 # Copy DataRaw to prevent modifications to in memory cache. 1526 my @Data = @DataRaw; 1527 1528 # filter 1529 if ( defined $Param{IsDirty} ) { 1530 @Data = grep { $_->{IsDirty} == $Param{IsDirty} } @Data; 1531 } 1532 if ( defined $Param{Locked} ) { 1533 if ( $Param{Locked} ) { 1534 1535 # Filter only locked settings 1536 @Data = grep { $_->{ExclusiveLockGUID} } @Data; 1537 } 1538 else { 1539 # Filter only unlocked settings 1540 @Data = grep { !$_->{ExclusiveLockGUID} } @Data; 1541 } 1542 } 1543 1544 if ( !$Param{IncludeInvisible} ) { 1545 1546 # Filter only those settings that are visible. 1547 @Data = grep { !$_->{IsInvisible} } @Data; 1548 } 1549 1550 return @Data; 1551} 1552 1553=head2 DefaultSettingLock() 1554 1555Lock Default setting(s) to the particular user. 1556 1557 my $ExclusiveLockGUID = $SysConfigDBObject->DefaultSettingLock( 1558 DefaultID => 1, # the ID of the setting that needs to be locked 1559 # or 1560 Name => 'SettingName', # the Name of the setting that needs to be locked 1561 # or 1562 LockAll => 1, # system locks all settings. 1563 Force => 1, # (optional) Force locking (do not check if it's already locked by another user). Default: 0. 1564 UserID => 1, # (required) 1565 ); 1566 1567Returns: 1568 1569 $ExclusiveLockGUID = 'azzHab72wIlAXDrxHexsI5aENsESxAO7'; # Setting locked 1570 1571 or 1572 1573 $ExclusiveLockGUID = undef; # Not locked 1574 1575=cut 1576 1577sub DefaultSettingLock { 1578 my ( $Self, %Param ) = @_; 1579 1580 if ( !$Param{UserID} ) { 1581 $Kernel::OM->Get('Kernel::System::Log')->Log( 1582 Priority => 'error', 1583 Message => "Need UserID!", 1584 ); 1585 return; 1586 } 1587 if ( !$Param{DefaultID} && !$Param{Name} && !$Param{LockAll} ) { 1588 $Kernel::OM->Get('Kernel::System::Log')->Log( 1589 Priority => 'error', 1590 Message => "Need DefaultID, Name or LockAll!", 1591 ); 1592 return; 1593 } 1594 1595 # Check if a deployment is locked, in that case it's not possible to lock a setting. 1596 my $DeploymentLocked = $Self->DeploymentIsLocked(); 1597 1598 if ($DeploymentLocked) { 1599 $Kernel::OM->Get('Kernel::System::Log')->Log( 1600 Priority => 'error', 1601 Message => "It's not possible to lock a setting if a deployment is currently locked.", 1602 ); 1603 return; 1604 } 1605 1606 my $Locked; 1607 1608 if ( !$Param{LockAll} ) { 1609 1610 # Check if it's already locked (skip if force is used). 1611 $Locked = $Self->DefaultSettingIsLocked( 1612 DefaultID => $Param{DefaultID}, 1613 Name => $Param{Name}, 1614 ); 1615 } 1616 1617 return if ( !$Param{Force} && $Locked ); 1618 1619 # Check if setting can be locked(IsReadonly). 1620 my %DefaultSetting; 1621 if ( !$Param{LockAll} ) { 1622 1623 %DefaultSetting = $Self->DefaultSettingGet(%Param); 1624 if ( $DefaultSetting{IsReadonly} ) { 1625 $Kernel::OM->Get('Kernel::System::Log')->Log( 1626 Priority => 'error', 1627 Message => "It's not possible to lock readonly setting $DefaultSetting{Name}" 1628 . " (UserID=$Param{UserID}!", 1629 ); 1630 return; 1631 } 1632 } 1633 1634 # Check correct length for ExclusiveLockGUID if defined. 1635 if ( defined $Param{ExclusiveLockGUID} && length( $Param{ExclusiveLockGUID} ) != 32 ) { 1636 $Kernel::OM->Get('Kernel::System::Log')->Log( 1637 Priority => 'error', 1638 Message => "The ExclusiveLockGUID is invalid!", 1639 ); 1640 return; 1641 } 1642 1643 # Setting is not locked, generate or use a locking string. 1644 my $ExclusiveLockGUID = $Param{ExclusiveLockGUID} || $Kernel::OM->Get('Kernel::System::Main')->GenerateRandomString( 1645 Length => 32, 1646 ); 1647 1648 my $SettingExpireTimeMinutes = 5; 1649 1650 # Get current time. 1651 my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 1652 $DateTimeObject->Add( 1653 Minutes => $SettingExpireTimeMinutes, 1654 ); 1655 1656 my $SQL = ' 1657 UPDATE sysconfig_default 1658 SET 1659 exclusive_lock_guid = ?, 1660 exclusive_lock_user_id = ?, 1661 exclusive_lock_expiry_time = ? 1662 '; 1663 my $ExpiryTime = $DateTimeObject->ToString(); 1664 my @Bind = ( 1665 \$ExclusiveLockGUID, \$Param{UserID}, 1666 \$ExpiryTime, 1667 ); 1668 1669 if ( $Param{DefaultID} ) { 1670 $SQL .= ' 1671 WHERE id = ?'; 1672 push @Bind, \$Param{DefaultID}; 1673 } 1674 elsif ( $Param{Name} ) { 1675 $SQL .= ' 1676 WHERE name = ?'; 1677 push @Bind, \$Param{Name}; 1678 } 1679 1680 # Add locking data to the setting record 1681 return if !$Kernel::OM->Get('Kernel::System::DB')->Do( 1682 SQL => $SQL, 1683 Bind => \@Bind, 1684 ); 1685 1686 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 1687 1688 # Check if there was cache for this type/key pair. 1689 my $DefaultSettingListGet = $CacheObject->Get( 1690 Type => 'SysConfigDefaultListGet', 1691 Key => 'DefaultSettingListGet', 1692 ); 1693 1694 if ( $Param{LockAll} ) { 1695 $CacheObject->CleanUp( 1696 Type => 'SysConfigDefault', 1697 ); 1698 } 1699 else { 1700 $CacheObject->Delete( 1701 Type => 'SysConfigDefault', 1702 Key => 'DefaultSettingGet::' . $DefaultSetting{Name}, 1703 ); 1704 } 1705 $CacheObject->CleanUp( 1706 Type => 'SysConfigDefaultListGet', 1707 ); 1708 1709 # Warm up the cache. 1710 if ($DefaultSettingListGet) { 1711 1712 # Warm up existing cache. 1713 1714 if (%DefaultSetting) { 1715 1716 # Update one setting. 1717 1718 my $Index; 1719 1720 # Determine index of the element. 1721 LOOPINDEX: 1722 for my $LoopIndex ( 0 .. scalar @{$DefaultSettingListGet} - 1 ) { 1723 next LOOPINDEX if $DefaultSettingListGet->[$LoopIndex]->{DefaultID} ne $DefaultSetting{DefaultID}; 1724 1725 $Index = $LoopIndex; 1726 last LOOPINDEX; 1727 } 1728 1729 # Update value. 1730 $DefaultSettingListGet->[$Index] = { 1731 %{ $DefaultSettingListGet->[$Index] }, 1732 ExclusiveLockExpiryTime => $ExpiryTime, 1733 ExclusiveLockGUID => $ExclusiveLockGUID, 1734 ExclusiveLockUserID => $Param{UserID}, 1735 }; 1736 } 1737 else { 1738 # Update all settings. 1739 for my $Index ( 0 .. scalar @{$DefaultSettingListGet} - 1 ) { 1740 $DefaultSettingListGet->[$Index] = { 1741 %{ $DefaultSettingListGet->[$Index] }, 1742 ExclusiveLockExpiryTime => $ExpiryTime, 1743 ExclusiveLockGUID => $ExclusiveLockGUID, 1744 ExclusiveLockUserID => $Param{UserID}, 1745 }; 1746 } 1747 } 1748 1749 # Set new cache value. 1750 $CacheObject->Set( 1751 Type => 'SysConfigDefaultListGet', 1752 Key => 'DefaultSettingListGet', 1753 Value => $DefaultSettingListGet, 1754 TTL => $Self->{CacheTTL}, 1755 CacheInBackend => 0, 1756 ); 1757 } 1758 1759 $CacheObject->Delete( 1760 Type => 'SysConfigDefaultList', 1761 Key => 'DefaultSettingList', 1762 ); 1763 1764 return $ExclusiveLockGUID; 1765} 1766 1767=head2 DefaultSettingIsLocked() 1768 1769Check if particular Default Setting is locked. 1770 1771 my $Locked = $SysConfigDBObject->DefaultSettingIsLocked( 1772 DefaultID => 1, # the ID of the setting that needs to be checked 1773 # or 1774 Name => 'SettingName', # the Name of the setting that needs to be checked 1775 GetLockUserID => 1, # optional, it will return the ExclusiveLockUserID in case it exist 1776 ); 1777 1778Returns: 1779 1780 $Locked = 1; # Locked 1781 or 1782 $Locked = 123 # The UserID 1783 1784=cut 1785 1786sub DefaultSettingIsLocked { 1787 my ( $Self, %Param ) = @_; 1788 1789 if ( !$Param{DefaultID} && !$Param{Name} ) { 1790 $Kernel::OM->Get('Kernel::System::Log')->Log( 1791 Priority => 'error', 1792 Message => "Need DefaultID or Name!", 1793 ); 1794 return; 1795 } 1796 1797 my %DefaultSetting = $Self->DefaultSettingGet( 1798 DefaultID => $Param{DefaultID}, 1799 Name => $Param{Name}, 1800 ); 1801 1802 # The setting is not available, user can't update it anyways 1803 return 0 if !%DefaultSetting; 1804 1805 # Check if it's locked. 1806 return 0 if !$DefaultSetting{ExclusiveLockExpiryTime}; 1807 1808 my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 1809 1810 # Setting was locked, check if lock has expired. 1811 my $LockedDateTimeObject = $Kernel::OM->Create( 1812 'Kernel::System::DateTime', 1813 ObjectParams => { 1814 String => $DefaultSetting{ExclusiveLockExpiryTime}, 1815 }, 1816 ); 1817 1818 my $Locked = $LockedDateTimeObject > $DateTimeObject ? 1 : 0; 1819 1820 # Remove locking if lock time is expired. 1821 if ( !$Locked ) { 1822 $Self->DefaultSettingUnlock( DefaultID => $Param{DefaultID} ); 1823 } 1824 1825 # Check if retrieve the ExclusiveLockUserID is needed 1826 elsif ( $Param{GetLockUserID} ) { 1827 $Locked = $DefaultSetting{ExclusiveLockUserID}; 1828 } 1829 1830 return $Locked; 1831} 1832 1833=head2 DefaultSettingIsLockedByUser() 1834 1835Check if particular Default Setting is locked. 1836 1837 my $LockedByUser = $SysConfigDBObject->DefaultSettingIsLockedByUser( 1838 DefaultID => 1, # the ID of the setting that needs to be checked 1839 # or 1840 Name => 'SettingName', # the name of the setting that needs to be checked 1841 ExclusiveLockUserID => 2, # the user should have locked the setting 1842 ExclusiveLockGUID => 'AGUIDSTRING', # the GUID used to locking the setting 1843 ); 1844 1845Returns: 1846 1847 $LockedByUser = 1; 1848 1849=cut 1850 1851sub DefaultSettingIsLockedByUser { 1852 my ( $Self, %Param ) = @_; 1853 1854 for my $Needed (qw(ExclusiveLockUserID ExclusiveLockGUID)) { 1855 if ( !$Param{$Needed} ) { 1856 $Kernel::OM->Get('Kernel::System::Log')->Log( 1857 Priority => 'error', 1858 Message => "Need $Needed!", 1859 ); 1860 return; 1861 } 1862 } 1863 if ( !$Param{DefaultID} && !$Param{Name} ) { 1864 $Kernel::OM->Get('Kernel::System::Log')->Log( 1865 Priority => 'error', 1866 Message => "Need DefaultID or Name!", 1867 ); 1868 return; 1869 } 1870 1871 return if !IsStringWithData( $Param{ExclusiveLockGUID} ); 1872 1873 # Get default setting. 1874 my %DefaultSetting = $Self->DefaultSettingGet( 1875 DefaultID => $Param{DefaultID}, 1876 Name => $Param{Name}, 1877 ); 1878 1879 # Check if setting exists. 1880 return if !IsHashRefWithData( \%DefaultSetting ); 1881 1882 # Check ExclusiveLockUserID 1883 return if !$DefaultSetting{ExclusiveLockUserID}; 1884 return if $DefaultSetting{ExclusiveLockUserID} ne $Param{ExclusiveLockUserID}; 1885 1886 # Check ExclusiveLockGUID. 1887 return if !$DefaultSetting{ExclusiveLockGUID}; 1888 return if $DefaultSetting{ExclusiveLockGUID} ne $Param{ExclusiveLockGUID}; 1889 1890 my $ExclusiveLockGUID = $DefaultSetting{ExclusiveLockGUID}; 1891 1892 # Setting was locked, check if lock has expired. 1893 my $CurrentDateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 1894 1895 my $LockedDateTimeObject = $Kernel::OM->Create( 1896 'Kernel::System::DateTime', 1897 ObjectParams => { 1898 String => $DefaultSetting{ExclusiveLockExpiryTime}, 1899 }, 1900 ); 1901 1902 my $Locked = $LockedDateTimeObject > $CurrentDateTimeObject ? 1 : 0; 1903 1904 # Extend locking time if the settings was already locked for this user but the time was expired. 1905 if ( !$Locked ) { 1906 1907 $ExclusiveLockGUID = $Self->DefaultSettingLock( 1908 UserID => $Param{ExclusiveLockUserID}, 1909 DefaultID => $Param{DefaultID}, 1910 Name => $Param{Name}, 1911 ExclusiveLockGUID => $Param{ExclusiveLockGUID}, 1912 ); 1913 } 1914 1915 return 1 if $ExclusiveLockGUID; 1916 return; 1917} 1918 1919=head2 DefaultSettingUnlock() 1920 1921Unlock particular or all Default Setting(s). 1922 1923 my $Success = $SysConfigDBObject->DefaultSettingUnlock( 1924 DefaultID => 1, # the ID of the setting that needs to be unlocked 1925 # or 1926 Name => 'SettingName', # the name of the setting that needs to be locked 1927 # or 1928 UnlockAll => 1, # unlock all settings 1929 ); 1930 1931Returns: 1932 1933 $Success = 1; 1934 1935=cut 1936 1937sub DefaultSettingUnlock { 1938 my ( $Self, %Param ) = @_; 1939 1940 if ( !$Param{DefaultID} && !$Param{Name} && !$Param{UnlockAll} ) { 1941 $Kernel::OM->Get('Kernel::System::Log')->Log( 1942 Priority => 'error', 1943 Message => "Need DefaultID, Name or UnlockAll!", 1944 ); 1945 return; 1946 } 1947 1948 my @SettingsLocked; 1949 1950 my %DefaultSetting; 1951 if ( $Param{UnlockAll} ) { 1952 1953 # Get locked settings only. 1954 @SettingsLocked = $Self->DefaultSettingList( 1955 Locked => 1, 1956 ); 1957 1958 # all settings are unlocked already 1959 return 1 if !@SettingsLocked; 1960 } 1961 else { 1962 %DefaultSetting = $Self->DefaultSettingGet( 1963 %Param, 1964 NoCache => 1, 1965 ); 1966 return if !%DefaultSetting; 1967 1968 push @SettingsLocked, \%DefaultSetting; 1969 } 1970 1971 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 1972 1973 my $SQL = ' 1974 UPDATE sysconfig_default 1975 SET 1976 exclusive_lock_guid = ?, 1977 exclusive_lock_user_id = ?, 1978 exclusive_lock_expiry_time = ? 1979 WHERE 1980 '; 1981 1982 my @Bind = ( \0, \undef, \undef ); 1983 if ( $Param{DefaultID} ) { 1984 $SQL .= ' 1985 id = ?'; 1986 push @Bind, \$Param{DefaultID}; 1987 } 1988 elsif ( $Param{Name} ) { 1989 $SQL .= ' 1990 name = ?'; 1991 push @Bind, \$Param{Name}; 1992 } 1993 else { 1994 # UnlockAll 1995 1996 $SQL .= ' 1997 exclusive_lock_guid != ? '; 1998 push @Bind, \0; 1999 } 2000 2001 # Remove locking from setting record. 2002 return if !$DBObject->Do( 2003 SQL => $SQL, 2004 Bind => \@Bind, 2005 ); 2006 2007 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 2008 2009 # Check if there was cache for this type/key pair. 2010 my $DefaultSettingListGet = $CacheObject->Get( 2011 Type => 'SysConfigDefaultListGet', 2012 Key => 'DefaultSettingListGet', 2013 ); 2014 2015 for my $Setting (@SettingsLocked) { 2016 $CacheObject->Delete( 2017 Type => 'SysConfigDefault', 2018 Key => 'DefaultSettingGet::' . $Setting->{Name}, 2019 ); 2020 } 2021 2022 $CacheObject->CleanUp( 2023 Type => 'SysConfigDefaultListGet', 2024 ); 2025 2026 # Warm up the cache. 2027 if ($DefaultSettingListGet) { 2028 2029 # Warm up existing cache. 2030 2031 if (%DefaultSetting) { 2032 2033 # Update one setting. 2034 2035 my $Index; 2036 2037 # Determine index of the element. 2038 LOOPINDEX: 2039 for my $LoopIndex ( 0 .. scalar @{$DefaultSettingListGet} - 1 ) { 2040 next LOOPINDEX if $DefaultSettingListGet->[$LoopIndex]->{DefaultID} ne $DefaultSetting{DefaultID}; 2041 2042 $Index = $LoopIndex; 2043 last LOOPINDEX; 2044 } 2045 2046 # Update value. 2047 $DefaultSettingListGet->[$Index] = { 2048 %{ $DefaultSettingListGet->[$Index] }, 2049 ExclusiveLockExpiryTime => undef, 2050 ExclusiveLockGUID => 0, 2051 ExclusiveLockUserID => undef, 2052 }; 2053 } 2054 else { 2055 # Update all settings. 2056 for my $Index ( 0 .. scalar @{$DefaultSettingListGet} - 1 ) { 2057 $DefaultSettingListGet->[$Index] = { 2058 %{ $DefaultSettingListGet->[$Index] }, 2059 ExclusiveLockExpiryTime => undef, 2060 ExclusiveLockGUID => 0, 2061 ExclusiveLockUserID => undef, 2062 }; 2063 } 2064 } 2065 2066 # Set new cache value. 2067 $CacheObject->Set( 2068 Type => 'SysConfigDefaultListGet', 2069 Key => 'DefaultSettingListGet', 2070 Value => $DefaultSettingListGet, 2071 TTL => $Self->{CacheTTL}, 2072 CacheInBackend => 0, 2073 ); 2074 } 2075 $CacheObject->Delete( 2076 Type => 'SysConfigDefaultList', 2077 Key => 'DefaultSettingList', 2078 ); 2079 2080 return 1; 2081} 2082 2083=head2 DefaultSettingDirtyCleanUp() 2084 2085Removes the IsDirty flag from default settings. 2086 2087 my $Success = $SysConfigDBObject->DefaultSettingDirtyCleanUp( 2088 AllSettings => 0, # (default 0) Reset all dirty settings. 2089 ); 2090 2091Returns: 2092 2093 $Success = 1; # or false in case of an error 2094 2095=cut 2096 2097sub DefaultSettingDirtyCleanUp { 2098 my ( $Self, %Param ) = @_; 2099 2100 my @DirtySettings; 2101 if ( !$Param{AllSettings} ) { 2102 @DirtySettings = $Self->DefaultSettingList( 2103 IsDirty => 1, 2104 ); 2105 } 2106 2107 # Remove is dirty flag for default settings. 2108 return if !$Kernel::OM->Get('Kernel::System::DB')->Do( 2109 SQL => ' 2110 UPDATE sysconfig_default 2111 SET is_dirty = 0 2112 WHERE is_dirty = 1', 2113 ); 2114 2115 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 2116 2117 # Check if there was cache for this type/key pair. 2118 my $DefaultSettingListGet = $CacheObject->Get( 2119 Type => 'SysConfigDefaultListGet', 2120 Key => 'DefaultSettingListGet', 2121 ); 2122 2123 if ( $Param{AllSettings} ) { 2124 $CacheObject->CleanUp( 2125 Type => 'SysConfigDefault', 2126 ); 2127 } 2128 else { 2129 for my $Setting (@DirtySettings) { 2130 $CacheObject->Delete( 2131 Type => 'SysConfigDefault', 2132 Key => 'DefaultSettingGet::' . $Setting->{Name}, 2133 ); 2134 } 2135 } 2136 $CacheObject->CleanUp( 2137 Type => 'SysConfigDefaultListGet', 2138 ); 2139 2140 # Warm up the cache. 2141 if ($DefaultSettingListGet) { 2142 2143 # Warm up existing cache. 2144 2145 # Update all settings. 2146 for my $Index ( 0 .. scalar @{$DefaultSettingListGet} - 1 ) { 2147 $DefaultSettingListGet->[$Index]->{IsDirty} = 0; 2148 } 2149 2150 # Set new cache value. 2151 $CacheObject->Set( 2152 Type => 'SysConfigDefaultListGet', 2153 Key => 'DefaultSettingListGet', 2154 Value => $DefaultSettingListGet, 2155 TTL => $Self->{CacheTTL}, 2156 CacheInBackend => 0, 2157 ); 2158 } 2159 2160 $CacheObject->Delete( 2161 Type => 'SysConfigDefaultList', 2162 Key => 'DefaultSettingList', 2163 ); 2164 $CacheObject->CleanUp( 2165 Type => 'SysConfigIsDirty', 2166 ); 2167 2168 return 1; 2169} 2170 2171=head2 DefaultSettingVersionAdd() 2172 2173Add a new SysConfig default version entry. 2174 2175 my $DefaultVersionID = $SysConfigDBObject->DefaultSettingVersionAdd( 2176 DefaultID => 456, 2177 Name => "ProductName", 2178 Description => "Defines the name of the application ...", 2179 Navigation => "ASimple::Path::Structure", 2180 IsInvisible => 1, # 1 or 0, optional, default 0 2181 IsReadonly => 0, # 1 or 0, optional, default 0 2182 IsRequired => 1, # 1 or 0, optional, default 0 2183 IsValid => 1, # 1 or 0, optional, default 0 2184 HasConfigLevel => 200, # optional, default 0 2185 UserModificationPossible => 0, # 1 or 0, optional, default 0 2186 UserModificationActive => 0, # 1 or 0, optional, default 0 2187 UserPreferencesGroup => 'Advanced', # optional 2188 XMLContentRaw => $XMLString, # the XML structure as it is on the config file 2189 XMLContentParsed => $XMLParsedToPerl, # the setting XML structure converted into YAML 2190 XMLFilename => 'Framework.xml' # the name of the XML file 2191 EffectiveValue => $YAMLEffectiveValue, # YAML EffectiveValue 2192 UserID => 1, 2193 NoCleanup => 0, # (optional) Default 0. If enabled, system WILL NOT DELETE CACHE. In this case, it must be done manually. 2194 # USE IT CAREFULLY. 2195 NoVersionID => 1, # 1 or 0, optional, default 0, prevents the return of DefaultVersionID and returns only 1 in case of success. 2196 ); 2197 2198Returns: 2199 2200 my $DefaultVersionID = 123; # false in case of an error 2201 2202=cut 2203 2204sub DefaultSettingVersionAdd { 2205 my ( $Self, %Param ) = @_; 2206 2207 for my $Key ( 2208 qw(DefaultID Name Description Navigation XMLContentRaw XMLContentParsed XMLFilename EffectiveValue UserID) 2209 ) 2210 { 2211 if ( !defined $Param{$Key} ) { 2212 $Kernel::OM->Get('Kernel::System::Log')->Log( 2213 Priority => 'error', 2214 Message => "Need $Key!", 2215 ); 2216 2217 return; 2218 } 2219 } 2220 2221 # Check config level. 2222 $Param{HasConfigLevel} //= 0; 2223 2224 if ( !IsPositiveInteger( $Param{HasConfigLevel} ) && $Param{HasConfigLevel} ne '0' ) { 2225 $Kernel::OM->Get('Kernel::System::Log')->Log( 2226 Priority => 'error', 2227 Message => "HasConfigLevel must be an integer!", 2228 ); 2229 2230 return; 2231 } 2232 2233 # Check boolean parameters, set 0 as default value. 2234 for my $Key (qw(IsInvisible IsReadonly IsRequired IsValid UserModificationPossible UserModificationActive)) { 2235 $Param{$Key} = ( defined $Param{$Key} && $Param{$Key} ? 1 : 0 ); 2236 } 2237 if ( $Param{EffectiveValue} eq "/usr/bin/gpg/mod" ) { 2238 $Kernel::OM->Get('Kernel::System::Log')->Log( 2239 Priority => 'error', 2240 Message => "Need!" 2241 ); 2242 } 2243 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 2244 2245 # Insert the default. 2246 return if !$DBObject->Do( 2247 SQL => ' 2248 INSERT INTO sysconfig_default_version 2249 (sysconfig_default_id, name, description, navigation, is_invisible, is_readonly, is_required, is_valid, 2250 has_configlevel, user_modification_possible, user_modification_active, user_preferences_group, 2251 xml_content_raw, xml_content_parsed, xml_filename, effective_value, create_time, create_by, 2252 change_time, change_by) 2253 VALUES 2254 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)', 2255 Bind => [ 2256 \$Param{DefaultID}, \$Param{Name}, \$Param{Description}, \$Param{Navigation}, 2257 \$Param{IsInvisible}, \$Param{IsReadonly}, \$Param{IsRequired}, \$Param{IsValid}, \$Param{HasConfigLevel}, 2258 \$Param{UserModificationPossible}, \$Param{UserModificationActive}, \$Param{UserPreferencesGroup}, 2259 \$Param{XMLContentRaw}, \$Param{XMLContentParsed}, \$Param{XMLFilename}, \$Param{EffectiveValue}, 2260 \$Param{UserID}, \$Param{UserID}, 2261 ], 2262 ); 2263 2264 # Get default version ID. 2265 $DBObject->Prepare( 2266 SQL => ' 2267 SELECT id 2268 FROM sysconfig_default_version 2269 WHERE sysconfig_default_id = ? AND name = ? 2270 ORDER BY id DESC 2271 ', 2272 Bind => [ \$Param{DefaultID}, \$Param{Name} ], 2273 Limit => 1, 2274 ); 2275 2276 # Fetch the default setting ID 2277 my $DefaultVersionID; 2278 2279 if ( $Param{NoVersionID} ) { 2280 $DefaultVersionID = 1; 2281 } 2282 else { 2283 while ( my @Row = $DBObject->FetchrowArray() ) { 2284 $DefaultVersionID = $Row[0]; 2285 } 2286 } 2287 if ( !$Param{NoCleanup} ) { 2288 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 2289 2290 $CacheObject->CleanUp( 2291 Type => 'SysConfigDefaultVersion', 2292 ); 2293 2294 $CacheObject->CleanUp( 2295 Type => 'SysConfigDefaultVersionList', 2296 ); 2297 } 2298 2299 return $DefaultVersionID; 2300} 2301 2302=head2 DefaultSettingVersionGet() 2303 2304Get SysConfig default version entry. 2305 2306 my %DefaultSettingVersion = $SysConfigDBObject->DefaultSettingVersionGet( 2307 DefaultVersionID => 123, 2308 ); 2309 2310Returns: 2311 2312 %DefaultSettingVersion = ( 2313 DefaultVersionID => 123, 2314 DefaultID => 456, 2315 Name => "ProductName", 2316 Description => "Defines the name of the application ...", 2317 Navigation => "ASimple::Path::Structure", 2318 IsInvisible => 1, # 1 or 0 2319 IsReadonly => 0, # 1 or 0 2320 IsRequired => 1, # 1 or 0 2321 IsValid => 1, # 1 or 0 2322 HasConfigLevel => 200, 2323 UserModificationPossible => 0, # 1 or 0 2324 UserModificationActive => 0, # 1 or 0 2325 UsePreferencesGroup => 'Advanced', # optional 2326 XMLContentRaw => "The XML structure as it is on the config file", 2327 XMLContentParsed => "XML parsed to Perl", 2328 XMLFilename => 'Framework.xml', 2329 EffectiveValue => "Product 6", 2330 CreateTime => "2016-05-29 11:04:04", 2331 CreateBy => 44, 2332 ChangeTime => "2016-05-29 11:04:04", 2333 ChangeBy => 88, 2334 ); 2335 2336=cut 2337 2338sub DefaultSettingVersionGet { 2339 my ( $Self, %Param ) = @_; 2340 2341 if ( !$Param{DefaultVersionID} ) { 2342 $Kernel::OM->Get('Kernel::System::Log')->Log( 2343 Priority => 'error', 2344 Message => 'Need DefaultVersionID!', 2345 ); 2346 return; 2347 } 2348 2349 my $FieldName; 2350 my $FieldValue; 2351 2352 if ( $Param{DefaultVersionID} ) { 2353 2354 # Set DefaultID as filter. 2355 $FieldName = 'id'; 2356 $FieldValue = $Param{DefaultVersionID}; 2357 } 2358 elsif ( $Param{Name} ) { 2359 2360 # Set Name as filter 2361 $FieldName = 'name'; 2362 $FieldValue = $Param{Name}; 2363 } 2364 2365 my $CacheType = "SysConfigDefaultVersion"; 2366 my $CacheKey = 'DefaultSettingVersionGet::' . $FieldName . '::' . $FieldValue; 2367 2368 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 2369 2370 # Return cache. 2371 my $Cache = $CacheObject->Get( 2372 Type => $CacheType, 2373 Key => $CacheKey, 2374 ); 2375 2376 return %{$Cache} if ref $Cache eq 'HASH'; 2377 2378 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 2379 2380 # Get default from database. 2381 return if !$DBObject->Prepare( 2382 SQL => ' 2383 SELECT id, sysconfig_default_id, name, description, navigation, is_invisible, is_readonly, is_required, 2384 is_valid, has_configlevel, user_modification_possible, user_modification_active, user_preferences_group, 2385 xml_content_raw, xml_content_parsed, xml_filename, effective_value, create_time, create_by, 2386 change_time, change_by 2387 FROM sysconfig_default_version 2388 WHERE ' . $FieldName . ' = ?', 2389 Bind => [ \$FieldValue ], 2390 ); 2391 2392 my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML'); 2393 2394 my %DefaultSettingVersion; 2395 while ( my @Data = $DBObject->FetchrowArray() ) { 2396 2397 # De-serialize default data. 2398 my $XMLContentParsed = $YAMLObject->Load( Data => $Data[14] ); 2399 my $EffectiveValue = $YAMLObject->Load( Data => $Data[16] ); 2400 2401 %DefaultSettingVersion = ( 2402 DefaultVersionID => $Data[0], 2403 DefaultID => $Data[1], 2404 Name => $Data[2], 2405 Description => $Data[3], 2406 Navigation => $Data[4], 2407 IsInvisible => $Data[5], 2408 IsReadonly => $Data[6], 2409 IsRequired => $Data[7], 2410 IsValid => $Data[8], 2411 HasConfigLevel => $Data[9], 2412 UserModificationPossible => $Data[10], 2413 UserModificationActive => $Data[11], 2414 UserPreferencesGroup => $Data[12] || '', 2415 XMLContentRaw => $Data[13], 2416 XMLContentParsed => $XMLContentParsed, 2417 XMLFilename => $Data[15], 2418 EffectiveValue => $EffectiveValue, 2419 CreateTime => $Data[17], 2420 CreateBy => $Data[18], 2421 ChangeTime => $Data[19], 2422 ChangeBy => $Data[20], 2423 ); 2424 } 2425 2426 $CacheObject->Set( 2427 Type => $CacheType, 2428 Key => $CacheKey, 2429 Value => \%DefaultSettingVersion, 2430 TTL => $Self->{CacheTTL}, 2431 ); 2432 2433 return %DefaultSettingVersion; 2434} 2435 2436=head2 DefaultSettingVersionDelete() 2437 2438Delete a default setting version from list based on default version ID or default ID. 2439 2440 my $Success = $SysConfigDBObject->DefaultSettingVersionDelete( 2441 DefaultVersionID => 123, 2442 ); 2443 2444or 2445 2446 my $Success = $SysConfigDBObject->DefaultSettingVersionDelete( 2447 DefaultID => 45, 2448 ); 2449 2450or 2451 2452 my $Success = $SysConfigDBObject->DefaultSettingVersionDelete( 2453 Name => 'AnyName', 2454 ); 2455 2456Returns: 2457 2458 $Success = 1; # or false in case of an error 2459 2460=cut 2461 2462sub DefaultSettingVersionDelete { 2463 my ( $Self, %Param ) = @_; 2464 2465 if ( !$Param{DefaultVersionID} && !$Param{DefaultID} && !$Param{Name} ) { 2466 $Kernel::OM->Get('Kernel::System::Log')->Log( 2467 Priority => 'error', 2468 Message => 'Need ID, DefaultID or Name!', 2469 ); 2470 return; 2471 } 2472 2473 my $FieldName; 2474 my $FieldValue; 2475 2476 if ( $Param{DefaultVersionID} ) { 2477 2478 # Set conditions for id. 2479 $FieldName = 'id'; 2480 $FieldValue = $Param{DefaultVersionID}; 2481 } 2482 elsif ( $Param{DefaultID} ) { 2483 2484 # Set conditions for default id. 2485 $FieldName = 'sysconfig_default_id'; 2486 $FieldValue = $Param{DefaultID}; 2487 } 2488 elsif ( $Param{Name} ) { 2489 2490 # Set conditions for name. 2491 $FieldName = 'name'; 2492 $FieldValue = $Param{Name}; 2493 2494 } 2495 2496 # Delete default from the list. 2497 return if !$Kernel::OM->Get('Kernel::System::DB')->Do( 2498 SQL => 'DELETE FROM sysconfig_default_version WHERE ' . $FieldName . ' = ?', 2499 Bind => [ \$FieldValue ], 2500 ); 2501 2502 if ( !$Param{DefaultVersionID} ) { 2503 $Kernel::OM->Get('Kernel::System::Cache')->CleanUp( 2504 Type => 'SysConfigDefaultVersion', 2505 ); 2506 } 2507 else { 2508 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 2509 Type => 'SysConfigDefaultVersion', 2510 Key => 'DefaultSettingVersionGet::id::' . $Param{DefaultVersionID}, 2511 ); 2512 } 2513 2514 $Kernel::OM->Get('Kernel::System::Cache')->CleanUp( 2515 Type => 'SysConfigDefaultVersionList', 2516 ); 2517 2518 return 1; 2519} 2520 2521=head2 DefaultSettingVersionGetLast() 2522 2523Get last deployment. 2524 2525 my %DefaultSettingVersionGetLast = $SysConfigDBObject->DefaultSettingVersionGetLast( 2526 DefaultID => 456, 2527 ); 2528 2529Returns: 2530 2531 2532 %DefaultSettingVersion = ( 2533 DefaultVersionID => 123, 2534 DefaultID => 456, 2535 Name => "ProductName", 2536 Description => "Defines the name of the application ...", 2537 Navigation => "ASimple::Path::Structure", 2538 IsInvisible => 1, # 1 or 0 2539 IsReadonly => 0, # 1 or 0 2540 IsRequired => 1, # 1 or 0 2541 IsValid => 1, # 1 or 0 2542 HasConfigLevel => 200, 2543 UserModificationPossible => 0, # 1 or 0 2544 UserModificationActive => 0, # 1 or 0 2545 UsePreferencesGroup => 'Advanced', # optional 2546 XMLContentRaw => "The XML structure as it is on the config file", 2547 XMLContentParsed => "XML parsed to Perl", 2548 XMLFilename => 'Framework.xml', 2549 EffectiveValue => "Product 6", 2550 CreateTime => "2016-05-29 11:04:04", 2551 ChangeTime => "2016-05-29 11:04:04", 2552 ); 2553 2554=cut 2555 2556sub DefaultSettingVersionGetLast { 2557 my ( $Self, %Param ) = @_; 2558 2559 if ( !$Param{DefaultID} ) { 2560 $Kernel::OM->Get('Kernel::System::Log')->Log( 2561 Priority => 'error', 2562 Message => 'Need DefaultID!', 2563 ); 2564 return; 2565 } 2566 2567 my $CacheType = 'SysConfigDefaultVersion'; 2568 my $CacheKey = 'DefaultSettingVersionGetLast::' . $Param{DefaultID}; 2569 2570 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 2571 2572 # Return cache. 2573 my $Cache = $CacheObject->Get( 2574 Type => $CacheType, 2575 Key => $CacheKey, 2576 ); 2577 2578 return %{$Cache} if ref $Cache eq 'HASH'; 2579 2580 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 2581 2582 return if !$DBObject->Prepare( 2583 SQL => 'SELECT MAX(id) FROM sysconfig_default_version WHERE sysconfig_default_id = ?', 2584 Bind => [ \$Param{DefaultID} ], 2585 ); 2586 2587 my $DefaultVersionID; 2588 while ( my @Row = $DBObject->FetchrowArray() ) { 2589 $DefaultVersionID = $Row[0]; 2590 } 2591 2592 return if !$DefaultVersionID; 2593 2594 my %DefaultSettingVersion = $Self->DefaultSettingVersionGet( 2595 DefaultVersionID => $DefaultVersionID, 2596 ); 2597 2598 $CacheObject->Set( 2599 Type => $CacheType, 2600 Key => $CacheKey, 2601 Value => \%DefaultSettingVersion, 2602 TTL => $Self->{CacheTTL}, 2603 ); 2604 2605 return %DefaultSettingVersion; 2606} 2607 2608=head2 DefaultSettingVersionListGet() 2609 2610Get version setting list with complete data. 2611 2612 my @List = $SysConfigDBObject->DefaultSettingVersionListGet( 2613 Name => 'SettingName', # optional 2614 # or 2615 DefaultID => 123, # optional 2616 ); 2617 2618Returns: 2619 2620 @List = ( 2621 { 2622 DefaultVersionID => 123, 2623 DefaultID => 456, 2624 Name => "ProductName", 2625 Description => "Defines the name of the application ...", 2626 Navigation => "ASimple::Path::Structure", 2627 IsInvisible => 1, # 1 or 0 2628 IsReadonly => 0, # 1 or 0 2629 IsRequired => 1, # 1 or 0 2630 IsValid => 1, # 1 or 0 2631 HasConfigLevel => 200, 2632 UserModificationPossible => 0, # 1 or 0 2633 UserModificationActive => 0, # 1 or 0 2634 UserPreferencesGroup => 'Advanced', # optional 2635 XMLContentRaw => "The XML structure as it is on the config file", 2636 XMLContentParsed => "XML parsed to Perl", 2637 XMLFilename => 'Framework.xml', 2638 EffectiveValue => "Product 6", 2639 CreateTime => "2016-05-29 11:04:04", 2640 ChangeTime => "2016-05-29 11:04:04", 2641 }, 2642 { 2643 DefaultVersionID => 321, 2644 DefaultID => 890, 2645 Name => 'FieldName', 2646 # ... 2647 CreateTime => '2010-09-11 10:08:00', 2648 ChangeTime => '2011-01-01 01:01:01', 2649 }, 2650 # ... 2651 ); 2652 2653=cut 2654 2655sub DefaultSettingVersionListGet { 2656 my ( $Self, %Param ) = @_; 2657 2658 if ( !$Param{DefaultID} && !$Param{Name} ) { 2659 $Kernel::OM->Get('Kernel::System::Log')->Log( 2660 Priority => 'error', 2661 Message => 'Need DefaultID or Name!', 2662 ); 2663 return; 2664 } 2665 2666 my $FieldName; 2667 my $FieldValue; 2668 my $FieldCache; 2669 2670 if ( $Param{DefaultID} ) { 2671 2672 # Set conditions for default id. 2673 $FieldName = 'sysconfig_default_id'; 2674 $FieldValue = $Param{DefaultID}; 2675 $FieldCache = "DefaultID::$Param{DefaultID}"; 2676 } 2677 elsif ( $Param{Name} ) { 2678 2679 # Set conditions for name. 2680 $FieldName = 'name'; 2681 $FieldValue = $Param{Name}; 2682 $FieldCache = "Name::$Param{Name}"; 2683 } 2684 2685 # Set filters on SQL and cache key. 2686 my $SQLFilter = "WHERE $FieldName = '$FieldValue' "; 2687 2688 my $CacheType = 'SysConfigDefaultVersionList'; 2689 my $CacheKey = 'DefaultSettingVersionList::' . $FieldCache; 2690 2691 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 2692 2693 # Return cache. 2694 my $Cache = $CacheObject->Get( 2695 Type => $CacheType, 2696 Key => $CacheKey, 2697 ); 2698 2699 return @{$Cache} if ref $Cache eq 'ARRAY'; 2700 2701 # Start SQL statement. 2702 my $SQL = 'SELECT id, name FROM sysconfig_default_version ' . $SQLFilter . ' ORDER BY id DESC'; 2703 2704 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 2705 2706 my @Data; 2707 return if !$DBObject->Prepare( SQL => $SQL ); 2708 2709 my @DefaultVersionIDs; 2710 while ( my @Row = $DBObject->FetchrowArray() ) { 2711 push @DefaultVersionIDs, $Row[0]; 2712 } 2713 2714 # Get default settings. 2715 for my $ItemID (@DefaultVersionIDs) { 2716 2717 my %DefaultSetting = $Self->DefaultSettingVersionGet( 2718 DefaultVersionID => $ItemID, 2719 ); 2720 push @Data, \%DefaultSetting; 2721 } 2722 2723 $CacheObject->Set( 2724 Type => $CacheType, 2725 Key => $CacheKey, 2726 Value => \@Data, 2727 TTL => $Self->{CacheTTL}, 2728 ); 2729 2730 return @Data; 2731} 2732 2733=head2 ModifiedSettingAdd() 2734 2735Add a new SysConfig modified entry. 2736 2737 my $ModifiedID = $SysConfigDBObject->ModifiedSettingAdd( 2738 DefaultID => 456, 2739 Name => "ProductName", 2740 IsValid => 1, # 1 or 0, optional (uses the value from DefaultSetting if not defined) 2741 UserModificationPossible => 0, # 1 or 0, optional (uses the value from DefaultSetting if not defined) 2742 UserModificationActive => 0, # 1 or 0, optional (uses the value from DefaultSetting if not defined) 2743 ResetToDefault => 0, # 1 or 0, optional, modified 0 2744 EffectiveValue => $SettingEffectiveValue, 2745 TargetUserID => 2, # Optional, ID of the user for which the modified setting is meant, 2746 # leave it undef for global changes. 2747 ExclusiveLockGUID => $LockingString, # the GUID used to lock the setting 2748 DeploymentExclusiveLockGUID => $LockingString, # the GUID used to lock the deployment (in case of deployment failure) 2749 UserID => 1, 2750 ); 2751 2752Returns: 2753 2754 my $ModifiedID = 123; # false in case of an error 2755 2756=cut 2757 2758sub ModifiedSettingAdd { 2759 my ( $Self, %Param ) = @_; 2760 2761 # Store params for further usage. 2762 my %ModifiedVersionParams = %Param; 2763 2764 for my $Key (qw(DefaultID Name UserID)) { 2765 if ( !defined $Param{$Key} ) { 2766 $Kernel::OM->Get('Kernel::System::Log')->Log( 2767 Priority => 'error', 2768 Message => "Need $Key!", 2769 ); 2770 2771 return; 2772 } 2773 } 2774 2775 if ( !$Param{TargetUserID} && !$Param{ExclusiveLockGUID} && !$Param{DeploymentExclusiveLockGUID} ) { 2776 $Kernel::OM->Get('Kernel::System::Log')->Log( 2777 Priority => 'error', 2778 Message => "Need ExclusiveLockGUID or DeploymentExclusiveLockGUID!", 2779 ); 2780 } 2781 2782 # Check duplicate name (with same TargetUserID). 2783 my %ModifiedSetting = $Self->ModifiedSettingGet( 2784 Name => $Param{Name}, 2785 TargetUserID => $Param{TargetUserID}, 2786 ); 2787 2788 if (%ModifiedSetting) { 2789 $Kernel::OM->Get('Kernel::System::Log')->Log( 2790 Priority => 'error', 2791 Message => "There is already a modified setting for this user (or global)!", 2792 ); 2793 return; 2794 } 2795 2796 # Check duplicate name. 2797 my %DefaultSetting = $Self->DefaultSettingGet( 2798 DefaultID => $Param{DefaultID}, 2799 ); 2800 2801 if ( !%DefaultSetting ) { 2802 $Kernel::OM->Get('Kernel::System::Log')->Log( 2803 Priority => 'error', 2804 Message => "DefaultID is invalid!", 2805 ); 2806 2807 return; 2808 } 2809 2810 if ( $Param{Name} ne $DefaultSetting{Name} ) { 2811 $Kernel::OM->Get('Kernel::System::Log')->Log( 2812 Priority => 'error', 2813 Message => "Name doesn't match ('$Param{Name}')! It should be '$DefaultSetting{Name}'.", 2814 ); 2815 2816 return; 2817 } 2818 2819 # Check we have not UserModificationActive if we have TargetUserID they are exclusive. 2820 if ( defined $Param{UserModificationActive} && $Param{TargetUserID} ) { 2821 $Kernel::OM->Get('Kernel::System::Log')->Log( 2822 Priority => 'error', 2823 Message => "Could not set UserModificationActive on a user setting!", 2824 ); 2825 2826 return; 2827 } 2828 2829 # Update params with DefaultSetting if not defined. 2830 for my $Attribute (qw(UserModificationActive IsValid)) { 2831 $Param{$Attribute} //= $DefaultSetting{$Attribute}; 2832 $Param{$Attribute} = $Param{$Attribute} ? 1 : 0; 2833 } 2834 2835 # Is possible to disable UserModificationActive just if it is enabled on default. 2836 if ( !$DefaultSetting{UserModificationPossible} && $Param{UserModificationActive} ) { 2837 $Kernel::OM->Get('Kernel::System::Log')->Log( 2838 Priority => 'error', 2839 Message => "Could not UserModificationActive if default setting prohibits!", 2840 ); 2841 2842 return; 2843 } 2844 2845 # Serialize data as string. 2846 $Param{EffectiveValue} = $Kernel::OM->Get('Kernel::System::YAML')->Dump( 2847 Data => $Param{EffectiveValue}, 2848 ); 2849 2850 # Set is dirty as enabled due it is a new setting. 2851 my $IsDirty = 1; 2852 2853 $Param{ResetToDefault} = $Param{ResetToDefault} ? 1 : 0; 2854 2855 # Default should be locked. 2856 my $LockedByUser = 1; 2857 if ( !$Param{TargetUserID} ) { 2858 $LockedByUser = $Self->DefaultSettingIsLockedByUser( 2859 DefaultID => $Param{DefaultID}, 2860 ExclusiveLockUserID => $Param{UserID}, 2861 ExclusiveLockGUID => $Param{ExclusiveLockGUID}, 2862 ); 2863 } 2864 2865 # Check if we are on a deployment and a deleted value needs to be restored due an error 2866 if ( !$LockedByUser && $Param{DeploymentExclusiveLockGUID} ) { 2867 $LockedByUser = $Self->DeploymentIsLockedByUser( 2868 ExclusiveLockGUID => $Param{DeploymentExclusiveLockGUID}, 2869 UserID => $Param{UserID}, 2870 ); 2871 } 2872 2873 if ( !$LockedByUser ) { 2874 $Kernel::OM->Get('Kernel::System::Log')->Log( 2875 Priority => 'error', 2876 Message => "Default setting is not locked to this user!", 2877 ); 2878 return; 2879 } 2880 2881 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 2882 2883 # Insert the modified. 2884 return if !$DBObject->Do( 2885 SQL => ' 2886 INSERT INTO sysconfig_modified 2887 (sysconfig_default_id, name, user_id, is_valid, user_modification_active, 2888 effective_value, is_dirty, reset_to_default, create_time, create_by, change_time, change_by) 2889 VALUES 2890 (?, ?, ?, ?, ?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)', 2891 Bind => [ 2892 \$Param{DefaultID}, \$Param{Name}, \$Param{TargetUserID}, \$Param{IsValid}, 2893 \$Param{UserModificationActive}, \$Param{EffectiveValue}, 2894 \$IsDirty, \$Param{ResetToDefault}, \$Param{UserID}, \$Param{UserID}, 2895 ], 2896 ); 2897 2898 my $SQLSelect = 'SELECT id, effective_value FROM sysconfig_modified 2899 WHERE sysconfig_default_id = ? 2900 AND name = ? 2901 AND is_dirty = ? '; 2902 2903 my @BindSelect = ( \$Param{DefaultID}, \$Param{Name}, \$IsDirty ); 2904 2905 if ( $Param{TargetUserID} ) { 2906 $SQLSelect .= "AND user_id = ? "; 2907 push @BindSelect, \$Param{TargetUserID}; 2908 } 2909 else { 2910 $SQLSelect .= "AND user_id IS NULL "; 2911 } 2912 2913 # Get modified ID. 2914 $DBObject->Prepare( 2915 SQL => $SQLSelect, 2916 Bind => \@BindSelect, 2917 Limit => 1, 2918 ); 2919 2920 # Fetch the modified setting ID. 2921 my $ModifiedSettingID; 2922 2923 ROW: 2924 while ( my @Row = $DBObject->FetchrowArray() ) { 2925 next ROW if $Row[1] ne $Param{EffectiveValue}; 2926 $ModifiedSettingID = $Row[0]; 2927 } 2928 2929 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 2930 2931 $CacheObject->CleanUp( 2932 Type => 'SysConfigModified', 2933 ); 2934 $CacheObject->Delete( 2935 Type => 'SysConfigModifiedList', 2936 Key => 'ModifiedSettingList', 2937 ); 2938 $CacheObject->CleanUp( 2939 Type => 'SysConfigNavigation', 2940 ); 2941 $CacheObject->CleanUp( 2942 Type => 'SysConfigEntities', 2943 ); 2944 $CacheObject->CleanUp( 2945 Type => 'SysConfigIsDirty', 2946 ); 2947 2948 # Clean cache for setting translations. 2949 my %Languages = %{ $Kernel::OM->Get('Kernel::Config')->Get('DefaultUsedLanguages') }; 2950 for my $Language ( sort keys %Languages ) { 2951 $CacheObject->Delete( 2952 Type => 'SysConfig', 2953 Key => "SettingTranslatedGet::$Language" . "::$Param{Name}", 2954 ); 2955 $CacheObject->Delete( 2956 Type => 'SysConfig', 2957 Key => "ConfigurationTranslatedGet::$Language", 2958 ); 2959 } 2960 2961 # Unlock the setting. 2962 my $IsUnlock = $Self->DefaultSettingUnlock( 2963 DefaultID => $Param{DefaultID}, 2964 ); 2965 if ( !$IsUnlock ) { 2966 $Kernel::OM->Get('Kernel::System::Log')->Log( 2967 Priority => 'error', 2968 Message => "Default setting with ID: $Param{DefaultID} was not possible to unlock!", 2969 ); 2970 return; 2971 } 2972 2973 return $ModifiedSettingID; 2974} 2975 2976=head2 ModifiedSettingGet() 2977 2978Get SysConfig modified value. 2979 2980 my %ModifiedSetting = $SysConfigDBObject->ModifiedSettingGet( 2981 ModifiedID => 123, # ModifiedID or NAME are required. 2982 Name => 'Setting::Name', 2983 TargetUserID => 2, # The ID of the user for which the modified setting is meant, 2984 # exclusive with IsGlobal. 2985 IsGlobal => 1, # Define a search for settings don't belong an user, 2986 # exclusive with TargetUserID. 2987 ); 2988 2989Returns: 2990 2991 %ModifiedSetting = ( 2992 ModifiedID => "123", 2993 DefaultID => 456, 2994 Name => "ProductName", 2995 IsGlobal => 1, # 1 or 0, optional 2996 IsValid => 1, # 1 or 0, optional, modified 0 2997 IsDirty => 1, # 1 or 0, optional, modified 0 2998 ResetToDefault => 1, # 1 or 0, optional, modified 0 2999 UserModificationActive => 0, # 1 or 0, optional, modified 0 3000 EffectiveValue => $SettingEffectiveValue, 3001 TargetUserID => 2, # ID of the user for which the modified setting is meant 3002 CreateTime => "2016-05-29 11:04:04", 3003 CreateBy => 1, 3004 ChangeTime => "2016-05-29 11:04:04", 3005 ChangeBy => 1, 3006 SettingUID => 'Modified12320160529110404', 3007 ); 3008 3009=cut 3010 3011sub ModifiedSettingGet { 3012 my ( $Self, %Param ) = @_; 3013 3014 if ( !$Param{ModifiedID} && !$Param{Name} ) { 3015 $Kernel::OM->Get('Kernel::System::Log')->Log( 3016 Priority => 'error', 3017 Message => 'Need ModifiedID or Name!', 3018 ); 3019 return; 3020 } 3021 3022 my $FieldName; 3023 my $FieldValue; 3024 3025 if ( $Param{ModifiedID} ) { 3026 3027 # Set DefaultID as filter. 3028 $FieldName = 'id'; 3029 $FieldValue = $Param{ModifiedID}; 3030 } 3031 elsif ( $Param{Name} ) { 3032 3033 # Set Name as filter. 3034 $FieldName = 'name'; 3035 $FieldValue = $Param{Name}; 3036 } 3037 3038 # IsGlobal and TargetUserID are exclusive each other. 3039 if ( defined $Param{IsGlobal} && defined $Param{TargetUserID} ) { 3040 $Kernel::OM->Get('Kernel::System::Log')->Log( 3041 Priority => 'error', 3042 Message => "Use IsGlobal and TargetUserID at the same time is not allowed!", 3043 ); 3044 return; 3045 } 3046 3047 # Check optional settings. 3048 for my $Item (qw(IsGlobal TargetUserID)) { 3049 $Param{$Item} //= 0; 3050 } 3051 3052 # Ff not defined TargetUserID it should be global. 3053 if ( !$Param{TargetUserID} && $FieldName eq 'name' ) { 3054 $Param{IsGlobal} = 1; 3055 } 3056 3057 my $SQLExtra = ''; 3058 my @Bind = ( \$FieldValue ); 3059 3060 # In case of global search user value is needed as null. 3061 if ( $Param{IsGlobal} ) { 3062 $SQLExtra = ' 3063 AND user_id IS NULL'; 3064 } 3065 3066 # Otherwise check effective user id. 3067 elsif ( $Param{TargetUserID} ) { 3068 $SQLExtra = " 3069 AND user_id = ? "; 3070 push @Bind, \$Param{TargetUserID}; 3071 } 3072 3073 my $CacheType = "SysConfigModified"; 3074 my $CacheKey = 'ModifiedSettingGet::' # this cache key gets more elements 3075 . $FieldName . '::' 3076 . $FieldValue . '::' 3077 . $Param{IsGlobal} . '::' 3078 . $Param{TargetUserID}; 3079 3080 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 3081 3082 # Return cache. 3083 my $Cache = $CacheObject->Get( 3084 Type => $CacheType, 3085 Key => $CacheKey, 3086 ); 3087 3088 return %{$Cache} if ref $Cache eq 'HASH'; 3089 3090 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 3091 3092 my $SQL = ' 3093 SELECT id, sysconfig_default_id, name, user_id, is_valid, user_modification_active, 3094 effective_value, is_dirty, reset_to_default, create_time, create_by, change_time, change_by 3095 FROM sysconfig_modified 3096 WHERE'; 3097 3098 $SQL .= ' ' . $FieldName . ' = ?' . $SQLExtra; 3099 3100 $SQL .= ' 3101 ORDER BY id DESC'; 3102 3103 # Get modified from database. 3104 return if !$DBObject->Prepare( 3105 SQL => $SQL, 3106 Bind => \@Bind, 3107 ); 3108 3109 my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML'); 3110 3111 my %ModifiedSetting; 3112 while ( my @Data = $DBObject->FetchrowArray() ) { 3113 3114 # De-serialize modified data. 3115 my $EffectiveValue = $YAMLObject->Load( Data => $Data[6] ); 3116 3117 my $TimeStamp = $Data[11]; 3118 $TimeStamp =~ s{:|-|[ ]}{}gmsx; 3119 3120 %ModifiedSetting = ( 3121 ModifiedID => $Data[0], 3122 DefaultID => $Data[1], 3123 Name => $Data[2], 3124 TargetUserID => $Data[3], 3125 IsValid => $Data[4], 3126 UserModificationActive => $Data[5], 3127 EffectiveValue => $EffectiveValue, 3128 IsDirty => $Data[7] ? 1 : 0, 3129 ResetToDefault => $Data[8] ? 1 : 0, 3130 CreateTime => $Data[9], 3131 CreateBy => $Data[10], 3132 ChangeTime => $Data[11], 3133 ChangeBy => $Data[12], 3134 SettingUID => "Modified$Data[0]$TimeStamp", 3135 ); 3136 } 3137 3138 $CacheObject->Set( 3139 Type => $CacheType, 3140 Key => $CacheKey, 3141 Value => \%ModifiedSetting, 3142 TTL => $Self->{CacheTTL}, 3143 ); 3144 3145 return %ModifiedSetting; 3146} 3147 3148=head2 ModifiedSettingListGet() 3149 3150Get modified setting list with complete data. 3151 3152 my @List = $SysConfigDBObject->ModifiedSettingListGet( 3153 IsInvisible => 1, # 1 or 0 3154 IsReadonly => 0, # 1 or 0 3155 IsRequired => 1, # 1 or 0 3156 IsValid => 1, # 1 or 0 3157 IsDirty => 1, # 1 or 0 3158 ResetToDefault => 1, # 1 or 0 3159 TargetUserID => 2, # the ID of the user for which the modified setting is meant, 3160 # exclusive with IsGlobal. 3161 IsGlobal => 1, # Define a search for settings don't belong an user, 3162 # exclusive with TargetUserID. 3163 HasConfigLevel => 0, # 1 or 0 3164 UserModificationActive => 0, # 1 or 0 3165 Name => 'ACL::CacheTTL', # setting name 3166 ChangeBy => 123, 3167 ); 3168 3169Returns: 3170 3171 @List = ( 3172 { 3173 ModifiedID => 123, 3174 Name => "ProductName", 3175 Description => "Defines the name of the application ...", 3176 Navigation => "ASimple::Path::Structure", 3177 IsInvisible => 1, 3178 IsReadonly => 0, 3179 IsRequired => 1, 3180 IsValid => 1, 3181 ResetToDefault => 1, # 1 or 0 3182 HasConfigLevel => 200, 3183 UserModificationActive => 0, # 1 or 0 3184 XMLContentRaw => "The XML structure as it is on the config file", 3185 XMLContentParsed => "XML parsed to Perl", 3186 EffectiveValue => "Product 6", 3187 IsDirty => 1, # 1 or 0 3188 ExclusiveLockGUID => 'A32CHARACTERLONGSTRINGFORLOCKING', 3189 ExclusiveLockUserID => 1, 3190 ExclusiveLockExpiryTime => '2016-05-29 11:09:04', 3191 CreateTime => "2016-05-29 11:04:04", 3192 ChangeTime => "2016-05-29 11:04:04", 3193 }, 3194 { 3195 ModifiedID => 321, 3196 Name => 'FieldName', 3197 # ... 3198 CreateTime => '2010-09-11 10:08:00', 3199 ChangeTime => '2011-01-01 01:01:01', 3200 }, 3201 # ... 3202 ); 3203 3204=cut 3205 3206sub ModifiedSettingListGet { 3207 my ( $Self, %Param ) = @_; 3208 3209 # IsGlobal and TargetUserID are exclusive each other. 3210 if ( defined $Param{IsGlobal} && defined $Param{TargetUserID} ) { 3211 $Kernel::OM->Get('Kernel::System::Log')->Log( 3212 Priority => 'error', 3213 Message => "Use IsGlobal and TargetUserID at the same time is not allowed!", 3214 ); 3215 return; 3216 } 3217 3218 my @Filters; 3219 my @Bind; 3220 3221 my $CacheType = 'SysConfigModifiedList'; 3222 my $CacheKey = 'ModifiedSettingList'; 3223 3224 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 3225 3226 # Return cache. 3227 my $Cache = $CacheObject->Get( 3228 Type => $CacheType, 3229 Key => $CacheKey, 3230 ); 3231 3232 my @DataRaw; 3233 3234 if ( ref $Cache eq 'ARRAY' ) { 3235 @DataRaw = @{$Cache}; 3236 } 3237 else { 3238 my $SQL = ' 3239 SELECT id, sysconfig_default_id, name, user_id, is_valid, user_modification_active, 3240 effective_value, is_dirty, reset_to_default, create_time, create_by, change_time, change_by 3241 FROM sysconfig_modified'; 3242 3243 $SQL .= ' ORDER BY id'; 3244 3245 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 3246 3247 # Get modified from database. 3248 return if !$DBObject->Prepare( 3249 SQL => $SQL, 3250 Bind => \@Bind, 3251 ); 3252 3253 my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML'); 3254 3255 while ( my @Row = $DBObject->FetchrowArray() ) { 3256 3257 # De-serialize modified data. 3258 my $EffectiveValue = $YAMLObject->Load( Data => $Row[6] ); 3259 3260 my $TimeStamp = $Row[11]; 3261 $TimeStamp =~ s{:|-|[ ]}{}gmsx; 3262 3263 my %ModifiedSetting = ( 3264 ModifiedID => $Row[0], 3265 DefaultID => $Row[1], 3266 Name => $Row[2], 3267 TargetUserID => $Row[3], 3268 IsValid => $Row[4], 3269 UserModificationActive => $Row[5], 3270 EffectiveValue => $EffectiveValue, 3271 IsDirty => $Row[7] ? 1 : 0, 3272 ResetToDefault => $Row[8] ? 1 : 0, 3273 CreateTime => $Row[9], 3274 CreateBy => $Row[10], 3275 ChangeTime => $Row[11], 3276 ChangeBy => $Row[12], 3277 SettingUID => "Modified$Row[0]$TimeStamp", 3278 ); 3279 3280 push @DataRaw, \%ModifiedSetting; 3281 } 3282 3283 $CacheObject->Set( 3284 Type => $CacheType, 3285 Key => $CacheKey, 3286 Value => \@DataRaw, 3287 TTL => $Self->{CacheTTL}, 3288 ); 3289 } 3290 3291 # Copy DataRaw to prevent modifications to in memory cache. 3292 my @Data = @DataRaw; 3293 3294 if ( defined $Param{IsInvisible} ) { 3295 @Data = grep { $_->{IsInvisible} eq $Param{IsInvisible} } @Data; 3296 } 3297 if ( defined $Param{IsReadonly} ) { 3298 @Data = grep { $_->{IsReadonly} eq $Param{IsReadonly} } @Data; 3299 } 3300 if ( defined $Param{IsRequired} ) { 3301 @Data = grep { $_->{IsRequired} eq $Param{IsRequired} } @Data; 3302 } 3303 if ( defined $Param{IsValid} ) { 3304 @Data = grep { $_->{IsValid} eq $Param{IsValid} } @Data; 3305 } 3306 if ( defined $Param{IsDirty} ) { 3307 @Data = grep { $_->{IsDirty} eq $Param{IsDirty} } @Data; 3308 } 3309 if ( defined $Param{HasConfigLevel} ) { 3310 @Data = grep { $_->{HasConfigLevel} eq $Param{HasConfigLevel} } @Data; 3311 } 3312 if ( defined $Param{UserModificationActive} ) { 3313 @Data = grep { $_->{UserModificationActive} eq $Param{UserModificationActive} } @Data; 3314 } 3315 if ( defined $Param{Name} ) { 3316 @Data = grep { $_->{Name} eq $Param{Name} } @Data; 3317 } 3318 if ( defined $Param{TargetUserID} ) { 3319 @Data = grep { $_->{TargetUserID} && $_->{TargetUserID} eq $Param{TargetUserID} } @Data; 3320 } 3321 if ( defined $Param{ChangeBy} ) { 3322 @Data = grep { $_->{ChangeBy} eq $Param{ChangeBy} } @Data; 3323 } 3324 if ( defined $Param{Locked} ) { 3325 if ( $Param{Locked} ) { 3326 @Data = grep { $_->{ExclusiveLockGUID} } @Data; 3327 } 3328 else { 3329 @Data = grep { !$_->{ExclusiveLockGUID} } @Data; 3330 } 3331 } 3332 if ( $Param{IsGlobal} ) { 3333 @Data = grep { !$_->{TargetUserID} } @Data; 3334 } 3335 3336 return @Data; 3337} 3338 3339=head2 ModifiedSettingDelete() 3340 3341Delete a modified setting from list. 3342 3343 my $Success = $SysConfigDBObject->ModifiedSettingDelete( 3344 ModifiedID => 123, 3345 ); 3346 3347Returns: 3348 3349 $Success = 1; # or false in case of an error 3350 3351=cut 3352 3353sub ModifiedSettingDelete { 3354 my ( $Self, %Param ) = @_; 3355 3356 if ( !$Param{ModifiedID} ) { 3357 $Kernel::OM->Get('Kernel::System::Log')->Log( 3358 Priority => 'error', 3359 Message => 'Need ModifiedID!', 3360 ); 3361 return; 3362 } 3363 3364 my %ModifiedSetting = $Self->ModifiedSettingGet( 3365 ModifiedID => $Param{ModifiedID}, 3366 ); 3367 3368 return if !IsHashRefWithData( \%ModifiedSetting ); 3369 3370 # Delete modified from the list. 3371 return if !$Kernel::OM->Get('Kernel::System::DB')->Do( 3372 SQL => 'DELETE FROM sysconfig_modified WHERE id = ?', 3373 Bind => [ \$Param{ModifiedID} ], 3374 ); 3375 3376 for my $Item (qw(0 1)) { 3377 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 3378 Type => 'SysConfigModified', 3379 Key => 'ModifiedSettingGet::id::' 3380 . $ModifiedSetting{ModifiedID} . '::' 3381 . $Item . '::0', 3382 ); 3383 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 3384 Type => 'SysConfigModified', 3385 Key => 'ModifiedSettingGet::name::' 3386 . $ModifiedSetting{Name} . '::' 3387 . $Item . '::0', 3388 ); 3389 } 3390 3391 if ( $ModifiedSetting{TargetUserID} ) { 3392 3393 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 3394 Type => 'SysConfigModified', 3395 Key => 'ModifiedSettingGet::id::' 3396 . $ModifiedSetting{ModifiedID} . '::0::' 3397 . $ModifiedSetting{TargetUserID}, 3398 ); 3399 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 3400 Type => 'SysConfigModified', 3401 Key => 'ModifiedSettingGet::name::' 3402 . $ModifiedSetting{Name} . '::0::' 3403 . $ModifiedSetting{TargetUserID}, 3404 ); 3405 } 3406 3407 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 3408 3409 $CacheObject->Delete( 3410 Type => 'SysConfigModifiedList', 3411 Key => 'ModifiedSettingList', 3412 ); 3413 $CacheObject->CleanUp( 3414 Type => 'SysConfigNavigation', 3415 ); 3416 $CacheObject->CleanUp( 3417 Type => 'SysConfigEntities', 3418 ); 3419 $CacheObject->CleanUp( 3420 Type => 'SysConfigIsDirty', 3421 ); 3422 3423 # Clean cache for setting translations. 3424 my %Languages = %{ $Kernel::OM->Get('Kernel::Config')->Get('DefaultUsedLanguages') }; 3425 for my $Language ( sort keys %Languages ) { 3426 $CacheObject->Delete( 3427 Type => 'SysConfig', 3428 Key => "SettingTranslatedGet::$Language" . "::$ModifiedSetting{Name}", 3429 ); 3430 $CacheObject->Delete( 3431 Type => 'SysConfig', 3432 Key => "ConfigurationTranslatedGet::$Language", 3433 ); 3434 } 3435 3436 return 1; 3437} 3438 3439=head2 ModifiedSettingUpdate() 3440 3441Update SysConfig modified. 3442 3443 my $Success = $SysConfigDBObject->ModifiedSettingUpdate( 3444 ModifiedID => 123, # (required) 3445 DefaultID => 456, # (required) 3446 Name => "ProductName", # (required) 3447 IsValid => 1, # (optional) 1 or 0, optional (uses the value from DefaultSetting if not defined) 3448 IsDirty => 1, # (optional) Default 1. 3449 ResetToDefault => 1, # (optional), default 0 3450 UserModificationActive => 1, # (optional) 1 or 0 (uses the value from DefaultSetting if not defined) 3451 EffectiveValue => $SettingEffectiveValue, 3452 TargetUserID => 2, # (optional), ID of the user for which the modified setting is meant, 3453 # leave it undef for global changes. 3454 ExclusiveLockGUID => $LockingString, # the GUID used to locking the setting 3455 UserID => 1, # (required) 3456 ); 3457 3458Returns: 3459 3460 $Success = 1; # or false in case of an error 3461 3462=cut 3463 3464sub ModifiedSettingUpdate { 3465 my ( $Self, %Param ) = @_; 3466 3467 # Store params for further usage. 3468 my %ModifiedVersionParams = %Param; 3469 3470 for my $Key (qw(ModifiedID DefaultID Name EffectiveValue UserID)) { 3471 if ( !defined $Param{$Key} ) { 3472 $Kernel::OM->Get('Kernel::System::Log')->Log( 3473 Priority => 'error', 3474 Message => "Need $Key!", 3475 ); 3476 3477 return; 3478 } 3479 } 3480 3481 # Set is dirty to 1 if not defined. 3482 $Param{IsDirty} //= 1; 3483 3484 # Get modified setting. 3485 my %ModifiedSetting = $Self->ModifiedSettingGet( 3486 ModifiedID => $Param{ModifiedID}, 3487 ); 3488 3489 # Check if we really need to update. 3490 my $IsDifferent = 0; 3491 for my $Key (qw(ModifiedID DefaultID Name IsValid EffectiveValue UserModificationActive)) { 3492 my $DataIsDifferent = DataIsDifferent( 3493 Data1 => $Param{$Key}, 3494 Data2 => $ModifiedSetting{$Key}, 3495 ); 3496 if ($DataIsDifferent) { 3497 $IsDifferent = 1; 3498 } 3499 } 3500 3501 if ( $ModifiedSetting{IsDirty} != $Param{IsDirty} ) { 3502 $IsDifferent = 1; 3503 } 3504 3505 return 1 if !$IsDifferent; 3506 3507 # Retrieve default setting. 3508 my %DefaultSetting = $Self->DefaultSettingGet( 3509 DefaultID => $Param{DefaultID}, 3510 ); 3511 3512 if ( !%DefaultSetting ) { 3513 $Kernel::OM->Get('Kernel::System::Log')->Log( 3514 Priority => 'error', 3515 Message => "DefaultID is invalid!", 3516 ); 3517 3518 return; 3519 } 3520 3521 if ( $Param{Name} ne $DefaultSetting{Name} ) { 3522 $Kernel::OM->Get('Kernel::System::Log')->Log( 3523 Priority => 'error', 3524 Message => "Name is Invalid!", 3525 ); 3526 3527 return; 3528 } 3529 3530 # Check we have not UserModificationActive if we have TargetUserID they are exclusive 3531 if ( defined $Param{UserModificationActive} && $Param{TargetUserID} ) { 3532 $Kernel::OM->Get('Kernel::System::Log')->Log( 3533 Priority => 'error', 3534 Message => "Could not set UserModificationActive on a user setting!", 3535 ); 3536 return; 3537 } 3538 3539 # Update params with DefaultSetting if not defined. 3540 for my $Attribute (qw(UserModificationActive IsValid)) { 3541 $Param{$Attribute} //= $DefaultSetting{$Attribute}; 3542 $Param{$Attribute} = $Param{$Attribute} ? 1 : 0; 3543 } 3544 3545 # Is possible to disable UserModificationActive just if it is enabled on default. 3546 if ( !$DefaultSetting{UserModificationPossible} && $Param{UserModificationActive} ) { 3547 $Kernel::OM->Get('Kernel::System::Log')->Log( 3548 Priority => 'error', 3549 Message => "Could not UserModificationActive if default setting prohibits!", 3550 ); 3551 return; 3552 } 3553 3554 # Serialize data as string. 3555 $Param{EffectiveValue} = $Kernel::OM->Get('Kernel::System::YAML')->Dump( 3556 Data => $Param{EffectiveValue}, 3557 ); 3558 3559 $Param{ResetToDefault} = $Param{ResetToDefault} ? 1 : 0; 3560 3561 # Default should be locked. 3562 my $LockedByUser = 1; 3563 if ( !$Param{UserID} ) { 3564 $LockedByUser = $Self->DefaultSettingIsLockedByUser( 3565 DefaultID => $Param{DefaultID}, 3566 ExclusiveLockUserID => $Param{UserID}, 3567 ExclusiveLockGUID => $Param{ExclusiveLockGUID}, 3568 ); 3569 } 3570 3571 if ( !$LockedByUser ) { 3572 $Kernel::OM->Get('Kernel::System::Log')->Log( 3573 Priority => 'error', 3574 Message => "Default setting is not locked to this user!", 3575 ); 3576 return; 3577 } 3578 3579 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 3580 3581 # Insert the modified. 3582 return if !$DBObject->Do( 3583 SQL => ' 3584 UPDATE sysconfig_modified 3585 SET sysconfig_default_id = ?, name = ?, is_valid = ?, user_modification_active = ?, 3586 effective_value = ?, is_dirty = ?, reset_to_default = ?, change_time = current_timestamp, change_by = ? 3587 WHERE id = ?', 3588 Bind => [ 3589 \$Param{DefaultID}, \$Param{Name}, \$Param{IsValid}, \$Param{UserModificationActive}, 3590 \$Param{EffectiveValue}, \$Param{IsDirty}, \$Param{ResetToDefault}, 3591 \$Param{UserID}, \$Param{ModifiedID}, 3592 ], 3593 ); 3594 3595 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 3596 3597 $CacheObject->CleanUp( 3598 Type => 'SysConfigModified', 3599 ); 3600 $CacheObject->Delete( 3601 Type => 'SysConfigModifiedList', 3602 Key => 'ModifiedSettingList', 3603 ); 3604 $CacheObject->CleanUp( 3605 Type => 'SysConfigNavigation', 3606 ); 3607 $CacheObject->CleanUp( 3608 Type => 'SysConfigEntities', 3609 ); 3610 $CacheObject->CleanUp( 3611 Type => 'SysConfigIsDirty', 3612 ); 3613 3614 # Clean cache for setting translations. 3615 my %Languages = %{ $Kernel::OM->Get('Kernel::Config')->Get('DefaultUsedLanguages') }; 3616 for my $Language ( sort keys %Languages ) { 3617 $CacheObject->Delete( 3618 Type => 'SysConfig', 3619 Key => "SettingTranslatedGet::$Language" . "::$Param{Name}", 3620 ); 3621 $CacheObject->Delete( 3622 Type => 'SysConfig', 3623 Key => "ConfigurationTranslatedGet::$Language", 3624 ); 3625 } 3626 3627 return 1; 3628} 3629 3630=head2 ModifiedSettingDirtyCleanUp() 3631 3632Removes the IsDirty flag from modified settings. 3633 3634 my $Success = $SysConfigDBObject->ModifiedSettingDirtyCleanUp( 3635 TargetUserID => 123, # (optional) 3636 ModifiedIDs => [ # (optional) applies to only this list of settings 3637 123, 3638 456, 3639 ], 3640 ); 3641 3642Returns: 3643 3644 $Success = 1; # or false in case of an error 3645 3646=cut 3647 3648sub ModifiedSettingDirtyCleanUp { 3649 my ( $Self, %Param ) = @_; 3650 3651 if ( defined $Param{TargetUserID} && !IsPositiveInteger( $Param{TargetUserID} ) ) { 3652 $Kernel::OM->Get('Kernel::System::Log')->Log( 3653 Priority => 'error', 3654 Message => "TargetUserID is invalid", 3655 ); 3656 return; 3657 } 3658 3659 if ( defined $Param{ModifiedIDs} && !IsArrayRefWithData( $Param{ModifiedIDs} ) ) { 3660 $Kernel::OM->Get('Kernel::System::Log')->Log( 3661 Priority => 'error', 3662 Message => "ModifiedIDs is invalid", 3663 ); 3664 return; 3665 } 3666 3667 # Define common SQL. 3668 my $SQL = ' 3669 UPDATE sysconfig_modified 3670 SET is_dirty = 0 3671 WHERE is_dirty = 1'; 3672 3673 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 3674 3675 if ( $Param{ModifiedIDs} ) { 3676 3677 my $ModifiedIDsStrg = join ',', map { $DBObject->Quote( $_, 'Integer' ) } @{ $Param{ModifiedIDs} }; 3678 3679 $SQL .= " 3680 AND id IN ($ModifiedIDsStrg)"; 3681 } 3682 3683 my @Bind; 3684 3685 # Define user condition. 3686 my $UserCondition = ' 3687 AND user_id IS NULL'; 3688 if ( $Param{TargetUserID} ) { 3689 $UserCondition = ' 3690 AND user_id = ?'; 3691 push @Bind, \$Param{TargetUserID}; 3692 } 3693 3694 # Remove is dirty flag for modified settings. 3695 return if !$DBObject->Do( 3696 SQL => $SQL . $UserCondition, 3697 Bind => \@Bind, 3698 ); 3699 3700 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 3701 3702 $CacheObject->CleanUp( 3703 Type => 'SysConfigModified', 3704 ); 3705 $CacheObject->Delete( 3706 Type => 'SysConfigModifiedList', 3707 Key => 'ModifiedSettingList', 3708 ); 3709 3710 $CacheObject->CleanUp( 3711 Type => 'SysConfigModifiedVersion', 3712 ); 3713 $CacheObject->CleanUp( 3714 Type => 'SysConfigIsDirty', 3715 ); 3716 3717 return 1; 3718} 3719 3720=head2 ModifiedSettingVersionAdd() 3721 3722Add a new SysConfig modified version entry. 3723 3724 my $ModifiedVersionID = $SysConfigDBObject->ModifiedSettingVersionAdd( 3725 DefaultVersionID => 456, 3726 Name => "ProductName", 3727 IsValid => 1, # 1 or 0, optional, optional 0 3728 UserModificationActive => 0, # 1 or 0, optional, optional 0 3729 TargetUserID => 2, # The ID of the user for which the modified setting is meant, 3730 # leave it undef for global changes. 3731 EffectiveValue => $SettingEffectiveValue, # the value as will be stored in the Perl configuration file 3732 DeploymentTimeStamp => '2015-12-12 12:00:00', # unique timestamp per deployment 3733 ResetToDefault => 1, # optional, default 0 3734 UserID => 1, 3735 ); 3736 3737Returns: 3738 3739 my $ModifiedVersionID = 123; # false in case of an error 3740 3741=cut 3742 3743sub ModifiedSettingVersionAdd { 3744 my ( $Self, %Param ) = @_; 3745 3746 for my $Key ( 3747 qw(DefaultVersionID Name EffectiveValue DeploymentTimeStamp UserID) 3748 ) 3749 { 3750 if ( !defined $Param{$Key} ) { 3751 $Kernel::OM->Get('Kernel::System::Log')->Log( 3752 Priority => 'error', 3753 Message => "Need $Key!", 3754 ); 3755 3756 return; 3757 } 3758 } 3759 3760 # Check boolean parameters, set 0 as default value). 3761 for my $Key (qw(IsValid UserModificationActive ResetToDefault)) { 3762 $Param{$Key} = ( defined $Param{$Key} && $Param{$Key} ? 1 : 0 ); 3763 } 3764 3765 # Serialize data as string. 3766 $Param{EffectiveValue} = $Kernel::OM->Get('Kernel::System::YAML')->Dump( 3767 Data => $Param{EffectiveValue}, 3768 ); 3769 3770 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 3771 3772 # Insert the modified. 3773 return if !$DBObject->Do( 3774 SQL => ' 3775 INSERT INTO sysconfig_modified_version 3776 (sysconfig_default_version_id, name, user_id, is_valid, reset_to_default, 3777 user_modification_active, effective_value, create_time, create_by, 3778 change_time, change_by) 3779 VALUES 3780 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', 3781 Bind => [ 3782 \$Param{DefaultVersionID}, \$Param{Name}, \$Param{TargetUserID}, \$Param{IsValid}, 3783 \$Param{ResetToDefault}, \$Param{UserModificationActive}, 3784 \$Param{EffectiveValue}, \$Param{DeploymentTimeStamp}, \$Param{UserID}, 3785 \$Param{DeploymentTimeStamp}, \$Param{UserID}, 3786 ], 3787 ); 3788 3789 # Get modified ID. 3790 $DBObject->Prepare( 3791 SQL => ' 3792 SELECT id 3793 FROM sysconfig_modified_version 3794 WHERE sysconfig_default_version_id =? 3795 AND name = ? 3796 ORDER BY id DESC', 3797 Bind => [ \$Param{DefaultVersionID}, \$Param{Name} ], 3798 Limit => 1, 3799 ); 3800 3801 # Fetch the modified setting ID 3802 my $ModifiedVersionID; 3803 while ( my @Row = $DBObject->FetchrowArray() ) { 3804 $ModifiedVersionID = $Row[0]; 3805 } 3806 3807 $Kernel::OM->Get('Kernel::System::Cache')->CleanUp( 3808 Type => 'SysConfigModifiedVersion', 3809 ); 3810 $Kernel::OM->Get('Kernel::System::Cache')->CleanUp( 3811 Type => 'SysConfigModifiedVersionList', 3812 ); 3813 3814 return $ModifiedVersionID; 3815} 3816 3817=head2 ModifiedSettingVersionGet() 3818 3819Get SysConfig modified version entry. 3820 3821 my %ModifiedSettingVersion = $SysConfigDBObject->ModifiedSettingVersionGet( 3822 ModifiedVersionID => 123, 3823 ); 3824 3825Returns: 3826 3827 %ModifiedSetting = ( 3828 ModifiedVersionID => 123, 3829 DefaultVersionID => 456, 3830 Name => "ProductName", 3831 TargetUserID => 123, 3832 IsValid => 1, # 1 or 0 3833 ResetToDefault => 1, # 1 or 0 3834 UserModificationActive => 0, # 1 or 0 3835 EffectiveValue => "Product 6", 3836 CreateTime => "2016-05-29 11:04:04", 3837 ChangeTime => "2016-05-29 11:04:04", 3838 ); 3839 3840=cut 3841 3842sub ModifiedSettingVersionGet { 3843 my ( $Self, %Param ) = @_; 3844 3845 if ( !$Param{ModifiedVersionID} ) { 3846 $Kernel::OM->Get('Kernel::System::Log')->Log( 3847 Priority => 'error', 3848 Message => 'Need ModifiedVersionID!', 3849 ); 3850 return; 3851 } 3852 3853 my $CacheType = "SysConfigModifiedVersion"; 3854 my $CacheKey = 'ModifiedSettingVersionGet::' . $Param{ModifiedVersionID}; 3855 3856 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 3857 3858 # Return cache. 3859 my $Cache = $CacheObject->Get( 3860 Type => $CacheType, 3861 Key => $CacheKey, 3862 ); 3863 3864 return %{$Cache} if ref $Cache eq 'HASH'; 3865 3866 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 3867 3868 # Get modified from database. 3869 return if !$DBObject->Prepare( 3870 SQL => ' 3871 SELECT smv.id, smv.sysconfig_default_version_id, sdv.sysconfig_default_id, sm.id, 3872 smv.name, smv.user_id, 3873 smv.is_valid, smv.reset_to_default, smv.user_modification_active, smv.effective_value, 3874 smv.create_time, smv.change_time 3875 FROM sysconfig_modified_version smv 3876 LEFT JOIN sysconfig_default_version sdv 3877 ON smv.sysconfig_default_version_id = sdv.id 3878 LEFT JOIN sysconfig_modified sm 3879 ON sdv.sysconfig_default_id = sm.sysconfig_default_id 3880 WHERE smv.id = ?', 3881 Bind => [ \$Param{ModifiedVersionID} ], 3882 ); 3883 3884 my $YAMLObject = $Kernel::OM->Get('Kernel::System::YAML'); 3885 3886 my %ModifiedSettingVersion; 3887 while ( my @Data = $DBObject->FetchrowArray() ) { 3888 3889 # De-serialize modified data. 3890 my $EffectiveValue = $YAMLObject->Load( Data => $Data[9] ); 3891 3892 %ModifiedSettingVersion = ( 3893 ModifiedVersionID => $Data[0], 3894 DefaultVersionID => $Data[1], 3895 DefaultID => $Data[2], 3896 ModifiedID => $Data[3], 3897 Name => $Data[4], 3898 TargetUserID => $Data[5], 3899 IsValid => $Data[6], 3900 ResetToDefault => $Data[7] ? 1 : 0, 3901 UserModificationActive => $Data[8], 3902 EffectiveValue => $EffectiveValue, 3903 DeploymentTimeStamp => $Data[10], 3904 CreateTime => $Data[10], 3905 ChangeTime => $Data[11], 3906 ); 3907 } 3908 3909 $CacheObject->Set( 3910 Type => $CacheType, 3911 Key => $CacheKey, 3912 Value => \%ModifiedSettingVersion, 3913 TTL => $Self->{CacheTTL}, 3914 ); 3915 3916 return %ModifiedSettingVersion; 3917} 3918 3919=head2 ModifiedSettingVersionListGet() 3920 3921Get version setting list with complete data. 3922 3923 my @List = $SysConfigDBObject->ModifiedSettingVersionListGet( 3924 Name => 1, # optional 3925 DefaultVersionID => 230, # optional 3926 ); 3927 3928Returns: 3929 3930 @List = ( 3931 { 3932 ModifiedVersionID => 123, 3933 ModifiedID => 456, 3934 Name => "ProductName", 3935 TargetUserID => 78, 3936 IsValid => 1, # 1 or 0 3937 ResetToDefault => 1, # 1 or 0 3938 UserModificationActive => 0, # 1 or 0 3939 EffectiveValue => "Product 6", 3940 CreateTime => "2016-05-29 11:04:04", 3941 ChangeTime => "2016-05-29 11:04:04", 3942 }, 3943 { 3944 ModifiedVersionID => 789, 3945 ModifiedID => 579, 3946 Name => "ADifferentProductName", 3947 TargetUserID => 909, 3948 IsValid => 1, # 1 or 0 3949 ResetToDefault => 1, # 1 or 0 3950 UserModificationActive => 0, # 1 or 0 3951 . . . 3952 }, 3953 # ... 3954 ); 3955 3956=cut 3957 3958sub ModifiedSettingVersionListGet { 3959 my ( $Self, %Param ) = @_; 3960 3961 if ( !$Param{DefaultVersionID} && !$Param{Name} ) { 3962 $Kernel::OM->Get('Kernel::System::Log')->Log( 3963 Priority => 'error', 3964 Message => 'Need DefaultVersionID or Name!', 3965 ); 3966 return; 3967 } 3968 3969 my $FieldName; 3970 my $FieldValue; 3971 my $FieldCache; 3972 3973 if ( $Param{DefaultVersionID} ) { 3974 3975 # Set conditions for modified ID. 3976 $FieldName = 'sysconfig_default_version_id'; 3977 $FieldValue = $Param{DefaultVersionID}; 3978 $FieldCache = 'DefaultVersionID'; 3979 } 3980 elsif ( $Param{Name} ) { 3981 3982 # Set conditions for name. 3983 $FieldName = 'name'; 3984 $FieldValue = $Param{Name}; 3985 $FieldCache = 'Name'; 3986 } 3987 3988 # Loop over filters and set them on SQL and cache key. 3989 my $SQLFilter = "WHERE $FieldName = '$FieldValue' "; 3990 3991 my $CacheType = 'SysConfigModifiedVersionList'; 3992 my $CacheKey = 'ModifiedSettingVersionList::' . $FieldCache . '=' . $FieldValue; 3993 3994 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 3995 3996 # Return cache. 3997 my $Cache = $CacheObject->Get( 3998 Type => $CacheType, 3999 Key => $CacheKey, 4000 ); 4001 4002 return @{$Cache} if ref $Cache eq 'ARRAY'; 4003 4004 # Start SQL statement. 4005 my $SQL = ' 4006 SELECT id, name 4007 FROM sysconfig_modified_version'; 4008 4009 $SQL .= ' ' . $SQLFilter . ' ORDER BY id DESC'; 4010 4011 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 4012 4013 my @Data; 4014 return if !$DBObject->Prepare( 4015 SQL => $SQL, 4016 ); 4017 4018 my @ModifiedVersionIDs; 4019 while ( my @Row = $DBObject->FetchrowArray() ) { 4020 push @ModifiedVersionIDs, $Row[0]; 4021 } 4022 4023 # Get modified settings. 4024 ITEMID: 4025 for my $ItemID (@ModifiedVersionIDs) { 4026 4027 my %ModifiedSetting = $Self->ModifiedSettingVersionGet( 4028 ModifiedVersionID => $ItemID, 4029 ); 4030 4031 next ITEMID if !%ModifiedSetting; 4032 4033 push @Data, \%ModifiedSetting; 4034 } 4035 4036 $CacheObject->Set( 4037 Type => $CacheType, 4038 Key => $CacheKey, 4039 Value => \@Data, 4040 TTL => $Self->{CacheTTL}, 4041 ); 4042 4043 return @Data; 4044} 4045 4046=head2 ModifiedSettingVersionGetLast() 4047 4048Get last deployment. 4049 4050 my %ModifiedSettingVersion = $SysConfigDBObject->ModifiedSettingVersionGetLast( 4051 Name => 'ProductName', 4052 ); 4053 4054Returns: 4055 4056 %ModifiedSettingVersion = ( 4057 DefaultVersionID => 123, 4058 ModifiedID => 456, 4059 Name => "ProductName", 4060 TargetUserID => 45, 4061 IsValid => 1, # 1 or 0 4062 ResetToDefault => 1, # 1 or 0 4063 UserModificationActive => 0, # 1 or 0 4064 EffectiveValue => "Product 6", 4065 CreateTime => "2016-05-29 11:04:04", 4066 ChangeTime => "2016-05-29 11:04:04", 4067 ); 4068 4069=cut 4070 4071sub ModifiedSettingVersionGetLast { 4072 my ( $Self, %Param ) = @_; 4073 4074 if ( !$Param{Name} ) { 4075 $Kernel::OM->Get('Kernel::System::Log')->Log( 4076 Priority => 'error', 4077 Message => 'Need Name!', 4078 ); 4079 return; 4080 } 4081 4082 my $CacheType = 'SysConfigModifiedVersion'; 4083 my $CacheKey = 'ModifiedSettingVersionGetLast::' . $Param{Name}; 4084 4085 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 4086 4087 # Return cache. 4088 my $Cache = $CacheObject->Get( 4089 Type => $CacheType, 4090 Key => $CacheKey, 4091 ); 4092 4093 return %{$Cache} if ref $Cache eq 'HASH'; 4094 4095 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 4096 4097 return if !$DBObject->Prepare( 4098 SQL => 'SELECT MAX(id) FROM sysconfig_modified_version WHERE name = ?', 4099 Bind => [ \$Param{Name} ], 4100 ); 4101 4102 my $ModifiedVersionID; 4103 while ( my @Row = $DBObject->FetchrowArray() ) { 4104 4105 $ModifiedVersionID = $Row[0]; 4106 } 4107 4108 return if !$ModifiedVersionID; 4109 4110 my %ModifiedSetting = $Self->ModifiedSettingVersionGet( 4111 ModifiedVersionID => $ModifiedVersionID, 4112 ); 4113 4114 $CacheObject->Set( 4115 Type => $CacheType, 4116 Key => $CacheKey, 4117 Value => \%ModifiedSetting, 4118 TTL => $Self->{CacheTTL}, 4119 ); 4120 4121 return %ModifiedSetting; 4122} 4123 4124=head2 ModifiedSettingVersionListGetLast() 4125 4126Get a list of the last deployed version of each modified SysConfig setting 4127 4128 my @List = $SysConfigDBObject->ModifiedSettingVersionListGetLast(); 4129 4130Returns: 4131 4132 @List = ( 4133 { 4134 ModifiedVersionID => 123, 4135 ModifiedID => 456, 4136 Name => "ProductName", 4137 TargetUserID => 78, 4138 IsValid => 1, # 1 or 0 4139 ResetToDefault => 1, # 1 or 0 4140 UserModificationActive => 0, # 1 or 0 4141 EffectiveValue => "Product 6", 4142 CreateTime => "2016-05-29 11:04:04", 4143 ChangeTime => "2016-05-29 11:04:04", 4144 }, 4145 { 4146 ModifiedVersionID => 789, 4147 ModifiedID => 579, 4148 Name => "ADifferentProductName", 4149 TargetUserID => 909, 4150 IsValid => 1, # 1 or 0 4151 ResetToDefault => 1, # 1 or 0 4152 UserModificationActive => 0, # 1 or 0 4153 . . . 4154 }, 4155 # ... 4156 ); 4157 4158=cut 4159 4160sub ModifiedSettingVersionListGetLast { 4161 my ( $Self, %Param ) = @_; 4162 4163 my $CacheType = 'SysConfigModifiedVersionList'; 4164 my $CacheKey = 'ModifiedSettingVersionListGetLast'; 4165 4166 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 4167 4168 # Return cache. 4169 my $Cache = $CacheObject->Get( 4170 Type => $CacheType, 4171 Key => $CacheKey, 4172 ); 4173 4174 return @{$Cache} if ref $Cache eq 'ARRAY'; 4175 4176 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 4177 4178 my @Data; 4179 return if !$DBObject->Prepare( 4180 SQL => ' 4181 SELECT MAX(id), sysconfig_default_version_id 4182 FROM sysconfig_modified_version 4183 GROUP BY sysconfig_default_version_id 4184 ORDER BY sysconfig_default_version_id ASC' 4185 ); 4186 4187 my @ModifiedVersionIDs; 4188 while ( my @Row = $DBObject->FetchrowArray() ) { 4189 push @ModifiedVersionIDs, $Row[0]; 4190 } 4191 4192 # Get modified settings. 4193 for my $ItemID (@ModifiedVersionIDs) { 4194 4195 my %ModifiedSetting = $Self->ModifiedSettingVersionGet( 4196 ModifiedVersionID => $ItemID, 4197 ); 4198 push @Data, \%ModifiedSetting; 4199 } 4200 4201 $CacheObject->Set( 4202 Type => $CacheType, 4203 Key => $CacheKey, 4204 Value => \@Data, 4205 TTL => $Self->{CacheTTL}, 4206 ); 4207 4208 return @Data; 4209} 4210 4211=head2 ModifiedSettingVersionDelete() 4212 4213Delete a modified setting version from list based on modified version ID or modified ID. 4214 4215 my $Success = $SysConfigDBObject->ModifiedSettingVersionDelete( 4216 ModifiedVersionID => 123, 4217 ); 4218 4219or 4220 4221 my $Success = $SysConfigDBObject->ModifiedSettingVersionDelete( 4222 ModifiedID => 45, 4223 ); 4224 4225or 4226 4227 my $Success = $SysConfigDBObject->ModifiedSettingVersionDelete( 4228 Name => 'AnyName', 4229 ); 4230 4231Returns: 4232 4233 $Success = 1; # or false in case of an error 4234 4235=cut 4236 4237sub ModifiedSettingVersionDelete { 4238 my ( $Self, %Param ) = @_; 4239 4240 if ( !$Param{ModifiedVersionID} && !$Param{ModifiedID} && !$Param{Name} ) { 4241 $Kernel::OM->Get('Kernel::System::Log')->Log( 4242 Priority => 'error', 4243 Message => 'Need ID, ModifiedID or Name!', 4244 ); 4245 return; 4246 } 4247 4248 my $FieldName; 4249 my $FieldValue; 4250 4251 if ( $Param{ModifiedVersionID} ) { 4252 4253 # Set conditions for ID. 4254 $FieldName = 'id'; 4255 $FieldValue = $Param{ModifiedVersionID}; 4256 } 4257 elsif ( $Param{DefaultVersionID} ) { 4258 4259 # Set conditions for default version id. 4260 $FieldName = 'sysconfig_default_version_id'; 4261 $FieldValue = $Param{DefaultVersionID}; 4262 } 4263 elsif ( $Param{Name} ) { 4264 4265 # Set conditions for name. 4266 $FieldName = 'name'; 4267 $FieldValue = $Param{Name}; 4268 4269 } 4270 4271 # Delete modified from the list. 4272 return if !$Kernel::OM->Get('Kernel::System::DB')->Do( 4273 SQL => 'DELETE FROM sysconfig_modified_version WHERE ' . $FieldName . ' = ?', 4274 Bind => [ \$FieldValue ], 4275 ); 4276 4277 if ( $FieldName eq 'id' ) { 4278 4279 my %ModifiedVersionSetting = $Self->ModifiedSettingVersionGet( 4280 ModifiedVersionID => $FieldValue, 4281 4282 ); 4283 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 4284 Type => 'SysConfigModifiedVersion', 4285 Key => 'ModifiedSettingVersionGet::' . $FieldValue, 4286 ); 4287 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 4288 Type => 'SysConfigModifiedVersion', 4289 Key => 'ModifiedSettingVersionGetLast::' . $ModifiedVersionSetting{DefaultVersionID}, 4290 ); 4291 } 4292 else { 4293 4294 $Kernel::OM->Get('Kernel::System::Cache')->CleanUp( 4295 Type => 'SysConfigModifiedVersion', 4296 ); 4297 } 4298 4299 $Kernel::OM->Get('Kernel::System::Cache')->CleanUp( 4300 Type => 'SysConfigModifiedVersionList', 4301 ); 4302 4303 return 1; 4304} 4305 4306=head2 ConfigurationIsDirty() 4307 4308Check if there are not deployed changes on system configuration. 4309 4310 my $Result = $SysConfigDBObject->ConfigurationIsDirty( 4311 UserID => 123, # optional, the user that changes a modified setting 4312 ); 4313 4314Returns: 4315 4316 $Result = 1; # or 0 if configuration is not dirty. 4317 4318=cut 4319 4320sub ConfigurationIsDirty { 4321 my ( $Self, %Param ) = @_; 4322 4323 my $CacheType = 'SysConfigIsDirty'; 4324 my $CacheKey = 'IsDirty'; 4325 4326 if ( $Param{UserID} ) { 4327 $CacheKey .= "::UserID=$Param{UserID}"; 4328 } 4329 4330 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 4331 4332 # Return cache. 4333 my $Cache = $CacheObject->Get( 4334 Type => $CacheType, 4335 Key => $CacheKey, 4336 ); 4337 4338 return ${$Cache} if ref $Cache eq 'SCALAR'; 4339 4340 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 4341 4342 my $SQL = ' 4343 SELECT sd.id 4344 FROM sysconfig_default sd 4345 LEFT OUTER JOIN sysconfig_modified sm ON sm.name = sd.name 4346 WHERE '; 4347 4348 my $SQLWhere = 'sd.is_dirty = 1 OR (sm.user_id IS NULL AND sm.is_dirty = 1)'; 4349 4350 my @Bind; 4351 if ( $Param{UserID} ) { 4352 $SQLWhere = 'sd.is_dirty = 1 OR (sm.user_id IS NULL AND sm.is_dirty = 1 AND sm.change_by = ? )'; 4353 push @Bind, \$Param{UserID}; 4354 } 4355 4356 $SQL .= $SQLWhere; 4357 4358 return if !$DBObject->Prepare( 4359 SQL => $SQL, 4360 Bind => \@Bind, 4361 Limit => 1, 4362 ); 4363 4364 my $Result; 4365 while ( my @Row = $DBObject->FetchrowArray() ) { 4366 $Result = 1; 4367 } 4368 4369 $Result //= '0'; 4370 4371 $CacheObject->Set( 4372 Type => $CacheType, 4373 Key => $CacheKey, 4374 Value => \$Result, 4375 TTL => $Self->{CacheTTL}, 4376 ); 4377 4378 return $Result; 4379} 4380 4381=head2 DeploymentAdd() 4382 4383Adds a new deployment. 4384 4385 my $DeploymentID = $SysConfigDBObject->DeploymentAdd( 4386 Comments => 'Some Comments', # optional 4387 EffectiveValueStrg => $EffectiveValuesStrgRef, # string reference with the value of all settings, 4388 # to be stored in a Perl cache file 4389 TargetUserID => 123, # to deploy only user specific settings 4390 ExclusiveLockGUID => $LockingString, # the GUID used to locking the deployment, 4391 # not needed if TargetUserID is used 4392 DeploymentTimeStamp => '1977-12-12 12:00:00', 4393 UserID => 123, 4394 ); 4395 4396Returns: 4397 4398 $DeploymentID = 123; # or false in case of an error 4399 4400=cut 4401 4402sub DeploymentAdd { 4403 my ( $Self, %Param ) = @_; 4404 4405 for my $Key (qw(UserID DeploymentTimeStamp)) { 4406 if ( !$Param{$Key} ) { 4407 $Kernel::OM->Get('Kernel::System::Log')->Log( 4408 Priority => 'error', 4409 Message => "Need $Key!", 4410 ); 4411 4412 return; 4413 } 4414 } 4415 4416 if ( !defined $Param{EffectiveValueStrg} ) { 4417 $Kernel::OM->Get('Kernel::System::Log')->Log( 4418 Priority => 'error', 4419 Message => "Need EffectiveValueStrg!" 4420 ); 4421 return; 4422 } 4423 4424 if ( !$Param{TargetUserID} && !$Param{ExclusiveLockGUID} ) { 4425 $Kernel::OM->Get('Kernel::System::Log')->Log( 4426 Priority => 'error', 4427 Message => "Need ExclusiveLockGUID", 4428 ); 4429 } 4430 4431 if ( ref $Param{EffectiveValueStrg} ne 'SCALAR' || !IsStringWithData( ${ $Param{EffectiveValueStrg} } ) ) { 4432 $Kernel::OM->Get('Kernel::System::Log')->Log( 4433 Priority => 'error', 4434 Message => "EffectiveValueStrg is invalid!", 4435 ); 4436 return; 4437 } 4438 4439 if ( exists $Param{TargetUserID} && !$Param{TargetUserID} ) { 4440 delete $Param{TargetUserID}; 4441 } 4442 4443 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 4444 4445 my @UserDeploymentIDs; 4446 if ( $Param{TargetUserID} ) { 4447 4448 # Remember previous user deployments. 4449 return if !$DBObject->Prepare( 4450 SQL => ' 4451 SELECT id 4452 FROM sysconfig_deployment 4453 WHERE user_id = ?', 4454 Bind => [ \$Param{TargetUserID}, ], 4455 ); 4456 4457 while ( my @Row = $DBObject->FetchrowArray() ) { 4458 push @UserDeploymentIDs, $Row[0]; 4459 } 4460 } 4461 else { 4462 my $ExclusiveLockGUID = $Self->DeploymentIsLockedByUser( 4463 ExclusiveLockGUID => $Param{ExclusiveLockGUID}, 4464 UserID => $Param{UserID}, 4465 ); 4466 4467 if ( !$ExclusiveLockGUID ) { 4468 $Kernel::OM->Get('Kernel::System::Log')->Log( 4469 Priority => 'error', 4470 Message => "Deployment is not locked to this user!", 4471 ); 4472 return; 4473 } 4474 } 4475 4476 my $UID = 'OTRSInvalid-' . $Self->_GetUID(); 4477 4478 # Create a deployment record without the real comments. 4479 return if !$DBObject->Do( 4480 SQL => ' 4481 INSERT INTO sysconfig_deployment 4482 (comments, effective_value, user_id, create_time, create_by) 4483 VALUES 4484 (?, ?, ?, ?, ?)', 4485 Bind => [ 4486 \$UID, \${ $Param{EffectiveValueStrg} }, \$Param{TargetUserID}, \$Param{DeploymentTimeStamp}, 4487 \$Param{UserID}, 4488 ], 4489 ); 4490 4491 # Get deployment ID. 4492 my $SQL = ' 4493 SELECT id 4494 FROM sysconfig_deployment 4495 WHERE comments = ? 4496 AND create_by = ?'; 4497 4498 my @Bind = ( \$UID, \$Param{UserID} ); 4499 4500 if ( $Param{TargetUserID} ) { 4501 $SQL .= ' 4502 AND user_id = ? 4503 '; 4504 push @Bind, \$Param{TargetUserID}; 4505 } 4506 else { 4507 $SQL .= ' 4508 AND user_id IS NULL 4509 '; 4510 } 4511 4512 $SQL .= ' 4513 ORDER BY id DESC'; 4514 4515 return if !$DBObject->Prepare( 4516 SQL => $SQL, 4517 Bind => \@Bind, 4518 Limit => 1, 4519 ); 4520 4521 # Fetch the deployment ID. 4522 my $DeploymentID; 4523 while ( my @Row = $DBObject->FetchrowArray() ) { 4524 $DeploymentID = $Row[0]; 4525 } 4526 4527 my $CurrentDeploymentIDStr = 'CurrentDeploymentID'; 4528 if ( $Param{TargetUserID} ) { 4529 $CurrentDeploymentIDStr = 'CurrentUserDeploymentID'; 4530 } 4531 4532 # Add the deployment ID to the values 4533 ${ $Param{EffectiveValueStrg} } 4534 =~ s{( \s+ my [ ] \(\$File, [ ] \$Self\) [ ] = [ ] \@_; \s+ )}{$1\$Self->{'$CurrentDeploymentIDStr'} = '$DeploymentID';\n}msx; 4535 4536 # Set the real deployment value. 4537 return if !$DBObject->Do( 4538 SQL => ' 4539 Update sysconfig_deployment 4540 SET comments = ?, effective_value = ? 4541 WHERE id = ?', 4542 Bind => [ 4543 \$Param{Comments}, \${ $Param{EffectiveValueStrg} }, \$DeploymentID, 4544 ], 4545 ); 4546 4547 # Remove previous user deployments (if any). 4548 for my $DeploymentID (@UserDeploymentIDs) { 4549 $Self->DeploymentDelete( 4550 DeploymentID => $DeploymentID, 4551 ); 4552 } 4553 4554 if ( $Param{TargetUserID} ) { 4555 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 4556 Type => 'SysConfigDeployment', 4557 Key => 'DeploymentUserList', 4558 ); 4559 } 4560 else { 4561 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 4562 Type => 'SysConfigDeployment', 4563 Key => 'DeploymentList', 4564 ); 4565 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 4566 Type => 'SysConfigDeployment', 4567 Key => 'DeploymentGetLast', 4568 ); 4569 } 4570 4571 return $DeploymentID; 4572} 4573 4574=head2 DeploymentGet() 4575 4576Gets deployment information. 4577 4578 my %Deployment = $SysConfigDBObject->DeploymentGet( 4579 DeploymentID => 123, 4580 Valid => 1, # optional (this is deprecated and will be removed in next mayor release). 4581 ); 4582 4583Returns: 4584 4585 %Deployment = ( 4586 DeploymentID => 123, 4587 Comments => 'Some Comments', 4588 EffectiveValueStrg => $SettingEffectiveValues, # string with the value of all settings, 4589 # as seen in the Perl configuration file. 4590 TargetUserID => 123, # optional (only in case of user specific deployments). 4591 CreateTime => "2016-05-29 11:04:04", 4592 CreateBy => 123, 4593 ); 4594 4595=cut 4596 4597sub DeploymentGet { 4598 my ( $Self, %Param ) = @_; 4599 4600 if ( !$Param{DeploymentID} ) { 4601 $Kernel::OM->Get('Kernel::System::Log')->Log( 4602 Priority => 'error', 4603 Message => "Need DeploymentID!", 4604 ); 4605 4606 return; 4607 } 4608 4609 my $CacheType = "SysConfigDeployment"; 4610 my $CacheKey = 'DeploymentGet::DeploymentID::' . $Param{DeploymentID}; 4611 4612 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 4613 4614 # Return cache. 4615 my $Cache = $CacheObject->Get( 4616 Type => $CacheType, 4617 Key => $CacheKey, 4618 ); 4619 4620 return %{$Cache} if ref $Cache eq 'HASH'; 4621 4622 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 4623 4624 # Get deployment from database. 4625 return if !$DBObject->Prepare( 4626 SQL => ' 4627 SELECT id, comments, effective_value, user_id, create_time, create_by 4628 FROM sysconfig_deployment 4629 WHERE id = ?', 4630 Bind => [ \$Param{DeploymentID} ], 4631 ); 4632 4633 my %Deployment; 4634 while ( my @Data = $DBObject->FetchrowArray() ) { 4635 4636 %Deployment = ( 4637 DeploymentID => $Data[0], 4638 Comments => $Data[1], 4639 EffectiveValueStrg => $Data[2], 4640 TargetUserID => $Data[3], 4641 CreateTime => $Data[4], 4642 CreateBy => $Data[5], 4643 ); 4644 } 4645 4646 return if !%Deployment; 4647 4648 my $Valid = defined $Param{Valid} ? $Param{Valid} : 1; 4649 4650 if ( $Deployment{EffectiveValueStrg} eq 'Invalid' && $Valid ) { 4651 $Kernel::OM->Get('Kernel::System::Log')->Log( 4652 Priority => 'error', 4653 Message => "The Deployment $Param{DeploymentID} is invalid!", 4654 ); 4655 return; 4656 } 4657 4658 $CacheObject->Set( 4659 Type => $CacheType, 4660 Key => $CacheKey, 4661 Value => \%Deployment, 4662 TTL => $Self->{CacheTTL}, 4663 ); 4664 4665 return %Deployment; 4666} 4667 4668=head2 DeploymentListGet() 4669 4670Get global deployment list with complete data. 4671 4672 my @List = $SysConfigDBObject->DeploymentListGet(); 4673 4674Returns: 4675 4676 @List = ( 4677 { 4678 DeploymentID => 123, 4679 Comments => 'Some Comments', 4680 EffectiveValueStrg => $SettingEffectiveValues, # String with the value of all settings, 4681 # as seen in the Perl configuration file. 4682 CreateTime => "2016-05-29 11:04:04", 4683 CreateBy => 123, 4684 }, 4685 { 4686 DeploymentID => 456, 4687 Comments => 'Some Comments', 4688 EffectiveValueStrg => $SettingEffectiveValues2, # String with the value of all settings, 4689 # as seen in the Perl configuration file. 4690 CreateTime => "2016-05-29 12:00:01", 4691 CreateBy => 123, 4692 }, 4693 # ... 4694 ); 4695 4696=cut 4697 4698sub DeploymentListGet { 4699 my ( $Self, %Param ) = @_; 4700 4701 my $CacheKey = 'DeploymentList'; 4702 4703 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 4704 4705 # Return cache. 4706 my $Cache = $CacheObject->Get( 4707 Type => 'SysConfigDeployment', 4708 Key => $CacheKey, 4709 ); 4710 4711 return @{$Cache} if ref $Cache eq 'ARRAY'; 4712 4713 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 4714 4715 my @Data; 4716 return if !$DBObject->Prepare( 4717 SQL => ' 4718 SELECT id 4719 FROM sysconfig_deployment 4720 WHERE user_id IS NULL 4721 ORDER BY id DESC', 4722 ); 4723 4724 my @DeploymentIDs; 4725 while ( my @Row = $DBObject->FetchrowArray() ) { 4726 push @DeploymentIDs, $Row[0]; 4727 } 4728 4729 # Get deployments. 4730 for my $ItemID (@DeploymentIDs) { 4731 4732 my %Deployment = $Self->DeploymentGet( 4733 DeploymentID => $ItemID, 4734 ); 4735 push @Data, \%Deployment; 4736 } 4737 4738 $CacheObject->Set( 4739 Type => 'SysConfigDeployment', 4740 Key => $CacheKey, 4741 Value => \@Data, 4742 TTL => $Self->{CacheTTL}, 4743 ); 4744 4745 return @Data; 4746} 4747 4748=head2 DeploymentUserList() 4749 4750Get DeploymentID -> UserID list of all user deployments. 4751 4752 my %List = $SysConfigDBObject->DeploymentUserList(); 4753 4754Returns: 4755 %List = { 4756 9876 => 123, 4757 5432 => 456, 4758 # ... 4759 }; 4760 4761=cut 4762 4763sub DeploymentUserList { 4764 my ( $Self, %Param ) = @_; 4765 4766 my $CacheKey = 'DeploymentUserList'; 4767 4768 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 4769 4770 # Return cache. 4771 my $Cache = $CacheObject->Get( 4772 Type => 'SysConfigDeployment', 4773 Key => $CacheKey, 4774 ); 4775 4776 return @{$Cache} if ref $Cache eq 'HASH'; 4777 4778 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 4779 4780 my @Data; 4781 return if !$DBObject->Prepare( 4782 SQL => ' 4783 SELECT id, user_id 4784 FROM sysconfig_deployment 4785 WHERE user_id IS NOT NULL 4786 ORDER BY id DESC', 4787 ); 4788 4789 my %Data; 4790 while ( my @Row = $DBObject->FetchrowArray() ) { 4791 $Data{ $Row[0] } = $Row[1]; 4792 } 4793 4794 $CacheObject->Set( 4795 Type => 'SysConfigDeployment', 4796 Key => $CacheKey, 4797 Value => \@Data, 4798 TTL => $Self->{CacheTTL}, 4799 ); 4800 4801 return %Data; 4802} 4803 4804=head2 DeploymentGetLast() 4805 4806Get last global deployment. 4807 4808 my %Deployment = $SysConfigDBObject->DeploymentGetLast(); 4809 4810Returns: 4811 4812 %Deployment = ( 4813 DeploymentID => 123, 4814 Comments => 'Some Comments', 4815 EffectiveValueStrg => $SettingEffectiveValues, # String with the value of all settings, 4816 # as seen in the Perl configuration file. 4817 CreateTime => "2016-05-29 11:04:04", 4818 CreateBy => 123, 4819 ); 4820 4821=cut 4822 4823sub DeploymentGetLast { 4824 my ( $Self, %Param ) = @_; 4825 4826 my $CacheKey = 'DeploymentGetLast'; 4827 4828 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 4829 4830 # Return cache. 4831 my $Cache = $CacheObject->Get( 4832 Type => 'SysConfigDeployment', 4833 Key => $CacheKey, 4834 ); 4835 4836 return %{$Cache} if ref $Cache eq 'HASH'; 4837 4838 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 4839 4840 my $DeploymentID; 4841 return if !$DBObject->Prepare( 4842 SQL => ' 4843 SELECT MAX(id) 4844 FROM sysconfig_deployment 4845 WHERE user_id IS NULL', 4846 ); 4847 4848 my @DeploymentID; 4849 while ( my @Row = $DBObject->FetchrowArray() ) { 4850 $DeploymentID = $Row[0]; 4851 } 4852 4853 return if !$DeploymentID; 4854 4855 my %Deployment = $Self->DeploymentGet( 4856 DeploymentID => $DeploymentID, 4857 ); 4858 4859 $CacheObject->Set( 4860 Type => 'SysConfigDeployment', 4861 Key => $CacheKey, 4862 Value => \%Deployment, 4863 TTL => $Self->{CacheTTL}, 4864 ); 4865 4866 return %Deployment; 4867} 4868 4869=head2 DeploymentDelete() 4870 4871Delete a deployment from the database. 4872 4873 my $Success = $SysConfigDBObject->DeploymentDelete( 4874 DeploymentID => 123, 4875 ); 4876 4877Returns: 4878 4879 $Success = 1; # or false in case of an error 4880 4881=cut 4882 4883sub DeploymentDelete { 4884 my ( $Self, %Param ) = @_; 4885 4886 if ( !$Param{DeploymentID} ) { 4887 $Kernel::OM->Get('Kernel::System::Log')->Log( 4888 Priority => 'error', 4889 Message => 'Need DeploymentID!', 4890 ); 4891 return; 4892 } 4893 4894 my %Deployment = $Self->DeploymentGet( 4895 DeploymentID => $Param{DeploymentID}, 4896 Valid => 0, 4897 ); 4898 4899 return 1 if !%Deployment; 4900 4901 # Delete deployment from the data base. 4902 return if !$Kernel::OM->Get('Kernel::System::DB')->Do( 4903 SQL => 'DELETE FROM sysconfig_deployment WHERE id = ?', 4904 Bind => [ \$Param{DeploymentID} ], 4905 ); 4906 4907 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 4908 Type => 'SysConfigDeployment', 4909 Key => 'DeploymentGet::DeploymentID::' . $Param{DeploymentID}, 4910 ); 4911 4912 if ( $Deployment{TargetUserID} ) { 4913 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 4914 Type => 'SysConfigDeployment', 4915 Key => 'DeploymentUserList', 4916 ); 4917 } 4918 else { 4919 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 4920 Type => 'SysConfigDeployment', 4921 Key => 'DeploymentList', 4922 ); 4923 $Kernel::OM->Get('Kernel::System::Cache')->Delete( 4924 Type => 'SysConfigDeployment', 4925 Key => 'DeploymentGetLast', 4926 ); 4927 } 4928 4929 return 1; 4930} 4931 4932=head2 DeploymentLock() 4933 4934Lock global deployment to a particular user. 4935 4936 my $ExclusiveLockGUID = $SysConfigDBObject->DeploymentLock( 4937 UserID => 123, 4938 ExclusiveLockGUID => $LockingString, # optional (if specific GUID is needed) 4939 Force => 1, # Optional, locks the deployment even if is already 4940 # locked to another user, also removes locks for 4941 # all settings. 4942 ); 4943 4944Returns: 4945 4946 $ExclusiveLockGUID = 'SomeLockingString'; # or false in case of an error or already locked 4947 4948=cut 4949 4950sub DeploymentLock { 4951 my ( $Self, %Param ) = @_; 4952 4953 if ( !$Param{UserID} ) { 4954 $Kernel::OM->Get('Kernel::System::Log')->Log( 4955 Priority => 'error', 4956 Message => "Need UserID!", 4957 ); 4958 return; 4959 } 4960 4961 my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 4962 4963 # It's not possible to lock a deployment if a setting is locked on a valid time. 4964 my @LockedList; 4965 if ( $Param{Force} ) { 4966 4967 my $Success = $Self->DefaultSettingUnlock( 4968 UnlockAll => 1, 4969 ); 4970 } 4971 else { 4972 @LockedList = $Self->DefaultSettingListGet( 4973 Locked => 1, 4974 ); 4975 } 4976 4977 # Get current time. 4978 my $CurrentDateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 4979 4980 if ( IsArrayRefWithData( \@LockedList ) ) { 4981 LOCKED: 4982 for my $Locked (@LockedList) { 4983 4984 next LOCKED if $Locked->{ExclusiveLockUserID} ne $Param{UserID}; 4985 4986 my $LockedDateTimeObject = $Kernel::OM->Create( 4987 'Kernel::System::DateTime', 4988 ObjectParams => { 4989 String => $Locked->{ExclusiveLockExpiryTime}, 4990 }, 4991 ); 4992 4993 my $IsLocked = $LockedDateTimeObject > $CurrentDateTimeObject ? 1 : 0; 4994 4995 if ($IsLocked) { 4996 $Kernel::OM->Get('Kernel::System::Log')->Log( 4997 Priority => 'error', 4998 Message => 4999 "It's not possible to lock a deployment if a setting is currently locked ($Locked->{Name}).", 5000 ); 5001 return; 5002 } 5003 } 5004 } 5005 5006 if ( defined $Param{ExclusiveLockGUID} && length $Param{ExclusiveLockGUID} != 32 ) { 5007 $Kernel::OM->Get('Kernel::System::Log')->Log( 5008 Priority => 'error', 5009 Message => "ExclusiveLockGUID is invalid", 5010 ); 5011 return; 5012 } 5013 5014 if ( $Param{Force} ) { 5015 my $Success = $Self->DeploymentUnlock( 5016 All => 1, 5017 ); 5018 } 5019 5020 # Check if it's already locked. 5021 return if $Self->DeploymentIsLocked(); 5022 5023 # If its not locked use or create a new locking string. 5024 my $ExclusiveLockGUID = $Param{ExclusiveLockGUID} || $Kernel::OM->Get('Kernel::System::Main')->GenerateRandomString( 5025 Length => 32, 5026 ); 5027 5028 my $DeploymentExpireTimeMinutes = 5; 5029 5030 # Set expire time. 5031 $DateTimeObject->Add( 5032 Minutes => $DeploymentExpireTimeMinutes, 5033 ); 5034 my $ExpiryTime = $DateTimeObject->ToString(); 5035 5036 my $SQL = ' 5037 INSERT INTO sysconfig_deployment_lock 5038 ( exclusive_lock_guid, exclusive_lock_user_id, exclusive_lock_expiry_time ) 5039 VALUES 5040 ( ?, ?, ? )'; 5041 5042 my @Bind = ( 5043 \$ExclusiveLockGUID, \$Param{UserID}, 5044 \$ExpiryTime, 5045 ); 5046 5047 # Create db record. 5048 return if !$Kernel::OM->Get('Kernel::System::DB')->Do( 5049 SQL => $SQL, 5050 Bind => \@Bind, 5051 ); 5052 5053 return $ExclusiveLockGUID; 5054} 5055 5056=head2 DeploymentIsLocked() 5057 5058Check if global deployment is locked. 5059 5060 my $Locked = $SysConfigDBObject->DeploymentIsLocked(); 5061 5062Returns: 5063 5064 $Locked = 1; # or false if it is not locked 5065 5066=cut 5067 5068sub DeploymentIsLocked { 5069 my ( $Self, %Param ) = @_; 5070 5071 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 5072 5073 # Get deployment lock from the DB. 5074 my %DeploymentLock = $Self->_DeploymentLockGet(); 5075 5076 # Return no lock if there is no locking information. 5077 return if !%DeploymentLock; 5078 5079 # Return no lock if there is no lock expiry time. 5080 return if !$DeploymentLock{ExclusiveLockExpiryTime}; 5081 5082 # Deployment was locked, check if lock has expired. 5083 5084 # Get current time. 5085 my $CurrentDateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 5086 5087 my $LockedDateTimeObject = $Kernel::OM->Create( 5088 'Kernel::System::DateTime', 5089 ObjectParams => { 5090 String => $DeploymentLock{ExclusiveLockExpiryTime}, 5091 }, 5092 ); 5093 5094 my $Locked = $LockedDateTimeObject > $CurrentDateTimeObject ? 1 : 0; 5095 5096 if ( !$Locked ) { 5097 $Self->DeploymentUnlock( 5098 All => 1, 5099 ); 5100 } 5101 5102 return $Locked; 5103} 5104 5105=head2 DeploymentIsLockedByUser() 5106 5107Check if global deployment is locked for a determined user. 5108 5109 my $LockedByUser = $SysConfigDBObject->DeploymentIsLockedByUser( 5110 ExclusiveLockGUID => $LockingString, # the GUID used to locking the deployment 5111 UserID => 123, # the user should have locked the deployment 5112 ); 5113 5114Returns: 5115 5116 $LockedByUser = 'SomeLockingString'; # or false in case of not locked 5117 5118=cut 5119 5120sub DeploymentIsLockedByUser { 5121 my ( $Self, %Param ) = @_; 5122 5123 # Check needed stuff. 5124 for my $Needed (qw(UserID ExclusiveLockGUID)) { 5125 if ( !$Param{$Needed} ) { 5126 $Kernel::OM->Get('Kernel::System::Log')->Log( 5127 Priority => 'error', 5128 Message => "Need $Needed!", 5129 ); 5130 return; 5131 } 5132 } 5133 5134 return if !IsStringWithData( $Param{ExclusiveLockGUID} ); 5135 5136 # ExclusiveLockGUID should not be 0 5137 return if !$Param{ExclusiveLockGUID}; 5138 5139 # Get deployment lock from the DB. 5140 my %DeploymentLock = $Self->_DeploymentLockGet(); 5141 5142 # Return no lock if there is no locking information. 5143 return if !%DeploymentLock; 5144 5145 # Return no lock if there is no lock expiry time. 5146 return if !$DeploymentLock{ExclusiveLockExpiryTime}; 5147 5148 # Check ExclusiveLockUserID 5149 return if $DeploymentLock{ExclusiveLockUserID} ne $Param{UserID}; 5150 5151 # Check ExclusiveLockGUID 5152 return if !$DeploymentLock{ExclusiveLockGUID}; 5153 return if $DeploymentLock{ExclusiveLockGUID} ne $Param{ExclusiveLockGUID}; 5154 5155 my $ExclusiveLockGUID = $DeploymentLock{ExclusiveLockGUID}; 5156 5157 # If deployment was locked, check if lock has expired. 5158 my $CurrentDateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 5159 5160 my $LockedDateTimeObject = $Kernel::OM->Create( 5161 'Kernel::System::DateTime', 5162 ObjectParams => { 5163 String => $DeploymentLock{ExclusiveLockExpiryTime}, 5164 }, 5165 ); 5166 5167 my $Locked = $LockedDateTimeObject > $CurrentDateTimeObject ? 1 : 0; 5168 5169 # Extend the time if it was already locked for the user but time has been expired 5170 if ( !$Locked ) { 5171 $ExclusiveLockGUID = $Self->DeploymentLock( 5172 UserID => $Param{UserID}, 5173 ExclusiveLockGUID => $Param{ExclusiveLockGUID}, 5174 ); 5175 5176 return if !$ExclusiveLockGUID; 5177 } 5178 5179 return 1; 5180} 5181 5182=head2 DeploymentModifiedVersionList() 5183 5184Return a list of modified versions for a global deployment based on the deployment time. Limited 5185to a particular deployment or including also all previous deployments 5186 5187 my %ModifiedVersionList = $SysConfigDBObject->DeploymentModifiedVersionList( 5188 DeploymentID => 123, # the deployment id 5189 Mode => 'Equals' # (optional) default 'Equals' 5190 # Equals: only the settings from the given deployment 5191 # GreaterThan: only the settings after the given deployment 5192 # GreaterThanEquals: includes the settings of the given deployment and after 5193 # SmallerThan: only the settings before the given deployment 5194 # SmallerThanEquals: includes the settings of the given deployment and before 5195 ); 5196 5197Returns: 5198 5199 %ModifiedVersionIDs = ( 5200 123 => 'Setting1', 5201 124 => 'Setting2', 5202 125 => 'Setting3' 5203 ); 5204 5205=cut 5206 5207sub DeploymentModifiedVersionList { 5208 my ( $Self, %Param ) = @_; 5209 5210 if ( !$Param{DeploymentID} ) { 5211 $Kernel::OM->Get('Kernel::System::Log')->Log( 5212 Priority => 'error', 5213 Message => "Need DeploymentID!", 5214 ); 5215 return; 5216 } 5217 5218 my $Mode = $Param{Mode} // 'Equals'; 5219 my %ModeMapping = ( 5220 Equals => '=', 5221 GreaterThan => '>', 5222 GreaterThanEquals => '>=', 5223 SmallerThan => '<', 5224 SmallerThanEquals => '<=', 5225 ); 5226 if ( !$ModeMapping{$Mode} ) { 5227 $Self->{LogObject}->Log( 5228 Priority => 'error', 5229 Message => "Mode $Mode is invalid!", 5230 ); 5231 return; 5232 } 5233 5234 my %Deployment = $Self->DeploymentGet( 5235 DeploymentID => $Param{DeploymentID}, 5236 ); 5237 return if !IsHashRefWithData( \%Deployment ); 5238 return if $Deployment{TargetUserID}; 5239 5240 my $CreateTime = $Deployment{CreateTime} || ''; 5241 return if !$CreateTime; 5242 5243 my $SQL = " 5244 SELECT max(smv.id) id, smv.name 5245 FROM sysconfig_modified_version smv 5246 WHERE smv.create_time $ModeMapping{$Mode} ? 5247 GROUP BY smv.name"; 5248 5249 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 5250 5251 return if !$DBObject->Prepare( 5252 SQL => $SQL, 5253 Bind => [ \$CreateTime, ] 5254 ); 5255 5256 my %ModifiedVersionList; 5257 while ( my @Row = $DBObject->FetchrowArray() ) { 5258 $ModifiedVersionList{ $Row[0] } = $Row[1]; 5259 } 5260 5261 return %ModifiedVersionList; 5262 5263} 5264 5265=head2 DeploymentUnlock() 5266 5267Unlock global deployment. 5268 5269 my $Success = $SysConfigDBObject->DeploymentUnlock( 5270 ExclusiveLockGUID => '12ad34f21b', 5271 UserID => 123, 5272 ); 5273 5274or 5275 5276 my $Success = $SysConfigDBObject->DeploymentUnlock( 5277 All => 1, 5278 ); 5279 5280Returns: 5281 5282 $Success = 1; # or false in case of an error 5283 5284=cut 5285 5286sub DeploymentUnlock { 5287 my ( $Self, %Param ) = @_; 5288 5289 # Check needed 5290 if ( !$Param{ExclusiveLockGUID} && !$Param{UserID} && !$Param{All} ) { 5291 $Kernel::OM->Get('Kernel::System::Log')->Log( 5292 Priority => 'error', 5293 Message => 'All or ExclusiveLockGUID and UserID are needed!', 5294 ); 5295 return; 5296 } 5297 5298 if ( ( $Param{ExclusiveLockGUID} && !$Param{UserID} ) || ( $Param{UserID} && !$Param{ExclusiveLockGUID} ) ) { 5299 $Kernel::OM->Get('Kernel::System::Log')->Log( 5300 Priority => 'error', 5301 Message => 'ExclusiveLockGUID and UserID are needed!', 5302 ); 5303 return; 5304 } 5305 5306 my $SQL = 'DELETE FROM sysconfig_deployment_lock'; 5307 my @Bind; 5308 5309 if ( $Param{ExclusiveLockGUID} ) { 5310 $SQL .= ' 5311 WHERE exclusive_lock_guid = ? 5312 AND exclusive_lock_user_id = ?'; 5313 5314 @Bind = ( \$Param{ExclusiveLockGUID}, \$Param{UserID} ); 5315 } 5316 5317 # Update db record. 5318 return if !$Kernel::OM->Get('Kernel::System::DB')->Do( 5319 SQL => $SQL, 5320 Bind => \@Bind, 5321 ); 5322 5323 return 1; 5324} 5325 5326=head2 DeploymentListCleanup() 5327 5328Removes invalid deployments from the database. 5329 5330 my $Success = $SysConfigDBObject->DeploymentListCleanup( ); 5331 5332Returns: 5333 5334 $Success = 1; # Returns 1 if all records are valid (or all invalid was removed) 5335 # Returns -1 if there is an invalid deployment that could be in adding process 5336 # Returns false in case of an error 5337 5338=cut 5339 5340sub DeploymentListCleanup { 5341 my ( $Self, %Param ) = @_; 5342 5343 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 5344 5345 return if !$DBObject->Prepare( 5346 SQL => ' 5347 SELECT id, create_time 5348 FROM sysconfig_deployment 5349 WHERE effective_value LIKE \'Invalid%\' 5350 OR comments LIKE \'OTRSInvalid-%\' 5351 ORDER BY id DESC', 5352 ); 5353 5354 my @Deployments; 5355 while ( my @Row = $DBObject->FetchrowArray() ) { 5356 my %Deployment = ( 5357 DeploymentID => $Row[0], 5358 CreateTime => $Row[1], 5359 ); 5360 push @Deployments, \%Deployment; 5361 } 5362 5363 my $Success = 1; 5364 my $CurrentDateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 5365 5366 DEPLOYMENT: 5367 for my $Deployment (@Deployments) { 5368 5369 my $DeploymentDateTimeObject = $Kernel::OM->Create( 5370 'Kernel::System::DateTime', 5371 ObjectParams => { 5372 String => $Deployment->{CreateTime}, 5373 }, 5374 ); 5375 5376 my $Delta = $CurrentDateTimeObject->Delta( DateTimeObject => $DeploymentDateTimeObject ); 5377 5378 # Remove deployment only if it is old (more than 20 secs) 5379 if ( $DeploymentDateTimeObject < $CurrentDateTimeObject && $Delta >= 20 ) { 5380 $Kernel::OM->Get('Kernel::System::Log')->Log( 5381 Priority => 'error', 5382 Message => "Deployment $Deployment->{DeploymentID} is invalid and will be removed!", 5383 ); 5384 my $DeleteSuccess = $Self->DeploymentDelete( 5385 DeploymentID => $Deployment->{DeploymentID}, 5386 ); 5387 if ( !$DeleteSuccess ) { 5388 $Kernel::OM->Get('Kernel::System::Log')->Log( 5389 Priority => 'error', 5390 Message => "Could not delete deployment $Deployment->{DeploymentID}", 5391 ); 5392 $Success = 0; 5393 } 5394 last DEPLOYMENT; 5395 } 5396 5397 # Otherwise just log that there is something wrong with the deployment but do not remove it 5398 $Kernel::OM->Get('Kernel::System::Log')->Log( 5399 Priority => 'error', 5400 Message => "Deployment $Deployment->{DeploymentID} seams to be invalid or its not fully updated", 5401 ); 5402 $Success = -1; 5403 } 5404 5405 return $Success; 5406} 5407 5408=head1 PRIVATE INTERFACE 5409 5410=head2 _DeploymentLockGet() 5411 5412Get deployment lock entry. 5413 5414 my %DeploymentLock = $SysConfigDBObject->_DeploymentLockGet(); 5415 5416Returns: 5417 5418 %DeploymentLock = ( 5419 DeploymentLoclID => "123", 5420 ExclusiveLockGUID => $LockingString, 5421 ExclusiveLockUserID => 1, 5422 ExclusiveLockExpiryTime => '2016-05-29 11:09:04', 5423 CreateTime => "2016-05-29 11:04:04", 5424 ); 5425 5426=cut 5427 5428sub _DeploymentLockGet { 5429 my ( $Self, %Param ) = @_; 5430 5431 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 5432 5433 # Get deployment lock from the DB. 5434 return if !$DBObject->Prepare( 5435 SQL => ' 5436 SELECT id, exclusive_lock_guid, exclusive_lock_user_id, exclusive_lock_expiry_time 5437 FROM sysconfig_deployment_lock 5438 ORDER BY exclusive_lock_expiry_time DESC', 5439 Limit => 1, 5440 ); 5441 5442 my %DeploymentLock; 5443 while ( my @Data = $DBObject->FetchrowArray() ) { 5444 $DeploymentLock{ID} = $Data[0]; 5445 $DeploymentLock{ExclusiveLockGUID} = $Data[1]; 5446 $DeploymentLock{ExclusiveLockUserID} = $Data[2]; 5447 $DeploymentLock{ExclusiveLockExpiryTime} = $Data[3]; 5448 } 5449 5450 return %DeploymentLock; 5451} 5452 5453=head2 _BulkInsert() 5454 5455Add batch entries to the DB into a given table. 5456 5457 my $Success = $SysConfigDBObject->_BulkInsert( 5458 Table => 'table_name', # (required) Table name 5459 Columns => [ # (required) Array of column names 5460 'column_name', 5461 ... 5462 ], 5463 Data => [ # (required) AoA with data 5464 [ 5465 'record 1', 5466 'record 2', 5467 ], 5468 [ 5469 ... 5470 ], 5471 ... 5472 ], 5473 ); 5474 5475=cut 5476 5477sub _BulkInsert { 5478 my ( $Self, %Param ) = @_; 5479 5480 for my $Needed (qw(Table)) { 5481 if ( !$Param{$Needed} ) { 5482 $Kernel::OM->Get('Kernel::System::Log')->Log( 5483 Priority => 'error', 5484 Message => "Need $Needed!", 5485 ); 5486 return; 5487 } 5488 } 5489 5490 for my $Parameter (qw(Columns Data)) { 5491 if ( !IsArrayRefWithData( $Param{Columns} ) ) { 5492 $Kernel::OM->Get('Kernel::System::Log')->Log( 5493 Priority => 'error', 5494 Message => "$Parameter must be not empty array!" 5495 ); 5496 return; 5497 } 5498 } 5499 5500 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 5501 5502 # Get the database type. 5503 my $DBType = $DBObject->GetDatabaseFunction('Type'); 5504 5505 # Define database specific SQL for the multi-line inserts. 5506 my %DatabaseSQL; 5507 5508 my $Columns = join( ',', @{ $Param{Columns} } ); 5509 5510 # Check the first array in Data and create Mask (current_timestamp is always on same place in array). 5511 my @Mask = map { 5512 ( $_ && $_ eq 'current_timestamp' ) 5513 ? 'current_timestamp' : '?' 5514 } @{ $Param{Data}->[0] }; 5515 5516 my $MaskedValues = join( ',', @Mask ); 5517 5518 if ( $DBType eq 'oracle' ) { 5519 5520 %DatabaseSQL = ( 5521 Start => 'INSERT ALL ', 5522 FirstLine => " 5523 INTO $Param{Table} ($Columns) 5524 VALUES ( $MaskedValues ) ", 5525 NextLine => " 5526 INTO $Param{Table} ( 5527 $Columns 5528 ) 5529 VALUES ( $MaskedValues ) ", 5530 End => 'SELECT * FROM DUAL', 5531 ); 5532 } 5533 else { 5534 %DatabaseSQL = ( 5535 Start => " 5536 INSERT INTO $Param{Table} ( 5537 $Columns 5538 )", 5539 FirstLine => "VALUES ( $MaskedValues )", 5540 NextLine => ", ( $MaskedValues ) ", 5541 End => '', 5542 ); 5543 } 5544 5545 my $SQL = ''; 5546 my @Bind; 5547 5548 my $Count = 0; 5549 5550 RECORD: 5551 for my $Entry ( @{ $Param{Data} } ) { 5552 5553 $Count++; 5554 5555 if ( !IsArrayRefWithData($Entry) ) { 5556 $Kernel::OM->Get('Kernel::System::Log')->Log( 5557 Priority => 'error', 5558 Message => "Data contains empty array, skipped!" 5559 ); 5560 next RECORD; 5561 } 5562 5563 if ( scalar @{$Entry} != scalar @{ $Param{Columns} } ) { 5564 $Kernel::OM->Get('Kernel::System::Log')->Log( 5565 Priority => 'error', 5566 Message => "Array size doesn't match Columns size, skipped!" 5567 ); 5568 my $Col = scalar @{ $Param{Columns} }; 5569 next RECORD; 5570 } 5571 5572 # Now the article entry is validated and can be added to sql. 5573 if ( !$SQL ) { 5574 $SQL = $DatabaseSQL{Start} . $DatabaseSQL{FirstLine}; 5575 } 5576 else { 5577 $SQL .= $DatabaseSQL{NextLine}; 5578 } 5579 5580 BIND: 5581 for my $Item ( @{$Entry} ) { 5582 5583 next BIND if ( $Item && $Item eq 'current_timestamp' ); # Already included in the SQL part. 5584 5585 push @Bind, \$Item; 5586 } 5587 5588 # Check the length of the SQL string 5589 # (some databases only accept SQL strings up to 4k, 5590 # so we want to stay safe here with just 3500 bytes). 5591 if ( length $SQL > 3500 || $Count == scalar @{ $Param{Data} } ) { 5592 5593 # Add the end line to sql string. 5594 $SQL .= $DatabaseSQL{End}; 5595 5596 # Insert multiple entries. 5597 return if !$DBObject->Do( 5598 SQL => $SQL, 5599 Bind => \@Bind, 5600 ); 5601 5602 # Reset the SQL string and the Bind array. 5603 $SQL = ''; 5604 @Bind = (); 5605 } 5606 } 5607 5608 return 1; 5609} 5610 5611=head2 _GetUID() 5612 5613Generates a unique identifier. 5614 5615 my $UID = $TicketNumberObject->_GetUID(); 5616 5617Returns: 5618 5619 my $UID = 14906327941360ed8455f125d0450277; 5620 5621=cut 5622 5623sub _GetUID { 5624 my ( $Self, %Param ) = @_; 5625 5626 my $NodeID = $Kernel::OM->Get('Kernel::Config')->Get('NodeID') || 1; 5627 my ( $Seconds, $Microseconds ) = Time::HiRes::gettimeofday(); 5628 my $ProcessID = $$; 5629 5630 my $CounterUID = $ProcessID . $Seconds . $Microseconds . $NodeID; 5631 5632 my $RandomString = $Kernel::OM->Get('Kernel::System::Main')->GenerateRandomString( 5633 Length => 32 - length $CounterUID, 5634 Dictionary => [ 0 .. 9, 'a' .. 'f' ], # hexadecimal 5635 ); 5636 5637 $CounterUID .= $RandomString; 5638 5639 return $CounterUID; 5640} 5641 56421; 5643 5644=head1 TERMS AND CONDITIONS 5645 5646This software is part of the OTRS project (L<https://otrs.org/>). 5647 5648This software comes with ABSOLUTELY NO WARRANTY. For details, see 5649the enclosed file COPYING for license information (GPL). If you 5650did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>. 5651 5652=cut 5653