Commit ab199bf5 authored by lpsolit%gmail.com's avatar lpsolit%gmail.com

Bug 286294: cleanup editclassifications.cgi and migrate the existent code to use…

Bug 286294: cleanup editclassifications.cgi and migrate the existent code to use Classification.pm - Patch by Tiago R. Mello <timello@gmail.com> r=LpSolit a=myk
parent 966c2621
...@@ -21,6 +21,7 @@ package Bugzilla::Classification; ...@@ -21,6 +21,7 @@ package Bugzilla::Classification;
use Bugzilla; use Bugzilla;
use Bugzilla::Util; use Bugzilla::Util;
use Bugzilla::Error;
############################### ###############################
#### Initialization #### #### Initialization ####
...@@ -87,7 +88,7 @@ sub product_count { ...@@ -87,7 +88,7 @@ sub product_count {
if (!defined $self->{'product_count'}) { if (!defined $self->{'product_count'}) {
$self->{'product_count'} = $dbh->selectrow_array(q{ $self->{'product_count'} = $dbh->selectrow_array(q{
SELECT COUNT(*) FROM products SELECT COUNT(*) FROM products
WHERE classification_id = ?}, undef, $self->id); WHERE classification_id = ?}, undef, $self->id) || 0;
} }
return $self->{'product_count'}; return $self->{'product_count'};
} }
...@@ -108,13 +109,31 @@ sub get_all_classifications () { ...@@ -108,13 +109,31 @@ sub get_all_classifications () {
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
my $ids = $dbh->selectcol_arrayref(q{ my $ids = $dbh->selectcol_arrayref(q{
SELECT id FROM classifications}); SELECT id FROM classifications ORDER BY name});
my $classifications; my @classifications;
foreach my $id (@$ids) { foreach my $id (@$ids) {
$classifications->{$id} = new Bugzilla::Classification($id); push @classifications, new Bugzilla::Classification($id);
} }
return $classifications; return @classifications;
}
sub check_classification ($) {
my ($class_name) = @_;
unless ($class_name) {
ThrowUserError("classification_not_specified");
}
my $classification =
new Bugzilla::Classification({name => $class_name});
unless ($classification) {
ThrowUserError("classification_doesnt_exist",
{ name => $class_name });
}
return $classification;
} }
1; 1;
...@@ -140,11 +159,14 @@ Bugzilla::Classification - Bugzilla classification class. ...@@ -140,11 +159,14 @@ Bugzilla::Classification - Bugzilla classification class.
my $hash_ref = Bugzilla::Classification::get_all_classifications(); my $hash_ref = Bugzilla::Classification::get_all_classifications();
my $classification = $hash_ref->{1}; my $classification = $hash_ref->{1};
my $classification =
Bugzilla::Classification::check_classification('AcmeClass');
=head1 DESCRIPTION =head1 DESCRIPTION
Classification.pm represents a Classification object. Classification.pm represents a Classification object.
A Classification is a higher-level grouping of Bugzilla Products. A Classification is a higher-level grouping of Products.
=head1 METHODS =head1 METHODS
...@@ -181,12 +203,20 @@ A Classification is a higher-level grouping of Bugzilla Products. ...@@ -181,12 +203,20 @@ A Classification is a higher-level grouping of Bugzilla Products.
=item C<get_all_classifications()> =item C<get_all_classifications()>
Description: Returns all Bugzilla classifications. Description: Returns all classifications.
Params: none. Params: none.
Returns: A hash with classification id as key and Returns: Bugzilla::Classification object list.
Bugzilla::Classification object as value.
=item C<check_classification($classification_name)>
Description: Checks if the classification name passed in is a
valid classification.
Params: $classification_name - String with a classification name.
Returns: Bugzilla::Classification object.
=back =back
......
...@@ -196,13 +196,13 @@ sub get_products_by_classification ($) { ...@@ -196,13 +196,13 @@ sub get_products_by_classification ($) {
my $ids = $dbh->selectcol_arrayref(q{ my $ids = $dbh->selectcol_arrayref(q{
SELECT id FROM products SELECT id FROM products
WHERE classification_id = ?}, undef, $class_id); WHERE classification_id = ? ORDER by name}, undef, $class_id);
my $products; my @products;
foreach my $id (@$ids) { foreach my $id (@$ids) {
$products->{$id} = new Bugzilla::Product($id); push @products, new Bugzilla::Product($id);
} }
return $products; return @products;
} }
sub get_all_products () { sub get_all_products () {
...@@ -265,8 +265,7 @@ Bugzilla::Product - Bugzilla product class. ...@@ -265,8 +265,7 @@ Bugzilla::Product - Bugzilla product class.
my $defaultmilestone = $product->default_milestone; my $defaultmilestone = $product->default_milestone;
my $classificationid = $product->classification_id; my $classificationid = $product->classification_id;
my $hash_ref = Bugzilla::Product::get_products_by_classification(1); my @products = Bugzilla::Product::get_products_by_classification(1);
my $product = $hash_ref->{1};
=head1 DESCRIPTION =head1 DESCRIPTION
...@@ -355,8 +354,7 @@ Product.pm represents a product object. ...@@ -355,8 +354,7 @@ Product.pm represents a product object.
Params: $class_id - Integer with classification id. Params: $class_id - Integer with classification id.
Returns: A hash with product id as key and a Bugzilla::Product Returns: Bugzilla::Product object list.
object as value.
=item C<get_all_products()> =item C<get_all_products()>
......
...@@ -28,6 +28,8 @@ use Bugzilla::Constants; ...@@ -28,6 +28,8 @@ use Bugzilla::Constants;
use Bugzilla::Util; use Bugzilla::Util;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::Config qw($datadir); use Bugzilla::Config qw($datadir);
use Bugzilla::Classification;
use Bugzilla::Product;
require "globals.pl"; require "globals.pl";
...@@ -36,34 +38,6 @@ my $dbh = Bugzilla->dbh; ...@@ -36,34 +38,6 @@ my $dbh = Bugzilla->dbh;
my $template = Bugzilla->template; my $template = Bugzilla->template;
my $vars = {}; my $vars = {};
# TestClassification: just returns if the specified classification does exist
# CheckClassification: same check, optionally emit an error text
sub TestClassification ($) {
my $cl = shift;
my $dbh = Bugzilla->dbh;
trick_taint($cl);
# does the classification exist?
my $sth = $dbh->prepare("SELECT name
FROM classifications
WHERE name=?");
$sth->execute($cl);
my @row = $sth->fetchrow_array();
return $row[0];
}
sub CheckClassification ($) {
my $cl = shift;
unless ($cl) {
ThrowUserError("classification_not_specified");
}
if (! TestClassification($cl)) {
ThrowUserError("classification_doesnt_exist", { name => $cl });
}
}
sub LoadTemplate ($) { sub LoadTemplate ($) {
my $action = shift; my $action = shift;
...@@ -94,43 +68,15 @@ ThrowUserError("auth_classification_not_enabled") unless Param("useclassificatio ...@@ -94,43 +68,15 @@ ThrowUserError("auth_classification_not_enabled") unless Param("useclassificatio
# often used variables # often used variables
# #
my $action = trim($cgi->param('action') || ''); my $action = trim($cgi->param('action') || '');
my $classification = trim($cgi->param('classification') || ''); my $class_name = trim($cgi->param('classification') || '');
trick_taint($classification);
$vars->{'classification'} = $classification;
# #
# action='' -> Show nice list of classifications # action='' -> Show nice list of classifications
# #
unless ($action) { unless ($action) {
my @classifications; my @classifications =
# left join is tricky Bugzilla::Classification::get_all_classifications();
# - must select "classifications" fields if you want a REAL value
# - must use "count(products.classification_id)" if you want a true
# count. If you use count(classifications.id), it will return 1 for NULL
# - must use "group by classifications.id" instead of
# products.classification_id. Otherwise it won't look for all
# classification ids, just the ones used by the products.
my $sth = $dbh->prepare("SELECT classifications.id, classifications.name,
classifications.description,
COUNT(classification_id) AS total
FROM classifications
LEFT JOIN products
ON classifications.id = products.classification_id
" . $dbh->sql_group_by('classifications.id',
'classifications.name,
classifications.description') . "
ORDER BY name");
$sth->execute();
while (my ($id,$classification,$description,$total) = $sth->fetchrow_array()) {
my $cl = {};
$cl->{'id'} = $id;
$cl->{'classification'} = $classification;
$cl->{'description'} = $description if (defined $description);
$cl->{'total'} = $total;
push(@classifications, $cl);
}
$vars->{'classifications'} = \@classifications; $vars->{'classifications'} = \@classifications;
LoadTemplate("select"); LoadTemplate("select");
...@@ -151,19 +97,24 @@ if ($action eq 'add') { ...@@ -151,19 +97,24 @@ if ($action eq 'add') {
# #
if ($action eq 'new') { if ($action eq 'new') {
unless ($classification) {
ThrowUserError("classification_not_specified"); $class_name || ThrowUserError("classification_not_specified");
}
if (TestClassification($classification)) { my $classification =
ThrowUserError("classification_already_exists", { name => $classification }); new Bugzilla::Classification({name => $class_name});
if ($classification) {
ThrowUserError("classification_already_exists",
{ name => $classification->name });
} }
my $description = trim($cgi->param('description') || ''); my $description = trim($cgi->param('description') || '');
trick_taint($description); trick_taint($description);
trick_taint($class_name);
# Add the new classification. # Add the new classification.
my $sth = $dbh->prepare("INSERT INTO classifications (name,description) $dbh->do("INSERT INTO classifications (name, description)
VALUES (?,?)"); VALUES (?, ?)", undef, ($class_name, $description));
$sth->execute($classification,$description);
# Make versioncache flush # Make versioncache flush
unlink "$datadir/versioncache"; unlink "$datadir/versioncache";
...@@ -178,25 +129,20 @@ if ($action eq 'new') { ...@@ -178,25 +129,20 @@ if ($action eq 'new') {
# #
if ($action eq 'del') { if ($action eq 'del') {
CheckClassification($classification);
my $sth;
# display some data about the classification my $classification =
$sth = $dbh->prepare("SELECT id, description Bugzilla::Classification::check_classification($class_name);
FROM classifications
WHERE name=?");
$sth->execute($classification);
my ($classification_id, $description) = $sth->fetchrow_array();
ThrowUserError("classification_not_deletable") if ($classification_id eq "1"); if ($classification->id == 1) {
ThrowUserError("classification_not_deletable");
}
$sth = $dbh->prepare("SELECT name if ($classification->product_count()) {
FROM products ThrowUserError("classification_has_products");
WHERE classification_id=$classification_id"); }
$sth->execute();
ThrowUserError("classification_has_products") if ($sth->fetchrow_array());
$vars->{'description'} = $description if (defined $description); $vars->{'description'} = $classification->description;
$vars->{'classification'} = $classification->name;
LoadTemplate($action); LoadTemplate($action);
} }
...@@ -206,32 +152,31 @@ if ($action eq 'del') { ...@@ -206,32 +152,31 @@ if ($action eq 'del') {
# #
if ($action eq 'delete') { if ($action eq 'delete') {
CheckClassification($classification);
my $sth; my $classification =
my $classification_id = get_classification_id($classification); Bugzilla::Classification::check_classification($class_name);
if ($classification_id == 1) { if ($classification->id == 1) {
ThrowUserError("cant_delete_default_classification", { name => $classification }); ThrowUserError("classification_not_deletable");
} }
# lock the tables before we start to change everything: # lock the tables before we start to change everything:
$dbh->bz_lock_tables('classifications WRITE', 'products WRITE'); $dbh->bz_lock_tables('classifications WRITE', 'products WRITE');
# delete # delete
$sth = $dbh->prepare("DELETE FROM classifications WHERE id=?"); $dbh->do("DELETE FROM classifications WHERE id = ?", undef,
$sth->execute($classification_id); $classification->id);
# update products just in case # update products just in case
$sth = $dbh->prepare("UPDATE products $dbh->do("UPDATE products SET classification_id = 1
SET classification_id=1 WHERE classification_id = ?", undef, $classification->id);
WHERE classification_id=?");
$sth->execute($classification_id);
$dbh->bz_unlock_tables(); $dbh->bz_unlock_tables();
unlink "$datadir/versioncache"; unlink "$datadir/versioncache";
$vars->{'classification'} = $classification->name;
LoadTemplate($action); LoadTemplate($action);
} }
...@@ -242,34 +187,17 @@ if ($action eq 'delete') { ...@@ -242,34 +187,17 @@ if ($action eq 'delete') {
# #
if ($action eq 'edit') { if ($action eq 'edit') {
CheckClassification($classification);
my $classification =
my @products = (); Bugzilla::Classification::check_classification($class_name);
my $has_products = 0;
my $sth; my @products =
Bugzilla::Product::get_products_by_classification(
$classification->id);
# get data of classification
$sth = $dbh->prepare("SELECT id,description $vars->{'description'} = $classification->description;
FROM classifications $vars->{'classification'} = $classification->name;
WHERE name=?"); $vars->{'products'} = \@products;
$sth->execute($classification);
my ($classification_id,$description) = $sth->fetchrow_array();
$vars->{'description'} = $description if (defined $description);
$sth = $dbh->prepare("SELECT name,description
FROM products
WHERE classification_id=?
ORDER BY name");
$sth->execute($classification_id);
while ( my ($product, $prod_description) = $sth->fetchrow_array()) {
my $prod = {};
$has_products = 1;
$prod->{'name'} = $product;
$prod->{'description'} = $prod_description if (defined $prod_description);
push(@products, $prod);
}
$vars->{'products'} = \@products if ($has_products);
LoadTemplate($action); LoadTemplate($action);
} }
...@@ -279,44 +207,39 @@ if ($action eq 'edit') { ...@@ -279,44 +207,39 @@ if ($action eq 'edit') {
# #
if ($action eq 'update') { if ($action eq 'update') {
my $classificationold = trim($cgi->param('classificationold') || '');
my $description = trim($cgi->param('description') || '');
my $descriptionold = trim($cgi->param('descriptionold') || '');
my $checkvotes = 0;
my $sth;
CheckClassification($classificationold); $class_name || ThrowUserError("classification_not_specified");
my $classification_id = get_classification_id($classificationold); my $class_old_name = trim($cgi->param('classificationold') || '');
trick_taint($description); my $description = trim($cgi->param('description') || '');
# Note that we got the $classification_id using $classificationold my $class_old =
# above so it will remain static even after we rename the Bugzilla::Classification::check_classification($class_old_name);
# classification in the database.
$dbh->bz_lock_tables('classifications WRITE'); $dbh->bz_lock_tables('classifications WRITE');
if ($classification ne $classificationold) { if ($class_name ne $class_old->name) {
unless ($classification) {
ThrowUserError("classification_not_specified");
}
if (TestClassification($classification)) { my $class = new Bugzilla::Classification({name => $class_name});
ThrowUserError("classification_already_exists", { name => $classification }); if ($class) {
ThrowUserError("classification_already_exists",
{ name => $class->name });
} }
$sth = $dbh->prepare("UPDATE classifications trick_taint($class_name);
SET name=? WHERE id=?"); $dbh->do("UPDATE classifications SET name = ? WHERE id = ?",
$sth->execute($classification,$classification_id); undef, ($class_name, $class_old->id));
$vars->{'updated_classification'} = 1; $vars->{'updated_classification'} = 1;
unlink "$datadir/versioncache"; unlink "$datadir/versioncache";
} }
if ($description ne $descriptionold) { if ($description ne $class_old->description) {
$sth = $dbh->prepare("UPDATE classifications trick_taint($description);
SET description=? $dbh->do("UPDATE classifications SET description = ?
WHERE id=?"); WHERE id = ?", undef,
$sth->execute($description,$classification_id); ($description, $class_old->id));
$vars->{'updated_description'} = 1; $vars->{'updated_description'} = 1;
unlink "$datadir/versioncache"; unlink "$datadir/versioncache";
...@@ -332,26 +255,20 @@ if ($action eq 'update') { ...@@ -332,26 +255,20 @@ if ($action eq 'update') {
# #
if ($action eq 'reclassify') { if ($action eq 'reclassify') {
CheckClassification($classification);
my $sth;
# display some data about the classification my $classification =
$sth = $dbh->prepare("SELECT id, description Bugzilla::Classification::check_classification($class_name);
FROM classifications
WHERE name=?");
$sth->execute($classification);
my ($classification_id, $description) = $sth->fetchrow_array();
$vars->{'description'} = $description if (defined $description); $vars->{'description'} = $classification->description;
my $sth = $dbh->prepare("UPDATE products SET classification_id = ?
WHERE name = ?");
$sth = $dbh->prepare("UPDATE products
SET classification_id=?
WHERE name=?");
if (defined $cgi->param('add_products')) { if (defined $cgi->param('add_products')) {
if (defined $cgi->param('prodlist')) { if (defined $cgi->param('prodlist')) {
foreach my $prod ($cgi->param("prodlist")) { foreach my $prod ($cgi->param("prodlist")) {
trick_taint($prod); trick_taint($prod);
$sth->execute($classification_id,$prod); $sth->execute($classification->id, $prod);
} }
} }
} elsif (defined $cgi->param('remove_products')) { } elsif (defined $cgi->param('remove_products')) {
...@@ -361,44 +278,24 @@ if ($action eq 'reclassify') { ...@@ -361,44 +278,24 @@ if ($action eq 'reclassify') {
$sth->execute(1,$prod); $sth->execute(1,$prod);
} }
} }
} elsif (defined $cgi->param('migrate_products')) {
if (defined $cgi->param('clprodlist')) {
foreach my $prod ($cgi->param("clprodlist")) {
trick_taint($prod);
$sth->execute($classification_id,$prod);
}
}
} }
my @selected_products = (); my @selected_products = ();
my @class_products = (); my @unselected_products = ();
$sth = $dbh->prepare("SELECT classifications.id, my @products = Bugzilla::Product::get_all_products();
products.name,
classifications.name, foreach my $product (@products) {
classifications.id > 1 as unknown if ($product->classification_id == $classification->id) {
FROM products push @selected_products, $product;
INNER JOIN classifications
ON classifications.id = products.classification_id
ORDER BY unknown, products.name,
classifications.name");
$sth->execute();
while ( my ($clid, $name, $clname) = $sth->fetchrow_array() ) {
if ($clid == $classification_id) {
push(@selected_products,$name);
} else {
my $cl = {};
if ($clid == 1) {
$cl->{'name'} = "[$clname] $name";
} else { } else {
$cl->{'name'} = "$name [$clname]"; push @unselected_products, $product;
}
$cl->{'value'} = $name;
push(@class_products,$cl);
} }
} }
$vars->{'selected_products'} = \@selected_products; $vars->{'selected_products'} = \@selected_products;
$vars->{'class_products'} = \@class_products; $vars->{'unselected_products'} = \@unselected_products;
$vars->{'classification'} = $classification->name;
LoadTemplate($action); LoadTemplate($action);
} }
...@@ -407,4 +304,4 @@ if ($action eq 'reclassify') { ...@@ -407,4 +304,4 @@ if ($action eq 'reclassify') {
# No valid action found # No valid action found
# #
ThrowCodeError("action_unrecognized", $vars); ThrowCodeError("action_unrecognized", {action => $action});
...@@ -59,7 +59,6 @@ ...@@ -59,7 +59,6 @@
</table> </table>
<input type=hidden name="classificationold" value="[% classification FILTER html %]"> <input type=hidden name="classificationold" value="[% classification FILTER html %]">
<input type=hidden name="descriptionold" value="[% description FILTER html %]">
<input type=hidden name="action" value="update"> <input type=hidden name="action" value="update">
<input type=submit value="Update"> <input type=submit value="Update">
</form> </form>
......
...@@ -51,9 +51,9 @@ ...@@ -51,9 +51,9 @@
<td></td> <td></td>
<td valign="top"> <td valign="top">
<select name="prodlist" id="prodlist" multiple="multiple" size="20"> <select name="prodlist" id="prodlist" multiple="multiple" size="20">
[% FOREACH cl = class_products %] [% FOREACH product = unselected_products %]
<option value="[% cl.value FILTER html %]"> <option value="[% product.name FILTER html %]">
[% cl.name FILTER html %] [[% product.classification.name FILTER html %]]&nbsp;[% product.name FILTER html %]
</option> </option>
[% END %] [% END %]
</select></td> </select></td>
...@@ -66,8 +66,8 @@ ...@@ -66,8 +66,8 @@
<td valign="middle" rowspan=2> <td valign="middle" rowspan=2>
<select name="myprodlist" id="myprodlist" multiple="multiple" size="20"> <select name="myprodlist" id="myprodlist" multiple="multiple" size="20">
[% FOREACH product = selected_products %] [% FOREACH product = selected_products %]
<option value="[% product FILTER html %]"> <option value="[% product.name FILTER html %]">
[% product FILTER html %] [% product.name FILTER html %]
</option> </option>
[% END %] [% END %]
</select></td> </select></td>
......
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
title = "Select classification" title = "Select classification"
%] %]
[% filt_classification = classification FILTER html %]
<table border=1 cellpadding=4 cellspacing=0> <table border=1 cellpadding=4 cellspacing=0>
<tr bgcolor="#6666ff"> <tr bgcolor="#6666ff">
<th align="left">Edit Classification ...</th> <th align="left">Edit Classification ...</th>
...@@ -35,7 +33,7 @@ ...@@ -35,7 +33,7 @@
[% FOREACH cl = classifications %] [% FOREACH cl = classifications %]
<tr> <tr>
<td valign="top"><a href="editclassifications.cgi?action=edit&amp;classification=[% cl.classification FILTER url_quote %]"><b>[% cl.classification FILTER html %]</b></a></td> <td valign="top"><a href="editclassifications.cgi?action=edit&amp;classification=[% cl.name FILTER url_quote %]"><b>[% cl.name FILTER html %]</b></a></td>
<td valign="top"> <td valign="top">
[% IF cl.description %] [% IF cl.description %]
[% cl.description %] [% cl.description %]
...@@ -44,16 +42,16 @@ ...@@ -44,16 +42,16 @@
[% END %] [% END %]
</td> </td>
[% IF (cl.id == 1) %] [% IF (cl.id == 1) %]
<td valign="top">[% cl.total FILTER html %]</td> <td valign="top">[% cl.product_count FILTER html %]</td>
[% ELSE %] [% ELSE %]
<td valign="top"><a href="editclassifications.cgi?action=reclassify&amp;classification=[% cl.classification FILTER url_quote %]">reclassify ([% cl.total FILTER html %])</a></td> <td valign="top"><a href="editclassifications.cgi?action=reclassify&amp;classification=[% cl.name FILTER url_quote %]">reclassify ([% cl.product_count FILTER html %])</a></td>
[% END %] [% END %]
[%# don't allow user to delete the default id. %] [%# don't allow user to delete the default id. %]
[% IF (cl.id == 1) %] [% IF (cl.id == 1) %]
<td valign="top">&nbsp;</td> <td valign="top">&nbsp;</td>
[% ELSE %] [% ELSE %]
<td valign="top"><a href="editclassifications.cgi?action=del&amp;classification=[% cl.classification FILTER url_quote %]">delete</a></td> <td valign="top"><a href="editclassifications.cgi?action=del&amp;classification=[% cl.name FILTER url_quote %]">delete</a></td>
[% END %] [% END %]
</tr> </tr>
[% END %] [% END %]
......
...@@ -248,10 +248,6 @@ ...@@ -248,10 +248,6 @@
must reassign those products to another classification before you must reassign those products to another classification before you
can delete this one. can delete this one.
[% ELSIF error == "cant_delete_default_classification" %]
Sorry, but you can not delete the default classification,
'[% name FILTER html %]'.
[% ELSIF error == "component_already_exists" %] [% ELSIF error == "component_already_exists" %]
[% title = "Component Already Exists" %] [% title = "Component Already Exists" %]
A component with the name '[% name FILTER html %]' already exists. A component with the name '[% name FILTER html %]' already exists.
......
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