# ==================================================================
# Gossamer Links - enhanced directory management system
#
#   Website  : http://gossamer-threads.com/
#   Support  : http://gossamer-threads.com/scripts/support/
#   CVS Info : 087,071,086,086,085      
#   Revision : $Id: Review.pm,v 1.78 2007/11/16 07:12:57 brewt Exp $
#
# Copyright (c) 2001 Gossamer Threads Inc.  All Rights Reserved.
# Redistribution in part or in whole strictly prohibited. Please
# see LICENSE file for full details.
# ==================================================================

package Links::User::Review;
# ==================================================================
use strict;
use Links qw/:objects/;
use Links::Build;
use Links::SiteHTML;

sub handle {
# ------------------------------------------------------------------
# Determine what to do.
#
    my $input = $IN->get_hash;
    if    ($input->{add_review})  { $PLG->dispatch('review_add', \&add_review) }
    elsif ($input->{edit_review}) { $PLG->dispatch('review_edit', \&edit_review) }
    elsif ($input->{helpful})     { $PLG->dispatch('review_helpful', \&helpful_review) }
    else                          { $PLG->dispatch('review_search', \&review_search_results) }
    return;
}
# ==================================================================

sub review_search_results {
# ------------------------------------------------------------------
# Display a list of validated reviews for a link
#
    my $id = shift;

    my $mtl = Links::Build::build('title', Links::language('LINKS_REVIEW'), "$CFG->{db_cgi_url}/review.cgi");

# Get our form data and prepare some default data.
    my $args = $IN->get_hash;
    $id ||= $args->{ID};
    $args->{username} = '\*' if $args->{username} eq '*';

# Return error if no action
    unless ($args->{keyword} or $args->{ReviewID} or $id) {
        if ($USER) {
            $args->{username} ||= $USER->{Username};
            $IN->param(username => $args->{username});
        }
        elsif (!$args->{username} and !$args->{helpful}) {
            print $IN->header();
            print Links::SiteHTML::display('error', { error => Links::language('REVIEW_INVALID_ACTION'), main_title_loop => $mtl });
            return;
        }
    }

# Reset ReviewID to null
    my $from_helpful = ($args->{helpful}) ? $args->{ReviewID} : '';
    $args->{ReviewID} = '';

# Review must be validated to list
    $args->{Review_Validated} = 'Yes';
    $args->{nh} = (defined $args->{nh} and $args->{nh} =~ /^(\d+)$/) ? $1 : 1;
    $args->{mh} = (defined $args->{mh} and $args->{mh} =~ /^(\d+)$/) ? $1 : $CFG->{reviews_per_page};
    $args->{so} = (defined $args->{so} and $args->{so} =~ /^(asc|desc)$/i) ? $1 : $CFG->{review_sort_order};
    ($args->{sb} and ($args->{sb} =~ /^[\w\s,]+$/) or ($args->{sb} = $CFG->{review_sort_by}));
    delete $args->{ma};

    my $rec = { noLink => 1 };
# If we are listing reviews of a link
    if ($id) {
        $id and $args->{ID} = $id;

# Check if ID is valid
        $rec = $DB->table('Links')->get($args->{ID});
        $rec or do {
            print $IN->header();
            print Links::SiteHTML::display('error', { error => Links::language('REVIEW_INVALIDID', $args->{ID}), main_title_loop => $mtl });
            return;
        };
        $rec = Links::SiteHTML::tags('link', $rec);
        $args->{Review_LinkID} = $args->{ID};
        $args->{ww} = 1;
    }
# If we have a user to list
    elsif ($args->{username}) {
        $args->{Review_LinkID} = '';
        $args->{Review_Owner} = $args->{username};
        $args->{'Review_Owner-opt'} = '=';
    }
    elsif ($IN->param('ReviewID')) {
        $args->{ReviewID} = $IN->param('ReviewID');
        $args->{'ReviewID-opt'} = '=';
    }

    my $reviews = $DB->table('Reviews');
    my $review_sth  = $reviews->query_sth($args);
    my $review_hits = $reviews->hits;

# Return if no results.
    unless ($review_hits) {
        print $IN->header();
        print Links::SiteHTML::display('error', { error => Links::language('REVIEW_NORESULTS', $args->{ID} || $args->{username}), main_title_loop => $mtl });
        return;
    }

    my @review_results_loop;
    Links::init_date();
    my $today = GT::Date::date_get(time, GT::Date::FORMAT_DATETIME);
    my %review_cache;
    my $last_review = 0;
    while (my $review = $review_sth->fetchrow_hashref) {
        $review->{Review_Count} = $reviews->count({ Review_LinkID => $review->{Review_LinkID}, Review_Validated => 'Yes' });
        $review->{Review_IsNew} = (GT::Date::date_diff($today, $review->{Review_Date}) < $CFG->{review_days_old});
        if ($CFG->{review_allow_modify} and $USER->{Username} eq $review->{Review_Owner}) {
            if ($CFG->{review_modify_timeout}) {
                my $oldfmt = GT::Date::date_get_format();
                GT::Date::date_set_format(GT::Date::FORMAT_DATETIME);
                my $timeout = GT::Date::date_get(time - $CFG->{review_modify_timeout} * 60);
                my $date = $review->{Review_ModifyDate} =~ /^0000-00-00 00:00:00/ ? $review->{Review_Date} : $review->{Review_ModifyDate};
                if (GT::Date::date_is_greater($date, $timeout)) {
                    $review->{Review_CanModify} = 1;
                }
                GT::Date::date_set_format($oldfmt);
            }
            else {
                $review->{Review_CanModify} = 1;
            }
        }
        if ($review->{Review_ModifyDate} ne $review->{Review_Date} and $review->{Review_ModifyDate} !~ /^0000-00-00 00:00:00/) {
            $review->{Review_ModifyDate} = GT::Date::date_transform($review->{Review_ModifyDate}, GT::Date::FORMAT_DATETIME, $CFG->{date_review_format});
        }
        else {
            delete $review->{Review_ModifyDate};
        }
        $review->{Review_Date} = GT::Date::date_transform($review->{Review_Date}, GT::Date::FORMAT_DATETIME, $CFG->{date_review_format});
        $review->{Num} = $review->{Review_WasHelpful} + $review->{Review_WasNotHelpful};
        ($from_helpful eq $review->{ReviewID}) and $review->{last_helpful} = 1;
        $CFG->{review_convert_br_tags} and $review->{Review_Contents} = _translate_html($review->{Review_Contents});

# Add the link info to the review
        if ($args->{username} or $args->{ReviewID} or $args->{keyword}) {
            my $catlink = $DB->table('CatLinks', 'Category', 'Links');
            unless (exists $review_cache{$review->{Review_LinkID}}) {
                $review_cache{$review->{Review_LinkID}} = $catlink->get({ LinkID => $review->{Review_LinkID} });
            }
            if ($last_review != $review->{Review_LinkID}) {
                my $names = $review_cache{$review->{Review_LinkID}};
                $review->{LinkID} = $names->{ID};
                $review->{cat_linked} = sub { Links::Build::build('title_linked', { name => $names->{Full_Name}, complete => 1 }) };
                $review->{cat_loop} = Links::Build::build('title', $names->{Full_Name});
                foreach my $key (keys %$names) {
                    next if ($key eq 'ID');
                    exists $review->{$key} or ($review->{$key} = $names->{$key});
                }
            }
            $last_review = $review->{Review_LinkID};
        }
        push @review_results_loop, $review;
    }

    my ($toolbar, %paging);
    if ($review_hits > $args->{mh}) {
        my $url  = $CFG->{db_cgi_url} . "/" . $IN->url;
        $url     =~ s/([;&?]?)nh=(\d+)/($1 and $1 eq '?') ? '?' : ''/eg;
        $url     =~ s/[;&]helpful=1//eg;
        $toolbar = $DB->html($reviews, $args)->toolbar($args->{nh} || 1, $args->{mh} || 25, $review_hits, $url);
        %paging = (
            url          => $url,
            num_hits     => $review_hits,
            max_hits     => $args->{mh} || 25,
            current_page => $args->{nh} || 1
        );
    }
    else {
        $toolbar = '';
    }

# Some statistics for review list
    my ($review_stats,$review_count);
    if (!defined $args->{keyword}) {
        if ($args->{username}) {
            %$review_stats = map { $_ => $reviews->count({ Review_Owner => $args->{username}, Review_Rating => $_, Review_Validated => 'Yes' }) } (1 .. 5);
            $review_count = $reviews->count({ Review_Owner => $args->{username}, Review_Validated => 'Yes'} );
        }
        else {
            %$review_stats = map { $_ => $reviews->count({ Review_LinkID => $args->{ID}, Review_Rating => $_, Review_Validated => 'Yes' }) } (1 .. 5);
            $review_count = $reviews->count({ Review_LinkID => $args->{ID}, Review_Validated => 'Yes'});
        }
        if ($review_count) {
            for (1 .. 5)  {
                $review_stats->{'p' . $_} = $review_stats->{$_} * 150 / $review_count;
            }
        }
    }
    $review_stats ||= { noStats => 1 };

    print $IN->header();
    print Links::SiteHTML::display('review_search_results', {
        %$review_stats,
        %$rec,
        show_link_info  => ($args->{username} or $args->{ReviewID} or $args->{keyword}),
        main_title_loop => $mtl,
        Review_Count    => $review_hits,
        Review_Loop     => \@review_results_loop,
        Review_SpeedBar => $toolbar,
        paging          => \%paging
    });
    return;
}

sub add_review {
# ------------------------------------------------------------------
# Add a review (only logged in users can add reviews if required)
#
    my $id = $IN->param('ID') || '';

    my $mtl = Links::Build::build('title', Links::language('LINKS_REVIEW_ADD'), "$CFG->{db_cgi_url}/review.cgi");

# Check if we have a valid ID
    my $db  = $DB->table('Links');
    my $rec = $db->get($id);
    unless ($id =~ /^\d+$/ and $rec) {
        print $IN->header();
        print Links::SiteHTML::display('error', { error => Links::language('REVIEW_INVALIDID', $id), main_title_loop => $mtl });
        return;
    }
    $rec = Links::SiteHTML::tags('link', $rec);
    $rec->{anonymous} = !$CFG->{user_review_required};

# Only logged in users can add reviews (if required) or must redirect to the login page
    if ($CFG->{user_review_required} and !$USER) {
        print $IN->redirect(Links::redirect_login_url('review'));
        return;
    }

    my ($cat_id, $cat_name) = each %{$db->get_categories($id)};
    my %title = (
        title_loop   => Links::Build::build('title', "$cat_name/$rec->{Title}"),
        title        => sub { Links::Build::build('title_unlinked', "$cat_name/$rec->{Title}") },
        title_linked => sub { Links::Build::build('title_linked', "$cat_name/$rec->{Title}") }
    );

    print $IN->header();
# If we have a review to add from a form
    if ($IN->param('add_this_review')) {
        my $results = $PLG->dispatch('add_this_review', \&_add_this_review, $rec);

# If we have error
        if (defined $results->{error}) {
            print Links::SiteHTML::display('review_add', { %$results, %$rec, %title, main_title_loop => $mtl });
        }
# Return to add success page
        else {
            print Links::SiteHTML::display('review_add_success', { %$results, %$rec, %title, main_title_loop => $mtl });
        }
    }
    else {
        if ($USER) {
            my $reviews = $DB->table('Reviews');
            my $rc = $reviews->count({ Review_LinkID => $id, Review_Owner => $USER->{Username} });
# Keep pre 3.2.0 behaviour of allowing the user to edit their existing review
            if ($rc == 1 and $CFG->{review_max_reviews} == 1) {
                my $review = $reviews->select({ Review_LinkID => $id, Review_Owner => $USER->{Username} })->fetchrow_hashref;
                my $oldfmt = GT::Date::date_get_format();
                GT::Date::date_set_format(GT::Date::FORMAT_DATETIME);
                my $timeout = GT::Date::date_get(time - $CFG->{review_modify_timeout} * 60);
                my $date = $review->{Review_ModifyDate} =~ /^0000-00-00 00:00:00/ ? $review->{Review_Date} : $review->{Review_ModifyDate};
                if (not $CFG->{review_allow_modify} or $review->{Review_Validated} eq 'No' or ($CFG->{review_modify_timeout} and GT::Date::date_is_smaller($date, $timeout))) {
                    print Links::SiteHTML::display('error', { error => Links::language('REVIEW_MAX_REVIEWS', $CFG->{review_max_reviews}), main_title_loop => $mtl });
                }
                else {
                    print Links::SiteHTML::display('review_edit', {
                        %$rec, %title, confirm => 1,
                        main_title_loop => Links::Build::build('title', Links::language('LINKS_REVIEW_EDIT'), "$CFG->{db_cgi_url}/review.cgi")
                    });
                }
                GT::Date::date_set_format($oldfmt);
                return;
            }
            elsif ($CFG->{review_max_reviews} and $rc + 1 > $CFG->{review_max_reviews}) {
                print Links::SiteHTML::display('error', { error => Links::language('REVIEW_MAX_REVIEWS', $CFG->{review_max_reviews}), main_title_loop => $mtl });
                return;
            }
        }
# We are displaying an add review form
        print Links::SiteHTML::display('review_add', { %$rec, %title, main_title_loop => $mtl });
    }
}

sub _add_this_review {
# ------------------------------------------------------------------
# Add this review
#

# Get our form data and some default data.
    my $rec = shift;
    my $reviews = $DB->table('Reviews');
    my $id = $IN->param('ID');
    my $input = $IN->get_hash;
    $input->{Review_LinkID} = $id;
    $input->{Review_Validated} = ($CFG->{review_auto_validate} == 1 and $USER or $CFG->{review_auto_validate} == 2) ? 'Yes' : 'No';
    $input->{Review_WasHelpful} = 0 ;
    $input->{Review_WasNotHelpful} = 0 ;
    $input->{Host} = $ENV{REMOTE_HOST} ? "$ENV{REMOTE_HOST} ($ENV{REMOTE_ADDR})" : $ENV{REMOTE_ADDR} ? $ENV{REMOTE_ADDR} : 'none';
    $input->{Referer} = $ENV{HTTP_REFERER} ? $ENV{HTTP_REFERER} : 'none';

# Get the review owner
    $input->{Review_Owner} = $USER ? $USER->{Username} : 'admin';

    if (not $CFG->{user_review_required} and not $USER) {
        $input->{Review_GuestName} or return { error => Links::language('REVIEW_GUEST_NAME_REQUIRED') };
        $input->{Review_GuestEmail} or return { error => Links::language('REVIEW_GUEST_EMAIL_REQUIRED') };
    }

# Make sure we have a valid rating.
    my $cols = $reviews->cols;
    if (exists $cols->{Review_Rating} and $cols->{Review_Rating}->{not_null} and ($input->{Review_Rating} !~ /^\d$/ or $input->{Review_Rating} < 1 or $input->{Review_Rating} > 5)) {
        return { error => Links::language('REVIEW_RATING', $input->{Review_Rating}) };
    }

# Set date review to today's date.
    Links::init_date();
    $input->{Review_Date} = GT::Date::date_get(time, GT::Date::FORMAT_DATETIME);
    $input->{Review_ModifyDate} = $input->{Review_Date};

# Check that the number of reviews the user owns is under the limit.
    if ($USER and $CFG->{review_max_reviews} and
        $CFG->{review_max_reviews} < $reviews->count({ Review_LinkID => $id, Review_Owner => $USER->{Username} }) + 1) {
        return { error => Links::language('REVIEW_MAX_REVIEWS', $CFG->{review_max_reviews}) };
    }

# Change the language.
    local $GT::SQL::ERRORS->{ILLEGALVAL} = Links::language('ADD_ILLEGALVAL');
    local $GT::SQL::ERRORS->{UNIQUE}     = Links::language('ADD_UNIQUE');
    local $GT::SQL::ERRORS->{NOTNULL}    = Links::language('ADD_NOTNULL');

# Add the review.
    # The review will be added only if Review_email_2 is blank
    my $added_id = $input->{Review_email_2} ? 1 : $reviews->add($input);
    $input->{ReviewID} = $added_id;
    unless ($added_id) {
        my $error = "<ul><li>" . join("</li><li>", $reviews->error) . "</li></ul>";
        return { error => $error };
    }

# Format the date for sending email
    $input->{Review_Date} = GT::Date::date_transform($input->{Review_Date}, GT::Date::FORMAT_DATETIME, $CFG->{date_review_format});

# Mail the email.
    if ($CFG->{admin_email_review_add}) {
        Links::send_email('review_added.eml', { %{$USER || {}}, %$input, %$rec }, { admin_email => 1 }) or die "Unable to send mail: $GT::Mail::error";
    }

# Review added successfully, return to review_add_success page
    $CFG->{review_convert_br_tags} and $input->{Review_Contents} = _translate_html($input->{Review_Contents});
    return $input;
}

sub edit_review {
# ------------------------------------------------------------------
# Edit a review (only logged in users can edit their reviews)
#
    my $id = $IN->param('ID') || '';
    my $rid = $IN->param('ReviewID');

    my $mtl = Links::Build::build('title', Links::language('LINKS_REVIEW_EDIT'), "$CFG->{db_cgi_url}/review.cgi");

    if (!$CFG->{review_allow_modify}) {
        print $IN->header();
        print Links::SiteHTML::display('error', { error => Links::language('REVIEW_MODIFY_DENIED'), main_title_loop => $mtl });
        return;
    }

# Only logged in users can update their reviews or must redirect to the login page
    if (!$USER) {
        print $IN->redirect(Links::redirect_login_url('review'));
        return;
    }

# Check if we have a valid ID
    my $db  = $DB->table('Links');
    my $rec = $db->get($id);
    unless (($id =~ /^\d+$/) and $rec) {
        print $IN->header();
        print Links::SiteHTML::display('error', { error => Links::language('REVIEW_INVALIDID', $id), main_title_loop => $mtl });
        return;
    }
    $rec = Links::SiteHTML::tags('link', $rec);

# If a ReviewID isn't passed in and they have more than one review, then just edit the first review
    my $review = $DB->table('Reviews')->select({ Review_LinkID => $id, Review_Owner => $USER->{Username}, $rid ? (ReviewID => $rid) : () })->fetchrow_hashref;
    if (!$review) {
        print $IN->header();
        print Links::SiteHTML::display('error', { error => Links::language('REVIEW_NOT_EXISTS', $id), main_title_loop => $mtl });
        return;
    }
    elsif ($review->{Review_Validated} eq 'No') {
        print $IN->header();
        print Links::SiteHTML::display('error', { error => Links::language('REVIEW_ADD_WAIT', $id), main_title_loop => $mtl });
        return;
    }

# Has the review modify period passed?
    if ($CFG->{review_modify_timeout}) {
        my $oldfmt = GT::Date::date_get_format();
        GT::Date::date_set_format(GT::Date::FORMAT_DATETIME);
        my $timeout = GT::Date::date_get(time - $CFG->{review_modify_timeout} * 60);
        my $date = $review->{Review_ModifyDate} =~ /^0000-00-00 00:00:00/ ? $review->{Review_Date} : $review->{Review_ModifyDate};
        my $smaller = GT::Date::date_is_smaller($date, $timeout);
        GT::Date::date_set_format($oldfmt);
        if ($smaller) {
            print $IN->header();
            print Links::SiteHTML::display('error', { error => Links::language('REVIEW_MODIFY_TIMEOUT', $CFG->{review_modify_timeout}), main_title_loop => $mtl });
            return;
        }
    }

    my ($cat_id, $cat_name) = each %{$db->get_categories($id)};
    my %title = (
        title_loop   => Links::Build::build('title', "$cat_name/$rec->{Title}"),
        title        => sub { Links::Build::build('title_unlinked', "$cat_name/$rec->{Title}") },
        title_linked => sub { Links::Build::build('title_linked', "$cat_name/$rec->{Title}") }
    );

# If we have a review to update from a form
    if ($IN->param('update_this_review')) {
        my $results = $PLG->dispatch('update_this_review', \&_update_this_review, $rec);

# If we have error
        if (defined $results->{error}) {
            print $IN->header();
            print Links::SiteHTML::display('review_edit', { %$results, %$rec, %title, main_title_loop => $mtl });
        }
# Return to edit success page
        else {
            print $IN->header();
            print Links::SiteHTML::display('review_edit_success', { %$results, %$rec, %title, main_title_loop => $mtl });
        }
    }
# We are displaying an edit review form
    elsif ($IN->param('confirmed')) {
        print $IN->header();
        print Links::SiteHTML::display('review_edit', { %$rec, %$review, %title, main_title_loop => $mtl });
    }

# Else invalid action
    else {
        return review_search_results();
    }
}

sub _update_this_review {
# ------------------------------------------------------------------
# Edit this review
#
# Get our link record.
    my $rec   = shift;

# Get our form data and some default data.
    my $input = $IN->get_hash;
    my $reviews = $DB->table('Reviews');
    my $id    = $IN->param('ID');
    $input->{Review_LinkID} = $id;
    $input->{Review_Validated} = ($CFG->{review_auto_validate} == 1 and $USER or $CFG->{review_auto_validate} == 2) ? 'Yes' : 'No';
    $input->{Review_WasHelpful} = 0 ;
    $input->{Review_WasNotHelpful} = 0 ;
    $input->{Host} = $ENV{REMOTE_HOST} ? "$ENV{REMOTE_HOST} ($ENV{REMOTE_ADDR})" : $ENV{REMOTE_ADDR} ? $ENV{REMOTE_ADDR} : 'none';
    $input->{Referer} = $ENV{HTTP_REFERER} ? $ENV{HTTP_REFERER} : 'none';

# Get the review owner
    $input->{Review_Owner} = $USER->{Username};

# Check if this review is valid for this user
    my $rows = $reviews->get({ Review_LinkID => $id, Review_Owner => $USER->{Username}, Review_Validated => 'Yes' });
    return { error => Links::language('REVIEW_INVALID_UPDATE') } unless $rows;

# Make sure we have a valid rating.
    my $cols = $reviews->cols;
    if (exists $cols->{Review_Rating} and $cols->{Review_Rating}->{not_null} and ($input->{Review_Rating} !~ /^\d$/ or $input->{Review_Rating} < 1 or $input->{Review_Rating} > 5)) {
        return { error => Links::language('REVIEW_RATING', $input->{Review_Rating}) };
    }

# Has the review modify period passed?
    if ($CFG->{review_modify_timeout}) {
        my $oldfmt = GT::Date::date_get_format();
        GT::Date::date_set_format(GT::Date::FORMAT_DATETIME);
        my $timeout = GT::Date::date_get(time - $CFG->{review_modify_timeout} * 60);
        my $date = $rows->{Review_ModifyDate} =~ /^0000-00-00 00:00:00/ ? $rows->{Review_Date} : $rows->{Review_ModifyDate};
        my $smaller = GT::Date::date_is_smaller($date, $timeout);
        GT::Date::date_set_format($oldfmt);
        if ($smaller) {
            return { error => Links::language('REVIEW_MODIFY_TIMEOUT', $CFG->{review_modify_timeout}) };
        }
    }

# Set date review to today's date.
    Links::init_date();
    delete $input->{Review_Date};
    $input->{Review_ModifyDate} = GT::Date::date_get(time, GT::Date::FORMAT_DATETIME);

# Change the language.
    local $GT::SQL::ERRORS->{ILLEGALVAL} = Links::language('ADD_ILLEGALVAL');
    local $GT::SQL::ERRORS->{UNIQUE}     = Links::language('ADD_UNIQUE');
    local $GT::SQL::ERRORS->{NOTNULL}    = Links::language('ADD_NOTNULL');

# Update the record.
    $reviews->modify($input, { ReviewID => $input->{ReviewID} }) or return { error => $GT::SQL::error };

# Delete the review track from this ReviewID
    $DB->table('ClickTrack')->delete({ ReviewID => $input->{ReviewID}, ClickType => 'Review' }) or return { error => $GT::SQL::error };

# Format the date for sending email
    $input->{Review_Date} = GT::Date::date_transform($input->{Review_ModifyDate}, GT::Date::FORMAT_DATETIME, $CFG->{date_review_format});

# Mail the email.
    if ($CFG->{admin_email_review_mod}) {
        my %tags;
        foreach my $key (keys %$rows) {
            $tags{"Original_$key"} = $rows->{$key};
        }
        foreach my $key (keys %$input) {
            $tags{"New_$key"} = $input->{$key};
        }

        Links::send_email('review_modified.eml', { %$USER, %tags, %$rec }, { admin_email => 1 }) or die "Unable to send mail: $GT::Mail::error";
    }

# Review added successfully, return to review_add_success page
    $CFG->{review_convert_br_tags} and $input->{Review_Contents} = _translate_html($input->{Review_Contents});
    return $input;

}

sub helpful_review {
# ------------------------------------------------------------------
# Review was helpful or not
#
    my $reviewID = $IN->param('ReviewID');

    my $mtl = Links::Build::build('title', Links::language('LINKS_REVIEW'), "$CFG->{db_cgi_url}/review.cgi");

# Get our Reviews db object
    my $db = $DB->table('Reviews');
    my $rec = $db->get($reviewID);

    if (!$rec) {
        print $IN->header;
        print Links::SiteHTML::display('error', { error => Links::language('REVIEW_INVALIDID', $rec->{Review_Subject}), main_title_loop => $mtl });
        return;
    }

# Update the rating unless they have already voted.
    my $click_db = $DB->table('ClickTrack');
    my $rows = $click_db->count({ ReviewID => $rec->{ReviewID}, IP => $ENV{REMOTE_ADDR}, ClickType => 'Review' });
    if ($rows) {
        print $IN->header;
        print Links::SiteHTML::display('error', { error => Links::language('REVIEW_VOTED', $rec->{Review_Subject}), main_title_loop => $mtl });
        return;
    }
    else {
        eval {
            $click_db->insert({ LinkID => $rec->{Review_LinkID}, ReviewID => $rec->{ReviewID}, IP => $ENV{REMOTE_ADDR}, ClickType => 'Review', Created => \"NOW()" });
# Update the Timestmp for the link so that the detailed page gets rebuilt with build changed
            $DB->table('Links')->update({ Timestmp => \'NOW()' }, { ID => $rec->{Review_LinkID} });
        };
    }

# Change the language.
    local $GT::SQL::ERRORS->{ILLEGALVAL} = Links::language('ADD_ILLEGALVAL');
    local $GT::SQL::ERRORS->{UNIQUE}     = Links::language('ADD_UNIQUE');
    local $GT::SQL::ERRORS->{NOTNULL}    = Links::language('ADD_NOTNULL');

# If this review was helpful
    if ($IN->param('yes')) {
        if (!$db->update({ Review_WasHelpful => $rec->{Review_WasHelpful} + 1 }, { ReviewID => $reviewID })) {
            print $IN->header;
            print Links::SiteHTML::display('error', { error => $db->error, main_title_loop => $mtl });
            return;
        }
    }
    else {
        if (!$db->update({ Review_WasNotHelpful => $rec->{Review_WasNotHelpful} + 1 }, { ReviewID => $reviewID })) {
            print $IN->header;
            print Links::SiteHTML::display('error', { error => $db->error, main_title_loop => $mtl });
            return;
        }
    }
    return review_search_results();
}

sub _translate_html {
# -------------------------------------------------------------------
# Translate contents to html format
#
    my $html = shift;
    $html = GT::CGI::html_escape($html);
    $html =~ s,\r?\n,<br />,g;
    return $html;
}

1;
