Version.pm 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. # -*- Mode: perl; indent-tabs-mode: nil -*-
  2. #
  3. # The contents of this file are subject to the Mozilla Public
  4. # License Version 1.1 (the "License"); you may not use this file
  5. # except in compliance with the License. You may obtain a copy of
  6. # the License at http://www.mozilla.org/MPL/
  7. #
  8. # Software distributed under the License is distributed on an "AS
  9. # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10. # implied. See the License for the specific language governing
  11. # rights and limitations under the License.
  12. #
  13. # The Original Code is the Bugzilla Bug Tracking System.
  14. #
  15. # Contributor(s): Tiago R. Mello <timello@async.com.br>
  16. # Max Kanat-Alexander <mkanat@bugzilla.org>
  17. use strict;
  18. package Bugzilla::Version;
  19. use base qw(Bugzilla::Object);
  20. use Bugzilla::Install::Util qw(vers_cmp);
  21. use Bugzilla::Util;
  22. use Bugzilla::Error;
  23. ################################
  24. ##### Initialization #####
  25. ################################
  26. use constant DEFAULT_VERSION => 'unspecified';
  27. use constant DB_TABLE => 'versions';
  28. use constant DB_COLUMNS => qw(
  29. id
  30. value
  31. product_id
  32. );
  33. use constant NAME_FIELD => 'value';
  34. # This is "id" because it has to be filled in and id is probably the fastest.
  35. # We do a custom sort in new_from_list below.
  36. use constant LIST_ORDER => 'id';
  37. sub new {
  38. my $class = shift;
  39. my $param = shift;
  40. my $dbh = Bugzilla->dbh;
  41. my $product;
  42. if (ref $param) {
  43. $product = $param->{product};
  44. my $name = $param->{name};
  45. if (!defined $product) {
  46. ThrowCodeError('bad_arg',
  47. {argument => 'product',
  48. function => "${class}::new"});
  49. }
  50. if (!defined $name) {
  51. ThrowCodeError('bad_arg',
  52. {argument => 'name',
  53. function => "${class}::new"});
  54. }
  55. my $condition = 'product_id = ? AND value = ?';
  56. my @values = ($product->id, $name);
  57. $param = { condition => $condition, values => \@values };
  58. }
  59. unshift @_, $param;
  60. return $class->SUPER::new(@_);
  61. }
  62. sub new_from_list {
  63. my $self = shift;
  64. my $list = $self->SUPER::new_from_list(@_);
  65. return [sort { vers_cmp(lc($a->name), lc($b->name)) } @$list];
  66. }
  67. sub bug_count {
  68. my $self = shift;
  69. my $dbh = Bugzilla->dbh;
  70. if (!defined $self->{'bug_count'}) {
  71. $self->{'bug_count'} = $dbh->selectrow_array(qq{
  72. SELECT COUNT(*) FROM bugs
  73. WHERE product_id = ? AND version = ?}, undef,
  74. ($self->product_id, $self->name)) || 0;
  75. }
  76. return $self->{'bug_count'};
  77. }
  78. sub remove_from_db {
  79. my $self = shift;
  80. my $dbh = Bugzilla->dbh;
  81. # The version cannot be removed if there are bugs
  82. # associated with it.
  83. if ($self->bug_count) {
  84. ThrowUserError("version_has_bugs", { nb => $self->bug_count });
  85. }
  86. $dbh->do(q{DELETE FROM versions WHERE product_id = ? AND value = ?},
  87. undef, ($self->product_id, $self->name));
  88. }
  89. sub update {
  90. my $self = shift;
  91. my ($name, $product) = @_;
  92. my $dbh = Bugzilla->dbh;
  93. $name || ThrowUserError('version_not_specified');
  94. # Remove unprintable characters
  95. $name = clean_text($name);
  96. return 0 if ($name eq $self->name);
  97. my $version = new Bugzilla::Version({ product => $product, name => $name });
  98. if ($version) {
  99. ThrowUserError('version_already_exists',
  100. {'name' => $version->name,
  101. 'product' => $product->name});
  102. }
  103. trick_taint($name);
  104. $dbh->do("UPDATE bugs SET version = ?
  105. WHERE version = ? AND product_id = ?", undef,
  106. ($name, $self->name, $self->product_id));
  107. $dbh->do("UPDATE versions SET value = ?
  108. WHERE product_id = ? AND value = ?", undef,
  109. ($name, $self->product_id, $self->name));
  110. $self->{'value'} = $name;
  111. return 1;
  112. }
  113. ###############################
  114. ##### Accessors ####
  115. ###############################
  116. sub name { return $_[0]->{'value'}; }
  117. sub product_id { return $_[0]->{'product_id'}; }
  118. ###############################
  119. ##### Subroutines ###
  120. ###############################
  121. sub create {
  122. my ($name, $product) = @_;
  123. my $dbh = Bugzilla->dbh;
  124. # Cleanups and validity checks
  125. $name || ThrowUserError('version_blank_name');
  126. # Remove unprintable characters
  127. $name = clean_text($name);
  128. my $version = new Bugzilla::Version({ product => $product, name => $name });
  129. if ($version) {
  130. ThrowUserError('version_already_exists',
  131. {'name' => $version->name,
  132. 'product' => $product->name});
  133. }
  134. # Add the new version
  135. trick_taint($name);
  136. $dbh->do(q{INSERT INTO versions (value, product_id)
  137. VALUES (?, ?)}, undef, ($name, $product->id));
  138. return new Bugzilla::Version($dbh->bz_last_key('versions', 'id'));
  139. }
  140. 1;
  141. __END__
  142. =head1 NAME
  143. Bugzilla::Version - Bugzilla product version class.
  144. =head1 SYNOPSIS
  145. use Bugzilla::Version;
  146. my $version = new Bugzilla::Version(1, 'version_value');
  147. my $product_id = $version->product_id;
  148. my $value = $version->value;
  149. $version->remove_from_db;
  150. my $updated = $version->update($version_name, $product);
  151. my $version = $hash_ref->{'version_value'};
  152. my $version = Bugzilla::Version::create($version_name, $product);
  153. =head1 DESCRIPTION
  154. Version.pm represents a Product Version object.
  155. =head1 METHODS
  156. =over
  157. =item C<new($product_id, $value)>
  158. Description: The constructor is used to load an existing version
  159. by passing a product id and a version value.
  160. Params: $product_id - Integer with a product id.
  161. $value - String with a version value.
  162. Returns: A Bugzilla::Version object.
  163. =item C<bug_count()>
  164. Description: Returns the total of bugs that belong to the version.
  165. Params: none.
  166. Returns: Integer with the number of bugs.
  167. =item C<remove_from_db()>
  168. Description: Removes the version from the database.
  169. Params: none.
  170. Retruns: none.
  171. =item C<update($name, $product)>
  172. Description: Update the value of the version.
  173. Params: $name - String with the new version value.
  174. $product - Bugzilla::Product object the version belongs to.
  175. Returns: An integer - 1 if the version has been updated, else 0.
  176. =back
  177. =head1 SUBROUTINES
  178. =over
  179. =item C<create($version_name, $product)>
  180. Description: Create a new version for the given product.
  181. Params: $version_name - String with a version value.
  182. $product - A Bugzilla::Product object.
  183. Returns: A Bugzilla::Version object.
  184. =back
  185. =cut