summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Bugzilla/FlagType.pm42
-rwxr-xr-xeditflagtypes.cgi91
-rw-r--r--template/en/default/admin/flag-type/edit.html.tmpl4
3 files changed, 91 insertions, 46 deletions
diff --git a/Bugzilla/FlagType.pm b/Bugzilla/FlagType.pm
index 6b4c31c7f..d07bb0b65 100644
--- a/Bugzilla/FlagType.pm
+++ b/Bugzilla/FlagType.pm
@@ -184,7 +184,9 @@ sub get_exclusions {
=item C<get_clusions($id, $type)>
-Someone please document this
+Return a hash of product/component IDs and names
+associated with the flagtype:
+$clusions{'product_name:component_name'} = "product_ID:component_ID"
=back
@@ -192,23 +194,29 @@ Someone please document this
sub get_clusions {
my ($id, $type) = @_;
-
- &::PushGlobalSQLState();
- &::SendSQL("SELECT products.name, components.name " .
- "FROM flagtypes, flag${type}clusions " .
- "LEFT OUTER JOIN products ON flag${type}clusions.product_id = products.id " .
- "LEFT OUTER JOIN components ON flag${type}clusions.component_id = components.id " .
- "WHERE flagtypes.id = $id AND flag${type}clusions.type_id = flagtypes.id");
- my @clusions = ();
- while (&::MoreSQLData()) {
- my ($product, $component) = &::FetchSQLData();
- $product ||= "Any";
- $component ||= "Any";
- push(@clusions, "$product:$component");
+ my $dbh = Bugzilla->dbh;
+
+ my $list =
+ $dbh->selectall_arrayref("SELECT products.id, products.name, " .
+ " components.id, components.name " .
+ "FROM flagtypes, flag${type}clusions " .
+ "LEFT OUTER JOIN products " .
+ " ON flag${type}clusions.product_id = products.id " .
+ "LEFT OUTER JOIN components " .
+ " ON flag${type}clusions.component_id = components.id " .
+ "WHERE flagtypes.id = ? " .
+ " AND flag${type}clusions.type_id = flagtypes.id",
+ undef, $id);
+ my %clusions;
+ foreach my $data (@$list) {
+ my ($product_id, $product_name, $component_id, $component_name) = @$data;
+ $product_id ||= 0;
+ $product_name ||= "__Any__";
+ $component_id ||= 0;
+ $component_name ||= "__Any__";
+ $clusions{"$product_name:$component_name"} = "$product_id:$component_id";
}
- &::PopGlobalSQLState();
-
- return \@clusions;
+ return \%clusions;
}
=pod
diff --git a/editflagtypes.cgi b/editflagtypes.cgi
index ed80a0130..bdf0779b4 100755
--- a/editflagtypes.cgi
+++ b/editflagtypes.cgi
@@ -146,9 +146,11 @@ sub edit {
# Otherwise set the target type (the minimal information about the type
# that the template needs to know) from the URL parameter and default
# the list of inclusions to all categories.
- else {
+ else {
+ my %inclusions;
+ $inclusions{"__Any__:__Any__"} = "0:0";
$vars->{'type'} = { 'target_type' => scalar $cgi->param('target_type'),
- 'inclusions' => ["__Any__:__Any__"] };
+ 'inclusions' => \%inclusions };
}
# Return the appropriate HTTP response headers.
@@ -171,13 +173,13 @@ sub processCategoryChange {
if ($categoryAction eq 'include') {
validateProduct();
validateComponent();
- my $category = ($cgi->param('product') || "__Any__") . ":" . ($cgi->param('component') || "__Any__");
+ my $category = ($product_id || 0) . ":" . ($component_id || 0);
push(@inclusions, $category) unless grep($_ eq $category, @inclusions);
}
elsif ($categoryAction eq 'exclude') {
validateProduct();
validateComponent();
- my $category = ($cgi->param('product') || "__Any__") . ":" . ($cgi->param('component') || "__Any__");
+ my $category = ($product_id || 0) . ":" . ($component_id || 0);
push(@exclusions, $category) unless grep($_ eq $category, @exclusions);
}
elsif ($categoryAction eq 'removeInclusion') {
@@ -187,6 +189,11 @@ sub processCategoryChange {
@exclusions = map(($_ eq $cgi->param('exclusion_to_remove') ? () : $_), @exclusions);
}
+ # Convert the array @clusions('prod_ID:comp_ID') back to a hash of
+ # the form %clusions{'prod_name:comp_name'} = 'prod_ID:comp_ID'
+ my %inclusions = clusion_array_to_hash(\@inclusions);
+ my %exclusions = clusion_array_to_hash(\@exclusions);
+
# Get this installation's products and components.
GetVersionTable();
@@ -199,8 +206,8 @@ sub processCategoryChange {
$vars->{'action'} = $cgi->param('action');
my $type = {};
foreach my $key ($cgi->param()) { $type->{$key} = $cgi->param($key) }
- $type->{'inclusions'} = \@inclusions;
- $type->{'exclusions'} = \@exclusions;
+ $type->{'inclusions'} = \%inclusions;
+ $type->{'exclusions'} = \%exclusions;
$vars->{'type'} = $type;
# Return the appropriate HTTP response headers.
@@ -211,6 +218,21 @@ sub processCategoryChange {
|| ThrowTemplateError($template->error());
}
+# Convert the array @clusions('prod_ID:comp_ID') back to a hash of
+# the form %clusions{'prod_name:comp_name'} = 'prod_ID:comp_ID'
+sub clusion_array_to_hash {
+ my $array = shift;
+ my %hash;
+ foreach my $ids (@$array) {
+ trick_taint($ids);
+ my ($product_id, $component_id) = split(":", $ids);
+ my $product_name = get_product_name($product_id) || "__Any__";
+ my $component_name = get_component_name($component_id) || "__Any__";
+ $hash{"$product_name:$component_name"} = $ids;
+ }
+ return %hash;
+}
+
sub insert {
validateName();
validateDescription();
@@ -253,16 +275,7 @@ sub insert {
$cgi->param('request_gid') . ")");
# Populate the list of inclusions/exclusions for this flag type.
- foreach my $category_type ("inclusions", "exclusions") {
- foreach my $category ($cgi->param($category_type)) {
- my ($product, $component) = split(/:/, $category);
- my $product_id = get_product_id($product) || "NULL";
- my $component_id =
- get_component_id($product_id, $component) || "NULL";
- SendSQL("INSERT INTO flag$category_type (type_id, product_id, " .
- "component_id) VALUES ($id, $product_id, $component_id)");
- }
- }
+ validateAndSubmit($id);
$dbh->bz_unlock_tables();
@@ -314,17 +327,7 @@ sub update {
WHERE id = $id");
# Update the list of inclusions/exclusions for this flag type.
- foreach my $category_type ("inclusions", "exclusions") {
- SendSQL("DELETE FROM flag$category_type WHERE type_id = $id");
- foreach my $category ($cgi->param($category_type)) {
- my ($product, $component) = split(/:/, $category);
- my $product_id = get_product_id($product) || "NULL";
- my $component_id =
- get_component_id($product_id, $component) || "NULL";
- SendSQL("INSERT INTO flag$category_type (type_id, product_id, " .
- "component_id) VALUES ($id, $product_id, $component_id)");
- }
- }
+ validateAndSubmit($id);
$dbh->bz_unlock_tables();
@@ -558,3 +561,37 @@ sub validateGroups {
$cgi->param($col, $gid);
}
}
+
+# At this point, values either come the DB itself or have been recently
+# added by the user and have passed all validation tests.
+# The only way to have invalid product/component combinations is to
+# hack the URL. So we silently ignore them, if any.
+sub validateAndSubmit ($) {
+ my ($id) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ foreach my $category_type ("inclusions", "exclusions") {
+ # Will be used several times below.
+ my $sth = $dbh->prepare("INSERT INTO flag$category_type " .
+ "(type_id, product_id, component_id) " .
+ "VALUES (?, ?, ?)");
+
+ $dbh->do("DELETE FROM flag$category_type WHERE type_id = ?", undef, $id);
+ foreach my $category ($cgi->param($category_type)) {
+ trick_taint($category);
+ my ($product_id, $component_id) = split(":", $category);
+ # The product does not exist.
+ next if ($product_id && !get_product_name($product_id));
+ # A component was selected without a product being selected.
+ next if (!$product_id && $component_id);
+ # The component does not belong to this product.
+ next if ($component_id
+ && !$dbh->selectrow_array("SELECT id FROM components
+ WHERE id = ? AND product_id = ?",
+ undef, ($component_id, $product_id)));
+ $product_id ||= undef;
+ $component_id ||= undef;
+ $sth->execute($id, $product_id, $component_id);
+ }
+ }
+}
diff --git a/template/en/default/admin/flag-type/edit.html.tmpl b/template/en/default/admin/flag-type/edit.html.tmpl
index 8afbc38cb..8491a1e7f 100644
--- a/template/en/default/admin/flag-type/edit.html.tmpl
+++ b/template/en/default/admin/flag-type/edit.html.tmpl
@@ -64,10 +64,10 @@
<input type="hidden" name="id" value="[% type.id %]">
<input type="hidden" name="target_type" value="[% type.target_type %]">
[% FOREACH category = type.inclusions %]
- <input type="hidden" name="inclusions" value="[% category FILTER html %]">
+ <input type="hidden" name="inclusions" value="[% category.value FILTER html %]">
[% END %]
[% FOREACH category = type.exclusions %]
- <input type="hidden" name="exclusions" value="[% category FILTER html %]">
+ <input type="hidden" name="exclusions" value="[% category.value FILTER html %]">
[% END %]
<table id="form" cellspacing="0" cellpadding="4" border="0">