#!/usr/bin/perl -w -I../perllib
# questionnaire.cgi:
# Questionnaire for problem creators
#
# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved.
# Email: matthew@mysociety.org. WWW: http://www.mysociety.org
#
# $Id: questionnaire.cgi,v 1.53 2009-12-08 17:43:13 louise Exp $
use strict;
use Standard;
use Error qw(:try);
use CrossSell;
use mySociety::AuthToken;
use mySociety::Locale;
use mySociety::MaPit;
use mySociety::Web qw(ent);
sub main {
my $q = shift;
my $out = '';
if ($q->param('submit')) {
$out = submit_questionnaire($q);
} else {
$out = display_questionnaire($q);
}
print Page::header($q, title=>_('Questionnaire'));
print $out;
print Page::footer($q);
}
Page::do_fastcgi(\&main);
sub check_stuff {
my $q = shift;
my $cobrand = Page::get_cobrand($q);
my $id = mySociety::AuthToken::retrieve('questionnaire', $q->param('token'));
throw Error::Simple(_("I'm afraid we couldn't validate that token. If you've copied the URL from an email, please check that you copied it exactly.\n")) unless $id;
my $questionnaire = dbh()->selectrow_hashref(
'select id, problem_id, whenanswered from questionnaire where id=?', {}, $id);
my $problem_id = $questionnaire->{problem_id};
my $problem_url = Cobrand::url($cobrand, "/report/$problem_id", $q);
my $contact_url = Cobrand::url($cobrand, "/contact", $q);
throw Error::Simple(sprintf(_("You have already answered this questionnaire. If you have a question, please get in touch, or view your problem.\n"), $contact_url, $problem_url)) if $questionnaire->{whenanswered};
my $problem = dbh()->selectrow_hashref(
"select *, extract(epoch from confirmed) as time, extract(epoch from whensent-confirmed) as whensent
from problem where id=? and state in ('confirmed','fixed')", {}, $problem_id);
throw Error::Simple(_("I'm afraid we couldn't locate your problem in the database.\n")) unless $problem;
my $num_questionnaire = dbh()->selectrow_array(
'select count(*) from questionnaire where problem_id=?', {}, $problem_id);
my $answered_ever_reported = dbh()->selectrow_array(
'select id from questionnaire where problem_id in (select id from problem where email=?) and ever_reported is not null', {}, $problem->{email});
return ($questionnaire, $problem, $num_questionnaire, $answered_ever_reported);
}
sub submit_questionnaire {
my $q = shift;
my $cobrand = Page::get_cobrand($q);
my $cobrand_data = Cobrand::extra_data($cobrand, $q);
my @vars = qw(token id been_fixed reported update another);
my %input = map { $_ => scalar $q->param($_) || '' } @vars;
my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars;
my ($error, $questionnaire, $num_questionnaire, $problem, $answered_ever_reported);
try {
($questionnaire, $problem, $num_questionnaire, $answered_ever_reported) = check_stuff($q);
} catch Error::Simple with {
my $e = shift;
$error = $e;
};
if ($error) {
my %vars = (heading => _('Questionnaire'),
error => $error->stringify());
my $template_error = Page::template_include('error', $q, Page::template_root($q), %vars);
return $template_error if $template_error;
return $error;
}
# EHA questionnaires done for you
if ($q->{site} eq 'emptyhomes') {
$input{another} = $num_questionnaire==1 ? 'Yes' : 'No';
}
my @errors;
push @errors, _('Please state whether or not the problem has been fixed') unless $input{been_fixed};
my $ask_ever_reported = Cobrand::ask_ever_reported($cobrand);
if ($ask_ever_reported) {
push @errors, _('Please say whether you\'ve ever reported a problem to your council before') unless $input{reported} || $answered_ever_reported;
}
push @errors, _('Please indicate whether you\'d like to receive another questionnaire')
if ($input{been_fixed} eq 'No' || $input{been_fixed} eq 'Unknown') && !$input{another};
push @errors, _('Please provide some explanation as to why you\'re reopening this report')
if $input{been_fixed} eq 'No' && $problem->{state} eq 'fixed' && !$input{update};
return display_questionnaire($q, @errors) if @errors;
my $fh = $q->upload('photo');
my $image;
if ($fh) {
my $err = Page::check_photo($q, $fh);
push @errors, $err if $err;
try {
$image = Page::process_photo($fh) unless $err;
} catch Error::Simple with {
my $e = shift;
push(@errors, "That image doesn't appear to have uploaded correctly ($e), please try again.");
};
}
push @errors, _('Please provide some text as well as a photo')
if $image && !$input{update};
return display_questionnaire($q, @errors) if @errors;
my $new_state = '';
$new_state = 'fixed' if $input{been_fixed} eq 'Yes' && $problem->{state} eq 'confirmed';
$new_state = 'confirmed' if $input{been_fixed} eq 'No' && $problem->{state} eq 'fixed';
# Record state change, if there was one
dbh()->do("update problem set state=?, lastupdate=ms_current_timestamp()
where id=?", {}, $new_state, $problem->{id})
if $new_state;
# If it's not fixed and they say it's still not been fixed, record time update
dbh()->do("update problem set lastupdate=ms_current_timestamp()
where id=?", {}, $problem->{id})
if $input{been_fixed} eq 'No' && $problem->{state} eq 'confirmed';
# Record questionnaire response
my $reported = $input{reported}
? ($input{reported} eq 'Yes' ? 't' : ($input{reported} eq 'No' ? 'f' : undef))
: undef;
dbh()->do('update questionnaire set whenanswered=ms_current_timestamp(),
ever_reported=?, old_state=?, new_state=? where id=?', {},
$reported, $problem->{state}, $input{been_fixed} eq 'Unknown'
? 'unknown'
: ($new_state ? $new_state : $problem->{state}),
$questionnaire->{id});
# Record an update if they've given one, or if there's a state change
my $name = $problem->{anonymous} ? undef : $problem->{name};
my $update = $input{update} ? $input{update} : _('Questionnaire filled in by problem reporter');
Utils::workaround_pg_bytea("insert into comment
(problem_id, name, email, website, text, state, mark_fixed, mark_open, photo, lang, cobrand, cobrand_data)
values (?, ?, ?, '', ?, 'confirmed', ?, ?, ?, ?, ?, ?)", 7,
$problem->{id}, $name, $problem->{email}, $update,
$new_state eq 'fixed' ? 't' : 'f', $new_state eq 'confirmed' ? 't' : 'f',
$image, $mySociety::Locale::lang, $cobrand, $cobrand_data
)
if $new_state || $input{update};
# If they've said they want another questionnaire, mark as such
dbh()->do("update problem set send_questionnaire = 't' where id=?", {}, $problem->{id})
if ($input{been_fixed} eq 'No' || $input{been_fixed} eq 'Unknown') && $input{another} eq 'Yes';
dbh()->commit();
my $out;
my $message;
my $advert_outcome = 1;
if ($input{been_fixed} eq 'Unknown') {
$message = _(<
Would you like to receive another questionnaire in 4 weeks, reminding you to check the status?