aboutsummaryrefslogtreecommitdiffstats
path: root/extensions/Mageia/Extension.pm
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/Mageia/Extension.pm')
-rw-r--r--extensions/Mageia/Extension.pm200
1 files changed, 200 insertions, 0 deletions
diff --git a/extensions/Mageia/Extension.pm b/extensions/Mageia/Extension.pm
new file mode 100644
index 000000000..c2f8466e7
--- /dev/null
+++ b/extensions/Mageia/Extension.pm
@@ -0,0 +1,200 @@
+# 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::Mageia;
+
+use 5.16.0;
+use strict;
+use warnings;
+
+use parent qw(Bugzilla::Extension);
+
+use Bugzilla::Constants qw(EVT_CC REL_GLOBAL_WATCHER);
+use Bugzilla::Bug qw(LogActivityEntry);
+use Bugzilla::Field qw(get_field_id);
+use Bugzilla::User qw();
+use Bugzilla::User::Setting qw(add_setting);
+use Bugzilla::Extension::Mageia::Util qw(compare_datetimes sync_ldap_groups_check);
+
+use Email::Address;
+
+# Let's match the Bugzilla version it's written for.
+our $VERSION = '5.0';
+
+# sysadmin-bugs@ml.mageia.org user ID = 175.
+use constant SYSADMIN_USER_ID => 175;
+
+use constant MGA_SETTINGS => {
+ mga_inline_history => { options => ['on', 'off'], default => 'on' },
+};
+
+sub bug_end_of_create_validators {
+ my ($self, $args) = @_;
+
+ # If a user enters 'validated_update' or 'validated_backport' as keyword,
+ # automatically CC sysadmin-bugs@ml.mageia.org.
+ my $keywords = $args->{params}->{keywords};
+
+ if (grep { $_->name =~ /^validated_(?:update|backport)$/ } @$keywords) {
+ my $cc_list = $args->{params}->{cc};
+ if (!grep { $_ == SYSADMIN_USER_ID } @$cc_list) {
+ push(@$cc_list, SYSADMIN_USER_ID);
+ }
+ }
+}
+
+sub bug_end_of_update {
+ my ($self, $args) = @_;
+ my $bug = $args->{bug};
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
+
+ my $new_keywords_str;
+ # Call exists to avoid autovivification of $args->{changes} if it does not exist.
+ # Else $bug->update() always sees the bug as being edited.
+ if (exists $args->{changes} && exists $args->{changes}->{keywords}) {
+ $new_keywords_str = $args->{changes}->{keywords}->[1];
+ }
+
+ # If a user enters 'validated_update' or 'validated_backport' as keyword,
+ # automatically CC sysadmin-bugs@ml.mageia.org.
+ if ($new_keywords_str) {
+ my @new_keywords = split(/[,\s]+/, $new_keywords_str);
+ if (grep { $_ =~ /^validated_(?:update|backport)$/ } @new_keywords
+ and !grep { $_->id == SYSADMIN_USER_ID } @{$bug->cc_users})
+ {
+ # Safer to clear the cache and let Bugzilla regenerate them if needed.
+ delete $bug->{cc_users};
+ delete $bug->{cc};
+ $dbh->do('INSERT INTO cc (bug_id, who) VALUES (?, ?)',
+ undef, ($bug->id, SYSADMIN_USER_ID));
+
+ # We also have to update the bug history to reflect this change.
+ my $changed_cc = $args->{changes}->{cc};
+ my $sysadmin_login = Bugzilla::User->new(SYSADMIN_USER_ID)->login;
+
+ if ($changed_cc->[1]) {
+ $changed_cc->[1] .= ", $sysadmin_login";
+ }
+ else {
+ $changed_cc->[1] = $sysadmin_login;
+ }
+
+ my $field_id = get_field_id('cc');
+ $dbh->do('DELETE FROM bugs_activity
+ WHERE bug_id = ? AND bug_when = ? AND fieldid = ?',
+ undef, ($bug->id, $args->{timestamp}, $field_id));
+
+ LogActivityEntry($bug->id, 'cc', $changed_cc->[0] // '', $changed_cc->[1],
+ $user->id, $args->{timestamp});
+ }
+ }
+}
+
+sub bug_format_comment {
+ my ($self, $args) = @_;
+ my $regexes = $args->{'regexes'};
+ # The Mageia DB was initially using SQL_ASCII as encoding (which means "no encoding").
+ # The move to UTF8 caused some characters to be badly decoded, which we fix here.
+ # Convert "é" into "é".
+ push(@$regexes, { match => qr/\xc3\xa9/, replace => "\xe9" });
+}
+
+sub enter_bug_entrydefaultvars {
+ my ($self, $vars) = @_;
+ my $cgi = Bugzilla->cgi;
+
+ # By default, users should get the guided form when reporting a new bug.
+ # Pass &normal=1 to the URL to get the official bug form.
+ my $format = $cgi->param('normal') ? '' : 'guided';
+ $cgi->param('format', $format);
+}
+
+sub install_before_final_checks {
+ # A hook in Bugzilla::Install::SETTINGS() would be much cleaner. :(
+ my %settings = %{MGA_SETTINGS()};
+ foreach my $setting (keys %settings) {
+ add_setting($setting, $settings{$setting}->{options}, $settings{$setting}->{default});
+ }
+}
+
+sub mailer_before_send {
+ my ($self, $args) = @_;
+ my $email = $args->{email};
+
+ # Include the changer's name in the "From:" field.
+ if (my $changer = $email->header('X-Bugzilla-Who')) {
+ $changer = Bugzilla::User->new({ name => $changer });
+ return unless $changer;
+ my $address = Email::Address->new($changer->name, $email->header('From'));
+ $email->header_str_set('From' => $address->format);
+ }
+}
+
+sub sanitycheck_check {
+ my ($self, $args) = @_;
+ &{$args->{status}}('ldap_check_group_membership');
+ sync_ldap_groups_check($args->{status});
+}
+
+sub sanitycheck_repair {
+ my ($self, $args) = @_;
+ if (Bugzilla->cgi->param('sync_ldap_groups')) {
+ &{$args->{status}}('ldap_repair_start');
+ sync_ldap_groups_check($args->{status}, 1);
+ &{$args->{status}}('ldap_repair_end');
+ }
+}
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ _inline_history($args) if $args->{file} eq 'bug/comments.html.tmpl';
+}
+
+sub _inline_history {
+ my $args = shift;
+ my $user = Bugzilla->user;
+ return if $user->setting('mga_inline_history') eq 'off';
+ # Only display the bug history in chronological order.
+ return if $user->setting('comment_sort_order') ne 'oldest_to_newest';
+
+ my $bug = $args->{vars}->{bug};
+ my ($history) = $bug->get_activity();
+ # Filter private comments that the user is not allowed to see.
+ my @comments = grep { !$_->is_private || $user->is_insider || $user->id == $_->author->id } @{ $bug->comments };
+ my %h_times = map { $_->{when} => $_ } @$history;
+ my %c_times = map { $_->creation_ts => $_ } @comments;
+ my @all_times = sort { compare_datetimes($a, $b) } (keys %c_times, keys %h_times);
+ my $curr_comment;
+
+ foreach my $time (@all_times) {
+ if ($c_times{$time}) {
+ $curr_comment = $c_times{$time};
+ $curr_comment->{inline_history} //= [];
+ }
+ if (my $activity = $h_times{$time}) {
+ # If we have no visible comment to attach the activity to, then ignore it.
+ # This can happen if the initial comment (comment 0) is private.
+ next unless $curr_comment;
+ $activity->{after} = compare_datetimes($time, $curr_comment->creation_ts);
+ $activity->{who} = new Bugzilla::User({ name => $activity->{who}, cache => 1 });
+ push(@{ $curr_comment->{inline_history} }, $activity);
+ }
+ }
+}
+
+sub user_wants_mail {
+ my ($self, $args) = @_;
+ return unless $args->{relationship} == REL_GLOBAL_WATCHER;
+
+ my $wants_mail = $args->{wants_mail};
+ my @events = @{ $args->{events} };
+ # Do not email global watchers if the single change is about the CC list.
+ $$wants_mail = (scalar(@events) == 1 && $events[0] == EVT_CC) ? 0 : 1;
+}
+
+__PACKAGE__->NAME;