X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=rt%2Flib%2FRT%2FQueue.pm;h=f8c0791a62e954252f07e56f2b8de842b7d36890;hb=7322f2afedcc2f427e997d1535a503613a83f088;hp=1656903b36dc9f1c0b226e110df2dcba3d0d41a3;hpb=c0567c688084e89fcd11bf82348b6c418f1254ac;p=freeside.git diff --git a/rt/lib/RT/Queue.pm b/rt/lib/RT/Queue.pm index 1656903b3..f8c0791a6 100755 --- a/rt/lib/RT/Queue.pm +++ b/rt/lib/RT/Queue.pm @@ -1,4 +1,50 @@ -# $Header: /home/cvs/cvsroot/freeside/rt/lib/RT/Queue.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $ +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2016 Best Practical Solutions, LLC +# +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} =head1 NAME @@ -10,935 +56,1169 @@ =head1 DESCRIPTION +An RT queue object. =head1 METHODS -=begin testing -use RT::TestHarness; +=cut + + +package RT::Queue; -use RT::Queue; +use strict; +use warnings; +use base 'RT::Record'; + +use Role::Basic 'with'; +with "RT::Record::Role::Lifecycle", + "RT::Record::Role::Links" => { -excludes => ["_AddLinksOnCreate"] }, + "RT::Record::Role::Roles", + "RT::Record::Role::Rights"; + +sub Table {'Queues'} + +sub LifecycleType { "ticket" } + +sub ModifyLinkRight { "AdminQueue" } + +require RT::ACE; +RT::ACE->RegisterCacheHandler(sub { + my %args = ( + Action => "", + RightName => "", + @_ + ); + + return unless $args{Action} =~ /^(Grant|Revoke)$/i + and $args{RightName} =~ /^(SeeQueue|CreateTicket)$/; + + RT->System->QueueCacheNeedsUpdate(1); +}); + +use RT::Groups; +use RT::ACL; +use RT::Interface::Email; + +__PACKAGE__->AddRight( General => SeeQueue => 'View queue' ); # loc +__PACKAGE__->AddRight( Admin => AdminQueue => 'Create, modify and delete queue' ); # loc +__PACKAGE__->AddRight( Admin => ShowACL => 'Display Access Control List' ); # loc +__PACKAGE__->AddRight( Admin => ModifyACL => 'Create, modify and delete Access Control List entries' ); # loc +__PACKAGE__->AddRight( Admin => ModifyQueueWatchers => 'Modify queue watchers' ); # loc +__PACKAGE__->AddRight( General => SeeCustomField => 'View custom field values' ); # loc +__PACKAGE__->AddRight( Staff => ModifyCustomField => 'Modify custom field values' ); # loc +__PACKAGE__->AddRight( Admin => AssignCustomFields => 'Assign and remove queue custom fields' ); # loc +__PACKAGE__->AddRight( Admin => ModifyTemplate => 'Modify Scrip templates' ); # loc +__PACKAGE__->AddRight( Admin => ShowTemplate => 'View Scrip templates' ); # loc + +__PACKAGE__->AddRight( Admin => ModifyScrips => 'Modify Scrips' ); # loc +__PACKAGE__->AddRight( Admin => ShowScrips => 'View Scrips' ); # loc + +__PACKAGE__->AddRight( General => ShowTicket => 'View ticket summaries' ); # loc +__PACKAGE__->AddRight( Staff => ShowTicketComments => 'View ticket private commentary' ); # loc +__PACKAGE__->AddRight( Staff => ShowOutgoingEmail => 'View exact outgoing email messages and their recipients' ); # loc + +__PACKAGE__->AddRight( General => Watch => 'Sign up as a ticket Requestor or ticket or queue Cc' ); # loc +__PACKAGE__->AddRight( Staff => WatchAsAdminCc => 'Sign up as a ticket or queue AdminCc' ); # loc +__PACKAGE__->AddRight( General => CreateTicket => 'Create tickets' ); # loc +__PACKAGE__->AddRight( General => ReplyToTicket => 'Reply to tickets' ); # loc +__PACKAGE__->AddRight( General => CommentOnTicket => 'Comment on tickets' ); # loc +__PACKAGE__->AddRight( Staff => OwnTicket => 'Own tickets' ); # loc +__PACKAGE__->AddRight( Staff => ModifyTicket => 'Modify tickets' ); # loc +__PACKAGE__->AddRight( Staff => DeleteTicket => 'Delete tickets' ); # loc +__PACKAGE__->AddRight( Staff => TakeTicket => 'Take tickets' ); # loc +__PACKAGE__->AddRight( Staff => StealTicket => 'Steal tickets' ); # loc +__PACKAGE__->AddRight( Staff => ReassignTicket => 'Modify ticket owner on owned tickets' ); # loc + +__PACKAGE__->AddRight( Staff => ForwardMessage => 'Forward messages outside of RT' ); # loc + +=head2 Create(ARGS) + +Arguments: ARGS is a hash of named parameters. Valid parameters are: + + Name (required) + Description + CorrespondAddress + CommentAddress + InitialPriority + FinalPriority + DefaultDueIn + +If you pass the ACL check, it creates the queue and returns its queue id. -=end testing =cut +sub Create { + my $self = shift; + my %args = ( + Name => undef, + Description => '', + CorrespondAddress => '', + CommentAddress => '', + Lifecycle => 'default', + SubjectTag => undef, + InitialPriority => 0, + FinalPriority => 0, + DefaultDueIn => 0, + Sign => undef, + SignAuto => undef, + Encrypt => undef, + _RecordTransaction => 1, + @_ + ); + + unless ( $self->CurrentUser->HasRight(Right => 'AdminQueue', Object => $RT::System) ) + { #Check them ACLs + return ( 0, $self->loc("No permission to create queues") ); + } + { + my ($val, $msg) = $self->_ValidateName( $args{'Name'} ); + return ($val, $msg) unless $val; + } -package RT::Queue; -use RT::Record; + $args{'Lifecycle'} ||= 'default'; + + return ( 0, $self->loc('[_1] is not a valid lifecycle', $args{'Lifecycle'} ) ) + unless $self->ValidateLifecycle( $args{'Lifecycle'} ); + + my %attrs = map {$_ => 1} $self->ReadableAttributes; -@ISA= qw(RT::Record); + #TODO better input validation + $RT::Handle->BeginTransaction(); + my $id = $self->SUPER::Create( map { $_ => $args{$_} } grep exists $args{$_}, keys %attrs ); + unless ($id) { + $RT::Handle->Rollback(); + return ( 0, $self->loc('Queue could not be created') ); + } -use vars (@STATUS); + my $create_ret = $self->_CreateRoleGroups(); + unless ($create_ret) { + $RT::Handle->Rollback(); + return ( 0, $self->loc('Queue could not be created') ); + } + if ( $args{'_RecordTransaction'} ) { + $self->_NewTransaction( Type => "Create" ); + } + $RT::Handle->Commit; + + for my $attr (qw/Sign SignAuto Encrypt/) { + next unless defined $args{$attr}; + my $set = "Set" . $attr; + my ($status, $msg) = $self->$set( $args{$attr} ); + $RT::Logger->error("Couldn't set attribute '$attr': $msg") + unless $status; + } -@STATUS = qw(new open stalled resolved dead); + RT->System->QueueCacheNeedsUpdate(1); + + return ( $id, $self->loc("Queue created") ); +} -=head2 StatusArray -Returns an array of all statuses for this queue + +sub Delete { + my $self = shift; + return ( 0, + $self->loc('Deleting this object would break referential integrity') ); +} + +=head2 Load + +Takes either a numerical id or a textual Name and loads the specified queue. =cut -sub StatusArray { +sub Load { my $self = shift; - return (@STATUS); + + my $identifier = shift; + if ( !$identifier ) { + return (undef); + } + + if ( $identifier =~ /^(\d+)$/ ) { + $self->SUPER::LoadById($identifier); + } + else { + $self->LoadByCols( Name => $identifier ); + } + + return ( $self->Id ); + } -=head2 IsValidStatus VALUE -Returns true if VALUE is a valid status. Otherwise, returns 0 +=head2 ValidateName NAME -=for testing -my $q = new RT::Queue($RT::SystemUser); -ok($q->IsValidStatus('new')== 1, 'New is a valid status'); -ok($q->IsValidStatus('f00')== 0, 'f00 is not a valid status'); +Takes a queue name. Returns true if it's an ok name for +a new queue. Returns undef if there's already a queue by that name. =cut -sub IsValidStatus { - my $self = shift; - my $value = shift; +sub ValidateName { + my $self = shift; + my $name = shift; - my $retval = grep (/^$value$/, $self->StatusArray); - return ($retval); + my ($ok, $msg) = $self->_ValidateName($name); + return $ok ? 1 : 0; } - +sub _ValidateName { + my $self = shift; + my $name = shift; + return (undef, "Queue name is required") unless length $name; -# {{{ sub _Init -sub _Init { - my $self = shift; - $self->{'table'} = "Queues"; - return ($self->SUPER::_Init(@_)); + # Validate via the superclass first + # Case: short circuit if it's an integer so we don't have + # fale negatives when loading a temp queue + unless ( my $q = $self->SUPER::ValidateName($name) ) { + return ($q, $self->loc("'[_1]' is not a valid name.", $name)); + } + + my $tempqueue = RT::Queue->new(RT->SystemUser); + $tempqueue->Load($name); + + #If this queue exists, return undef + if ( $tempqueue->Name() && $tempqueue->id != $self->id) { + return (undef, $self->loc("Queue already exists") ); + } + + return (1); } -# }}} -# {{{ sub _Accessible -sub _Accessible { - my $self = shift; - my %Cols = ( Name => 'read/write', - CorrespondAddress => 'read/write', - Description => 'read/write', - CommentAddress => 'read/write', - InitialPriority => 'read/write', - FinalPriority => 'read/write', - DefaultDueIn => 'read/write', - Creator => 'read/auto', - Created => 'read/auto', - LastUpdatedBy => 'read/auto', - LastUpdated => 'read/auto', - Disabled => 'read/write', - - ); - return($self->SUPER::_Accessible(@_, %Cols)); -} - -# }}} - -# {{{ sub Create - -=head2 Create - -Create takes the name of the new queue -If you pass the ACL check, it creates the queue and returns its queue id. +=head2 SetSign =cut -sub Create { +sub Sign { my $self = shift; - my %args = ( Name => undef, - CorrespondAddress => '', - Description => '', - CommentAddress => '', - InitialPriority => "0", - FinalPriority => "0", - DefaultDueIn => "0", - @_); - - unless ($self->CurrentUser->HasSystemRight('AdminQueue')) { #Check them ACLs - return (0, "No permission to create queues") - } + my $value = shift; - unless ($self->ValidateName($args{'Name'})) { - return(0, 'Queue already exists'); - } - #TODO better input validation - - my $id = $self->SUPER::Create(%args); - unless ($id) { - return (0, 'Queue could not be created'); - } + return undef unless $self->CurrentUserHasRight('SeeQueue'); + my $attr = $self->FirstAttribute('Sign') or return 0; + return $attr->Content; +} + +sub SetSign { + my $self = shift; + my $value = shift; - return ($id, "Queue $id created"); + return ( 0, $self->loc('Permission Denied') ) + unless $self->CurrentUserHasRight('AdminQueue'); + + my ($status, $msg) = $self->SetAttribute( + Name => 'Sign', + Description => 'Sign outgoing messages by default', + Content => $value, + ); + return ($status, $msg) unless $status; + + my ( undef, undef, $TransObj ) = $self->_NewTransaction( + Field => 'Signing', #loc + Type => $value ? "Enabled" : "Disabled" + ); + + return ($status, scalar $TransObj->BriefDescription); } -# }}} +sub SignAuto { + my $self = shift; + my $value = shift; -# {{{ sub Delete + return undef unless $self->CurrentUserHasRight('SeeQueue'); + my $attr = $self->FirstAttribute('SignAuto') or return 0; + return $attr->Content; +} -sub Delete { +sub SetSignAuto { my $self = shift; - return (0, 'Deleting this object would break referential integrity'); + my $value = shift; + + return ( 0, $self->loc('Permission Denied') ) + unless $self->CurrentUserHasRight('AdminQueue'); + + my ($status, $msg) = $self->SetAttribute( + Name => 'SignAuto', + Description => 'Sign auto-generated outgoing messages', + Content => $value, + ); + return ($status, $msg) unless $status; + + my ( undef, undef, $TransObj ) = $self->_NewTransaction( + Field => 'AutoSigning', #loc + Type => $value ? "Enabled" : "Disabled" + ); + + return ($status, scalar $TransObj->BriefDescription); } -# }}} +sub Encrypt { + my $self = shift; + my $value = shift; -# {{{ sub SetDisabled + return undef unless $self->CurrentUserHasRight('SeeQueue'); + my $attr = $self->FirstAttribute('Encrypt') or return 0; + return $attr->Content; +} -=head2 SetDisabled +sub SetEncrypt { + my $self = shift; + my $value = shift; -Takes a boolean. -1 will cause this queue to no longer be avaialble for tickets. -0 will re-enable this queue + return ( 0, $self->loc('Permission Denied') ) + unless $self->CurrentUserHasRight('AdminQueue'); -=cut + my ($status, $msg) = $self->SetAttribute( + Name => 'Encrypt', + Description => 'Encrypt outgoing messages by default', + Content => $value, + ); + return ($status, $msg) unless $status; -# }}} + my ( undef, undef, $TransObj ) = $self->_NewTransaction( + Field => 'Encrypting', #loc + Type => $value ? "Enabled" : "Disabled" + ); -# {{{ sub Load + return ($status, scalar $TransObj->BriefDescription); +} -=head2 Load +=head2 Templates + +Returns an RT::Templates object of all of this queue's templates. -Takes either a numerical id or a textual Name and loads the specified queue. - =cut -sub Load { +sub Templates { my $self = shift; - - my $identifier = shift; - if (!$identifier) { - return (undef); - } - - if ($identifier !~ /\D/) { - $self->SUPER::LoadById($identifier); - } - else { - $self->LoadByCol("Name", $identifier); - } - return ($self->Id); + my $templates = RT::Templates->new( $self->CurrentUser ); + if ( $self->CurrentUserHasRight('ShowTemplate') ) { + $templates->LimitToQueue( $self->id ); + } + return ($templates); } -# }}} -# {{{ sub ValidateName -=head2 ValidateName NAME -Takes a queue name. Returns true if it's an ok name for -a new queue. Returns undef if there's already a queue by that name. + +=head2 CustomField NAME + +Load the Ticket Custom Field applied to this Queue named NAME. +Does not load Global custom fields. =cut -sub ValidateName { +sub CustomField { my $self = shift; my $name = shift; - - my $tempqueue = new RT::Queue($RT::SystemUser); - $tempqueue->Load($name); + my $cf = RT::CustomField->new($self->CurrentUser); + $cf->LoadByName( + Name => $name, + LookupType => RT::Ticket->CustomFieldLookupType, + ObjectId => $self->id, + ); + return ($cf); +} - #If we couldn't load it :) - unless ($tempqueue->id()) { - return(1); - } - #If this queue exists, return undef - #Avoid the ACL check. - if ($tempqueue->Name()){ - return(undef); - } - #If the queue doesn't exist, return 1 - else { - return(1); +=head2 TicketCustomFields + +Returns an L object containing all global and +queue-specific B custom fields. + +=cut + +sub TicketCustomFields { + my $self = shift; + + my $cfs = RT::CustomFields->new( $self->CurrentUser ); + if ( $self->CurrentUserHasRight('SeeQueue') ) { + $cfs->SetContextObject( $self ); + $cfs->LimitToGlobalOrObjectId( $self->Id ); + $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket' ); + $cfs->ApplySortOrder; } + return ($cfs); +} + + + +=head2 TicketTransactionCustomFields + +Returns an L object containing all global and +queue-specific B custom fields. + +=cut +sub TicketTransactionCustomFields { + my $self = shift; + + my $cfs = RT::CustomFields->new( $self->CurrentUser ); + if ( $self->CurrentUserHasRight('SeeQueue') ) { + $cfs->SetContextObject( $self ); + $cfs->LimitToGlobalOrObjectId( $self->Id ); + $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket-RT::Transaction' ); + $cfs->ApplySortOrder; + } + return ($cfs); } -# }}} -# {{{ sub Templates -=head2 Templates -Returns an RT::Templates object of all of this queue's templates. +=head2 AllRoleGroupTypes + +B and will be removed in a future release. Use L +instead. + +Returns a list of the names of the various role group types for Queues, +including roles used only for ACLs like Requestor and Owner. If you don't want +them, see L. =cut -sub Templates { - my $self = shift; - +sub AllRoleGroupTypes { + RT->Deprecated( + Remove => "4.4", + Instead => "RT::Queue->Roles", + ); + shift->Roles; +} - my $templates = RT::Templates->new($self->CurrentUser); +=head2 IsRoleGroupType - if ($self->CurrentUserHasRight('ShowTemplate')) { - $templates->LimitToQueue($self->id); - } - - return ($templates); +B and will be removed in a future release. Use L instead. + +Returns whether the passed-in type is a role group type. + +=cut + +sub IsRoleGroupType { + RT->Deprecated( + Remove => "4.4", + Instead => "RT::Queue->HasRole", + ); + shift->HasRole(@_); } -# }}} +=head2 ManageableRoleGroupTypes -# {{{ Dealing with watchers +Returns a list of the names of the various role group types for Queues, +excluding ones used only for ACLs such as Requestor and Owner. If you want +them, see L. -# {{{ sub Watchers +=cut -=head2 Watchers +sub ManageableRoleGroupTypes { + shift->Roles( ACLOnly => 0 ) +} -Watchers returns a Watchers object preloaded with this queue\'s watchers. +=head2 IsManageableRoleGroupType + +Returns whether the passed-in type is a manageable role group type. =cut -sub Watchers { +sub IsManageableRoleGroupType { my $self = shift; - - require RT::Watchers; - my $watchers =RT::Watchers->new($self->CurrentUser); - - if ($self->CurrentUserHasRight('SeeQueue')) { - $watchers->LimitToQueue($self->id); - } - - return($watchers); + my $type = shift; + return( $self->HasRole($type) and not $self->Role($type)->{ACLOnly} ); +} + + +sub _HasModifyWatcherRight { + my $self = shift; + my ($type, $principal) = @_; + + # ModifyQueueWatchers works in any case + return 1 if $self->CurrentUserHasRight('ModifyQueueWatchers'); + # If the watcher isn't the current user then the current user has no right + return 0 unless $self->CurrentUser->PrincipalId == $principal->id; + # If it's an AdminCc and they don't have 'WatchAsAdminCc', bail + return 0 if $type eq 'AdminCc' and not $self->CurrentUserHasRight('WatchAsAdminCc'); + # If it's a Requestor or Cc and they don't have 'Watch', bail + return 0 if ($type eq "Cc" or $type eq 'Requestor') + and not $self->CurrentUserHasRight('Watch'); + return 1; } -# }}} -# {{{ sub WatchersAsString -=head2 WatchersAsString +=head2 AddWatcher + +Applies access control checking, then calls +L. Additionally, C is +accepted as an alternative argument name for C. -Returns a string of all queue watchers email addresses concatenated with ','s. +Returns a tuple of (status, message). =cut -sub WatchersAsString { - my $self=shift; - return($self->Watchers->EmailsAsString()); +sub AddWatcher { + my $self = shift; + my %args = ( + Type => undef, + PrincipalId => undef, + Email => undef, + @_ + ); + + $args{ACL} = sub { $self->_HasModifyWatcherRight( @_ ) }; + $args{User} ||= delete $args{Email}; + my ($principal, $msg) = $self->AddRoleMember( %args ); + return ( 0, $msg) unless $principal; + + return ( 1, $self->loc("Added [_1] to members of [_2] for this queue.", + $principal->Object->Name, $self->loc($args{'Type'}) )); } -# }}} -# {{{ sub AdminCcAsString +=head2 DeleteWatcher -=head2 AdminCcAsString +Applies access control checking, then calls +L. Additionally, C is +accepted as an alternative argument name for C. -Takes nothing. returns a string: All Ticket/Queue AdminCcs. +Returns a tuple of (status, message). =cut +sub DeleteWatcher { + my $self = shift; -sub AdminCcAsString { - my $self=shift; - - return($self->AdminCc->EmailsAsString()); - } + my %args = ( + Type => undef, + PrincipalId => undef, + Email => undef, + @_ + ); + + $args{ACL} = sub { $self->_HasModifyWatcherRight( @_ ) }; + $args{User} ||= delete $args{Email}; + my ($principal, $msg) = $self->DeleteRoleMember( %args ); + return ( 0, $msg) unless $principal; + + return ( 1, $self->loc("Removed [_1] from members of [_2] for this queue.", + $principal->Object->Name, $self->loc($args{'Type'}) )); +} -# }}} -# {{{ sub CcAsString -=head2 CcAsString +=head2 AdminCcAddresses -B String: All Queue Ccs as a comma delimited set of email addresses. +returns String: All queue AdminCc email addresses as a string =cut -sub CcAsString { - my $self=shift; +sub AdminCcAddresses { + my $self = shift; - return ($self->Cc->EmailsAsString()); -} + unless ( $self->CurrentUserHasRight('SeeQueue') ) { + return undef; + } + + return ( $self->AdminCc->MemberEmailAddressesAsString ) + +} -# }}} -# {{{ sub Cc -=head2 Cc +=head2 CcAddresses -Takes nothing. -Returns a watchers object which contains this queue\'s Cc watchers +returns String: All queue Ccs as a string of email addresses =cut -sub Cc { +sub CcAddresses { my $self = shift; - my $cc = $self->Watchers(); - if ($self->CurrentUserHasRight('SeeQueue')) { - $cc->LimitToCc(); + + unless ( $self->CurrentUserHasRight('SeeQueue') ) { + return undef; } - return ($cc); + + return ( $self->Cc->MemberEmailAddressesAsString); + } -# A helper function for Cc, so that we can call it from the ACL checks -# without going through acl checks. -sub _Cc { + +=head2 Cc + +Takes nothing. +Returns an RT::Group object which contains this Queue's Ccs. +If the user doesn't have "ShowQueue" permission, returns an empty group + +=cut + +sub Cc { my $self = shift; - my $cc = $self->Watchers(); - $cc->LimitToCc(); - return($cc); - + + return RT::Group->new($self->CurrentUser) + unless $self->CurrentUserHasRight('SeeQueue'); + return $self->RoleGroup( 'Cc' ); } -# }}} -# {{{ sub AdminCc =head2 AdminCc Takes nothing. -Returns this queue's administrative Ccs as an RT::Watchers object +Returns an RT::Group object which contains this Queue's AdminCcs. +If the user doesn't have "ShowQueue" permission, returns an empty group =cut sub AdminCc { my $self = shift; - my $admin_cc = $self->Watchers(); - if ($self->CurrentUserHasRight('SeeQueue')) { - $admin_cc->LimitToAdminCc(); - } - return($admin_cc); -} -#helper function for AdminCc so we can call it without ACLs -sub _AdminCc { - my $self = shift; - my $admin_cc = $self->Watchers(); - $admin_cc->LimitToAdminCc(); - return($admin_cc); + return RT::Group->new($self->CurrentUser) + unless $self->CurrentUserHasRight('SeeQueue'); + return $self->RoleGroup( 'AdminCc' ); } -# }}} - -# {{{ IsWatcher, IsCc, IsAdminCc -# {{{ sub IsWatcher # a generic routine to be called by IsRequestor, IsCc and IsAdminCc -=head2 IsWatcher +=head2 IsWatcher { Type => TYPE, PrincipalId => PRINCIPAL_ID } + +Takes a param hash with the attributes Type and PrincipalId + +Type is one of Requestor, Cc, AdminCc and Owner + +PrincipalId is an RT::Principal id + +Returns true if that principal is a member of the group Type for this queue -Takes a param hash with the attributes Type and User. User is either a user object or string containing an email address. Returns true if that user or string -is a queue watcher. Returns undef otherwise =cut sub IsWatcher { my $self = shift; - - my %args = ( Type => 'Requestor', - Id => undef, - Email => undef, - @_ - ); - #ACL check - can't do it. we need this method for ACL checks - # unless ($self->CurrentUserHasRight('SeeQueue')) { - # return(undef); - # } - - - my %cols = ('Type' => $args{'Type'}, - 'Scope' => 'Queue', - 'Value' => $self->Id - ); - if (defined ($args{'Id'})) { - if (ref($args{'Id'})){ #If it's a ref, assume it's an RT::User object; - #Dangerous but ok for now - $cols{'Owner'} = $args{'Id'}->Id; - } - elsif ($args{'Id'} =~ /^\d+$/) { # if it's an integer, it's an RT::User obj - $cols{'Owner'} = $args{'Id'}; - } - else { - $cols{'Email'} = $args{'Id'}; - } - } - - if (defined $args{'Email'}) { - $cols{'Email'} = $args{'Email'}; - } - my ($description); - $description = join(":",%cols); - - #If we've cached a positive match... - if (defined $self->{'watchers_cache'}->{"$description"}) { - if ($self->{'watchers_cache'}->{"$description"} == 1) { - return(1); - } - #If we've cached a negative match... - else { - return(undef); - } - } + my %args = ( Type => 'Cc', + PrincipalId => undef, + @_ + ); - require RT::Watcher; - my $watcher = new RT::Watcher($self->CurrentUser); - $watcher->LoadByCols(%cols); - - - if ($watcher->id) { - $self->{'watchers_cache'}->{"$description"} = 1; - return(1); - } - else { - $self->{'watchers_cache'}->{"$description"} = 0; - return(undef); + # Load the relevant group. + my $group = $self->RoleGroup( $args{'Type'} ); + # Ask if it has the member in question + + my $principal = RT::Principal->new($self->CurrentUser); + $principal->Load($args{'PrincipalId'}); + unless ($principal->Id) { + return (undef); } - + + return ($group->HasMemberRecursively($principal)); } -# }}} -# {{{ sub IsCc -=head2 IsCc -Takes a string. Returns true if the string is a Cc watcher of the current queue +=head2 IsCc PRINCIPAL_ID -=item Bugs +Takes an RT::Principal id. +Returns true if the principal is a requestor of the current queue. -Should also be able to handle an RT::User object =cut - sub IsCc { - my $self = shift; - my $cc = shift; - - return ($self->IsWatcher( Type => 'Cc', Id => $cc )); - -} + my $self = shift; + my $cc = shift; -# }}} + return ( $self->IsWatcher( Type => 'Cc', PrincipalId => $cc ) ); -# {{{ sub IsAdminCc +} -=head2 IsAdminCc -Takes a string. Returns true if the string is an AdminCc watcher of the current queue -=item Bugs +=head2 IsAdminCc PRINCIPAL_ID -Should also be able to handle an RT::User object +Takes an RT::Principal id. +Returns true if the principal is a requestor of the current queue. =cut sub IsAdminCc { - my $self = shift; - my $admincc = shift; - - return ($self->IsWatcher( Type => 'AdminCc', Id => $admincc )); - + my $self = shift; + my $person = shift; + + return ( $self->IsWatcher( Type => 'AdminCc', PrincipalId => $person ) ); + } -# }}} -# }}} -# {{{ sub AddWatcher -=head2 AddWatcher -Takes a paramhash of Email, Owner and Type. Type is one of 'Cc' or 'AdminCc', -We need either an Email Address in Email or a userid in Owner -=cut -sub AddWatcher { + + + +sub _Set { my $self = shift; - my %args = ( Email => undef, - Type => undef, - Owner => 0, - @_ - ); - - # {{{ Check ACLS - #If the watcher we're trying to add is for the current user - if ( ( ( defined $args{'Email'}) && - ( $args{'Email'} eq $self->CurrentUser->EmailAddress) ) or - ($args{'Owner'} eq $self->CurrentUser->Id)) { - - # If it's an AdminCc and they don't have - # 'WatchAsAdminCc' or 'ModifyQueueWatchers', bail - if ($args{'Type'} eq 'AdminCc') { - unless ($self->CurrentUserHasRight('ModifyQueueWatchers') or - $self->CurrentUserHasRight('WatchAsAdminCc')) { - return(0, 'Permission Denied'); - } - } - - # If it's a Requestor or Cc and they don't have - # 'Watch' or 'ModifyQueueWatchers', bail - elsif ($args{'Type'} eq 'Cc') { - unless ($self->CurrentUserHasRight('ModifyQueueWatchers') or - $self->CurrentUserHasRight('Watch')) { - return(0, 'Permission Denied'); - } - } - else { - $RT::Logger->warn("$self -> AddWatcher hit code". - " it never should. We got passed ". - " a type of ". $args{'Type'}); - return (0,'Error in parameters to $self AddWatcher'); - } + + my %args = ( + Field => undef, + Value => undef, + TransactionType => 'Set', + RecordTransaction => 1, + @_ + ); + + unless ( $self->CurrentUserHasRight('AdminQueue') ) { + return ( 0, $self->loc('Permission Denied') ); } - # If the watcher isn't the current user - # and the current user doesn't have 'ModifyQueueWatchers' - # bail - else { - unless ($self->CurrentUserHasRight('ModifyQueueWatchers')) { - return (0, "Permission Denied"); - } + + my $Old = $self->SUPER::_Value("$args{'Field'}"); + + my ($ret, $msg) = $self->SUPER::_Set( + Field => $args{'Field'}, + Value => $args{'Value'}, + ); + + if ( $ret == 0 ) { return ( 0, $msg ); } + + RT->System->QueueCacheNeedsUpdate(1); + + if ( $args{'RecordTransaction'} == 1 ) { + if ($args{'Field'} eq 'Disabled') { + $args{'TransactionType'} = ($args{'Value'} == 1) ? "Disabled" : "Enabled"; + delete $args{'Field'}; + } + my ( undef, undef, $TransObj ) = $self->_NewTransaction( + Type => $args{'TransactionType'}, + Field => $args{'Field'}, + NewValue => $args{'Value'}, + OldValue => $Old, + TimeTaken => $args{'TimeTaken'}, + ); } - # }}} - - require RT::Watcher; - my $Watcher = new RT::Watcher ($self->CurrentUser); - return ($Watcher->Create(Scope => 'Queue', - Value => $self->Id, - Email => $args{'Email'}, - Type => $args{'Type'}, - Owner => $args{'Owner'} - )); + + return ( $ret, $msg ); } -# }}} -# {{{ sub AddCc -=head2 AddCc +sub _Value { + my $self = shift; -Add a Cc to this queue. -Takes a paramhash of Email and Owner. -We need either an Email Address in Email or a userid in Owner + unless ( $self->CurrentUserHasRight('SeeQueue') ) { + return (undef); + } -=cut + return ( $self->__Value(@_) ); +} +=head2 CurrentUserCanSee -sub AddCc { +Returns true if the current user can see the queue, using SeeQueue + +=cut + +sub CurrentUserCanSee { my $self = shift; - return ($self->AddWatcher( Type => 'Cc', @_)); + + return $self->CurrentUserHasRight('SeeQueue'); } -# }}} -# {{{ sub AddAdminCc +=head2 id -=head2 AddAdminCc +Returns the current value of id. +(In the database, id is stored as int(11).) -Add an Administrative Cc to this queue. -Takes a paramhash of Email and Owner. -We need either an Email Address in Email or a userid in Owner =cut -sub AddAdminCc { - my $self = shift; - return ($self->AddWatcher( Type => 'AdminCc', @_)); -} -# }}} -# {{{ sub DeleteWatcher +=head2 Name + +Returns the current value of Name. +(In the database, Name is stored as varchar(200).) + + + +=head2 SetName VALUE -=head2 DeleteWatcher id [type] -DeleteWatcher takes a single argument which is either an email address -or a watcher id. -If the first argument is an email address, you need to specify the watcher type you're talking -about as the second argument. Valid values are 'Cc' or 'AdminCc'. -It removes that watcher from this Queue\'s list of watchers. +Set Name to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Name will be stored as a varchar(200).) =cut -sub DeleteWatcher { - my $self = shift; - my $id = shift; - - my $type; - - $type = shift if (@_); - +=head2 Description - require RT::Watcher; - my $Watcher = new RT::Watcher($self->CurrentUser); - - #If it\'s a numeric watcherid - if ($id =~ /^(\d*)$/) { - $Watcher->Load($id); - } - - #Otherwise, we'll assume it's an email address - elsif ($type) { - my ($result, $msg) = - $Watcher->LoadByValue( Email => $id, - Scope => 'Queue', - Value => $self->id, - Type => $type); - return (0,$msg) unless ($result); - } - - else { - return(0,"Can\'t delete a watcher by email address without specifying a type"); - } - - # {{{ Check ACLS - - #If the watcher we're trying to delete is for the current user - if ($Watcher->Email eq $self->CurrentUser->EmailAddress) { - - # If it's an AdminCc and they don't have - # 'WatchAsAdminCc' or 'ModifyQueueWatchers', bail - if ($Watcher->Type eq 'AdminCc') { - unless ($self->CurrentUserHasRight('ModifyQueueWatchers') or - $self->CurrentUserHasRight('WatchAsAdminCc')) { - return(0, 'Permission Denied'); - } - } - - # If it's a Cc and they don't have - # 'Watch' or 'ModifyQueueWatchers', bail - elsif ($Watcher->Type eq 'Cc') { - unless ($self->CurrentUserHasRight('ModifyQueueWatchers') or - $self->CurrentUserHasRight('Watch')) { - return(0, 'Permission Denied'); - } - } - else { - $RT::Logger->warn("$self -> DeleteWatcher hit code". - " it never should. We got passed ". - " a type of ". $args{'Type'}); - return (0,'Error in parameters to $self DeleteWatcher'); - } - } - # If the watcher isn't the current user - # and the current user doesn't have 'ModifyQueueWatchers' - # bail - else { - unless ($self->CurrentUserHasRight('ModifyQueueWatchers')) { - return (0, "Permission Denied"); - } - } +Returns the current value of Description. +(In the database, Description is stored as varchar(255).) - # }}} - - unless (($Watcher->Scope eq 'Queue') and - ($Watcher->Value == $self->id) ) { - return (0, "Not a watcher for this queue"); - } - - #Clear out the watchers hash. - $self->{'watchers'} = undef; - - my $retval = $Watcher->Delete(); - - unless ($retval) { - return(0,"Watcher could not be deleted."); - } - - return(1, "Watcher deleted"); -} -# {{{ sub DeleteCc +=head2 SetDescription VALUE -=head2 DeleteCc EMAIL -Takes an email address. It calls DeleteWatcher with a preset -type of 'Cc' +Set Description to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Description will be stored as a varchar(255).) =cut -sub DeleteCc { - my $self = shift; - my $id = shift; - return ($self->DeleteWatcher ($id, 'Cc')) -} -# }}} +=head2 CorrespondAddress + +Returns the current value of CorrespondAddress. +(In the database, CorrespondAddress is stored as varchar(120).) + -# {{{ sub DeleteAdminCc -=head2 DeleteAdminCc EMAIL +=head2 SetCorrespondAddress VALUE -Takes an email address. It calls DeleteWatcher with a preset -type of 'AdminCc' + +Set CorrespondAddress to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, CorrespondAddress will be stored as a varchar(120).) =cut -sub DeleteAdminCc { - my $self = shift; - my $id = shift; - return ($self->DeleteWatcher ($id, 'AdminCc')) -} -# }}} +=head2 CommentAddress +Returns the current value of CommentAddress. +(In the database, CommentAddress is stored as varchar(120).) -# }}} -# }}} -# {{{ Dealing with keyword selects +=head2 SetCommentAddress VALUE -# {{{ sub AddKeywordSelect -=head2 AddKeywordSelect +Set CommentAddress to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, CommentAddress will be stored as a varchar(120).) -Takes a paramhash of Name, Keyword, Depth and Single. Adds a new KeywordSelect for -this queue with those attributes. =cut -sub AddKeywordSelect { - my $self = shift; - my %args = ( Keyword => undef, - Depth => undef, - Single => undef, - Name => undef, - @_); - - #ACLS get handled in KeywordSelect - my $NewKeywordSelect = new RT::KeywordSelect($self->CurrentUser); - - return ($NewKeywordSelect->Create (Keyword => $args{'Keyword'}, - Depth => $args{'Depth'}, - Name => $args{'Name'}, - Single => $args{'Single'}, - ObjectType => 'Ticket', - ObjectField => 'Queue', - ObjectValue => $self->Id() - ) ); -} +=head2 Lifecycle + +Returns the current value of Lifecycle. +(In the database, Lifecycle is stored as varchar(32).) + -# }}} -# {{{ sub KeywordSelect +=head2 SetLifecycle VALUE -=head2 KeywordSelect([NAME]) -Takes the name of a keyword select for this queue or that's global. -Returns the relevant KeywordSelect object. Prefers a keywordselect that's -specific to this queue over a global one. If it can't find the proper -Keword select or the user doesn't have permission, returns an empty -KeywordSelect object +Set Lifecycle to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Lifecycle will be stored as a varchar(32).) + =cut -sub KeywordSelect { - my $self = shift; - my $name = shift; - - require RT::KeywordSelect; +=head2 SubjectTag + +Returns the current value of SubjectTag. +(In the database, SubjectTag is stored as varchar(120).) - my $select = RT::KeywordSelect->new($self->CurrentUser); - if ($self->CurrentUserHasRight('SeeQueue')) { - $select->LoadByName( Name => $name, Queue => $self->Id); - } - return ($select); -} -# }}} +=head2 SetSubjectTag VALUE -# {{{ sub KeywordSelects -=head2 KeywordSelects +Set SubjectTag to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, SubjectTag will be stored as a varchar(120).) -Returns an B object containing the collection of -B objects which apply to this queue. (Both queue specific keyword selects -and global keyword selects. =cut -sub KeywordSelects { - my $self = shift; +=head2 InitialPriority - use RT::KeywordSelects; - my $KeywordSelects = new RT::KeywordSelects($self->CurrentUser); +Returns the current value of InitialPriority. +(In the database, InitialPriority is stored as int(11).) - if ($self->CurrentUserHasRight('SeeQueue')) { - $KeywordSelects->LimitToQueue($self->id); - $KeywordSelects->IncludeGlobals(); - } - return ($KeywordSelects); -} -# }}} -# }}} -# {{{ ACCESS CONTROL +=head2 SetInitialPriority VALUE -# {{{ sub ACL -=head2 ACL +Set InitialPriority to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, InitialPriority will be stored as a int(11).) -#Returns an RT::ACL object of ACEs everyone who has anything to do with this queue. =cut -sub ACL { - my $self = shift; - - use RT::ACL; - my $acl = new RT::ACL($self->CurrentUser); - - if ($self->CurrentUserHasRight('ShowACL')) { - $acl->LimitToQueue($self->Id); - } - - return ($acl); -} -# }}} +=head2 FinalPriority -# {{{ sub _Set -sub _Set { - my $self = shift; +Returns the current value of FinalPriority. +(In the database, FinalPriority is stored as int(11).) - unless ($self->CurrentUserHasRight('AdminQueue')) { - return(0, 'Permission Denied'); - } - return ($self->SUPER::_Set(@_)); -} -# }}} -# {{{ sub _Value -sub _Value { - my $self = shift; +=head2 SetFinalPriority VALUE - unless ($self->CurrentUserHasRight('SeeQueue')) { - return (undef); - } - return ($self->__Value(@_)); -} +Set FinalPriority to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, FinalPriority will be stored as a int(11).) + + +=cut + + +=head2 DefaultDueIn + +Returns the current value of DefaultDueIn. +(In the database, DefaultDueIn is stored as int(11).) + -# }}} -# {{{ sub CurrentUserHasRight +=head2 SetDefaultDueIn VALUE -=head2 CurrentUserHasRight -Takes one argument. A textual string with the name of the right we want to check. -Returns true if the current user has that right for this queue. -Returns undef otherwise. +Set DefaultDueIn to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, DefaultDueIn will be stored as a int(11).) + =cut -sub CurrentUserHasRight { - my $self = shift; - my $right = shift; - return ($self->HasRight( Principal=> $self->CurrentUser, - Right => "$right")); +=head2 Creator + +Returns the current value of Creator. +(In the database, Creator is stored as int(11).) + + +=cut + + +=head2 Created + +Returns the current value of Created. +(In the database, Created is stored as datetime.) + + +=cut + + +=head2 LastUpdatedBy + +Returns the current value of LastUpdatedBy. +(In the database, LastUpdatedBy is stored as int(11).) + + +=cut + + +=head2 LastUpdated + +Returns the current value of LastUpdated. +(In the database, LastUpdated is stored as datetime.) + + +=cut + + +=head2 Disabled + +Returns the current value of Disabled. +(In the database, Disabled is stored as smallint(6).) -} -# }}} -# {{{ sub HasRight +=head2 SetDisabled VALUE -=head2 HasRight -Takes a param hash with the fields 'Right' and 'Principal'. -Principal defaults to the current user. -Returns true if the principal has that right for this queue. -Returns undef otherwise. +Set Disabled to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Disabled will be stored as a smallint(6).) + =cut -# TAKES: Right and optional "Principal" which defaults to the current user -sub HasRight { + + +sub _CoreAccessible { + { + + id => + {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + Name => + {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, + Description => + {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + CorrespondAddress => + {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''}, + CommentAddress => + {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''}, + SubjectTag => + {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''}, + Lifecycle => + {read => 1, write => 1, sql_type => 12, length => 32, is_blob => 0, is_numeric => 0, type => 'varchar(32)', default => 'default'}, + InitialPriority => + {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + FinalPriority => + {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + DefaultDueIn => + {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + Creator => + {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + Created => + {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + LastUpdatedBy => + {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + LastUpdated => + {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + Disabled => + {read => 1, write => 1, sql_type => 5, length => 6, is_blob => 0, is_numeric => 1, type => 'smallint(6)', default => '0'}, + + } +}; + +sub FindDependencies { my $self = shift; - my %args = ( Right => undef, - Principal => $self->CurrentUser, - @_); - unless(defined $args{'Principal'}) { - $RT::Logger->debug("Principal undefined in Queue::HasRight"); + my ($walker, $deps) = @_; + + $self->SUPER::FindDependencies($walker, $deps); + + # Queue role groups( Cc, AdminCc ) + my $objs = RT::Groups->new( $self->CurrentUser ); + $objs->Limit( FIELD => 'Domain', VALUE => 'RT::Queue-Role', CASESENSITIVE => 0 ); + $objs->Limit( FIELD => 'Instance', VALUE => $self->Id ); + $deps->Add( in => $objs ); + + # Scrips + $objs = RT::ObjectScrips->new( $self->CurrentUser ); + $objs->Limit( FIELD => 'ObjectId', + OPERATOR => '=', + VALUE => $self->id, + ENTRYAGGREGATOR => 'OR' ); + $objs->Limit( FIELD => 'ObjectId', + OPERATOR => '=', + VALUE => 0, + ENTRYAGGREGATOR => 'OR' ); + $deps->Add( in => $objs ); + + # Templates (global ones have already been dealt with) + $objs = RT::Templates->new( $self->CurrentUser ); + $objs->Limit( FIELD => 'Queue', VALUE => $self->Id); + $deps->Add( in => $objs ); + + # Custom Fields on things _in_ this queue (CFs on the queue itself + # have already been dealt with) + $objs = RT::ObjectCustomFields->new( $self->CurrentUser ); + $objs->Limit( FIELD => 'ObjectId', + OPERATOR => '=', + VALUE => $self->id, + ENTRYAGGREGATOR => 'OR' ); + $objs->Limit( FIELD => 'ObjectId', + OPERATOR => '=', + VALUE => 0, + ENTRYAGGREGATOR => 'OR' ); + my $cfs = $objs->Join( + ALIAS1 => 'main', + FIELD1 => 'CustomField', + TABLE2 => 'CustomFields', + FIELD2 => 'id', + ); + $objs->Limit( ALIAS => $cfs, + FIELD => 'LookupType', + OPERATOR => 'STARTSWITH', + VALUE => 'RT::Queue-' ); + $deps->Add( in => $objs ); + + # Tickets + $objs = RT::Tickets->new( $self->CurrentUser ); + $objs->Limit( FIELD => "Queue", VALUE => $self->Id ); + $objs->{allow_deleted_search} = 1; + $deps->Add( in => $objs ); +} - } - return($args{'Principal'}->HasQueueRight(QueueObj => $self, - Right => $args{'Right'})); +sub __DependsOn { + my $self = shift; + my %args = ( + Shredder => undef, + Dependencies => undef, + @_, + ); + my $deps = $args{'Dependencies'}; + my $list = []; + +# Tickets + my $objs = RT::Tickets->new( $self->CurrentUser ); + $objs->{'allow_deleted_search'} = 1; + $objs->Limit( FIELD => 'Queue', VALUE => $self->Id ); + push( @$list, $objs ); + +# Queue role groups( Cc, AdminCc ) + $objs = RT::Groups->new( $self->CurrentUser ); + $objs->Limit( FIELD => 'Domain', VALUE => 'RT::Queue-Role', CASESENSITIVE => 0 ); + $objs->Limit( FIELD => 'Instance', VALUE => $self->Id ); + push( @$list, $objs ); + +# Scrips + $objs = RT::Scrips->new( $self->CurrentUser ); + $objs->LimitToQueue( $self->id ); + push( @$list, $objs ); + +# Templates + $objs = $self->Templates; + push( @$list, $objs ); + +# Custom Fields + $objs = RT::CustomFields->new( $self->CurrentUser ); + $objs->SetContextObject( $self ); + $objs->LimitToQueue( $self->id ); + push( @$list, $objs ); + + $deps->_PushDependencies( + BaseObject => $self, + Flags => RT::Shredder::Constants::DEPENDS_ON, + TargetObjects => $list, + Shredder => $args{'Shredder'} + ); + return $self->SUPER::__DependsOn( %args ); +} + + +sub PreInflate { + my $class = shift; + my ($importer, $uid, $data) = @_; + + $class->SUPER::PreInflate( $importer, $uid, $data ); + + $data->{Name} = $importer->Qualify($data->{Name}) + if $data->{Name} ne "___Approvals"; + + return if $importer->MergeBy( "Name", $class, $uid, $data ); + + return 1; } -# }}} -# }}} + + +RT::Base->_ImportOverlays(); 1;