From 3844d9ddaf6d8a3af296568ed659c3344fd36b6d Mon Sep 17 00:00:00 2001 From: "preed%sigkill.com" <> Date: Sun, 11 Aug 2002 21:12:32 +0000 Subject: Bug 160410: defparams.pl support for single/multi pulldown menus; p=preed,r=joel,r2=bbaetz --- defparams.pl | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- doeditparams.cgi | 38 +++++++++++++++++-- editparams.cgi | 46 ++++++++++++++++++++++- globals.pl | 48 +++++++++++++----------- 4 files changed, 213 insertions(+), 28 deletions(-) diff --git a/defparams.pl b/defparams.pl index 3e3fd441d..5a1abdc43 100644 --- a/defparams.pl +++ b/defparams.pl @@ -22,6 +22,7 @@ # Dan Mosedale # Joe Robins # Jake +# J. Paul Reed # # This file defines all the parameters that we have a GUI to edit within @@ -43,12 +44,34 @@ sub defparams_pl_sillyness { $zz = %::param_checker; $zz = %::param_desc; $zz = %::param_type; + $zz = %::MFORM; } sub WriteParams { foreach my $i (@::param_list) { if (!defined $::param{$i}) { - $::param{$i} = $::param_default{$i}; + if ($::param_type{$i} eq "m") { + ## For list params (single or multi), param_default is an array + ## with the second element as the default; we have to loop + ## through it to get them all for multi lists and we have to + ## select the second one by itself for single list (next branch + ## of the if) + my $multiParamStr = "[ "; + foreach my $defaultParam (@{$::param_default{$i}->[1]}) { + $multiParamStr .= "'$defaultParam', "; + } + + $multiParamStr .= " ]"; + + $::param{$i} = $multiParamStr; + } + elsif ($::param_type{$i} eq "s") { + $::param{$i} = $::param_default{$i}->[1]; + } + else { + $::param{$i} = $::param_default{$i}; + } + if (!defined $::param{$i}) { die "No default parameter ever specified for $i"; } @@ -67,7 +90,11 @@ sub WriteParams { rename $tmpname, "data/params" || die "Can't rename $tmpname to data/params"; ChmodDataFile('data/params', 0666); } - + +## $checker is a CODE ref that points to a function that verifies the +## parameter for validity; it is called by doeditparams.cgi with the value +## of the param as the first arg and the param name as the 2nd arg (which +## many checker functions ignore, but a couple of them need it. sub DefParam { my ($id, $desc, $type, $default, $checker) = (@_); @@ -80,6 +107,57 @@ sub DefParam { } } +## Converts text parameters for single- and multi-select type params to their +## array indices; takes the name of the parameter and the value you want the +## index of; returns undef on failure. + +sub get_select_param_index { + my ($paramName, $val) = (@_); + + return undef if ($::param_type{$paramName} !~ /^m|s$/); + + my $paramList = $::param_default{$paramName}->[0]; + + for (my $ndx = 0; $ndx < scalar(@{$paramList}); $ndx++) { + ## The first element of the $param_default array in selects is the + ## list of possible params; search through this array for a match. + return $ndx if ($val eq $paramList->[$ndx]); + } + + return undef; +} + +sub check_multi { + my ($value, $param) = (@_); + + if ($::param_type{$param} eq "s") { + if (check_numeric($value) ne "") { + return "List param types must be digits"; + } + elsif ($value < 0 || $value > $#{$::param_default{$param}->[0]}) { + return "Invalid choice for single-select list param '$param'"; + } + else { + return ""; + } + } + elsif ($::param_type{$param} eq "m") { + foreach my $chkParam (@{$::MFORM{$param}}) { + if (check_numeric($chkParam) ne "") { + return "List param types must be digits"; + } + elsif ($chkParam < 0 || $chkParam > + $#{$::param_default{$param}->[0]}) { + return "Invalid choice for multi-select list param '$param'"; + } + } + + return ""; + } + else { + return "Invalid param type for check_multi(); contact your BZ admin"; + } +} sub check_numeric { my ($value) = (@_); @@ -119,6 +197,33 @@ sub check_shadowdb { # t -- A short text entry field (suitable for a single line) # l -- A long text field (suitable for many lines) # b -- A boolean value (either 1 or 0) +# m -- A list of values, with many selectable (shows up as a select box) +# To specify the list of values, make the 'default value' for DefParam() +# a reference to two anonymous arrays, the first being the list of options +# and the second being a list of defaults (which must appear in the +# first anonymous array), i.e.: +# DefParam("multiselect", "A list of options, choose many", +# "m", [ ['a','b','c','d'], ['a', 'd'] ], \&check_multi); +# +# Here, 'a' and 'd' are the default options, and the user may pick any +# combination of a, b, c, and d as valid options. +# +# &check_multi should always be used as the param verification function +# for list (single and multiple) parameter types. +# +# s -- A list of values, with one selectable (shows up as a select box) +# To specify the list of values, make the default value a reference to +# an anonymous array with two items inside of it, the first being an +# array of the possible values and the second being the scalar that is +# the default default value, i.e.: +# DefParam("singleselect", "A list of options, choose one", "s", +# [ ['a','b','c'], 'b'], \&check_multi); +# +# Here, 'b' is the default option, and 'a' and 'c' are other possible +# options, but only one at a time! +# +# &check_multi should always be used as the param verification function +# for list (single and multiple) parameter types. DefParam("maintainer", "The email address of the person who maintains this installation of Bugzilla.", diff --git a/doeditparams.cgi b/doeditparams.cgi index 3e97e140b..c237a1997 100755 --- a/doeditparams.cgi +++ b/doeditparams.cgi @@ -19,6 +19,7 @@ # Rights Reserved. # # Contributor(s): Terry Weissman +# J. Paul Reed use diagnostics; use strict; @@ -51,14 +52,30 @@ PutHeader("Saving new parameters"); foreach my $i (@::param_list) { # print "Processing $i...
\n"; if (exists $::FORM{"reset-$i"}) { - $::FORM{$i} = $::param_default{$i}; + if ($::param_type{$i} eq "s") { + my $index = get_select_param_index($i, $::param_default{$i}->[1]); + die "Param not found for '$i'" if ($index eq undef); + $::FORM{$i} = $index; + } + elsif ($::param_type{$i} eq "m") { + # For 'multi' selects, default is the 2nd anon array of the default + @{$::MFORM{$i}} = (); + foreach my $defaultPrm (@{$::param_default{$i}->[1]}) { + my $index = get_select_param_index($i, $defaultPrm); + die "Param not found for '$i'" if ($index eq undef); + push(@{$::MFORM{$i}}, $index); + } + } + else { + $::FORM{$i} = $::param_default{$i}; + } } $::FORM{$i} =~ s/\r\n?/\n/g; # Get rid of windows/mac-style line endings. $::FORM{$i} =~ s/^\n$//; # assume single linefeed is an empty string if ($::FORM{$i} ne Param($i)) { if (defined $::param_checker{$i}) { my $ref = $::param_checker{$i}; - my $ok = &$ref($::FORM{$i}); + my $ok = &$ref($::FORM{$i}, $i); if ($ok ne "") { print "New value for $i is invalid: $ok

\n"; print "Please hit Back and try again.\n"; @@ -69,7 +86,22 @@ foreach my $i (@::param_list) { print "Changed $i.
\n"; # print "Old: '" . url_quote(Param($i)) . "'
\n"; # print "New: '" . url_quote($::FORM{$i}) . "'
\n"; - $::param{$i} = $::FORM{$i}; + if ($::param_type{$i} eq "s") { + $::param{$i} = $::param_default{$i}->[0]->[$::FORM{$i}]; + } + elsif ($::param_type{$i} eq "m") { + my $multiParamStr = "[ "; + foreach my $chosenParam (@{$::MFORM{$i}}) { + $multiParamStr .= + "'$::param_default{$i}->[0]->[$chosenParam]', "; + } + $multiParamStr .= " ]"; + + $::param{$i} = $multiParamStr; + } + else { + $::param{$i} = $::FORM{$i}; + } } } diff --git a/editparams.cgi b/editparams.cgi index 40f5ad537..0e1b7161f 100755 --- a/editparams.cgi +++ b/editparams.cgi @@ -19,6 +19,7 @@ # Rights Reserved. # # Contributor(s): Terry Weissman +# J. Paul Reed use diagnostics; @@ -30,7 +31,8 @@ require "defparams.pl"; # Shut up misguided -w warnings about "used only once": use vars @::param_desc, - @::param_list; + @::param_list, + @::param_default; ConnectToDatabase(); confirm_login(); @@ -87,6 +89,48 @@ foreach my $i (@::param_list) { print "Off\n"; last SWITCH; }; + /^m$/ && do { + my $optList = $::param_default{$i}->[0]; #'cause we use it so much + ## showing 5 options seems like a nice round number; this should + ## probably be configurable; if you care, file a bug ;-) + my $boxSize = scalar(@{$optList}) < 5 ? scalar(@{$optList}) : 5; + + print "\n"; + last SWITCH; + }; + /^s$/ && do { + print "\n"; + last SWITCH; + }; # DEFAULT print "Unknown param type $::param_type{$i}!!!\n"; } diff --git a/globals.pl b/globals.pl index 6f7b22d38..9e2311a83 100644 --- a/globals.pl +++ b/globals.pl @@ -1413,36 +1413,40 @@ sub RemoveVotes { } } - sub Param ($) { my ($value) = (@_); - if (defined $::param{$value}) { - return $::param{$value}; + if (! defined $::param{$value}) { + # Um, maybe we haven't sourced in the params at all yet. + if (stat("data/params")) { + # Write down and restore the version # here. That way, we get + # around anyone who maliciously tries to tweak the version number + # by editing the params file. Not to mention that in 2.0, there + # was a bug that wrote the version number out to the params file... + my $v = $::param{'version'}; + require "data/params"; + $::param{'version'} = $v; + } } - # Um, maybe we haven't sourced in the params at all yet. - if (stat("data/params")) { - # Write down and restore the version # here. That way, we get around - # anyone who maliciously tries to tweak the version number by editing - # the params file. Not to mention that in 2.0, there was a bug that - # wrote the version number out to the params file... - my $v = $::param{'version'}; - require "data/params"; - $::param{'version'} = $v; + if (! defined $::param{$value}) { + # Well, that didn't help. Maybe it's a new param, and the user + # hasn't defined anything for it. Try and load a default value + # for it. + require "defparams.pl"; + WriteParams(); } - if (defined $::param{$value}) { - return $::param{$value}; + + # If it's still not defined, we're pimped. + die "Can't find param named $value" if (! defined $::param{$value}); + + if ($::param_type{$value} eq "m") { + my $valueList = eval($::param{$value}); + return $valueList if (!($@) && ref($valueList) eq "ARRAY"); + die "Multi-list param '$value' eval() failure ('$@'); data/params is horked"; } - # Well, that didn't help. Maybe it's a new param, and the user - # hasn't defined anything for it. Try and load a default value - # for it. - require "defparams.pl"; - WriteParams(); - if (defined $::param{$value}) { + else { return $::param{$value}; } - # We're pimped. - die "Can't find param named $value"; } # Take two comma or space separated strings and return what -- cgit v1.2.3-24-g4f1b