summaryrefslogtreecommitdiff
path: root/rt/lib/RT/Action
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2012-06-30 01:03:13 -0700
committerIvan Kohler <ivan@freeside.biz>2012-06-30 01:03:13 -0700
commitf3c4966ed1f6ec3db7accd6dcdd3a5a3821d72a7 (patch)
treee5e9a077260613e6117d4697dd2985abd9b03d34 /rt/lib/RT/Action
parentcf7cd8efc7095aadbdfb0cd8e7ea0e2e8b9e9085 (diff)
parentcd3eb95ed1f3dc3e04cfc2b3b405f75b3ab086da (diff)
merging RT 4.0.6
Diffstat (limited to 'rt/lib/RT/Action')
-rw-r--r--rt/lib/RT/Action/AutoOpen.pm57
-rwxr-xr-xrt/lib/RT/Action/Autoreply.pm8
-rw-r--r--rt/lib/RT/Action/CreateTickets.pm64
-rw-r--r--rt/lib/RT/Action/EscalatePriority.pm9
-rw-r--r--rt/lib/RT/Action/ExtractSubjectTag.pm8
-rwxr-xr-xrt/lib/RT/Action/Generic.pm73
-rwxr-xr-xrt/lib/RT/Action/LinearEscalate.pm2
-rwxr-xr-xrt/lib/RT/Action/Notify.pm29
-rwxr-xr-xrt/lib/RT/Action/NotifyAsComment.pm2
-rw-r--r--rt/lib/RT/Action/NotifyGroup.pm2
-rw-r--r--rt/lib/RT/Action/NotifyGroupAsComment.pm2
-rw-r--r--rt/lib/RT/Action/RecordComment.pm2
-rw-r--r--rt/lib/RT/Action/RecordCorrespondence.pm2
-rw-r--r--rt/lib/RT/Action/ResolveMembers.pm108
-rwxr-xr-xrt/lib/RT/Action/SendEmail.pm166
-rw-r--r--rt/lib/RT/Action/SetPriority.pm6
-rw-r--r--rt/lib/RT/Action/SetStatus.pm152
-rw-r--r--rt/lib/RT/Action/UserDefined.pm2
18 files changed, 370 insertions, 324 deletions
diff --git a/rt/lib/RT/Action/AutoOpen.pm b/rt/lib/RT/Action/AutoOpen.pm
index b99b21474..5f96e0649 100644
--- a/rt/lib/RT/Action/AutoOpen.pm
+++ b/rt/lib/RT/Action/AutoOpen.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -51,49 +51,64 @@ package RT::Action::AutoOpen;
use strict;
use warnings;
-
use base qw(RT::Action);
=head1 DESCRIPTION
-Opens a ticket unless it's allready open, but only unless transaction
-L<RT::Transaction/IsInbound is inbound>.
+This action automatically moves a ticket to an active status.
+
+Status is not changed if there is no active statuses in the lifecycle.
+
+Status is not changed if the current status is first active for ticket's status
+lifecycle. For example if ticket's status is 'processing' and active statuses are
+'processing', 'on hold' and 'waiting' then status is not changed, but for ticket
+with status 'on hold' other rules are checked.
+
+Status is not changed if it's in the list of C<initial> statuses for the
+current scheme and creator of the current transaction
+is one of the ticket's requestors.
-Doesn't open a ticket if message's head has field C<RT-Control> with
-C<no-autoopen> substring.
+Status is not changed if message's head has field C<RT-Control> with C<no-autoopen>
+substring.
+
+Status is set to the first possible active status. If the ticket's
+status is C<Stalled> then RT finds all possible transitions from C<Stalled>
+status and selects first one that results in the ticket having an
+active status.
=cut
sub Prepare {
my $self = shift;
- # if the ticket is already open or the ticket is new and the message is more mail from the
- # requestor, don't reopen it.
+ my $ticket = $self->TicketObj;
+ my $next = $ticket->FirstActiveStatus;
+ return 1 unless defined $next;
- my $status = $self->TicketObj->Status;
- return undef if $status eq 'open';
- return undef if $status eq 'new' && $self->TransactionObj->IsInbound;
+ # no change if the ticket is in initial status and the message is a mail
+ # from a requestor
+ return 1 if $ticket->QueueObj->Lifecycle->IsInitial($ticket->Status)
+ && $self->TransactionObj->IsInbound;
if ( my $msg = $self->TransactionObj->Message->First ) {
- return undef if ($msg->GetHeader('RT-Control') || '') =~ /\bno-autoopen\b/i;
+ return 1 if ($msg->GetHeader('RT-Control') || '') =~ /\bno-autoopen\b/i;
}
+ $self->{'set_status_to'} = $next;
+
return 1;
}
sub Commit {
my $self = shift;
- my $oldstatus = $self->TicketObj->Status;
- $self->TicketObj->__Set( Field => 'Status', Value => 'open' );
- $self->TicketObj->_NewTransaction(
- Type => 'Status',
- Field => 'Status',
- OldValue => $oldstatus,
- NewValue => 'open',
- Data => 'Ticket auto-opened on incoming correspondence'
- );
+ return 1 unless my $new_status = $self->{'set_status_to'};
+ my ($val, $msg) = $self->TicketObj->SetStatus( $new_status );
+ unless ( $val ) {
+ $RT::Logger->error( "Couldn't auto-open ticket: ". $msg );
+ return 0;
+ }
return 1;
}
diff --git a/rt/lib/RT/Action/Autoreply.pm b/rt/lib/RT/Action/Autoreply.pm
index e3e792ea7..cde874e45 100755
--- a/rt/lib/RT/Action/Autoreply.pm
+++ b/rt/lib/RT/Action/Autoreply.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -66,7 +66,6 @@ sub Prepare {
$self->SUPER::Prepare();
}
-# {{{ sub SetRecipients
=head2 SetRecipients
@@ -83,10 +82,8 @@ sub SetRecipients {
return(1);
}
-# }}}
-# {{{ sub SetReturnAddress
=head2 SetReturnAddress
@@ -108,9 +105,7 @@ sub SetReturnAddress {
}
-# }}}
-# {{{{ sub SetRTSpecialHeaders
=head2 SetRTSpecialHeaders
@@ -125,7 +120,6 @@ sub SetRTSpecialHeaders {
$self->SetHeader( 'Auto-Submitted', 'auto-replied' );
}
-# }}}
RT::Base->_ImportOverlays();
diff --git a/rt/lib/RT/Action/CreateTickets.pm b/rt/lib/RT/Action/CreateTickets.pm
index fd3e77c3a..31489c8ff 100644
--- a/rt/lib/RT/Action/CreateTickets.pm
+++ b/rt/lib/RT/Action/CreateTickets.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -130,14 +130,14 @@ A convoluted example
# of which the creator of this ticket is a member
my $name = "HR";
- my $groups = RT::Groups->new($RT::SystemUser);
+ my $groups = RT::Groups->new(RT->SystemUser);
$groups->LimitToUserDefinedGroups();
$groups->Limit(FIELD => "Name", OPERATOR => "=", VALUE => "$name");
$groups->WithMember($TransactionObj->CreatorObj->Id);
my $groupid = $groups->First->Id;
- my $adminccs = RT::Users->new($RT::SystemUser);
+ my $adminccs = RT::Users->new(RT->SystemUser);
$adminccs->WhoHaveRight(
Right => "AdminGroup",
Object =>$groups->First,
@@ -196,6 +196,9 @@ A complete list of acceptable fields for this beastie:
+ Requestor => Email address
+ Cc => Email address
+ AdminCc => Email address
+ + RequestorGroup => Group name
+ + CcGroup => Group name
+ + AdminCcGroup => Group name
TimeWorked =>
TimeEstimated =>
TimeLeft =>
@@ -230,7 +233,7 @@ by repeating the fieldname on a new line with an additional value.
Fields marked with a ! are postponed to be processed after all
tickets in the same actions are created. Except for 'Status', those
field can also take a ticket name within the same action (i.e.
-the identifiers after ==Create-Ticket), instead of raw Ticket ID
+the identifiers after ===Create-Ticket), instead of raw Ticket ID
numbers.
When parsed, field names are converted to lowercase and have -s stripped.
@@ -290,9 +293,7 @@ my %LINKTYPEMAP = (
);
-# {{{ Scrip methods (Commit, Prepare)
-# {{{ sub Commit
#Do what we need to do and send it out.
sub Commit {
my $self = shift;
@@ -305,9 +306,7 @@ sub Commit {
return (1);
}
-# }}}
-# {{{ sub Prepare
sub Prepare {
my $self = shift;
@@ -326,17 +325,25 @@ sub Prepare {
}
+ my $active = 0;
+ if ( $self->TemplateObj->Type eq 'Perl' ) {
+ $active = 1;
+ } else {
+ RT->Logger->info(sprintf(
+ "Template #%d is type %s. You most likely want to use a Perl template instead.",
+ $self->TemplateObj->id, $self->TemplateObj->Type
+ ));
+ }
+
$self->Parse(
Content => $self->TemplateObj->Content,
- _ActiveContent => 1
+ _ActiveContent => $active,
);
return 1;
}
-# }}}
-# }}}
sub CreateByTemplate {
my $self = shift;
@@ -579,11 +586,15 @@ sub _ParseMultilineTemplate {
my %args = (@_);
my $template_id;
+ require Encode;
+ require utf8;
my ( $queue, $requestor );
$RT::Logger->debug("Line: ===");
foreach my $line ( split( /\n/, $args{'Content'} ) ) {
$line =~ s/\r$//;
- $RT::Logger->debug("Line: $line");
+ $RT::Logger->debug( "Line: " . utf8::is_utf8($line)
+ ? Encode::encode_utf8($line)
+ : $line );
if ( $line =~ /^===/ ) {
if ( $template_id && !$queue && $args{'Queue'} ) {
$self->{'templates'}->{$template_id}
@@ -716,7 +727,11 @@ sub ParseLines {
$args{$tag} =~ s/^\s+//g;
$args{$tag} =~ s/\s+$//g;
}
- if (($tag =~ /^(requestor|cc|admincc)$/i or grep {lc $_ eq $tag} keys %LINKTYPEMAP) and $args{$tag} =~ /,/) {
+ if (
+ ($tag =~ /^(requestor|cc|admincc)(group)?$/i
+ or grep {lc $_ eq $tag} keys %LINKTYPEMAP)
+ and $args{$tag} =~ /,/
+ ) {
$args{$tag} = [ split /,\s*/, $args{$tag} ];
}
}
@@ -739,6 +754,21 @@ sub ParseLines {
$args{$date} = $dateobj->ISO;
}
+ foreach my $role (qw(requestor cc admincc)) {
+ next unless my $value = $args{ $role . 'group' };
+
+ my $group = RT::Group->new( $self->CurrentUser );
+ $group->LoadUserDefinedGroup( $value );
+ unless ( $group->id ) {
+ $RT::Logger->error("Couldn't load group '$value'");
+ next;
+ }
+
+ $args{ $role } = $args{ $role } ? [$args{ $role }] : []
+ unless ref $args{ $role };
+ push @{ $args{ $role } }, $group->PrincipalObj->id;
+ }
+
$args{'requestor'} ||= $self->TicketObj->Requestors->MemberEmailAddresses
if $self->TicketObj;
@@ -781,14 +811,17 @@ sub ParseLines {
my $orig_tag = $original_tags{$tag} or next;
if ( $orig_tag =~ /^customfield-?(\d+)$/i ) {
$ticketargs{ "CustomField-" . $1 } = $args{$tag};
- } elsif ( $orig_tag =~ /^(?:customfield|cf)-?(.*)$/i ) {
+ } elsif ( $orig_tag =~ /^(?:customfield|cf)-?(.+)$/i ) {
my $cf = RT::CustomField->new( $self->CurrentUser );
$cf->LoadByName( Name => $1, Queue => $ticketargs{Queue} );
+ $cf->LoadByName( Name => $1, Queue => 0 ) unless $cf->id;
+ next unless $cf->id;
$ticketargs{ "CustomField-" . $cf->id } = $args{$tag};
} elsif ($orig_tag) {
my $cf = RT::CustomField->new( $self->CurrentUser );
$cf->LoadByName( Name => $orig_tag, Queue => $ticketargs{Queue} );
- next unless ($cf->id) ;
+ $cf->LoadByName( Name => $orig_tag, Queue => 0 ) unless $cf->id;
+ next unless $cf->id;
$ticketargs{ "CustomField-" . $cf->id } = $args{$tag};
}
@@ -1148,6 +1181,7 @@ sub UpdateCustomFields {
my $cf = $1;
my $CustomFieldObj = RT::CustomField->new($self->CurrentUser);
+ $CustomFieldObj->SetContextObject( $ticket );
$CustomFieldObj->LoadById($cf);
my @values;
diff --git a/rt/lib/RT/Action/EscalatePriority.pm b/rt/lib/RT/Action/EscalatePriority.pm
index e15e50c84..cb19b4f41 100644
--- a/rt/lib/RT/Action/EscalatePriority.pm
+++ b/rt/lib/RT/Action/EscalatePriority.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -67,6 +67,9 @@ to final priority.
In this way, priority is either increased or decreased toward the final priority
as the ticket heads toward its due date.
+Alternately, if you don't set a due date, the Priority will be incremented by 1
+until it reaches the Final Priority. If a ticket without a due date has a Priority
+greater than Final Priority, it will be decremented by 1.
=cut
@@ -80,15 +83,12 @@ use strict;
#What does this type of Action does
-# {{{ sub Describe
sub Describe {
my $self = shift;
return (ref $self . " will move a ticket's priority toward its final priority.");
}
-# }}}
-# {{{ sub Prepare
sub Prepare {
my $self = shift;
@@ -152,7 +152,6 @@ sub Prepare {
}
return 1;
}
-# }}}
sub Commit {
my $self = shift;
diff --git a/rt/lib/RT/Action/ExtractSubjectTag.pm b/rt/lib/RT/Action/ExtractSubjectTag.pm
index 7121c1327..a4d6458cb 100644
--- a/rt/lib/RT/Action/ExtractSubjectTag.pm
+++ b/rt/lib/RT/Action/ExtractSubjectTag.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -63,13 +63,15 @@ sub Commit {
my $self = shift;
my $Transaction = $self->TransactionObj;
my $FirstAttachment = $Transaction->Attachments->First;
- return 1 unless ($FirstAttachment);
+ return 1 unless $FirstAttachment;
+
+ my $TransactionSubject = $FirstAttachment->Subject;
+ return 1 unless $TransactionSubject;
my $Ticket = $self->TicketObj;
my $TicketSubject = $self->TicketObj->Subject;
my $origTicketSubject = $TicketSubject;
- my $TransactionSubject = $FirstAttachment->Subject;
my $match = RT->Config->Get('ExtractSubjectTagMatch');
my $nomatch = RT->Config->Get('ExtractSubjectTagNoMatch');
diff --git a/rt/lib/RT/Action/Generic.pm b/rt/lib/RT/Action/Generic.pm
deleted file mode 100755
index d747813f0..000000000
--- a/rt/lib/RT/Action/Generic.pm
+++ /dev/null
@@ -1,73 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
-# <sales@bestpractical.com>
-#
-# (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
-
- RT::Action::Generic - deprecated, see RT::Action
-
-=head1 SYNOPSIS
-
- use RT::Action::Generic;
-
-=head1 DESCRIPTION
-
-This module is provided only for backwards compatibility.
-
-=head1 METHODS
-
-
-=cut
-
-use strict;
-use warnings;
-package RT::Action::Generic;
-use base 'RT::Action';
-
-RT::Base->_ImportOverlays();
-1;
-
diff --git a/rt/lib/RT/Action/LinearEscalate.pm b/rt/lib/RT/Action/LinearEscalate.pm
index 3e54320cb..0a0825e82 100755
--- a/rt/lib/RT/Action/LinearEscalate.pm
+++ b/rt/lib/RT/Action/LinearEscalate.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/Notify.pm b/rt/lib/RT/Action/Notify.pm
index 3f58bf52f..f1aef4092 100755
--- a/rt/lib/RT/Action/Notify.pm
+++ b/rt/lib/RT/Action/Notify.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -87,17 +87,6 @@ sub SetRecipients {
my ( @To, @PseudoTo, @Cc, @Bcc );
- if ( $arg =~ /\bOtherRecipients\b/ ) {
- if ( my $attachment = $self->TransactionObj->Attachments->First ) {
- push @Cc, map { $_->address } Email::Address->parse(
- $attachment->GetHeader('RT-Send-Cc')
- );
- push @Bcc, map { $_->address } Email::Address->parse(
- $attachment->GetHeader('RT-Send-Bcc')
- );
- }
- }
-
if ( $arg =~ /\bRequestor\b/ ) {
push @To, $ticket->Requestors->MemberEmailAddresses;
}
@@ -115,7 +104,10 @@ sub SetRecipients {
}
}
- if ( $arg =~ /\bOwner\b/ && $ticket->OwnerObj->id != $RT::Nobody->id ) {
+ if ( $arg =~ /\bOwner\b/
+ && $ticket->OwnerObj->id != RT->Nobody->id
+ && $ticket->OwnerObj->EmailAddress
+ ) {
# If we're not sending to Ccs or requestors,
# then the Owner can be the To.
if (@To) {
@@ -140,7 +132,7 @@ sub SetRecipients {
}
my $creatorObj = $self->TransactionObj->CreatorObj;
- my $creator = $creatorObj->EmailAddress();
+ my $creator = $creatorObj->EmailAddress() || '';
#Strip the sender out of the To, Cc and AdminCc and set the
# recipients fields used to build the message by the superclass.
@@ -159,7 +151,14 @@ sub SetRecipients {
}
@{ $self->{'PseudoTo'} } = @PseudoTo;
-
+ if ( $arg =~ /\bOtherRecipients\b/ ) {
+ if ( my $attachment = $self->TransactionObj->Attachments->First ) {
+ push @{ $self->{'NoSquelch'}{'Cc'} ||= [] }, map $_->address,
+ Email::Address->parse( $attachment->GetHeader('RT-Send-Cc') );
+ push @{ $self->{'NoSquelch'}{'Bcc'} ||= [] }, map $_->address,
+ Email::Address->parse( $attachment->GetHeader('RT-Send-Bcc') );
+ }
+ }
}
RT::Base->_ImportOverlays();
diff --git a/rt/lib/RT/Action/NotifyAsComment.pm b/rt/lib/RT/Action/NotifyAsComment.pm
index 504d139c0..b62f55599 100755
--- a/rt/lib/RT/Action/NotifyAsComment.pm
+++ b/rt/lib/RT/Action/NotifyAsComment.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/NotifyGroup.pm b/rt/lib/RT/Action/NotifyGroup.pm
index a0efd5b8f..5e7076f39 100644
--- a/rt/lib/RT/Action/NotifyGroup.pm
+++ b/rt/lib/RT/Action/NotifyGroup.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/NotifyGroupAsComment.pm b/rt/lib/RT/Action/NotifyGroupAsComment.pm
index a5bc49c3a..151189033 100644
--- a/rt/lib/RT/Action/NotifyGroupAsComment.pm
+++ b/rt/lib/RT/Action/NotifyGroupAsComment.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/RecordComment.pm b/rt/lib/RT/Action/RecordComment.pm
index 5d3664d16..62832a5f4 100644
--- a/rt/lib/RT/Action/RecordComment.pm
+++ b/rt/lib/RT/Action/RecordComment.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/RecordCorrespondence.pm b/rt/lib/RT/Action/RecordCorrespondence.pm
index 109c0df91..2faa56019 100644
--- a/rt/lib/RT/Action/RecordCorrespondence.pm
+++ b/rt/lib/RT/Action/RecordCorrespondence.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
diff --git a/rt/lib/RT/Action/ResolveMembers.pm b/rt/lib/RT/Action/ResolveMembers.pm
deleted file mode 100644
index aff636558..000000000
--- a/rt/lib/RT/Action/ResolveMembers.pm
+++ /dev/null
@@ -1,108 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
-# <sales@bestpractical.com>
-#
-# (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 }}}
-
-# This Action will resolve all members of a resolved group ticket
-
-package RT::Action::ResolveMembers;
-use base 'RT::Action';
-require RT::Links;
-
-use strict;
-
-#Do what we need to do and send it out.
-
-#What does this type of Action does
-
-# {{{ sub Describe
-sub Describe {
- my $self = shift;
- return $self->loc("[_1] will resolve all members of a resolved group ticket.", ref $self);
-}
-# }}}
-
-
-# {{{ sub Prepare
-sub Prepare {
- # nothing to prepare
- return 1;
-}
-# }}}
-
-sub Commit {
- my $self = shift;
-
- my $Links=RT::Links->new($RT::SystemUser);
- $Links->Limit(FIELD => 'Type', VALUE => 'MemberOf');
- $Links->Limit(FIELD => 'Target', VALUE => $self->TicketObj->id);
-
- while (my $Link=$Links->Next()) {
- # Todo: Try to deal with remote URIs as well
- next unless $Link->BaseURI->IsLocal;
- my $base=RT::Ticket->new($self->TicketObj->CurrentUser);
- # Todo: Only work if Base is a plain ticket num:
- $base->Load($Link->Base);
- # I'm afraid this might be a major bottleneck if ResolveGroupTicket is on.
- $base->Resolve;
- }
-}
-
-
-# Applicability checked in Commit.
-
-# {{{ sub IsApplicable
-sub IsApplicable {
- my $self = shift;
- 1;
- return 1;
-}
-# }}}
-
-RT::Base->_ImportOverlays();
-
-1;
-
diff --git a/rt/lib/RT/Action/SendEmail.pm b/rt/lib/RT/Action/SendEmail.pm
index 9e93e4aab..4ae1a8b66 100755
--- a/rt/lib/RT/Action/SendEmail.pm
+++ b/rt/lib/RT/Action/SendEmail.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -80,13 +80,12 @@ RT::Action::SendEmail.
=head2 CleanSlate
-Cleans class-wide options, like L</SquelchMailTo> or L</AttachTickets>.
+Cleans class-wide options, like L</AttachTickets>.
=cut
sub CleanSlate {
my $self = shift;
- $self->SquelchMailTo(undef);
$self->AttachTickets(undef);
}
@@ -166,8 +165,6 @@ sub Prepare {
# Header
$self->SetRTSpecialHeaders();
- $self->RemoveInappropriateRecipients();
-
my %seen;
foreach my $type (@EMAIL_RECIPIENT_HEADERS) {
@{ $self->{$type} }
@@ -175,6 +172,8 @@ sub Prepare {
@{ $self->{$type} };
}
+ $self->RemoveInappropriateRecipients();
+
# Go add all the Tos, Ccs and Bccs that we need to to the message to
# make it happy, but only if we actually have values in those arrays.
@@ -349,7 +348,7 @@ sub AddAttachments {
$MIMEObj->head->delete('RT-Attach-Message');
- my $attachments = RT::Attachments->new($RT::SystemUser);
+ my $attachments = RT::Attachments->new( RT->SystemUser );
$attachments->Limit(
FIELD => 'TransactionId',
VALUE => $self->TransactionObj->Id
@@ -409,11 +408,20 @@ sub AddAttachment {
my $attach = shift;
my $MIMEObj = shift || $self->TemplateObj->MIMEObj;
+ # $attach->TransactionObj may not always be $self->TransactionObj
+ return unless $attach->Id
+ and $attach->TransactionObj->CurrentUserCanSee;
+
+ # ->attach expects just the disposition type; extract it if we have the header
+ my $disp = ($attach->GetHeader('Content-Disposition') || '')
+ =~ /^\s*(inline|attachment)/i ? $1 : undef;
+
$MIMEObj->attach(
- Type => $attach->ContentType,
- Charset => $attach->OriginalEncoding,
- Data => $attach->OriginalContent,
- Filename => $self->MIMEEncodeString( $attach->Filename ),
+ Type => $attach->ContentType,
+ Charset => $attach->OriginalEncoding,
+ Data => $attach->OriginalContent,
+ Disposition => $disp, # a false value defaults to inline in MIME::Entity
+ Filename => $self->MIMEEncodeString( $attach->Filename ),
'RT-Attachment:' => $self->TicketObj->Id . "/"
. $self->TransactionObj->Id . "/"
. $attach->id,
@@ -467,8 +475,7 @@ sub AddTicket {
my $self = shift;
my $tid = shift;
- # XXX: we need a current user here, but who is current user?
- my $attachs = RT::Attachments->new($RT::SystemUser);
+ my $attachs = RT::Attachments->new( $self->TransactionObj->CreatorObj );
my $txn_alias = $attachs->TransactionAlias;
$attachs->Limit( ALIAS => $txn_alias, FIELD => 'Type', VALUE => 'Create' );
$attachs->Limit(
@@ -660,7 +667,7 @@ sub DeferDigestRecipients {
$RT::Logger->debug( $self->TemplateObj->MIMEObj->head->as_string );
foreach my $rcpt ( map { $_->address } $self->AddressesFromHeader($mailfield) ) {
next unless $rcpt;
- my $user_obj = RT::User->new($RT::SystemUser);
+ my $user_obj = RT::User->new(RT->SystemUser);
$user_obj->LoadByEmail($rcpt);
if ( ! $user_obj->id ) {
# If there's an email address in here without an associated
@@ -729,26 +736,15 @@ sub RecordDeferredRecipients {
return ($ret,$msg);
}
-=head2 SquelchMailTo [@ADDRESSES]
-
-Mark ADDRESSES to be removed from list of the recipients. Returns list of the addresses.
-To empty list pass undefined argument.
+=head2 SquelchMailTo
-B<Note> that this method can be called as class method and works globaly. Don't forget to
-clean this list when blocking is not required anymore, pass undef to do this.
+Returns list of the addresses to squelch on this transaction.
=cut
-{
- my $squelch = [];
-
- sub SquelchMailTo {
- my $self = shift;
- if (@_) {
- $squelch = [ grep defined, @_ ];
- }
- return @$squelch;
- }
+sub SquelchMailTo {
+ my $self = shift;
+ return map $_->Content, $self->TransactionObj->SquelchMailTo;
}
=head2 RemoveInappropriateRecipients
@@ -789,9 +785,9 @@ sub RemoveInappropriateRecipients {
# Only send to "privileged" watchers.
foreach my $type (@EMAIL_RECIPIENT_HEADERS) {
foreach my $addr ( @{ $self->{$type} } ) {
- my $user = RT::User->new($RT::SystemUser);
+ my $user = RT::User->new(RT->SystemUser);
$user->LoadByEmail($addr);
- push @blacklist, $addr if ( !$user->Privileged );
+ push @blacklist, $addr unless $user->id && $user->Privileged;
}
}
$RT::Logger->info( $msgid
@@ -806,15 +802,15 @@ sub RemoveInappropriateRecipients {
}
}
-# Let's grab the SquelchMailTo attribue and push those entries into the @blacklist
- push @blacklist, map $_->Content, $self->TicketObj->SquelchMailTo;
- push @blacklist, $self->SquelchMailTo;
+ # Let's grab the SquelchMailTo attributes and push those entries into the @blacklisted
+ push @blacklist, map $_->Content, $self->TicketObj->SquelchMailTo, $self->TransactionObj->SquelchMailTo;
# Cycle through the people we're sending to and pull out anyone on the
# system blacklist
# Trim leading and trailing spaces.
- @blacklist = map { RT::User->CanonicalizeEmailAddress( $_->address ) } Email::Address->parse(join(', ', grep {defined} @blacklist));
+ @blacklist = map { RT::User->CanonicalizeEmailAddress( $_->address ) }
+ Email::Address->parse( join ', ', grep defined, @blacklist );
foreach my $type (@EMAIL_RECIPIENT_HEADERS) {
my @addrs;
@@ -826,12 +822,20 @@ sub RemoveInappropriateRecipients {
$RT::Logger->info( $msgid . "$addr appears to point to this RT instance. Skipping" );
next;
}
- if ( grep /^\Q$addr\E$/, @blacklist ) {
+ if ( grep $addr eq $_, @blacklist ) {
$RT::Logger->info( $msgid . "$addr was blacklisted for outbound mail on this transaction. Skipping");
next;
}
push @addrs, $addr;
}
+ foreach my $addr ( @{ $self->{'NoSquelch'}{$type} || [] } ) {
+ # never send email to itself
+ if ( !RT::EmailParser->CullRTAddresses($addr) ) {
+ $RT::Logger->info( $msgid . "$addr appears to point to this RT instance. Skipping" );
+ next;
+ }
+ push @addrs, $addr;
+ }
@{ $self->{$type} } = @addrs;
}
}
@@ -864,36 +868,67 @@ sub SetReturnAddress {
}
unless ( $self->TemplateObj->MIMEObj->head->get('From') ) {
- if ( RT->Config->Get('UseFriendlyFromLine') ) {
- my $friendly_name = $args{friendly_name};
+ $self->SetFrom( %args, From => $replyto );
+ }
- unless ( $friendly_name ) {
- $friendly_name = $self->TransactionObj->CreatorObj->FriendlyName;
- if ( $friendly_name =~ /^"(.*)"$/ ) { # a quoted string
- $friendly_name = $1;
- }
- }
+ unless ( $self->TemplateObj->MIMEObj->head->get('Reply-To') ) {
+ $self->SetHeader( 'Reply-To', "$replyto" );
+ }
- $friendly_name =~ s/"/\\"/g;
- $self->SetHeader(
- 'From',
- sprintf(
- RT->Config->Get('FriendlyFromLineFormat'),
- $self->MIMEEncodeString(
- $friendly_name, RT->Config->Get('EmailOutputEncoding')
- ),
- $replyto
+}
+
+=head2 SetFrom ( From => emailaddress )
+
+Set the From: address for outgoing email
+
+=cut
+
+sub SetFrom {
+ my $self = shift;
+ my %args = @_;
+
+ if ( RT->Config->Get('UseFriendlyFromLine') ) {
+ my $friendly_name = $self->GetFriendlyName(%args);
+ $self->SetHeader(
+ 'From',
+ sprintf(
+ RT->Config->Get('FriendlyFromLineFormat'),
+ $self->MIMEEncodeString(
+ $friendly_name, RT->Config->Get('EmailOutputEncoding')
),
- );
- } else {
- $self->SetHeader( 'From', $replyto );
- }
+ $args{From}
+ ),
+ );
+ } else {
+ $self->SetHeader( 'From', $args{From} );
}
+}
- unless ( $self->TemplateObj->MIMEObj->head->get('Reply-To') ) {
- $self->SetHeader( 'Reply-To', "$replyto" );
+=head2 GetFriendlyName
+
+Calculate the proper Friendly Name based on the creator of the transaction
+
+=cut
+
+sub GetFriendlyName {
+ my $self = shift;
+ my %args = (
+ is_comment => 0,
+ friendly_name => '',
+ @_
+ );
+ my $friendly_name = $args{friendly_name};
+
+ unless ( $friendly_name ) {
+ $friendly_name = $self->TransactionObj->CreatorObj->FriendlyName;
+ if ( $friendly_name =~ /^"(.*)"$/ ) { # a quoted string
+ $friendly_name = $1;
+ }
}
+ $friendly_name =~ s/"/\\"/g;
+ return $friendly_name;
+
}
=head2 SetHeader FIELD, VALUE
@@ -982,16 +1017,17 @@ Set References and In-Reply-To headers for this message.
sub SetReferencesHeaders {
my $self = shift;
- my ( @in_reply_to, @references, @msgid );
- if ( my $top = $self->TransactionObj->Message->First ) {
- @in_reply_to = split( /\s+/m, $top->GetHeader('In-Reply-To') || '' );
- @references = split( /\s+/m, $top->GetHeader('References') || '' );
- @msgid = split( /\s+/m, $top->GetHeader('Message-ID') || '' );
- } else {
+ my $top = $self->TransactionObj->Message->First;
+ unless ( $top ) {
+ $self->SetHeader( References => $self->PseudoReference );
return (undef);
}
+ my @in_reply_to = split( /\s+/m, $top->GetHeader('In-Reply-To') || '' );
+ my @references = split( /\s+/m, $top->GetHeader('References') || '' );
+ my @msgid = split( /\s+/m, $top->GetHeader('Message-ID') || '' );
+
# There are two main cases -- this transaction was created with
# the RT Web UI, and hence we want to *not* append its Message-ID
# to the References and In-Reply-To. OR it came from an outside
diff --git a/rt/lib/RT/Action/SetPriority.pm b/rt/lib/RT/Action/SetPriority.pm
index 420f9bd24..783d57dd8 100644
--- a/rt/lib/RT/Action/SetPriority.pm
+++ b/rt/lib/RT/Action/SetPriority.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -55,20 +55,16 @@ use strict;
#What does this type of Action does
-# {{{ sub Describe
sub Describe {
my $self = shift;
return (ref $self . " will set a ticket's priority to the argument provided.");
}
-# }}}
-# {{{ sub Prepare
sub Prepare {
# nothing to prepare
return 1;
}
-# }}}
sub Commit {
my $self = shift;
diff --git a/rt/lib/RT/Action/SetStatus.pm b/rt/lib/RT/Action/SetStatus.pm
new file mode 100644
index 000000000..f52d401cc
--- /dev/null
+++ b/rt/lib/RT/Action/SetStatus.pm
@@ -0,0 +1,152 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
+# <sales@bestpractical.com>
+#
+# (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 }}}
+
+package RT::Action::SetStatus;
+
+use strict;
+use warnings;
+use base qw(RT::Action);
+
+=head1 NAME
+
+RT::Action::SetStatus - RT's scrip action to set status of a ticket
+
+=head1 DESCRIPTION
+
+This action changes status to a new value according to the rules in L</ARGUMENT>.
+Status is not changed if the transition is invalid or another error occurs. All
+issues are logged at apropriate levels.
+
+=head1 ARGUMENT
+
+Argument can be one of the following:
+
+=over 4
+
+=item status literally
+
+Status is changed from the current value to a new defined by the argument,
+but only if it's valid status and allowed by transitions of the current lifecycle,
+for example:
+
+ * The current status is 'stalled'
+ * Argument of this action is 'open'
+ * The only possible transition in the scheam from 'stalled' is 'open'
+ * Status is changed
+
+However, in the example above Status is not changed if argument is anything
+else as it's just not allowed by the lifecycle.
+
+=item 'initial', 'active' or 'inactive'
+
+Status is changed from the current value to first possible 'initial',
+'active' or 'inactive' correspondingly. First possible value is figured
+according to transitions to the target set, for example:
+
+ * The current status is 'open'
+ * Argument of this action is 'inactive'
+ * Possible transitions from 'open' are 'resolved', 'rejected' or 'deleted'
+ * Status is changed to 'resolved'
+
+=back
+
+=cut
+
+sub Prepare {
+ my $self = shift;
+
+ my $ticket = $self->TicketObj;
+ my $lifecycle = $ticket->QueueObj->Lifecycle;
+ my $status = $ticket->Status;
+
+ my $argument = $self->Argument;
+ unless ( $argument ) {
+ $RT::Logger->error("Argument is mandatory for SetStatus action");
+ return 0;
+ }
+
+ my $next = '';
+ if ( $argument =~ /^(initial|active|inactive)$/i ) {
+ my $method = 'Is'. ucfirst lc $argument;
+ ($next) = grep $lifecycle->$method($_), $lifecycle->Transitions($status);
+ unless ( $next ) {
+ $RT::Logger->info("No transition from '$status' to $argument set");
+ return 1;
+ }
+ }
+ elsif ( $lifecycle->IsValid( $argument ) ) {
+ unless ( $lifecycle->IsTransition( $status => $argument ) ) {
+ $RT::Logger->warning("Transition '$status -> $argument' is not valid");
+ return 1;
+ }
+ $next = $argument;
+ }
+ else {
+ $RT::Logger->error("Argument for SetStatus action is not valid status or one of set");
+ return 0;
+ }
+
+ $self->{'set_status_to'} = $next;
+
+ return 1;
+}
+
+sub Commit {
+ my $self = shift;
+
+ return 1 unless my $new_status = $self->{'set_status_to'};
+
+ my ($val, $msg) = $self->TicketObj->SetStatus( $new_status );
+ unless ( $val ) {
+ $RT::Logger->error( "Couldn't set status: ". $msg );
+ return 0;
+ }
+ return 1;
+}
+
+1;
diff --git a/rt/lib/RT/Action/UserDefined.pm b/rt/lib/RT/Action/UserDefined.pm
index 3d8e73cb0..1bad2bedd 100644
--- a/rt/lib/RT/Action/UserDefined.pm
+++ b/rt/lib/RT/Action/UserDefined.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)