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## nofilter(TidyAll::Plugin::OTRS::Perl::LayoutObject) 9 10package Kernel::System::SysConfig::ValueType::VacationDaysOneTime; 11 12use strict; 13use warnings; 14 15use Kernel::System::VariableCheck qw(:all); 16 17use parent qw(Kernel::System::SysConfig::BaseValueType); 18 19our @ObjectDependencies = ( 20 'Kernel::Language', 21 'Kernel::Output::HTML::Layout', 22 'Kernel::System::Log', 23); 24 25=head1 NAME 26 27Kernel::System::SysConfig::ValueType::VacationDaysOneTime - System configuration vacation-days-one-time value type backed. 28 29=head1 PUBLIC INTERFACE 30 31=head2 new() 32 33Create an object. Do not use it directly, instead use: 34 35 use Kernel::System::ObjectManager; 36 local $Kernel::OM = Kernel::System::ObjectManager->new(); 37 my $ValueTypeObject = $Kernel::OM->Get('Kernel::System::SysConfig::ValueType::VacationDaysOneTime'); 38 39=cut 40 41sub new { 42 my ( $Type, %Param ) = @_; 43 44 # Allocate new hash for object. 45 my $Self = {}; 46 bless( $Self, $Type ); 47 48 return $Self; 49} 50 51=head2 SettingEffectiveValueCheck() 52 53Check if provided EffectiveValue matches structure defined in XMLContentParsed. 54 55 my %Result = $ValueTypeObject->SettingEffectiveValueCheck( 56 XMLContentParsed => { 57 Value => [ 58 { 59 'Item' => [ 60 { 61 'Item' => [ 62 { 63 'Content' => 'New Year\'s Day', 64 'Translatable' => '1', 65 'ValueDay' => '1', 66 'ValueMonth' => '1', 67 'ValueYear' => '2004', 68 }, 69 ], 70 'ValueType' => 'VacationDaysOneTime', 71 }, 72 ], 73 }, 74 ], 75 }, 76 EffectiveValue => { 77 '2014' => { 78 '1' => { 79 '1' => 'New Year\'s Day', 80 }, 81 }, 82 '2016' => { 83 '2' => { 84 '2' => 'Test', 85 }, 86 }, 87 }, 88 ); 89 90Result: 91 %Result = ( 92 EffectiveValue => { # Note for VacationDaysOneTime ValueTypes EffectiveValue is not changed. 93 '2014' => { 94 '1' => { 95 '1' => 'New Year\'s Day', 96 }, 97 }, 98 '2016' => { 99 '2' => { 100 '2' => 'Test', 101 }, 102 }, 103 }, 104 Success => 1, 105 Error => undef, 106 ); 107 108=cut 109 110sub SettingEffectiveValueCheck { 111 my ( $Self, %Param ) = @_; 112 113 for my $Needed (qw(XMLContentParsed)) { 114 if ( !$Param{$Needed} ) { 115 $Kernel::OM->Get('Kernel::System::Log')->Log( 116 Priority => 'error', 117 Message => "Need $Needed!" 118 ); 119 120 return; 121 } 122 } 123 124 my %Result = ( 125 Success => 0, 126 ); 127 128 # Data should be hash. 129 if ( ref $Param{EffectiveValue} ne 'HASH' ) { 130 $Result{Error} = 'EffectiveValue for VacationDaysOneTime must be a hash!'; 131 return %Result; 132 } 133 134 YEAR: 135 for my $Year ( sort keys %{ $Param{EffectiveValue} } ) { 136 if ( $Year !~ m{^\d{4}$}gsmx ) { 137 $Result{Error} = "'$Year' must be a year number(1000-9999)!"; 138 last YEAR; 139 } 140 141 if ( !IsHashRefWithData( $Param{EffectiveValue}->{$Year} ) ) { 142 $Result{Error} = "'$Year' must be a hash reference!"; 143 return %Result; 144 } 145 146 for my $Month ( sort keys %{ $Param{EffectiveValue}->{$Year} } ) { 147 if ( $Month !~ m{^([1-9]|1[0-2])$}gsmx ) { 148 $Result{Error} = "'$Month' must be a month number(1..12)!"; 149 last YEAR; 150 } 151 152 if ( !IsHashRefWithData( $Param{EffectiveValue}->{$Year}->{$Month} ) ) { 153 $Result{Error} = "'$Month' must be a hash reference!"; 154 last YEAR; 155 } 156 157 for my $Day ( sort keys %{ $Param{EffectiveValue}->{$Year}->{$Month} } ) { 158 if ( $Day !~ m{^([1-9]|[12][0-9]|3[01])$}gsmx ) { 159 $Result{Error} = "'$Day' must be a day number(1..31)!"; 160 last YEAR; 161 } 162 163 if ( 164 ref $Param{EffectiveValue}->{$Year}->{$Month}->{$Day} 165 || !$Param{EffectiveValue}->{$Year}->{$Month}->{$Day} 166 ) 167 { 168 $Result{Error} = "Vacation description must be a string!"; 169 last YEAR; 170 } 171 } 172 } 173 } 174 return %Result if $Result{Error}; 175 176 $Result{Success} = 1; 177 $Result{EffectiveValue} = $Param{EffectiveValue}; 178 179 return %Result; 180} 181 182sub EffectiveValueGet { 183 my ( $Self, %Param ) = @_; 184 185 if ( !IsArrayRefWithData( $Param{Value} ) ) { 186 $Kernel::OM->Get('Kernel::System::Log')->Log( 187 Priority => 'error', 188 Message => "Value is missing or invalid!", 189 ); 190 191 return ''; 192 } 193 194 if ( scalar @{ $Param{Value} } > 1 ) { 195 $Kernel::OM->Get('Kernel::System::Log')->Log( 196 Priority => 'error', 197 Message => "Value must be a single element!", 198 ); 199 return ''; 200 } 201 202 return '' if !$Param{Value}->[0]->{Item}; 203 204 return '' if ref $Param{Value}->[0]->{Item} ne 'ARRAY'; 205 206 my %Result; 207 208 COMPONENT: 209 for my $Component ( @{ $Param{Value}->[0]->{Item} } ) { 210 next COMPONENT if !$Component->{ValueYear}; 211 next COMPONENT if !$Component->{ValueMonth}; 212 next COMPONENT if !$Component->{ValueDay}; 213 $Result{ $Component->{ValueYear} }->{ $Component->{ValueMonth} }->{ $Component->{ValueDay} } 214 = $Component->{Content}; 215 } 216 217 return \%Result; 218} 219 220sub ModifiedValueGet { 221 my ( $Self, %Param ) = @_; 222 223 for my $Needed (qw(Value EffectiveValue)) { 224 if ( !$Param{$Needed} ) { 225 $Kernel::OM->Get('Kernel::System::Log')->Log( 226 Priority => 'error', 227 Message => "Need $Needed!", 228 ); 229 return; 230 } 231 } 232 233 if ( ref $Param{EffectiveValue} ne 'HASH' ) { 234 $Kernel::OM->Get('Kernel::System::Log')->Log( 235 Priority => 'error', 236 Message => "EffectiveValue mush be a hash reference!" 237 ); 238 return; 239 } 240 241 my $Result = $Param{Value}; 242 243 my @Items; 244 245 # Update Content 246 YEAR: 247 for my $Year ( sort { $a <=> $b } keys %{ $Param{EffectiveValue} } ) { 248 if ( ref $Param{EffectiveValue}->{$Year} ne 'HASH' ) { 249 $Kernel::OM->Get('Kernel::System::Log')->Log( 250 Priority => 'error', 251 Message => "EffectiveValue must be a HoH!" 252 ); 253 next YEAR; 254 } 255 256 MONTH: 257 for my $Month ( sort { $a <=> $b } keys %{ $Param{EffectiveValue}->{$Year} } ) { 258 259 if ( ref $Param{EffectiveValue}->{$Year}->{$Month} ne 'HASH' ) { 260 $Kernel::OM->Get('Kernel::System::Log')->Log( 261 Priority => 'error', 262 Message => "EffectiveValue must be a HoHoH!" 263 ); 264 next MONTH; 265 } 266 267 for my $Day ( sort { $a <=> $b } keys %{ $Param{EffectiveValue}->{$Year}->{$Month} } ) { 268 my $Item = { 269 'ValueYear' => $Year, 270 'ValueMonth' => $Month, 271 'ValueDay' => $Day, 272 'Content' => $Param{EffectiveValue}->{$Year}->{$Month}->{$Day}, 273 }; 274 275 push @Items, $Item; 276 } 277 } 278 } 279 280 $Result->[0]->{Item}->[0]->{Item} = \@Items; 281 282 return $Result; 283} 284 285=head2 SettingRender() 286 287Extracts the effective value from a XML parsed setting. 288 289 my $SettingHTML = $ValueTypeObject->SettingRender( 290 Name => 'SettingName', 291 DefaultID => 123, # (required) 292 EffectiveValue => '{ 293 '2016' => { 294 '1' => { 295 '1' => 'New Year\'s Day', 296 }, 297 }, 298 ... 299 }, 300 DefaultValue => 'Product 5', # (optional) 301 Class => 'My class' # (optional) 302 Item => [ # (optional) XML parsed item 303 { 304 'ValueType' => 'VacationDaysOneTime', 305 'Content' => '', 306 'ValueRegex' => '', 307 }, 308 ], 309 RW => 1, # (optional) Allow editing. Default 0. 310 IsArray => 1, # (optional) Item is part of the array 311 IsHash => 1, # (optional) Item is part of the hash 312 IDSuffix => 1, # (optional) Suffix will be added to the element ID 313 SkipEffectiveValueCheck => 1, # (optional) If enabled, system will not perform effective value check. 314 # Default: 1. 315 ); 316 317Returns: 318 319 $SettingHTML = '<div class "Field"...</div>'; 320 321=cut 322 323sub SettingRender { 324 my ( $Self, %Param ) = @_; 325 326 for my $Needed (qw(Name EffectiveValue)) { 327 if ( !defined $Param{$Needed} ) { 328 $Kernel::OM->Get('Kernel::System::Log')->Log( 329 Priority => 'error', 330 Message => "Need $Needed", 331 ); 332 return; 333 } 334 } 335 336 $Param{Class} //= ''; 337 $Param{Class} .= " VacationDaysOneTime "; 338 $Param{DefaultValue} //= ''; 339 my $IDSuffix = $Param{IDSuffix} || ''; 340 341 my $LanguageObject = $Kernel::OM->Get('Kernel::Language'); 342 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 343 344 my $EffectiveValue = $Param{EffectiveValue}; 345 346 my %EffectiveValueCheck = ( 347 Success => 1, 348 ); 349 350 if ( !$Param{SkipEffectiveValueCheck} ) { 351 %EffectiveValueCheck = $Self->SettingEffectiveValueCheck( 352 EffectiveValue => $EffectiveValue, 353 XMLContentParsed => { 354 Value => [ 355 { 356 Item => $Param{Item}, 357 }, 358 ], 359 }, 360 ); 361 } 362 363 my $HTML = "<div class='Array VacationDaysOneTimeArray'>\n"; 364 365 if ( !$EffectiveValueCheck{Success} ) { 366 my $Message = $LanguageObject->Translate("Value is not correct! Please, consider updating this setting."); 367 368 $HTML .= $Param{IsValid} ? "<div class='BadEffectiveValue'>\n" : "<div>\n"; 369 $HTML .= "<p>* $Message</p>\n"; 370 $HTML .= "</div>\n"; 371 } 372 373 my @Days; 374 for my $Item ( 1 .. 31 ) { 375 push @Days, sprintf( "%02d", $Item ); 376 } 377 378 my @Months; 379 for my $Item ( 1 .. 12 ) { 380 push @Months, sprintf( "%02d", $Item ); 381 } 382 383 my $AddNewEntry = $LanguageObject->Translate("Add new entry"); 384 my $RemoveThisEntry = $LanguageObject->Translate("Remove this entry"); 385 386 my $Index = 1; 387 388 my $DateTime = $Kernel::OM->Create('Kernel::System::DateTime')->Get(); 389 390 for my $Year ( sort { $a <=> $b } keys %{ $Param{EffectiveValue} } ) { 391 for my $Month ( sort { $a <=> $b } keys %{ $Param{EffectiveValue}->{$Year} } ) { 392 393 for my $Day ( sort { $a <=> $b } keys %{ $Param{EffectiveValue}->{$Year}->{$Month} } ) { 394 my $Text = $Param{EffectiveValue}->{$Year}->{$Month}->{$Day}; 395 396 $HTML .= "<div class='ArrayItem'>\n"; 397 $HTML .= "<div class='SettingContent'>\n"; 398 399 my $YearPeriodFuture = 10; 400 my $YearPeriodPast = 10; 401 402 if ( $DateTime->{Year} - 10 > $Year ) { 403 $YearPeriodPast = $DateTime->{Year} - $Year; 404 } 405 elsif ( $DateTime->{Year} + 10 < $Year ) { 406 $YearPeriodFuture = $Year - $DateTime->{Year}; 407 } 408 409 my $Prefix = $Param{Name} . $IDSuffix . $Index; 410 411 $HTML .= $LayoutObject->BuildDateSelection( 412 Prefix => $Prefix, 413 $Prefix . "Year" => $Year, 414 $Prefix . "Month" => $Month, 415 $Prefix . "Day" => $Day, 416 $Prefix . "Class" => $Param{Class}, 417 YearPeriodFuture => $YearPeriodFuture, 418 YearPeriodPast => $YearPeriodPast, 419 Format => 'DateInputFormat', 420 Validate => 1, 421 Disabled => $Param{RW} ? 0 : 1, 422 ); 423 424 # description 425 my $HTMLDescription = $LayoutObject->Ascii2Html( 426 Text => $Text, 427 Type => 'Normal', 428 ); 429 $HTML .= "<input class=\"$Param{Class}\" type=\"text\" name=\"$Param{Name}\" " 430 . "id=\"$Param{Name}$IDSuffix" . $Index . "Description\" value=\"$HTMLDescription\" " 431 . "title=\"" . $LanguageObject->Translate("Description") . "\" "; 432 433 if ( !$Param{RW} ) { 434 $HTML .= "disabled='disabled' "; 435 } 436 437 $HTML .= " />\n"; 438 439 $HTML .= "</div>\n"; # SettingContent 440 441 if ( $Param{RW} ) { 442 $HTML .= "<button class='RemoveButton' type='button' " 443 . "title='$RemoveThisEntry' value='Remove this entry'>\n" 444 . " <i class='fa fa-minus-circle'></i>\n" 445 . " <span class='InvisibleText'>$RemoveThisEntry</span>\n" 446 . "</button>\n"; 447 } 448 $HTML .= "</div>\n"; # ArrayItem 449 $Index++; 450 } 451 } 452 } 453 454 if ( $Param{RW} ) { 455 $HTML .= " <button data-suffix='$Index' class='AddArrayItem' " 456 . "type='button' title='$AddNewEntry' value='Add new entry'>\n" 457 . " <i class='fa fa-plus-circle'></i>\n" 458 . " <span class='InvisibleText'>$AddNewEntry</span>\n" 459 . " </button>\n"; 460 } 461 $HTML .= "</div>\n"; # Array 462 463 if ( $Param{IsAjax} && $LayoutObject->{_JSOnDocumentComplete} && $Param{RW} ) { 464 for my $JS ( @{ $LayoutObject->{_JSOnDocumentComplete} } ) { 465 $HTML .= "<script>$JS</script>"; 466 } 467 } 468 469 return $HTML; 470} 471 472=head2 AddItem() 473 474Generate HTML for new array/hash item. 475 476 my $HTML = $ValueTypeObject->AddItem( 477 Name => 'SettingName', (required) Name 478 DefaultItem => { (optional) DefaultItem hash, if available 479 Item => { 480 Content => 'Value', 481 }, 482 }, 483 ); 484 485Returns: 486 487 $HTML = "<input type='text' id='Setting_ExampleArray' 488 value='Value' name='ExampleArray' class='Entry'/>"; 489 490=cut 491 492sub AddItem { 493 my ( $Self, %Param ) = @_; 494 495 # Check needed stuff. 496 for my $Needed (qw(Name)) { 497 if ( !$Param{$Needed} ) { 498 $Kernel::OM->Get('Kernel::System::Log')->Log( 499 Priority => 'error', 500 Message => "Need $Needed!", 501 ); 502 return; 503 } 504 } 505 506 my $LanguageObject = $Kernel::OM->Get('Kernel::Language'); 507 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 508 509 my $IDSuffix = $Param{IDSuffix} || ''; 510 my $Class = $Param{Class} || ''; 511 $Class .= " VacationDaysOneTime "; 512 513 my $Name = $Param{Name} . $IDSuffix; 514 515 my @Days; 516 for my $Item ( 1 .. 31 ) { 517 push @Days, sprintf( "%02d", $Item ); 518 } 519 520 my @Months; 521 for my $Item ( 1 .. 12 ) { 522 push @Months, sprintf( "%02d", $Item ); 523 } 524 525 my $RemoveThisEntry = $Kernel::OM->Get('Kernel::Language')->Translate("Remove this entry"); 526 527 my $DateTime = $Kernel::OM->Create('Kernel::System::DateTime')->Get(); 528 529 my $HTML = ""; 530 531 my $Prefix = $Param{Name} . $IDSuffix; 532 533 $HTML .= $LayoutObject->BuildDateSelection( 534 Prefix => $Prefix, 535 $Prefix . "Year" => $DateTime->{Year}, 536 $Prefix . "Month" => $DateTime->{Month}, 537 $Prefix . "Day" => $DateTime->{Day}, 538 $Prefix . "Class" => $Class, 539 YearPeriodFuture => 10, 540 YearPeriodPast => 10, 541 Format => 'DateInputFormat', 542 Validate => 1, 543 ); 544 545 # Description 546 $HTML .= "<input class=\"$Class\" type=\"text\" name=\"$Param{Name}\" " 547 . "id=\"$Param{Name}$IDSuffix" . "Description\" value=\"\" " 548 . "title=\"" . $LanguageObject->Translate("Description") . "\" " 549 . " />\n"; 550 551 for my $JS ( @{ $LayoutObject->{_JSOnDocumentComplete} } ) { 552 $HTML .= "<script>$JS</script>"; 553 } 554 555 return $HTML; 556} 557 558=head2 DefaultItemAdd() 559 560Return structure of the DefaultItem in case it's not inside of Array or Hash. 561 562 my $DefaultItem = $ValueTypeObject->DefaultItemAdd(); 563 564Returns: 565 566 $DefaultItem = { 567 Item => { 568 Content => '', 569 }, 570 ValueType => 'VacationDaysOneTime', 571 }; 572 573=cut 574 575sub DefaultItemAdd { 576 my ( $Self, %Param ) = @_; 577 578 my %Result = ( 579 Item => { 580 Content => '', 581 }, 582 ValueType => 'VacationDaysOneTime', 583 ); 584 585 return \%Result; 586} 587 5881; 589 590=head1 TERMS AND CONDITIONS 591 592This software is part of the OTRS project (L<https://otrs.org/>). 593 594This software comes with ABSOLUTELY NO WARRANTY. For details, see 595the enclosed file COPYING for license information (GPL). If you 596did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>. 597 598=cut 599