]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 299753: Replace old code in editproducts.cgi by routines from Product.pm - Patch...
authorlpsolit%gmail.com <>
Tue, 18 Oct 2005 04:43:40 +0000 (04:43 +0000)
committerlpsolit%gmail.com <>
Tue, 18 Oct 2005 04:43:40 +0000 (04:43 +0000)
15 files changed:
Bugzilla/Product.pm
editproducts.cgi
template/en/default/admin/products/confirm-delete.html.tmpl
template/en/default/admin/products/create.html.tmpl
template/en/default/admin/products/created.html.tmpl
template/en/default/admin/products/deleted.html.tmpl
template/en/default/admin/products/edit-common.html.tmpl
template/en/default/admin/products/edit.html.tmpl
template/en/default/admin/products/footer.html.tmpl
template/en/default/admin/products/groupcontrol/confirm-edit.html.tmpl
template/en/default/admin/products/groupcontrol/edit.html.tmpl
template/en/default/admin/products/groupcontrol/updated.html.tmpl
template/en/default/admin/products/list.html.tmpl
template/en/default/admin/products/updated.html.tmpl
template/en/default/filterexceptions.pl

index 1bf1d4e56369aa7dff63d88c824a229823a468f4..f55b5dd67395f7afec9e193a4d776270b474254a 100644 (file)
@@ -187,6 +187,20 @@ sub bug_count {
     return $self->{'bug_count'};
 }
 
+sub bug_ids {
+    my $self = shift;
+    my $dbh = Bugzilla->dbh;
+
+    if (!defined $self->{'bug_ids'}) {
+        $self->{'bug_ids'} = 
+            $dbh->selectcol_arrayref(q{SELECT bug_id FROM bugs
+                                       WHERE product_id = ?},
+                                     undef, $self->id);
+    }
+    return $self->{'bug_ids'};
+}
+
+
 ###############################
 ####      Accessors      ######
 ###############################
@@ -253,6 +267,7 @@ Bugzilla::Product - Bugzilla product class.
     my @milestones      = $product->milestones();
     my @versions        = $product->versions();
     my $bugcount        = $product->bug_count();
+    my $bug_ids         = $product->bug_ids();
 
     my $id               = $product->id;
     my $name             = $product->name;
@@ -330,6 +345,14 @@ Product.pm represents a product object.
 
  Returns:     Integer with the number of bugs.
 
+=item C<bug_ids()>
+
+ Description: Returns the IDs of bugs that belong to the product.
+
+ Params:      none.
+
+ Returns:     An array of integer.
+
 =back
 
 =head1 SUBROUTINES
index 82ce7433dec94c3bebd1be6aeb8da557c72a3388..9b188f2314b09696e7cc14b230a77a094ff11607 100755 (executable)
@@ -38,94 +38,14 @@ require "globals.pl";
 use Bugzilla::Bug;
 use Bugzilla::Series;
 use Bugzilla::Config qw(:DEFAULT $datadir);
+use Bugzilla::Product;
+use Bugzilla::Classification;
+use Bugzilla::Milestone;
 
 # Shut up misguided -w warnings about "used only once".  "use vars" just
 # doesn't work for me.
 use vars qw(@legal_bug_status @legal_resolution);
 
-# TestProduct:  just returns if the specified product does exists
-# CheckProduct: same check, optionally  emit an error text
-
-sub TestProduct
-{
-    my $prod = shift;
-
-    # does the product exist?
-    SendSQL("SELECT name
-             FROM products
-             WHERE name=" . SqlQuote($prod));
-    return FetchOneColumn();
-}
-
-sub CheckProduct
-{
-    my $prod = shift;
-
-    # do we have a product?
-    unless ($prod) {
-        ThrowUserError('product_not_specified');
-    }
-
-    unless (TestProduct($prod)) {
-        ThrowUserError('product_doesnt_exist',
-                       {'product' => $prod});
-    }
-}
-
-
-# TestClassification:  just returns if the specified classification does exists
-# CheckClassification: same check, optionally  emit an error text
-
-sub TestClassification
-{
-    my $cl = shift;
-
-    # does the classification exist?
-    SendSQL("SELECT name
-             FROM classifications
-             WHERE name=" . SqlQuote($cl));
-    return FetchOneColumn();
-}
-
-sub CheckClassification
-{
-    my $cl = shift;
-
-    # do we have a classification?
-    unless ($cl) {
-        ThrowUserError('classification_not_specified');    
-    }
-
-    unless (TestClassification($cl)) {
-        ThrowUserError('classification_doesnt_exist',
-                       {'name' => $cl});
-    }
-}
-
-sub CheckClassificationProduct
-{
-    my ($cl, $prod) = @_;
-    my $dbh = Bugzilla->dbh;
-    
-    CheckClassification($cl);
-
-    trick_taint($prod);
-    trick_taint($cl);
-
-    my ($res) = $dbh->selectrow_array(q{
-        SELECT products.name
-        FROM products
-        INNER JOIN classifications
-          ON products.classification_id = classifications.id
-        WHERE products.name = ? AND classifications.name = ?},
-        undef, ($prod, $cl));
-
-    unless ($res) {
-        ThrowUserError('classification_doesnt_exist_for_product',
-                       { product => $prod, classification => $cl });
-    }
-}
-
 #
 # Preliminary checks:
 #
@@ -144,8 +64,8 @@ $user->in_group('editcomponents')
 #
 # often used variables
 #
-my $classification = trim($cgi->param('classification') || '');
-my $product = trim($cgi->param('product') || '');
+my $classification_name = trim($cgi->param('classification') || '');
+my $product_name = trim($cgi->param('product') || '');
 my $action  = trim($cgi->param('action')  || '');
 my $dbh = Bugzilla->dbh;
 
@@ -155,23 +75,14 @@ my $dbh = Bugzilla->dbh;
 #
 
 if (Param('useclassification') 
-    && !$classification
-    && !$product)
+    && !$classification_name
+    && !$product_name)
 {
-    my $query = 
-        "SELECT classifications.name, classifications.description,
-                COUNT(classification_id) AS product_count
-         FROM classifications
-         LEFT JOIN products
-              ON classifications.id = products.classification_id " .
-              $dbh->sql_group_by('classifications.id',
-                                 'classifications.name,
-                                  classifications.description') . "
-         ORDER BY name";
-
-    $vars->{'classifications'} = $dbh->selectall_arrayref($query,
-                                                          {'Slice' => {}});
-
+    my @classifications =
+        Bugzilla::Classification::get_all_classifications();
+    
+    $vars->{'classifications'} = \@classifications;
+    
     $template->process("admin/products/list-classifications.html.tmpl",
                        $vars)
         || ThrowTemplateError($template->error());
@@ -185,50 +96,21 @@ if (Param('useclassification')
 #                is already specified (then edit it)
 #
 
-if (!$action && !$product) {
-
-    if (Param('useclassification')) {
-        CheckClassification($classification);
-    }
-
-    my @execute_params = ();
-    my @products = ();
-
-    my $query = "SELECT products.name,
-                        COALESCE(products.description,'') AS description, 
-                        disallownew = 0 AS status,
-                        votesperuser,  maxvotesperbug, votestoconfirm,
-                        COUNT(bug_id) AS bug_count
-                 FROM products";
+if (!$action && !$product_name) {
+    my @products;
 
     if (Param('useclassification')) {
-        $query .= " INNER JOIN classifications " .
-                  "ON classifications.id = products.classification_id";
-    }
-
-    $query .= " LEFT JOIN bugs ON products.id = bugs.product_id";
-
-    if (Param('useclassification')) {
-        $query .= " WHERE classifications.name = ? ";
-
-        # trick_taint is OK because we use this in a placeholder in a SELECT
-        trick_taint($classification);
+        my $classification = 
+            Bugzilla::Classification::check_classification($classification_name);
 
-        push(@execute_params,
-             $classification);
+        @products = @{$classification->products};
+        $vars->{'classification'} = $classification;
+    } else {
+        @products = Bugzilla::Product::get_all_products;
     }
 
-    $query .= " " . $dbh->sql_group_by('products.name',
-                                       'products.description, disallownew,
-                                        votesperuser, maxvotesperbug,
-                                        votestoconfirm');
-    $query .= " ORDER BY products.name";
-
-    $vars->{'products'} = $dbh->selectall_arrayref($query,
-                                                   {'Slice' => {}},
-                                                   @execute_params);
+    $vars->{'products'} = \@products; 
 
-    $vars->{'classification'} = $classification;
     $template->process("admin/products/list.html.tmpl",
                        $vars)
       || ThrowTemplateError($template->error());
@@ -248,9 +130,10 @@ if (!$action && !$product) {
 if ($action eq 'add') {
 
     if (Param('useclassification')) {
-        CheckClassification($classification);
+        my $classification = 
+            Bugzilla::Classification::check_classification($classification_name);
+        $vars->{'classification'} = $classification;
     }
-    $vars->{'classification'} = $classification;
     $template->process("admin/products/create.html.tmpl", $vars)
       || ThrowTemplateError($template->error());
 
@@ -268,30 +151,31 @@ if ($action eq 'new') {
 
     my $classification_id = 1;
     if (Param('useclassification')) {
-        CheckClassification($classification);
-        $classification_id = get_classification_id($classification);
+        my $classification = 
+            Bugzilla::Classification::check_classification($classification_name);
+        $classification_id = $classification->id;
         $vars->{'classification'} = $classification;
     }
 
-    unless ($product) {
+    unless ($product_name) {
         ThrowUserError("product_blank_name");  
     }
 
-    my $existing_product = TestProduct($product);
+    my $product = new Bugzilla::Product({name => $product_name});
 
-    if ($existing_product) {
+    if ($product) {
 
         # Check for exact case sensitive match:
-        if ($existing_product eq $product) {
+        if ($product->name eq $product_name) {
             ThrowUserError("prod_name_already_in_use",
-                           {'product' => $product});
+                           {'product' => $product->name});
         }
 
         # Next check for a case-insensitive match:
-        if (lc($existing_product) eq lc($product)) {
+        if (lc($product->name) eq lc($product_name)) {
             ThrowUserError("prod_name_diff_in_case",
-                           {'product' => $product,
-                            'existing_product' => $existing_product}); 
+                           {'product' => $product_name,
+                            'existing_product' => $product->name}); 
         }
     }
 
@@ -299,14 +183,14 @@ if ($action eq 'new') {
 
     if ($version eq '') {
         ThrowUserError("product_must_have_version",
-                       {'product' => $product});
+                       {'product' => $product_name});
     }
 
     my $description  = trim($cgi->param('description')  || '');
 
     if ($description eq '') {
         ThrowUserError('product_must_have_description',
-                       {'product' => $product});
+                       {'product' => $product_name});
     }
 
     my $milestoneurl = trim($cgi->param('milestoneurl') || '');
@@ -325,7 +209,7 @@ if ($action eq 'new') {
             "name, description, milestoneurl, disallownew, votesperuser, " .
             "maxvotesperbug, votestoconfirm, defaultmilestone, classification_id" .
             " ) VALUES ( " .
-            SqlQuote($product) . "," .
+            SqlQuote($product_name) . "," .
             SqlQuote($description) . "," .
             SqlQuote($milestoneurl) . "," .
             # had tainting issues under cygwin, IIS 5.0, perl -T %s %s
@@ -339,22 +223,23 @@ if ($action eq 'new') {
             SqlQuote($votestoconfirm) . "," .
             SqlQuote($defaultmilestone) . "," .
             SqlQuote($classification_id) . ")");
-    my $product_id = $dbh->bz_last_key('products', 'id');
 
+    $product = new Bugzilla::Product({name => $product_name});
+    
     SendSQL("INSERT INTO versions ( " .
           "value, product_id" .
           " ) VALUES ( " .
           SqlQuote($version) . "," .
-          $product_id . ")" );
+          $product->id . ")" );
 
     SendSQL("INSERT INTO milestones (product_id, value) VALUES (" .
-            $product_id . ", " . SqlQuote($defaultmilestone) . ")");
+            $product->id . ", " . SqlQuote($defaultmilestone) . ")");
 
     # If we're using bug groups, then we need to create a group for this
     # product as well.  -JMR, 2/16/00
     if (Param("makeproductgroups")) {
         # Next we insert into the groups table
-        my $productgroup = $product;
+        my $productgroup = $product->name;
         while (GroupExists($productgroup)) {
             $productgroup .= '_';
         }
@@ -362,7 +247,8 @@ if ($action eq 'new') {
                 "(name, description, isbuggroup, last_changed) " .
                 "VALUES (" .
                 SqlQuote($productgroup) . ", " .
-                SqlQuote("Access to bugs in the $product product") . ", 1, NOW())");
+                SqlQuote("Access to bugs in the " . $product->name . 
+                         " product") . ", 1, NOW())");
         my $gid = $dbh->bz_last_key('groups', 'id');
         my $admin = GroupNameToId('admin');
         # If we created a new group, give the "admin" group priviledges
@@ -378,7 +264,8 @@ if ($action eq 'new') {
         SendSQL("INSERT INTO group_control_map " .
                 "(group_id, product_id, entry, " .
                 "membercontrol, othercontrol, canedit) VALUES " .
-                "($gid, $product_id, " . Param("useentrygroupdefault") .
+                "($gid, " . $product->id . ", " . 
+                Param("useentrygroupdefault") .
                 ", " . CONTROLMAPDEFAULT . ", " .
                 CONTROLMAPNA . ", 0)");
     }
@@ -392,7 +279,6 @@ if ($action eq 'new') {
         # and never used again here, so we can trick_taint them.
         my $open_name = $cgi->param('open_name');
         trick_taint($open_name);
-        trick_taint($product);
     
         my @series;
     
@@ -415,10 +301,11 @@ if ($action eq 'new') {
         push(@series, [$open_name, $query]);
     
         foreach my $sdata (@series) {
-            my $series = new Bugzilla::Series(undef, $product, 
+            my $series = new Bugzilla::Series(undef, $product->name
                             scalar $cgi->param('subcategory'),
                             $sdata->[0], $::userid, 1,
-                            $sdata->[1] . "&product=" . url_quote($product), 1);
+                            $sdata->[1] . "&product=" .
+                            url_quote($product->name), 1);
             $series->writeToDatabase();
         }
     }
@@ -426,6 +313,7 @@ if ($action eq 'new') {
     unlink "$datadir/versioncache";
 
     $vars->{'product'} = $product;
+    
     $template->process("admin/products/created.html.tmpl", $vars)
         || ThrowTemplateError($template->error());
     exit;
@@ -439,68 +327,21 @@ if ($action eq 'new') {
 
 if ($action eq 'del') {
     
-    if (!$product) {
-        ThrowUserError('product_not_specified');
-    }
-
-    my $product_id = get_product_id($product);
-    $product_id || ThrowUserError('product_doesnt_exist',
-                                  {product => $product});
-
-    my $classification_id = 1;
+    my $product = Bugzilla::Product::check_product($product_name);
 
     if (Param('useclassification')) {
-        CheckClassificationProduct($classification, $product);
-        $classification_id = get_classification_id($classification);
+        my $classification = 
+            Bugzilla::Classification::check_classification($classification_name);
+        if ($classification->id != $product->classification_id) {
+            ThrowUserError('classification_doesnt_exist_for_product',
+                           { product => $product->name,
+                             classification => $classification->name });
+        }
         $vars->{'classification'} = $classification;
     }
 
-    # Extract some data about the product
-    my $query = q{SELECT classifications.description,
-                         products.description,
-                         products.milestoneurl,
-                         products.disallownew
-                  FROM products
-                  INNER JOIN classifications
-                    ON products.classification_id = classifications.id
-                  WHERE products.id = ?};
-
-    my ($class_description,
-        $prod_description,
-        $milestoneurl,
-        $disallownew) = $dbh->selectrow_array($query, undef,
-                                              $product_id);
-
-    $vars->{'class_description'} = $class_description;
-    $vars->{'product_id'}        = $product_id;
-    $vars->{'prod_description'}  = $prod_description;
-    $vars->{'milestoneurl'}      = $milestoneurl;
-    $vars->{'disallownew'}       = $disallownew;
-    $vars->{'product_name'}      = $product;
-
-    $vars->{'components'} = $dbh->selectall_arrayref(q{
-        SELECT name, description FROM components
-        WHERE product_id = ? ORDER BY name}, {'Slice' => {}},
-        $product_id);
-
-    $vars->{'versions'} = $dbh->selectcol_arrayref(q{
-            SELECT value FROM versions
-            WHERE product_id = ? ORDER BY value}, undef,
-            $product_id);
-
-    # Adding listing for associated target milestones - 
-    # matthew@zeroknowledge.com
-    if (Param('usetargetmilestone')) {
-        $vars->{'milestones'} = $dbh->selectcol_arrayref(q{
-            SELECT value FROM milestones
-            WHERE product_id = ?
-            ORDER BY sortkey, value}, undef, $product_id);
-    }
+    $vars->{'product'} = $product;
 
-    ($vars->{'bug_count'}) = $dbh->selectrow_array(q{
-        SELECT COUNT(*) FROM bugs WHERE product_id = ?},
-        undef, $product_id) || 0;
     $template->process("admin/products/confirm-delete.html.tmpl", $vars)
         || ThrowTemplateError($template->error());
     exit;
@@ -512,33 +353,32 @@ if ($action eq 'del') {
 
 if ($action eq 'delete') {
     
-    if (!$product) {
-        ThrowUserError('product_not_specified');
-    }
-
-    my $product_id = get_product_id($product);
-    $product_id || ThrowUserError('product_doesnt_exist',
-                                  {product => $product});
-
+    my $product = Bugzilla::Product::check_product($product_name);
+    
     $vars->{'product'} = $product;
-    $vars->{'classification'} = $classification;
 
-    my $bug_ids = $dbh->selectcol_arrayref(q{
-        SELECT bug_id FROM bugs
-        WHERE product_id = ?}, undef, $product_id);
+    if (Param('useclassification')) {
+        my $classification = 
+            Bugzilla::Classification::check_classification($classification_name);
+        if ($classification->id != $product->classification_id) {
+            ThrowUserError('classification_doesnt_exist_for_product',
+                           { product => $product->name,
+                             classification => $classification->name });
+        }
+        $vars->{'classification'} = $classification;
+    }
 
-    my $nb_bugs = scalar(@$bug_ids);
-    if ($nb_bugs) {
+    if ($product->bug_count) {
         if (Param("allowbugdeletion")) {
-            foreach my $bug_id (@$bug_ids) {
+            foreach my $bug_id (@{$product->bug_ids}) {
                 my $bug = new Bugzilla::Bug($bug_id, $whoid);
                 $bug->remove_from_db();
             }
         }
         else {
-            ThrowUserError("product_has_bugs", { nb => $nb_bugs });
+            ThrowUserError("product_has_bugs", 
+                           { nb => $product->bug_count });
         }
-        $vars->{'nb_bugs'} = $nb_bugs;
     }
 
     $dbh->bz_lock_tables('products WRITE', 'components WRITE',
@@ -547,25 +387,25 @@ if ($action eq 'delete') {
                          'flaginclusions WRITE', 'flagexclusions WRITE');
 
     $dbh->do("DELETE FROM components WHERE product_id = ?",
-             undef, $product_id);
+             undef, $product->id);
 
     $dbh->do("DELETE FROM versions WHERE product_id = ?",
-             undef, $product_id);
+             undef, $product->id);
 
     $dbh->do("DELETE FROM milestones WHERE product_id = ?",
-             undef, $product_id);
+             undef, $product->id);
 
     $dbh->do("DELETE FROM group_control_map WHERE product_id = ?",
-             undef, $product_id);
+             undef, $product->id);
 
     $dbh->do("DELETE FROM flaginclusions WHERE product_id = ?",
-             undef, $product_id);
+             undef, $product->id);
              
     $dbh->do("DELETE FROM flagexclusions WHERE product_id = ?",
-             undef, $product_id);
+             undef, $product->id);
              
     $dbh->do("DELETE FROM products WHERE id = ?",
-             undef, $product_id);
+             undef, $product->id);
 
     $dbh->bz_unlock_tables();
 
@@ -583,74 +423,28 @@ if ($action eq 'delete') {
 # (next action would be 'update')
 #
 
-if ($action eq 'edit' || (!$action && $product)) {
-    CheckProduct($product);
-    trick_taint($product);
-    my $product_id = get_product_id($product); 
-    my $classification_id=1;
+if ($action eq 'edit' || (!$action && $product_name)) {
+
+    my $product = Bugzilla::Product::check_product($product_name);
+
     if (Param('useclassification')) {
-        # If a product has been given with no classification associated
-        # with it, take this information from the DB
-        if ($classification) {
-            CheckClassificationProduct($classification, $product);
+        my $classification; 
+        if (!$classification_name) {
+            $classification = 
+                new Bugzilla::Classification($product->classification_id);
         } else {
-            $classification =
-                $dbh->selectrow_array("SELECT classifications.name
-                                       FROM products, classifications
-                                       WHERE products.name = ?
-                                       AND classifications.id = products.classification_id",
-                                       undef, $product);
+            $classification = 
+                Bugzilla::Classification::check_classification($classification_name);
+            if ($classification->id != $product->classification_id) {
+                ThrowUserError('classification_doesnt_exist_for_product',
+                               { product => $product->name,
+                                 classification => $classification->name });
+            }
         }
-        $classification_id = get_classification_id($classification);
-    }
-    
-    $vars->{'classification'} = $classification;
-
-    # get data of product
-    $vars->{'product'} = $dbh->selectrow_hashref(qq{
-            SELECT id, name, classification_id, description,
-                   milestoneurl, disallownew, votesperuser,
-                   maxvotesperbug, votestoconfirm, defaultmilestone
-              FROM products
-             WHERE id = ?}, undef, $product_id);
-    
-   
-    $vars->{'components'} = $dbh->selectall_arrayref(qq{
-            SELECT name, description
-              FROM components
-             WHERE product_id = ?
-          ORDER BY name}, {'Slice' => {}},$product_id); 
-    
-    
-    $vars->{'versions'} = $dbh->selectcol_arrayref(q{
-        SELECT value FROM versions
-         WHERE product_id = ?
-      ORDER BY value}, undef, $product_id);
-
-    if (Param('usetargetmilestone')) {
-        $vars->{'milestones'} = $dbh->selectcol_arrayref(q{
-                                    SELECT value 
-                                      FROM milestones
-                                     WHERE product_id = ?
-                                  ORDER BY sortkey, value}, 
-                                     undef, $product_id);
+        $vars->{'classification'} = $classification;
     }
+    my $group_controls = $product->group_controls;
         
-    my $query = qq{SELECT
-                       groups.id, groups.name, groups.isactive,
-                       group_control_map.entry,
-                       group_control_map.membercontrol,
-                       group_control_map.othercontrol,
-                       group_control_map.canedit
-                  FROM groups
-                 INNER JOIN group_control_map
-                        ON groups.id = group_control_map.group_id
-                  WHERE group_control_map.product_id = ?
-                  AND   groups.isbuggroup != 0
-                  ORDER BY groups.name};
-    my $groups = $dbh->selectall_arrayref($query, {'Slice' => {}},
-                                          $product_id);
-    
     # Convert Group Controls(membercontrol and othercontrol) from 
     # integer to string to display Membercontrol/Othercontrol names
     # at the template. <gabriel@async.com.br>
@@ -660,19 +454,16 @@ if ($action eq 'edit' || (!$action && $product)) {
         (CONTROLMAPDEFAULT) => 'Default',
         (CONTROLMAPMANDATORY) => 'Mandatory'};
 
-    foreach my $group (@$groups) {
-        $group->{'membercontrol'} =
-            $constants->{$group->{'membercontrol'}};
-        $group->{'othercontrol'} =
-            $constants->{$group->{'othercontrol'}};
+    foreach my $group (keys(%$group_controls)) {
+        foreach my $control ('membercontrol', 'othercontrol') {
+            $group_controls->{$group}->{$control} = 
+                $constants->{$group_controls->{$group}->{$control}};
+        }
     }
-   
-    $vars->{'groups'} = $groups;
-    
-    $vars->{'bug_count'} = $dbh->selectrow_array(qq{
-            SELECT COUNT(*) FROM bugs
-            WHERE product_id = ?}, undef, $product_id);
-    
+    $vars->{'group_controls'} = $group_controls;
+
+    $vars->{'product'} = $product;
+        
     $template->process("admin/products/edit.html.tmpl", $vars)
         || ThrowTemplateError($template->error());
 
@@ -684,7 +475,8 @@ if ($action eq 'edit' || (!$action && $product)) {
 #
 
 if ($action eq 'updategroupcontrols') {
-    my $product_id = get_product_id($product);
+
+    my $product = Bugzilla::Product::check_product($product_name);
     my @now_na = ();
     my @now_mandatory = ();
     foreach my $f ($cgi->param()) {
@@ -705,7 +497,7 @@ if ($action eq 'updategroupcontrols') {
                      WHERE groups.id IN(" . join(', ', @now_na) . ")
                      AND bug_group_map.group_id = groups.id
                      AND bug_group_map.bug_id = bugs.bug_id
-                     AND bugs.product_id = $product_id " .
+                     AND bugs.product_id = " . $product->id . " " .
                     $dbh->sql_group_by('groups.name'));
             while (MoreSQLData()) {
                 my ($groupname, $bugcount) = FetchSQLData();
@@ -725,7 +517,7 @@ if ($action eq 'updategroupcontrols') {
                  INNER JOIN groups
                          ON bug_group_map.group_id = groups.id
                       WHERE groups.id IN(" . join(', ', @now_mandatory) . ")
-                        AND bugs.product_id = $product_id
+                        AND bugs.product_id = " . $product->id . " 
                         AND bug_group_map.bug_id IS NULL " .
                         $dbh->sql_group_by('groups.name'));
             while (MoreSQLData()) {
@@ -775,8 +567,8 @@ if ($action eq 'updategroupcontrols') {
     SendSQL("SELECT id, name, entry, membercontrol, othercontrol, canedit " .
             "FROM groups " .
             "LEFT JOIN group_control_map " .
-            "ON group_control_map.group_id = id AND product_id = $product_id " .
-            "WHERE isbuggroup != 0 AND isactive != 0");
+            "ON group_control_map.group_id = id AND product_id = " .
+            $product->id . " WHERE isbuggroup != 0 AND isactive != 0");
     while (MoreSQLData()) {
         my ($groupid, $groupname, $entry, $membercontrol, 
             $othercontrol, $canedit) = FetchSQLData();
@@ -800,7 +592,7 @@ if ($action eq 'updategroupcontrols') {
                     "(group_id, product_id, entry, " .
                     "membercontrol, othercontrol, canedit) " .
                     "VALUES " .
-                    "($groupid, $product_id, $newentry, " .
+                    "($groupid, " . $product->id . ", $newentry, " .
                     "$newmembercontrol, $newothercontrol, $newcanedit)");
             PopGlobalSQLState();
         } elsif (($newentry != $entry) 
@@ -814,7 +606,7 @@ if ($action eq 'updategroupcontrols') {
                     "othercontrol = $newothercontrol, " .
                     "canedit = $newcanedit " .
                     "WHERE group_id = $groupid " .
-                    "AND product_id = $product_id");
+                    "AND product_id = " . $product->id);
             PopGlobalSQLState();
         }
 
@@ -823,7 +615,7 @@ if ($action eq 'updategroupcontrols') {
             PushGlobalSQLState();
             SendSQL("DELETE FROM group_control_map " .
                     "WHERE group_id = $groupid " .
-                    "AND product_id = $product_id");
+                    "AND product_id = " . $product->id);
             PopGlobalSQLState();
         }
     }
@@ -836,7 +628,7 @@ if ($action eq 'updategroupcontrols') {
                  FROM bugs, bug_group_map
                  WHERE group_id = $groupid
                  AND bug_group_map.bug_id = bugs.bug_id
-                 AND bugs.product_id = $product_id
+                 AND bugs.product_id = " . $product->id . "
                  ORDER BY bugs.bug_id");
         while (MoreSQLData()) {
             my ($bugid, $mailiscurrent) = FetchSQLData();
@@ -871,7 +663,7 @@ if ($action eq 'updategroupcontrols') {
                  LEFT JOIN bug_group_map
                  ON bug_group_map.bug_id = bugs.bug_id
                  AND group_id = $groupid
-                 WHERE bugs.product_id = $product_id
+                 WHERE bugs.product_id = " . $product->id . "
                  AND bug_group_map.bug_id IS NULL
                  ORDER BY bugs.bug_id");
         while (MoreSQLData()) {
@@ -903,8 +695,6 @@ if ($action eq 'updategroupcontrols') {
 
     $vars->{'added_mandatory'} = \@added_mandatory;
 
-    $vars->{'classification'} = $classification;
-
     $vars->{'product'} = $product;
 
     $template->process("admin/products/groupcontrol/updated.html.tmpl", $vars)
@@ -917,28 +707,45 @@ if ($action eq 'updategroupcontrols') {
 #
 if ($action eq 'update') {
 
-    $vars->{'classification'} = $classification;
-
-    my $productold          = trim($cgi->param('productold')          || '');
+    my $product_old_name    = trim($cgi->param('product_old_name')    || '');
     my $description         = trim($cgi->param('description')         || '');
-    my $descriptionold      = trim($cgi->param('descriptionold')      || '');
     my $disallownew         = trim($cgi->param('disallownew')         || '');
-    my $disallownewold      = trim($cgi->param('disallownewold')      || '');
     my $milestoneurl        = trim($cgi->param('milestoneurl')        || '');
-    my $milestoneurlold     = trim($cgi->param('milestoneurlold')     || '');
     my $votesperuser        = trim($cgi->param('votesperuser')        || 0);
-    my $votesperuserold     = trim($cgi->param('votesperuserold')     || 0);
     my $maxvotesperbug      = trim($cgi->param('maxvotesperbug')      || 0);
-    my $maxvotesperbugold   = trim($cgi->param('maxvotesperbugold')   || 0);
     my $votestoconfirm      = trim($cgi->param('votestoconfirm')      || 0);
-    my $votestoconfirmold   = trim($cgi->param('votestoconfirmold')   || 0);
     my $defaultmilestone    = trim($cgi->param('defaultmilestone')    || '---');
-    my $defaultmilestoneold = trim($cgi->param('defaultmilestoneold') || '---');
 
     my $checkvotes = 0;
 
-    CheckProduct($productold);
-    my $product_id = get_product_id($productold);
+    my $product_old = Bugzilla::Product::check_product($product_old_name);
+
+    if (Param('useclassification')) {
+        my $classification; 
+        if (!$classification_name) {
+            $classification = 
+                new Bugzilla::Classification($product_old->classification_id);
+        } else {
+            $classification = 
+                Bugzilla::Classification::check_classification($classification_name);
+            if ($classification->id != $product_old->classification_id) {
+                ThrowUserError('classification_doesnt_exist_for_product',
+                               { product => $product_old->name,
+                                 classification => $classification->name });
+            }
+        }
+        $vars->{'classification'} = $classification;
+    }
+
+    unless ($product_name) {
+        ThrowUserError('prod_cant_delete_name',
+                       {product => $product_old->name});
+    }
+
+    unless ($description) {
+        ThrowUserError('prod_cant_delete_description',
+                       {product => $product_old->name});
+    }
 
     my $stored_maxvotesperbug = $maxvotesperbug;
     if (!detaint_natural($maxvotesperbug)) {
@@ -958,9 +765,6 @@ if ($action eq 'update') {
                        {votestoconfirm => $stored_votestoconfirm});
     }
 
-    # Note that we got the $product_id using $productold above so it will
-    # remain static even after we rename the product in the database.
-
     $dbh->bz_lock_tables('products WRITE',
                          'versions READ',
                          'groups WRITE',
@@ -968,120 +772,87 @@ if ($action eq 'update') {
                          'profiles WRITE',
                          'milestones READ');
 
-    if ($disallownew ne $disallownewold) {
-        $disallownew = $disallownew ? 1 : 0;
+    my $testproduct = 
+        new Bugzilla::Product({name => $product_name});
+    if (lc($product_name) ne lc($product_old->name) &&
+        $testproduct) {
+        ThrowUserError('prod_name_already_in_use',
+                       {product => $product_name});
+    }
+
+    my $milestone = new Bugzilla::Milestone($product_old->id,
+                                            $defaultmilestone);
+    if (!$milestone) {
+        ThrowUserError('prod_must_define_defaultmilestone',
+                       {product          => $product_old->name,
+                        defaultmilestone => $defaultmilestone,
+                        classification   => $classification_name});
+    }
+
+    $disallownew = $disallownew ? 1 : 0;
+    if ($disallownew ne $product_old->disallow_new) {
         SendSQL("UPDATE products
                  SET disallownew=$disallownew
-                 WHERE id=$product_id");
-        $vars->{'updated_bugsubmitstatus'} = 1;
-        $vars->{'new_bugsubmitstatus'} = $disallownew;        
+                 WHERE id = " . $product_old->id);
     }
 
-    if ($description ne $descriptionold) {
-        unless ($description) {
-            ThrowUserError('prod_cant_delete_description',
-                           {product => $productold});
-        }
+    if ($description ne $product_old->description) {
         SendSQL("UPDATE products
                  SET description=" . SqlQuote($description) . "
-                 WHERE id=$product_id");
-        $vars->{'updated_description'} = 1;
-        $vars->{'old_description'} = $descriptionold;        
-        $vars->{'new_description'} = $description;        
+                 WHERE id = " . $product_old->id);
     }
 
     if (Param('usetargetmilestone')
-        && ($milestoneurl ne $milestoneurlold)) {
+        && ($milestoneurl ne $product_old->milestone_url)) {
         SendSQL("UPDATE products
                  SET milestoneurl=" . SqlQuote($milestoneurl) . "
-                 WHERE id=$product_id");
-        $vars->{'updated_milestoneurl'} = 1;
-        $vars->{'old_milestoneurl'} = $milestoneurlold;        
-        $vars->{'new_milestoneurl'} = $milestoneurl;        
+                 WHERE id = " . $product_old->id);
     }
 
 
-    if ($votesperuser ne $votesperuserold) {
+    if ($votesperuser ne $product_old->votes_per_user) {
         SendSQL("UPDATE products
                  SET votesperuser=$votesperuser
-                 WHERE id=$product_id");
-        $vars->{'updated_votesperuser'} = 1;
-        $vars->{'old_votesperuser'} = $votesperuserold;        
-        $vars->{'new_votesperuser'} = $votesperuser;        
-
+                 WHERE id = " . $product_old->id);
         $checkvotes = 1;
     }
 
 
-    if ($maxvotesperbug ne $maxvotesperbugold) {
+    if ($maxvotesperbug ne $product_old->max_votes_per_bug) {
         SendSQL("UPDATE products
                  SET maxvotesperbug=$maxvotesperbug
-                 WHERE id=$product_id");
-        $vars->{'updated_maxvotesperbug'} = 1;
-        $vars->{'old_maxvotesperbug'} = $maxvotesperbugold;        
-        $vars->{'new_maxvotesperbug'} = $maxvotesperbug;        
-
+                 WHERE id = " . $product_old->id);
         $checkvotes = 1;
     }
 
 
-    if ($votestoconfirm ne $votestoconfirmold) {
+    if ($votestoconfirm ne $product_old->votes_to_confirm) {
         SendSQL("UPDATE products
                  SET votestoconfirm=$votestoconfirm
-                 WHERE id=$product_id");
-
-        $vars->{'updated_votestoconfirm'} = 1;
-        $vars->{'old_votestoconfirm'} = $votestoconfirmold;
-        $vars->{'new_votestoconfirm'} = $votestoconfirm;
+                 WHERE id = " . $product_old->id);
 
         $checkvotes = 1;
     }
 
 
-    if ($defaultmilestone ne $defaultmilestoneold) {
-        SendSQL("SELECT value FROM milestones " .
-                "WHERE value = " . SqlQuote($defaultmilestone) .
-                "  AND product_id = $product_id");
-        if (!FetchOneColumn()) {
-            ThrowUserError('prod_must_define_defaultmilestone',
-                           {product          => $productold,
-                            defaultmilestone => $defaultmilestone,
-                            classification   => $classification});
-        }
+    if ($defaultmilestone ne $product_old->default_milestone) {
         SendSQL("UPDATE products " .
                 "SET defaultmilestone = " . SqlQuote($defaultmilestone) .
-                "WHERE id=$product_id");
+                "WHERE id = " . $product_old->id);
 
-        $vars->{'updated_defaultmilestone'} = 1;
-        $vars->{'old_defaultmilestone'} = $defaultmilestoneold;
-        $vars->{'new_defaultmilestone'} = $defaultmilestone;
     }
 
-    my $qp = SqlQuote($product);
-    my $qpold = SqlQuote($productold);
-
-    if ($product ne $productold) {
-        unless ($product) {
-            ThrowUserError('prod_cant_delete_name',
-                           {product => $productold});
-        }
-
-        if (lc($product) ne lc($productold) &&
-            TestProduct($product)) {
-            ThrowUserError('prod_name_already_in_use',
-                           {product => $product});
-        }
-
-        SendSQL("UPDATE products SET name=$qp WHERE id=$product_id");
+    my $qp = SqlQuote($product_name);
 
-        $vars->{'updated_product'} = 1;
-        $vars->{'old_product'} = $productold;
-        $vars->{'new_product'} = $product;
+    if ($product_name ne $product_old->name) {
+        SendSQL("UPDATE products SET name=$qp WHERE id= ".$product_old->id);
 
     }
     $dbh->bz_unlock_tables();
     unlink "$datadir/versioncache";
 
+    my $product = new Bugzilla::Product({name => $product_name});
+
     if ($checkvotes) {
         $vars->{'checkvotes'} = 1;
 
@@ -1092,7 +863,7 @@ if ($action eq 'update') {
             SendSQL("SELECT votes.who, votes.bug_id " .
                     "FROM votes, bugs " .
                     "WHERE bugs.bug_id = votes.bug_id " .
-                    " AND bugs.product_id = $product_id " .
+                    " AND bugs.product_id = " . $product->id .
                     " AND votes.vote_count > $maxvotesperbug");
             my @list;
             while (MoreSQLData()) {
@@ -1122,7 +893,7 @@ if ($action eq 'update') {
 
         SendSQL("SELECT votes.who, votes.vote_count FROM votes, bugs " .
                 "WHERE bugs.bug_id = votes.bug_id " .
-                " AND bugs.product_id = $product_id");
+                " AND bugs.product_id = " . $product->id);
         my %counts;
         while (MoreSQLData()) {
             my ($who, $count) = (FetchSQLData());
@@ -1137,7 +908,7 @@ if ($action eq 'update') {
             if ($counts{$who} > $votesperuser) {
                 SendSQL("SELECT votes.bug_id FROM votes, bugs " .
                         "WHERE bugs.bug_id = votes.bug_id " .
-                        " AND bugs.product_id = $product_id " .
+                        " AND bugs.product_id = " . $product->id .
                         " AND votes.who = $who");
                 while (MoreSQLData()) {
                     my ($id) = FetchSQLData();
@@ -1157,7 +928,7 @@ if ($action eq 'update') {
                                                  WHERE product_id = ?
                                                  AND bug_status = 'UNCONFIRMED'
                                                  AND votes >= ?",
-                                                 undef, ($product_id, $votestoconfirm));
+                                                 undef, ($product->id, $votestoconfirm));
 
         my @updated_bugs = ();
         foreach my $bug_id (@$bug_list) {
@@ -1170,7 +941,9 @@ if ($action eq 'update') {
 
     }
 
-    $vars->{'name'} = $product;
+    $vars->{'old_product'} = $product_old;
+    $vars->{'product'} = $product;
+
     $template->process("admin/products/updated.html.tmpl", $vars)
         || ThrowTemplateError($template->error());
 
@@ -1182,22 +955,20 @@ if ($action eq 'update') {
 #
 
 if ($action eq 'editgroupcontrols') {
-    my $product_id = get_product_id($product);
-    $product_id
-      || ThrowUserError("invalid_product_name", { product => $product });
+    my $product = Bugzilla::Product::check_product($product_name);
     # Display a group if it is either enabled or has bugs for this product.
     SendSQL("SELECT id, name, entry, membercontrol, othercontrol, canedit, " .
             "isactive, COUNT(bugs.bug_id) " .
             "FROM groups " .
             "LEFT JOIN group_control_map " .
             "ON group_control_map.group_id = id " .
-            "AND group_control_map.product_id = $product_id " .
-            "LEFT JOIN bug_group_map " .
+            "AND group_control_map.product_id = " . $product->id .
+            " LEFT JOIN bug_group_map " .
             "ON bug_group_map.group_id = groups.id " .
             "LEFT JOIN bugs " .
             "ON bugs.bug_id = bug_group_map.bug_id " .
-            "AND bugs.product_id = $product_id " .
-            "WHERE isbuggroup != 0 " .
+            "AND bugs.product_id = " . $product->id .
+            " WHERE isbuggroup != 0 " .
             "AND (isactive != 0 OR entry IS NOT NULL " .
             "OR bugs.bug_id IS NOT NULL) " .
             $dbh->sql_group_by('name', 'id, entry, membercontrol,
@@ -1218,8 +989,9 @@ if ($action eq 'editgroupcontrols') {
         push @groups,\%group;
     }
     $vars->{'product'} = $product;
-    $vars->{'classification'} = $classification;
+
     $vars->{'groups'} = \@groups;
+    
     $vars->{'const'} = {
         'CONTROLMAPNA' => CONTROLMAPNA,
         'CONTROLMAPSHOWN' => CONTROLMAPSHOWN,
index 672f345e9a59cead3454df8b29497faba2bdb537..9358974de1f600adb0671aa170d9f780464f5e75 100644 (file)
   #%]
 
 [%# INTERFACE:
-  # product_name: string; The name of the product
-  #
-  # prod_description: string; Product description, may be empty
+  # product: Bugzilla::Product object; The product
   #
   # (classification fields available if Param('useclassification') is enabled:)
   #
-  # classification: string; The name of the classification the product is in
-  #
-  # class_description: string; Classification description, may be empty
-  #
-  # bug_count: number; The number of bugs belonging to the product
-  #
-  # milestoneurl: string; milestone url, if milestones are in use,
-  #                       may be empty
-  #
-  # disallownew: boolean; Are new bugs allowed for the product flag
-  #
-  # components: list of hashes, members are: name, description
-  #
-  # versions: list of version values.
-  #
-  # milestones: list of milestone values.
+  # classification: Bugzilla::Classification object; The classification 
+  #                                                  the product is in
   #
   #%]
 
-[% title = BLOCK %]Delete Product '[% product_name FILTER html %]'
+[% title = BLOCK %]Delete Product '[% product.name FILTER html %]'
 [% END %]
 
 [% PROCESS global/header.html.tmpl
 
 [% IF classification %]
   [% classification_url_part = BLOCK %]&amp;classification=
-    [%- classification FILTER url_quote %]
+    [%- classification.name FILTER url_quote %]
   [%- END %]
 [% ELSE %]
   [% classification_url_part = "" %]
 [% END %]
 
-[% UNLESS class_description %]
-  [% class_description = '<span style="color: red">missing</span>' %]
-[% END %]
-[% UNLESS prod_description %]
-  [% prod_description = '<span style="color: red">missing</span>' %]
-[% END %]
-
-[% IF disallownew %]
-  [% disallownew = "closed" %]
-[% ELSE %]
-  [% disallownew = "open" %]
-[% END %]
-
 <table border="1" cellpadding="4" cellspacing="0">
   <tr bgcolor="#6666FF">
     <th valign="top" align="left">Field</th>
   [% IF Param('useclassification') %]
     <tr>
       <td>Classification:</td>
-      <td>[% classification FILTER html %]</td>
+      <td>[% classification.name FILTER html %]</td>
     </tr>
     <tr>
       <td>Classification Description:</td>
       [%# descriptions are intentionally not filtered to allow html content %]
-      <td>[% class_description FILTER none %]</td>
+      <td>
+        [% IF classification.description %]
+          [% classification.description FILTER none %]
+        [% ELSE %]
+          <span style="color: red">missing</span>
+        [% END %]
+      </td>
     </tr>
   [% END %]
 
   <tr>
     <td valign="top">Product:</td>
     <td valign="top">
-      <a href="editproducts.cgi?product=[% product_name FILTER url_quote %]
+      <a href="editproducts.cgi?product=[% product.name FILTER url_quote %]
          [%- classification_url_part %]">
-        [% product_name FILTER html %]
+        [% product.name FILTER html %]
       </a>
     </td>
   </tr>
   <tr>
     <td valign="top">Description:</td>
     [%# descriptions are intentionally not filtered to allow html content %]
-    <td valign="top">[% prod_description FILTER none %]</td>
+    <td valign="top">
+      [% IF product.description %]
+        [% product.description FILTER none %]
+      [% ELSE %]
+        <span style="color: red">missing</span>
+      [% END %]
+    </td>
   </tr>
 
   [% IF Param('usetargetmilestone') %]
     <tr>
       <td>Milestone URL:</td>
       <td>
-        [% IF milestoneurl %]
-          <a href="[% milestoneurl FILTER uri %]">
-            [%- milestoneurl FILTER html %]
+        [% IF product.milestone_url %]
+          <a href="[% product.milestone_url FILTER uri %]">
+            [%- product.milestone_url FILTER html %]
           </a>
         [% ELSE %]
           none
 
   <tr>
     <td>Closed for [% terms.bugs %]:</td>
-    <td>[% disallownew FILTER html %]</td>
+    <td>
+      [% IF product.disallownew %]
+        closed
+      [% ELSE %]
+        open
+      [% END %]
+    </td>
   </tr>
 
   <tr>
     <td>
-      [% IF components.size > 0 %]
-        <a href="editcomponents.cgi?product=[% product_name FILTER url_quote %]
+      [% IF product.components.size > 0 %]
+        <a href="editcomponents.cgi?product=[% product.name FILTER url_quote %]
            [%- classification_url_part %]"
-           title="Edit components for product '[% product_name FILTER html %]'">
+           title="Edit components for product '[% product.name FILTER html %]'">
           Components:
         </a>
       [% ELSE %]
       [% END %]
     </td>
     <td>
-      [% IF components.size > 0 %]
+      [% IF product.components.size > 0 %]
         <table>
-          [% FOREACH c = components %]
+          [% FOREACH c = product.components %]
             <tr>
               <th align="right">[% c.name FILTER html %]:</th>
               [%# descriptions are intentionally not filtered to allow html content %]
 
   <tr>
     <td>
-      [% IF versions.size > 0 %]
-        <a href="editversions.cgi?product=[%- product_name FILTER url_quote %]
+      [% IF product.versions.size > 0 %]
+        <a href="editversions.cgi?product=[%- product.name FILTER url_quote %]
            [%- classification_url_part %]">
           Versions:
         </a>
         Versions:
       [% END %]
     <td>
-      [% IF versions.size > 0 %]
-        [% FOREACH v = versions %]
-          [% v FILTER html %]<br>
+      [% IF product.versions.size > 0 %]
+        [% FOREACH v = product.versions %]
+          [% v.name FILTER html %]<br>
         [% END %]
       [% ELSE %]
         none
 
   <tr>
     <td valign="top">
-      [% IF milestones.size > 0 %]
-        <a href="editmilestones.cgi?product=[%- product_name FILTER url_quote %]
+      [% IF product.milestones.size > 0 %]
+        <a href="editmilestones.cgi?product=[%- product.name FILTER url_quote %]
            [%- classification_url_part -%]">
           Milestones:
         </a>
       [% END %]
     </td>
     <td>
-      [% IF milestones.size > 0 %]
-        [% FOREACH m = milestones %]
-          [% m FILTER html %]<br>
+      [% IF product.milestones.size > 0 %]
+        [% FOREACH m = product.milestones %]
+          [% m.name FILTER html %]<br>
         [% END %]
       [% ELSE %]
         none
   <tr>
     <td>[% terms.Bugs %]:</td>
     <td>
-      [% IF bug_count %]
-        <a href="buglist.cgi?product=[%- product_name FILTER url_quote %]
+      [% IF product.bug_count %]
+        <a href="buglist.cgi?product=[%- product.name FILTER url_quote %]
            [%- classification_url_part %]"
            title="List of [% terms.bugs %] for product '
-           [%- product_name FILTER html %]'">
-          [% bug_count %]
+           [%- product.name FILTER html %]'">
+          [% product.bug_count FILTER html %]
         </a>
       [% ELSE %]
         none
 
 <h2>Confirmation</h2>
 
-[% IF bug_count %]
+[% IF product.bug_count %]
 
   [% IF !Param("allowbugdeletion") %]
 
     Sorry, there
 
-    [% IF bug_count > 1 %]
-      are [% bug_count %] [%+ terms.bugs %]
+    [% IF product.bug_count > 1 %]
+      are [% product.bug_count FILTER html %] [%+ terms.bugs %]
     [% ELSE %]
       is 1 [% terms.bug %]
     [% END %]
 
     outstanding for this product. You must reassign
 
-    [% IF bug_count > 1 %]
+    [% IF product.bug_count > 1 %]
        those [% terms.bugs %]
     [% ELSE %]
        that [% terms.bug %]
       <tr>
         <td>
           There
-          [% IF bug_count > 1 %]
-            are [% bug_count %] [%+ terms.bugs %]
+          [% IF product.bug_count > 1 %]
+            are [% product.bug_count FILTER html %] [%+ terms.bugs %]
           [% ELSE %]
             is 1 [% terms.bug %]
           [% END %]
 
 [% END %]
 
-[% IF bug_count == 0 || Param('allowbugdeletion') %]
+[% IF product.bug_count == 0 || Param('allowbugdeletion') %]
 
   <p>Do you really want to delete this product?<p>
 
   <form method="post" action="editproducts.cgi">
     <input type="submit" value="Yes, delete">
     <input type="hidden" name="action" value="delete">
-    <input type="hidden" name="product" value="[% product_name FILTER html %]">
+    <input type="hidden" name="product" value="[% product.name FILTER html %]">
     <input type="hidden" name="classification"
-           value="[% classification FILTER html %]">
+           value="[% classification.name FILTER html %]">
   </form>
 
 [% END %]
index 8dc6615b4eb3df2e1778e6c6156dc17d8496f3a2..dc60299b8d5c1a54d24fdcd8cbdf4768a9aa4361 100644 (file)
@@ -15,8 +15,9 @@
   #%]
 
 [%# INTERFACE:
-  # classification: string; name of the classification in which the new
-  #                         product is  created.
+  # classification: Bugzilla::Classification object; If classifications
+  #                         are enabled, then this is 
+  #                         the currently selected classification
   #
   #%]
 
   <input type="hidden" name="open_name"   value="All Open">
   <input type="hidden" name="action" value="new">
   <input type="hidden" name="classification"
-        value="[% classification FILTER html %]">
+        value="[% classification.name FILTER html %]">
 </form>
 
-[% PROCESS "admin/products/footer.html.tmpl" no_add_product_link = 1 %]
+[% PROCESS "admin/products/footer.html.tmpl"
+   no_add_product_link = 1 
+   no_edit_product_link = 1 %]
 
 [% PROCESS global/footer.html.tmpl %]
index e4229f8a23bd47b42da617c5b44f56fdc38605f0..f19854200fd03b6d80091084559125bedea6346b 100644 (file)
   # Contributor(s): Gabriel S. Oliveira <gabriel@async.com.br>
   #%]
 
+[%# INTERFACE:
+  # product: Bugzilla::Product object; the Product created.
+  #
+  #%]
+
 [% PROCESS global/header.html.tmpl 
   title = 'New Product Created'
 %]
 <br>
 <div style='border: 1px red solid; padding: 1ex;'>
   <b>You will need to   
-   <a href="editcomponents.cgi?action=add&product=[% product FILTER url_quote %]">
+   <a href="editcomponents.cgi?action=add&product=[% product.name FILTER url_quote %]">
      add at least one component
    </a> before you can enter [% terms.bugs %] against this product
   </b>
 </div>
 
-[% PROCESS "admin/products/footer.html.tmpl" name = product %]
+[% PROCESS "admin/products/footer.html.tmpl" %]
 
 [% PROCESS global/footer.html.tmpl %]
index 3252f97c9d5848467aa8a5f71a126b163e4b5f6b..049bcae0bf92665658c16280a464895e9a6c5b96 100644 (file)
   #
   #%]
 
+[%# INTERFACE:
+  # product: Bugzilla::Product object; The product
+  #
+  #%]
+
 [% PROCESS global/header.html.tmpl
   title = 'Deleting product'
 %]
 
-[% IF nb_bugs %]
+[% IF product.bug_count %]
   All references to deleted [% terms.bugs %] removed.
 [% END %]
 
@@ -35,7 +40,7 @@
 </p>
 
 <p>
-  Product [% product FILTER html %] deleted.
+  Product [% product.name FILTER html %] deleted.
 </p>
 
 [% PROCESS admin/products/footer.html.tmpl
index cbbbd8232b4396df35934619c669da189002514d..f6b0d53ce03b1d8f164671f718b715b938c61fa0 100644 (file)
   #%]
 
 [%# INTERFACE:
-  # classification: string; name of classification product is in.
-  #        product: array;  an array of product objects.
+  # product: Bugzilla::Product object; The product
+  #
+  # classification: Bugzilla::Classifiation object; classification product is in.
   #%]
 
 [% IF Param('useclassification') %]
   <tr>
     <th align="right"><b>Classification:</b></th>
-    <td><b>[% classification FILTER html %]</b></td>
+    <td><b>[% classification.name FILTER html %]</b></td>
   </tr>
 [% END %]
     
index 15843bb448708636af0d7eb996fd488965d99dc2..089ce4c8db54d745be5b111881878efccbd3eaf2 100644 (file)
   #%]
 
 [%# INTERFACE:
-  # classification: string; name of classification product is in.
-  #        product: an array of product objects.
-  #     components: an array of component object(s) related to the product.
-  #         groups: an array of group objects related to the product.
-  #       versions: an array of version objects related to product.
-  #     milestones: an array of milestones objects related to product.
-  #      bug_count: integer; number of bugs in this product.
+  # product: Bugzilla::Product object; The product
+  #
+  # (classification fields available if Param('useclassification') is enabled:)
+  #
+  # classification: Bugzilla::Classification object; The classification 
+  #                                                  the product is in
+  #
+  # groups_controls: a hash of group controls related to the product.
   #%]
 
 [% title = BLOCK %]Edit Product[% END %]
@@ -44,8 +45,8 @@
         </a>
       </th>
       <td>
-        [% IF components.size -%]
-          [% FOREACH component = components %]
+        [% IF product.components.size -%]
+          [% FOREACH component = product.components %]
             <b>[% component.name FILTER html %]:</b>&nbsp;
             [% IF component.description %]
               [% component.description FILTER none %]
@@ -65,9 +66,9 @@
 versions:</a>
       </th>
       <td>
-        [%- IF versions.size -%]
-          [% FOREACH v = versions %]
-            [% v FILTER html %]
+        [%- IF product.versions.size -%]
+          [% FOREACH v = product.versions %]
+            [% v.name FILTER html %]
             <br>
           [% END %]
         [% ELSE %]
@@ -82,9 +83,9 @@ versions:</a>
           Edit milestones:</a>
         </th>
         <td>
-          [%- IF milestones.size -%]
-            [%- FOREACH m = milestones -%]
-              [% m FILTER html %]
+          [%- IF product.milestones.size -%]
+            [%- FOREACH m = product.milestones -%]
+              [% m.name FILTER html %]
             <br>
             [% END %]
           [% ELSE %]
@@ -97,15 +98,15 @@ versions:</a>
       <th align="right" valign="top">
         <a href="editproducts.cgi?action=editgroupcontrols&product=
           [%- product.name FILTER url_quote %]&classification=
-          [%- classification FILTER url_quote %]">
+          [%- classification.name FILTER url_quote %]">
           Edit Group Access Controls:
         </a>
       </th>
       <td>
-        [% IF groups.size %]
-          [% FOREACH g = groups %]
-            <b>[% g.name FILTER html %]:</b>&nbsp;
-            [% IF g.isactive %]
+        [% IF group_controls.size %]
+          [% FOREACH g = group_controls.values %]
+            <b>[% g.group.name FILTER html %]:</b>&nbsp;
+            [% IF g.group.isactive %]
               [% g.membercontrol FILTER html %]/
               [% g.othercontrol FILTER html %]
               [% IF g.entry %], ENTRY[% END %]
@@ -122,32 +123,21 @@ versions:</a>
     </tr>
     <tr>
       <th align="right">[% terms.Bugs %]:</th>
-      <td>[% bug_count FILTER html %]</td>
+      <td><a href="buglist.cgi?product=[% product.name FILTER url_quote %]">
+            [% product.bug_count FILTER html %]</a></td>
     </tr>
   </table>
   
-  <input type="hidden" name="productold
+  <input type="hidden" name="product_old_name
         value="[% product.name FILTER html %]">
-  <input type="hidden" name="descriptionold"
-         value="[% product.description FILTER html %]">
-  <input type="hidden" name="milestoneurlold" 
-         value="[% product.milestoneurl FILTER html %]">
-  <input type="hidden" name="disallownewold"
-         value="[% product.disallownew FILTER html %]">
-  <input type="hidden" name="votesperuserold"
-       value="[% product.votesperuser FILTER html %]">
-  <input type="hidden" name="maxvotesperbugold" 
-         value="[% product.maxvotesperbug FILTER html %]">
-  <input type="hidden" name="votestoconfirmold" 
-         value="[% product.votestoconfirm FILTER html %]">
-  <input type="hidden" name="defaultmilestoneold"
-         value="[% product.defaultmilestone FILTER html %]">
   <input type="hidden" name="action" value="update">
   <input type="hidden" name="classification"
-         value="[% classification FILTER html %]">
+         value="[% classification.name FILTER html %]">
   <input type="submit" name="submit" value="Update">
 </form>
   
-[% PROCESS "admin/products/footer.html.tmpl" no_add_product_link = 1 %]
+[% PROCESS "admin/products/footer.html.tmpl"
+   no_add_product_link = 1 
+   no_edit_product_link = 1 %]
 
 [% PROCESS global/footer.html.tmpl %]
index 531e6c48ebceb1dd0696afae426c0c4fb1855488..480868abdb44cae13838724427f96ce5d7d04294 100644 (file)
   #%]
 
 [%# INTERFACE:
-  # name: string; the name of the product
+  # product: Bugzilla::Product Object; the product
   #
-  # classification: string; If classifications are enabled, then this is 
-  #                         the currently selected classification
+  # classification: Bugzilla::Classification object ; If classifications
+  #                         are enabled, then this is the currently 
+  #                         selected classification
   #
   # no_XXX_link: boolean; if defined, then don't show the corresponding
   #                       link. Supported parameters are:
 
 [% IF Param('useclassification') && classification %]
   [% classification_url_part = BLOCK %]&amp;classification=
-     [%- classification FILTER url_quote %]
+     [%- classification.name FILTER url_quote %]
   [% END %]
   [% classification_url_part_start = BLOCK %]classification=
-     [%- classification FILTER url_quote %]
+     [%- classification.name FILTER url_quote %]
   [% END %]
   [% classification_text = BLOCK %] 
-    of classification '[% classification FILTER html %]'
+    of classification '[% classification.name FILTER html %]'
   [% END %]
 [% END %]
   
     classification if they are enabled, but I'm just being paranoid %]
   [% IF Param('useclassification') && classification %]
     (<a title="Add a product to classification '
-               [%- classification FILTER html %]'"
+               [%- classification.name FILTER html %]'"
          href="editproducts.cgi?action=add
                [%- classification_url_part %]">to
-     classification '[% classification FILTER html %]'</a>)
+     classification '[% classification.name FILTER html %]'
+     </a>)
   [% END %].
 [% END %]
 
-[% IF name && !no_edit_product_link %]
+[% IF product && !no_edit_product_link %]
   Edit product <a 
-  title="Edit Product '[% name FILTER html %]' 
-         [% classification_text %]"
+  title="Edit Product '[% product.name FILTER html %]' 
+         [%- classification_text %]"
   href="editproducts.cgi?action=edit&amp;product=
-        [%- name FILTER url_quote %][% classification_url_part %]">
-        '[% name FILTER html %]'</a>.
+        [%- product.name FILTER url_quote %]
+        [%- classification_url_part %]">
+        '[% product.name FILTER html %]'</a>.
 [% END %]
 
 
@@ -80,7 +83,7 @@
 [% IF Param('useclassification') && classification %]
   Edit classification <a href="editclassifications.cgi?action=edit
     [%- classification_url_part %]">'
-    [%- classification FILTER html %]'</a>.
+    [%- classification.name FILTER html %]'</a>.
 
 [% END %]
 
index 006189c13d78a8facd55f48d457b2551c7bad77c..f8d55c397df2224a1f426851e13320ae902a5d39 100644 (file)
   #%]
 
 [% PROCESS global/variables.none.tmpl %]
+[% title = BLOCK %]
+  Confirm Group Control Change for product '[%- product.name FILTER html %]'
+[% END %]
 
-[% PROCESS global/header.html.tmpl title="Confirm Group Control Change for product \'$product\'" %]
-
+[% PROCESS global/header.html.tmpl title = title %]
 [% FOREACH group = mandatory_groups %]
 <P>
 group '[% group.name FILTER html %]' impacts [% group.count %] 
index 4f13e6f22969a30885d84bf27f4ac721a8e63ac3..174d1586903df0c51b40e77caa89e6c6cf41cd98 100644 (file)
 
 [% PROCESS global/variables.none.tmpl %]
 
-[% filt_product = product FILTER html %]
-[% filt_classification = classification FILTER html %]
-[% PROCESS global/header.html.tmpl
-  title = "Edit Group Controls for '$filt_product'"
+[% title = BLOCK %]
+    Edit Group Controls for [% product.name FILTER html %]
+[% END %]
+[% PROCESS global/header.html.tmpl 
+   title = title 
 %]
 
 <form method="post" action="editproducts.cgi">
   <input type="hidden" name="action" value="updategroupcontrols">
-  <input type="hidden" name="product" value="[% filt_product %]">
-  <input type="hidden" name="classification" value="[% filt_classification %]">
+  <input type="hidden" name="product" value="[% product.name FILTER html %]">
+  <input type="hidden" name="classification" 
+         value="[% classification.name FILTER html %]">
 
   <table id="form" cellspacing="0" cellpadding="4" border="1">
     <tr bgcolor="#6666ff">
index 71ae0d7eb217d6039facfc26cec0aee7b6faaccc..5719bc6e6b9424ced3d9479c6f7f6d84313453b9 100644 (file)
 [%# INTERFACE:
   #      removed_na: array of hashes; groups not applicable for the product.  
   # added_mandatory: array of hashes; groups mandatory for the product.  
-  #  classification: string; product classification name.
-  #         product: string; name of the product.
+  #  classification: Bugzilla::Classification object;  product classification.
+  #         product: Bugzilla::Product object; the product.
   #%]
 
 [% title = BLOCK %]
-    Update group access controls for [% product FILTER html %]
+    Update group access controls for [% product.name FILTER html %]
 [% END %]
 
 [% PROCESS global/header.html.tmpl
@@ -48,6 +48,6 @@
 
 Group control updates done<p>
 
-[% PROCESS admin/products/footer.html.tmpl name = product %]
+[% PROCESS admin/products/footer.html.tmpl %]
 
 [% PROCESS global/footer.html.tmpl %]
index 98676e198efc3634058a62128d7436a917c4e3fa..17eb61c0df7402b6e7de22c212cbe72738d392a7 100644 (file)
   #%]
 
 [%# INTERFACE:
-  # products: array of hashes having the following properties:
-  #   - name: string; The name of the product
-  #   - description: string; The product description (html allowed)
-  #   - status: boolean; Can new bugs be created for the product?
-  #   - votesperuser: number; The number of votes a user is allowed 
-  #                           in the product
-  #   - maxvotersperbug: number; Maximum votes allowed per bug in this
-  #                              product
-  #   - votestoconfirm: number; The number of votes that are needed to
-  #                             auto-confirm a bug in this product
-  #   - bug_count: number; The number of bugs in this product
+  # products: array of Bugzilla::Product objects 
   #
-  # classification: string; If classifications are enabled, then this is 
+  # classification: Bugzilla::Classification object; If classifications
+  #                         are enabled, then this is 
   #                         the currently selected classification
   #%]
 
 
 [% IF classification %]
   [% classification_url_part = BLOCK %]&amp;classification=
-    [%- classification FILTER url_quote %]
+    [%- classification.name FILTER url_quote %]
   [%- END %]
   [% classification_title = BLOCK %] 
-    in classification '[% classification FILTER html %]'
+    in classification '[% classification.name FILTER html %]'
   [% END %]
 [% END %]
   
@@ -54,7 +45,7 @@
   editproducts.cgi?action=del&amp;product=%%name%%
   [%- classification_url_part %]
 [% END %]
-[% bug_count_contentlink = BLOCK %]buglist.cgi?product=%%name%%&amp;
+[% bug_count_contentlink = BLOCK %]buglist.cgi?product=%%name%%
   [%- classification_url_part %][% END %]
 
 
@@ -70,9 +61,8 @@
        allow_html_content => 1
      },
      { 
-       name => "status"
+       name => "disallow_new"
        heading => "Open For New $terms.Bugs"
-       yesno_field => 1
      },
      { 
        name => "votesperuser"
        align => 'right'
        contentlink => bug_count_contentlink
      },
+     {
+       heading => "Action"
+       content => "Delete"
+       contentlink => delete_contentlink
+     },
    ]
 %]
 
-[% columns.push({
-     heading => "Action"
-     content => "Delete"
-     contentlink => delete_contentlink
-   })
-%]
+[% overrides.disallow_new = [ {
+     match_value => "1"
+     match_field => 'disallow_new'
+     override_content => 1
+     content => "No"
+   },
+   {
+     match_value => 0
+     match_field => 'disallow_new'
+     override_content => 1
+     content => "Yes"
+   }]
+%] 
 
 [% PROCESS admin/table.html.tmpl
      columns = columns
index 7c00c4ae53354dbb4ce1fb3b351444fdb6b15c1a..993a27ed911e41071073a23d278c056068986eb6 100644 (file)
 
 [%# INTERFACE:
   #
-  # updated_XXX : boolean; is true when the 'XXX' field has been updated.
-  # old_XXX : ... string; old value of the field 'XXX'.
-  # new_XXX : ... string; new value of the field 'XXX'.
+  # old_product : Bugzilla::Product Object; old product.
+  # product : Bugzilla::Product Object; new product.
   #
-  # updated_product: boolean; the name of the product was updated
-  #
-  # updated_description: boolean; the product description was updated
-  #
-  # updated_milestoneurl: boolean; the product milestone URL was updated
-  #
-  # updated_votesperuser: boolean; the votes per user was updated
-  #
-  # updated_maxvotesperbug: boolean; the max votes per bug was updated
-  #
-  # updated_votestoconfirm: boolean; the votes to confirm a bug was updated
-  #
-  # updated_defaultmilestone: boolean; the default milestone was updated
-  #
-  # updated_bugsubmitstatus: boolean; the open/closed for new bugs status 
-  #                          was updated (no 'old_XXX' value)
-  #
-  # classification: string; The product classification (may be empty or missing)
-  #
-  # changer: string; user id of the user making the changes, used for mailing
-  #          bug changes if necessary
-  #
-  # name: string; the product name
+  # classification: Bugzilla::Classification Object; The product classification (may be empty or missing)
   #
   # checkvotes: boolean; is true if vote related fields have changed. If so, 
   #             then the following parameters will be specified:
   #
   # confirmedbugs: list of bug ids, which were confirmed by votes
   #
+  # changer: string; user id of the user making the changes, used for mailing
+  #          bug changes if necessary
+  #
   #%]
 
 [% IF classification %]
   [% classification_url_part = BLOCK %]&amp;classification=
-     [%- classification FILTER url_quote %]
+     [%- classification.name FILTER url_quote %]
   [% END %]
   [% classification_text = BLOCK %] 
-    of classification '[% classification FILTER html %]'
+    of classification '[% classification.name FILTER html %]'
   [% END %]
 [% END %]
 
-[% title = BLOCK %]Updating Product '[% name FILTER html %]' 
+[% title = BLOCK %]Updating Product '[% product.name FILTER html %]' 
                    [% classification_text FILTER none %][% END %]
 [% PROCESS global/header.html.tmpl
   title = title
   style_urls = ['skins/standard/admin.css']
 %]
+[% updated = 0 %]
 
-[% IF updated_product %]
+[% IF product.name != old_product.name %]
   <p>
-  Updated product name from '[% old_product FILTER html %]' to 
+  Updated product name from '[% old_product.name FILTER html %]' to 
   <a href="editproducts.cgi?action=edit&amp;product=
-  [%- new_product FILTER url_quote %]
-  [%- classification_url_part FILTER none %]">[% new_product FILTER html %]</a>.
+  [%- product.name FILTER url_quote %]
+  [%- classification_url_part FILTER none %]">[% product.name FILTER html %]</a>.
+  [% updated = 1 %]
 [% END %]
 
 
-[% IF updated_description %]
+[% IF product.description != old_product.description %]
   <p>
     Updated description to:</p>
   </p>
-  <p style="margin: 1em 3em 1em 3em">[% new_description FILTER html %]</p>
+  <p style="margin: 1em 3em 1em 3em">[% product.description FILTER html %]</p>
+  [% updated = 1 %]
 [% END %]
 
-[% IF updated_bugsubmitstatus %]
+[% IF product.disallow_new != old_product.disallow_new %]
   <p>
   Product is now
-  [% IF new_bugsubmitstatus %]
+  [% IF product.disallow_new %]
     closed to
   [% ELSE %]
     open for 
   [% END %]
   new [% terms.bugs %].
+  [% updated = 1 %]
 [% END %]
 
-[% IF updated_milestoneurl %]
+[% IF product.milestone_url != old_product.milestone_url %]
   <p>
   Updated milestone URL 
-  [% IF old_milestoneurl != '' %]
-    from<br> <a href="[%- old_milestoneurl FILTER html %]">'
-    [%- old_milestoneurl FILTER html %]'</a>
+  [% IF old_product.milestone_url != '' %]
+    from<br> <a href="[%- old_product.milestone_url FILTER html %]">'
+    [%- old_product.milestone_url FILTER html %]'</a>
   [% END %]
   to
-  [% IF new_milestoneurl != '' %]
-     <br><a href="[%- new_milestoneurl FILTER html %]">'
-     [%- new_milestoneurl FILTER html %]'</a>.
+  [% IF product.milestone_url != '' %]
+     <br><a href="[%- product.milestone_url FILTER html %]">'
+     [%- product.milestone_url FILTER html %]'</a>.
   [% ELSE %]
     be empty.
   [% END %]
   </p>
+  [% updated = 1 %]
 [% END %]
 
-[% IF updated_defaultmilestone %]
+[% IF product.default_milestone != old_product.default_milestone %]
   <p>
-  Updated default milestone from '[% old_defaultmilestone FILTER html %]' to
-  '[% new_defaultmilestone FILTER html %]'.
+  Updated default milestone from '[% old_product.default_milestone FILTER html %]' to
+  '[% product.default_milestone FILTER html %]'.
   </p>
+  [% updated = 1 %]
 [% END %]
   
-[% IF updated_votesperuser %]
+[% IF product.votes_per_user != old_product.votes_per_user %]
   <p>
   Updated votes per user from
-  [%+ old_votesperuser FILTER html %] to 
-  [%+ new_votesperuser FILTER html %].
+  [%+ old_product.votes_per_user FILTER html %] to 
+  [%+ product.votes_per_user FILTER html %].
+  [% updated = 1 %]
 [% END %]
 
-[% IF updated_maxvotesperbug %]
+[% IF product.max_votes_per_bug != old_product.max_votes_per_bug %]
   <p>
   Updated maximum votes per [% terms.bug %] from 
-  [%+ old_maxvotesperbug FILTER html %] to 
-  [%+ new_maxvotesperbug FILTER html %].
+  [%+ old_product.max_votes_per_bug FILTER html %] to 
+  [%+ product.max_votes_per_bug FILTER html %].
+  [% updated = 1 %]
 [% END %]
 
-[% IF updated_votestoconfirm %]
+[% IF product.votes_to_confirm != old_product.votes_to_confirm %]
   <p>
   Updated number of votes needed to confirm a [% terms.bug %] from
-  [%+ old_votestoconfirm FILTER html %] to 
-  [%+ new_votestoconfirm FILTER html %].
+  [%+ old_product.votes_to_confirm FILTER html %] to 
+  [%+ product.votes_to_confirm FILTER html %].
+  [% updated = 1 %]
 [% END %]
 
-[% UNLESS updated_bugsubmitstatus ||
-          updated_description || 
-          updated_milestoneurl ||
-          updated_votesperuser ||
-          updated_maxvotesperbug ||
-          updated_votestoconfirm ||
-          updated_defaultmilestone ||
-          updated_product %]
-  <p>Nothing changed for product '[% name FILTER html %]'.
+[% UNLESS updated %]
+  <p>Nothing changed for product '[% product.name FILTER html %]'.
 [% END %]
 
 [%# Note that this display of changed votes and/or confirmed bugs is
index e0a811a48a950a4127cf957d1a9e3d1451f99aac..eb0368c0ce94e318151a9a942bc1a3a5ff6d2822 100644 (file)
 ],
 
 'admin/products/groupcontrol/edit.html.tmpl' => [
-  'filt_classification', 
-  'filt_product', 
   'group.bugcount', 
   'group.id', 
   'const.CONTROLMAPNA', 
 
 'admin/products/confirm-delete.html.tmpl' => [
   'classification_url_part', 
-  'bug_count', 
 ],
 
 'admin/products/footer.html.tmpl' => [