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