Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REST 1.0 - Add fetching and setting of transaction CustomFields #368

Open
wants to merge 6 commits into
base: 5.0-trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions lib/RT/Test.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,33 @@ sub load_or_create_custom_field {
return $obj;
}

=head2 load_or_create_txn_custom_field

=cut

sub load_or_create_txn_custom_field {
my $self = shift;
my %args = ( Disabled => 0, @_ );
my $obj = RT::CustomField->new( RT->SystemUser );
if ( $args{'Name'} ) {
$obj->LoadByName(
Name => $args{'Name'},
LookupType => RT::Transaction->CustomFieldLookupType,
ObjectId => $args{'Queue'}->id,
);
} else {
die "Name is required";
}
unless ( $obj->id ) {
$args{'LookupType'} = 'RT::Queue-RT::Ticket-RT::Transaction';
my $queue = delete $args{'Queue'};
my ($val, $msg) = $obj->Create( %args );
$obj->AddToObject($queue);
}

return $obj;
}

sub last_ticket {
my $self = shift;
my $current = shift;
Expand Down
52 changes: 45 additions & 7 deletions share/html/REST/1.0/Forms/ticket/comment
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ $id
use MIME::Entity;
use RT::Interface::REST;

my $cf_spec = RT::Interface::REST->custom_field_spec(1);

$RT::Logger->debug("Got ticket id=$id for comment");
$RT::Logger->debug("Got args @{[keys(%changes)]}.");

Expand All @@ -78,7 +80,8 @@ unless ($action =~ /^(?:Comment|Correspond)$/) {
}

my $text = $changes{Text};
my @atts = @{ vsplit($changes{Attachment}) };
my @atts = @{ vsplit($changes{Attachment}) }
if defined $changes{Attachment};

if (!$changes{Text} && @atts == 0) {
$e = 1;
Expand Down Expand Up @@ -106,6 +109,20 @@ $ent->attach(
}
}

{
my ($status, @msg) = $m->comp(
'/Elements/ValidateCustomFields',
CustomFields => $ticket->TransactionCustomFields,
Object => RT::Transaction->new( $session{'CurrentUser'} ),
ARGSRef => \%ARGS
);
unless ( $status ) {
$e = 1;
$c = "# " . join("\n# ", @msg);
goto OUTPUT;
}
}

unless ($ticket->CurrentUserHasRight('ModifyTicket') ||
($action eq "Comment" &&
$ticket->CurrentUserHasRight("CommentOnTicket")) ||
Expand All @@ -117,18 +134,39 @@ unless ($ticket->CurrentUserHasRight('ModifyTicket') ||
goto OUTPUT;
}

my $cc = join ", ", @{ vsplit($changes{Cc}) };
my $bcc = join ", ", @{ vsplit($changes{Bcc}) };
my ($n, $s) = $ticket->$action(MIMEObj => $ent,
CcMessageTo => $cc,
BccMessageTo => $bcc,
TimeTaken => $changes{TimeWorked} || 0);
my $cc = join ", ", @{ vsplit($changes{Cc} || '') };
my $bcc = join ", ", @{ vsplit($changes{Bcc} || '') };
my ($n, $s, $txn) = $ticket->$action(MIMEObj => $ent,
CcMessageTo => $cc,
BccMessageTo => $bcc,
TimeTaken => $changes{TimeWorked} || 0);
$c = "# ".$s;
if ($changes{Status}) {
my ($status_n, $status_s) = $ticket->SetStatus($changes{'Status'} );
$c .= "\n# ".$status_s;
}

my %v;
foreach my $k (keys %changes) {
if ($k =~ /^$cf_spec/) {
my $key = $1 || $2;

my $cf = $txn->LoadCustomFieldByIdentifier($key);

if (not $cf->id) {
$c .= "\n# Invalid custom field name ($key)";
delete $changes{$k};
next;
}
if ($cf->SingleValue) {
$v{"CustomField-".$cf->Id()} = delete $changes{$k};
} else {
$v{"CustomField-".$cf->Id()} = vsplit(delete $changes{$k});
}
}
}
$txn->UpdateCustomFields(%v);

OUTPUT:

return [ $c, $o, $k, $e ];
Expand Down
31 changes: 31 additions & 0 deletions share/html/REST/1.0/Forms/ticket/history
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,37 @@ if ($tid) {
push @data, [Attachments => $attachlist];
}

# Display custom fields
my $CustomFields = $t->CustomFields;
while (my $cf = $CustomFields->Next()) {
next unless !%$fields
|| exists $fields->{"cf.{".lc($cf->Name)."}"}
|| exists $fields->{"cf-".lc $cf->Name};

my $vals = $t->CustomFieldValues($cf->Id());
my @out = ();
my $count = $vals->Count;
next unless $count;

if ( $count == 1) {
my $v = $vals->First;
push @out, $v->Content if $v;
}
else {
while (my $v = $vals->Next()) {
my $content = $v->Content;
if ( $v->Content =~ /,/ ) {
$content =~ s/([\\'])/\\$1/g;
push @out, q{'} . $content . q{'};
}
else {
push @out, $content;
}
}
}
push @data, [ ('CF.{' . $cf->Name . '}') => join ',', @out ];
}

my %k = map {@$_} @data;
$o = [ map {$_->[0]} @data ];
$k = \%k;
Expand Down
196 changes: 196 additions & 0 deletions t/web/rest-txn-cf.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
use strict;
use warnings;
use RT::Interface::REST;

use RT::Test tests => 37;
use Test::Warn;

my ($baseurl, $m) = RT::Test->started_ok;

my $queue = RT::Test->load_or_create_queue(Name => 'General');
ok($queue->Id, "loaded the General queue");

{
my $cf = RT::Test->load_or_create_txn_custom_field(
Name => 'txn_cf',
Type => 'FreeformSingle',
Queue => $queue,
);
ok($cf->Id, "created a CustomField: txn_cf");
}
{
my $cf = RT::Test->load_or_create_txn_custom_field(
Name => 'txn_cf_multi',
Type => 'FreeformMultiple',
Queue => $queue,
);
ok($cf->Id, "created a CustomField: txn_cf");
}

my $other_queue = RT::Test->load_or_create_queue(Name => 'Other Queue');
ok($other_queue->Id, "loaded the Other Queue queue");

{
my $cf = RT::Test->load_or_create_txn_custom_field(
Name => 'txn_other_queue_cf',
Type => 'FreeformSingle',
Queue => $other_queue,
);
ok($cf->Id, "created a CustomField");
}

$m->post("$baseurl/REST/1.0/ticket/new", [
user => 'root',
pass => 'password',
format => 'l',
]);

my $text = $m->content;
my @lines = $text =~ m{.*}g;
shift @lines; # header

ok($text =~ s/Subject:\s*$/Subject: REST interface/m, "successfully replaced subject");

$m->post("$baseurl/REST/1.0/ticket/edit", [
user => 'root',
pass => 'password',

content => $text,
], Content_Type => 'form-data');

my ($id) = $m->content =~ /Ticket (\d+) created/;
ok($id, "got ticket #$id");

$text = join("\n", ( "Ticket: $id", "Action: correspond", "Content-Type: text/plain" ));
$m->post(
"$baseurl/REST/1.0/ticket/$id/comment",
[
user => 'root',
pass => 'password',
content => "$text\nText: Test with no CF",
],
Content_Type => 'form-data'
);
like($m->content, qr{Correspondence added}, "correspondance added - no CF");

my $with_valid_cf = $text . "\nText: Test with valid CF\nCF.{txn_cf}: valid cf";

$m->post(
"$baseurl/REST/1.0/ticket/$id/comment",
[
user => 'root',
pass => 'password',
content => $with_valid_cf,
],
Content_Type => 'form-data'
);
like($m->content, qr{Correspondence added}, "correspondance added - valid CF");
unlike($m->content, qr{Invalid custom field name}, "no invalid custom field - valid CF");

my $ticket = RT::Ticket->new(RT->SystemUser);
$ticket->Load($id);
is($ticket->Id, $id, "loaded the REST-created ticket");
is($ticket->Subject, "REST interface", "subject successfully set");

my $txn = $ticket->Transactions->Last;
my ($msg, @attachments) = @{$txn->Attachments->ItemsArrayRef};
like($msg->Content, qr/Test with valid CF/, "Transaction contains expected content - valid CF");

is($txn->FirstCustomFieldValue('txn_cf'), "valid cf", "CF successfully set - valid CF");

$m->post(
"$baseurl/REST/1.0/ticket/$id/history",
[
user => 'root',
pass => 'password',
format => 'l',
],
Content_Type => 'form-data'
);

like($m->content, qr/CF.\{txn_cf\}: valid cf/, "Ticket history contains expected content - valid CF");

my $with_nonexistant_cf = $text . "\nText: Test with invalid CF\nCF.{other_cf}: invalid cf";

$m->post(
"$baseurl/REST/1.0/ticket/$id/comment",
[
user => 'root',
pass => 'password',
content => $with_nonexistant_cf,
],
Content_Type => 'form-data'
);
like($m->content, qr{Correspondence added}, "correspondance added - nonexistant CF");
like($m->content, qr{Invalid custom field name}, "invalid custom field - nonexistant CF");

$ticket->Load($id);
is($ticket->Id, $id, "loaded the REST-created ticket");
is($ticket->Subject, "REST interface", "subject successfully set");

$txn = $ticket->Transactions->Last;
($msg, @attachments) = @{$txn->Attachments->ItemsArrayRef};
like($msg->Content, qr/Test with invalid CF/, "Transaction contains expected content - invalid CF");

warning_like {$txn->FirstCustomFieldValue('other_cf')} qr"Couldn't load custom field by 'other_cf' identifier", "CF isn't set - invalid CF";

my $with_other_queue_cf = $text . "\nText: Test with other queue CF\nCF.{txn_other_queue_cf}: invalid cf";

$m->post(
"$baseurl/REST/1.0/ticket/$id/comment",
[
user => 'root',
pass => 'password',
content => $with_other_queue_cf,
],
Content_Type => 'form-data'
);
like($m->content, qr{Correspondence added}, "correspondance added - other queue CF");
like($m->content, qr{Invalid custom field name}, "invalid custom field - other queue CF");

$ticket->Load($id);
is($ticket->Id, $id, "loaded the REST-created ticket");
is($ticket->Subject, "REST interface", "subject successfully set");

$txn = $ticket->Transactions->Last;
($msg, @attachments) = @{$txn->Attachments->ItemsArrayRef};
like($msg->Content, qr/Test with other queue CF/, "Transaction contains expected content - other queue CF");

warning_like {$txn->FirstCustomFieldValue('txn_other_queue_cf')} qr"Couldn't load custom field by 'txn_other_queue_cf' identifier", "CF isn't set - other queue CF";

my $with_valid_cf_multi = $text . "\nText: Test with multi CF\nCF.{txn_cf_multi}: Value 1, Value 2";

$m->post(
"$baseurl/REST/1.0/ticket/$id/comment",
[
user => 'root',
pass => 'password',
content => $with_valid_cf_multi,
],
Content_Type => 'form-data'
);
like($m->content, qr{Correspondence added}, "correspondance added - valid CF multi");
unlike($m->content, qr{Invalid custom field name}, "no invalid custom field - valid CF multi");

$ticket = RT::Ticket->new(RT->SystemUser);
$ticket->Load($id);
is($ticket->Id, $id, "loaded the REST-created ticket - valid CF multi");
is($ticket->Subject, "REST interface", "subject successfully set - valid CF multi");

$txn = $ticket->Transactions->Last;
($msg, @attachments) = @{$txn->Attachments->ItemsArrayRef};
like($msg->Content, qr/Test with multi CF/, "Transaction contains expected content - valid CF multi");

is($txn->FirstCustomFieldValue('txn_cf_multi'), "Value 1", "CF successfully set - valid CF multi");

$m->post(
"$baseurl/REST/1.0/ticket/$id/history",
[
user => 'root',
pass => 'password',
format => 'l',
],
Content_Type => 'form-data'
);

like($m->content, qr/CF.\{txn_cf_multi\}: Value 1,Value 2/, "Ticket history contains expected content - valid CF multi");