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::LinkObject::Ticket;
10
11use strict;
12use warnings;
13
14use Kernel::System::VariableCheck qw(:all);
15
16our @ObjectDependencies = (
17    'Kernel::Config',
18    'Kernel::System::Log',
19    'Kernel::System::Ticket',
20);
21
22=head1 NAME
23
24Kernel::System::LinkObject::Ticket
25
26=head1 DESCRIPTION
27
28Ticket backend for the ticket link object.
29
30=head1 PUBLIC INTERFACE
31
32=head2 new()
33
34Don't use the constructor directly, use the ObjectManager instead:
35
36    my $LinkObjectTicketObject = $Kernel::OM->Get('Kernel::System::LinkObject::Ticket');
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 LinkListWithData()
51
52fill up the link list with data
53
54    $Success = $LinkObject->LinkListWithData(
55        LinkList                     => $HashRef,
56        IgnoreLinkedTicketStateTypes => 0|1,        # (optional) default 0
57        UserID                       => 1,
58    );
59
60=cut
61
62sub LinkListWithData {
63    my ( $Self, %Param ) = @_;
64
65    # check needed stuff
66    for my $Argument (qw(LinkList UserID)) {
67        if ( !$Param{$Argument} ) {
68            $Kernel::OM->Get('Kernel::System::Log')->Log(
69                Priority => 'error',
70                Message  => "Need $Argument!",
71            );
72            return;
73        }
74    }
75
76    # check link list
77    if ( ref $Param{LinkList} ne 'HASH' ) {
78        $Kernel::OM->Get('Kernel::System::Log')->Log(
79            Priority => 'error',
80            Message  => 'LinkList must be a hash reference!',
81        );
82        return;
83    }
84
85    # get ticket object
86    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
87
88    # get config, which ticket state types should not be included in linked tickets overview
89    my @IgnoreLinkedTicketStateTypes = @{
90        $Kernel::OM->Get('Kernel::Config')->Get('LinkObject::IgnoreLinkedTicketStateTypes')
91            // []
92    };
93
94    my %IgnoreLinkTicketStateTypesHash;
95    map { $IgnoreLinkTicketStateTypesHash{$_}++ } @IgnoreLinkedTicketStateTypes;
96
97    for my $LinkType ( sort keys %{ $Param{LinkList} } ) {
98
99        for my $Direction ( sort keys %{ $Param{LinkList}->{$LinkType} } ) {
100
101            TICKETID:
102            for my $TicketID ( sort keys %{ $Param{LinkList}->{$LinkType}->{$Direction} } ) {
103
104                # get ticket data
105                my %TicketData = $TicketObject->TicketGet(
106                    TicketID      => $TicketID,
107                    UserID        => $Param{UserID},
108                    DynamicFields => 0,
109                );
110
111                # remove id from hash if ticket can not get
112                if ( !%TicketData ) {
113                    delete $Param{LinkList}->{$LinkType}->{$Direction}->{$TicketID};
114                    next TICKETID;
115                }
116
117                # if param is set, remove entries from hash with configured ticket state types
118                if (
119                    $Param{IgnoreLinkedTicketStateTypes}
120                    && $IgnoreLinkTicketStateTypesHash{ $TicketData{StateType} }
121                    )
122                {
123                    delete $Param{LinkList}->{$LinkType}->{$Direction}->{$TicketID};
124                    next TICKETID;
125                }
126
127                # add ticket data
128                $Param{LinkList}->{$LinkType}->{$Direction}->{$TicketID} = \%TicketData;
129            }
130        }
131    }
132
133    return 1;
134}
135
136=head2 ObjectPermission()
137
138checks read permission for a given object and UserID.
139
140    $Permission = $LinkObject->ObjectPermission(
141        Object  => 'Ticket',
142        Key     => 123,
143        UserID  => 1,
144    );
145
146=cut
147
148sub ObjectPermission {
149    my ( $Self, %Param ) = @_;
150
151    # check needed stuff
152    for my $Argument (qw(Object Key UserID)) {
153        if ( !$Param{$Argument} ) {
154            $Kernel::OM->Get('Kernel::System::Log')->Log(
155                Priority => 'error',
156                Message  => "Need $Argument!",
157            );
158            return;
159        }
160    }
161
162    return $Kernel::OM->Get('Kernel::System::Ticket')->TicketPermission(
163        Type     => 'ro',
164        TicketID => $Param{Key},
165        UserID   => $Param{UserID},
166    );
167}
168
169=head2 ObjectDescriptionGet()
170
171return a hash of object descriptions
172
173Return
174    %Description = (
175        Normal => "Ticket# 1234455",
176        Long   => "Ticket# 1234455: The Ticket Title",
177    );
178
179    %Description = $LinkObject->ObjectDescriptionGet(
180        Key     => 123,
181        Mode    => 'Temporary',  # (optional)
182        UserID  => 1,
183    );
184
185=cut
186
187sub ObjectDescriptionGet {
188    my ( $Self, %Param ) = @_;
189
190    # check needed stuff
191    for my $Argument (qw(Object Key UserID)) {
192        if ( !$Param{$Argument} ) {
193            $Kernel::OM->Get('Kernel::System::Log')->Log(
194                Priority => 'error',
195                Message  => "Need $Argument!",
196            );
197            return;
198        }
199    }
200
201    # create description
202    my %Description = (
203        Normal => 'Ticket',
204        Long   => 'Ticket',
205    );
206
207    return %Description if $Param{Mode} && $Param{Mode} eq 'Temporary';
208
209    # get ticket
210    my %Ticket = $Kernel::OM->Get('Kernel::System::Ticket')->TicketGet(
211        TicketID      => $Param{Key},
212        UserID        => $Param{UserID},
213        DynamicFields => 0,
214    );
215
216    return if !%Ticket;
217
218    my $ParamHook = $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Hook') || 'Ticket#';
219    $ParamHook .= $Kernel::OM->Get('Kernel::Config')->Get('Ticket::HookDivider') || '';
220
221    # create description
222    %Description = (
223        Normal => $ParamHook . "$Ticket{TicketNumber}",
224        Long   => $ParamHook . "$Ticket{TicketNumber}: $Ticket{Title}",
225    );
226
227    return %Description;
228}
229
230=head2 ObjectSearch()
231
232return a hash list of the search results
233
234Returns:
235
236    $SearchList = {
237        NOTLINKED => {
238            Source => {
239                12  => $DataOfItem12,
240                212 => $DataOfItem212,
241                332 => $DataOfItem332,
242            },
243        },
244    };
245
246    $SearchList = $LinkObject->ObjectSearch(
247        SubObject    => 'Bla',     # (optional)
248        SearchParams => $HashRef,  # (optional)
249        UserID       => 1,
250    );
251
252=cut
253
254sub ObjectSearch {
255    my ( $Self, %Param ) = @_;
256
257    # check needed stuff
258    if ( !$Param{UserID} ) {
259        $Kernel::OM->Get('Kernel::System::Log')->Log(
260            Priority => 'error',
261            Message  => 'Need UserID!',
262        );
263        return;
264    }
265
266    # set default params
267    $Param{SearchParams} ||= {};
268
269    # set focus
270    my %Search;
271    if ( $Param{SearchParams}->{TicketFulltext} ) {
272        $Search{Fulltext} = '*' . $Param{SearchParams}->{TicketFulltext} . '*';
273    }
274    if ( $Param{SearchParams}->{TicketTitle} ) {
275        $Search{Title} = '*' . $Param{SearchParams}->{TicketTitle} . '*';
276    }
277
278    if ( IsArrayRefWithData( $Param{SearchParams}->{ArchiveID} ) ) {
279        if ( $Param{SearchParams}->{ArchiveID}->[0] eq 'AllTickets' ) {
280            $Search{ArchiveFlags} = [ 'y', 'n' ];
281        }
282        elsif ( $Param{SearchParams}->{ArchiveID}->[0] eq 'NotArchivedTickets' ) {
283            $Search{ArchiveFlags} = ['n'];
284        }
285        elsif ( $Param{SearchParams}->{ArchiveID}->[0] eq 'ArchivedTickets' ) {
286            $Search{ArchiveFlags} = ['y'];
287        }
288    }
289
290    # get ticket object
291    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
292
293    # search the tickets
294    my @TicketIDs = $TicketObject->TicketSearch(
295        %{ $Param{SearchParams} },
296        %Search,
297        Limit               => 50,
298        Result              => 'ARRAY',
299        ConditionInline     => 1,
300        ContentSearchPrefix => '*',
301        ContentSearchSuffix => '*',
302        FullTextIndex       => 1,
303        OrderBy             => 'Down',
304        SortBy              => 'Age',
305        UserID              => $Param{UserID},
306    );
307
308    my %SearchList;
309    TICKETID:
310    for my $TicketID (@TicketIDs) {
311
312        # get ticket data
313        my %TicketData = $TicketObject->TicketGet(
314            TicketID      => $TicketID,
315            UserID        => $Param{UserID},
316            DynamicFields => 0,
317        );
318
319        next TICKETID if !%TicketData;
320
321        # add ticket data
322        $SearchList{NOTLINKED}->{Source}->{$TicketID} = \%TicketData;
323    }
324
325    return \%SearchList;
326}
327
328=head2 LinkAddPre()
329
330link add pre event module
331
332    $True = $LinkObject->LinkAddPre(
333        Key          => 123,
334        SourceObject => 'Ticket',
335        SourceKey    => 321,
336        Type         => 'Normal',
337        State        => 'Valid',
338        UserID       => 1,
339    );
340
341    or
342
343    $True = $LinkObject->LinkAddPre(
344        Key          => 123,
345        TargetObject => 'Ticket',
346        TargetKey    => 321,
347        Type         => 'Normal',
348        State        => 'Valid',
349        UserID       => 1,
350    );
351
352=cut
353
354sub LinkAddPre {
355    my ( $Self, %Param ) = @_;
356
357    # check needed stuff
358    for my $Argument (qw(Key Type State UserID)) {
359        if ( !$Param{$Argument} ) {
360            $Kernel::OM->Get('Kernel::System::Log')->Log(
361                Priority => 'error',
362                Message  => "Need $Argument!",
363            );
364            return;
365        }
366    }
367
368    return 1 if $Param{State} eq 'Temporary';
369
370    return 1;
371}
372
373=head2 LinkAddPost()
374
375link add pre event module
376
377    $True = $LinkObject->LinkAddPost(
378        Key          => 123,
379        SourceObject => 'Ticket',
380        SourceKey    => 321,
381        Type         => 'Normal',
382        State        => 'Valid',
383        UserID       => 1,
384    );
385
386    or
387
388    $True = $LinkObject->LinkAddPost(
389        Key          => 123,
390        TargetObject => 'Ticket',
391        TargetKey    => 321,
392        Type         => 'Normal',
393        State        => 'Valid',
394        UserID       => 1,
395    );
396
397=cut
398
399sub LinkAddPost {
400    my ( $Self, %Param ) = @_;
401
402    # check needed stuff
403    for my $Argument (qw(Key Type State UserID)) {
404        if ( !$Param{$Argument} ) {
405            $Kernel::OM->Get('Kernel::System::Log')->Log(
406                Priority => 'error',
407                Message  => "Need $Argument!",
408            );
409            return;
410        }
411    }
412
413    return 1 if $Param{State} eq 'Temporary';
414
415    # get ticket object
416    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
417
418    if ( $Param{SourceObject} && $Param{SourceObject} eq 'Ticket' && $Param{SourceKey} ) {
419
420        # lookup ticket number
421        my $TicketNumber = $TicketObject->TicketNumberLookup(
422            TicketID => $Param{SourceKey},
423            UserID   => $Param{UserID},
424        );
425
426        # add ticket history entry
427        $TicketObject->HistoryAdd(
428            TicketID     => $Param{Key},
429            CreateUserID => $Param{UserID},
430            HistoryType  => 'TicketLinkAdd',
431            Name         => "\%\%$TicketNumber\%\%$Param{SourceKey}\%\%$Param{Key}",
432        );
433
434        return 1;
435    }
436
437    if ( $Param{TargetObject} && $Param{TargetObject} eq 'Ticket' && $Param{TargetKey} ) {
438
439        # lookup ticket number
440        my $TicketNumber = $TicketObject->TicketNumberLookup(
441            TicketID => $Param{TargetKey},
442            UserID   => $Param{UserID},
443        );
444
445        # add ticket history entry
446        $TicketObject->HistoryAdd(
447            TicketID     => $Param{Key},
448            CreateUserID => $Param{UserID},
449            HistoryType  => 'TicketLinkAdd',
450            Name         => "\%\%$TicketNumber\%\%$Param{TargetKey}\%\%$Param{Key}",
451        );
452
453        return 1;
454    }
455
456    return 1;
457}
458
459=head2 LinkDeletePre()
460
461link delete pre event module
462
463    $True = $LinkObject->LinkDeletePre(
464        Key          => 123,
465        SourceObject => 'Ticket',
466        SourceKey    => 321,
467        Type         => 'Normal',
468        State        => 'Valid',
469        UserID       => 1,
470    );
471
472    or
473
474    $True = $LinkObject->LinkDeletePre(
475        Key          => 123,
476        TargetObject => 'Ticket',
477        TargetKey    => 321,
478        Type         => 'Normal',
479        State        => 'Valid',
480        UserID       => 1,
481    );
482
483=cut
484
485sub LinkDeletePre {
486    my ( $Self, %Param ) = @_;
487
488    # check needed stuff
489    for my $Argument (qw(Key Type State UserID)) {
490        if ( !$Param{$Argument} ) {
491            $Kernel::OM->Get('Kernel::System::Log')->Log(
492                Priority => 'error',
493                Message  => "Need $Argument!",
494            );
495            return;
496        }
497    }
498
499    return 1 if $Param{State} eq 'Temporary';
500
501    return 1;
502}
503
504=head2 LinkDeletePost()
505
506link delete post event module
507
508    $True = $LinkObject->LinkDeletePost(
509        Key          => 123,
510        SourceObject => 'Ticket',
511        SourceKey    => 321,
512        Type         => 'Normal',
513        State        => 'Valid',
514        UserID       => 1,
515    );
516
517    or
518
519    $True = $LinkObject->LinkDeletePost(
520        Key          => 123,
521        TargetObject => 'Ticket',
522        TargetKey    => 321,
523        Type         => 'Normal',
524        State        => 'Valid',
525        UserID       => 1,
526    );
527
528=cut
529
530sub LinkDeletePost {
531    my ( $Self, %Param ) = @_;
532
533    # check needed stuff
534    for my $Argument (qw(Key Type State UserID)) {
535        if ( !$Param{$Argument} ) {
536            $Kernel::OM->Get('Kernel::System::Log')->Log(
537                Priority => 'error',
538                Message  => "Need $Argument!",
539            );
540            return;
541        }
542    }
543
544    return 1 if $Param{State} eq 'Temporary';
545
546    # get ticket object
547    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
548
549    if ( $Param{SourceObject} && $Param{SourceObject} eq 'Ticket' && $Param{SourceKey} ) {
550
551        # lookup ticket number
552        my $TicketNumber = $TicketObject->TicketNumberLookup(
553            TicketID => $Param{SourceKey},
554            UserID   => $Param{UserID},
555        );
556
557        # add ticket history entry
558        $TicketObject->HistoryAdd(
559            TicketID     => $Param{Key},
560            CreateUserID => $Param{UserID},
561            HistoryType  => 'TicketLinkDelete',
562            Name         => "\%\%$TicketNumber\%\%$Param{SourceKey}\%\%$Param{Key}",
563        );
564
565        return 1;
566    }
567
568    if ( $Param{TargetObject} && $Param{TargetObject} eq 'Ticket' && $Param{TargetKey} ) {
569
570        # lookup ticket number
571        my $TicketNumber = $TicketObject->TicketNumberLookup(
572            TicketID => $Param{TargetKey},
573            UserID   => $Param{UserID},
574        );
575
576        # add ticket history entry
577        $TicketObject->HistoryAdd(
578            TicketID     => $Param{Key},
579            CreateUserID => $Param{UserID},
580            HistoryType  => 'TicketLinkDelete',
581            Name         => "\%\%$TicketNumber\%\%$Param{TargetKey}\%\%$Param{Key}",
582        );
583
584        return 1;
585    }
586
587    return 1;
588}
589
5901;
591
592=head1 TERMS AND CONDITIONS
593
594This software is part of the OTRS project (L<https://otrs.org/>).
595
596This software comes with ABSOLUTELY NO WARRANTY. For details, see
597the enclosed file COPYING for license information (GPL). If you
598did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>.
599
600=cut
601