Rev 1293 | Blame | Last modification | View Log | RSS feed
################################################################################ Codestriker: Copyright (c) 2001, 2002 David Sitsky. All rights reserved.# sits@users.sourceforge.net## This program is free software; you can redistribute it and modify it under# the terms of the GPL.# Model object for handling project data.package Codestriker::Model::Project;use strict;use Carp;use Encode qw(decode_utf8);use Codestriker::DB::DBI;# Simple private method which returns the mapping of project state id to# its textual representation.sub _state_id_to_string {my ($id) = @_;return 'Open' if $id == 0;return 'Closed' if $id == 1;return 'Deleted' if $id == 2;return "State $id";}# Simple private method which returns the mapping of project state to# its id.sub _state_string_to_id {my ($state) = @_;return 0 if $state eq 'Open';return 1 if $state eq 'Closed';return 2 if $state eq 'Deleted';return 3;}# Create a new project with all of the specified properties.sub create($$$$) {my ($type, $name, $description) = @_;my $rc = $Codestriker::OK;# Obtain a database connection.my $dbh = Codestriker::DB::DBI->get_connection();# Check that a project with this name doesn't already exist.my $select = $dbh->prepare_cached('SELECT COUNT(*) FROM project ' .'WHERE name = ?');my $success = defined $select;$success &&= $select->execute($name);if ($success) {my ($count) = $select->fetchrow_array();$select->finish();if ($count != 0) {$success = 0;$rc = $Codestriker::DUPLICATE_PROJECT_NAME;}}# Create the project entry.my $timestamp = Codestriker->get_timestamp(time);my $create = $dbh->prepare_cached('INSERT INTO project ' .'(name, description, creation_ts, ' .'modified_ts, version, state ) ' .'VALUES (?, ?, ?, ?, ?, ?) ');$success &&=$create->execute($name, $description, $timestamp, $timestamp, 0, 0);$success &&= $create->finish();Codestriker::DB::DBI->release_connection($dbh, $success);return $rc;}# Return all projects in the system.sub list($$) {my ($type, $state) = @_;# Obtain a database connection.my $dbh = Codestriker::DB::DBI->get_connection();# Store the results into an array of objects.my @results = ();# Retrieve all of the comment information for the specified topicid.my $select =$dbh->prepare_cached('SELECT id, name, description, version, state ' .'FROM project ORDER BY state, name, creation_ts');my $success = defined $select;$success &&= $select->execute();# Store the results in the array.if ($success) {my @data;while (@data = $select->fetchrow_array()) {my $project = {};$project->{id} = $data[0];$project->{name} = decode_utf8($data[1]);$project->{description} = decode_utf8($data[2]);$project->{version} = $data[3];$project->{state} = _state_id_to_string($data[4]);if (!defined $state || $project->{state} eq $state){push @results, $project;}}$select->finish();}Codestriker::DB::DBI->release_connection($dbh, $success);die $dbh->errstr unless $success;return @results;}# Read the details of a specific project from the database.sub read($$) {my ($type, $id) = @_;# Obtain a database connection.my $dbh = Codestriker::DB::DBI->get_connection();my $select =$dbh->prepare_cached('SELECT name, description, version, state ' .'FROM project WHERE id = ?');my $success = defined $select;$success &&= $select->execute($id);my ($name, $description, $version, $state);if ($success &&! (($name, $description, $version, $state) =$select->fetchrow_array())) {$success = 0;}$success &&= $select->finish();my $project = {};if ($success) {# Populate return object.$project->{id} = $id;$project->{name} = decode_utf8($name);$project->{description} = decode_utf8($description);$project->{version} = $version;$project->{state} = _state_id_to_string($state);}Codestriker::DB::DBI->release_connection($dbh, $success);return $project;}# Update the project details.sub update($$$$$$) {my ($type, $id, $name, $description, $version, $project_state) = @_;# Map the new state to its number.my $new_stateid = _state_string_to_id($project_state);# Obtain a database connection.my $dbh = Codestriker::DB::DBI->get_connection();# Check that the version reflects the current version in the DB.my $select =$dbh->prepare_cached('SELECT version FROM project ' .'WHERE id = ?');my $update =$dbh->prepare_cached('UPDATE project SET version = ?, ' .'name = ?, description = ?, modified_ts = ?, ' .'state = ? WHERE id = ?');my $success = defined $select && defined $update;my $rc = $Codestriker::OK;# Retrieve the current comment data.$success &&= $select->execute($id);# Make sure that the project still exists, and is therefore valid.my $current_version;if ($success && ! (($current_version) = $select->fetchrow_array())) {# Invalid project id.$success = 0;$rc = $Codestriker::INVALID_PROJECT;}$success &&= $select->finish();# Check the version number.if ($success && $version != $current_version) {$success = 0;$rc = $Codestriker::STALE_VERSION;}# Update the project details.my $timestamp = Codestriker->get_timestamp(time);$success &&= $update->execute($version+1, $name, $description,$timestamp, $new_stateid, $id);Codestriker::DB::DBI->release_connection($dbh, $success);return $rc;}# Update the project details.sub delete($$) {my ($type, $id, $version) = @_;# Obtain a database connection.my $dbh = Codestriker::DB::DBI->get_connection();# Check that the version reflects the current version in the DB.my $select =$dbh->prepare_cached('SELECT version FROM project ' .'WHERE id = ?');# Create the prepared statements.my $delete = $dbh->prepare_cached('DELETE FROM project WHERE id = ?');my $success = defined $select && defined $delete;my $rc = $Codestriker::OK;# Retrieve the current comment data.$success &&= $select->execute($id);# Make sure that the project still exists, and is therefore valid.my $current_version;if ($success && ! (($current_version) = $select->fetchrow_array())) {# Invalid project id.$success = 0;$rc = $Codestriker::INVALID_PROJECT;}$success &&= $select->finish();# Check the version number.if ($success && $version != $current_version) {$success = 0;$rc = $Codestriker::STALE_VERSION;}if ($success == 0) {Codestriker::DB::DBI->release_connection($dbh, $success);return $rc;} else {# Delete the topics in this project.my @sort_order;my @topic_query_results;Codestriker::Model::Topic->query("", "", "", "","", $id, "","", "","", "", "",\@sort_order, \@topic_query_results);# Delete each of the topics for this projectfor (my $index = 0; $index <= $#topic_query_results; $index++) {my $topic_row = $topic_query_results[$index];my $topicid = $topic_row->{id};my $topic_delete = Codestriker::Model::Topic->new($topicid);$topic_delete->delete();}# Now delete the project.$delete->execute($id);Codestriker::DB::DBI->release_connection($dbh, $success);return $rc;}}# Determine the number of open topics in the specified project.sub num_open_topics {my ($type, $id) = @_;my $dbh = Codestriker::DB::DBI->get_connection();my $count;eval {$count = $dbh->selectrow_array('SELECT COUNT(topic.id) ' .'FROM topic ' .'WHERE topic.projectid = ? ' .'AND topic.state = 0', {}, $id);};Codestriker::DB::DBI->release_connection($dbh, 1);if ($@) {carp "Problem retrieving count of open topics in project: $@";}return $count;}# Determine the number of topics in the specified project.sub num_topics {my ($type, $id) = @_;my $dbh = Codestriker::DB::DBI->get_connection();my $count;eval {$count = $dbh->selectrow_array('SELECT COUNT(topic.id) ' .'FROM topic ' .'WHERE topic.projectid = ? ', {}, $id);};Codestriker::DB::DBI->release_connection($dbh, 1);if ($@) {carp "Problem retrieving count of topics in project: $@";}return $count;}1;