[Rt-commit] rt branch, 4.2/attach-from-transactions, created. rt-4.0.1-399-gea61a55

Thomas Sibley trs at bestpractical.com
Thu Aug 11 13:23:15 EDT 2011


The branch, 4.2/attach-from-transactions has been created
        at  ea61a555cc95a4423d8a94f1aa32751f88704a71 (commit)

- Log -----------------------------------------------------------------
commit 0f43ef5248c702fb14dae95dea1918039f1ac997
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Wed Aug 10 18:05:34 2011 -0400

    Add the ability to include existing attachments when responding to a transaction
    
    The ticket update page (and any other place which uses
    /Ticket/Elements/AddAttachments) will offer up the named attachments
    from the transaction being quoted (if any).  Each selected attachment
    causes an RT-Attach: id header to be added to the update.
    
    The RT-Attach headers are inspected to actually add the attachments to
    outgoing mail in RT::Action::SendEmail, as long as the creator of the
    transaction with the RT-Attach headers can see the requested
    attachments.  If the outgoing template has a false RT-Attach-Message
    value, then RT-Attach headers are skipped just like attachments directly
    on the transaction.
    
    Any RT-Attach headers in the template are merged with the ones from the
    transaction.  This makes it possible, if permissions are correct, to use
    a template-level RT-Attach header to attach arbitrary content.
    
    This feature is accessible via the Perl API by passing in the
    AttachExisting option (as an arrayref) to RT::Ticket->Correspond and
    RT::Ticket->Comment, or manually setting RT-Attach headers on
    transaction content.

diff --git a/lib/RT/Action/SendEmail.pm b/lib/RT/Action/SendEmail.pm
index 553b736..fac2481 100644
--- a/lib/RT/Action/SendEmail.pm
+++ b/lib/RT/Action/SendEmail.pm
@@ -58,6 +58,7 @@ use base qw(RT::Action);
 use RT::EmailParser;
 use RT::Interface::Email;
 use Email::Address;
+use List::MoreUtils qw(uniq);
 our @EMAIL_RECIPIENT_HEADERS = qw(To Cc Bcc);
 
 
@@ -394,6 +395,51 @@ sub AddAttachments {
         }
         $self->AddAttachment($attach);
     }
+
+    # attach any attachments requested by the transaction or template
+    # that aren't part of the transaction itself
+    $self->AddAttachmentsFromHeaders;
+}
+
+=head2 AddAttachmentsFromHeaders
+
+Add attachments requested by the transaction or template that aren't part of
+the transaction itself.
+
+This inspects C<RT-Attach> headers, which are expected to contain an
+L<RT::Attachment> ID that the transaction's creator can See.
+
+L<RT::Ticket->_RecordNote> accepts an C<AttachExisting> argument which sets
+C<RT-Attach> headers appropriately on Comment/Correspond.
+
+=cut
+
+sub AddAttachmentsFromHeaders {
+    my $self  = shift;
+    my $orig  = $self->TransactionObj->Attachments->First;
+    my $email = $self->TemplateObj->MIMEObj;
+
+    # Add the RT-Attach headers from the transaction to the email
+    if ($orig and $orig->GetHeader('RT-Attach')) {
+        for my $id ($orig->ContentAsMIME(Children => 0)->head->get_all('RT-Attach')) {
+            $email->head->add('RT-Attach' => $id);
+        }
+    }
+
+    # Take all RT-Attach headers and add the attachments to the outgoing mail
+    my $seen_attachment = 0;
+    for my $id (uniq $email->head->get_all('RT-Attach')) {
+        my $attach = RT::Attachment->new( $self->TransactionObj->CreatorObj );
+        $attach->Load($id);
+        next unless $attach->Id
+                and $attach->TransactionObj->CurrentUserCanSee;
+
+        if ( !$seen_attachment ) {
+            $email->make_multipart( 'mixed', Force => 1 );
+            $seen_attachment = 1;
+        }
+        $self->AddAttachment($attach, $email);
+    }
 }
 
 =head2 AddAttachment $attachment
diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index cb22847..41af8ce 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -1521,7 +1521,8 @@ sub ProcessUpdateMessage {
         Sign         => ( $args{ARGSRef}->{'Sign'} ? 1 : 0 ),
         Encrypt      => ( $args{ARGSRef}->{'Encrypt'} ? 1 : 0 ),
         MIMEObj      => $Message,
-        TimeTaken    => $args{ARGSRef}->{'UpdateTimeWorked'}
+        TimeTaken    => $args{ARGSRef}->{'UpdateTimeWorked'},
+        AttachExisting => $args{ARGSRef}->{'AttachExisting'},
     );
 
     _ProcessUpdateMessageRecipients(
diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index 8a3e78c..f1d0e19 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -2183,6 +2183,7 @@ sub _RecordNote {
         TimeTaken    => 0,
         CommitScrips => 1,
         SquelchMailTo => undef,
+        AttachExisting => [],
         @_
     );
 
@@ -2199,6 +2200,17 @@ sub _RecordNote {
     # convert text parts into utf-8
     RT::I18N::SetMIMEEntityToUTF8( $args{'MIMEObj'} );
 
+    # Set the magic RT headers which include existing attachments on this note
+    if ($args{'AttachExisting'}) {
+        $args{'AttachExisting'} = [$args{'AttachExisting'}]
+            if not ref $args{'AttachExisting'} eq 'ARRAY';
+
+        for my $attach (@{$args{'AttachExisting'}}) {
+            next if $attach =~ /\D/;
+            $args{'MIMEObj'}->head->add( 'RT-Attach' => $attach );
+        }
+    }
+
     # If we've been passed in CcMessageTo and BccMessageTo fields,
     # add them to the mime object for passing on to the transaction handler
     # The "NotifyOtherRecipients" scripAction will look for RT-Send-Cc: and
diff --git a/share/html/Ticket/Elements/AddAttachments b/share/html/Ticket/Elements/AddAttachments
index ba97a83..937730c 100644
--- a/share/html/Ticket/Elements/AddAttachments
+++ b/share/html/Ticket/Elements/AddAttachments
@@ -59,3 +59,32 @@
 <tr><td class="label"><&|/l&>Attach</&>:</td><td><input name="Attach" type="file" /><input type="submit" class="button" name="AddMoreAttach" value="<&|/l&>Add More Files</&>" /><input type="hidden" class="hidden" name="UpdateAttach" value="1" />
 </td></tr>
 
+% if (@quoted_attachments) {
+<tr>
+  <td class="label"><&|/l&>Include attachments</&>:</td>
+  <td>
+%     for my $attach (@quoted_attachments) {
+    <label>
+      <input type="checkbox" class="checkbox" name="AttachExisting" value="<% $attach->Id %>" \
+             <% (grep { $attach->Id == $_ } @AttachExisting) ? 'checked' : '' %> />
+      <% $attach->Filename %>
+    </label>
+%     }
+  </td>
+</tr>
+% }
+<%init>
+my @quoted_attachments;
+if ($QuoteTransaction) {
+    my $txn = RT::Transaction->new( $session{'CurrentUser'} );
+    $txn->Load($QuoteTransaction);
+    if ($txn->Id and $txn->CurrentUserCanSee) {
+        @quoted_attachments = grep { defined $_->Filename and length $_->Filename }
+                                  @{$txn->Attachments->ItemsArrayRef};
+    }
+}
+</%init>
+<%args>
+ at AttachExisting => ()
+$QuoteTransaction => ''
+</%args>

commit 7b0cb858d1848cfa2ce53745fc377279a1ba9124
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Thu Aug 11 12:40:51 2011 -0400

    Simplify the copying of RT-Attach headers from the txn into the mail
    
    By adding an RT::Attachment->GetAllHeaders method comparable to
    MIME::Head->get_all.

diff --git a/lib/RT/Action/SendEmail.pm b/lib/RT/Action/SendEmail.pm
index fac2481..f162fab 100644
--- a/lib/RT/Action/SendEmail.pm
+++ b/lib/RT/Action/SendEmail.pm
@@ -416,12 +416,11 @@ C<RT-Attach> headers appropriately on Comment/Correspond.
 
 sub AddAttachmentsFromHeaders {
     my $self  = shift;
-    my $orig  = $self->TransactionObj->Attachments->First;
     my $email = $self->TemplateObj->MIMEObj;
 
     # Add the RT-Attach headers from the transaction to the email
-    if ($orig and $orig->GetHeader('RT-Attach')) {
-        for my $id ($orig->ContentAsMIME(Children => 0)->head->get_all('RT-Attach')) {
+    if (my $attachment = $self->TransactionObj->Attachments->First) {
+        for my $id ($attachment->GetAllHeaders('RT-Attach')) {
             $email->head->add('RT-Attach' => $id);
         }
     }
diff --git a/lib/RT/Attachment.pm b/lib/RT/Attachment.pm
index 1feb632..392d8f3 100644
--- a/lib/RT/Attachment.pm
+++ b/lib/RT/Attachment.pm
@@ -580,8 +580,8 @@ sub EncodedHeaders {
 
 =head2 GetHeader $TAG
 
-Returns the value of the header Tag as a string. This bypasses the weeding out
-done in Headers() above.
+Returns the value of the B<first> header Tag as a string. This bypasses the
+weeding out done in Headers() above.
 
 =cut
 
@@ -599,6 +599,24 @@ sub GetHeader {
     return undef;
 }
 
+=head2 GetAllHeaders $TAG
+
+Returns a list of all values for the the given header tag, in the order they
+appear.
+
+=cut
+
+sub GetAllHeaders {
+    my $self = shift;
+    my $tag = shift;
+    my @values = ();
+    foreach my $line ($self->_SplitHeaders) {
+        next unless $line =~ /^\Q$tag\E:\s+(.*)$/si;
+        push @values, $1;
+    }
+    return @values;
+}
+
 =head2 DelHeader $TAG
 
 Delete a field from the attachment's headers.

commit af0c0adbb7bd577a8e2fec89eb04e51f9dc136d3
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Thu Aug 11 12:42:11 2011 -0400

    Each include attachment checkbox and filename gets its own line

diff --git a/share/html/Ticket/Elements/AddAttachments b/share/html/Ticket/Elements/AddAttachments
index 937730c..a8f2878 100644
--- a/share/html/Ticket/Elements/AddAttachments
+++ b/share/html/Ticket/Elements/AddAttachments
@@ -61,14 +61,14 @@
 
 % if (@quoted_attachments) {
 <tr>
-  <td class="label"><&|/l&>Include attachments</&>:</td>
+  <td class="label" valign="top"><&|/l&>Include attachments</&>:</td>
   <td>
 %     for my $attach (@quoted_attachments) {
     <label>
       <input type="checkbox" class="checkbox" name="AttachExisting" value="<% $attach->Id %>" \
              <% (grep { $attach->Id == $_ } @AttachExisting) ? 'checked' : '' %> />
       <% $attach->Filename %>
-    </label>
+    </label><br />
 %     }
   </td>
 </tr>

commit ea61a555cc95a4423d8a94f1aa32751f88704a71
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Thu Aug 11 13:17:25 2011 -0400

    Display RT-Attach headers in history by linking the filename
    
    It is possible recipients of the transaction saw the attachment via
    email but can't see it via the web.  This should be improved in the
    future, but it's an acceptable edge case at the moment since we avoid
    storing the attachment twice.

diff --git a/share/html/Ticket/Elements/ShowMessageHeaders b/share/html/Ticket/Elements/ShowMessageHeaders
index 943b567..5220f9a 100755
--- a/share/html/Ticket/Elements/ShowMessageHeaders
+++ b/share/html/Ticket/Elements/ShowMessageHeaders
@@ -78,6 +78,17 @@ unless ( $display_headers{'_all'} ) {
 my $ticket = $Message->TransactionObj->TicketObj;
 foreach my $f (@headers) {
     $m->comp('/Elements/MakeClicky', content => \$f->{'Value'}, ticket => $ticket, %ARGS);
+    if ($f->{'Tag'} eq 'RT-Attach') {
+        # Blat in the filename and linkify
+        my $att = RT::Attachment->new( $session{'CurrentUser'} );
+        $att->Load($f->{'Value'});
+        next unless $att->Id and $att->TransactionObj->CurrentUserCanSee;
+
+        $f->{'Value'} = sprintf '<a href="%s/Ticket/Attachment/%d/%d/%s">%s</a>',
+                                RT->Config->Get('WebPath'), $att->TransactionObj->Id, $att->Id,
+                                $m->interp->apply_escapes($att->Filename, qw(u h)),
+                                $m->interp->apply_escapes($att->Filename, 'h');
+    }
 }
 
 if ( $Localize ) {
diff --git a/share/html/Ticket/Elements/ShowTransactionAttachments b/share/html/Ticket/Elements/ShowTransactionAttachments
index ccf35fd..3569003 100644
--- a/share/html/Ticket/Elements/ShowTransactionAttachments
+++ b/share/html/Ticket/Elements/ShowTransactionAttachments
@@ -118,7 +118,7 @@ if ( $Transaction->Type =~ /EmailRecord$/ ) {
 
 # If the transaction has anything attached to it at all
 elsif (!$ShowHeaders)  {
-    @DisplayHeaders = qw(To From RT-Send-Cc Cc Bcc Date Subject);
+    @DisplayHeaders = qw(To From RT-Send-Cc Cc Bcc RT-Attach Date Subject);
     push @DisplayHeaders, 'RT-Send-Bcc' if RT->Config->Get('ShowBccHeader');
 }
 

-----------------------------------------------------------------------


More information about the Rt-commit mailing list