Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1293 dpurdie 1
###############################################################################
2
# Codestriker: Copyright (c) 2001, 2002 David Sitsky.  All rights reserved.
3
# sits@users.sourceforge.net
4
#
5
# This program is free software; you can redistribute it and modify it under
6
# the terms of the GPL.
7
 
8
# Model object for handling project data.
9
 
10
package Codestriker::Model::Project;
11
 
12
use strict;
13
use Carp;
14
use Encode qw(decode_utf8);
15
 
16
use Codestriker::DB::DBI;
17
 
18
# Simple private method which returns the mapping of project state id to
19
# its textual representation.
20
sub _state_id_to_string {
21
    my ($id) = @_;
22
    return 'Open' if $id == 0;
23
    return 'Closed' if $id == 1;
24
    return 'Deleted' if $id == 2;
25
    return "State $id";
26
}
27
 
28
# Simple private method which returns the mapping of project state to
29
# its id.
30
sub _state_string_to_id {
31
    my ($state) = @_;
32
    return 0 if $state eq 'Open';
33
    return 1 if $state eq 'Closed';
34
    return 2 if $state eq 'Deleted';
35
    return 3;
36
}
37
 
38
# Create a new project with all of the specified properties.
39
sub create($$$$) {
40
    my ($type, $name, $description) = @_;
41
 
42
    my $rc = $Codestriker::OK;
43
 
44
    # Obtain a database connection.
45
    my $dbh = Codestriker::DB::DBI->get_connection();
46
 
47
    # Check that a project with this name doesn't already exist.
48
    my $select = $dbh->prepare_cached('SELECT COUNT(*) FROM project ' .
49
				      'WHERE name = ?');
50
    my $success = defined $select;
51
    $success &&= $select->execute($name);
52
    if ($success) {
53
	my ($count) = $select->fetchrow_array();
54
	$select->finish();
55
	if ($count != 0) {
56
	    $success = 0;
57
	    $rc = $Codestriker::DUPLICATE_PROJECT_NAME;
58
	}
59
    }
60
 
61
    # Create the project entry.
62
    my $timestamp = Codestriker->get_timestamp(time);
63
    my $create = $dbh->prepare_cached('INSERT INTO project ' .
64
				      '(name, description, creation_ts, ' .
65
				      'modified_ts, version, state ) ' .
66
				      'VALUES (?, ?, ?, ?, ?, ?) ');
67
    $success &&=
68
	$create->execute($name, $description, $timestamp, $timestamp, 0, 0);
69
    $success &&= $create->finish();
70
 
71
    Codestriker::DB::DBI->release_connection($dbh, $success);
72
    return $rc;
73
}
74
 
75
# Return all projects in the system.
76
sub list($$) {
77
    my ($type, $state) = @_;
78
 
79
    # Obtain a database connection.
80
    my $dbh = Codestriker::DB::DBI->get_connection();
81
 
82
    # Store the results into an array of objects.
83
    my @results = ();
84
 
85
    # Retrieve all of the comment information for the specified topicid.
86
    my $select =
87
	$dbh->prepare_cached('SELECT id, name, description, version, state ' .
88
			     'FROM project ORDER BY state, name, creation_ts');
89
    my $success = defined $select;
90
    $success &&= $select->execute();
91
 
92
    # Store the results in the array.
93
    if ($success) {
94
	my @data;
95
	while (@data = $select->fetchrow_array()) {
96
	    my $project = {};
97
	    $project->{id} = $data[0];
98
	    $project->{name} = decode_utf8($data[1]);
99
	    $project->{description} = decode_utf8($data[2]);
100
	    $project->{version} = $data[3];
101
	    $project->{state} = _state_id_to_string($data[4]);
102
	    if (!defined $state || $project->{state} eq $state)
103
	    {
104
		push @results, $project;
105
	    }
106
	}
107
	$select->finish();
108
    }
109
 
110
    Codestriker::DB::DBI->release_connection($dbh, $success);
111
    die $dbh->errstr unless $success;
112
 
113
    return @results;
114
}
115
 
116
# Read the details of a specific project from the database.
117
sub read($$) {
118
    my ($type, $id) = @_;
119
 
120
    # Obtain a database connection.
121
    my $dbh = Codestriker::DB::DBI->get_connection();
122
 
123
    my $select =
124
	$dbh->prepare_cached('SELECT name, description, version, state ' .
125
			     'FROM project WHERE id = ?');
126
    my $success = defined $select;
127
    $success &&= $select->execute($id);
128
    my ($name, $description, $version, $state);
129
    if ($success &&
130
	! (($name, $description, $version, $state) =
131
	   $select->fetchrow_array())) {
132
	$success = 0;
133
    }
134
    $success &&= $select->finish();
135
 
136
    my $project = {};
137
    if ($success) {
138
	# Populate return object.
139
	$project->{id} = $id;
140
	$project->{name} = decode_utf8($name);
141
	$project->{description} = decode_utf8($description);
142
	$project->{version} = $version;
143
	$project->{state} = _state_id_to_string($state);
144
    }
145
 
146
    Codestriker::DB::DBI->release_connection($dbh, $success);
147
 
148
    return $project;
149
}
150
 
151
# Update the project details.
152
sub update($$$$$$) {
153
    my ($type, $id, $name, $description, $version, $project_state) = @_;
154
 
155
    # Map the new state to its number.
156
    my $new_stateid = _state_string_to_id($project_state);
157
 
158
    # Obtain a database connection.
159
    my $dbh = Codestriker::DB::DBI->get_connection();
160
 
161
    # Check that the version reflects the current version in the DB.
162
    my $select =
163
	$dbh->prepare_cached('SELECT version FROM project ' .
164
			     'WHERE id = ?');
165
    my $update =
166
	$dbh->prepare_cached('UPDATE project SET version = ?, ' .
167
			     'name = ?, description = ?, modified_ts = ?, ' .
168
			     'state = ? WHERE id = ?');
169
 
170
    my $success = defined $select && defined $update;
171
    my $rc = $Codestriker::OK;
172
 
173
    # Retrieve the current comment data.
174
    $success &&= $select->execute($id);
175
 
176
    # Make sure that the project still exists, and is therefore valid.
177
    my $current_version;
178
    if ($success && ! (($current_version) = $select->fetchrow_array())) {
179
	# Invalid project id.
180
	$success = 0;
181
	$rc = $Codestriker::INVALID_PROJECT;
182
    }
183
    $success &&= $select->finish();
184
 
185
    # Check the version number.
186
    if ($success && $version != $current_version) {
187
	$success = 0;
188
	$rc = $Codestriker::STALE_VERSION;
189
    }
190
 
191
    # Update the project details.
192
    my $timestamp = Codestriker->get_timestamp(time);
193
    $success &&= $update->execute($version+1, $name, $description,
194
				  $timestamp, $new_stateid, $id);
195
    Codestriker::DB::DBI->release_connection($dbh, $success);
196
    return $rc;
197
}
198
 
199
# Update the project details.
200
sub delete($$) {
201
    my ($type, $id, $version) = @_;
202
 
203
    # Obtain a database connection.
204
    my $dbh = Codestriker::DB::DBI->get_connection();
205
 
206
    # Check that the version reflects the current version in the DB.
207
    my $select =
208
	$dbh->prepare_cached('SELECT version FROM project ' .
209
			     'WHERE id = ?');
210
 
211
    # Create the prepared statements.
212
    my $delete = $dbh->prepare_cached('DELETE FROM project WHERE id = ?');
213
 
214
    my $success = defined $select && defined $delete;
215
    my $rc = $Codestriker::OK;
216
 
217
    # Retrieve the current comment data.
218
    $success &&= $select->execute($id);
219
 
220
    # Make sure that the project still exists, and is therefore valid.
221
    my $current_version;
222
    if ($success && ! (($current_version) = $select->fetchrow_array())) {
223
	# Invalid project id.
224
	$success = 0;
225
	$rc = $Codestriker::INVALID_PROJECT;
226
    }
227
    $success &&= $select->finish();
228
 
229
    # Check the version number.
230
    if ($success && $version != $current_version) {
231
	$success = 0;
232
	$rc = $Codestriker::STALE_VERSION;
233
    }
234
 
235
    if ($success == 0) {
236
	Codestriker::DB::DBI->release_connection($dbh, $success);
237
	return $rc;
238
    } else {
239
	# Delete the topics in this project.
240
	my @sort_order;
241
	my @topic_query_results;
242
	Codestriker::Model::Topic->query("", "", "", "",
243
					 "", $id, "",
244
					 "", "",
245
					 "", "", "",
246
					 \@sort_order, \@topic_query_results);
247
 
248
	# Delete each of the topics for this project
249
	for (my $index = 0; $index <= $#topic_query_results; $index++) {
250
	    my $topic_row = $topic_query_results[$index];
251
	    my $topicid = $topic_row->{id};
252
	    my $topic_delete = Codestriker::Model::Topic->new($topicid);
253
	    $topic_delete->delete();
254
	}
255
 
256
	# Now delete the project.
257
	$delete->execute($id);
258
	Codestriker::DB::DBI->release_connection($dbh, $success);
259
 
260
	return $rc;
261
    }
262
}
263
 
264
# Determine the number of open topics in the specified project.
265
sub num_open_topics {
266
    my ($type, $id) = @_;
267
 
268
    my $dbh = Codestriker::DB::DBI->get_connection();
269
    my $count;
270
    eval {
271
	$count = $dbh->selectrow_array('SELECT COUNT(topic.id) ' .
272
				       'FROM topic ' .
273
				       'WHERE topic.projectid = ? ' .
274
				       'AND topic.state = 0', {}, $id);
275
    };
276
    Codestriker::DB::DBI->release_connection($dbh, 1);
277
    if ($@) {
278
	carp "Problem retrieving count of open topics in project: $@";
279
    }
280
 
281
    return $count;
282
}
283
 
284
# Determine the number of topics in the specified project.
285
sub num_topics {
286
    my ($type, $id) = @_;
287
 
288
    my $dbh = Codestriker::DB::DBI->get_connection();
289
    my $count;
290
    eval {
291
	$count = $dbh->selectrow_array('SELECT COUNT(topic.id) ' .
292
				       'FROM topic ' .
293
				       'WHERE topic.projectid = ? ', {}, $id);
294
    };
295
    Codestriker::DB::DBI->release_connection($dbh, 1);
296
 
297
    if ($@) {
298
	carp "Problem retrieving count of topics in project: $@";
299
    }
300
 
301
    return $count;
302
}
303
 
304
 
305
1;