diff options
Diffstat (limited to 'Bugzilla/Classification.pm')
-rw-r--r-- | Bugzilla/Classification.pm | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/Bugzilla/Classification.pm b/Bugzilla/Classification.pm new file mode 100644 index 0000000..2b35a88 --- /dev/null +++ b/Bugzilla/Classification.pm @@ -0,0 +1,261 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +use strict; + +package Bugzilla::Classification; + +use Bugzilla::Constants; +use Bugzilla::Field; +use Bugzilla::Util; +use Bugzilla::Error; +use Bugzilla::Product; + +use base qw(Bugzilla::Field::ChoiceInterface Bugzilla::Object Exporter); +@Bugzilla::Classification::EXPORT = qw(sort_products_by_classification); + +############################### +#### Initialization #### +############################### + +use constant DB_TABLE => 'classifications'; +use constant LIST_ORDER => 'sortkey, name'; + +use constant DB_COLUMNS => qw( + id + name + description + sortkey +); + +use constant UPDATE_COLUMNS => qw( + name + description + sortkey +); + +use constant VALIDATORS => { + name => \&_check_name, + description => \&_check_description, + sortkey => \&_check_sortkey, +}; + +############################### +#### Constructors ##### +############################### +sub remove_from_db { + my $self = shift; + my $dbh = Bugzilla->dbh; + + ThrowUserError("classification_not_deletable") if ($self->id == 1); + + $dbh->bz_start_transaction(); + # Reclassify products to the default classification, if needed. + $dbh->do("UPDATE products SET classification_id = 1 + WHERE classification_id = ?", undef, $self->id); + + $self->SUPER::remove_from_db(); + + $dbh->bz_commit_transaction(); + +} + +############################### +#### Validators #### +############################### + +sub _check_name { + my ($invocant, $name) = @_; + + $name = trim($name); + $name || ThrowUserError('classification_not_specified'); + + if (length($name) > MAX_CLASSIFICATION_SIZE) { + ThrowUserError('classification_name_too_long', {'name' => $name}); + } + + my $classification = new Bugzilla::Classification({name => $name}); + if ($classification && (!ref $invocant || $classification->id != $invocant->id)) { + ThrowUserError("classification_already_exists", { name => $classification->name }); + } + return $name; +} + +sub _check_description { + my ($invocant, $description) = @_; + + $description = trim($description || ''); + return $description; +} + +sub _check_sortkey { + my ($invocant, $sortkey) = @_; + + $sortkey ||= 0; + my $stored_sortkey = $sortkey; + if (!detaint_natural($sortkey) || $sortkey > MAX_SMALLINT) { + ThrowUserError('classification_invalid_sortkey', { 'sortkey' => $stored_sortkey }); + } + return $sortkey; +} + +##################################### +# Implement Bugzilla::Field::Choice # +##################################### + +use constant FIELD_NAME => 'classification'; +use constant is_default => 0; +use constant is_active => 1; + +############################### +#### Methods #### +############################### + +sub set_name { $_[0]->set('name', $_[1]); } +sub set_description { $_[0]->set('description', $_[1]); } +sub set_sortkey { $_[0]->set('sortkey', $_[1]); } + +sub product_count { + my $self = shift; + my $dbh = Bugzilla->dbh; + + if (!defined $self->{'product_count'}) { + $self->{'product_count'} = $dbh->selectrow_array(q{ + SELECT COUNT(*) FROM products + WHERE classification_id = ?}, undef, $self->id) || 0; + } + return $self->{'product_count'}; +} + +sub products { + my $self = shift; + my $dbh = Bugzilla->dbh; + + if (!$self->{'products'}) { + my $product_ids = $dbh->selectcol_arrayref(q{ + SELECT id FROM products + WHERE classification_id = ? + ORDER BY name}, undef, $self->id); + + $self->{'products'} = Bugzilla::Product->new_from_list($product_ids); + } + return $self->{'products'}; +} + +############################### +#### Accessors #### +############################### + +sub description { return $_[0]->{'description'}; } +sub sortkey { return $_[0]->{'sortkey'}; } + + +############################### +#### Helpers #### +############################### + +# This function is a helper to sort products to be listed +# in global/choose-product.html.tmpl. + +sub sort_products_by_classification { + my $products = shift; + my $list; + + if (Bugzilla->params->{'useclassification'}) { + my $class = {}; + # Get all classifications with at least one product. + foreach my $product (@$products) { + $class->{$product->classification_id}->{'object'} ||= + new Bugzilla::Classification($product->classification_id); + # Nice way to group products per classification, without querying + # the DB again. + push(@{$class->{$product->classification_id}->{'products'}}, $product); + } + $list = [sort {$a->{'object'}->sortkey <=> $b->{'object'}->sortkey + || lc($a->{'object'}->name) cmp lc($b->{'object'}->name)} + (values %$class)]; + } + else { + $list = [{object => undef, products => $products}]; + } + return $list; +} + +1; + +__END__ + +=head1 NAME + +Bugzilla::Classification - Bugzilla classification class. + +=head1 SYNOPSIS + + use Bugzilla::Classification; + + my $classification = new Bugzilla::Classification(1); + my $classification = new Bugzilla::Classification({name => 'Acme'}); + + my $id = $classification->id; + my $name = $classification->name; + my $description = $classification->description; + my $sortkey = $classification->sortkey; + my $product_count = $classification->product_count; + my $products = $classification->products; + +=head1 DESCRIPTION + +Classification.pm represents a classification object. It is an +implementation of L<Bugzilla::Object>, and thus provides all methods +that L<Bugzilla::Object> provides. + +The methods that are specific to C<Bugzilla::Classification> are listed +below. + +A Classification is a higher-level grouping of Products. + +=head1 METHODS + +=over + +=item C<product_count()> + + Description: Returns the total number of products that belong to + the classification. + + Params: none. + + Returns: Integer - The total of products inside the classification. + +=item C<products> + + Description: Returns all products of the classification. + + Params: none. + + Returns: A reference to an array of Bugzilla::Product objects. + +=back + +=head1 SUBROUTINES + +=over + +=item C<sort_products_by_classification> + + Description: This is a helper which returns a list of products sorted + by classification in a form suitable to be passed to the + global/choose-product.html.tmpl template. + + Params: An arrayref of product objects. + + Returns: An arrayref of hashes suitable to be passed to + global/choose-product.html.tmpl. + +=back + +=cut |