summaryrefslogtreecommitdiffstats
path: root/Bugzilla
diff options
context:
space:
mode:
authortravis%sedsystems.ca <>2005-03-11 00:51:40 +0100
committertravis%sedsystems.ca <>2005-03-11 00:51:40 +0100
commit6674f61905d98aee08b95c22181aa439bfb041e5 (patch)
tree1b220ecddbfbc5a433982841508571696e211c60 /Bugzilla
parent9ffc6eb52bb9c549dae85a51aaf2b29750b7ba14 (diff)
downloadbugzilla-6674f61905d98aee08b95c22181aa439bfb041e5.tar.gz
bugzilla-6674f61905d98aee08b95c22181aa439bfb041e5.tar.xz
Bug 98123 : Create a user preferences infrastructure (became 'General Settings')
Patch by Shane H. W. Travis <travis@sedsystems.ca> r=jouni, mkanat a=myk
Diffstat (limited to 'Bugzilla')
-rw-r--r--Bugzilla/DB/Schema.pm49
-rw-r--r--Bugzilla/User.pm33
-rw-r--r--Bugzilla/User/Setting.pm352
3 files changed, 434 insertions, 0 deletions
diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm
index 3a15a755e..99f5f106f 100644
--- a/Bugzilla/DB/Schema.pm
+++ b/Bugzilla/DB/Schema.pm
@@ -913,6 +913,55 @@ use constant ABSTRACT_SCHEMA => {
],
},
+ # SETTINGS
+ # --------
+ # setting - each global setting will have exactly one entry
+ # in this table.
+ # setting_value - stores the list of acceptable values for each
+ # setting, and a sort index that controls the order
+ # in which the values are displayed.
+ # profile_setting - If a user has chosen to use a value other than the
+ # global default for a given setting, it will be
+ # stored in this table. Note: even if a setting is
+ # later changed so is_enabled = false, the stored
+ # value will remain in case it is ever enabled again.
+ #
+ setting => {
+ FIELDS => [
+ name => {TYPE => 'varchar(32)', NOTNULL => 1,
+ PRIMARYKEY => 1},
+ default_value => {TYPE => 'varchar(32)', NOTNULL => 1},
+ is_enabled => {TYPE => 'BOOLEAN', NOTNULL => 1,
+ DEFAULT => 'TRUE'},
+ ],
+ },
+
+ setting_value => {
+ FIELDS => [
+ name => {TYPE => 'varchar(32)', NOTNULL => 1},
+ value => {TYPE => 'varchar(32)', NOTNULL => 1},
+ sortindex => {TYPE => 'INT2', NOTNULL => 1},
+ ],
+ INDEXES => [
+ setting_value_nv_unique_idx => {FIELDS => [qw(name value)],
+ TYPE => 'UNIQUE'},
+ setting_value_ns_unique_idx => {FIELDS => [qw(name sortindex)],
+ TYPE => 'UNIQUE'},
+ ],
+ },
+
+ profile_setting => {
+ FIELDS => [
+ user_id => {TYPE => 'INT3', NOTNULL => 1},
+ setting_name => {TYPE => 'varchar(32)', NOTNULL => 1},
+ setting_value => {TYPE => 'varchar(32)', NOTNULL => 1},
+ ],
+ INDEXES => [
+ profile_setting_value_unique_idx => {FIELDS => [qw(user_id setting_name)],
+ TYPE => 'UNIQUE'},
+ ],
+ },
+
};
#--------------------------------------------------------------------------
diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm
index e67a78c83..8045ee228 100644
--- a/Bugzilla/User.pm
+++ b/Bugzilla/User.pm
@@ -22,6 +22,7 @@
# Bradley Baetz <bbaetz@acm.org>
# Joel Peshkin <bugreport@peshkin.net>
# Byron Jones <bugzilla@glob.com.au>
+# Shane H. W. Travis <travis@sedsystems.ca>
# Max Kanat-Alexander <mkanat@kerio.com>
################################################################################
@@ -38,6 +39,7 @@ use Bugzilla::Config;
use Bugzilla::Error;
use Bugzilla::Util;
use Bugzilla::Constants;
+use Bugzilla::User::Setting;
use Bugzilla::Auth;
use base qw(Exporter);
@@ -224,6 +226,23 @@ sub queries {
return $self->{queries};
}
+sub settings {
+ my ($self) = @_;
+
+ return $self->{'settings'} if (defined $self->{'settings'});
+
+ # IF the user is logged in
+ # THEN get the user's settings
+ # ELSE get default settings
+ if ($self->id) {
+ $self->{'settings'} = get_all_settings($self->id);
+ } else {
+ $self->{'settings'} = get_defaults();
+ }
+
+ return $self->{'settings'};
+}
+
sub flush_queries_cache {
my $self = shift;
@@ -1148,6 +1167,20 @@ linkinfooter - Whether or not the query should be displayed in the footer.
Returns the disable text of the user, if any.
+=item C<settings>
+
+Returns a hash of hashes which holds the user's settings. The first key is
+the name of the setting, as found in setting.name. The second key is one of:
+is_enabled - true if the user is allowed to set the preference themselves;
+ false to force the site defaults
+ for themselves or must accept the global site default value
+default_value - the global site default for this setting
+value - the value of this setting for this user. Will be the same
+ as the default_value if the user is not logged in, or if
+ is_default is true.
+is_default - a boolean to indicate whether the user has chosen to make
+ a preference for themself or use the site default.
+
=item C<flush_queries_cache>
Some code modifies the set of stored queries. Because C<Bugzilla::User> does
diff --git a/Bugzilla/User/Setting.pm b/Bugzilla/User/Setting.pm
new file mode 100644
index 000000000..a8e1cbaed
--- /dev/null
+++ b/Bugzilla/User/Setting.pm
@@ -0,0 +1,352 @@
+# -*- 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): Shane H. W. Travis <travis@sedsystems.ca>
+# Max Kanat-Alexander <mkanat@kerio.com>
+#
+
+
+package Bugzilla::User::Setting;
+
+use strict;
+use base qw(Exporter);
+
+# Module stuff
+@Bugzilla::User::Setting::EXPORT = qw(get_all_settings get_defaults
+ add_setting);
+
+use Bugzilla::Error;
+
+###############################
+### Module Initialization ###
+###############################
+
+sub new {
+ my $invocant = shift;
+ my $setting_name = shift;
+ my $user_id = shift;
+
+ my $class = ref($invocant) || $invocant;
+
+ # Create a ref to an empty hash and bless it
+ my $self = {};
+ bless($self, $class);
+
+ my $dbh = Bugzilla->dbh;
+
+ # Confirm that the $setting_name is properly formed;
+ # if not, throw a code error.
+ #
+ # NOTE: due to the way that setting names are used in templates,
+ # they must conform to to the limitations set for HTML NAMEs and IDs.
+ #
+ if ( !($setting_name =~ /^[a-zA-Z][-.:\w]*$/) ) {
+ ThrowCodeError("setting_name_invalid", { name => $setting_name });
+ }
+
+ # If there were only two parameters passed in, then we need
+ # to retrieve the information for this setting ourselves.
+ if (scalar @_ == 0) {
+
+ my ($default, $is_enabled, $value) =
+ $dbh->selectrow_array(
+ q{SELECT default_value, is_enabled, setting_value
+ FROM setting
+ LEFT JOIN profile_setting
+ ON setting.name = profile_setting.setting_name
+ WHERE name = ?
+ AND (profile_setting.user_id = ?
+ OR profile_setting.user_id IS NULL)},
+ undef,
+ $setting_name, $user_id);
+
+ $self->{'is_enabled'} = $is_enabled;
+ $self->{'default_value'} = $default;
+
+ # IF the setting is enabled, AND the user has chosen a setting
+ # THEN return that value
+ # ELSE return the site default, and note that it is the default.
+ if ( ($is_enabled) && (defined $value) ) {
+ $self->{'value'} = $value;
+ } else {
+ $self->{'value'} = $default;
+ $self->{'isdefault'} = 1;
+ }
+ }
+ 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;
+ }
+
+ $self->{'_setting_name'} = $setting_name;
+ $self->{'_user_id'} = $user_id;
+
+ return $self;
+}
+
+###############################
+### Subroutine Definitions ###
+###############################
+
+sub add_setting {
+ my ($name, $values, $default_value) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ return if _setting_exists($name);
+
+ ($name && $values && $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));
+
+ my $sth = $dbh->prepare(q{INSERT INTO setting_value (name, value, sortindex)
+ VALUES (?, ?, ?)});
+
+ my @values_list = keys %{$values};
+ foreach my $key (@values_list){
+ $sth->execute($name, $key, $values->{$key});
+ }
+}
+
+sub get_all_settings {
+ my ($user_id) = @_;
+ my $settings;
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare(
+ q{SELECT name, default_value, is_enabled, setting_value
+ FROM setting
+ LEFT JOIN profile_setting
+ ON setting.name = profile_setting.setting_name
+ WHERE profile_setting.user_id = ?
+ OR profile_setting.user_id IS NULL
+ ORDER BY name});
+
+ $sth->execute($user_id);
+ while (my ($name, $default_value, $is_enabled, $value)
+ = $sth->fetchrow_array()) {
+
+ my $is_default;
+
+ if ( ($is_enabled) && (defined $value) ) {
+ $is_default = 0;
+ } else {
+ $value = $default_value;
+ $is_default = 1;
+ }
+
+ $settings->{$name} = new Bugzilla::User::Setting(
+ $name, $user_id, $is_enabled,
+ $default_value, $value, $is_default);
+ }
+
+ return $settings;
+}
+
+sub get_defaults {
+ my $dbh = Bugzilla->dbh;
+ my $default_settings;
+
+ my $sth = $dbh->prepare(q{SELECT name, default_value, is_enabled
+ FROM setting
+ ORDER BY name});
+ $sth->execute();
+ while (my ($name, $default_value, $is_enabled) = $sth->fetchrow_array()) {
+
+ $default_settings->{$name} = new Bugzilla::User::Setting(
+ $name, 0, $is_enabled, $default_value, $default_value, 1);
+ }
+
+ return $default_settings;
+}
+
+sub set_default {
+ my ($setting_name, $default_value, $is_enabled) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare(q{UPDATE setting
+ SET default_value = ?, is_enabled = ?
+ WHERE name = ?});
+ $sth->execute($default_value, $is_enabled, $setting_name);
+}
+
+sub _setting_exists {
+ my ($setting_name) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $sth = $dbh->prepare("SELECT name FROM setting WHERE name = ?");
+ $sth->execute($setting_name);
+ return ($sth->rows) ? 1 : 0;
+}
+
+
+sub legal_values {
+ my ($self) = @_;
+
+ return $self->{'legal_values'} if defined $self->{'legal_values'};
+
+ my $dbh = Bugzilla->dbh;
+ $self->{'legal_values'} = $dbh->selectcol_arrayref(
+ q{SELECT value
+ FROM setting_value
+ WHERE name = ?
+ ORDER BY sortindex},
+ undef, $self->{'_setting_name'});
+
+ return $self->{'legal_values'};
+}
+
+sub reset_to_default {
+ my ($self) = @_;
+
+ my $dbh = Bugzilla->dbh;
+ my $sth = $dbh->do(q{ DELETE
+ FROM profile_setting
+ WHERE setting_name = ?
+ AND user_id = ?},
+ undef, $self->{'_setting_name'}, $self->{'_user_id'});
+ $self->{'value'} = $self->{'default_value'};
+ $self->{'is_default'} = 1;
+}
+
+sub set {
+ my ($self, $value) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $query;
+
+ if ($self->{'is_default'}) {
+ $query = q{INSERT INTO profile_setting
+ (setting_value, setting_name, user_id)
+ VALUES (?,?,?)};
+ } else {
+ $query = q{UPDATE profile_setting
+ SET setting_value = ?
+ WHERE setting_name = ?
+ AND user_id = ?};
+ }
+ $dbh->do($query, undef, $value, $self->{'_setting_name'}, $self->{'_user_id'});
+
+ $self->{'value'} = $value;
+ $self->{'is_default'} = 0;
+}
+
+
+
+1;
+
+__END__
+
+=head1 NAME
+Bugzilla::User::Setting - Object for a user preference setting
+
+=head1 SYNOPSIS
+Setting.pm creates a setting object, which is a hash containing the user
+preference information for a single preference for a single user. These
+are usually accessed through the "settings" object of a user, and not
+directly.
+
+=head1 DESCRIPTION
+use Bugzilla::User::Setting;
+my $settings;
+
+$settings->{$setting_name} = new Bugzilla::User::Setting(
+ $setting_name, $user_id);
+
+OR
+
+$settings->{$setting_name} = new Bugzilla::User::Setting(
+ $setting_name, $user_id, $is_enabled,
+ $default_value, $value, $is_default);
+
+=head1 CLASS FUNCTIONS
+
+=over 4
+
+=item C<add_setting($name, $values, $default_value)>
+
+Description: Checks for the existence of a setting, and adds it
+ to the database if it does not yet exist.
+Params: C<$name> - string - the name of the new setting
+ C<$values> - hash - contains the new values (key) and
+ sortindexes for the new setting
+ C<$default_value> - string - the site default
+Returns: a pointer to a hash of settings
+#
+#
+=item C<get_all_settings($user_id)>
+
+Description: Provides the user's choices for each setting in the
+ system; if the user has made no choice, uses the site
+ default instead.
+Params: C<$user_id> - integer - the user id.
+Returns: a pointer to a hash of settings
+
+=item C<get_defaults>
+
+Description: When a user is not logged in, they must use the site
+ defaults for every settings; this subroutine provides them.
+Params: none
+Returns: A pointer to a hash of settings
+
+=item C<set_default($setting_name, $default_value, $is_enabled)>
+
+Description: Sets the global default for a given setting. Also sets
+ whether users are allowed to choose their own value for
+ this setting, or if they must use the global default.
+Params: C<$setting_name> - string - the name of the setting
+ C<$default_value> - string - the new default value for this setting
+ C<$is_enabled> - boolean - if false, all users must use the global default
+Returns: nothing
+
+=begin private
+=item C<_setting_exists>
+
+Description: Determines if a given setting exists in the database.
+Params: C<$setting_name> - string - the setting name
+Returns: boolean - true if the setting already exists in the DB.
+
+=end private
+=head1 METHODS
+
+=over 4
+
+=item C<legal_values($setting_name)>
+
+Description: Returns all legal values for this setting
+Params: none
+Returns: A reference to an array containing all legal values
+
+=item C<reset_to_default>
+
+Description: If a user chooses to use the global default for a given
+ setting, their saved entry is removed from the database via
+ this subroutine.
+Params: none
+Returns: nothing
+
+=item C<set($value)>
+
+Description: If a user chooses to use their own value rather than the
+ global value for a given setting, OR changes their value for
+ a given setting, this subroutine is called to insert or
+ update the database as appropriate.
+Params: C<$value> - string - the new value for this setting for this user.
+Returns: nothing
+
+