summaryrefslogtreecommitdiffstats
path: root/editclassifications.cgi
diff options
context:
space:
mode:
authorbugreport%peshkin.net <>2004-08-21 06:49:17 +0200
committerbugreport%peshkin.net <>2004-08-21 06:49:17 +0200
commit88d26275229b5f52f435130496169766313c87b7 (patch)
treec71532045500b6e2335b1e5e2512d10b8846551b /editclassifications.cgi
parent2f9f28d0bfb1f321d1548844a41aaf2d51789695 (diff)
downloadbugzilla-88d26275229b5f52f435130496169766313c87b7.tar.gz
bugzilla-88d26275229b5f52f435130496169766313c87b7.tar.xz
Bug 224208 Add a higher level of categorization (.ie departments, locations, etc.)
patch by Albert Ting r=joel, glob a=myk
Diffstat (limited to 'editclassifications.cgi')
-rwxr-xr-xeditclassifications.cgi391
1 files changed, 391 insertions, 0 deletions
diff --git a/editclassifications.cgi b/editclassifications.cgi
new file mode 100755
index 000000000..c1186f792
--- /dev/null
+++ b/editclassifications.cgi
@@ -0,0 +1,391 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil; cperl-indent-level: 4 -*-
+#
+# 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.
+#
+# The Initial Developer of the Original Code is Albert Ting
+#
+# Contributor(s): Albert Ting <alt@sonic.net>
+#
+# Direct any questions on this source code to mozilla.org
+
+use strict;
+use lib ".";
+
+use Bugzilla;
+use Bugzilla::Constants;
+require "CGI.pl";
+require "globals.pl";
+
+my $cgi = Bugzilla->cgi;
+my $dbh = Bugzilla->dbh;
+
+use vars qw ($template $vars);
+
+# TestClassification: just returns if the specified classification does exists
+# CheckClassification: same check, optionally emit an error text
+
+sub TestClassification ($) {
+ my $cl = shift;
+
+ 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 ($) {
+ my $action = shift;
+
+ $action =~ /(\w+)/;
+ $action = $1;
+ print $cgi->header();
+ $template->process("admin/classifications/$action.html.tmpl", $vars)
+ || ThrowTemplateError($template->error());
+ exit;
+}
+
+#
+# Preliminary checks:
+#
+
+Bugzilla->login(LOGIN_REQUIRED);
+
+print $cgi->header();
+
+ThrowUserError("auth_cant_edit_classifications") unless UserInGroup("editclassifications");
+ThrowUserError("auth_classification_not_enabled") unless Param("useclassification");
+
+#
+# often used variables
+#
+my $action = trim($cgi->param('action') || '');
+my $classification = trim($cgi->param('classification') || '');
+trick_taint($classification);
+$vars->{'classification'} = $classification;
+
+#
+# action='' -> Show nice list of classifications
+#
+
+unless ($action) {
+ my @classifications;
+ # left join is tricky
+ # - 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
+ GROUP BY classifications.id
+ 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;
+ LoadTemplate("select");
+}
+
+#
+# action='add' -> present form for parameters for new classification
+#
+# (next action will be 'new')
+#
+
+if ($action eq 'add') {
+ LoadTemplate($action);
+}
+
+#
+# action='new' -> add classification entered in the 'action=add' screen
+#
+
+if ($action eq 'new') {
+ if (TestClassification($classification)) {
+ ThrowUserError("classification_already_exists", { name => $classification });
+ }
+ my $description = trim($cgi->param('description') || '');
+ trick_taint($description);
+
+ # Add the new classification.
+ my $sth = $dbh->prepare("INSERT INTO classifications (name,description)
+ VALUES (?,?)");
+ $sth->execute($classification,$description);
+
+ # Make versioncache flush
+ unlink "data/versioncache";
+
+ LoadTemplate($action);
+}
+
+#
+# action='del' -> ask if user really wants to delete
+#
+# (next action would be 'delete')
+#
+
+if ($action eq 'del') {
+ CheckClassification($classification);
+ my $sth;
+
+ # display some data about the classification
+ $sth = $dbh->prepare("SELECT id, description
+ FROM classifications
+ WHERE name=?");
+ $sth->execute($classification);
+ my ($classification_id, $description) = $sth->fetchrow_array();
+
+ ThrowUserError("classification_not_deletable") if ($classification_id eq "1");
+
+ $sth = $dbh->prepare("SELECT name
+ FROM products
+ WHERE classification_id=$classification_id");
+ $sth->execute();
+ ThrowUserError("classification_has_products") if ($sth->fetchrow_array());
+
+ $vars->{'description'} = $description if (defined $description);
+
+ LoadTemplate($action);
+}
+
+#
+# action='delete' -> really delete the classification
+#
+
+if ($action eq 'delete') {
+ CheckClassification($classification);
+
+ my $sth;
+ my $classification_id = get_classification_id($classification);
+
+ if ($classification_id == 1) {
+ ThrowUserError("cant_delete_default_classification", { name => $classification });
+ }
+
+ # lock the tables before we start to change everything:
+ $dbh->do("LOCK TABLES classifications WRITE, products WRITE");
+
+ # delete
+ $sth = $dbh->prepare("DELETE FROM classifications WHERE id=?");
+ $sth->execute($classification_id);
+
+ # update products just in case
+ $sth = $dbh->prepare("UPDATE products
+ SET classification_id=1
+ WHERE classification_id=?");
+ $sth->execute($classification_id);
+
+ $dbh->do("UNLOCK TABLES");
+
+ unlink "data/versioncache";
+
+ LoadTemplate($action);
+}
+
+#
+# action='edit' -> present the edit classifications from
+#
+# (next action would be 'update')
+#
+
+if ($action eq 'edit') {
+ CheckClassification($classification);
+
+ my @products = ();
+ my $has_products = 0;
+ my $sth;
+
+
+ # get data of classification
+ $sth = $dbh->prepare("SELECT id,description
+ FROM classifications
+ WHERE name=?");
+ $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);
+}
+
+#
+# action='update' -> update the classification
+#
+
+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);
+
+ my $classification_id = get_classification_id($classificationold);
+ trick_taint($description);
+
+ # Note that we got the $classification_id using $classificationold
+ # above so it will remain static even after we rename the
+ # classification in the database.
+
+ $dbh->do("LOCK TABLES classifications WRITE");
+
+ if ($description ne $descriptionold) {
+ $sth = $dbh->prepare("UPDATE classifications
+ SET description=?
+ WHERE id=?");
+ $sth->execute($description,$classification_id);
+ $vars->{'updated_description'} = 1;
+ }
+
+ if ($classification ne $classificationold) {
+ unless ($classification) {
+ $dbh->do("UNLOCK TABLES");
+ ThrowUserError("classification_not_specified")
+ }
+
+ if (TestClassification($classification)) {
+ $dbh->do("UNLOCK TABLES");
+ ThrowUserError("classification_already_exists", { name => $classification });
+ }
+ $sth = $dbh->prepare("UPDATE classifications
+ SET name=? WHERE id=?");
+ $sth->execute($classification,$classification_id);
+ $vars->{'updated_classification'} = 1;
+ }
+ $dbh->do("UNLOCK TABLES");
+
+ unlink "data/versioncache";
+ LoadTemplate($action);
+}
+
+#
+# action='reclassify' -> reclassify products for the classification
+#
+
+if ($action eq 'reclassify') {
+ CheckClassification($classification);
+ my $sth;
+
+ # display some data about the classification
+ $sth = $dbh->prepare("SELECT id, description
+ FROM classifications
+ WHERE name=?");
+ $sth->execute($classification);
+ my ($classification_id, $description) = $sth->fetchrow_array();
+
+ $vars->{'description'} = $description if (defined $description);
+
+ $sth = $dbh->prepare("UPDATE products
+ SET classification_id=?
+ WHERE name=?");
+ if (defined $cgi->param('add_products')) {
+ if (defined $cgi->param('prodlist')) {
+ foreach my $prod ($cgi->param("prodlist")) {
+ trick_taint($prod);
+ $sth->execute($classification_id,$prod);
+ }
+ }
+ } elsif (defined $cgi->param('remove_products')) {
+ if (defined $cgi->param('myprodlist')) {
+ foreach my $prod ($cgi->param("myprodlist")) {
+ trick_taint($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 @class_products = ();
+
+ $sth = $dbh->prepare("SELECT classifications.id,
+ products.name,
+ classifications.name,
+ classifications.id > 1 as unknown
+ FROM products,classifications
+ WHERE 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 {
+ $cl->{'name'} = "$name [$clname]";
+ }
+ $cl->{'value'} = $name;
+ push(@class_products,$cl);
+ }
+ }
+ $vars->{'selected_products'} = \@selected_products;
+ $vars->{'class_products'} = \@class_products;
+
+ LoadTemplate($action);
+}
+
+#
+# No valid action found
+#
+
+ThrowCodeError("action_unrecognized", $vars);