Patch for SelfService upload multiple files. any better?

I’ve noticed that the “Reply” form at /SelfService/Update.html does
not allow customers to submit multiple file attachments in a single
post like privileged users can do in /Ticket/Update.html

I have tried to patch the feature from Ticket/Update.html back into a
"local" SelfService/Update.html
A “local” SelfService/Display.html also needed patching because
Update.html now redirects there, like on the privileged side.

It seems to work, but I don’t really know what I am doing.
Is it right? Does anyone do this better?

$ diff -u /usr/share/request-tracker3.8/html/SelfService/Update.html
Update.html
— /usr/share/request-tracker3.8/html/SelfService/Update.html
2009-06-16 14:57:46.000000000 -0700
+++ Update.html 2010-02-11 17:41:08.000000000 -0800
@@ -51,7 +51,7 @@

% $m->callback(CallbackName => ‘BeforeForm’, %ARGS, ARGSRef =>
%ARGS, Ticket => $Ticket );

-
+

@@ -91,28 +91,48 @@
+
<& /Ticket/Elements/EditCustomFields, TicketObj => $Ticket &> -<& /Elements/MessageBox, - Name => "UpdateContent", - QuoteTransaction => $ARGS{QuoteTransaction} - &> +% if (exists $ARGS{UpdateContent}) { +% my $temp = $ARGS{'QuoteTransaction'}; +% delete $ARGS{'QuoteTransaction'}; +<& /Elements/MessageBox, Name=>"UpdateContent", Default=>$ARGS{UpdateContent}, IncludeSignature => 0, %ARGS&> +% $ARGS{'QuoteTransaction'} = $temp; +% } else { +<& /Elements/MessageBox, Name=>"UpdateContent", %ARGS &> +% }

-<& /Elements/Submit &>
+<& /Elements/Submit, Label => loc(‘Update Ticket’), Name => ‘SubmitTicket’ &>

+
+<& /Ticket/Elements/ShowHistory,

  •  Ticket => $Ticket,
    
  •  URIFile => "Display.html",
    
  •  ShowHeaders => $ARGS{'ShowHeaders'},
    
  •  DownloadableHeaders => 0,
    
  •  AttachPath => "Attachment",
    
  •  Attachments => $attachments,
    
  •  UpdatePath => "Update.html"
    

+&>

<%INIT>

my $Ticket = LoadTicket($id);

-$m->callback( Ticket => $Ticket, ARGSRef => %ARGS, CallbackName =>
‘Initial’ );
+# my @results;
+# $m->callback( Ticket => $Ticket, ARGSRef => %ARGS, results =>
@results, CallbackName => ‘Initial’ );
+# add this to get Hiztory on Reply screen
+my $attachments = $m->comp( ‘/Ticket/Elements/FindAttachments’,
Ticket => $Ticket );

my $title = loc( “Update ticket #[_1]”, $Ticket->id );

@@ -123,7 +143,53 @@
unless ( $Ticket->CurrentUserHasRight(‘ReplyToTicket’)
or $Ticket->CurrentUserHasRight(‘ModifyTicket’) );

-$m->callback(CallbackName => ‘BeforeDisplay’, Ticket => $Ticket,
ARGSRef => %ARGS);
+# stolen from /Ticket/Update.html to process multiple attachments for 1 post
+# {{{ deal with deleting uploaded attachments
+foreach my $key (keys %ARGS) {

  • if ($key =~ m/^DeleteAttach-(.+)$/) {
  •    delete $session{'Attachments'}{$1};
    
  • }
  • $session{‘Attachments’} = { %{$session{‘Attachments’} || {}} };
    +}
    +# }}}
    +# {{{ store the uploaded attachment in session
    +if ($ARGS{‘Attach’}) { # attachment?
  • my $attachment = MakeMIMEEntity(
  •    AttachmentFieldName => 'Attach'
    
  • );
  • my $file_path = Encode::decode_utf8("$ARGS{‘Attach’}");
  • $session{‘Attachments’} = {
  •    %{$session{'Attachments'} || {}},
    
  •    $file_path => $attachment,
    
  • };
    +}
    +# }}}
    +# delete temporary storage entry to make WebUI clean
    +unless (keys %{$session{‘Attachments’}} and $ARGS{‘UpdateAttach’}) {
  • delete $session{‘Attachments’};
    +}
    +# }}}
    +$m->callback( TicketObj => $Ticket, ARGSRef => %ARGS );
    +my @results;
    +#unless ( $ARGS{‘AddMoreAttach’} ) {
    +# # Add session attachments if any to be processed by ProcessUpdateMessage
    +# $ARGS{‘UpdateAttachments’} = $session{‘Attachments’} if (
    $session{‘Attachments’} );
    +# # my @results, ProcessUpdateMessage(TicketObj => $Ticket,
    ARGSRef => %ARGS );
    +# # Cleanup WebUI
    +# delete $session{‘Attachments’};
    +#}
    +if ( exists $ARGS{‘SubmitTicket’} ) {
  • $m->callback(CallbackName => ‘BeforeDisplay’, Ticket => $Ticket,
    ARGSRef => %ARGS);
  • return $m->comp(‘Display.html’, TicketObj => $Ticket, %ARGS);
    +}
    </%INIT>

<%ARGS>

diff -u /usr/share/request-tracker3.8/html/SelfService/Display.html
Display.html
— /usr/share/request-tracker3.8/html/SelfService/Display.html
2009-06-16 14:57:46.000000000 -0700
+++ Display.html 2010-02-11 18:28:46.000000000 -0800
@@ -48,29 +48,11 @@
<& /SelfService/Elements/Header, Title => loc(’#[_1]: [_2]’,
$Ticket->id, $Ticket->Subject) &>

% $m->callback(CallbackName => ‘BeforeActionList’, %ARGS, Actions =>
@results, ARGSRef => %ARGS, Ticket => $Ticket );
<& /Elements/ListActions, actions => @results &>

  •  <tr>
    
  •    <td valign="top" width="50%" class="boxcontainer">
    
  •      <&| /Widgets/TitleBox, title => loc('The Basics'),
    
  •            title_class=> 'inverse',
    
  •            color => "#993333" &>
    
  •            <& /Ticket/Elements/ShowBasics, Ticket => $Ticket &>
    
  •            <& /Ticket/Elements/ShowCustomFields, Ticket => $Ticket &>
    
  •      </&>
    
  • -

    •    <td valign="top" width="50%" class="boxcontainer">
      
    •      <&| /Widgets/TitleBox, title => loc("Dates"),
      
    •            title_class=> 'inverse',
      
    •             color => "#663366" &>
      
    •      <& /Ticket/Elements/ShowDates, Ticket => $Ticket, UpdatedLink => 0 &>
      
    •      </&>
      

    -
    -
    -


    +
    • <&|/l&>Status</&>: <% loc($Ticket->Status) %>
      +

%#!!pape: selfservice_find_attachments.patch {{
@@ -89,9 +71,10 @@

<%INIT>

-my ( $field, @results );
+$m->callback( TicketObj => $Ticket, ARGSRef => %ARGS, CallbackName
=> ‘Initial’ );
+my @results;

-$m->callback( ARGSRef => %ARGS, CallbackName => ‘Initial’ );

{{{ Load the ticket

#If we get handed two ids, mason will make them an array. bleck.
@@ -99,22 +82,6 @@

to deal

my @id = ( ref $id eq ‘ARRAY’ ) ? @{$id} : ($id);

-my $Ticket = new RT::Ticket( $session{‘CurrentUser’} );
-# store the uploaded attachment in session
-if ( $ARGS{‘Attach’} ) { # attachment?

  • $session{‘Attachments’} = {} unless defined $session{‘Attachments’};
  • my $attachment = MakeMIMEEntity(
  •    AttachmentFieldName => 'Attach'
    
  • );
  • my $file_path = Encode::decode_utf8("$ARGS{‘Attach’}");
  • $session{‘Attachments’} = {
  •    %{ $session{'Attachments'} || {} },
    
  •    $file_path => $attachment,
    
  • };
    -}

if ( defined ($id[0]) && $id[0] eq ‘new’ ) {

@@ -134,58 +101,36 @@
}

  • ( $Ticket, @results ) =
  • CreateTicket( Attachments => $session{‘Attachments’}, %ARGS,
    Status => ‘new’ );
  • ( $Ticket, @results ) = CreateTicket(
  •     Attachments => delete $session{'Attachments'}, %ARGS, Status
    

=> ‘new’ );

 unless ( $Ticket->id ) {
     $m->comp( 'Error.html', Why => join( "\n", @results ));
  •          $m->abort();
    
  •    }
    
  •    # }}}
    
  •    # delete temporary storage entry to make WebUI clean
    
  •    unless ( keys %{ $session{'Attachments'} } and
    

$ARGS{‘UpdateAttach’} ) {

  •        delete $session{'Attachments'};
    
  •    }
    
  •    # }}}
    
  • }
  • else {
  •    unless ( $Ticket->Load( $id[0] ) ) {
    
  •        $m->comp( 'Error.html',
    
  •            Why => loc( "Couldn't load ticket '[_1]'", $id ) );
    
  •        $m->abort();
    
  •    }
    
  • my ( $code, $msg );
  •    $m->abort();
    
  • }
  • }}}

  • if (
  •    $session{'Attachments'}
    
  •    || ( defined $ARGS{'UpdateContent'}
    
  •        && $ARGS{'UpdateContent'} ne ''
    
  •        && $ARGS{'UpdateContent'} ne "-- \n"
    
  •        . $session{'CurrentUser'}->UserObj->Signature )
    
  •  )
    
  • {
  •    $ARGS{UpdateAttachments} = $session{'Attachments'};
    

+} else {

  • $Ticket = new RT::Ticket( $session{‘CurrentUser’} );
  • unless ( $Ticket->Load( $ARGS{‘id’} ) ) {
  •    $m->comp( 'Error.html', Why => loc( "Couldn't load ticket
    

‘[_1]’", $id ) );

  •    $m->abort();
    
    }
  • push @results, ProcessUpdateMessage(
  • $ARGS{UpdateAttachments} = $session{‘Attachments’};
  • push @results,
  •    ProcessUpdateMessage(
       ARGSRef   => \%ARGS,
    
  •    results   => \@results,
       TicketObj => $Ticket
    
    );
  •        delete $session{'Attachments'};
    
  • delete $session{‘Attachments’};
  • delete temporary storage entry to make WebUI clean

  • unless ( keys %{ $session{‘Attachments’} } and $ARGS{‘UpdateAttach’} ) {

  •    delete $session{'Attachments'};
    
  • }

  • my @cfupdates = ProcessObjectCustomFieldUpdates(Object =>
    $Ticket, ARGSRef => %ARGS);

  • push (@results, @cfupdates);

  • push @results, ProcessObjectCustomFieldUpdates(Object => $Ticket,
    ARGSRef => %ARGS);
  • }}}

  • my ( $code, $msg );

    #Update the status
    if ( ( defined $ARGS{‘Status’} )
    @@ -198,10 +143,7 @@

    }}}

  • }

    This code does automatic redirection if any updates happen.

    unless ( $Ticket->CurrentUserHasRight(‘ShowTicket’) ) {
    $m->comp( ‘Error.html’,
    Why => loc(“No permission to display that ticket”) );
    @@ -209,7 +151,11 @@
    $m->abort();
    }

  • if (@results) {
    +}
    +if (@results) {
    # We’ve done something, so we need to clear the decks to avoid
    # resubmission on refresh.
    # But we need to store Actions somewhere too, so we don’t lose them.
    @@ -217,17 +163,17 @@
    push @{ $session{“Actions”}->{$key} ||= [] }, @results;
    $session{‘i’}++;
    RT::Interface::Web::Redirect( RT->Config->Get(‘WebURL’)
    .“SelfService/Display.html?id=”. $Ticket->id."&results=".$key);

  • }
    +}

  • my $Transactions = $Ticket->Transactions;
    +my $Transactions = $Ticket->Transactions;

  • my $attachments =

  •  $m->comp( '/Ticket/Elements/FindAttachments', Ticket => $Ticket );
    

+my $attachments = $m->comp( ‘/Ticket/Elements/FindAttachments’,
Ticket => $Ticket );

  • $m->callback(CallbackName => ‘BeforeDisplay’, Ticket => $Ticket,
    ARGSRef => %ARGS);
    +$m->callback(CallbackName => ‘BeforeDisplay’, Ticket => $Ticket,
    ARGSRef => %ARGS);
    </%INIT>

<%ARGS>
$id => undef
+$Ticket => undef
</%ARGS>

SelfService/Create.html also only allows 1 file upload per post and
really needs a similar patch.