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