diff options
Diffstat (limited to 'extensions/RequestNagger/Extension.pm')
-rw-r--r-- | extensions/RequestNagger/Extension.pm | 552 |
1 files changed, 251 insertions, 301 deletions
diff --git a/extensions/RequestNagger/Extension.pm b/extensions/RequestNagger/Extension.pm index e0f97c9f7..54a11ff5b 100644 --- a/extensions/RequestNagger/Extension.pm +++ b/extensions/RequestNagger/Extension.pm @@ -25,241 +25,239 @@ use DateTime; our $VERSION = '1'; BEGIN { - *Bugzilla::Flag::age = \&_flag_age; - *Bugzilla::Flag::deferred = \&_flag_deferred; - *Bugzilla::Product::nag_interval = \&_product_nag_interval; + *Bugzilla::Flag::age = \&_flag_age; + *Bugzilla::Flag::deferred = \&_flag_deferred; + *Bugzilla::Product::nag_interval = \&_product_nag_interval; } sub _flag_age { - return time_ago(datetime_from($_[0]->modification_date)); + return time_ago(datetime_from($_[0]->modification_date)); } sub _flag_deferred { - my ($self) = @_; - if (!exists $self->{deferred}) { - my $dbh = Bugzilla->dbh; - my ($defer_until) = $dbh->selectrow_array( - "SELECT defer_until FROM nag_defer WHERE flag_id=?", - undef, - $self->id - ); - $self->{deferred} = $defer_until ? datetime_from($defer_until) : undef; - } - return $self->{deferred}; + my ($self) = @_; + if (!exists $self->{deferred}) { + my $dbh = Bugzilla->dbh; + my ($defer_until) + = $dbh->selectrow_array("SELECT defer_until FROM nag_defer WHERE flag_id=?", + undef, $self->id); + $self->{deferred} = $defer_until ? datetime_from($defer_until) : undef; + } + return $self->{deferred}; } sub _product_nag_interval { $_[0]->{nag_interval} } sub object_columns { - my ($self, $args) = @_; - my ($class, $columns) = @$args{qw(class columns)}; - if ($class->isa('Bugzilla::Product')) { - push @$columns, 'nag_interval'; - } + my ($self, $args) = @_; + my ($class, $columns) = @$args{qw(class columns)}; + if ($class->isa('Bugzilla::Product')) { + push @$columns, 'nag_interval'; + } } sub object_update_columns { - my ($self, $args) = @_; - my ($object, $columns) = @$args{qw(object columns)}; - if ($object->isa('Bugzilla::Product')) { - push @$columns, 'nag_interval'; - } + my ($self, $args) = @_; + my ($object, $columns) = @$args{qw(object columns)}; + if ($object->isa('Bugzilla::Product')) { + push @$columns, 'nag_interval'; + } } sub object_before_create { - my ($self, $args) = @_; - my ($class, $params) = @$args{qw(class params)}; - return unless $class->isa('Bugzilla::Product'); - my $input = Bugzilla->input_params; - if (exists $input->{nag_interval}) { - my $interval = _check_nag_interval($input->{nag_interval}); - $params->{nag_interval} = $interval; - } + my ($self, $args) = @_; + my ($class, $params) = @$args{qw(class params)}; + return unless $class->isa('Bugzilla::Product'); + my $input = Bugzilla->input_params; + if (exists $input->{nag_interval}) { + my $interval = _check_nag_interval($input->{nag_interval}); + $params->{nag_interval} = $interval; + } } sub object_end_of_set_all { - my ($self, $args) = @_; - my ($object, $params) = @$args{qw(object params)}; - return unless $object->isa('Bugzilla::Product'); - my $input = Bugzilla->input_params; - if (exists $input->{nag_interval}) { - my $interval = _check_nag_interval($input->{nag_interval}); - $object->set('nag_interval', $interval); - } + my ($self, $args) = @_; + my ($object, $params) = @$args{qw(object params)}; + return unless $object->isa('Bugzilla::Product'); + my $input = Bugzilla->input_params; + if (exists $input->{nag_interval}) { + my $interval = _check_nag_interval($input->{nag_interval}); + $object->set('nag_interval', $interval); + } } sub _check_nag_interval { - my ($value) = @_; - detaint_natural($value) - || ThrowUserError('invalid_parameter', { name => 'request reminding interval', err => 'must be numeric' }); - return $value < 0 ? 0 : $value * 24; + my ($value) = @_; + detaint_natural($value) + || ThrowUserError('invalid_parameter', + {name => 'request reminding interval', err => 'must be numeric'}); + return $value < 0 ? 0 : $value * 24; } sub page_before_template { - my ($self, $args) = @_; - my ($vars, $page) = @$args{qw(vars page_id)}; - return unless $page eq 'request_defer.html'; - - my $user = Bugzilla->login(LOGIN_REQUIRED); - my $input = Bugzilla->input_params; - - # load flag - my $flag_id = scalar($input->{flag}) - || ThrowUserError('request_nagging_flag_invalid'); - detaint_natural($flag_id) - || ThrowUserError('request_nagging_flag_invalid'); - my $flag = Bugzilla::Flag->new({ id => $flag_id, cache => 1 }) - || ThrowUserError('request_nagging_flag_invalid'); - - # you can only defer flags directed at you - $user->can_see_bug($flag->bug->id) - || ThrowUserError("bug_access_denied", { bug_id => $flag->bug->id }); - $flag->status eq '?' - || ThrowUserError('request_nagging_flag_set'); - $flag->requestee - || ThrowUserError('request_nagging_flag_wind'); - $flag->requestee->id == $user->id - || ThrowUserError('request_nagging_flag_not_owned'); - - my $date = DateTime->now()->truncate(to => 'day'); - my $defer_until; - if ($input->{'defer-until'} - && $input->{'defer-until'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)$/) - { - $defer_until = DateTime->new(year => $1, month => $2, day => $3); - if ($defer_until > $date->clone->add(days => 7)) { - $defer_until = undef; - } + my ($self, $args) = @_; + my ($vars, $page) = @$args{qw(vars page_id)}; + return unless $page eq 'request_defer.html'; + + my $user = Bugzilla->login(LOGIN_REQUIRED); + my $input = Bugzilla->input_params; + + # load flag + my $flag_id + = scalar($input->{flag}) || ThrowUserError('request_nagging_flag_invalid'); + detaint_natural($flag_id) || ThrowUserError('request_nagging_flag_invalid'); + my $flag = Bugzilla::Flag->new({id => $flag_id, cache => 1}) + || ThrowUserError('request_nagging_flag_invalid'); + + # you can only defer flags directed at you + $user->can_see_bug($flag->bug->id) + || ThrowUserError("bug_access_denied", {bug_id => $flag->bug->id}); + $flag->status eq '?' || ThrowUserError('request_nagging_flag_set'); + $flag->requestee || ThrowUserError('request_nagging_flag_wind'); + $flag->requestee->id == $user->id + || ThrowUserError('request_nagging_flag_not_owned'); + + my $date = DateTime->now()->truncate(to => 'day'); + my $defer_until; + if ( $input->{'defer-until'} + && $input->{'defer-until'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)$/) + { + $defer_until = DateTime->new(year => $1, month => $2, day => $3); + if ($defer_until > $date->clone->add(days => 7)) { + $defer_until = undef; } - - if ($input->{save} && $defer_until) { - $self->_defer_until($flag_id, $defer_until); - $vars->{saved} = "1"; - $vars->{defer_until} = $defer_until; - } - else { - my @dates; - foreach my $i (1..7) { - $date->add(days => 1); - unshift @dates, { days => $i, date => $date->clone }; - } - $vars->{defer_until} = \@dates; + } + + if ($input->{save} && $defer_until) { + $self->_defer_until($flag_id, $defer_until); + $vars->{saved} = "1"; + $vars->{defer_until} = $defer_until; + } + else { + my @dates; + foreach my $i (1 .. 7) { + $date->add(days => 1); + unshift @dates, {days => $i, date => $date->clone}; } + $vars->{defer_until} = \@dates; + } - $vars->{flag} = $flag; + $vars->{flag} = $flag; } sub _defer_until { - my ($self, $flag_id, $defer_until) = @_; - my $dbh = Bugzilla->dbh; - - $dbh->bz_start_transaction(); - - my ($defer_id) = $dbh->selectrow_array("SELECT id FROM nag_defer WHERE flag_id=?", undef, $flag_id); - if ($defer_id) { - $dbh->do("UPDATE nag_defer SET defer_until=? WHERE id=?", undef, $defer_until->ymd, $flag_id); - } else { - $dbh->do("INSERT INTO nag_defer(flag_id, defer_until) VALUES (?, ?)", undef, $flag_id, $defer_until->ymd); - } - - $dbh->bz_commit_transaction(); + my ($self, $flag_id, $defer_until) = @_; + my $dbh = Bugzilla->dbh; + + $dbh->bz_start_transaction(); + + my ($defer_id) + = $dbh->selectrow_array("SELECT id FROM nag_defer WHERE flag_id=?", + undef, $flag_id); + if ($defer_id) { + $dbh->do("UPDATE nag_defer SET defer_until=? WHERE id=?", + undef, $defer_until->ymd, $flag_id); + } + else { + $dbh->do("INSERT INTO nag_defer(flag_id, defer_until) VALUES (?, ?)", + undef, $flag_id, $defer_until->ymd); + } + + $dbh->bz_commit_transaction(); } sub object_end_of_update { - my ($self, $args) = @_; - if ($args->{object}->isa("Bugzilla::Flag") && exists $args->{changes}) { - # any change to the flag (setting, clearing, or retargetting) will clear the deferals - my $flag = $args->{object}; - Bugzilla->dbh->do("DELETE FROM nag_defer WHERE flag_id=?", undef, $flag->id); - } + my ($self, $args) = @_; + if ($args->{object}->isa("Bugzilla::Flag") && exists $args->{changes}) { + +# any change to the flag (setting, clearing, or retargetting) will clear the deferals + my $flag = $args->{object}; + Bugzilla->dbh->do("DELETE FROM nag_defer WHERE flag_id=?", undef, $flag->id); + } } sub user_preferences { - my ($self, $args) = @_; - my $tab = $args->{'current_tab'}; - return unless $tab eq 'request_nagging'; - - my $save = $args->{'save_changes'}; - my $vars = $args->{'vars'}; - my $user = Bugzilla->user; - my $dbh = Bugzilla->dbh; - - my %watching = - map { $_ => 1 } - @{ $dbh->selectcol_arrayref( - "SELECT profiles.login_name + my ($self, $args) = @_; + my $tab = $args->{'current_tab'}; + return unless $tab eq 'request_nagging'; + + my $save = $args->{'save_changes'}; + my $vars = $args->{'vars'}; + my $user = Bugzilla->user; + my $dbh = Bugzilla->dbh; + + my %watching = map { $_ => 1 } @{ + $dbh->selectcol_arrayref( + "SELECT profiles.login_name FROM nag_watch INNER JOIN profiles ON nag_watch.nagged_id = profiles.userid WHERE nag_watch.watcher_id = ? - ORDER BY profiles.login_name", - undef, - $user->id - ) }; - - my $nag_settings = Bugzilla::Extension::RequestNagger::Settings->new($user->id); - - if ($save) { - my $input = Bugzilla->input_params; - Bugzilla::User::match_field({ 'add_watching' => {'type' => 'multi'} }); - - $dbh->bz_start_transaction(); - - # user preference - if (my $value = $input->{request_nagging}) { - my $settings = $user->settings; - my $setting = new Bugzilla::User::Setting('request_nagging'); - if ($value eq 'default') { - $settings->{request_nagging}->reset_to_default; - } - else { - $setting->validate_value($value); - $settings->{request_nagging}->set($value); - } - } - - # watching - if ($input->{remove_watched_users}) { - my $del_watching = ref($input->{del_watching}) ? $input->{del_watching} : [ $input->{del_watching} ]; - foreach my $login (@$del_watching) { - my $u = Bugzilla::User->new({ name => $login, cache => 1 }) - || next; - next unless exists $watching{$u->login}; - $dbh->do( - "DELETE FROM nag_watch WHERE watcher_id=? AND nagged_id=?", - undef, - $user->id, $u->id - ); - delete $watching{$u->login}; - } - } - if ($input->{add_watching}) { - my $add_watching = ref($input->{add_watching}) ? $input->{add_watching} : [ $input->{add_watching} ]; - foreach my $login (@$add_watching) { - my $u = Bugzilla::User->new({ name => $login, cache => 1 }) - || next; - next if exists $watching{$u->login}; - $dbh->do( - "INSERT INTO nag_watch(watcher_id, nagged_id) VALUES(?, ?)", - undef, - $user->id, $u->id - ); - $watching{$u->login} = 1; - } - } - - # watching settings - foreach my $field (Bugzilla::Extension::RequestNagger::Settings::FIELDS()) { - $nag_settings->set($field, $input->{$field}); - } - - $dbh->bz_commit_transaction(); + ORDER BY profiles.login_name", undef, $user->id + ) + }; + + my $nag_settings = Bugzilla::Extension::RequestNagger::Settings->new($user->id); + + if ($save) { + my $input = Bugzilla->input_params; + Bugzilla::User::match_field({'add_watching' => {'type' => 'multi'}}); + + $dbh->bz_start_transaction(); + + # user preference + if (my $value = $input->{request_nagging}) { + my $settings = $user->settings; + my $setting = new Bugzilla::User::Setting('request_nagging'); + if ($value eq 'default') { + $settings->{request_nagging}->reset_to_default; + } + else { + $setting->validate_value($value); + $settings->{request_nagging}->set($value); + } } - $vars->{watching} = [ sort keys %watching ]; - $vars->{settings} = $nag_settings; + # watching + if ($input->{remove_watched_users}) { + my $del_watching + = ref($input->{del_watching}) + ? $input->{del_watching} + : [$input->{del_watching}]; + foreach my $login (@$del_watching) { + my $u = Bugzilla::User->new({name => $login, cache => 1}) || next; + next unless exists $watching{$u->login}; + $dbh->do("DELETE FROM nag_watch WHERE watcher_id=? AND nagged_id=?", + undef, $user->id, $u->id); + delete $watching{$u->login}; + } + } + if ($input->{add_watching}) { + my $add_watching + = ref($input->{add_watching}) + ? $input->{add_watching} + : [$input->{add_watching}]; + foreach my $login (@$add_watching) { + my $u = Bugzilla::User->new({name => $login, cache => 1}) || next; + next if exists $watching{$u->login}; + $dbh->do("INSERT INTO nag_watch(watcher_id, nagged_id) VALUES(?, ?)", + undef, $user->id, $u->id); + $watching{$u->login} = 1; + } + } + + # watching settings + foreach my $field (Bugzilla::Extension::RequestNagger::Settings::FIELDS()) { + $nag_settings->set($field, $input->{$field}); + } - my $handled = $args->{'handled'}; - $$handled = 1; + $dbh->bz_commit_transaction(); + } + + $vars->{watching} = [sort keys %watching]; + $vars->{settings} = $nag_settings; + + my $handled = $args->{'handled'}; + $$handled = 1; } # @@ -267,125 +265,77 @@ sub user_preferences { # sub db_schema_abstract_schema { - my ($self, $args) = @_; - $args->{'schema'}->{'nag_watch'} = { - FIELDS => [ - id => { - TYPE => 'MEDIUMSERIAL', - NOTNULL => 1, - PRIMARYKEY => 1, - }, - nagged_id => { - TYPE => 'INT3', - NOTNULL => 1, - REFERENCES => { - TABLE => 'profiles', - COLUMN => 'userid', - DELETE => 'CASCADE', - } - }, - watcher_id => { - TYPE => 'INT3', - NOTNULL => 1, - REFERENCES => { - TABLE => 'profiles', - COLUMN => 'userid', - DELETE => 'CASCADE', - } - }, - ], - INDEXES => [ - nag_watch_idx => { - FIELDS => [ 'nagged_id', 'watcher_id' ], - TYPE => 'UNIQUE', - }, - ], - }; - $args->{'schema'}->{'nag_defer'} = { - FIELDS => [ - id => { - TYPE => 'MEDIUMSERIAL', - NOTNULL => 1, - PRIMARYKEY => 1, - }, - flag_id => { - TYPE => 'INT3', - NOTNULL => 1, - REFERENCES => { - TABLE => 'flags', - COLUMN => 'id', - DELETE => 'CASCADE', - } - }, - defer_until => { - TYPE => 'DATETIME', - NOTNULL => 1, - }, - ], - INDEXES => [ - nag_defer_idx => { - FIELDS => [ 'flag_id' ], - TYPE => 'UNIQUE', - }, - ], - }; - $args->{'schema'}->{'nag_settings'} = { - FIELDS => [ - id => { - TYPE => 'MEDIUMSERIAL', - NOTNULL => 1, - PRIMARYKEY => 1, - }, - user_id => { - TYPE => 'INT3', - NOTNULL => 1, - REFERENCES => { - TABLE => 'profiles', - COLUMN => 'userid', - DELETE => 'CASCADE', - } - }, - setting_name => { - TYPE => 'VARCHAR(16)', - NOTNULL => 1, - }, - setting_value => { - TYPE => 'VARCHAR(16)', - NOTNULL => 1, - }, - ], - INDEXES => [ - nag_setting_idx => { - FIELDS => [ 'user_id', 'setting_name' ], - TYPE => 'UNIQUE', - }, - ], - }; + my ($self, $args) = @_; + $args->{'schema'}->{'nag_watch'} = { + FIELDS => [ + id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1,}, + nagged_id => { + TYPE => 'INT3', + NOTNULL => 1, + REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE',} + }, + watcher_id => { + TYPE => 'INT3', + NOTNULL => 1, + REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE',} + }, + ], + INDEXES => [ + nag_watch_idx => {FIELDS => ['nagged_id', 'watcher_id'], TYPE => 'UNIQUE',}, + ], + }; + $args->{'schema'}->{'nag_defer'} = { + FIELDS => [ + id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1,}, + flag_id => { + TYPE => 'INT3', + NOTNULL => 1, + REFERENCES => {TABLE => 'flags', COLUMN => 'id', DELETE => 'CASCADE',} + }, + defer_until => {TYPE => 'DATETIME', NOTNULL => 1,}, + ], + INDEXES => [nag_defer_idx => {FIELDS => ['flag_id'], TYPE => 'UNIQUE',},], + }; + $args->{'schema'}->{'nag_settings'} = { + FIELDS => [ + id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1,}, + user_id => { + TYPE => 'INT3', + NOTNULL => 1, + REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE',} + }, + setting_name => {TYPE => 'VARCHAR(16)', NOTNULL => 1,}, + setting_value => {TYPE => 'VARCHAR(16)', NOTNULL => 1,}, + ], + INDEXES => [ + nag_setting_idx => {FIELDS => ['user_id', 'setting_name'], TYPE => 'UNIQUE',}, + ], + }; } sub install_update_db { - my $dbh = Bugzilla->dbh; - $dbh->bz_add_column('products', 'nag_interval', { TYPE => 'INT2', NOTNULL => 1, DEFAULT => 7 * 24 }); + my $dbh = Bugzilla->dbh; + $dbh->bz_add_column('products', 'nag_interval', + {TYPE => 'INT2', NOTNULL => 1, DEFAULT => 7 * 24}); } sub install_filesystem { - my ($self, $args) = @_; - my $files = $args->{'files'}; - my $extensions_dir = bz_locations()->{'extensionsdir'}; - my $script_name = $extensions_dir . "/" . __PACKAGE__->NAME . "/bin/send-request-nags.pl"; - $files->{$script_name} = { - perms => Bugzilla::Install::Filesystem::WS_EXECUTE - }; + my ($self, $args) = @_; + my $files = $args->{'files'}; + my $extensions_dir = bz_locations()->{'extensionsdir'}; + my $script_name + = $extensions_dir . "/" . __PACKAGE__->NAME . "/bin/send-request-nags.pl"; + $files->{$script_name} = {perms => Bugzilla::Install::Filesystem::WS_EXECUTE}; } sub install_before_final_checks { - my ($self, $args) = @_; - add_setting({ - name => 'request_nagging', - options => ['on', 'off'], - default => 'on', - category => 'Reviews and Needinfo' - }); + my ($self, $args) = @_; + add_setting({ + name => 'request_nagging', + options => ['on', 'off'], + default => 'on', + category => 'Reviews and Needinfo' + }); } __PACKAGE__->NAME; |