# 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::ContributorEngagement; use 5.10.1; use strict; use warnings; use base qw(Bugzilla::Extension); use Bugzilla::User; use Bugzilla::Util qw(format_time); use Bugzilla::Mailer; use Bugzilla::Install::Util qw(indicate_progress); use Bugzilla::Extension::ContributorEngagement::Constants; our $VERSION = '2.0'; BEGIN { *Bugzilla::User::first_patch_reviewed_id = \&_first_patch_reviewed_id; } sub _first_patch_reviewed_id { return $_[0]->{'first_patch_reviewed_id'}; } sub install_update_db { my ($self) = @_; my $dbh = Bugzilla->dbh; if ($dbh->bz_column_info('profiles', 'first_patch_approved_id')) { $dbh->bz_drop_column('profiles', 'first_patch_approved_id'); } if (!$dbh->bz_column_info('profiles', 'first_patch_reviewed_id')) { $dbh->bz_add_column('profiles', 'first_patch_reviewed_id', { TYPE => 'INT3' }); _populate_first_reviewed_ids(); } } sub _populate_first_reviewed_ids { my $dbh = Bugzilla->dbh; my $sth = $dbh->prepare('UPDATE profiles SET first_patch_reviewed_id = ? WHERE userid = ?'); my $ra = $dbh->selectall_arrayref("SELECT attachments.submitter_id, attachments.attach_id FROM attachments INNER JOIN flags ON attachments.attach_id = flags.attach_id INNER JOIN flagtypes ON flags.type_id = flagtypes.id WHERE flagtypes.name LIKE 'review%' AND flags.status = '+' ORDER BY flags.modification_date"); my $count = 1; my $total = scalar @$ra; my %user_seen; foreach my $ra_row (@$ra) { my ($user_id, $attach_id) = @$ra_row; indicate_progress({ current => $count++, total => $total, every => 25 }); next if $user_seen{$user_id}; $sth->execute($attach_id, $user_id); $user_seen{$user_id} = 1; } print "done\n"; } sub object_columns { my ($self, $args) = @_; my ($class, $columns) = @$args{qw(class columns)}; if ($class->isa('Bugzilla::User')) { my $dbh = Bugzilla->dbh; if ($dbh->bz_column_info($class->DB_TABLE, 'first_patch_reviewed_id')) { push @$columns, 'first_patch_reviewed_id'; } } } sub flag_end_of_update { my ($self, $args) = @_; my ($object, $timestamp, $new_flags) = @$args{qw(object timestamp new_flags)}; if ($object->isa('Bugzilla::Attachment') && @$new_flags && !$object->attacher->first_patch_reviewed_id && grep($_ eq $object->bug->product, ENABLED_PRODUCTS)) { my $attachment = $object; foreach my $orig_change (@$new_flags) { my $change = $orig_change; $change =~ s/^[^:]+://; # get rid of setter $change =~ s/\([^\)]+\)$//; # get rid of requestee my ($name, $value) = $change =~ /^(.+)(.)$/; # Only interested in review flags set to + next unless $name =~ /^review/ && $value eq '+'; _send_mail($attachment, $timestamp); Bugzilla->dbh->do("UPDATE profiles SET first_patch_reviewed_id = ? WHERE userid = ?", undef, $attachment->id, $attachment->attacher->id); Bugzilla->memcached->clear({ table => 'profiles', id => $attachment->attacher->id }); last; } } } sub _send_mail { my ($attachment, $timestamp) = @_; my $vars = { date => format_time($timestamp, '%a, %d %b %Y %T %z', 'UTC'), attachment => $attachment, from_user => EMAIL_FROM, }; my $msg; my $template = Bugzilla->template_inner($attachment->attacher->setting('lang')); $template->process("contributor/email.txt.tmpl", $vars, \$msg) || ThrowTemplateError($template->error()); MessageToMTA($msg); } __PACKAGE__->NAME;