summaryrefslogtreecommitdiffstats
path: root/extensions/ContributorEngagement
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/ContributorEngagement')
-rw-r--r--extensions/ContributorEngagement/Config.pm19
-rw-r--r--extensions/ContributorEngagement/Extension.pm134
-rw-r--r--extensions/ContributorEngagement/lib/Constants.pm36
-rw-r--r--extensions/ContributorEngagement/template/en/default/contributor/email.txt.tmpl46
4 files changed, 235 insertions, 0 deletions
diff --git a/extensions/ContributorEngagement/Config.pm b/extensions/ContributorEngagement/Config.pm
new file mode 100644
index 000000000..3984dd60e
--- /dev/null
+++ b/extensions/ContributorEngagement/Config.pm
@@ -0,0 +1,19 @@
+# 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 strict;
+
+use constant NAME => 'ContributorEngagement';
+
+use constant REQUIRED_MODULES => [
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/ContributorEngagement/Extension.pm b/extensions/ContributorEngagement/Extension.pm
new file mode 100644
index 000000000..7e7031b33
--- /dev/null
+++ b/extensions/ContributorEngagement/Extension.pm
@@ -0,0 +1,134 @@
+# 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 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 = '1.0';
+
+BEGIN {
+ *Bugzilla::User::first_patch_approved_id = \&_first_patch_approved_id;
+}
+
+sub _first_patch_approved_id { return $_[0]->{'first_patch_approved_id'}; }
+
+sub install_update_db {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ if (!$dbh->bz_column_info('profiles', 'first_patch_approved_id')) {
+ $dbh->bz_add_column('profiles', 'first_patch_approved_id',
+ { TYPE => 'INT3' });
+ _migrate_first_approved_ids();
+ }
+}
+
+sub _migrate_first_approved_ids {
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare('UPDATE profiles SET first_patch_approved_id = ? WHERE userid = ?');
+ my $ra = $dbh->selectall_arrayref("SELECT attachments.submitter_id,
+ attachments.attach_id,
+ flagtypes.name
+ FROM attachments
+ INNER JOIN flags ON attachments.attach_id = flags.attach_id
+ INNER JOIN flagtypes ON flags.type_id = flagtypes.id
+ WHERE 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, $flag_name) = @$ra_row;
+ next if $user_seen{$user_id};
+ my $found_flag = 0;
+ foreach my $flag_re (FLAG_REGEXES) {
+ $found_flag = 1 if ($flag_name =~ $flag_re);
+ }
+ next if !$found_flag;
+ indicate_progress({ current => $count++, total => $total, every => 25 });
+ $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')) {
+ push(@$columns, 'first_patch_approved_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
+ && grep($_ eq $object->bug->product, ENABLED_PRODUCTS)
+ && !$object->attacher->first_patch_approved_id)
+ {
+ my $attachment = $object;
+
+ # Glob: Borrowed this code from your push extension :)
+ foreach my $change (@$new_flags) {
+ $change =~ s/^[^:]+://; # get rid of setter
+ $change =~ s/\([^\)]+\)$//; # get rid of requestee
+ my ($name, $value) = $change =~ /^(.+)(.)$/;
+
+ # Only interested in flags set to +
+ next if $value ne '+';
+
+ my $found_flag = 0;
+ foreach my $flag_re (FLAG_REGEXES) {
+ $found_flag = 1 if ($name =~ $flag_re);
+ }
+ next if !$found_flag;
+
+ _send_approval_mail($attachment, $timestamp);
+
+ last;
+ }
+ }
+}
+
+sub _send_approval_mail {
+ my ($attachment, $timestamp) = @_;
+
+ my $vars = {
+ date => format_time($timestamp, '%a, %d %b %Y %T %z', 'UTC'),
+ to_user => $attachment->attacher->email,
+ 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);
+
+ # Make sure we don't do this again
+ Bugzilla->dbh->do("UPDATE profiles SET first_patch_approved_id = ? WHERE userid = ?",
+ undef, $attachment->id, $attachment->attacher->id);
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/ContributorEngagement/lib/Constants.pm b/extensions/ContributorEngagement/lib/Constants.pm
new file mode 100644
index 000000000..851c0dbc2
--- /dev/null
+++ b/extensions/ContributorEngagement/lib/Constants.pm
@@ -0,0 +1,36 @@
+# 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::Constants;
+
+use strict;
+
+use base qw(Exporter);
+
+our @EXPORT = qw(
+ EMAIL_FROM
+ ENABLED_PRODUCTS
+ FLAG_REGEXES
+);
+
+use constant EMAIL_FROM => 'bugzilla-daemon@mozilla.org';
+
+use constant ENABLED_PRODUCTS => (
+ "Core",
+ "Firefox for Android",
+ "Firefox",
+ "Testing",
+ "Toolkit",
+ "Mozilla Services",
+ "TestProduct",
+);
+
+use constant FLAG_REGEXES => (
+ qr/^approval/
+);
+
+1;
diff --git a/extensions/ContributorEngagement/template/en/default/contributor/email.txt.tmpl b/extensions/ContributorEngagement/template/en/default/contributor/email.txt.tmpl
new file mode 100644
index 000000000..b403a4bfb
--- /dev/null
+++ b/extensions/ContributorEngagement/template/en/default/contributor/email.txt.tmpl
@@ -0,0 +1,46 @@
+[%# 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.
+ #%]
+[% PROCESS "global/variables.none.tmpl" %]
+From: [% from_user FILTER none %]
+To: [% to_user FILTER none %]
+Subject: Congratulations on having your first patch approved
+Date: [% date FILTER none %]
+
+Congratulations on having your first patch approved, and thank you
+for your contribution to Mozilla.
+
+The next step is to get the patch actually checked in to our repository.
+For more information about how to make that happen, check out this post:
+
+https://developer.mozilla.org/en/Creating_a_patch_that_can_be_checked_in
+
+While you are going through those final steps, if you're looking for a
+new project to take on, have a look at our list of 'mentored' [% terms.bugs %] ([% terms.bugs %] where
+someone is specifically available to help you):
+
+https://bugzil.la/sw:mentor
+
+Alternatively, you could join us on our IRC chat server in the #introduction
+channel and ask for suggestions about what would be a good [% terms.bugs %] to work on.
+There's more about using our chat server at:
+
+http://irc.mozilla.org/
+
+If you haven't done so already, this is also a good time to sign up to the
+Mozilla Contributor Directory and create a profile for yourself. Doing this
+will give you access to community members' profiles so you can reach out and
+connect with other Mozillians. You will need someone to 'vouch for' your
+profile; if you don't know any other Mozillians well, why not contact the
+person who approved your patch?
+
+The directory is here:
+
+https://mozillians.org/
+
+Thanks again for your help :-)
+Josh, Kyle, Dietrich and Brian; Coding Stewards