Commit 6b44875b authored by lpsolit%gmail.com's avatar lpsolit%gmail.com

Bug 286158: Remove GetSelectableProducts() from globals.pl and use…

Bug 286158: Remove GetSelectableProducts() from globals.pl and use Bugzilla::User::get_selectable_products() instead - Patch by Frédéric Buclin <LpSolit@gmail.com> r=joel,kiko a=justdave
parent 3c36f041
...@@ -121,11 +121,11 @@ sub get_components_by_product { ...@@ -121,11 +121,11 @@ sub get_components_by_product {
SELECT id FROM components SELECT id FROM components
WHERE product_id = ?}, undef, $product_id); WHERE product_id = ?}, undef, $product_id);
my $components; my @components;
foreach my $id (@$ids) { foreach my $id (@$ids) {
$components->{$id} = new Bugzilla::Component($id); push @components, new Bugzilla::Component($id);
} }
return $components; return @components;
} }
1; 1;
...@@ -151,8 +151,7 @@ Bugzilla::Component - Bugzilla product component class. ...@@ -151,8 +151,7 @@ Bugzilla::Component - Bugzilla product component class.
my $default_assignee = $component->default_assignee; my $default_assignee = $component->default_assignee;
my $default_qa_contact = $component->default_qa_contact; my $default_qa_contact = $component->default_qa_contact;
my $hash_ref = Bugzilla::Component::get_components_by_product(1); my @components = Bugzilla::Component::get_components_by_product($id);
my $component = $hash_ref->{1};
=head1 DESCRIPTION =head1 DESCRIPTION
...@@ -184,13 +183,11 @@ Component.pm represents a Product Component object. ...@@ -184,13 +183,11 @@ Component.pm represents a Product Component object.
=item C<get_components_by_product($product_id)> =item C<get_components_by_product($product_id)>
Description: Returns all Bugzilla components that belong to the Description: Returns all components that belong to the supplied product.
supplied product.
Params: $product_id - Integer with a Bugzilla product id. Params: $product_id - Integer with a Bugzilla product id.
Returns: A hash with component id as key and Bugzilla::Component Returns: An array of Bugzilla::Component objects.
object as value.
=back =back
......
...@@ -98,8 +98,9 @@ sub components { ...@@ -98,8 +98,9 @@ sub components {
my $self = shift; my $self = shift;
if (!defined $self->{components}) { if (!defined $self->{components}) {
$self->{components} = my @components =
Bugzilla::Component::get_components_by_product($self->id); Bugzilla::Component::get_components_by_product($self->id);
$self->{components} = \@components;
} }
return $self->{components}; return $self->{components};
} }
...@@ -247,11 +248,11 @@ Bugzilla::Product - Bugzilla product class. ...@@ -247,11 +248,11 @@ Bugzilla::Product - Bugzilla product class.
my $product = new Bugzilla::Product(1); my $product = new Bugzilla::Product(1);
my $product = new Bugzilla::Product('AcmeProduct'); my $product = new Bugzilla::Product('AcmeProduct');
my $components = $product->components(); my @components = $product->components();
my $classification = $product->classification(); my $classification = $product->classification();
my $hash_ref = $product->group_controls(); my $groups_controls = $product->group_controls();
my @array_ref = $product->milestones(); my @milestones = $product->milestones();
my @array_ref = $product->versions(); my @versions = $product->versions();
my $bugcount = $product->bug_count(); my $bugcount = $product->bug_count();
my $id = $product->id; my $id = $product->id;
...@@ -290,12 +291,12 @@ Product.pm represents a product object. ...@@ -290,12 +291,12 @@ Product.pm represents a product object.
=item C<components()> =item C<components()>
Description: Returns a hash with all product components. Description: Returns an array of component objects belonging to
the product.
Params: none. Params: none.
Returns: A hash where component id is the hash key and Returns: An array of Bugzilla::Component object.
Bugzilla::Component object is the hash value.
=item C<classification()> =item C<classification()>
......
...@@ -61,8 +61,6 @@ use constant USER_MATCH_SUCCESS => 1; ...@@ -61,8 +61,6 @@ use constant USER_MATCH_SUCCESS => 1;
use constant MATCH_SKIP_CONFIRM => 1; use constant MATCH_SKIP_CONFIRM => 1;
use constant GET_PRODUCTS_BY_ID => 1;
################################################################################ ################################################################################
# Functions # Functions
################################################################################ ################################################################################
...@@ -420,13 +418,12 @@ sub can_see_bug { ...@@ -420,13 +418,12 @@ sub can_see_bug {
sub get_selectable_products { sub get_selectable_products {
my ($self, $by_id) = @_; my ($self, $by_id) = @_;
if (defined $self->{SelectableProducts}) { if (defined $self->{selectable_products}) {
my %list = @{$self->{SelectableProducts}}; return $self->{selectable_products};
return \%list if $by_id;
return values(%list);
} }
my $query = "SELECT id, name " . my $dbh = Bugzilla->dbh;
my $query = "SELECT id " .
"FROM products " . "FROM products " .
"LEFT JOIN group_control_map " . "LEFT JOIN group_control_map " .
"ON group_control_map.product_id = products.id "; "ON group_control_map.product_id = products.id ";
...@@ -439,38 +436,31 @@ sub get_selectable_products { ...@@ -439,38 +436,31 @@ sub get_selectable_products {
$query .= "AND group_id NOT IN(" . $query .= "AND group_id NOT IN(" .
$self->groups_as_string . ") " . $self->groups_as_string . ") " .
"WHERE group_id IS NULL ORDER BY name"; "WHERE group_id IS NULL ORDER BY name";
my $dbh = Bugzilla->dbh;
my $sth = $dbh->prepare($query); my $prod_ids = $dbh->selectcol_arrayref($query);
$sth->execute(); my @products;
my @products = (); foreach my $prod_id (@$prod_ids) {
while (my @row = $sth->fetchrow_array) { push(@products, new Bugzilla::Product($prod_id));
push(@products, @row);
} }
$self->{SelectableProducts} = \@products; $self->{selectable_products} = \@products;
my %list = @products; return $self->{selectable_products};
return \%list if $by_id;
return values(%list);
} }
sub get_selectable_classifications ($) { sub get_selectable_classifications {
my ($self) = @_; my ($self) = @_;
if (defined $self->{selectable_classifications}) { if (defined $self->{selectable_classifications}) {
return $self->{selectable_classifications}; return $self->{selectable_classifications};
} }
my $products = $self->get_selectable_products(GET_PRODUCTS_BY_ID); my $products = $self->get_selectable_products;
my $selectable_classifications; my $class;
foreach my $product (@$products) {
foreach my $prod_id (keys %$products) { $class->{$product->classification_id} ||= $product->classification;
my $product = new Bugzilla::Product($prod_id);
$selectable_classifications->{$product->classification_id} =
$product->classification;
} }
$self->{selectable_classifications} = my @sorted_class = sort {lc($a->name) cmp lc($b->name)} (values %$class);
[values %$selectable_classifications]; $self->{selectable_classifications} = \@sorted_class;
return $self->{selectable_classifications}; return $self->{selectable_classifications};
} }
...@@ -1450,22 +1440,23 @@ care of by the constructor. However, when updating the email address, the ...@@ -1450,22 +1440,23 @@ care of by the constructor. However, when updating the email address, the
user may be placed into different groups, based on a new email regexp. This user may be placed into different groups, based on a new email regexp. This
method should be called in such a case to force reresolution of these groups. method should be called in such a case to force reresolution of these groups.
=item C<get_selectable_products(by_id)> =item C<get_selectable_products>
Description: Returns all products the user is allowed to access.
Params: none
Returns an alphabetical list of product names from which Returns: An array of product objects, sorted by the product name.
the user can select bugs. If the $by_id parameter is true, it returns
a hash where the keys are the product ids and the values are the
product names.
=item C<get_selectable_classifications> =item C<get_selectable_classifications>
Description: Returns the classifications that a user, according his Description: Returns all classifications containing at least one product
groups ownership, can select to entering, serch, view or the user is allowed to view.
edit a bug.
Params: none. Params: none
Returns: Bugzilla::Classification objects values. Returns: An array of Bugzilla::Classification objects, sorted by
the classification name.
=item C<get_userlist> =item C<get_userlist>
......
...@@ -64,11 +64,8 @@ $vars->{'keyword'} = \@::legal_keywords; ...@@ -64,11 +64,8 @@ $vars->{'keyword'} = \@::legal_keywords;
$vars->{'resolution'} = \@::legal_resolution; $vars->{'resolution'} = \@::legal_resolution;
$vars->{'status'} = \@::legal_bug_status; $vars->{'status'} = \@::legal_bug_status;
# Include lists of products, components, versions, and target milestones. # Include a list of product objects.
my $selectables = GetSelectableProductHash(); $vars->{'products'} = Bugzilla->user->get_selectable_products;
foreach my $selectable (keys %$selectables) {
$vars->{$selectable} = $selectables->{$selectable};
}
# Create separate lists of open versus resolved statuses. This should really # Create separate lists of open versus resolved statuses. This should really
# be made part of the configuration. # be made part of the configuration.
......
...@@ -265,8 +265,7 @@ $vars->{'openonly'} = $openonly; ...@@ -265,8 +265,7 @@ $vars->{'openonly'} = $openonly;
$vars->{'reverse'} = $reverse; $vars->{'reverse'} = $reverse;
$vars->{'format'} = $cgi->param('format'); $vars->{'format'} = $cgi->param('format');
$vars->{'query_products'} = \@query_products; $vars->{'query_products'} = \@query_products;
my @selectable_products = GetSelectableProducts(); $vars->{'products'} = Bugzilla->user->get_selectable_products;
$vars->{'products'} = \@selectable_products;
my $format = $template->get_format("reports/duplicates", my $format = $template->get_format("reports/duplicates",
......
...@@ -80,21 +80,13 @@ if (!defined $product || $product eq "") { ...@@ -80,21 +80,13 @@ if (!defined $product || $product eq "") {
} }
if (!$cgi->param('classification')) { if (!$cgi->param('classification')) {
my %classdesc; my $classifications = Bugzilla->user->get_selectable_classifications();
my %classifications;
foreach my $c (GetSelectableClassifications()) {
$classdesc{$c} = $::classdesc{$c};
$classifications{$c} = $::classifications{$c};
}
my $classification_size = scalar(keys %classdesc); if (scalar(@$classifications) == 0) {
if ($classification_size == 0) {
ThrowUserError("no_products"); ThrowUserError("no_products");
} }
elsif ($classification_size > 1) { elsif (scalar(@$classifications) > 1) {
$vars->{'classdesc'} = \%classdesc; $vars->{'classifications'} = $classifications;
$vars->{'classifications'} = \%classifications;
$vars->{'target'} = "enter_bug.cgi"; $vars->{'target'} = "enter_bug.cgi";
$vars->{'format'} = $cgi->param('format'); $vars->{'format'} = $cgi->param('format');
...@@ -106,7 +98,7 @@ if (!defined $product || $product eq "") { ...@@ -106,7 +98,7 @@ if (!defined $product || $product eq "") {
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
} }
$cgi->param(-name => 'classification', -value => (keys %classdesc)[0]); $cgi->param(-name => 'classification', -value => @$classifications[0]->name);
} }
my %products; my %products;
......
...@@ -518,113 +518,6 @@ sub GetEnterableProducts { ...@@ -518,113 +518,6 @@ sub GetEnterableProducts {
return (@products); return (@products);
} }
#
# This function returns an alphabetical list of product names to which
# the user can enter bugs. If the $by_id parameter is true, also retrieves IDs
# and pushes them onto the list as id, name [, id, name...] for easy slurping
# into a hash by the calling code.
sub GetSelectableProducts {
my ($by_id,$by_classification) = @_;
my $extra_sql = $by_id ? "id, " : "";
my $extra_from_sql = $by_classification ? " INNER JOIN classifications"
. " ON classifications.id = products.classification_id" : "";
my $query = "SELECT $extra_sql products.name " .
"FROM products $extra_from_sql " .
"LEFT JOIN group_control_map " .
"ON group_control_map.product_id = products.id ";
if (Param('useentrygroupdefault')) {
$query .= "AND group_control_map.entry != 0 ";
} else {
$query .= "AND group_control_map.membercontrol = " .
CONTROLMAPMANDATORY . " ";
}
if (%{Bugzilla->user->groups}) {
$query .= "AND group_id NOT IN(" .
join(',', values(%{Bugzilla->user->groups})) . ") ";
}
$query .= "WHERE group_id IS NULL ";
if ($by_classification) {
$query .= "AND classifications.name = ";
$query .= SqlQuote($by_classification) . " ";
}
$query .= "ORDER BY name";
PushGlobalSQLState();
SendSQL($query);
my @products = ();
push(@products, FetchSQLData()) while MoreSQLData();
PopGlobalSQLState();
return (@products);
}
# GetSelectableProductHash
# returns a hash containing
# legal_products => an enterable product list
# legal_(components|versions|milestones) =>
# the list of components, versions, and milestones of enterable products
# (components|versions|milestones)_by_product
# => a hash of component lists for each enterable product
# Milestones only get returned if the usetargetmilestones parameter is set.
sub GetSelectableProductHash {
# The hash of selectable products and their attributes that gets returned
# at the end of this function.
my $selectables = {};
my %products = GetSelectableProducts(1);
$selectables->{legal_products} = [sort values %products];
# Run queries that retrieve the list of components, versions,
# and target milestones (if used) for the selectable products.
my @tables = qw(components versions);
push(@tables, 'milestones') if Param('usetargetmilestone');
PushGlobalSQLState();
foreach my $table (@tables) {
my %values;
my %values_by_product;
if (scalar(keys %products)) {
# Why oh why can't we standardize on these names?!?
my $fld = ($table eq "components" ? "name" : "value");
my $query = "SELECT $fld, product_id FROM $table WHERE product_id " .
"IN (" . join(",", keys %products) . ") ORDER BY $fld";
SendSQL($query);
while (MoreSQLData()) {
my ($name, $product_id) = FetchSQLData();
next unless $name;
$values{$name} = 1;
push @{$values_by_product{$products{$product_id}}}, $name;
}
}
$selectables->{"legal_$table"} = [sort keys %values];
$selectables->{"${table}_by_product"} = \%values_by_product;
}
PopGlobalSQLState();
return $selectables;
}
#
# This function returns an alphabetical list of classifications that has products the user can enter bugs.
sub GetSelectableClassifications {
my @selectable_classes = ();
foreach my $c (sort keys %::classdesc) {
if ( scalar(GetSelectableProducts(0,$c)) > 0) {
push(@selectable_classes,$c);
}
}
return (@selectable_classes);
}
sub ValidatePassword { sub ValidatePassword {
# Determines whether or not a password is valid (i.e. meets Bugzilla's # Determines whether or not a password is valid (i.e. meets Bugzilla's
# requirements for length and content). # requirements for length and content).
......
...@@ -66,7 +66,8 @@ if ($cgi->param("GoAheadAndLogIn")) { ...@@ -66,7 +66,8 @@ if ($cgi->param("GoAheadAndLogIn")) {
Bugzilla->login(); Bugzilla->login();
} }
my $userid = Bugzilla->user->id; my $user = Bugzilla->user;
my $userid = $user->id;
# Backwards compatibility hack -- if there are any of the old QUERY_* # Backwards compatibility hack -- if there are any of the old QUERY_*
# cookies around, and we are logged in, then move them into the database # cookies around, and we are logged in, then move them into the database
...@@ -219,23 +220,26 @@ GetVersionTable(); ...@@ -219,23 +220,26 @@ GetVersionTable();
# if using groups for entry, then we don't want people to see products they # if using groups for entry, then we don't want people to see products they
# don't have access to. Remove them from the list. # don't have access to. Remove them from the list.
my @products = (); my @selectable_product_objects = @{$user->get_selectable_products};
my %component_set; my %component_set;
my %version_set; my %version_set;
my %milestone_set; my %milestone_set;
foreach my $p (GetSelectableProducts()) { # extract product names
my @products = map { $_->name } @selectable_product_objects;
foreach my $prod_name (@products) {
# We build up boolean hashes in the "-set" hashes for each of these things # We build up boolean hashes in the "-set" hashes for each of these things
# before making a list because there may be duplicates names across products. # before making a list because there may be duplicates names across products.
push @products, $p; if ($::components{$prod_name}) {
if ($::components{$p}) { foreach my $c (@{$::components{$prod_name}}) {
foreach my $c (@{$::components{$p}}) {
$component_set{$c} = 1; $component_set{$c} = 1;
} }
} }
foreach my $v (@{$::versions{$p}}) { foreach my $v (@{$::versions{$prod_name}}) {
$version_set{$v} = 1; $version_set{$v} = 1;
} }
foreach my $m (@{$::target_milestone{$p}}) { foreach my $m (@{$::target_milestone{$prod_name}}) {
$milestone_set{$m} = 1; $milestone_set{$m} = 1;
} }
} }
...@@ -296,11 +300,16 @@ $vars->{'product'} = \@products; ...@@ -296,11 +300,16 @@ $vars->{'product'} = \@products;
if (Param('useclassification')) { if (Param('useclassification')) {
my @classifications = (); my @classifications = ();
foreach my $c (GetSelectableClassifications()) { my $class = $user->get_selectable_classifications;
foreach my $c (@$class) {
# Extract the name of products being in this classification.
my @prod_in_class
= grep { $_->classification_id == $c->id } @selectable_product_objects;
@prod_in_class = map { $_->name } @prod_in_class;
# Create hash to hold attributes for each classification. # Create hash to hold attributes for each classification.
my %classification = ( my %classification = (
'name' => $c, 'name' => $c->name,
'products' => [ GetSelectableProducts(0,$c) ] 'products' => \@prod_in_class
); );
# Assign hash back to classification array. # Assign hash back to classification array.
push @classifications, \%classification; push @classifications, \%classification;
......
...@@ -54,7 +54,7 @@ use Bugzilla; ...@@ -54,7 +54,7 @@ use Bugzilla;
# If we're using bug groups for products, we should apply those restrictions # If we're using bug groups for products, we should apply those restrictions
# to viewing reports, as well. Time to check the login in that case. # to viewing reports, as well. Time to check the login in that case.
Bugzilla->login(); my $user = Bugzilla->login();
GetVersionTable(); GetVersionTable();
...@@ -66,7 +66,8 @@ my $template = Bugzilla->template; ...@@ -66,7 +66,8 @@ my $template = Bugzilla->template;
# We only want those products that the user has permissions for. # We only want those products that the user has permissions for.
my @myproducts; my @myproducts;
push( @myproducts, "-All-"); push( @myproducts, "-All-");
push( @myproducts, GetSelectableProducts()); # Extract product names from objects and add them to the list.
push( @myproducts, map { $_->name } @{$user->get_selectable_products} );
if (! defined $cgi->param('product')) { if (! defined $cgi->param('product')) {
......
...@@ -27,28 +27,26 @@ ...@@ -27,28 +27,26 @@
# Make it harder for us to do dangerous things in Perl. # Make it harder for us to do dangerous things in Perl.
use strict; use strict;
# Include the Bugzilla CGI and general utility library.
use lib qw(.); use lib qw(.);
require "globals.pl"; require "globals.pl";
use Bugzilla; use Bugzilla;
# Use Bugzilla's Request module which contains utilities for handling requests.
use Bugzilla::Flag; use Bugzilla::Flag;
use Bugzilla::FlagType; use Bugzilla::FlagType;
# use Bugzilla's User module which contains utilities for handling users.
use Bugzilla::User; use Bugzilla::User;
use vars qw($template $vars @legal_product @legal_components %components); use vars qw($template $vars);
# Make sure the user is logged in. # Make sure the user is logged in.
Bugzilla->login(); my $user = Bugzilla->login();
my $userid = $user->id;
my $cgi = Bugzilla->cgi;
################################################################################ ################################################################################
# Main Body Execution # Main Body Execution
################################################################################ ################################################################################
my $cgi = Bugzilla->cgi;
my $fields; my $fields;
$fields->{'requester'}->{'type'} = 'single'; $fields->{'requester'}->{'type'} = 'single';
# If the user doesn't restrict his search to requests from the wind # If the user doesn't restrict his search to requests from the wind
...@@ -116,17 +114,17 @@ sub queue { ...@@ -116,17 +114,17 @@ sub queue {
LEFT JOIN bug_group_map AS bgmap LEFT JOIN bug_group_map AS bgmap
ON bgmap.bug_id = bugs.bug_id ON bgmap.bug_id = bugs.bug_id
AND bgmap.group_id NOT IN (" . AND bgmap.group_id NOT IN (" .
join(', ', (-1, values(%{Bugzilla->user->groups}))) . ") join(', ', (-1, values(%{$user->groups}))) . ")
LEFT JOIN cc AS ccmap LEFT JOIN cc AS ccmap
ON ccmap.who = $::userid ON ccmap.who = $userid
AND ccmap.bug_id = bugs.bug_id AND ccmap.bug_id = bugs.bug_id
" . " .
# Weed out bug the user does not have access to # Weed out bug the user does not have access to
" WHERE ((bgmap.group_id IS NULL) OR " WHERE ((bgmap.group_id IS NULL) OR
(ccmap.who IS NOT NULL AND cclist_accessible = 1) OR (ccmap.who IS NOT NULL AND cclist_accessible = 1) OR
(bugs.reporter = $::userid AND bugs.reporter_accessible = 1) OR (bugs.reporter = $userid AND bugs.reporter_accessible = 1) OR
(bugs.assigned_to = $::userid))"; (bugs.assigned_to = $userid))";
# Non-deleted flags only # Non-deleted flags only
$query .= " AND flags.is_active = 1 "; $query .= " AND flags.is_active = 1 ";
...@@ -279,15 +277,7 @@ sub queue { ...@@ -279,15 +277,7 @@ sub queue {
SendSQL("SELECT DISTINCT(name) FROM flagtypes ORDER BY name"); SendSQL("SELECT DISTINCT(name) FROM flagtypes ORDER BY name");
push(@types, FetchOneColumn()) while MoreSQLData(); push(@types, FetchOneColumn()) while MoreSQLData();
# products and components and the function used to modify the components $vars->{'products'} = $user->get_selectable_products;
# menu when the products menu changes; used by the template to populate
# the menus and keep the components menu consistent with the products menu
GetVersionTable();
my $selectable = GetSelectableProductHash();
$vars->{'products'} = $selectable->{legal_products};
$vars->{'components'} = $selectable->{legal_components};
$vars->{'components_by_product'} = $selectable->{components_by_product};
$vars->{'excluded_columns'} = \@excluded_columns; $vars->{'excluded_columns'} = \@excluded_columns;
$vars->{'group_field'} = $form_group; $vars->{'group_field'} = $form_group;
$vars->{'requests'} = \@requests; $vars->{'requests'} = \@requests;
......
...@@ -73,10 +73,10 @@ var component = new Object(); ...@@ -73,10 +73,10 @@ var component = new Object();
var version = new Object(); var version = new Object();
var target_milestone = new Object(); var target_milestone = new Object();
[% FOREACH p = legal_products %] [% FOREACH p = products %]
component['[% p FILTER js %]'] = [ [% FOREACH x = components_by_product.$p %]'[% x FILTER js %]', [% END %] ]; component['[% p.name FILTER js %]'] = [ [% FOREACH x = p.components %]'[% x.name FILTER js %]', [% END %] ];
version['[% p FILTER js %]'] = [ [% FOREACH x = versions_by_product.$p %]'[% x FILTER js %]', [% END %] ]; version['[% p.name FILTER js %]'] = [ [% FOREACH x = p.versions %]'[% x.name FILTER js %]', [% END %] ];
target_milestone['[% p FILTER js %]'] = [ [% FOREACH x = milestones_by_product.$p %]'[% x FILTER js %]', [% END %] ]; target_milestone['[% p.name FILTER js %]'] = [ [% FOREACH x = p.milestones %]'[% x.name FILTER js %]', [% END %] ];
[% END %] [% END %]
// Product and Component Exceptions // Product and Component Exceptions
......
...@@ -105,23 +105,23 @@ ...@@ -105,23 +105,23 @@
<bz:products> <bz:products>
<Seq> <Seq>
[% FOREACH product = legal_products %] [% FOREACH product = products %]
<li> <li>
<bz:product rdf:about="[% Param('urlbase') %]product.cgi?name=[% product FILTER uri %]"> <bz:product rdf:about="[% Param('urlbase') %]product.cgi?name=[% product.name FILTER uri %]">
<bz:name>[% product FILTER html %]</bz:name> <bz:name>[% product.name FILTER html %]</bz:name>
<bz:components> <bz:components>
<Seq> <Seq>
[% FOREACH component = components_by_product.$product %] [% FOREACH component = product.components %]
<li resource="[% Param('urlbase') %]component.cgi?name=[% component FILTER uri %]"/> <li resource="[% Param('urlbase') %]component.cgi?name=[% component.name FILTER uri %]"/>
[% END %] [% END %]
</Seq> </Seq>
</bz:components> </bz:components>
<bz:versions> <bz:versions>
<Seq> <Seq>
[% FOREACH version = versions_by_product.$product %] [% FOREACH version = product.versions %]
<li resource="[% Param('urlbase') %]version.cgi?name=[% version FILTER uri %]"/> <li resource="[% Param('urlbase') %]version.cgi?name=[% version.name FILTER uri %]"/>
[% END %] [% END %]
</Seq> </Seq>
</bz:versions> </bz:versions>
...@@ -129,8 +129,8 @@ ...@@ -129,8 +129,8 @@
[% IF Param('usetargetmilestone') %] [% IF Param('usetargetmilestone') %]
<bz:target_milestones> <bz:target_milestones>
<Seq> <Seq>
[% FOREACH milestone = milestones_by_product.$product %] [% FOREACH milestone = product.milestones %]
<li resource="[% Param('urlbase') %]milestone.cgi?name=[% milestone FILTER uri %]"/> <li resource="[% Param('urlbase') %]milestone.cgi?name=[% milestone.name FILTER uri %]"/>
[% END %] [% END %]
</Seq> </Seq>
</bz:target_milestones> </bz:target_milestones>
...@@ -144,24 +144,28 @@ ...@@ -144,24 +144,28 @@
<bz:components> <bz:components>
<Seq> <Seq>
[% FOREACH item = legal_components %] [% FOREACH product = products %]
<li> [% FOREACH component = product.components %]
<bz:component rdf:about="[% Param('urlbase') %]component.cgi?name=[% item FILTER uri %]"> <li>
<bz:name>[% item FILTER html %]</bz:name> <bz:component rdf:about="[% Param('urlbase') %]component.cgi?name=[% component.name FILTER uri %]">
</bz:component> <bz:name>[% component.name FILTER html %]</bz:name>
</li> </bz:component>
</li>
[% END %]
[% END %] [% END %]
</Seq> </Seq>
</bz:components> </bz:components>
<bz:versions> <bz:versions>
<Seq> <Seq>
[% FOREACH item = legal_versions %] [% FOREACH product = products %]
<li> [% FOREACH version = product.versions %]
<bz:version rdf:about="[% Param('urlbase') %]version.cgi?name=[% item FILTER uri %]"> <li>
<bz:name>[% item FILTER html %]</bz:name> <bz:version rdf:about="[% Param('urlbase') %]version.cgi?name=[% version.name FILTER uri %]">
</bz:version> <bz:name>[% version.name FILTER html %]</bz:name>
</li> </bz:version>
</li>
[% END %]
[% END %] [% END %]
</Seq> </Seq>
</bz:versions> </bz:versions>
...@@ -169,12 +173,14 @@ ...@@ -169,12 +173,14 @@
[% IF Param('usetargetmilestone') %] [% IF Param('usetargetmilestone') %]
<bz:target_milestones> <bz:target_milestones>
<Seq> <Seq>
[% FOREACH item = legal_milestones %] [% FOREACH product = products %]
<li> [% FOREACH milestone = product.milestones %]
<bz:target_milestone rdf:about="[% Param('urlbase') %]milestone.cgi?name=[% item FILTER uri %]"> <li>
<bz:name>[% item FILTER html %]</bz:name> <bz:target_milestone rdf:about="[% Param('urlbase') %]milestone.cgi?name=[% milestone.name FILTER uri %]">
</bz:target_milestone> <bz:name>[% milestone.name FILTER html %]</bz:name>
</li> </bz:target_milestone>
</li>
[% END %]
[% END %] [% END %]
</Seq> </Seq>
</bz:target_milestones> </bz:target_milestones>
......
...@@ -244,7 +244,7 @@ ...@@ -244,7 +244,7 @@
], ],
'global/choose-classification.html.tmpl' => [ 'global/choose-classification.html.tmpl' => [
'classdesc.$p', 'class.description',
], ],
'global/choose-product.html.tmpl' => [ 'global/choose-product.html.tmpl' => [
......
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
#%] #%]
[%# INTERFACE: [%# INTERFACE:
# classdesc: hash. May be empty. The hash keys are the classifications, and the values # classifications: an array of classification objects containing
# are their descriptions. # at least one product accessible by the user.
#%] #%]
[% IF target == "enter_bug.cgi" %] [% IF target == "enter_bug.cgi" %]
...@@ -45,21 +45,19 @@ ...@@ -45,21 +45,19 @@
</tr> </tr>
[% END %] [% END %]
[% FOREACH p = classdesc.keys.sort %] [% FOREACH class = classifications %]
[% IF classifications.$p.size > 0 %]
<tr> <tr>
<th align="right" valign="top"> <th align="right" valign="top">
<a href="[% target FILTER url_quote %]?classification=[% p FILTER url_quote -%] <a href="[% target FILTER url_quote %]?classification=[% class.name FILTER url_quote -%]
[%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER url_quote %][% END -%] [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER url_quote %][% END -%]
[%- IF format %]&amp;format=[% format FILTER url_quote %][% END %]"> [%- IF format %]&amp;format=[% format FILTER url_quote %][% END %]">
[% p FILTER html %]</a>: [% class.name FILTER html %]</a>:
</th> </th>
[% IF classdesc.$p %] [% IF class.description %]
<td valign="top">&nbsp;[% classdesc.$p %]</td> <td valign="top">&nbsp;[% class.description %]</td>
[% END %] [% END %]
</tr> </tr>
[% END %]
[% END %] [% END %]
</table> </table>
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#%] #%]
[%# INTERFACE: [%# INTERFACE:
# products: list of strings. The products this user can see. # products: an array of product objects this user can see.
# #
# sortby: string. the column on which we are sorting the buglist. # sortby: string. the column on which we are sorting the buglist.
# reverse: boolean. True if we are reversing the current sort. # reverse: boolean. True if we are reversing the current sort.
...@@ -84,9 +84,9 @@ ...@@ -84,9 +84,9 @@
<td rowspan="4" valign="top"> <td rowspan="4" valign="top">
<select name="product" size="5" multiple="multiple"> <select name="product" size="5" multiple="multiple">
[% FOREACH p = products %] [% FOREACH p = products %]
<option name="[% p FILTER html %]" <option name="[% p.name FILTER html %]"
[% " selected" IF lsearch(query_products, p) != -1 %] [% " selected" IF lsearch(query_products, p.name) != -1 %]
>[% p FILTER html %]</option> >[% p.name FILTER html %]</option>
[% END %] [% END %]
</select> </select>
</td> </td>
......
...@@ -30,9 +30,9 @@ ...@@ -30,9 +30,9 @@
var first_load = 1; // is this the first time we load the page? var first_load = 1; // is this the first time we load the page?
var last_sel = []; // caches last selection var last_sel = []; // caches last selection
var cpts = new Array(); var cpts = new Array();
[% FOREACH p = products %] [% FOREACH prod = products %]
cpts['[% p FILTER js %]'] = [ cpts['[% prod.name FILTER js %]'] = [
[%- FOREACH item = components_by_product.$p %]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ]; [%- FOREACH comp = prod.components %]'[% comp.name FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
[% END %] [% END %]
[% END %] [% END %]
...@@ -58,9 +58,10 @@ ...@@ -58,9 +58,10 @@
<td> <td>
<select name="product" onchange="selectProduct(this.form, 'product', 'component', 'Any');"> <select name="product" onchange="selectProduct(this.form, 'product', 'component', 'Any');">
<option value="">Any</option> <option value="">Any</option>
[% FOREACH item = products %] [% FOREACH prod = products %]
<option value="[% item FILTER html %]" <option value="[% prod.name FILTER html %]"
[% "selected" IF cgi.param('product') == item %]>[% item FILTER html %]</option> [% "selected" IF cgi.param('product') == prod.name %]>
[% prod.name FILTER html %]</option>
[% END %] [% END %]
</select> </select>
</td> </td>
...@@ -92,9 +93,11 @@ ...@@ -92,9 +93,11 @@
<td> <td>
<select name="component"> <select name="component">
<option value="">Any</option> <option value="">Any</option>
[% FOREACH item = components %] [% FOREACH prod = products %]
<option value="[% item FILTER html %]" [% "selected" IF cgi.param('component') == item %]> [% FOREACH comp = prod.components %]
[% item FILTER html %]</option> <option value="[% comp.name FILTER html %]" [% "selected" IF cgi.param('component') == comp.name %]>
[% comp.name FILTER html %]</option>
[% END %]
[% END %] [% END %]
</select> </select>
</td> </td>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment