diff options
-rw-r--r-- | Bugzilla/Constants.pm | 1 | ||||
-rw-r--r-- | Bugzilla/DB/Schema.pm | 1 | ||||
-rw-r--r-- | Bugzilla/Install.pm | 8 | ||||
-rw-r--r-- | Bugzilla/Install/DB.pm | 2 | ||||
-rw-r--r-- | Bugzilla/Install/Filesystem.pm | 1 | ||||
-rw-r--r-- | Bugzilla/User/Setting.pm | 43 | ||||
-rwxr-xr-x | Bugzilla/User/Setting/Skin.pm | 80 | ||||
-rw-r--r-- | template/en/default/global/code-error.html.tmpl | 4 | ||||
-rw-r--r-- | template/en/default/global/header.html.tmpl | 85 | ||||
-rw-r--r-- | template/en/default/global/setting-descs.none.tmpl | 2 |
10 files changed, 201 insertions, 26 deletions
diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index 2d6c2f561..a0e869c33 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -368,6 +368,7 @@ sub bz_locations { 'localconfig' => "$libpath/$localconfig", 'datadir' => "$libpath/$datadir", 'attachdir' => "$libpath/$datadir/attachments", + 'skinsdir' => "$libpath/skins/contrib", # $webdotdir must be in the webtree somewhere. Even if you use a # local dot, we output images to there. Also, if $webdotdir is # not relative to the bugzilla root directory, you'll need to diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm index 0a5cf9420..ea25a125a 100644 --- a/Bugzilla/DB/Schema.pm +++ b/Bugzilla/DB/Schema.pm @@ -1047,6 +1047,7 @@ use constant ABSTRACT_SCHEMA => { default_value => {TYPE => 'varchar(32)', NOTNULL => 1}, is_enabled => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'TRUE'}, + subclass => {TYPE => 'varchar(32)'}, ], }, diff --git a/Bugzilla/Install.pm b/Bugzilla/Install.pm index b014d6f6e..d8fc47894 100644 --- a/Bugzilla/Install.pm +++ b/Bugzilla/Install.pm @@ -50,6 +50,8 @@ use constant SETTINGS => { # 2006-05-01 olav@bkor.dhs.org -- Bug 7710 state_addselfcc => { options => ['always', 'never', 'cc_unless_role'], default => 'cc_unless_role' }, + # 2006-08-04 wurblzap@gmail.com -- Bug 322693 + skin => { subclass => 'Skin', default => 'standard' }, }; @@ -75,8 +77,10 @@ use constant DEFAULT_COMPONENT => { sub update_settings { my %settings = %{SETTINGS()}; foreach my $setting (keys %settings) { - add_setting($setting, $settings{$setting}->{options}, - $settings{$setting}->{default}); + add_setting($setting, + $settings{$setting}->{options}, + $settings{$setting}->{default}, + $settings{$setting}->{subclass}); } } diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm index ccbb5f8cd..d7918f6ac 100644 --- a/Bugzilla/Install/DB.pm +++ b/Bugzilla/Install/DB.pm @@ -485,6 +485,8 @@ sub update_table_definitions { _update_longdescs_who_index(); + $dbh->bz_add_column('setting', 'subclass', {TYPE => 'varchar(32)'}); + ################################################################ # New --TABLE-- changes should go *** A B O V E *** this point # ################################################################ diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm index 5261989dd..43c964ba7 100644 --- a/Bugzilla/Install/Filesystem.pm +++ b/Bugzilla/Install/Filesystem.pm @@ -184,6 +184,7 @@ sub FILESYSTEM { graphs => $ws_dir_writeable, $webdotdir => $ws_dir_writeable, 'skins/custom' => $ws_dir_readable, + 'skins/contrib' => $ws_dir_readable, ); # The name of each file, pointing at its default permissions and diff --git a/Bugzilla/User/Setting.pm b/Bugzilla/User/Setting.pm index 71aeb2ef4..7ed1b2f11 100644 --- a/Bugzilla/User/Setting.pm +++ b/Bugzilla/User/Setting.pm @@ -14,6 +14,7 @@ # # Contributor(s): Shane H. W. Travis <travis@sedsystems.ca> # Max Kanat-Alexander <mkanat@bugzilla.org> +# Marc Schumann <wurblzap@gmail.com> # @@ -39,10 +40,10 @@ sub new { my $user_id = shift; my $class = ref($invocant) || $invocant; + my $subclass = ''; # Create a ref to an empty hash and bless it my $self = {}; - bless($self, $class); my $dbh = Bugzilla->dbh; @@ -60,9 +61,10 @@ sub new { # to retrieve the information for this setting ourselves. if (scalar @_ == 0) { - my ($default, $is_enabled, $value) = + my ($default, $is_enabled, $value); + ($default, $is_enabled, $value, $subclass) = $dbh->selectrow_array( - q{SELECT default_value, is_enabled, setting_value + q{SELECT default_value, is_enabled, setting_value, subclass FROM setting LEFT JOIN profile_setting ON setting.name = profile_setting.setting_name @@ -73,9 +75,9 @@ sub new { # if not defined, then grab the default value if (! defined $value) { - ($default, $is_enabled) = + ($default, $is_enabled, $subclass) = $dbh->selectrow_array( - q{SELECT default_value, is_enabled + q{SELECT default_value, is_enabled, subclass FROM setting WHERE name = ?}, undef, @@ -96,12 +98,23 @@ sub new { } } else { - # If the values were passed in, simply assign them and return. - $self->{'is_enabled'} = shift; - $self->{'default_value'} = shift; - $self->{'value'} = shift; - $self->{'is_default'} = shift; + ($subclass) = $dbh->selectrow_array( + q{SELECT subclass FROM setting WHERE name = ?}, + undef, + $setting_name); + # If the values were passed in, simply assign them and return. + $self->{'is_enabled'} = shift; + $self->{'default_value'} = shift; + $self->{'value'} = shift; + $self->{'is_default'} = shift; + } + if ($subclass) { + eval('require ' . $class . '::' . $subclass); + $@ && ThrowCodeError('setting_subclass_invalid', + {'subclass' => $subclass}); + $class = $class . '::' . $subclass; } + bless($self, $class); $self->{'_setting_name'} = $setting_name; $self->{'_user_id'} = $user_id; @@ -114,18 +127,18 @@ sub new { ############################### sub add_setting { - my ($name, $values, $default_value) = @_; + my ($name, $values, $default_value, $subclass) = @_; my $dbh = Bugzilla->dbh; return if _setting_exists($name); - ($name && $values && $default_value) + ($name && $default_value) || ThrowCodeError("setting_info_invalid"); print "Adding a new user setting called '$name'\n"; - $dbh->do(q{INSERT INTO setting (name, default_value, is_enabled) - VALUES (?, ?, 1)}, - undef, ($name, $default_value)); + $dbh->do(q{INSERT INTO setting (name, default_value, is_enabled, subclass) + VALUES (?, ?, 1, ?)}, + undef, ($name, $default_value, $subclass)); my $sth = $dbh->prepare(q{INSERT INTO setting_value (name, value, sortindex) VALUES (?, ?, ?)}); diff --git a/Bugzilla/User/Setting/Skin.pm b/Bugzilla/User/Setting/Skin.pm new file mode 100755 index 000000000..c4858503f --- /dev/null +++ b/Bugzilla/User/Setting/Skin.pm @@ -0,0 +1,80 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# Contributor(s): Marc Schumann <wurblzap@gmail.com> +# + + +package Bugzilla::User::Setting::Skin; + +use strict; + +use base qw(Bugzilla::User::Setting); + +use Bugzilla::Constants; +use File::Spec::Functions; +use File::Basename; + +use constant BUILTIN_SKIN_NAMES => ['standard']; + +sub legal_values { + my ($self) = @_; + + return $self->{'legal_values'} if defined $self->{'legal_values'}; + + my $dirbase = bz_locations()->{'skinsdir'}; + # Avoid modification of the list BUILTIN_SKIN_NAMES points to by copying the + # list over instead of simply writing $legal_values = BUILTIN_SKIN_NAMES. + my @legal_values = @{(BUILTIN_SKIN_NAMES)}; + + foreach my $direntry (glob(catdir($dirbase, '*'))) { + if (-d $direntry) { + # Stylesheet set + push(@legal_values, basename($direntry)); + } + elsif ($direntry =~ /\.css$/) { + # Single-file stylesheet + push(@legal_values, basename($direntry)); + } + } + + return $self->{'legal_values'} = \@legal_values; +} + +1; + +__END__ + +=head1 NAME + +Bugzilla::User::Setting::Skin - Object for a user preference setting for skins + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +Skin.pm extends Bugzilla::User::Setting and implements a class specialized for +skins settings. + +=head1 METHODS + +=over + +=item C<legal_values()> + +Description: Returns all legal skins +Params: none +Returns: A reference to an array containing the names of all legal skins + +=back diff --git a/template/en/default/global/code-error.html.tmpl b/template/en/default/global/code-error.html.tmpl index a66524355..e62ef7abc 100644 --- a/template/en/default/global/code-error.html.tmpl +++ b/template/en/default/global/code-error.html.tmpl @@ -330,6 +330,10 @@ option. Setting names must begin with a letter, and contain only letters, digits, or the symbols '_', '-', '.', or ':'. + [% ELSIF error == "setting_subclass_invalid" %] + There is no such Setting subclass as + <code>[% subclass FILTER html %]</code>. + [% ELSIF error == "setting_value_invalid" %] The value "<code>[% value FILTER html %]</code>" is not in the list of legal values for the <em>[% name FILTER html %]</em> setting. diff --git a/template/en/default/global/header.html.tmpl b/template/en/default/global/header.html.tmpl index e4a5f4954..026698426 100644 --- a/template/en/default/global/header.html.tmpl +++ b/template/en/default/global/header.html.tmpl @@ -46,6 +46,7 @@ h2 = "" h3 = "" onload = "" + style_urls = [] %] [%# We should be able to set the default value of the h1 variable @@ -67,6 +68,8 @@ [% PROCESS "global/site-navigation.html.tmpl" %] + [% PROCESS 'global/setting-descs.none.tmpl' %] + [% IF javascript %] <script type="text/javascript"> [% javascript %] @@ -81,22 +84,86 @@ [%+ INCLUDE "global/help-header.html.tmpl" %] - <link href="skins/standard/global.css" rel="stylesheet" type="text/css"> - <link href="skins/custom/global.css" rel="stylesheet" type="text/css"> + [%# Set up the skin CSS cascade: + # 1. Standard Bugzilla stylesheet set (persistent) + # 2. Standard Bugzilla stylesheet set (selectable) + # 3. All third-party "skin" stylesheet sets (selectable) + # 4. Page-specific styles + # 5. Custom Bugzilla stylesheet set (persistent) + # "Selectable" skin file sets may be either preferred or alternate. + # Exactly one is preferred, determined by the "skin" user preference. + #%] + [% IF user.settings.skin.value != 'standard' %] + [% user_skin = user.settings.skin.value %] + [% END %] + [% style_urls.unshift('skins/standard/global.css') %] + + [%# CSS cascade, part 1: Standard Bugzilla stylesheet set (persistent). + # Always present. + #%] + [% FOREACH style_url = style_urls %] + <link href="[% style_url FILTER html %]" + rel="stylesheet" + type="text/css"> + [% END %] + + [%# CSS cascade, part 2: Standard Bugzilla stylesheet set (selectable) + # Present if skin selection is enabled. + #%] + [% IF user.settings.skin.is_enabled %] + [% FOREACH style_url = style_urls %] + <link href="[% style_url FILTER html %]" + rel="[% 'alternate ' IF user_skin %]stylesheet" + title="[% setting_descs.standard FILTER html %]" + type="text/css"> + [% END %] + [% END %] + [%# CSS cascade, part 3: Third-party stylesheet set (selectable). + # All third-party skins are present if skin selection is enabled. + # The admin-selected skin is always present. + #%] + [% FOREACH contrib_skin = user.settings.skin.legal_values %] + [% NEXT IF contrib_skin == 'standard' %] + [% NEXT UNLESS contrib_skin == user_skin + OR user.settings.skin.is_enabled %] + [% contrib_skin = contrib_skin FILTER url_quote %] + [% IF contrib_skin.match('\.css$') %] + [%# 1st skin variant: single-file stylesheet %] + <link href="[% "skins/contrib/$contrib_skin" %]" + rel="[% 'alternate ' UNLESS contrib_skin == user_skin %]stylesheet" + title="[% contrib_skin FILTER html %]" + type="text/css"> + [% ELSE %] + [%# 2nd skin variant: stylesheet set %] + [% FOREACH style_url = style_urls %] + [% IF style_url.match('^skins/standard/') %] + <link href="[% style_url.replace('^skins/standard/', + "skins/contrib/$contrib_skin/") %]" + rel="[% 'alternate ' UNLESS contrib_skin == user_skin %]stylesheet" + title="[% contrib_skin FILTER html %]" + type="text/css"> + [% END %] + [% END %] + [% END %] + [% END %] + + [%# CSS cascade, part 4: page-specific styles. + #%] [% IF style %] <style type="text/css"> [% style %] </style> [% END %] - [% IF style_urls %] - [% FOREACH style_url = style_urls %] - <link href="[% style_url FILTER html %]" rel="stylesheet" type="text/css"> - [% IF style_url.match('^skins/standard/') %] - <link href="[% style_url.replace('^skins/standard/', 'skins/custom/') - FILTER html %]" rel="stylesheet" type="text/css"> - [% END %] + [%# CSS cascade, part 5: Custom Bugzilla stylesheet set (persistent). + # Always present. Site administrators may override all other style + # definitions, including skins, using custom stylesheets. + #%] + [% FOREACH style_url = style_urls %] + [% IF style_url.match('^skins/standard/') %] + <link href="[% style_url.replace('^skins/standard/', "skins/custom/") + FILTER html %]" rel="stylesheet" type="text/css"> [% END %] [% END %] diff --git a/template/en/default/global/setting-descs.none.tmpl b/template/en/default/global/setting-descs.none.tmpl index 6962d9ea6..4fb2a031b 100644 --- a/template/en/default/global/setting-descs.none.tmpl +++ b/template/en/default/global/setting-descs.none.tmpl @@ -33,6 +33,8 @@ "post_bug_submit_action" => "After changing $terms.abug", "next_bug" => "Show next $terms.bug in my list", "same_bug" => "Show the updated $terms.bug", + "standard" => "Classic", + "skin" => "$terms.Bugzilla's general appearance (skin)", "nothing" => "Do Nothing", "state_addselfcc" => "Automatically add me to the CC list of bugs I change", "always" => "Always", |