Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions Bugzilla/Config/Donation.pm
Original file line number Diff line number Diff line change
@@ -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::Config::Donation;

use 5.10.1;
use strict;
use warnings;

use Bugzilla::Config::Common;

our $sortkey = 175;

use constant get_param_list => (
{
name => 'donation_banner_visibility',
type => 's',
choices => ['admins_only', 'end_users', 'disabled'],
default => 'admins_only',
checker => \&check_multi,
},
);

1;

__END__

=head1 NAME

Bugzilla::Config::Donation - Donation banner settings

=cut
129 changes: 129 additions & 0 deletions Bugzilla/Donation.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# 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::Donation;

use 5.10.1;
use strict;
use warnings;

use Bugzilla::Constants;
use Bugzilla::Token qw(issue_hash_token);

use DateTime;

use constant BANNER_URL => 'https://bugzilla.org/donate';
use constant BANNER_MESSAGES => (
'Help us make Bugzilla better more often.',
'A small donation helps keep Bugzilla moving forward.',
'Support the people who keep Bugzilla running.',
'Even a little funding helps Bugzilla improve more quickly.',
'If Bugzilla helps your team, consider helping Bugzilla too.',
);

sub get_banner {
my $user = Bugzilla->user;
return undef if !$user->id;

my $visibility = Bugzilla->params->{'donation_banner_visibility'} || 'admins_only';
return undef if $visibility eq 'disabled';
return undef if $visibility eq 'admins_only' && !$user->in_group('admin');

my $settings = $user->settings;
my $pref = $settings->{'donate_banner_pref'}->{'value'};
my $last_version = $settings->{'donate_banner_last_version'}->{'value'} || '0.0';
my $next_date = $settings->{'donate_banner_reminder_date'}->{'value'} || '1970-01-01';
my $current_version = BUGZILLA_VERSION;

my $show;
my $show_thanks = 0;
if ($pref eq 'next_upgrade') {
$show = ($last_version ne $current_version);
$show_thanks = $show
&& $user->in_group('admin')
&& $last_version ne '0'
&& $last_version ne '0.0';
}
elsif ($pref eq 'specific_date') {
my $today = DateTime->now(time_zone => Bugzilla->local_timezone)->ymd;
$show = ($next_date le $today);
}
else {
$show = 0;
}

return undef if !$show;

my @messages = BANNER_MESSAGES;
my $message = $messages[int(rand(@messages))];

my $data = {
url => BANNER_URL,
message => $message,
show_thanks => $show_thanks,
visibility => $visibility,
settings_link => 'editparams.cgi?section=donation#donation_banner_visibility_desc',
token => issue_hash_token(['donation_banner']),
};

if ($visibility eq 'admins_only') {
$data->{'visibility_note'}
= 'This message is only shown to logged-in users with admin privs.';
}
elsif ($user->in_group('admin')) {
$data->{'visibility_note'}
= 'This message is visible to all logged-in users.';
}

return $data;
}

sub set_banner_preference {
my ($action) = @_;
my $user = Bugzilla->user;
my $settings = $user->settings;

my $pref_setting = $settings->{'donate_banner_pref'};
my $date_setting = $settings->{'donate_banner_reminder_date'};
my $version_setting = $settings->{'donate_banner_last_version'};
my $current_version = BUGZILLA_VERSION;

if ($action eq 'next_upgrade') {
$pref_setting->set('next_upgrade');
$version_setting->set($current_version);
return 'index.cgi';
}
if ($action eq 'week' || $action eq 'month') {
my $days = $action eq 'week' ? 7 : 30;
my $dt = DateTime->now(time_zone => Bugzilla->local_timezone);
$dt->add(days => $days);
$pref_setting->set('specific_date');
$date_setting->set($dt->ymd);
$version_setting->set($current_version);
return 'index.cgi';
}
if ($action eq 'never') {
$pref_setting->set('never');
$version_setting->set($current_version);
return 'index.cgi';
}
if ($action eq 'date') {
return 'userprefs.cgi?tab=donate';
}

return 'index.cgi';
}

1;

__END__
=head1 NAME
Bugzilla::Donation - Donation banner helpers
=cut
18 changes: 18 additions & 0 deletions Bugzilla/Install.pm
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,24 @@ sub SETTINGS {
category => 'Searching'
},

# 2026-07-01 bugzilla@mozilla.org -- Bug 1983391
{
name => 'donate_banner_pref',
options => ['next_upgrade', 'specific_date', 'never'],
default => 'next_upgrade',
category => 'Bugzilla.org',
},
{
name => 'donate_banner_last_version',
default => '0.0',
category => 'Bugzilla.org',
},
{
name => 'donate_banner_reminder_date',
default => '1970-01-01',
category => 'Bugzilla.org',
},

# 2005-03-10 travis@sedsystems.ca -- Bug 199048
{
name => 'comment_sort_order',
Expand Down
8 changes: 7 additions & 1 deletion Bugzilla/Install/DB.pm
Original file line number Diff line number Diff line change
Expand Up @@ -3076,7 +3076,13 @@ sub _rederive_regex_groups {

$sth->execute(GRANT_REGEXP);
while (my ($uid, $login, $gid, $rexp, $present) = $sth->fetchrow_array()) {
if ($login =~ m/$rexp/i) {
my $matches = eval { $login =~ m/$rexp/i ? 1 : 0 };
if ($@) {
print "Skipping invalid group regexp for group $gid: $rexp\n";
next;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look related to the banner addition to me?


if ($matches) {
$sth_add->execute($uid, $gid) unless $present;
}
else {
Expand Down
17 changes: 17 additions & 0 deletions index.cgi
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ use lib qw(. lib local/lib/perl5);
use Bugzilla;
use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::Token;
use Bugzilla::Donation;
use Bugzilla::Update;
use Digest::MD5 qw(md5_hex);
use List::MoreUtils qw(any);
Expand Down Expand Up @@ -44,6 +46,19 @@ if ($cgi->param('logout')) {
$cgi->delete('logout');
}

my $donate_action = $cgi->param('donate_action');
if ($donate_action) {
Bugzilla->login(LOGIN_REQUIRED) unless Bugzilla->user->id;

my $token = $cgi->param('token');
check_hash_token($token, ['donation_banner']);

my $redirect = Bugzilla::Donation::set_banner_preference($donate_action);

print $cgi->redirect(-uri => $redirect);
exit;
}

# our weak etag is based on the Bugzilla version parameter (BMO customization) and the announcehtml
# if either change, the cache will be considered invalid.
my @etag_parts = (
Expand Down Expand Up @@ -90,6 +105,8 @@ else {
$vars->{'release'} = Bugzilla::Update::get_notifications();
}

$vars->{'donation'} = Bugzilla::Donation::get_banner();

# Generate and return the UI (HTML page) from the appropriate template.
$template->process("index.html.tmpl", $vars)
or ThrowTemplateError($template->error());
Expand Down
142 changes: 142 additions & 0 deletions skins/standard/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,148 @@ input[type="radio"]:checked {
color: var(--secondary-label-color);
}

.donation_banner {
border-color: rgba(var(--accent-color-green-1), 0.75);
color: var(--primary-text-color);
background: var(--primary-region-background-color);
box-shadow: var(--primary-region-box-shadow);
font-weight: normal;
}

.donation_banner_layout {
display: flex;
align-items: center;
gap: 1rem;
}

.donation_banner_image {
width: 110px;
height: 110px;
flex: 0 0 auto;
object-fit: contain;
object-position: center;
border: 1px dashed rgba(var(--accent-color-green-1), 0.7);
border-radius: 10px;
background: rgba(var(--accent-color-green-1), 0.08);
}

.donation_banner_content {
flex: 1 1 auto;
padding-top: 0.35rem;
}

.donation_banner_thanks {
margin: 0 0 0.5rem;
color: var(--primary-text-color);
font-weight: bold;
}

.donation_banner_message {
margin: 0 0 0.6rem;
color: var(--primary-text-color);
font-size: 1.08rem;
line-height: 1.45;
}

.donation_banner_cta_row {
margin: 0 0 0.75rem;
}

.donation_banner_cta {
display: inline-block;
padding: 0.55rem 1rem;
border: 1px solid rgb(var(--accent-color-green-1));
border-radius: 5px;
background: rgb(var(--accent-color-green-1));
Comment on lines +1103 to +1105

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In dark mode, the contrast ratio is too low. We have two options:

  1. Use --accent-color-lightgreen-1 for the border and background color
  2. Use --accent-color-green-1 with color: #000 !important

I, personally, find option 1 more aesthitically more pleasing.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a follow-up using your version 1 suggestion.

color: #fff !important;
text-decoration: none;
font-weight: bold;
font-size: 1rem;
}

.donation_banner_cta:hover {
border-color: rgb(var(--accent-color-green-1));
background: rgba(var(--accent-color-green-1), 0.9);
text-decoration: none;
}

.donation_banner_form {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 0.5rem;
}

.donation_banner_label {
font-weight: bold;
}

.donation_banner_select {
min-width: 240px;
}

.donation_banner_submit {
padding: 0.35rem 0.8rem;
}

.donation_banner_submit:hover {
border-color: var(--hovered-secondary-button-border-color);
color: var(--hovered-secondary-button-foreground-color);
background: var(--hovered-secondary-button-background-color);
}

.donation_banner_form_subtle {
font-size: 0.9rem;
opacity: 0.9;
}

.donation_banner_form_subtle .donation_banner_label {
font-weight: normal;
color: var(--secondary-label-color);
}

.donation_banner_form_subtle .donation_banner_select {
min-width: 230px;
padding: 0.25rem 0.4rem;
font-size: 0.9rem;
}

.donation_banner_form_subtle .donation_banner_submit {
padding: 0.25rem 0.65rem;
font-size: 0.88rem;
}

@media (max-width: 720px) {
.donation_banner_layout {
align-items: flex-start;
}

.donation_banner_image {
width: 84px;
height: 84px;
}

.donation_banner_select {
min-width: 100%;
}
}

@media screen and (prefers-color-scheme: dark) {
.donation_banner {
border-color: rgb(var(--accent-color-lightgreen-1));
background: rgba(var(--accent-color-lightgreen-1), 0.12);
}

.donation_banner_image {
border-color: rgba(var(--accent-color-lightgreen-1), 0.55);
background: rgba(var(--accent-color-lightgreen-1), 0.12);
}

.donation_banner_form_subtle {
opacity: 1;
}
}

/**
* Global header
*/
Expand Down
Loading
Loading