[Rt-commit] rt branch, 4.0/rest-attachments-on-create, created. rt-4.0.13-89-g0ea9d95
Ruslan Zakirov
ruz at bestpractical.com
Thu Jun 27 10:51:35 EDT 2013
The branch, 4.0/rest-attachments-on-create has been created
at 0ea9d955789bf18e4fc0a824396a56011e58c9ad (commit)
- Log -----------------------------------------------------------------
commit 7b6ddfb45a5c4c794845fc588806efdbc6daaa77
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Wed Jun 26 12:39:52 2013 +0400
extract attachments processing in REST into lib
diff --git a/lib/RT/Interface/REST.pm b/lib/RT/Interface/REST.pm
index 5f8ff99..3a85c2d 100644
--- a/lib/RT/Interface/REST.pm
+++ b/lib/RT/Interface/REST.pm
@@ -52,7 +52,7 @@ use warnings;
use RT;
use base 'Exporter';
-our @EXPORT = qw(expand_list form_parse form_compose vpush vsplit);
+our @EXPORT = qw(expand_list form_parse form_compose vpush vsplit process_attachments);
sub custom_field_spec {
my $self = shift;
@@ -296,6 +296,45 @@ sub vsplit {
return \@words;
}
+sub process_attachments {
+ my $entity = shift;
+ my @list = @_;
+ return 1 unless @list;
+
+ my $m = $HTML::Mason::Commands::m;
+ my $cgi = $m->cgi_object;
+
+ my $i = 1;
+ foreach my $e ( @list ) {
+
+ my $fh = $cgi->upload("attachment_$i");
+ return (0, "No attachment for $e") unless $fh;
+
+ local $/=undef;
+
+ my $file = $e;
+ $file =~ s#^.*[\\/]##;
+
+ my ($tmp_fh, $tmp_fn) = File::Temp::tempfile( UNLINK => 1 );
+
+ my $buf;
+ while (sysread($fh, $buf, 8192)) {
+ syswrite($tmp_fh, $buf);
+ }
+
+ my $info = $cgi->uploadInfo($fh);
+ my $new_entity = $entity->attach(
+ Path => $tmp_fn,
+ Type => $info->{'Content-Type'} || guess_media_type($tmp_fn),
+ Filename => $file,
+ Disposition => "attachment",
+ );
+ $new_entity->bodyhandle->{'_dirty_hack_to_save_a_ref_tmp_fh'} = $tmp_fh;
+ $i++;
+ }
+ return (1);
+}
+
RT::Base->_ImportOverlays();
1;
diff --git a/share/html/REST/1.0/Forms/ticket/comment b/share/html/REST/1.0/Forms/ticket/comment
index b50135f..c7e8b9c 100644
--- a/share/html/REST/1.0/Forms/ticket/comment
+++ b/share/html/REST/1.0/Forms/ticket/comment
@@ -55,8 +55,6 @@ $id
use MIME::Entity;
use LWP::MediaTypes;
use RT::Interface::REST;
-use File::Temp qw(tempfile);
-my @tmp_files;
$RT::Logger->debug("Got ticket id=$id for comment");
$RT::Logger->debug("Got args @{[keys(%changes)]}.");
@@ -89,44 +87,19 @@ if (!$changes{Text} && @atts == 0) {
goto OUTPUT;
}
-my $cgi = $m->cgi_object;
my $ent = MIME::Entity->build(
Type => "multipart/mixed",
'X-RT-Interface' => 'REST',
);
$ent->attach(Data => $changes{Text}) if $changes{Text};
-my $i = 1;
-foreach my $att (@atts) {
- local $/=undef;
- my $file = $att;
- $file =~ s#^.*[\\/]##;
-
- my $fh = $cgi->upload("attachment_$i");
- if ($fh) {
- my $buf;
- my ($w, $tmp) = tempfile();
- my $info = $cgi->uploadInfo($fh);
- push @tmp_files, $tmp;
-
- while (sysread($fh, $buf, 8192)) {
- syswrite($w, $buf);
- }
-
- $ent->attach(
- Path => $tmp,
- Type => $info->{'Content-Type'} || guess_media_type($tmp),
- Filename => $file,
- Disposition => "attachment"
- );
- }
- else {
+{
+ my ($status, $msg) = process_attachments($ent, @atts);
+ unless ( $status ) {
$e = 1;
- $c = "# No attachment for $att.";
+ $c = "# $msg";
goto OUTPUT;
}
-
- $i++;
}
unless ($ticket->CurrentUserHasRight('ModifyTicket') ||
@@ -154,6 +127,5 @@ if ($changes{Status}) {
OUTPUT:
-unlink @tmp_files;
return [ $c, $o, $k, $e ];
</%INIT>
diff --git a/share/html/REST/1.0/ticket/comment b/share/html/REST/1.0/ticket/comment
index 475e3a8..0999024 100644
--- a/share/html/REST/1.0/ticket/comment
+++ b/share/html/REST/1.0/ticket/comment
@@ -54,8 +54,6 @@ $content
use MIME::Entity;
use LWP::MediaTypes;
use RT::Interface::REST;
-use File::Temp qw(tempfile);
-my @tmp_files;
my $ticket = RT::Ticket->new($session{CurrentUser});
my $object = $r->path_info;
@@ -113,37 +111,13 @@ my $ent = MIME::Entity->build(
);
$ent->attach(Data => $k->{Text}) if $k->{Text};
-my $i = 1;
-foreach my $att (@atts) {
- local $/=undef;
- my $file = $att;
- $file =~ s#^.*[\\/]##;
-
- my $fh = $cgi->upload("attachment_$i");
- if ($fh) {
- my $buf;
- my ($w, $tmp) = tempfile();
- push @tmp_files, $tmp;
- my $info = $cgi->uploadInfo();
-
- while (sysread($fh, $buf, 8192)) {
- syswrite($w, $buf);
- }
-
- $ent->attach(
- Path => $tmp,
- Type => $info->{'Content-Type'} || guess_media_type($tmp),
- Filename => $file,
- Disposition => "attachment"
- );
- }
- else {
+{
+ my ($res, $msg) = process_attachments($ent, @atts);
+ unless ( $res ) {
$status = "400 Bad Request";
- $output = "No attachment for $att.\n";
+ $output = "$msg\n";
goto OUTPUT;
}
-
- $i++;
}
$ticket->Load($object);
@@ -177,7 +151,6 @@ if ($k->{Status}) {
OUTPUT:
-unlink @tmp_files;
</%INIT>
RT/<% $RT::VERSION %> <% $status %>
commit d69d41b0c11b4fc02289cd76ba246055ea4f10be
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Thu Jun 27 18:02:40 2013 +0400
extract form editor loop into a sub for error checks
Extracts form editor with loop into vi_form_while function
that takes text and a callback, so callback can check errors
and keep asking user to fix problems.
Use it in comment command and check files existance in the callback.
diff --git a/bin/rt.in b/bin/rt.in
index 4a3eada..cc84f96 100644
--- a/bin/rt.in
+++ b/bin/rt.in
@@ -809,30 +809,19 @@ sub comment {
my $text = Form::compose([ $form ]);
if ($edit || !$msg) {
- my $error = 0;
- my ($c, $o, $k, $e);
-
- do {
- my $ntext = vi($text);
- return if ($error && $ntext eq $text);
- $text = $ntext;
- $form = Form::parse($text);
- $error = 0;
-
- ($c, $o, $k, $e) = @{ $form->[0] };
- if ($e) {
- $error = 1;
- $c = "# Syntax error.";
- goto NEXT;
- }
- elsif (!@$o) {
- return 0;
- }
- @files = @{ vsplit($k->{Attachment}) };
-
- NEXT:
- $text = Form::compose([[$c, $o, $k, $e]]);
- } while ($error);
+ my ($tmp) = vi_form_while(
+ $text,
+ sub {
+ my ($text, $form) = @_;
+ foreach my $f ( @{ vsplit($form->[2]{'Attachment'}) } ) {
+ return (0, "File '$f' doesn't exist") unless -f $f;
+ }
+ @files = @{ vsplit($form->[2]{'Attachment'}) };
+ return 1;
+ },
+ );
+ return $tmp unless $tmp;
+ $text = $tmp;
}
my $i = 1;
@@ -1466,6 +1455,43 @@ sub read_passwd {
return $passwd;
}
+sub vi_form_while {
+ my $text = shift;
+ my $cb = shift;
+
+ my $error = 0;
+ my ($c, $o, $k, $e);
+ do {
+ my $ntext = vi($text);
+ return undef if ($error && $ntext eq $text);
+
+ $text = $ntext;
+
+ my $form = Form::parse($text);
+ $error = 0;
+ ($c, $o, $k, $e) = @{ $form->[0] };
+ if ( $e ) {
+ $error = 1;
+ $c = "# Syntax error.";
+ goto NEXT;
+ }
+ elsif (!@$o) {
+ return 0;
+ }
+
+ my ($status, $msg) = $cb->( $text, [$c, $o, $k, $e] );
+ unless ( $status ) {
+ $error = 1;
+ $c = "# $msg";
+ }
+
+ NEXT:
+ $text = Form::compose([[$c, $o, $k, $e]]);
+ } while ($error);
+
+ return $text;
+}
+
sub vi {
my ($text) = @_;
my $editor = $ENV{EDITOR} || $ENV{VISUAL} || "vi";
commit 0ea9d955789bf18e4fc0a824396a56011e58c9ad
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Wed Jun 26 13:28:53 2013 +0400
REST: make it possible to attach files on create
Now ticket create form has Attachment field and
it's possible to use set attachment=foo.txt from
command line.
diff --git a/bin/rt.in b/bin/rt.in
index cc84f96..8088312 100644
--- a/bin/rt.in
+++ b/bin/rt.in
@@ -655,17 +655,40 @@ sub edit {
return 0;
}
+ my @files;
+ @files = @{ vsplit($set{'attachment'}) } if exists $set{'attachment'};
+
my $synerr = 0;
EDIT:
# We'll let the user edit the form before sending it to the server,
# unless we have enough information to submit it non-interactively.
if ($edit || (!$input && !$cl)) {
- my $newtext = vi($text);
+ my ($newtext) = vi_form_while(
+ $text,
+ sub {
+ my ($text, $form) = @_;
+ return 1 unless exists $form->[2]{'Attachment'};
+
+ foreach my $f ( @{ vsplit($form->[2]{'Attachment'}) } ) {
+ return (0, "File '$f' doesn't exist") unless -f $f;
+ }
+ @files = @{ vsplit($form->[2]{'Attachment'}) };
+ return 1;
+ },
+ );
+ return $newtext unless $newtext;
# We won't resubmit a bad form unless it was changed.
$text = ($synerr && $newtext eq $text) ? undef : $newtext;
}
+ delete @data{ grep /^attachment_\d+$/, keys %data };
+ my $i = 1;
+ foreach my $file (@files) {
+ $data{"attachment_$i"} = bless([ $file ], "Attachment");
+ $i++;
+ }
+
if ($text) {
my $r = submit("$REST/edit", {content => $text, %data});
if ($r->code == 409) {
diff --git a/share/html/REST/1.0/Forms/ticket/default b/share/html/REST/1.0/Forms/ticket/default
index a48876b..41dd2c1 100644
--- a/share/html/REST/1.0/Forms/ticket/default
+++ b/share/html/REST/1.0/Forms/ticket/default
@@ -110,7 +110,7 @@ else {
return [
"# Required: id, Queue",
[ qw(id Queue Requestor Subject Cc AdminCc Owner Status Priority
- InitialPriority FinalPriority TimeEstimated Starts Due Text) ],
+ InitialPriority FinalPriority TimeEstimated Starts Due Attachment Text) ],
{
id => "ticket/new",
Queue => $queue->Name,
@@ -126,6 +126,7 @@ else {
TimeEstimated => 0,
Starts => $starts->ISO,
Due => $due->ISO,
+ Attachment => '',
Text => "",
},
0
@@ -134,7 +135,7 @@ else {
else {
# We'll create a new ticket, and fall through to set fields that
# can't be set in the call to Create().
- my (%v, $text);
+ my (%v, $text, @atts);
foreach my $k (keys %data) {
# flexibly parse any dates
@@ -167,6 +168,9 @@ else {
elsif (lc $k eq 'text') {
$text = delete $data{$k};
}
+ elsif (lc $k eq 'attachment') {
+ push @atts, @{ vsplit(delete $data{$k}) };
+ }
elsif ( $k !~ /^(?:id|requestors)$/i ) {
$e = 1;
push @$o, $k;
@@ -183,14 +187,21 @@ else {
# people fields allow multiple values
$v{$_} = vsplit($v{$_}) foreach ( grep $create{lc $_}, @people );
- if ($text) {
+ if ($text || @atts) {
$v{MIMEObj} =
MIME::Entity->build(
+ Type => "multipart/mixed",
From => $session{CurrentUser}->EmailAddress,
Subject => $v{Subject},
- Data => $text,
'X-RT-Interface' => 'REST',
);
+ $v{MIMEObj}->attach( Data => $text ) if $text;
+ my ($status, $msg) = process_attachments($v{'MIMEObj'}, @atts);
+ unless ($status) {
+ push(@comments, "# $msg");
+ goto DONE;
+ }
+ $v{MIMEObj}->make_singlepart;
}
my($tid,$trid,$terr) = $ticket->Create(%v);
-----------------------------------------------------------------------
More information about the Rt-commit
mailing list