diff options
Diffstat (limited to 'Bugzilla/Series.pm')
-rw-r--r-- | Bugzilla/Series.pm | 421 |
1 files changed, 226 insertions, 195 deletions
diff --git a/Bugzilla/Series.pm b/Bugzilla/Series.pm index 22202c6f1..ec0a16e34 100644 --- a/Bugzilla/Series.pm +++ b/Bugzilla/Series.pm @@ -7,9 +7,9 @@ # This module implements a series - a set of data to be plotted on a chart. # -# This Series is in the database if and only if self->{'series_id'} is defined. -# Note that the series being in the database does not mean that the fields of -# this object are the same as the DB entries, as the object may have been +# This Series is in the database if and only if self->{'series_id'} is defined. +# Note that the series being in the database does not mean that the fields of +# this object are the same as the DB entries, as the object may have been # altered. package Bugzilla::Series; @@ -27,224 +27,255 @@ use constant DB_TABLE => 'series'; use constant ID_FIELD => 'series_id'; sub new { - my $invocant = shift; - my $class = ref($invocant) || $invocant; - - # Create a ref to an empty hash and bless it - my $self = {}; - bless($self, $class); - - my $arg_count = scalar(@_); - - # new() can return undef if you pass in a series_id and the user doesn't - # have sufficient permissions. If you create a new series in this way, - # you need to check for an undef return, and act appropriately. - my $retval = $self; - - # There are three ways of creating Series objects. Two (CGI and Parameters) - # are for use when creating a new series. One (Database) is for retrieving - # information on existing series. - if ($arg_count == 1) { - if (ref($_[0])) { - # We've been given a CGI object to create a new Series from. - # This series may already exist - external code needs to check - # before it calls writeToDatabase(). - $self->initFromCGI($_[0]); - } - else { - # We've been given a series_id, which should represent an existing - # Series. - $retval = $self->initFromDatabase($_[0]); - } - } - elsif ($arg_count >= 6 && $arg_count <= 8) { - # We've been given a load of parameters to create a new Series from. - # Currently, undef is always passed as the first parameter; this allows - # you to call writeToDatabase() unconditionally. - # XXX - You cannot set category_id and subcategory_id from here. - $self->initFromParameters(@_); + my $invocant = shift; + my $class = ref($invocant) || $invocant; + + # Create a ref to an empty hash and bless it + my $self = {}; + bless($self, $class); + + my $arg_count = scalar(@_); + + # new() can return undef if you pass in a series_id and the user doesn't + # have sufficient permissions. If you create a new series in this way, + # you need to check for an undef return, and act appropriately. + my $retval = $self; + + # There are three ways of creating Series objects. Two (CGI and Parameters) + # are for use when creating a new series. One (Database) is for retrieving + # information on existing series. + if ($arg_count == 1) { + if (ref($_[0])) { + + # We've been given a CGI object to create a new Series from. + # This series may already exist - external code needs to check + # before it calls writeToDatabase(). + $self->initFromCGI($_[0]); } else { - die("Bad parameters passed in - invalid number of args: $arg_count"); + # We've been given a series_id, which should represent an existing + # Series. + $retval = $self->initFromDatabase($_[0]); } - - return $retval; + } + elsif ($arg_count >= 6 && $arg_count <= 8) { + + # We've been given a load of parameters to create a new Series from. + # Currently, undef is always passed as the first parameter; this allows + # you to call writeToDatabase() unconditionally. + # XXX - You cannot set category_id and subcategory_id from here. + $self->initFromParameters(@_); + } + else { + die("Bad parameters passed in - invalid number of args: $arg_count"); + } + + return $retval; } sub initFromDatabase { - my ($self, $series_id) = @_; - my $dbh = Bugzilla->dbh; - my $user = Bugzilla->user; - - detaint_natural($series_id) - || ThrowCodeError("invalid_series_id", { 'series_id' => $series_id }); - - my $grouplist = $user->groups_as_string; - - my @series = $dbh->selectrow_array("SELECT series.series_id, cc1.name, " . - "cc2.name, series.name, series.creator, series.frequency, " . - "series.query, series.is_public, series.category, series.subcategory " . - "FROM series " . - "INNER JOIN series_categories AS cc1 " . - " ON series.category = cc1.id " . - "INNER JOIN series_categories AS cc2 " . - " ON series.subcategory = cc2.id " . - "LEFT JOIN category_group_map AS cgm " . - " ON series.category = cgm.category_id " . - " AND cgm.group_id NOT IN($grouplist) " . - "WHERE series.series_id = ? " . - " AND (creator = ? OR (is_public = 1 AND cgm.category_id IS NULL))", - undef, ($series_id, $user->id)); - - if (@series) { - $self->initFromParameters(@series); - return $self; - } - else { - return undef; - } + my ($self, $series_id) = @_; + my $dbh = Bugzilla->dbh; + my $user = Bugzilla->user; + + detaint_natural($series_id) + || ThrowCodeError("invalid_series_id", {'series_id' => $series_id}); + + my $grouplist = $user->groups_as_string; + + my @series = $dbh->selectrow_array( + "SELECT series.series_id, cc1.name, " + . "cc2.name, series.name, series.creator, series.frequency, " + . "series.query, series.is_public, series.category, series.subcategory " + . "FROM series " + . "INNER JOIN series_categories AS cc1 " + . " ON series.category = cc1.id " + . "INNER JOIN series_categories AS cc2 " + . " ON series.subcategory = cc2.id " + . "LEFT JOIN category_group_map AS cgm " + . " ON series.category = cgm.category_id " + . " AND cgm.group_id NOT IN($grouplist) " + . "WHERE series.series_id = ? " + . " AND (creator = ? OR (is_public = 1 AND cgm.category_id IS NULL))", + undef, + ($series_id, $user->id) + ); + + if (@series) { + $self->initFromParameters(@series); + return $self; + } + else { + return undef; + } } sub initFromParameters { - # Pass undef as the first parameter if you are creating a new series. - my $self = shift; - ($self->{'series_id'}, $self->{'category'}, $self->{'subcategory'}, - $self->{'name'}, $self->{'creator_id'}, $self->{'frequency'}, - $self->{'query'}, $self->{'public'}, $self->{'category_id'}, - $self->{'subcategory_id'}) = @_; + # Pass undef as the first parameter if you are creating a new series. + my $self = shift; + + ( + $self->{'series_id'}, $self->{'category'}, $self->{'subcategory'}, + $self->{'name'}, $self->{'creator_id'}, $self->{'frequency'}, + $self->{'query'}, $self->{'public'}, $self->{'category_id'}, + $self->{'subcategory_id'} + ) = @_; - # If the first parameter is undefined, check if this series already - # exists and update it series_id accordingly - $self->{'series_id'} ||= $self->existsInDatabase(); + # If the first parameter is undefined, check if this series already + # exists and update it series_id accordingly + $self->{'series_id'} ||= $self->existsInDatabase(); } sub initFromCGI { - my $self = shift; - my $cgi = shift; - - $self->{'series_id'} = $cgi->param('series_id') || undef; - if (defined($self->{'series_id'})) { - detaint_natural($self->{'series_id'}) - || ThrowCodeError("invalid_series_id", - { 'series_id' => $self->{'series_id'} }); - } - - $self->{'category'} = $cgi->param('category') - || $cgi->param('newcategory') - || ThrowUserError("missing_category"); - - $self->{'subcategory'} = $cgi->param('subcategory') - || $cgi->param('newsubcategory') - || ThrowUserError("missing_subcategory"); - - $self->{'name'} = $cgi->param('name') - || ThrowUserError("missing_name"); - - $self->{'creator_id'} = Bugzilla->user->id; - - $self->{'frequency'} = $cgi->param('frequency'); - detaint_natural($self->{'frequency'}) - || ThrowUserError("missing_frequency"); - - $self->{'query'} = $cgi->canonicalise_query("format", "ctype", "action", - "category", "subcategory", "name", - "frequency", "public", "query_format"); - trick_taint($self->{'query'}); - - $self->{'public'} = $cgi->param('public') ? 1 : 0; - - # Change 'admin' here and in series.html.tmpl, or remove the check - # completely, if you want to change who can make series public. - $self->{'public'} = 0 unless Bugzilla->user->in_group('admin'); + my $self = shift; + my $cgi = shift; + + $self->{'series_id'} = $cgi->param('series_id') || undef; + if (defined($self->{'series_id'})) { + detaint_natural($self->{'series_id'}) + || ThrowCodeError("invalid_series_id", {'series_id' => $self->{'series_id'}}); + } + + $self->{'category'} + = $cgi->param('category') + || $cgi->param('newcategory') + || ThrowUserError("missing_category"); + + $self->{'subcategory'} + = $cgi->param('subcategory') + || $cgi->param('newsubcategory') + || ThrowUserError("missing_subcategory"); + + $self->{'name'} = $cgi->param('name') || ThrowUserError("missing_name"); + + $self->{'creator_id'} = Bugzilla->user->id; + + $self->{'frequency'} = $cgi->param('frequency'); + detaint_natural($self->{'frequency'}) || ThrowUserError("missing_frequency"); + + $self->{'query'} = $cgi->canonicalise_query( + "format", "ctype", "action", "category", + "subcategory", "name", "frequency", "public", + "query_format" + ); + trick_taint($self->{'query'}); + + $self->{'public'} = $cgi->param('public') ? 1 : 0; + + # Change 'admin' here and in series.html.tmpl, or remove the check + # completely, if you want to change who can make series public. + $self->{'public'} = 0 unless Bugzilla->user->in_group('admin'); } sub writeToDatabase { - my $self = shift; + my $self = shift; - my $dbh = Bugzilla->dbh; - $dbh->bz_start_transaction(); + my $dbh = Bugzilla->dbh; + $dbh->bz_start_transaction(); - my $category_id = getCategoryID($self->{'category'}); - my $subcategory_id = getCategoryID($self->{'subcategory'}); + my $category_id = getCategoryID($self->{'category'}); + my $subcategory_id = getCategoryID($self->{'subcategory'}); - my $exists; - if ($self->{'series_id'}) { - $exists = - $dbh->selectrow_array("SELECT series_id FROM series - WHERE series_id = $self->{'series_id'}"); - } - - # Is this already in the database? - if ($exists) { - # Update existing series - my $dbh = Bugzilla->dbh; - $dbh->do("UPDATE series SET " . - "category = ?, subcategory = ?," . - "name = ?, frequency = ?, is_public = ? " . - "WHERE series_id = ?", undef, - $category_id, $subcategory_id, $self->{'name'}, - $self->{'frequency'}, $self->{'public'}, - $self->{'series_id'}); - } - else { - # Insert the new series into the series table - $dbh->do("INSERT INTO series (creator, category, subcategory, " . - "name, frequency, query, is_public) VALUES " . - "(?, ?, ?, ?, ?, ?, ?)", undef, - $self->{'creator_id'}, $category_id, $subcategory_id, $self->{'name'}, - $self->{'frequency'}, $self->{'query'}, $self->{'public'}); - - # Retrieve series_id - $self->{'series_id'} = $dbh->selectrow_array("SELECT MAX(series_id) " . - "FROM series"); - $self->{'series_id'} - || ThrowCodeError("missing_series_id", { 'series' => $self }); - } - - $dbh->bz_commit_transaction(); + my $exists; + if ($self->{'series_id'}) { + $exists = $dbh->selectrow_array( + "SELECT series_id FROM series + WHERE series_id = $self->{'series_id'}" + ); + } + + # Is this already in the database? + if ($exists) { + + # Update existing series + my $dbh = Bugzilla->dbh; + $dbh->do( + "UPDATE series SET " + . "category = ?, subcategory = ?," + . "name = ?, frequency = ?, is_public = ? " + . "WHERE series_id = ?", + undef, + $category_id, + $subcategory_id, + $self->{'name'}, + $self->{'frequency'}, + $self->{'public'}, + $self->{'series_id'} + ); + } + else { + # Insert the new series into the series table + $dbh->do( + "INSERT INTO series (creator, category, subcategory, " + . "name, frequency, query, is_public) VALUES " + . "(?, ?, ?, ?, ?, ?, ?)", + undef, + $self->{'creator_id'}, + $category_id, + $subcategory_id, + $self->{'name'}, + $self->{'frequency'}, + $self->{'query'}, + $self->{'public'} + ); + + # Retrieve series_id + $self->{'series_id'} + = $dbh->selectrow_array("SELECT MAX(series_id) " . "FROM series"); + $self->{'series_id'} + || ThrowCodeError("missing_series_id", {'series' => $self}); + } + + $dbh->bz_commit_transaction(); } # Check whether a series with this name, category and subcategory exists in # the DB and, if so, returns its series_id. sub existsInDatabase { - my $self = shift; - my $dbh = Bugzilla->dbh; + my $self = shift; + my $dbh = Bugzilla->dbh; + + my $category_id = getCategoryID($self->{'category'}); + my $subcategory_id = getCategoryID($self->{'subcategory'}); - my $category_id = getCategoryID($self->{'category'}); - my $subcategory_id = getCategoryID($self->{'subcategory'}); - - trick_taint($self->{'name'}); - my $series_id = $dbh->selectrow_array("SELECT series_id " . - "FROM series WHERE category = $category_id " . - "AND subcategory = $subcategory_id AND name = " . - $dbh->quote($self->{'name'})); - - return($series_id); + trick_taint($self->{'name'}); + my $series_id + = $dbh->selectrow_array("SELECT series_id " + . "FROM series WHERE category = $category_id " + . "AND subcategory = $subcategory_id AND name = " + . $dbh->quote($self->{'name'})); + + return ($series_id); } # Get a category or subcategory IDs, creating the category if it doesn't exist. sub getCategoryID { - my ($category) = @_; - my $category_id; - my $dbh = Bugzilla->dbh; + my ($category) = @_; + my $category_id; + my $dbh = Bugzilla->dbh; - # This seems for the best idiom for "Do A. Then maybe do B and A again." - while (1) { - # We are quoting this to put it in the DB, so we can remove taint - trick_taint($category); + # This seems for the best idiom for "Do A. Then maybe do B and A again." + while (1) { - $category_id = $dbh->selectrow_array("SELECT id " . - "from series_categories " . - "WHERE name =" . $dbh->quote($category)); + # We are quoting this to put it in the DB, so we can remove taint + trick_taint($category); - last if defined($category_id); + $category_id + = $dbh->selectrow_array("SELECT id " + . "from series_categories " + . "WHERE name =" + . $dbh->quote($category)); - $dbh->do("INSERT INTO series_categories (name) " . - "VALUES (" . $dbh->quote($category) . ")"); - } + last if defined($category_id); + + $dbh->do("INSERT INTO series_categories (name) " + . "VALUES (" + . $dbh->quote($category) + . ")"); + } - return $category_id; + return $category_id; } ########## @@ -254,20 +285,20 @@ sub id { return $_[0]->{'series_id'}; } sub name { return $_[0]->{'name'}; } sub creator { - my $self = shift; + my $self = shift; - if (!$self->{creator} && $self->{creator_id}) { - require Bugzilla::User; - $self->{creator} = new Bugzilla::User($self->{creator_id}); - } - return $self->{creator}; + if (!$self->{creator} && $self->{creator_id}) { + require Bugzilla::User; + $self->{creator} = new Bugzilla::User($self->{creator_id}); + } + return $self->{creator}; } sub remove_from_db { - my $self = shift; - my $dbh = Bugzilla->dbh; + my $self = shift; + my $dbh = Bugzilla->dbh; - $dbh->do('DELETE FROM series WHERE series_id = ?', undef, $self->id); + $dbh->do('DELETE FROM series WHERE series_id = ?', undef, $self->id); } 1; |