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::ValueType::Entity;
10## nofilter(TidyAll::Plugin::OTRS::Perl::LayoutObject)
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    'Kernel::System::Main',
24    'Kernel::System::SysConfig::EntityType',
25);
26
27=head1 NAME
28
29Kernel::System::SysConfig::ValueType::Entity - System configuration entity value type backed.
30
31=head1 PUBLIC INTERFACE
32
33=head2 new()
34
35Create an object. Do not use it directly, instead use:
36
37    use Kernel::System::ObjectManager;
38    local $Kernel::OM = Kernel::System::ObjectManager->new();
39    my $ValueTypeObject = $Kernel::OM->Get('Kernel::System::SysConfig::ValueType::Entity');
40
41=cut
42
43sub new {
44    my ( $Type, %Param ) = @_;
45
46    # Allocate new hash for object.
47    my $Self = {};
48    bless( $Self, $Type );
49
50    return $Self;
51}
52
53=head2 SettingEffectiveValueCheck()
54
55Check if provided EffectiveValue matches structure defined in XMLContentParsed.
56
57    my %Result = $ValueTypeObject->SettingEffectiveValueCheck(
58        XMLContentParsed => {
59            Value => [
60                {
61                    'Item' => [
62                        {
63                            'Content'            => '3 - normal',
64                            'ValueEntityType'    => 'Priority',
65                            'ValueEntitySubType' => 'SomeSubType',
66                            'ValueType'          => 'Entity',
67                        },
68                    ],
69                },
70            ],
71        },
72        EffectiveValue => '2 - low',
73    );
74
75Result:
76    $Result = (
77        EffectiveValue => '2 - low',    # Note for Entity ValueTypes EffectiveValue is not changed.
78        Success => 1,
79        Error   => undef,
80    );
81
82=cut
83
84sub SettingEffectiveValueCheck {
85    my ( $Self, %Param ) = @_;
86
87    for (qw(XMLContentParsed)) {
88        if ( !$Param{$_} ) {
89            $Kernel::OM->Get('Kernel::System::Log')->Log(
90                Priority => 'error',
91                Message  => "Need $_!"
92            );
93            return;
94        }
95    }
96
97    my %Result = (
98        Success => 0,
99    );
100
101    # Data should be scalar.
102    if ( ref $Param{EffectiveValue} ) {
103        $Result{Error} = 'EffectiveValue for Entity must be scalar!';
104        return %Result;
105    }
106
107    my $Value = $Param{XMLContentParsed}->{Value};
108
109    for my $Parameter ( sort keys %{ $Param{Parameters} } ) {
110        if ( !defined $Value->[0]->{Item}->[0]->{$Parameter} ) {
111            $Value->[0]->{Item}->[0]->{$Parameter} = $Param{Parameters}->{$Parameter};
112        }
113    }
114
115    my $EntityType = $Value->[0]->{Item}->[0]->{ValueEntityType};
116
117    if ( !$EntityType ) {
118        $Result{Error} = 'ValueEntityType not provided!';
119        return %Result;
120    }
121
122    my $EntitySubType = $Value->[0]->{Item}->[0]->{ValueEntitySubType} || '';
123
124    my @ValidValues = $Self->EntityValueList(
125        EntityType    => $EntityType,
126        EntitySubType => $EntitySubType,
127    );
128
129    if ( !grep { $_ eq $Param{EffectiveValue} } @ValidValues ) {
130        $Result{Error} = "Entity value is invalid($Param{EffectiveValue})!";
131        return %Result;
132    }
133
134    $Result{Success}        = 1;
135    $Result{EffectiveValue} = $Param{EffectiveValue};
136
137    return %Result;
138}
139
140=head2 EntityValueList()
141
142Returns a list of valid values for provided EntityType.
143
144    my $Result = $ValueTypeObject->EntityValueList(
145        EntityType    => 'Priority',
146        EntitySubType => 'SomeSubtype',     # optional e.g. the ObjectType for DynamicField entities
147    );
148
149Returns:
150
151    $Result = [
152        '1 very low',
153        '2 low',
154        '3 medium',
155        '4 high',
156        '5 very high',
157    ];
158
159=cut
160
161sub EntityValueList {
162    my ( $Self, %Param ) = @_;
163
164    for my $Needed (qw(EntityType)) {
165        if ( !$Param{$Needed} ) {
166            $Kernel::OM->Get('Kernel::System::Log')->Log(
167                Priority => 'error',
168                Message  => "Need $Needed!",
169            );
170            return;
171        }
172    }
173
174    my $Loaded = $Kernel::OM->Get('Kernel::System::Main')->Require(
175        "Kernel::System::SysConfig::ValueType::Entity::$Param{EntityType}",
176    );
177
178    return [] if !$Loaded;
179
180    my $BackendObject = $Kernel::OM->Get(
181        "Kernel::System::SysConfig::ValueType::Entity::$Param{EntityType}",
182    );
183
184    return $BackendObject->EntityValueList(%Param);
185}
186
187=head2 SettingRender()
188
189Extracts the effective value from a XML parsed setting.
190
191    my $SettingHTML = $ValueTypeObject->SettingRender(
192        Name           => 'SettingName',
193        EffectiveValue => '3 medium',       # (optional)
194        DefaultValue   => '3 medium',       # (optional)
195        Class          => 'My class'        # (optional)
196        RW             => 1,                # (optional) Allow editing. Default 0.
197        Item           => [                 # (optional) XML parsed item
198            {
199                'ValueType'          => 'Entity',
200                'ValueEntityType'    => 'Priority',
201                'ValueEntitySubType' => 'SomeSubType',
202                'Content'            => '2 low',
203            },
204        ],
205        IsArray => 1,                       # (optional) Item is part of the array
206        IsHash  => 1,                       # (optional) Item is part of the hash
207        SkipEffectiveValueCheck => 1,       # (optional) If enabled, system will not perform effective value check.
208                                            #            Default: 1.
209    );
210
211Returns:
212
213    $SettingHTML = '<div class "Field"...</div>';
214
215=cut
216
217sub SettingRender {
218    my ( $Self, %Param ) = @_;
219
220    if ( !defined $Param{Name} ) {
221        $Kernel::OM->Get('Kernel::System::Log')->Log(
222            Priority => 'error',
223            Message  => "Need Name",
224        );
225        return;
226    }
227
228    $Param{Class}        //= '';
229    $Param{DefaultValue} //= '';
230    $Param{IDSuffix}     //= '';
231
232    my $LanguageObject = $Kernel::OM->Get('Kernel::Language');
233
234    my $Value = $Param{Value};
235
236    my $EntityType;
237    my $EntitySubType;
238
239    my $EffectiveValue = $Param{EffectiveValue};
240    if (
241        !defined $EffectiveValue
242        && $Param{Item}->[0]->{Content}
243        )
244    {
245        $EffectiveValue = $Param{Item}->[0]->{Content};
246    }
247
248    if (
249        $Param{Item}
250        && $Param{Item}->[0]->{ValueEntityType}
251        )
252    {
253        $EntityType    = $Param{Item}->[0]->{ValueEntityType};
254        $EntitySubType = $Param{Item}->[0]->{ValueEntitySubType} || '';
255    }
256    elsif (
257        $Value->[0]->{Item}
258        && $Value->[0]->{Item}->[0]->{ValueEntityType}
259        )
260    {
261        $EntityType    = $Value->[0]->{Item}->[0]->{ValueEntityType};
262        $EntitySubType = $Value->[0]->{Item}->[0]->{ValueEntitySubType} || '';
263    }
264    elsif ( $Value->[0]->{Array} ) {
265        $EntityType    = $Value->[0]->{Array}->[0]->{DefaultItem}->[0]->{ValueEntityType};
266        $EntitySubType = $Value->[0]->{Array}->[0]->{DefaultItem}->[0]->{ValueEntitySubType} || '';
267    }
268    elsif ( $Value->[0]->{Hash} ) {
269        if (
270            $Value->[0]->{Hash}->[0]->{DefaultItem}
271            && $Value->[0]->{Hash}->[0]->{DefaultItem}->[0]->{ValueEntityType}
272            )
273        {
274
275            # take ValueEntityType from DefaultItem
276            $EntityType    = $Value->[0]->{Hash}->[0]->{DefaultItem}->[0]->{ValueEntityType};
277            $EntitySubType = $Value->[0]->{Hash}->[0]->{DefaultItem}->[0]->{ValueEntitySubType} || '';
278        }
279        else {
280            # check if there is definition for certain key
281            ITEM:
282            for my $Item ( @{ $Value->[0]->{Hash}->[0]->{Item} } ) {
283                if ( $Item->{Key} eq $Param{Key} ) {
284                    $EntityType    = $Item->{ValueEntityType}    || '';
285                    $EntitySubType = $Item->{ValueEntitySubType} || '';
286                    last ITEM;
287                }
288            }
289        }
290    }
291
292    my @EntityValues = $Self->EntityValueList(
293        EntityType    => $EntityType,
294        EntitySubType => $EntitySubType,
295    );
296
297    # When displaying diff between current and old value, it can happen that value is missing
298    #    since it was renamed, or removed. In this case, we need to add this "old" value also.
299    if (
300        $EffectiveValue
301        && !grep { $_ eq $EffectiveValue } @EntityValues
302        )
303    {
304        push @EntityValues, $EffectiveValue;
305    }
306
307    my %EffectiveValueCheck = (
308        Success => 1,
309    );
310
311    if ( !$Param{SkipEffectiveValueCheck} ) {
312        %EffectiveValueCheck = $Self->SettingEffectiveValueCheck(
313            EffectiveValue   => $EffectiveValue,
314            XMLContentParsed => {
315                Value => [
316                    {
317                        Item => $Param{Item},
318                    },
319                ],
320            },
321        );
322    }
323
324    my $HTML = "<div class='SettingContent'>\n";
325    $HTML .= $Kernel::OM->Get('Kernel::Output::HTML::Layout')->BuildSelection(
326        Data          => \@EntityValues,
327        Name          => $Param{Name},
328        ID            => $Param{Name} . $Param{IDSuffix},
329        Disabled      => $Param{RW} ? 0 : 1,
330        SelectedValue => $EffectiveValue,
331        Title         => $Param{Name},
332        OptionTitle   => 1,
333        Class         => "$Param{Class} Modernize",
334    );
335
336    if ( !$EffectiveValueCheck{Success} ) {
337        my $Message = $LanguageObject->Translate("Value is not correct! Please, consider updating this field.");
338
339        $HTML .= $Param{IsValid} ? "<div class='BadEffectiveValue'>\n" : "<div>\n";
340        $HTML .= "<p>* $Message</p>\n";
341        $HTML .= "</div>\n";
342    }
343
344    $HTML .= "</div>\n";
345
346    if ( !$Param{IsArray} && !$Param{IsHash} ) {
347        my $DefaultText = $LanguageObject->Translate('Default');
348
349        $HTML .= <<"EOF";
350                                <div class=\"WidgetMessage Bottom\">
351                                    $DefaultText: $Param{DefaultValue}
352                                </div>
353EOF
354    }
355
356    return $HTML;
357}
358
359=head2 AddItem()
360
361Generate HTML for new array/hash item.
362
363    my $HTML = $ValueTypeObject->AddItem(
364        Name           => 'SettingName',    (required) Name
365        DefaultItem    => {                 (required) DefaultItem hash
366            'Content'            => '3 normal',
367            'ValueType'          => 'Entity',
368            'ValueEntityType'    => 'Priority',
369            'ValueEntitySubType' => 'SomeSubType',
370        },
371        IDSuffix       => '_Array1',        (optional) IDSuffix is needed for arrays and hashes.
372    );
373
374Returns:
375
376    $HTML = '<select class="Modernize" id="SettingName" name="SettingName" title="SettingName">
377        ...
378        </select>';
379
380=cut
381
382sub AddItem {
383    my ( $Self, %Param ) = @_;
384
385    # Check needed stuff.
386    for my $Needed (qw(Name DefaultItem)) {
387        if ( !$Param{$Needed} ) {
388            $Kernel::OM->Get('Kernel::System::Log')->Log(
389                Priority => 'error',
390                Message  => "Need $Needed!",
391            );
392            return;
393        }
394    }
395
396    $Param{Class}    //= '';
397    $Param{IDSuffix} //= '';
398
399    my @EntityValues = $Self->EntityValueList(
400        EntityType    => $Param{DefaultItem}->{ValueEntityType},
401        EntitySubType => $Param{DefaultItem}->{ValueEntitySubType} || '',
402    );
403
404    my $Result = $Kernel::OM->Get('Kernel::Output::HTML::Layout')->BuildSelection(
405        Data          => \@EntityValues,
406        Name          => $Param{Name},
407        ID            => $Param{Name} . $Param{IDSuffix},
408        SelectedValue => $Param{DefaultItem}->{Content},
409        Title         => $Param{Name},
410        OptionTitle   => 1,
411        Class         => "$Param{Class} Modernize Entry",
412    );
413
414    return $Result;
415}
416
417=head2 EntityLookupFromWebRequest()
418
419Gets the entity name from the web request
420
421Called URL: index.pl?Action=AdminQueue;Subaction=Change;QueueID=1
422
423    my $EntityName = $ValueTypeObject->EntityLookupFromWebRequest(
424        EntityType    => 'Queue',
425    );
426
427Returns:
428
429    $EntityName = 'Postmaster';
430
431=cut
432
433sub EntityLookupFromWebRequest {
434    my ( $Self, %Param ) = @_;
435
436    for my $Needed (qw(EntityType)) {
437        if ( !$Param{$Needed} ) {
438            $Kernel::OM->Get('Kernel::System::Log')->Log(
439                Priority => 'error',
440                Message  => "Need $Needed!",
441            );
442            return;
443        }
444    }
445
446    my $Loaded = $Kernel::OM->Get('Kernel::System::Main')->Require(
447        "Kernel::System::SysConfig::ValueType::Entity::$Param{EntityType}",
448    );
449
450    return if !$Loaded;
451
452    my $BackendObject = $Kernel::OM->Get(
453        "Kernel::System::SysConfig::ValueType::Entity::$Param{EntityType}",
454    );
455
456    return if !$BackendObject->can('EntityLookupFromWebRequest');
457
458    return $BackendObject->EntityLookupFromWebRequest();
459}
460
4611;
462
463=head1 TERMS AND CONDITIONS
464
465This software is part of the OTRS project (L<https://otrs.org/>).
466
467This software comes with ABSOLUTELY NO WARRANTY. For details, see
468the enclosed file COPYING for license information (GPL). If you
469did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>.
470
471=cut
472