Bug 322693: Create a mechanism to manage multiple custom skins.

Patch by Marc Schumann <wurblzap@gmail.com>;
r=myk,mkanat; a=myk
This commit is contained in:
wurblzap%gmail.com 2006-09-06 20:45:30 +00:00
Родитель aef28cebd5
Коммит e0c494d2e3
10 изменённых файлов: 201 добавлений и 26 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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)'},
],
},

Просмотреть файл

@ -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});
}
}

Просмотреть файл

@ -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 #
################################################################

Просмотреть файл

@ -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

Просмотреть файл

@ -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 (?, ?, ?)});

Просмотреть файл

@ -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

Просмотреть файл

@ -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.

Просмотреть файл

@ -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 %]

Просмотреть файл

@ -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",