📄 topic.pm
字号:
$self->{obsoleted_by} = \@obsoleted_by; # Set the repository to the default system value if it is not defined. if (!defined $repository || $repository eq "") { $self->{repository} = $Codestriker::default_repository; } else { $self->{repository} = $repository; } } return $success ? $Codestriker::OK : $rc;}# Reads from the db if needed, and returns the list of comments for# this topic. If the list of comments have already been returned, the# function will skip the db call, and just return the list from# memory.sub read_comments { my ($self) = shift; if (scalar(@{$self->{comments}}) == 0) { my @comments = Codestriker::Model::Comment->read_all_comments_for_topic($self->{topicid}); $self->{comments} = \@comments; } return @{$self->{comments}};}# returns a count of the comments that have the given comment# metric (commentmetrictype) set to value. Used# on the search page.sub get_comment_metric_count { my ($self,$commentmetrictype,$value) = @_; my $count = 0; if (scalar(@{$self->{comments}}) == 0) { # Obtain a database connection. my $dbh = Codestriker::DB::DBI->get_connection(); # the comments have not been read into memory yet. $count = $dbh->selectrow_array(' SELECT COUNT(commentstatemetric.value) FROM commentstatemetric, commentstate WHERE commentstate.topicid = ? AND commentstate.id = commentstatemetric.id AND commentstatemetric.name = ? AND commentstatemetric.value = ?', { }, $self->{topicid}, $commentmetrictype, $value); Codestriker::DB::DBI->release_connection($dbh, 1); } else { # already read into memory, don't hit the database. foreach my $comment (@{$self->{comments}}) { if ( exists( $comment->{$commentmetrictype} ) && $comment->{$commentmetrictype} eq $value ) { ++$count; } } } return $count;}# Retrieve the changed files which are a part of this review. It will only pull them# from the database once.sub get_filestable { my ($self,$filenames, $revisions, $offsets, $binary, $numchanges) = @_; if (exists ($self->{filetable})) { ( $filenames, $revisions, $offsets,$binary, $numchanges ) = @{$self->{filetable}}; } else { Codestriker::Model::File->get_filetable($self->{topicid}, $filenames, $revisions, $offsets, $binary, $numchanges); $self->{filetable} = [ $filenames, $revisions, $offsets, $binary, $numchanges ]; } }# Determine if the specified topic id exists in the table or not.sub exists($) { my ($topicid) = @_; # Obtain a database connection. my $dbh = Codestriker::DB::DBI->get_connection(); # Prepare the statement and execute it. my $select_topic = $dbh->prepare_cached('SELECT COUNT(*) FROM topic ' . 'WHERE id = ?'); my $success = defined $select_topic; $success &&= $select_topic->execute($topicid); my $count; if ($success) { ($count) = $select_topic->fetchrow_array(); $select_topic->finish(); } Codestriker::DB::DBI->release_connection($dbh, $success); die $dbh->errstr unless $success; return $count;}# This function returns the metrics objects that are part of the topic.sub get_metrics { my ($self) = @_; return $self->{metrics};}# Returns the size of the topic text in lines. If the topic is a diff topic# it attempts to only count the lines that have changed, and not count the# context around the lines.sub get_topic_size_in_lines { my ($self) = @_; my @deltas = Codestriker::Model::Delta->get_delta_set($self->{topicid}, -1); my $line_count = 0; foreach my $delta (@deltas) { my @document = split /\n/, $delta->{text}; $line_count += scalar( grep /^[+-][^+-][^+-]/, @document ); } return $line_count;}# This function is used to create a new topic id. The function insures# that the new topic id is difficult to guess, and is not taken in the# database already.sub create_new_topicid { # For "hysterical" reasons, the topic id is randomly generated. Seed the # generator based on the time and the pid. Keep searching until we find # a free topicid. In 99% of the time, we will get a new one first time. srand(time() ^ ($$ + ($$ << 15))); my $topicid; do { $topicid = int rand(10000000); } while (Codestriker::Model::Topic::exists($topicid)); return $topicid;}# Everytime a topic is stored the version number is incremented. When# a page is created it includes the version number of the topic used# to create the page. The user posts information back to server to# change, the version information needs to be checked to make sure# somebody else has not modified the server.sub check_for_stale($$) { my ($self, $version) = @_; return $self->{version} ne $version;}# Update the state of the specified topic.sub change_state($$) { my ($self, $new_state) = @_; my $modified_ts = Codestriker->get_timestamp(time); # Map the new state to its number. my $new_stateid; for ($new_stateid = 0; $new_stateid <= $#Codestriker::topic_states; $new_stateid++) { last if ($Codestriker::topic_states[$new_stateid] eq $new_state); } if ($new_stateid > $#Codestriker::topic_states) { die "Unable to change topic to invalid state: \"$new_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_topic = $dbh->prepare_cached('SELECT version ' . 'FROM topic WHERE id = ?'); my $update_topic = $dbh->prepare_cached('UPDATE topic SET version = ?, state = ?, ' . 'modified_ts = ? WHERE id = ?'); my $success = defined $select_topic && defined $update_topic; my $rc = $Codestriker::OK; # Retrieve the current topic data. $success &&= $select_topic->execute($self->{topicid}); # Make sure that the topic still exists, and is therefore valid. my ($current_version); if ($success && ! (($current_version) = $select_topic->fetchrow_array())) { # Invalid topic id. $success = 0; $rc = $Codestriker::INVALID_TOPIC; } $success &&= $select_topic->finish(); # Check the version number. if ($self->{version} != $current_version) { $success = 0; $rc = $Codestriker::STALE_VERSION; } # If the state hasn't changed, don't do anything, otherwise update the # topic. if ($new_state ne $self->{topic_state}) { $self->{version} = $self->{version} + 1; $success &&= $update_topic->execute($self->{version}, $new_stateid, $modified_ts, $self->{topicid}); } $self->{modified_ts} = $modified_ts; $self->{topic_state} = $new_state; Codestriker::DB::DBI->release_connection($dbh, $success); return $rc;}# Update the properties of the specified topic. This is not implemented# very efficiently, however it is not expected to be called very often.sub update($$$$$$$$$$) { my ($self, $new_title, $new_author, $new_reviewers, $new_cc, $new_repository, $new_bug_ids, $new_projectid, $new_description, $new_state) = @_; # First check that the version matches the current topic version in the # database. my $dbh = Codestriker::DB::DBI->get_connection(); my $select_topic = $dbh->prepare_cached('SELECT version ' . 'FROM topic WHERE id = ?'); my $success = defined $select_topic; my $rc = $Codestriker::OK; # Make sure that the topic still exists, and is therefore valid. $success &&= $select_topic->execute($self->{topicid}); my $current_version; if ($success && ! (($current_version) = $select_topic->fetchrow_array())) { # Invalid topic id. $success = 0; $rc = $Codestriker::INVALID_TOPIC; } $success &&= $select_topic->finish(); # Check the version number. if ($success && $self->{version} != $current_version) { $success = 0; $rc = $Codestriker::STALE_VERSION; } # Get the modified date to the current time. my $modified_ts = Codestriker->get_timestamp(time); # Map the new state to its number. my $new_stateid; for ($new_stateid = 0; $new_stateid <= $#Codestriker::topic_states; $new_stateid++) { last if ($Codestriker::topic_states[$new_stateid] eq $new_state); } if ($new_stateid > $#Codestriker::topic_states) { die "Unable to change topic to invalid state: \"$new_state\""; } # Update the topic object's properties. $self->{title} = $new_title; $self->{author} = $new_author; $self->{repository} = $new_repository; $self->{project_id} = $new_projectid; $self->{description} = $new_description; $self->{modified_ts} = $modified_ts; $self->{topic_state} = $new_state; $self->{topic_state_id} = $new_stateid; # Now update the database with the new properties. my $update_topic = $dbh->prepare_cached('UPDATE topic SET version = ?, state = ?, ' . 'modified_ts = ?, ' . 'title = ?, author = ?, ' . 'repository = ?, projectid = ?, ' . 'description = ? WHERE id = ?'); $success &&= defined $update_topic; # If the state hasn't changed, don't do anything, otherwise update the # topic. if ($success) { $self->{version} = $self->{version} + 1; $success &&= $update_topic->execute($self->{version}, $new_stateid, $modified_ts, $new_title, $new_author, $new_repository, $new_projectid, $new_description, $self->{topicid}); } # Now delete all bugs associated with this topic, and recreate them again # if they have changed. if ($success && $self->{bug_ids} ne $new_bug_ids) { $success &&= $self->_delete_bug_ids($dbh); $success &&= $self->_insert_bug_ids($dbh, $new_bug_ids); $self->{bug_ids} = $new_bug_ids; } # Now delete all reviewers associated with this topic, and recreate # them again, if they have changed. if ($success && $self->{reviewers} ne $new_reviewers) { $success &&= $self->_delete_participants($dbh, $Codestriker::PARTICIPANT_REVIEWER); $success &&= $self->_insert_participants($dbh, $Codestriker::PARTICIPANT_REVIEWER, $new_reviewers, $modified_ts); $self->{reviewers} = $new_reviewers; } # Now delete all CCs associated with this topic, and recreate # them again, if they have changed. if ($success && $self->{cc} ne $new_cc) { $success &&= $self->_delete_participants($dbh, $Codestriker::PARTICIPANT_CC); $success &&=
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -