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