pjs/webtools/bugzilla/Bugzilla/Version.pm

283 строки
6.9 KiB
Perl

# -*- 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 <timello@async.com.br>
use strict;
package Bugzilla::Version;
use Bugzilla::Util;
use Bugzilla::Error;
################################
##### Initialization #####
################################
use constant DEFAULT_VERSION => 'unspecified';
use constant DB_COLUMNS => qw(
versions.value
versions.product_id
);
our $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 ($product_id, $value) = (@_);
my $dbh = Bugzilla->dbh;
my $version;
if (defined $product_id
&& detaint_natural($product_id)
&& defined $value) {
trick_taint($value);
$version = $dbh->selectrow_hashref(qq{
SELECT $columns FROM versions
WHERE value = ?
AND product_id = ?}, undef, ($value, $product_id));
} else {
ThrowCodeError('bad_arg',
{argument => 'product_id/value',
function => 'Bugzilla::Version::_init'});
}
return undef unless (defined $version);
foreach my $field (keys %$version) {
$self->{$field} = $version->{$field};
}
return $self;
}
sub bug_count {
my $self = shift;
my $dbh = Bugzilla->dbh;
if (!defined $self->{'bug_count'}) {
$self->{'bug_count'} = $dbh->selectrow_array(qq{
SELECT COUNT(*) FROM bugs
WHERE product_id = ? AND version = ?}, undef,
($self->product_id, $self->name)) || 0;
}
return $self->{'bug_count'};
}
sub remove_from_db {
my $self = shift;
my $dbh = Bugzilla->dbh;
# The version cannot be removed if there are bugs
# associated with it.
if ($self->bug_count) {
ThrowUserError("version_has_bugs", { nb => $self->bug_count });
}
$dbh->do(q{DELETE FROM versions WHERE product_id = ? AND value = ?},
undef, ($self->product_id, $self->name));
}
sub update {
my $self = shift;
my ($name, $product) = @_;
my $dbh = Bugzilla->dbh;
$name || ThrowUserError('version_not_specified');
# Remove unprintable characters
$name = clean_text($name);
return 0 if ($name eq $self->name);
my $version = new Bugzilla::Version($self->product_id, $name);
if ($version) {
ThrowUserError('version_already_exists',
{'name' => $version->name,
'product' => $product->name});
}
trick_taint($name);
$dbh->do("UPDATE bugs SET version = ?
WHERE version = ? AND product_id = ?", undef,
($name, $self->name, $self->product_id));
$dbh->do("UPDATE versions SET value = ?
WHERE product_id = ? AND value = ?", undef,
($name, $self->product_id, $self->name));
$self->{'value'} = $name;
return 1;
}
###############################
##### Accessors ####
###############################
sub name { return $_[0]->{'value'}; }
sub product_id { return $_[0]->{'product_id'}; }
###############################
##### Subroutines ###
###############################
sub check_version {
my ($product, $version_name) = @_;
$version_name || ThrowUserError('version_not_specified');
my $version = new Bugzilla::Version($product->id, $version_name);
unless ($version) {
ThrowUserError('version_not_valid',
{'product' => $product->name,
'version' => $version_name});
}
return $version;
}
sub create {
my ($name, $product) = @_;
my $dbh = Bugzilla->dbh;
# Cleanups and validity checks
$name || ThrowUserError('version_blank_name');
# Remove unprintable characters
$name = clean_text($name);
my $version = new Bugzilla::Version($product->id, $name);
if ($version) {
ThrowUserError('version_already_exists',
{'name' => $version->name,
'product' => $product->name});
}
# Add the new version
trick_taint($name);
$dbh->do(q{INSERT INTO versions (value, product_id)
VALUES (?, ?)}, undef, ($name, $product->id));
$version = new Bugzilla::Version($product->id, $name);
return $version;
}
1;
__END__
=head1 NAME
Bugzilla::Version - Bugzilla product version class.
=head1 SYNOPSIS
use Bugzilla::Version;
my $version = new Bugzilla::Version(1, 'version_value');
my $product_id = $version->product_id;
my $value = $version->value;
$version->remove_from_db;
my $updated = $version->update($version_name, $product);
my $version = $hash_ref->{'version_value'};
my $version = Bugzilla::Version::check_version($product_obj,
'acme_version');
my $version = Bugzilla::Version::create($version_name, $product);
=head1 DESCRIPTION
Version.pm represents a Product Version object.
=head1 METHODS
=over
=item C<new($product_id, $value)>
Description: The constructor is used to load an existing version
by passing a product id and a version value.
Params: $product_id - Integer with a product id.
$value - String with a version value.
Returns: A Bugzilla::Version object.
=item C<bug_count()>
Description: Returns the total of bugs that belong to the version.
Params: none.
Returns: Integer with the number of bugs.
=item C<remove_from_db()>
Description: Removes the version from the database.
Params: none.
Retruns: none.
=item C<update($name, $product)>
Description: Update the value of the version.
Params: $name - String with the new version value.
$product - Bugzilla::Product object the version belongs to.
Returns: An integer - 1 if the version has been updated, else 0.
=back
=head1 SUBROUTINES
=over
=item C<check_version($product, $version_name)>
Description: Checks if the version name exists for the product name.
Params: $product - A Bugzilla::Product object.
$version_name - String with a version name.
Returns: Bugzilla::Version object.
=item C<create($version_name, $product)>
Description: Create a new version for the given product.
Params: $version_name - String with a version value.
$product - A Bugzilla::Product object.
Returns: A Bugzilla::Version object.
=back
=cut