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