]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 339380: Make Bugzilla::Component use Bugzilla::Object
authormkanat%bugzilla.org <>
Tue, 19 Dec 2006 14:39:28 +0000 (14:39 +0000)
committermkanat%bugzilla.org <>
Tue, 19 Dec 2006 14:39:28 +0000 (14:39 +0000)
Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=LpSolit, a=myk

Bugzilla/Component.pm
Bugzilla/Object.pm
Bugzilla/Product.pm
Bugzilla/User.pm
editcomponents.cgi
importxml.pl
template/en/default/global/code-error.html.tmpl

index 657d0f7287b01011a0fc29b07377cad88af5f598..1b2e8f8d28b6f168df9114b00d807d24385bf0e4 100644 (file)
@@ -21,6 +21,8 @@ use strict;
 
 package Bugzilla::Component;
 
+use base qw(Bugzilla::Object);
+
 use Bugzilla::Util;
 use Bugzilla::Error;
 use Bugzilla::User;
@@ -30,68 +32,50 @@ use Bugzilla::FlagType;
 ####    Initialization     ####
 ###############################
 
+use constant DB_TABLE => 'components';
+
 use constant DB_COLUMNS => qw(
-    components.id
-    components.name
-    components.product_id
-    components.initialowner
-    components.initialqacontact
-    components.description
+    id
+    name
+    product_id
+    initialowner
+    initialqacontact
+    description
 );
 
-our $columns = join(", ", DB_COLUMNS);
-
 ###############################
 ####       Methods         ####
 ###############################
 
 sub new {
-    my $invocant = shift;
-    my $class = ref($invocant) || $invocant;
-    my $self = {};
-    bless($self, $class);
-    return $self->_init(@_);
-}
-
-sub _init {
-    my $self = shift;
-    my ($param) = (@_);
+    my $class = shift;
+    my $param = shift;
     my $dbh = Bugzilla->dbh;
 
-    my $id = $param unless (ref $param eq 'HASH');
-    my $component;
-
-    if (defined $id) {
-        detaint_natural($id)
-          || ThrowCodeError('param_must_be_numeric',
-                            {function => 'Bugzilla::Component::_init'});
-
-        $component = $dbh->selectrow_hashref(qq{
-            SELECT $columns FROM components
-            WHERE id = ?}, undef, $id);
-
-    } elsif (defined $param->{'product_id'}
-        && detaint_natural($param->{'product_id'})
-        && defined $param->{'name'}) {
-
-        trick_taint($param->{'name'});
-
-        $component = $dbh->selectrow_hashref(qq{
-            SELECT $columns FROM components
-            WHERE name = ? AND product_id = ?}, undef,
-            ($param->{'name'}, $param->{'product_id'}));
-    } else {
-        ThrowCodeError('bad_arg',
-            {argument => 'param',
-             function => 'Bugzilla::Component::_init'});
+    my $product;
+    if (ref $param) {
+        $product = $param->{product};
+        my $name = $param->{name};
+        if (!defined $product) {
+            ThrowCodeError('bad_arg',
+                {argument => 'product',
+                 function => "${class}::new"});
+        }
+        if (!defined $name) {
+            ThrowCodeError('bad_arg',
+                {argument => 'name',
+                 function => "${class}::new"});
+        }
+
+        my $condition = 'product_id = ? AND name = ?';
+        my @values = ($product->id, $name);
+        $param = { condition => $condition, values => \@values };
     }
 
-    return undef unless (defined $component);
-
-    foreach my $field (keys %$component) {
-        $self->{$field} = $component->{$field};
-    }
-    return $self;
+    unshift @_, $param;
+    my $component = $class->SUPER::new(@_);
+    $component->{product} = $product if $product;
+    return $component;
 }
 
 sub bug_count {
@@ -204,8 +188,8 @@ sub check_component {
     }
 
     my $component =
-        new Bugzilla::Component({product_id => $product->id,
-                                 name       => $comp_name});
+        new Bugzilla::Component({product => $product,
+                                 name    => $comp_name});
     unless ($component) {
         ThrowUserError('component_not_valid',
                        {'product' => $product->name,
@@ -227,8 +211,8 @@ Bugzilla::Component - Bugzilla product component class.
     use Bugzilla::Component;
 
     my $component = new Bugzilla::Component(1);
-    my $component = new Bugzilla::Component({product_id => 1,
-                                             name       => 'AcmeComp'});
+    my $component = new Bugzilla::Component({product => $product,
+                                             name    => 'AcmeComp'});
 
     my $bug_count          = $component->bug_count();
     my $bug_ids            = $component->bug_ids();
index a2ca8ff94234cdcdc9dac64b0c6639cc6b664ceb..30ecc77e23460108182233452b3e66026bde0471 100644 (file)
@@ -60,6 +60,8 @@ sub _init {
     my $object;
 
     if (defined $id) {
+        # We special-case if somebody specifies an ID, so that we can
+        # validate it as numeric.
         detaint_natural($id)
           || ThrowCodeError('param_must_be_numeric',
                             {function => $class . '::_init'});
@@ -67,23 +69,40 @@ sub _init {
         $object = $dbh->selectrow_hashref(qq{
             SELECT $columns FROM $table
              WHERE $id_field = ?}, undef, $id);
-    } elsif (defined $param->{'name'}) {
-        trick_taint($param->{'name'});
-        $object = $dbh->selectrow_hashref(qq{
-            SELECT $columns FROM $table
-             WHERE } . $dbh->sql_istrcmp($name_field, '?'), 
-            undef, $param->{'name'});
     } else {
-        ThrowCodeError('bad_arg',
-            {argument => 'param',
-             function => $class . '::_init'});
+        unless (defined $param->{name} || (defined $param->{'condition'} 
+                                           && defined $param->{'values'}))
+        {
+            ThrowCodeError('bad_arg', { argument => 'param',
+                                        function => $class . '::new' });
+        }
+
+        my ($condition, @values);
+        if (defined $param->{name}) {
+            $condition = $dbh->sql_istrcmp($name_field, '?');
+            push(@values, $param->{name});
+        }
+        elsif (defined $param->{'condition'} && defined $param->{'values'}) {
+            caller->isa('Bugzilla::Object')
+                || ThrowCodeError('protection_violation',
+                       { caller    => caller, 
+                         function  => $class . '::new',
+                         argument  => 'condition/values' });
+            $condition = $param->{'condition'};
+            push(@values, @{$param->{'values'}});
+        }
+
+        map { trick_taint($_) } @values;
+        $object = $dbh->selectrow_hashref(
+            "SELECT $columns FROM $table WHERE $condition", undef, @values);
     }
 
     return $object;
 }
 
 sub new_from_list {
-    my $class = shift;
+    my $invocant = shift;
+    my $class = ref($invocant) || $invocant;
     my ($id_list) = @_;
     my $dbh = Bugzilla->dbh;
     my $columns = join(',', $class->DB_COLUMNS);
@@ -363,17 +382,47 @@ the L</ID_FIELD> usually can't be updated.)
 
 =item C<new($param)>
 
- Description: The constructor is used to load an existing object
-              from the database, by id or by name.
+=over
+
+=item B<Description>
+
+The constructor is used to load an existing object from the database,
+by id or by name.
 
- Params:      $param - If you pass an integer, the integer is the
-                       id of the object, from the database, that we 
-                       want to read in. If you pass in a hash with 
-                       C<name> key, then the value of the name key 
-                       is the case-insensitive name of the object from 
-                       the DB.
+=item B<Params>
+
+If you pass an integer, the integer is the id of the object, 
+from the database, that we  want to read in. (id is defined
+as the value in the L</ID_FIELD> column).
+
+If you pass in a hash, you can pass a C<name> key. The 
+value of the C<name> key is the case-insensitive name of the object 
+(from L</NAME_FIELD>) in the DB.
+
+B<Additional Parameters Available for Subclasses>
+
+If you are a subclass of C<Bugzilla::Object>, you can pass
+C<condition> and C<values> as hash keys, instead of the above.
+
+C<condition> is a set of SQL conditions for the WHERE clause, which contain
+placeholders.
+
+C<values> is a reference to an array. The array contains the values
+for each placeholder in C<condition>, in order.
 
- Returns:     A fully-initialized object.
+This is to allow subclasses to have complex parameters, and then to
+translate those parameters into C<condition> and C<values> when they
+call C<$self->SUPER::new> (which is this function, usually).
+
+If you try to call C<new> outside of a subclass with the C<condition>
+and C<values> parameters, Bugzilla will throw an error. These parameters
+are intended B<only> for use by subclasses.
+
+=item B<Returns>
+
+A fully-initialized object.
+
+=back
 
 =item C<new_from_list(\@id_list)>
 
index 4edc7ef8575f3a64b322eded93390e6a376a57d1..465d12515b02c01c9a235d0970e4f488ed8df6cc 100644 (file)
@@ -65,12 +65,8 @@ sub components {
             WHERE product_id = ?
             ORDER BY name}, undef, $self->id);
 
-        my @components;
         require Bugzilla::Component;
-        foreach my $id (@$ids) {
-            push @components, new Bugzilla::Component($id);
-        }
-        $self->{components} = \@components;
+        $self->{components} = Bugzilla::Component->new_from_list($ids);
     }
     return $self->{components};
 }
index 05b96dd29f376177279f772b27b644d9c1fa0aa2..a4ff44331e34aafc8043bde6911cb18097e37a36 100644 (file)
@@ -931,10 +931,7 @@ sub product_responsibilities {
 
     # We cannot |use| it, because Component.pm already |use|s User.pm.
     require Bugzilla::Component;
-    my @components;
-    push(@components, new Bugzilla::Component($_)) foreach (@$comp_ids);
-
-    $self->{'product_resp'} = \@components;
+    $self->{'product_resp'} = Bugzilla::Component->new_from_list($comp_ids);
     return $self->{'product_resp'};
 }
 
index 17ad290c52574e625c2883434524eafc95fe227f..f28a87b7a8ba66dd3b4c37b366ba6474ecadff04 100755 (executable)
@@ -168,7 +168,7 @@ if ($action eq 'new') {
     }
 
     my $component =
-        new Bugzilla::Component({product_id => $product->id,
+        new Bugzilla::Component({product => $product,
                                  name => $comp_name});
 
     if ($component) {
@@ -200,7 +200,7 @@ if ($action eq 'new') {
              ($product->id, $comp_name, $description,
               $default_assignee_id, $default_qa_contact_id));
 
-    $component = new Bugzilla::Component({ product_id => $product->id,
+    $component = new Bugzilla::Component({ product => $product,
                                            name => $comp_name });
 
     my $sth = $dbh->prepare("INSERT INTO component_cc 
@@ -383,7 +383,7 @@ if ($action eq 'update') {
 
     if ($comp_name ne $component_old->name) {
         my $component =
-            new Bugzilla::Component({product_id => $product->id,
+            new Bugzilla::Component({product => $product,
                                      name => $comp_name});
         if ($component) {
             ThrowUserError('component_already_exists',
index b637f98fd69ad4c9fb436cb9571a061bf33b4a13..989eb31e0d7a7c9b184835ff511f9e186aeb0986 100755 (executable)
@@ -326,8 +326,8 @@ sub init() {
                   moved-default-product. \n", "REOPEN", $exporter);
     my $def_component = new Bugzilla::Component(
         {
-            product_id => $def_product->id,
-            name       => $params->{"moved-default-component"}
+            product => $def_product,
+            name    => $params->{"moved-default-component"}
         })
     || Error("Cannot import these bugs because an invalid default 
               component was defined for the target db."
@@ -622,8 +622,8 @@ sub process_bug {
       new Bugzilla::Product( { name => $params->{"moved-default-product"} } );
     my $def_component = new Bugzilla::Component(
         {
-            product_id => $def_product->id,
-            name       => $params->{"moved-default-component"}
+            product => $def_product,
+            name    => $params->{"moved-default-component"}
         }
     );
     my $product;
@@ -643,8 +643,8 @@ sub process_bug {
     if ( defined $bug_fields{'component'} ) {
         $component = new Bugzilla::Component(
             {
-                product_id => $product->id,
-                name       => $bug_fields{'component'}
+                product => $product,
+                name    => $bug_fields{'component'}
             }
         );
         unless ($component) {
index a0e9bd9b9286717a5e03f33c240ccbd952e826da..d48b89993e4ac9fa531da9f07008b0edf78d0bdb 100644 (file)
 
   [% ELSIF error == "protection_violation" %]
     The function <code>[% function FILTER html %]</code> was called
+
+    [% IF argument %]
+        with the argument <code>[% argument FILTER html %]</code>
+    [% END %]
+
     from
    
     [% IF caller %]