From b7c87a7217ea157c1305526e6d62c94d5ef8d36f Mon Sep 17 00:00:00 2001 From: "mkanat%bugzilla.org" <> Date: Tue, 19 Dec 2006 14:39:28 +0000 Subject: Bug 339380: Make Bugzilla::Component use Bugzilla::Object Patch By Max Kanat-Alexander r=LpSolit, a=myk --- Bugzilla/Component.pm | 92 +++++++++++++++++++++------------------------------ Bugzilla/Object.pm | 87 +++++++++++++++++++++++++++++++++++++----------- Bugzilla/Product.pm | 6 +--- Bugzilla/User.pm | 5 +-- 4 files changed, 108 insertions(+), 82 deletions(-) (limited to 'Bugzilla') diff --git a/Bugzilla/Component.pm b/Bugzilla/Component.pm index 657d0f728..1b2e8f8d2 100644 --- a/Bugzilla/Component.pm +++ b/Bugzilla/Component.pm @@ -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(); diff --git a/Bugzilla/Object.pm b/Bugzilla/Object.pm index a2ca8ff94..30ecc77e2 100644 --- a/Bugzilla/Object.pm +++ b/Bugzilla/Object.pm @@ -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 usually can't be updated.) =item C - Description: The constructor is used to load an existing object - from the database, by id or by name. +=over + +=item B + +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 key, then the value of the name key - is the case-insensitive name of the object from - the DB. +=item B + +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 column). + +If you pass in a hash, you can pass a C key. The +value of the C key is the case-insensitive name of the object +(from L) in the DB. + +B + +If you are a subclass of C, you can pass +C and C as hash keys, instead of the above. + +C is a set of SQL conditions for the WHERE clause, which contain +placeholders. + +C is a reference to an array. The array contains the values +for each placeholder in C, in order. - Returns: A fully-initialized object. +This is to allow subclasses to have complex parameters, and then to +translate those parameters into C and C when they +call C<$self->SUPER::new> (which is this function, usually). + +If you try to call C outside of a subclass with the C +and C parameters, Bugzilla will throw an error. These parameters +are intended B for use by subclasses. + +=item B + +A fully-initialized object. + +=back =item C diff --git a/Bugzilla/Product.pm b/Bugzilla/Product.pm index 4edc7ef85..465d12515 100644 --- a/Bugzilla/Product.pm +++ b/Bugzilla/Product.pm @@ -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}; } diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm index 05b96dd29..a4ff44331 100644 --- a/Bugzilla/User.pm +++ b/Bugzilla/User.pm @@ -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'}; } -- cgit v1.2.3-24-g4f1b