From 8738a27c2ff267266e3f4db17e71305c6840fa42 Mon Sep 17 00:00:00 2001 From: Date: Thu, 6 Mar 2014 15:13:11 +0800 Subject: Bug 956229: develop a system to track the lifetime of review/feedback/needinfo requests --- extensions/Review/lib/FlagStateActivity.pm | 122 +++++++++++++++++++++++++++++ extensions/Review/lib/WebService.pm | 70 ++++++++++++++++- 2 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 extensions/Review/lib/FlagStateActivity.pm (limited to 'extensions/Review/lib') 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 -- cgit v1.2.3-24-g4f1b