rt 4.2.13 ticket#13852
[freeside.git] / rt / lib / RT / Queue.pm
1 # BEGIN BPS TAGGED BLOCK {{{
2 #
3 # COPYRIGHT:
4 #
5 # This software is Copyright (c) 1996-2016 Best Practical Solutions, LLC
6 #                                          <sales@bestpractical.com>
7 #
8 # (Except where explicitly superseded by other copyright notices)
9 #
10 #
11 # LICENSE:
12 #
13 # This work is made available to you under the terms of Version 2 of
14 # the GNU General Public License. A copy of that license should have
15 # been provided with this software, but in any event can be snarfed
16 # from www.gnu.org.
17 #
18 # This work is distributed in the hope that it will be useful, but
19 # WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 # General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 # 02110-1301 or visit their web page on the internet at
27 # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
28 #
29 #
30 # CONTRIBUTION SUBMISSION POLICY:
31 #
32 # (The following paragraph is not intended to limit the rights granted
33 # to you to modify and distribute this software under the terms of
34 # the GNU General Public License and is only of importance to you if
35 # you choose to contribute your changes and enhancements to the
36 # community by submitting them to Best Practical Solutions, LLC.)
37 #
38 # By intentionally submitting any modifications, corrections or
39 # derivatives to this work, or any other work intended for use with
40 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
41 # you are the copyright holder for those contributions and you grant
42 # Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
43 # royalty-free, perpetual, license to use, copy, create derivative
44 # works based on those contributions, and sublicense and distribute
45 # those contributions and any derivatives thereof.
46 #
47 # END BPS TAGGED BLOCK }}}
48
49 =head1 NAME
50
51   RT::Queue - an RT Queue object
52
53 =head1 SYNOPSIS
54
55   use RT::Queue;
56
57 =head1 DESCRIPTION
58
59 An RT queue object.
60
61 =head1 METHODS
62
63 =cut
64
65
66 package RT::Queue;
67
68 use strict;
69 use warnings;
70 use base 'RT::Record';
71
72 use Role::Basic 'with';
73 with "RT::Record::Role::Lifecycle",
74      "RT::Record::Role::Links" => { -excludes => ["_AddLinksOnCreate"] },
75      "RT::Record::Role::Roles",
76      "RT::Record::Role::Rights";
77
78 sub Table {'Queues'}
79
80 sub LifecycleType { "ticket" }
81
82 sub ModifyLinkRight { "AdminQueue" }
83
84 require RT::ACE;
85 RT::ACE->RegisterCacheHandler(sub {
86     my %args = (
87         Action      => "",
88         RightName   => "",
89         @_
90     );
91
92     return unless $args{Action}    =~ /^(Grant|Revoke)$/i
93               and $args{RightName} =~ /^(SeeQueue|CreateTicket)$/;
94
95     RT->System->QueueCacheNeedsUpdate(1);
96 });
97
98 use RT::Groups;
99 use RT::ACL;
100 use RT::Interface::Email;
101
102 __PACKAGE__->AddRight( General => SeeQueue            => 'View queue' ); # loc
103 __PACKAGE__->AddRight( Admin   => AdminQueue          => 'Create, modify and delete queue' ); # loc
104 __PACKAGE__->AddRight( Admin   => ShowACL             => 'Display Access Control List' ); # loc
105 __PACKAGE__->AddRight( Admin   => ModifyACL           => 'Create, modify and delete Access Control List entries' ); # loc
106 __PACKAGE__->AddRight( Admin   => ModifyQueueWatchers => 'Modify queue watchers' ); # loc
107 __PACKAGE__->AddRight( General => SeeCustomField      => 'View custom field values' ); # loc
108 __PACKAGE__->AddRight( Staff   => ModifyCustomField   => 'Modify custom field values' ); # loc
109 __PACKAGE__->AddRight( Admin   => AssignCustomFields  => 'Assign and remove queue custom fields' ); # loc
110 __PACKAGE__->AddRight( Admin   => ModifyTemplate      => 'Modify Scrip templates' ); # loc
111 __PACKAGE__->AddRight( Admin   => ShowTemplate        => 'View Scrip templates' ); # loc
112
113 __PACKAGE__->AddRight( Admin   => ModifyScrips        => 'Modify Scrips' ); # loc
114 __PACKAGE__->AddRight( Admin   => ShowScrips          => 'View Scrips' ); # loc
115
116 __PACKAGE__->AddRight( General => ShowTicket          => 'View ticket summaries' ); # loc
117 __PACKAGE__->AddRight( Staff   => ShowTicketComments  => 'View ticket private commentary' ); # loc
118 __PACKAGE__->AddRight( Staff   => ShowOutgoingEmail   => 'View exact outgoing email messages and their recipients' ); # loc
119
120 __PACKAGE__->AddRight( General => Watch               => 'Sign up as a ticket Requestor or ticket or queue Cc' ); # loc
121 __PACKAGE__->AddRight( Staff   => WatchAsAdminCc      => 'Sign up as a ticket or queue AdminCc' ); # loc
122 __PACKAGE__->AddRight( General => CreateTicket        => 'Create tickets' ); # loc
123 __PACKAGE__->AddRight( General => ReplyToTicket       => 'Reply to tickets' ); # loc
124 __PACKAGE__->AddRight( General => CommentOnTicket     => 'Comment on tickets' ); # loc
125 __PACKAGE__->AddRight( Staff   => OwnTicket           => 'Own tickets' ); # loc
126 __PACKAGE__->AddRight( Staff   => ModifyTicket        => 'Modify tickets' ); # loc
127 __PACKAGE__->AddRight( Staff   => DeleteTicket        => 'Delete tickets' ); # loc
128 __PACKAGE__->AddRight( Staff   => TakeTicket          => 'Take tickets' ); # loc
129 __PACKAGE__->AddRight( Staff   => StealTicket         => 'Steal tickets' ); # loc
130 __PACKAGE__->AddRight( Staff   => ReassignTicket      => 'Modify ticket owner on owned tickets' ); # loc
131
132 __PACKAGE__->AddRight( Staff   => ForwardMessage      => 'Forward messages outside of RT' ); # loc
133
134 =head2 Create(ARGS)
135
136 Arguments: ARGS is a hash of named parameters.  Valid parameters are:
137
138   Name (required)
139   Description
140   CorrespondAddress
141   CommentAddress
142   InitialPriority
143   FinalPriority
144   DefaultDueIn
145  
146 If you pass the ACL check, it creates the queue and returns its queue id.
147
148
149 =cut
150
151 sub Create {
152     my $self = shift;
153     my %args = (
154         Name              => undef,
155         Description       => '',
156         CorrespondAddress => '',
157         CommentAddress    => '',
158         Lifecycle         => 'default',
159         SubjectTag        => undef,
160         InitialPriority   => 0,
161         FinalPriority     => 0,
162         DefaultDueIn      => 0,
163         Sign              => undef,
164         SignAuto          => undef,
165         Encrypt           => undef,
166         _RecordTransaction => 1,
167         @_
168     );
169
170     unless ( $self->CurrentUser->HasRight(Right => 'AdminQueue', Object => $RT::System) )
171     {    #Check them ACLs
172         return ( 0, $self->loc("No permission to create queues") );
173     }
174
175     {
176         my ($val, $msg) = $self->_ValidateName( $args{'Name'} );
177         return ($val, $msg) unless $val;
178     }
179
180     $args{'Lifecycle'} ||= 'default';
181
182     return ( 0, $self->loc('[_1] is not a valid lifecycle', $args{'Lifecycle'} ) )
183       unless $self->ValidateLifecycle( $args{'Lifecycle'} );
184
185     my %attrs = map {$_ => 1} $self->ReadableAttributes;
186
187     #TODO better input validation
188     $RT::Handle->BeginTransaction();
189     my $id = $self->SUPER::Create( map { $_ => $args{$_} } grep exists $args{$_}, keys %attrs );
190     unless ($id) {
191         $RT::Handle->Rollback();
192         return ( 0, $self->loc('Queue could not be created') );
193     }
194
195     my $create_ret = $self->_CreateRoleGroups();
196     unless ($create_ret) {
197         $RT::Handle->Rollback();
198         return ( 0, $self->loc('Queue could not be created') );
199     }
200     if ( $args{'_RecordTransaction'} ) {
201         $self->_NewTransaction( Type => "Create" );
202     }
203     $RT::Handle->Commit;
204
205     for my $attr (qw/Sign SignAuto Encrypt/) {
206         next unless defined $args{$attr};
207         my $set = "Set" . $attr;
208         my ($status, $msg) = $self->$set( $args{$attr} );
209         $RT::Logger->error("Couldn't set attribute '$attr': $msg")
210             unless $status;
211     }
212
213     RT->System->QueueCacheNeedsUpdate(1);
214
215     return ( $id, $self->loc("Queue created") );
216 }
217
218
219
220 sub Delete {
221     my $self = shift;
222     return ( 0,
223         $self->loc('Deleting this object would break referential integrity') );
224 }
225
226 =head2 Load
227
228 Takes either a numerical id or a textual Name and loads the specified queue.
229
230 =cut
231
232 sub Load {
233     my $self = shift;
234
235     my $identifier = shift;
236     if ( !$identifier ) {
237         return (undef);
238     }
239
240     if ( $identifier =~ /^(\d+)$/ ) {
241         $self->SUPER::LoadById($identifier);
242     }
243     else {
244         $self->LoadByCols( Name => $identifier );
245     }
246
247     return ( $self->Id );
248
249 }
250
251
252
253 =head2 ValidateName NAME
254
255 Takes a queue name. Returns true if it's an ok name for
256 a new queue. Returns undef if there's already a queue by that name.
257
258 =cut
259
260 sub ValidateName {
261     my $self = shift;
262     my $name = shift;
263
264     my ($ok, $msg) = $self->_ValidateName($name);
265
266     return $ok ? 1 : 0;
267 }
268
269 sub _ValidateName {
270     my $self = shift;
271     my $name = shift;
272
273     return (undef, "Queue name is required") unless length $name;
274
275     # Validate via the superclass first
276     # Case: short circuit if it's an integer so we don't have
277     # fale negatives when loading a temp queue
278     unless ( my $q = $self->SUPER::ValidateName($name) ) {
279         return ($q, $self->loc("'[_1]' is not a valid name.", $name));
280     }
281
282     my $tempqueue = RT::Queue->new(RT->SystemUser);
283     $tempqueue->Load($name);
284
285     #If this queue exists, return undef
286     if ( $tempqueue->Name() && $tempqueue->id != $self->id)  {
287         return (undef, $self->loc("Queue already exists") );
288     }
289
290     return (1);
291 }
292
293
294 =head2 SetSign
295
296 =cut
297
298 sub Sign {
299     my $self = shift;
300     my $value = shift;
301
302     return undef unless $self->CurrentUserHasRight('SeeQueue');
303     my $attr = $self->FirstAttribute('Sign') or return 0;
304     return $attr->Content;
305 }
306
307 sub SetSign {
308     my $self = shift;
309     my $value = shift;
310
311     return ( 0, $self->loc('Permission Denied') )
312         unless $self->CurrentUserHasRight('AdminQueue');
313
314     my ($status, $msg) = $self->SetAttribute(
315         Name        => 'Sign',
316         Description => 'Sign outgoing messages by default',
317         Content     => $value,
318     );
319     return ($status, $msg) unless $status;
320
321     my ( undef, undef, $TransObj ) = $self->_NewTransaction(
322         Field => 'Signing', #loc
323         Type  => $value ? "Enabled" : "Disabled"
324     );
325
326     return ($status, scalar $TransObj->BriefDescription);
327 }
328
329 sub SignAuto {
330     my $self = shift;
331     my $value = shift;
332
333     return undef unless $self->CurrentUserHasRight('SeeQueue');
334     my $attr = $self->FirstAttribute('SignAuto') or return 0;
335     return $attr->Content;
336 }
337
338 sub SetSignAuto {
339     my $self = shift;
340     my $value = shift;
341
342     return ( 0, $self->loc('Permission Denied') )
343         unless $self->CurrentUserHasRight('AdminQueue');
344
345     my ($status, $msg) = $self->SetAttribute(
346         Name        => 'SignAuto',
347         Description => 'Sign auto-generated outgoing messages',
348         Content     => $value,
349     );
350     return ($status, $msg) unless $status;
351
352     my ( undef, undef, $TransObj ) = $self->_NewTransaction(
353         Field => 'AutoSigning', #loc
354         Type  => $value ? "Enabled" : "Disabled"
355     );
356
357     return ($status, scalar $TransObj->BriefDescription);
358 }
359
360 sub Encrypt {
361     my $self = shift;
362     my $value = shift;
363
364     return undef unless $self->CurrentUserHasRight('SeeQueue');
365     my $attr = $self->FirstAttribute('Encrypt') or return 0;
366     return $attr->Content;
367 }
368
369 sub SetEncrypt {
370     my $self = shift;
371     my $value = shift;
372
373     return ( 0, $self->loc('Permission Denied') )
374         unless $self->CurrentUserHasRight('AdminQueue');
375
376     my ($status, $msg) = $self->SetAttribute(
377         Name        => 'Encrypt',
378         Description => 'Encrypt outgoing messages by default',
379         Content     => $value,
380     );
381     return ($status, $msg) unless $status;
382
383     my ( undef, undef, $TransObj ) = $self->_NewTransaction(
384         Field => 'Encrypting', #loc
385         Type  => $value ? "Enabled" : "Disabled"
386     );
387
388     return ($status, scalar $TransObj->BriefDescription);
389 }
390
391 =head2 Templates
392
393 Returns an RT::Templates object of all of this queue's templates.
394
395 =cut
396
397 sub Templates {
398     my $self = shift;
399
400     my $templates = RT::Templates->new( $self->CurrentUser );
401
402     if ( $self->CurrentUserHasRight('ShowTemplate') ) {
403         $templates->LimitToQueue( $self->id );
404     }
405
406     return ($templates);
407 }
408
409
410
411
412 =head2 CustomField NAME
413
414 Load the Ticket Custom Field applied to this Queue named NAME.
415 Does not load Global custom fields.
416
417 =cut
418
419 sub CustomField {
420     my $self = shift;
421     my $name = shift;
422     my $cf = RT::CustomField->new($self->CurrentUser);
423     $cf->LoadByName(
424         Name       => $name,
425         LookupType => RT::Ticket->CustomFieldLookupType,
426         ObjectId   => $self->id,
427     );
428     return ($cf);
429 }
430
431
432
433 =head2 TicketCustomFields
434
435 Returns an L<RT::CustomFields> object containing all global and
436 queue-specific B<ticket> custom fields.
437
438 =cut
439
440 sub TicketCustomFields {
441     my $self = shift;
442
443     my $cfs = RT::CustomFields->new( $self->CurrentUser );
444     if ( $self->CurrentUserHasRight('SeeQueue') ) {
445         $cfs->SetContextObject( $self );
446         $cfs->LimitToGlobalOrObjectId( $self->Id );
447         $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket' );
448         $cfs->ApplySortOrder;
449     }
450     return ($cfs);
451 }
452
453
454
455 =head2 TicketTransactionCustomFields
456
457 Returns an L<RT::CustomFields> object containing all global and
458 queue-specific B<transaction> custom fields.
459
460 =cut
461
462 sub TicketTransactionCustomFields {
463     my $self = shift;
464
465     my $cfs = RT::CustomFields->new( $self->CurrentUser );
466     if ( $self->CurrentUserHasRight('SeeQueue') ) {
467         $cfs->SetContextObject( $self );
468         $cfs->LimitToGlobalOrObjectId( $self->Id );
469         $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket-RT::Transaction' );
470         $cfs->ApplySortOrder;
471     }
472     return ($cfs);
473 }
474
475
476
477
478
479 =head2 AllRoleGroupTypes
480
481 B<DEPRECATED> and will be removed in a future release. Use L</Roles>
482 instead.
483
484 Returns a list of the names of the various role group types for Queues,
485 including roles used only for ACLs like Requestor and Owner. If you don't want
486 them, see L</ManageableRoleGroupTypes>.
487
488 =cut
489
490 sub AllRoleGroupTypes {
491     RT->Deprecated(
492         Remove => "4.4",
493         Instead => "RT::Queue->Roles",
494     );
495     shift->Roles;
496 }
497
498 =head2 IsRoleGroupType
499
500 B<DEPRECATED> and will be removed in a future release. Use L</HasRole> instead.
501
502 Returns whether the passed-in type is a role group type.
503
504 =cut
505
506 sub IsRoleGroupType {
507     RT->Deprecated(
508         Remove => "4.4",
509         Instead => "RT::Queue->HasRole",
510     );
511     shift->HasRole(@_);
512 }
513
514 =head2 ManageableRoleGroupTypes
515
516 Returns a list of the names of the various role group types for Queues,
517 excluding ones used only for ACLs such as Requestor and Owner. If you want
518 them, see L</Roles>.
519
520 =cut
521
522 sub ManageableRoleGroupTypes {
523     shift->Roles( ACLOnly => 0 )
524 }
525
526 =head2 IsManageableRoleGroupType
527
528 Returns whether the passed-in type is a manageable role group type.
529
530 =cut
531
532 sub IsManageableRoleGroupType {
533     my $self = shift;
534     my $type = shift;
535     return( $self->HasRole($type) and not $self->Role($type)->{ACLOnly} );
536 }
537
538
539 sub _HasModifyWatcherRight {
540     my $self = shift;
541     my ($type, $principal) = @_;
542
543     # ModifyQueueWatchers works in any case
544     return 1 if $self->CurrentUserHasRight('ModifyQueueWatchers');
545     # If the watcher isn't the current user then the current user has no right
546     return 0 unless $self->CurrentUser->PrincipalId == $principal->id;
547     # If it's an AdminCc and they don't have 'WatchAsAdminCc', bail
548     return 0 if $type eq 'AdminCc' and not $self->CurrentUserHasRight('WatchAsAdminCc');
549     # If it's a Requestor or Cc and they don't have 'Watch', bail
550     return 0 if ($type eq "Cc" or $type eq 'Requestor')
551         and not $self->CurrentUserHasRight('Watch');
552     return 1;
553 }
554
555
556 =head2 AddWatcher
557
558 Applies access control checking, then calls
559 L<RT::Record::Role::Roles/AddRoleMember>.  Additionally, C<Email> is
560 accepted as an alternative argument name for C<User>.
561
562 Returns a tuple of (status, message).
563
564 =cut
565
566 sub AddWatcher {
567     my $self = shift;
568     my %args = (
569         Type  => undef,
570         PrincipalId => undef,
571         Email => undef,
572         @_
573     );
574
575     $args{ACL} = sub { $self->_HasModifyWatcherRight( @_ ) };
576     $args{User} ||= delete $args{Email};
577     my ($principal, $msg) = $self->AddRoleMember( %args );
578     return ( 0, $msg) unless $principal;
579
580     return ( 1, $self->loc("Added [_1] to members of [_2] for this queue.",
581                            $principal->Object->Name, $self->loc($args{'Type'}) ));
582 }
583
584
585 =head2 DeleteWatcher
586
587 Applies access control checking, then calls
588 L<RT::Record::Role::Roles/DeleteRoleMember>.  Additionally, C<Email> is
589 accepted as an alternative argument name for C<User>.
590
591 Returns a tuple of (status, message).
592
593 =cut
594
595 sub DeleteWatcher {
596     my $self = shift;
597
598     my %args = (
599         Type => undef,
600         PrincipalId => undef,
601         Email => undef,
602         @_
603     );
604
605     $args{ACL} = sub { $self->_HasModifyWatcherRight( @_ ) };
606     $args{User} ||= delete $args{Email};
607     my ($principal, $msg) = $self->DeleteRoleMember( %args );
608     return ( 0, $msg) unless $principal;
609
610     return ( 1, $self->loc("Removed [_1] from members of [_2] for this queue.",
611                            $principal->Object->Name, $self->loc($args{'Type'}) ));
612 }
613
614
615
616 =head2 AdminCcAddresses
617
618 returns String: All queue AdminCc email addresses as a string
619
620 =cut
621
622 sub AdminCcAddresses {
623     my $self = shift;
624     
625     unless ( $self->CurrentUserHasRight('SeeQueue') ) {
626         return undef;
627     }   
628     
629     return ( $self->AdminCc->MemberEmailAddressesAsString )
630     
631 }   
632
633
634
635 =head2 CcAddresses
636
637 returns String: All queue Ccs as a string of email addresses
638
639 =cut
640
641 sub CcAddresses {
642     my $self = shift;
643
644     unless ( $self->CurrentUserHasRight('SeeQueue') ) {
645         return undef;
646     }
647
648     return ( $self->Cc->MemberEmailAddressesAsString);
649
650 }
651
652
653
654 =head2 Cc
655
656 Takes nothing.
657 Returns an RT::Group object which contains this Queue's Ccs.
658 If the user doesn't have "ShowQueue" permission, returns an empty group
659
660 =cut
661
662 sub Cc {
663     my $self = shift;
664
665     return RT::Group->new($self->CurrentUser)
666         unless $self->CurrentUserHasRight('SeeQueue');
667     return $self->RoleGroup( 'Cc' );
668 }
669
670
671
672 =head2 AdminCc
673
674 Takes nothing.
675 Returns an RT::Group object which contains this Queue's AdminCcs.
676 If the user doesn't have "ShowQueue" permission, returns an empty group
677
678 =cut
679
680 sub AdminCc {
681     my $self = shift;
682
683     return RT::Group->new($self->CurrentUser)
684         unless $self->CurrentUserHasRight('SeeQueue');
685     return $self->RoleGroup( 'AdminCc' );
686 }
687
688
689
690 # a generic routine to be called by IsRequestor, IsCc and IsAdminCc
691
692 =head2 IsWatcher { Type => TYPE, PrincipalId => PRINCIPAL_ID }
693
694 Takes a param hash with the attributes Type and PrincipalId
695
696 Type is one of Requestor, Cc, AdminCc and Owner
697
698 PrincipalId is an RT::Principal id 
699
700 Returns true if that principal is a member of the group Type for this queue
701
702
703 =cut
704
705 sub IsWatcher {
706     my $self = shift;
707
708     my %args = ( Type  => 'Cc',
709         PrincipalId    => undef,
710         @_
711     );
712
713     # Load the relevant group.
714     my $group = $self->RoleGroup( $args{'Type'} );
715     # Ask if it has the member in question
716
717     my $principal = RT::Principal->new($self->CurrentUser);
718     $principal->Load($args{'PrincipalId'});
719     unless ($principal->Id) {
720         return (undef);
721     }
722
723     return ($group->HasMemberRecursively($principal));
724 }
725
726
727
728
729 =head2 IsCc PRINCIPAL_ID
730
731 Takes an RT::Principal id.
732 Returns true if the principal is a requestor of the current queue.
733
734
735 =cut
736
737 sub IsCc {
738     my $self = shift;
739     my $cc   = shift;
740
741     return ( $self->IsWatcher( Type => 'Cc', PrincipalId => $cc ) );
742
743 }
744
745
746
747 =head2 IsAdminCc PRINCIPAL_ID
748
749 Takes an RT::Principal id.
750 Returns true if the principal is a requestor of the current queue.
751
752 =cut
753
754 sub IsAdminCc {
755     my $self   = shift;
756     my $person = shift;
757
758     return ( $self->IsWatcher( Type => 'AdminCc', PrincipalId => $person ) );
759
760 }
761
762
763
764
765
766
767
768
769
770
771 sub _Set {
772     my $self = shift;
773
774     my %args = (
775         Field             => undef,
776         Value             => undef,
777         TransactionType   => 'Set',
778         RecordTransaction => 1,
779         @_
780     );
781
782     unless ( $self->CurrentUserHasRight('AdminQueue') ) {
783         return ( 0, $self->loc('Permission Denied') );
784     }
785
786     my $Old = $self->SUPER::_Value("$args{'Field'}");
787
788     my ($ret, $msg) = $self->SUPER::_Set(
789         Field => $args{'Field'},
790         Value => $args{'Value'},
791     );
792
793     if ( $ret == 0 ) { return ( 0, $msg ); }
794
795     RT->System->QueueCacheNeedsUpdate(1);
796
797     if ( $args{'RecordTransaction'} == 1 ) {
798         if ($args{'Field'} eq 'Disabled') {
799             $args{'TransactionType'} = ($args{'Value'} == 1) ? "Disabled" : "Enabled";
800             delete $args{'Field'};
801         }
802         my ( undef, undef, $TransObj ) = $self->_NewTransaction(
803             Type      => $args{'TransactionType'},
804             Field     => $args{'Field'},
805             NewValue  => $args{'Value'},
806             OldValue  => $Old,
807             TimeTaken => $args{'TimeTaken'},
808         );
809     }
810
811     return ( $ret, $msg );
812 }
813
814
815
816 sub _Value {
817     my $self = shift;
818
819     unless ( $self->CurrentUserHasRight('SeeQueue') ) {
820         return (undef);
821     }
822
823     return ( $self->__Value(@_) );
824 }
825
826 =head2 CurrentUserCanSee
827
828 Returns true if the current user can see the queue, using SeeQueue
829
830 =cut
831
832 sub CurrentUserCanSee {
833     my $self = shift;
834
835     return $self->CurrentUserHasRight('SeeQueue');
836 }
837
838 =head2 id
839
840 Returns the current value of id. 
841 (In the database, id is stored as int(11).)
842
843
844 =cut
845
846
847 =head2 Name
848
849 Returns the current value of Name. 
850 (In the database, Name is stored as varchar(200).)
851
852
853
854 =head2 SetName VALUE
855
856
857 Set Name to VALUE. 
858 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
859 (In the database, Name will be stored as a varchar(200).)
860
861
862 =cut
863
864
865 =head2 Description
866
867 Returns the current value of Description. 
868 (In the database, Description is stored as varchar(255).)
869
870
871
872 =head2 SetDescription VALUE
873
874
875 Set Description to VALUE. 
876 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
877 (In the database, Description will be stored as a varchar(255).)
878
879
880 =cut
881
882
883 =head2 CorrespondAddress
884
885 Returns the current value of CorrespondAddress. 
886 (In the database, CorrespondAddress is stored as varchar(120).)
887
888
889
890 =head2 SetCorrespondAddress VALUE
891
892
893 Set CorrespondAddress to VALUE. 
894 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
895 (In the database, CorrespondAddress will be stored as a varchar(120).)
896
897
898 =cut
899
900
901 =head2 CommentAddress
902
903 Returns the current value of CommentAddress. 
904 (In the database, CommentAddress is stored as varchar(120).)
905
906
907
908 =head2 SetCommentAddress VALUE
909
910
911 Set CommentAddress to VALUE. 
912 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
913 (In the database, CommentAddress will be stored as a varchar(120).)
914
915
916 =cut
917
918
919 =head2 Lifecycle
920
921 Returns the current value of Lifecycle. 
922 (In the database, Lifecycle is stored as varchar(32).)
923
924
925
926 =head2 SetLifecycle VALUE
927
928
929 Set Lifecycle to VALUE. 
930 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
931 (In the database, Lifecycle will be stored as a varchar(32).)
932
933
934 =cut
935
936 =head2 SubjectTag
937
938 Returns the current value of SubjectTag. 
939 (In the database, SubjectTag is stored as varchar(120).)
940
941
942
943 =head2 SetSubjectTag VALUE
944
945
946 Set SubjectTag to VALUE. 
947 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
948 (In the database, SubjectTag will be stored as a varchar(120).)
949
950
951 =cut
952
953
954 =head2 InitialPriority
955
956 Returns the current value of InitialPriority. 
957 (In the database, InitialPriority is stored as int(11).)
958
959
960
961 =head2 SetInitialPriority VALUE
962
963
964 Set InitialPriority to VALUE. 
965 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
966 (In the database, InitialPriority will be stored as a int(11).)
967
968
969 =cut
970
971
972 =head2 FinalPriority
973
974 Returns the current value of FinalPriority. 
975 (In the database, FinalPriority is stored as int(11).)
976
977
978
979 =head2 SetFinalPriority VALUE
980
981
982 Set FinalPriority to VALUE. 
983 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
984 (In the database, FinalPriority will be stored as a int(11).)
985
986
987 =cut
988
989
990 =head2 DefaultDueIn
991
992 Returns the current value of DefaultDueIn. 
993 (In the database, DefaultDueIn is stored as int(11).)
994
995
996
997 =head2 SetDefaultDueIn VALUE
998
999
1000 Set DefaultDueIn to VALUE. 
1001 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
1002 (In the database, DefaultDueIn will be stored as a int(11).)
1003
1004
1005 =cut
1006
1007
1008 =head2 Creator
1009
1010 Returns the current value of Creator. 
1011 (In the database, Creator is stored as int(11).)
1012
1013
1014 =cut
1015
1016
1017 =head2 Created
1018
1019 Returns the current value of Created. 
1020 (In the database, Created is stored as datetime.)
1021
1022
1023 =cut
1024
1025
1026 =head2 LastUpdatedBy
1027
1028 Returns the current value of LastUpdatedBy. 
1029 (In the database, LastUpdatedBy is stored as int(11).)
1030
1031
1032 =cut
1033
1034
1035 =head2 LastUpdated
1036
1037 Returns the current value of LastUpdated. 
1038 (In the database, LastUpdated is stored as datetime.)
1039
1040
1041 =cut
1042
1043
1044 =head2 Disabled
1045
1046 Returns the current value of Disabled. 
1047 (In the database, Disabled is stored as smallint(6).)
1048
1049
1050
1051 =head2 SetDisabled VALUE
1052
1053
1054 Set Disabled to VALUE. 
1055 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
1056 (In the database, Disabled will be stored as a smallint(6).)
1057
1058
1059 =cut
1060
1061
1062
1063 sub _CoreAccessible {
1064     {
1065      
1066         id =>
1067         {read => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
1068         Name => 
1069         {read => 1, write => 1, sql_type => 12, length => 200,  is_blob => 0,  is_numeric => 0,  type => 'varchar(200)', default => ''},
1070         Description => 
1071         {read => 1, write => 1, sql_type => 12, length => 255,  is_blob => 0,  is_numeric => 0,  type => 'varchar(255)', default => ''},
1072         CorrespondAddress => 
1073         {read => 1, write => 1, sql_type => 12, length => 120,  is_blob => 0,  is_numeric => 0,  type => 'varchar(120)', default => ''},
1074         CommentAddress => 
1075         {read => 1, write => 1, sql_type => 12, length => 120,  is_blob => 0,  is_numeric => 0,  type => 'varchar(120)', default => ''},
1076         SubjectTag => 
1077         {read => 1, write => 1, sql_type => 12, length => 120,  is_blob => 0,  is_numeric => 0,  type => 'varchar(120)', default => ''},
1078         Lifecycle => 
1079         {read => 1, write => 1, sql_type => 12, length => 32,  is_blob => 0, is_numeric => 0,  type => 'varchar(32)', default => 'default'},
1080         InitialPriority => 
1081         {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
1082         FinalPriority => 
1083         {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
1084         DefaultDueIn => 
1085         {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
1086         Creator => 
1087         {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
1088         Created => 
1089         {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
1090         LastUpdatedBy => 
1091         {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
1092         LastUpdated => 
1093         {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
1094         Disabled => 
1095         {read => 1, write => 1, sql_type => 5, length => 6,  is_blob => 0,  is_numeric => 1,  type => 'smallint(6)', default => '0'},
1096
1097  }
1098 };
1099
1100 sub FindDependencies {
1101     my $self = shift;
1102     my ($walker, $deps) = @_;
1103
1104     $self->SUPER::FindDependencies($walker, $deps);
1105
1106     # Queue role groups( Cc, AdminCc )
1107     my $objs = RT::Groups->new( $self->CurrentUser );
1108     $objs->Limit( FIELD => 'Domain', VALUE => 'RT::Queue-Role', CASESENSITIVE => 0 );
1109     $objs->Limit( FIELD => 'Instance', VALUE => $self->Id );
1110     $deps->Add( in => $objs );
1111
1112     # Scrips
1113     $objs = RT::ObjectScrips->new( $self->CurrentUser );
1114     $objs->Limit( FIELD           => 'ObjectId',
1115                   OPERATOR        => '=',
1116                   VALUE           => $self->id,
1117                   ENTRYAGGREGATOR => 'OR' );
1118     $objs->Limit( FIELD           => 'ObjectId',
1119                   OPERATOR        => '=',
1120                   VALUE           => 0,
1121                   ENTRYAGGREGATOR => 'OR' );
1122     $deps->Add( in => $objs );
1123
1124     # Templates (global ones have already been dealt with)
1125     $objs = RT::Templates->new( $self->CurrentUser );
1126     $objs->Limit( FIELD => 'Queue', VALUE => $self->Id);
1127     $deps->Add( in => $objs );
1128
1129     # Custom Fields on things _in_ this queue (CFs on the queue itself
1130     # have already been dealt with)
1131     $objs = RT::ObjectCustomFields->new( $self->CurrentUser );
1132     $objs->Limit( FIELD           => 'ObjectId',
1133                   OPERATOR        => '=',
1134                   VALUE           => $self->id,
1135                   ENTRYAGGREGATOR => 'OR' );
1136     $objs->Limit( FIELD           => 'ObjectId',
1137                   OPERATOR        => '=',
1138                   VALUE           => 0,
1139                   ENTRYAGGREGATOR => 'OR' );
1140     my $cfs = $objs->Join(
1141         ALIAS1 => 'main',
1142         FIELD1 => 'CustomField',
1143         TABLE2 => 'CustomFields',
1144         FIELD2 => 'id',
1145     );
1146     $objs->Limit( ALIAS    => $cfs,
1147                   FIELD    => 'LookupType',
1148                   OPERATOR => 'STARTSWITH',
1149                   VALUE    => 'RT::Queue-' );
1150     $deps->Add( in => $objs );
1151
1152     # Tickets
1153     $objs = RT::Tickets->new( $self->CurrentUser );
1154     $objs->Limit( FIELD => "Queue", VALUE => $self->Id );
1155     $objs->{allow_deleted_search} = 1;
1156     $deps->Add( in => $objs );
1157 }
1158
1159 sub __DependsOn {
1160     my $self = shift;
1161     my %args = (
1162         Shredder => undef,
1163         Dependencies => undef,
1164         @_,
1165     );
1166     my $deps = $args{'Dependencies'};
1167     my $list = [];
1168
1169 # Tickets
1170     my $objs = RT::Tickets->new( $self->CurrentUser );
1171     $objs->{'allow_deleted_search'} = 1;
1172     $objs->Limit( FIELD => 'Queue', VALUE => $self->Id );
1173     push( @$list, $objs );
1174
1175 # Queue role groups( Cc, AdminCc )
1176     $objs = RT::Groups->new( $self->CurrentUser );
1177     $objs->Limit( FIELD => 'Domain', VALUE => 'RT::Queue-Role', CASESENSITIVE => 0 );
1178     $objs->Limit( FIELD => 'Instance', VALUE => $self->Id );
1179     push( @$list, $objs );
1180
1181 # Scrips
1182     $objs = RT::Scrips->new( $self->CurrentUser );
1183     $objs->LimitToQueue( $self->id );
1184     push( @$list, $objs );
1185
1186 # Templates
1187     $objs = $self->Templates;
1188     push( @$list, $objs );
1189
1190 # Custom Fields
1191     $objs = RT::CustomFields->new( $self->CurrentUser );
1192     $objs->SetContextObject( $self );
1193     $objs->LimitToQueue( $self->id );
1194     push( @$list, $objs );
1195
1196     $deps->_PushDependencies(
1197         BaseObject => $self,
1198         Flags => RT::Shredder::Constants::DEPENDS_ON,
1199         TargetObjects => $list,
1200         Shredder => $args{'Shredder'}
1201     );
1202     return $self->SUPER::__DependsOn( %args );
1203 }
1204
1205
1206 sub PreInflate {
1207     my $class = shift;
1208     my ($importer, $uid, $data) = @_;
1209
1210     $class->SUPER::PreInflate( $importer, $uid, $data );
1211
1212     $data->{Name} = $importer->Qualify($data->{Name})
1213         if $data->{Name} ne "___Approvals";
1214
1215     return if $importer->MergeBy( "Name", $class, $uid, $data );
1216
1217     return 1;
1218 }
1219
1220
1221
1222 RT::Base->_ImportOverlays();
1223
1224 1;