# -*- Mode: perl; indent-tabs-mode: nil -*- # # The contents of this file are subject to the Mozilla Public # License Version 1.1 (the "License"); you may not use this file # except in compliance with the License. You may obtain a copy of # the License at http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or # implied. See the License for the specific language governing # rights and limitations under the License. # # The Original Code is the Bugzilla Bug Tracking System. # # Contributor(s): Tiago R. Mello use strict; package Bugzilla::Product; use Bugzilla::Component; use Bugzilla::Version; use Bugzilla::Milestone; use Bugzilla::Util; use Bugzilla::Group; use Bugzilla::Error; use constant DEFAULT_CLASSIFICATION_ID => 1; ############################### #### Initialization #### ############################### use constant DB_COLUMNS => qw( products.id products.name products.classification_id products.description products.milestoneurl products.disallownew products.votesperuser products.maxvotesperbug products.votestoconfirm products.defaultmilestone ); my $columns = join(", ", DB_COLUMNS); 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 $dbh = Bugzilla->dbh; my $id = $param unless (ref $param eq 'HASH'); my $product; if (defined $id) { detaint_natural($id) || ThrowCodeError('param_must_be_numeric', {function => 'Bugzilla::Product::_init'}); $product = $dbh->selectrow_hashref(qq{ SELECT $columns FROM products WHERE id = ?}, undef, $id); } elsif (defined $param->{'name'}) { trick_taint($param->{'name'}); $product = $dbh->selectrow_hashref(qq{ SELECT $columns FROM products WHERE name = ?}, undef, $param->{'name'}); } else { ThrowCodeError('bad_arg', {argument => 'param', function => 'Bugzilla::Product::_init'}); } return undef unless (defined $product); foreach my $field (keys %$product) { $self->{$field} = $product->{$field}; } return $self; } ############################### #### Methods #### ############################### sub components { my $self = shift; my $dbh = Bugzilla->dbh; if (!defined $self->{components}) { my $ids = $dbh->selectcol_arrayref(q{ SELECT id FROM components WHERE product_id = ? ORDER BY name}, undef, $self->id); my @components; foreach my $id (@$ids) { push @components, new Bugzilla::Component($id); } $self->{components} = \@components; } return $self->{components}; } sub group_controls { my $self = shift; my $dbh = Bugzilla->dbh; if (!defined $self->{group_controls}) { my $query = qq{SELECT groups.id, group_control_map.entry, group_control_map.membercontrol, group_control_map.othercontrol, group_control_map.canedit FROM groups LEFT 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}; $self->{group_controls} = $dbh->selectall_hashref($query, 'id', undef, $self->id); foreach my $group (keys(%{$self->{group_controls}})) { $self->{group_controls}->{$group}->{'group'} = new Bugzilla::Group($group); } } return $self->{group_controls}; } sub versions { my $self = shift; my $dbh = Bugzilla->dbh; if (!defined $self->{versions}) { my $values = $dbh->selectcol_arrayref(q{ SELECT value FROM versions WHERE product_id = ? ORDER BY value}, undef, $self->id); my @versions; foreach my $value (@$values) { push @versions, new Bugzilla::Version($self->id, $value); } $self->{versions} = \@versions; } return $self->{versions}; } sub milestones { my $self = shift; my $dbh = Bugzilla->dbh; if (!defined $self->{milestones}) { my $values = $dbh->selectcol_arrayref(q{ SELECT value FROM milestones WHERE product_id = ? ORDER BY sortkey}, undef, $self->id); my @milestones; foreach my $value (@$values) { push @milestones, new Bugzilla::Milestone($self->id, $value); } $self->{milestones} = \@milestones; } return $self->{milestones}; } sub bug_count { my $self = shift; my $dbh = Bugzilla->dbh; if (!defined $self->{'bug_count'}) { $self->{'bug_count'} = $dbh->selectrow_array(qq{ SELECT COUNT(bug_id) FROM bugs WHERE product_id = ?}, undef, $self->id); } 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 ###### ############################### sub id { return $_[0]->{'id'}; } sub name { return $_[0]->{'name'}; } sub description { return $_[0]->{'description'}; } sub milestone_url { return $_[0]->{'milestoneurl'}; } sub disallow_new { return $_[0]->{'disallownew'}; } sub votes_per_user { return $_[0]->{'votesperuser'}; } sub max_votes_per_bug { return $_[0]->{'maxvotesperbug'}; } sub votes_to_confirm { return $_[0]->{'votestoconfirm'}; } sub default_milestone { return $_[0]->{'defaultmilestone'}; } sub classification_id { return $_[0]->{'classification_id'}; } ############################### #### Subroutines ###### ############################### sub get_all_products { my $dbh = Bugzilla->dbh; my $ids = $dbh->selectcol_arrayref(q{ SELECT id FROM products ORDER BY name}); my @products; foreach my $id (@$ids) { push @products, new Bugzilla::Product($id); } return @products; } sub check_product { my ($product_name) = @_; unless ($product_name) { ThrowUserError('product_not_specified'); } my $product = new Bugzilla::Product({name => $product_name}); unless ($product) { ThrowUserError('product_doesnt_exist', {'product' => $product_name}); } return $product; } 1; __END__ =head1 NAME Bugzilla::Product - Bugzilla product class. =head1 SYNOPSIS use Bugzilla::Product; my $product = new Bugzilla::Product(1); my $product = new Bugzilla::Product('AcmeProduct'); my @components = $product->components(); my $groups_controls = $product->group_controls(); 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; my $description = $product->description; my $milestoneurl = $product->milestone_url; my disallownew = $product->disallow_new; my votesperuser = $product->votes_per_user; my maxvotesperbug = $product->max_votes_per_bug; my votestoconfirm = $product->votes_to_confirm; my $defaultmilestone = $product->default_milestone; my $classificationid = $product->classification_id; =head1 DESCRIPTION Product.pm represents a product object. =head1 METHODS =over =item C Description: The constructor is used to load an existing product by passing a product id or a hash. Params: $param - If you pass an integer, the integer is the product id from the database that we want to read in. If you pass in a hash with 'name' key, then the value of the name key is the name of a product from the DB. Returns: A Bugzilla::Product object. =item C Description: Returns an array of component objects belonging to the product. Params: none. Returns: An array of Bugzilla::Component object. =item C Description: Returns a hash (group id as key) with all product group controls. Params: none. Returns: A hash with group id as key and hash containing a Bugzilla::Group object and the properties of group relative to the product. =item C Description: Returns all valid versions for that product. Params: none. Returns: An array of Bugzilla::Version objects. =item C Description: Returns all valid milestones for that product. Params: none. Returns: An array of Bugzilla::Milestone objects. =item C Description: Returns the total of bugs that belong to the product. Params: none. Returns: Integer with the number of bugs. =item C Description: Returns the IDs of bugs that belong to the product. Params: none. Returns: An array of integer. =back =head1 SUBROUTINES =over =item C Description: Returns all products from the database. Params: none. Returns: Bugzilla::Product object list. =item C Description: Checks if the product name was passed in and if is a valid product. Params: $product_name - String with a product name. Returns: Bugzilla::Product object. =back =cut