import rt 3.6.10
[freeside.git] / rt / lib / RT / Queue_Overlay.pm
index 0d50a74..7d93852 100644 (file)
@@ -1,8 +1,8 @@
-# {{{ BEGIN BPS TAGGED BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
 # 
 # COPYRIGHT:
 #  
-# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC 
+# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC 
 #                                          <jesse@bestpractical.com>
 # 
 # (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
 # 
 # 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# 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:
@@ -42,7 +44,7 @@
 # works based on those contributions, and sublicense and distribute
 # those contributions and any derivatives thereof.
 # 
-# }}} END BPS TAGGED BLOCK
+# END BPS TAGGED BLOCK }}}
 =head1 NAME
 
   RT::Queue - an RT Queue object
@@ -64,18 +66,20 @@ use RT::Queue;
 
 =cut
 
+
+package RT::Queue;
+
 use strict;
 no warnings qw(redefine);
 
-use vars qw(@STATUS @ACTIVE_STATUS @INACTIVE_STATUS $RIGHTS);
+use vars qw(@DEFAULT_ACTIVE_STATUS @DEFAULT_INACTIVE_STATUS $RIGHTS);
+
 use RT::Groups;
 use RT::ACL;
-use RT::EmailParser;
+use RT::Interface::Email;
 
-
-@ACTIVE_STATUS = qw(new open stalled);
-@INACTIVE_STATUS = qw(resolved rejected deleted);
-@STATUS = (@ACTIVE_STATUS, @INACTIVE_STATUS);
+@DEFAULT_ACTIVE_STATUS = qw(new open stalled);
+@DEFAULT_INACTIVE_STATUS = qw(resolved rejected deleted);  
 
 # $self->loc('new'); # For the string extractor to get a string to localize
 # $self->loc('open'); # For the string extractor to get a string to localize
@@ -91,7 +95,7 @@ $RIGHTS = {
     ShowACL             => 'Display Access Control List',             # loc_pair
     ModifyACL           => 'Modify Access Control List',              # loc_pair
     ModifyQueueWatchers => 'Modify the queue watchers',               # loc_pair
-    AdminCustomFields   => 'Create, delete and modify custom fields', # loc_pair
+    AssignCustomFields  => 'Assign and remove custom fields',         # loc_pair
     ModifyTemplate      => 'Modify Scrip templates for this queue',   # loc_pair
     ShowTemplate        => 'Display Scrip templates for this queue',  # loc_pair
 
@@ -180,7 +184,12 @@ Returns an array of all ActiveStatuses for this queue
 
 sub ActiveStatusArray {
     my $self = shift;
-    return (@ACTIVE_STATUS);
+    if (@RT::ActiveStatus) {
+       return (@RT::ActiveStatus)
+    } else {
+        $RT::Logger->warning("RT::ActiveStatus undefined, falling back to deprecated defaults");
+        return (@DEFAULT_ACTIVE_STATUS);
+    }
 }
 
 # }}}
@@ -195,7 +204,12 @@ Returns an array of all InactiveStatuses for this queue
 
 sub InactiveStatusArray {
     my $self = shift;
-    return (@INACTIVE_STATUS);
+    if (@RT::InactiveStatus) {
+       return (@RT::InactiveStatus)
+    } else {
+        $RT::Logger->warning("RT::InactiveStatus undefined, falling back to deprecated defaults");
+        return (@DEFAULT_INACTIVE_STATUS);
+    }
 }
 
 # }}}
@@ -210,7 +224,7 @@ Returns an array of all statuses for this queue
 
 sub StatusArray {
     my $self = shift;
-    return (@STATUS);
+    return ($self->ActiveStatusArray(), $self->InactiveStatusArray());
 }
 
 # }}}
@@ -219,20 +233,23 @@ sub StatusArray {
 
 =head2 IsValidStatus VALUE
 
-Returns true if VALUE is a valid status.  Otherwise, returns 0
+Returns true if VALUE is a valid status.  Otherwise, returns 0.
+
+=begin testing
 
-=for testing
 my $q = RT::Queue->new($RT::SystemUser);
 ok($q->IsValidStatus('new')== 1, 'New is a valid status');
 ok($q->IsValidStatus('f00')== 0, 'f00 is not a valid status');
 
+=end testing
+
 =cut
 
 sub IsValidStatus {
     my $self  = shift;
     my $value = shift;
 
-    my $retval = grep ( /^$value$/, $self->StatusArray );
+    my $retval = grep ( $_ eq $value, $self->StatusArray );
     return ($retval);
 
 }
@@ -245,19 +262,22 @@ sub IsValidStatus {
 
 Returns true if VALUE is a Active status.  Otherwise, returns 0
 
-=for testing
+=begin testing
+
 my $q = RT::Queue->new($RT::SystemUser);
 ok($q->IsActiveStatus('new')== 1, 'New is a Active status');
 ok($q->IsActiveStatus('rejected')== 0, 'Rejected is an inactive status');
 ok($q->IsActiveStatus('f00')== 0, 'f00 is not a Active status');
 
+=end testing
+
 =cut
 
 sub IsActiveStatus {
     my $self  = shift;
     my $value = shift;
 
-    my $retval = grep ( /^$value$/, $self->ActiveStatusArray );
+    my $retval = grep ( $_ eq $value, $self->ActiveStatusArray );
     return ($retval);
 
 }
@@ -270,19 +290,22 @@ sub IsActiveStatus {
 
 Returns true if VALUE is a Inactive status.  Otherwise, returns 0
 
-=for testing
+=begin testing
+
 my $q = RT::Queue->new($RT::SystemUser);
 ok($q->IsInactiveStatus('new')== 0, 'New is a Active status');
 ok($q->IsInactiveStatus('rejected')== 1, 'rejeected is an Inactive status');
 ok($q->IsInactiveStatus('f00')== 0, 'f00 is not a Active status');
 
+=end testing
+
 =cut
 
 sub IsInactiveStatus {
     my $self  = shift;
     my $value = shift;
 
-    my $retval = grep ( /^$value$/, $self->InactiveStatusArray );
+    my $retval = grep ( $_ eq $value, $self->InactiveStatusArray );
     return ($retval);
 
 }
@@ -292,11 +315,34 @@ sub IsInactiveStatus {
 
 # {{{ sub Create
 
-=head2 Create
 
-Create takes the name of the new queue 
+
+
+=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.
 
+=begin testing
+
+my $queue = RT::Queue->new($RT::SystemUser);
+my ($id, $val) = $queue->Create( Name => 'Test1');
+ok($id, $val);
+
+($id, $val) = $queue->Create( Name => '66');
+ok(!$id, $val);
+
+=end testing
+
 =cut
 
 sub Create {
@@ -357,8 +403,8 @@ sub Delete {
 =head2 SetDisabled
 
 Takes a boolean.
-1 will cause this queue to no longer be avaialble for tickets.
-0 will re-enable this queue
+1 will cause this queue to no longer be available for tickets.
+0 will re-enable this queue.
 
 =cut
 
@@ -409,20 +455,14 @@ sub ValidateName {
     my $tempqueue = new RT::Queue($RT::SystemUser);
     $tempqueue->Load($name);
 
-    #If we couldn't load it :)
-    unless ( $tempqueue->id() ) {
-        return (1);
-    }
-
     #If this queue exists, return undef
-    #Avoid the ACL check.
-    if ( $tempqueue->Name() ) {
+    if ( $tempqueue->Name() && $tempqueue->id != $self->id)  {
         return (undef);
     }
 
     #If the queue doesn't exist, return 1
     else {
-        return (1);
+        return ($self->SUPER::ValidateName($name));
     }
 
 }
@@ -455,7 +495,7 @@ sub Templates {
 
 # {{{  CustomField
 
-=item CustomField NAME
+=head2 CustomField NAME
 
 Load the queue-specific custom field named NAME
 
@@ -472,18 +512,38 @@ sub CustomField {
 
 # {{{ CustomFields
 
-=item CustomFields
+=head2 CustomFields
 
 Returns an RT::CustomFields object containing all global custom fields, as well as those tied to this queue
 
 =cut
 
+# XXX TODO - this should become TicketCustomFields
+
 sub CustomFields {
     my $self = shift;
+    warn "Queue->CustomFields is deprecated, use Queue->TicketCustomFields instead at (". join(":",caller).")";
+    return $self->TicketCustomFields(@_);
+}
+
+sub TicketCustomFields {
+    my $self = shift;
+
+    my $cfs = RT::CustomFields->new( $self->CurrentUser );
+    if ( $self->CurrentUserHasRight('SeeQueue') ) {
+       $cfs->LimitToGlobalOrObjectId( $self->Id );
+       $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket' );
+    }
+    return ($cfs);
+}
+
+sub TicketTransactionCustomFields {
+    my $self = shift;
 
     my $cfs = RT::CustomFields->new( $self->CurrentUser );
     if ( $self->CurrentUserHasRight('SeeQueue') ) {
-        $cfs->LimitToGlobalOrQueue( $self->Id );
+       $cfs->LimitToGlobalOrObjectId( $self->Id );
+       $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket-RT::Transaction' );
     }
     return ($cfs);
 }
@@ -588,45 +648,41 @@ sub AddWatcher {
         @_
     );
 
+    return ( 0, "No principal specified" )
+        unless $args{'Email'} or $args{'PrincipalId'};
+
+    if ( !$args{'PrincipalId'} && $args{'Email'} ) {
+        my $user = RT::User->new( $self->CurrentUser );
+        $user->LoadByEmail( $args{'Email'} );
+        $args{'PrincipalId'} = $user->PrincipalId if $user->id;
+    }
+
     # {{{ Check ACLS
+    return ( $self->_AddWatcher(%args) )
+        if $self->CurrentUserHasRight('ModifyQueueWatchers');
+
     #If the watcher we're trying to add is for the current user
-    if ( $self->CurrentUser->PrincipalId  eq $args{'PrincipalId'}) {
+    if ( $self->CurrentUser->PrincipalId == ($args{'PrincipalId'}||0) ) {
         #  If it's an AdminCc and they don't have 
         #   'WatchAsAdminCc' or 'ModifyTicket', bail
         if ( $args{'Type'} eq 'AdminCc' ) {
-            unless ( $self->CurrentUserHasRight('ModifyQueueWatchers')
-                or $self->CurrentUserHasRight('WatchAsAdminCc') ) {
-                return ( 0, $self->loc('Permission Denied'))
-            }
+            return ( $self->_AddWatcher(%args) )
+                if $self->CurrentUserHasRight('WatchAsAdminCc');
         }
 
         #  If it's a Requestor or Cc and they don't have
         #   'Watch' or 'ModifyTicket', bail
-        elsif ( ( $args{'Type'} eq 'Cc' ) or ( $args{'Type'} eq 'Requestor' ) ) {
-
-            unless ( $self->CurrentUserHasRight('ModifyQueueWatchers')
-                or $self->CurrentUserHasRight('Watch') ) {
-                return ( 0, $self->loc('Permission Denied'))
-            }
+        elsif ( $args{'Type'} eq 'Cc' or $args{'Type'} eq 'Requestor' ) {
+            return ( $self->_AddWatcher(%args) )
+                if $self->CurrentUserHasRight('Watch');
         }
-     else {
-            $RT::Logger->warn( "$self -> AddWatcher got passed a bogus type");
+        else {
+            $RT::Logger->warning( "$self -> AddWatcher got passed a bogus type");
             return ( 0, $self->loc('Error in parameters to Queue->AddWatcher') );
         }
     }
 
-    # If the watcher isn't the current user 
-    # and the current user  doesn't have 'ModifyQueueWatcher'
-    # bail
-    else {
-        unless ( $self->CurrentUserHasRight('ModifyQueueWatchers') ) {
-            return ( 0, $self->loc("Permission Denied") );
-        }
-    }
-
-    # }}}
-
-    return ( $self->_AddWatcher(%args) );
+    return ( 0, $self->loc("Permission Denied") );
 }
 
 #This contains the meat of AddWatcher. but can be called from a routine like
@@ -642,48 +698,45 @@ sub _AddWatcher {
     );
 
 
-    my $principal = RT::Principal->new($self->CurrentUser);
-    if ($args{'PrincipalId'}) {
-        $principal->Load($args{'PrincipalId'});
+    my $principal = RT::Principal->new( $self->CurrentUser );
+    if ( $args{'PrincipalId'} ) {
+        $principal->Load( $args{'PrincipalId'} );
     }
-    elsif ($args{'Email'}) {
-
+    elsif ( $args{'Email'} ) {
         my $user = RT::User->new($self->CurrentUser);
-        $user->LoadByEmail($args{'Email'});
+        $user->LoadByEmail( $args{'Email'} );
+        $user->Load( $args{'Email'} )
+            unless $user->id;
 
-        unless ($user->Id) {
-            $user->Load($args{'Email'});
-        }
-        if ($user->Id) { # If the user exists
-            $principal->Load($user->PrincipalId);
+        if ( $user->Id ) { # If the user exists
+            $principal->Load( $user->PrincipalId );
         } else {
-
-        # if the user doesn't exist, we need to create a new user
-             my $new_user = RT::User->new($RT::SystemUser);
+            # if the user doesn't exist, we need to create a new user
+            my $new_user = RT::User->new($RT::SystemUser);
 
             my ( $Address, $Name ) =  
-               RT::EmailParser::ParseAddressFromHeader('', $args{'Email'});
+               RT::Interface::Email::ParseAddressFromHeader($args{'Email'});
 
             my ( $Val, $Message ) = $new_user->Create(
-                Name => $Address,
+                Name         => $Address,
                 EmailAddress => $Address,
                 RealName     => $Name,
                 Privileged   => 0,
-                Comments     => 'Autocreated when added as a watcher');
+                Comments     => 'Autocreated when added as a watcher'
+            );
             unless ($Val) {
                 $RT::Logger->error("Failed to create user ".$args{'Email'} .": " .$Message);
                 # Deal with the race condition of two account creations at once
-                $new_user->LoadByEmail($args{'Email'});
+                $new_user->LoadByEmail( $args{'Email'} );
             }
-            $principal->Load($new_user->PrincipalId);
+            $principal->Load( $new_user->PrincipalId );
         }
     }
     # If we can't find this watcher, we need to bail.
-    unless ($principal->Id) {
+    unless ( $principal->Id ) {
         return(0, $self->loc("Could not find or create that user"));
     }
 
-
     my $group = RT::Group->new($self->CurrentUser);
     $group->LoadQueueRoleGroup(Type => $args{'Type'}, Queue => $self->Id);
     unless ($group->id) {
@@ -731,11 +784,18 @@ sub DeleteWatcher {
 
     my %args = ( Type => undef,
                  PrincipalId => undef,
+                 Email => undef,
                  @_ );
 
-    unless ($args{'PrincipalId'} ) {
-        return(0, $self->loc("No principal specified"));
+    return ( 0, "No principal specified" )
+        unless $args{Email} or $args{PrincipalId};
+
+    if ( !$args{PrincipalId} and $args{Email} ) {
+        my $user = RT::User->new( $self->CurrentUser );
+        my ($rv, $msg) = $user->LoadByEmail( $args{Email} );
+        $args{PrincipalId} = $user->PrincipalId if $rv;
     }
+
     my $principal = RT::Principal->new($self->CurrentUser);
     $principal->Load($args{'PrincipalId'});
 
@@ -750,13 +810,15 @@ sub DeleteWatcher {
         return(0,$self->loc("Group not found"));
     }
 
+    my $can_modify_queue = $self->CurrentUserHasRight('ModifyQueueWatchers');
+
     # {{{ Check ACLS
     #If the watcher we're trying to add is for the current user
     if ( $self->CurrentUser->PrincipalId  eq $args{'PrincipalId'}) {
         #  If it's an AdminCc and they don't have 
         #   'WatchAsAdminCc' or 'ModifyQueue', bail
-  if ( $args{'Type'} eq 'AdminCc' ) {
-            unless ( $self->CurrentUserHasRight('ModifyQueueWatchers')
+        if ( $args{'Type'} eq 'AdminCc' ) {
+            unless ( $can_modify_queue
                 or $self->CurrentUserHasRight('WatchAsAdminCc') ) {
                 return ( 0, $self->loc('Permission Denied'))
             }
@@ -765,13 +827,13 @@ sub DeleteWatcher {
         #  If it's a Requestor or Cc and they don't have
         #   'Watch' or 'ModifyQueue', bail
         elsif ( ( $args{'Type'} eq 'Cc' ) or ( $args{'Type'} eq 'Requestor' ) ) {
-            unless ( $self->CurrentUserHasRight('ModifyQueueWatchers')
+            unless ( $can_modify_queue
                 or $self->CurrentUserHasRight('Watch') ) {
                 return ( 0, $self->loc('Permission Denied'))
             }
         }
         else {
-            $RT::Logger->warn( "$self -> DeleteWatcher got passed a bogus type");
+            $RT::Logger->warning( "$self -> DeleteWatcher got passed a bogus type");
             return ( 0, $self->loc('Error in parameters to Queue->DeleteWatcher') );
         }
     }
@@ -779,7 +841,7 @@ sub DeleteWatcher {
     # If the watcher isn't the current user 
     # and the current user  doesn't have 'ModifyQueueWathcers' bail
     else {
-        unless ( $self->CurrentUserHasRight('ModifyQueueWatchers') ) {
+        unless ( $can_modify_queue ) {
             return ( 0, $self->loc("Permission Denied") );
         }
     }
@@ -942,8 +1004,8 @@ sub IsWatcher {
 
 =head2 IsCc PRINCIPAL_ID
 
-  Takes an RT::Principal id.
-  Returns true if the principal is a requestor of the current queue.
+Takes an RT::Principal id.
+Returns true if the principal is a requestor of the current queue.
 
 
 =cut
@@ -962,8 +1024,8 @@ sub IsCc {
 
 =head2 IsAdminCc PRINCIPAL_ID
 
-  Takes an RT::Principal id.
-  Returns true if the principal is a requestor of the current queue.
+Takes an RT::Principal id.
+Returns true if the principal is a requestor of the current queue.
 
 =cut
 
@@ -1064,7 +1126,7 @@ sub HasRight {
     }
     return (
         $args{'Principal'}->HasRight(
-            Object => $self,
+            Object => $self->Id ? $self : $RT::System,
             Right    => $args{'Right'}
           )
     );