summaryrefslogtreecommitdiffstats
path: root/extensions/Review/lib
diff options
context:
space:
mode:
author <Dylan>2014-03-06 08:13:11 +0100
committerByron Jones <bjones@mozilla.com>2014-03-06 08:13:11 +0100
commit8738a27c2ff267266e3f4db17e71305c6840fa42 (patch)
tree41d6ad668f1a04df29e22132d58d0199f55fc2d1 /extensions/Review/lib
parent51539e843226f3a85776159d2cb68ce2cc192d24 (diff)
downloadbugzilla-8738a27c2ff267266e3f4db17e71305c6840fa42.tar.gz
bugzilla-8738a27c2ff267266e3f4db17e71305c6840fa42.tar.xz
Bug 956229: develop a system to track the lifetime of review/feedback/needinfo requests
Diffstat (limited to 'extensions/Review/lib')
-rw-r--r--extensions/Review/lib/FlagStateActivity.pm122
-rw-r--r--extensions/Review/lib/WebService.pm70
2 files changed, 190 insertions, 2 deletions
diff --git a/extensions/Review/lib/FlagStateActivity.pm b/extensions/Review/lib/FlagStateActivity.pm
new file mode 100644
index 000000000..46e9300a5
--- /dev/null
+++ b/extensions/Review/lib/FlagStateActivity.pm
@@ -0,0 +1,122 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Review::FlagStateActivity;
+use strict;
+use warnings;
+
+use Bugzilla::Error qw(ThrowUserError);
+use Bugzilla::Util qw(trim datetime_from);
+use List::MoreUtils qw(none);
+
+use base qw( Bugzilla::Object );
+
+use constant DB_TABLE => 'flag_state_activity';
+use constant LIST_ORDER => 'id';
+use constant AUDIT_CREATES => 0;
+use constant AUDIT_UPDATES => 0;
+use constant AUDIT_REMOVES => 0;
+
+use constant DB_COLUMNS => qw(
+ id
+ flag_when
+ type_id
+ flag_id
+ setter_id
+ requestee_id
+ bug_id
+ attachment_id
+ status
+);
+
+
+sub _check_param_required {
+ my ($param) = @_;
+
+ return sub {
+ my ($invocant, $value) = @_;
+ $value = trim($value)
+ or ThrowCodeError('param_required', {param => $param});
+ return $value;
+ },
+}
+
+sub _check_date {
+ my ($invocant, $date) = @_;
+
+ $date = trim($date);
+ datetime_from($date)
+ or ThrowUserError('illegal_date', { date => $date,
+ format => 'YYYY-MM-DD HH24:MI:SS' });
+ return $date;
+}
+
+sub _check_status {
+ my ($self, $status) = @_;
+
+ # - Make sure the status is valid.
+ # - Make sure the user didn't request the flag unless it's requestable.
+ # If the flag existed and was requested before it became unrequestable,
+ # leave it as is.
+ if (none { $status eq $_ } qw( X + - ? )) {
+ ThrowUserError(
+ 'flag_status_invalid',
+ {
+ id => $self->id,
+ status => $status
+ }
+ );
+ }
+ return $status;
+}
+
+use constant VALIDATORS => {
+ flag_when => \&_check_date,
+ type_id => _check_param_required('type_id'),
+ flag_id => _check_param_required('flag_id'),
+ setter_id => _check_param_required('setter_id'),
+ bug_id => _check_param_required('bug_id'),
+ status => \&_check_status,
+};
+
+sub flag_when { return $_[0]->{flag_when} }
+sub type_id { return $_[0]->{type_id} }
+sub flag_id { return $_[0]->{flag_id} }
+sub setter_id { return $_[0]->{setter_id} }
+sub bug_id { return $_[0]->{bug_id} }
+sub requestee_id { return $_[0]->{requestee_id} }
+sub attachment_id { return $_[0]->{attachment_id} }
+sub status { return $_[0]->{status} }
+
+sub type {
+ my ($self) = @_;
+ return $self->{type} //= Bugzilla::FlagType->new({ id => $self->type_id, cache => 1 });
+}
+
+sub setter {
+ my ($self) = @_;
+ return $self->{setter} //= Bugzilla::User->new({ id => $self->setter_id, cache => 1 });
+}
+
+sub requestee {
+ my ($self) = @_;
+ return undef unless defined $self->requestee_id;
+ return $self->{requestee} //= Bugzilla::User->new({ id => $self->requestee_id, cache => 1 });
+}
+
+sub bug {
+ my ($self) = @_;
+ return $self->{bug} //= Bugzilla::Bug->new({ id => $self->bug_id, cache => 1 });
+}
+
+sub attachment {
+ my ($self) = @_;
+ return $self->{attachment} //=
+ Bugzilla::Attachment->new({ id => $self->attachment_id, cache => 1 });
+}
+
+1;
diff --git a/extensions/Review/lib/WebService.pm b/extensions/Review/lib/WebService.pm
index 4cb3d48d8..17ab51864 100644
--- a/extensions/Review/lib/WebService.pm
+++ b/extensions/Review/lib/WebService.pm
@@ -15,6 +15,8 @@ use base qw(Bugzilla::WebService);
use Bugzilla::Bug;
use Bugzilla::Component;
use Bugzilla::Error;
+use Bugzilla::Util qw(detaint_natural);
+use Bugzilla::WebService::Util 'filter';
sub suggestions {
my ($self, $params) = @_;
@@ -69,6 +71,20 @@ sub suggestions {
return \@result;
}
+sub flag_activity {
+ my ( $self, $params ) = @_;
+ my $dbh = Bugzilla->switch_to_shadow_db();
+
+ my $flag_id = $params->{flag_id};
+
+ detaint_natural($flag_id)
+ or ThrowUserError('invalid_flag_id', { flag_id => $flag_id });
+
+ my $matches = Bugzilla::Extension::Review::FlagStateActivity->match({flag_id => $flag_id});
+ my @results = map { $self->_flag_state_activity_to_hash($_, $params) } @$matches;
+ return \@results;
+}
+
sub rest_resources {
return [
# bug-id
@@ -104,11 +120,61 @@ sub rest_resources {
method => 'suggestions',
},
},
+ # flag activity by flag id
+ qr{^/review/flag_activity/(\d+)$}, {
+ GET => {
+ method => 'flag_activity',
+ params => sub {
+ return {flag_id => $_[0]}
+ },
+ },
+ },
];
-};
+}
-1;
+sub _flag_state_activity_to_hash {
+ my ($self, $fsa, $params) = @_;
+
+ my %flag = (
+ creation_time => $self->type('string', $fsa->flag_when),
+ type => $self->_flagtype_to_hash($fsa->type),
+ setter => $self->_user_to_hash($fsa->setter),
+ bug_id => $self->type('int', $fsa->bug_id),
+ attachment_id => $self->type('int', $fsa->attachment_id),
+ status => $self->type('string', $fsa->status),
+ );
+
+ $flag{requestee} = $self->_user_to_hash($fsa->requestee) if $fsa->requestee;
+ return filter($params, \%flag);
+}
+
+sub _flagtype_to_hash {
+ my ($self, $flagtype) = @_;
+ my $user = Bugzilla->user;
+
+ return {
+ id => $self->type('int', $flagtype->id),
+ name => $self->type('string', $flagtype->name),
+ description => $self->type('string', $flagtype->description),
+ type => $self->type('string', $flagtype->target_type),
+ is_active => $self->type('boolean', $flagtype->is_active),
+ is_requesteeble => $self->type('boolean', $flagtype->is_requesteeble),
+ is_multiplicable => $self->type('boolean', $flagtype->is_multiplicable),
+ };
+}
+
+sub _user_to_hash {
+ my ($self, $user) = @_;
+
+ return {
+ id => $self->type('int', $user->id),
+ real_name => $self->type('string', $user->name),
+ name => $self->type('email', $user->login),
+ };
+}
+
+1;
__END__
=head1 NAME