aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports/New.pm371
-rw-r--r--templates/web/default/reports/new/fill_in_details.html59
2 files changed, 384 insertions, 46 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Reports/New.pm b/perllib/FixMyStreet/App/Controller/Reports/New.pm
index cd2c78bca..10a10b55d 100644
--- a/perllib/FixMyStreet/App/Controller/Reports/New.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports/New.pm
@@ -9,6 +9,7 @@ use Encode;
use Sort::Key qw(keysort);
use List::MoreUtils qw(uniq);
use HTML::Entities;
+use mySociety::MaPit;
=head1 NAME
@@ -76,14 +77,22 @@ sub report_new : Path : Args(0) {
# FIXME - deal with partial reports here
# work out the location for this report and do some checks
- $c->forward('determine_location') || return;
- $c->forward('check_councils') || return;
+ return
+ unless $c->forward('determine_location')
+ && $c->forward('check_councils');
# create a problem from the submitted details
$c->stash->{template} = "reports/new/fill_in_details.html";
$c->forward('setup_categories_and_councils');
- $c->forward('prepare_report');
$c->forward('generate_map');
+
+ # deal with the user and report and check both are happy
+ return
+ unless $c->forward('process_user')
+ && $c->forward('process_report')
+ && $c->forward('check_form_submitted')
+ && $c->forward('check_for_errors')
+ && $c->forward('save_user_and_report');
}
=head2 determine_location
@@ -102,14 +111,28 @@ sub determine_location : Private {
|| $c->forward('determine_location_from_coords')
|| $c->forward('determine_location_from_pc');
+ # These should be set now
+ my $lat = $c->stash->{latitude};
+ my $lon = $c->stash->{longitude};
+
# Check this location is okay to be displayed for the cobrand
my ( $success, $error_msg ) = $c->cobrand->council_check( #
- { lat => $c->stash->{latitude}, lon => $c->stash->{longitude} },
+ { lat => $lat, lon => $lon },
'submit_problem'
);
+ # If in UK and we have a lat,lon coocdinate check it is in UK
+ # FIXME - is this a redundant check as we already see if report has a body
+ # to handle it?
+ if ( !$error_msg && $c->config->{COUNTRY} eq 'GB' ) {
+ eval { Utils::convert_latlon_to_en( $lat, $lon ); };
+ $error_msg =
+ _( "We had a problem with the supplied co-ordinates - outside the UK?"
+ ) if $@;
+ }
+
# all good
- return 1 if $success;
+ return 1 if !$error_msg;
# show error
$c->stash->{pc_error} = $error_msg;
@@ -368,7 +391,35 @@ sub setup_categories_and_councils : Private {
$c->stash->{missing_names} = @missing_names;
}
-=head2 prepare_report
+=head2 process_user
+
+Load user from the database or prepare a new one.
+
+=cut
+
+sub process_user : Private {
+ my ( $self, $c ) = @_;
+
+ # FIXME - If user already logged in use them regardless
+
+ # Extract all the params to a hash to make them easier to work with
+ my %params = #
+ map { $_ => scalar $c->req->param($_) } #
+ ( 'email', 'name', 'phone', );
+
+ my $report_user =
+ $c->model('DB::User')->find_or_new( { email => $params{email} } );
+
+ # set the user's name and phone (if given)
+ $report_user->name( $params{name} );
+ $report_user->phone( $params{phone} ) if $params{phone};
+
+ $c->stash->{report_user} = $report_user;
+
+ return 1;
+}
+
+=head2 process_report
Looking at the parameters passed in create a new item and return it. Does not
save anything to the database. If no item can be created (ie no information
@@ -376,24 +427,316 @@ provided) returns undef.
=cut
-sub prepare_report : Private {
+sub _cleanup_text {
+ my $input = shift || '';
+
+ # lowercase everything if looks like it might be SHOUTING
+ $input = lc $input if $input !~ /[a-z]/;
+
+ # Start with a capital
+ $input = ucfirst $input;
+
+ # clean up language and tradmarks
+ for ($input) {
+
+ # shit -> poo
+ s{\bdog\s*shit\b}{dog poo}ig;
+
+ # 'portakabin' to '[portable cabin]' (and variations)
+ s{\b(porta)\s*([ck]abin|loo)\b}{[$1ble $2]}ig;
+ s{kabin\]}{cabin\]}ig;
+ }
+
+ return $input;
+}
+
+sub process_report : Private {
my ( $self, $c ) = @_;
+ # Extract all the params to a hash to make them easier to work with
+ my %params = #
+ map { $_ => scalar $c->req->param($_) } #
+ (
+ 'title', 'detail', 'pc', #
+ 'name', 'may_show_name', #
+ 'council', 'category', #
+ 'partial', 'skipped', 'upload_fileid', #
+ );
+
# create a new report, but don't save it yet
- my $report = $c->model('DB::Problem')->new(
- {
- latitude => $c->stash->{latitude},
- longitude => $c->stash->{longitude},
+ my $report = $c->model('DB::Problem')->new( {} );
+
+ # Enter the location
+ $report->postcode( $params{pc} );
+ $report->latitude( $c->stash->{latitude} );
+ $report->longitude( $c->stash->{longitude} );
+
+ # set some simple bool values (note they get inverted)
+ $report->used_map( $params{skipped} ? 0 : 1 );
+ $report->anonymous( $params{may_show_name} ? 0 : 1 );
+
+ # clean up text before setting
+ $report->title( _cleanup_text( $params{title} ) );
+ $report->detail( _cleanup_text( $params{detail} ) );
+
+ # set these straight from the params
+ $report->name( $params{name} );
+ $report->category( $params{category} );
+
+ # my $fh = $q->upload('photo');
+ # if ($fh) {
+ # my $err = Page::check_photo( $q, $fh );
+ # $field_errors{photo} = $err if $err;
+ # }
+
+ my $mapit_query =
+ sprintf( "4326/%s,%s", $report->longitude, $report->latitude );
+ my $areas = mySociety::MaPit::call( 'point', $mapit_query );
+ $report->areas( ',' . join( ',', sort keys %$areas ) . ',' );
+
+ # council = -1 - none
+ # council = 1,2,3 - all found
+ # council = 1,2|3,4 - found|missing
+ if ( $params{council} =~ m{^\d} ) {
+
+ my ( $found_council_str, $missing_council_str ) =
+ split( m{\|}, $params{council}, 2 );
+
+ my @area_types = $c->cobrand->area_types();
+ my %area_types_lookup = map { $_ => 1 } @area_types;
+
+ my %councils =
+ map { $_ => 1 } #
+ grep { $area_types_lookup{ $areas->{$_}->type } } #
+ keys %$areas;
+
+ my @input_councils = split /,|\|/, $params{council};
+
+ foreach (@input_councils) {
+ if ( !$councils{$_} ) {
+ push( @errors, _('That location is not part of that council') );
+ last;
+ }
}
- );
- # set some simple values
- $report->used_map( $c->req->param('skipped') ? 0 : 1 );
+ if ($missing_council_str) {
+ $input{council} =~ $found_council_str;
+ @input_councils = split /,/, $input{council};
+ }
+
+ # Check category here, won't be present if council is -1
+ my @valid_councils = @input_councils;
+ if ( $input{category} && $q->{site} ne 'emptyhomes' ) {
+ my $categories = select_all(
+ "select area_id from contacts
+ where deleted='f' and area_id in ("
+ . $input{council} . ') and category = ?', $input{category}
+ );
+ $field_errors{category} = _('Please choose a category')
+ unless @$categories;
+ @valid_councils = map { $_->{area_id} } @$categories;
+ foreach my $c (@valid_councils) {
+ if ( $no_details =~ /$c/ ) {
+ push( @errors, _('We have details for that council') );
+ $no_details =~ s/,?$c//;
+ }
+ }
+ }
+ $input{council} = join( ',', @valid_councils ) . $no_details;
+ }
+
+# my $image;
+# if ($fh) {
+# try {
+# $image = Page::process_photo($fh);
+# }
+# catch Error::Simple with {
+# my $e = shift;
+# $field_errors{photo} = sprintf(
+# _(
+# "That image doesn't appear to have uploaded correctly (%s), please try again."
+# ),
+# $e
+# );
+# };
+# }
+#
+# if ( $input{upload_fileid} ) {
+# open FP,
+# mySociety::Config::get('UPLOAD_CACHE') . $input{upload_fileid};
+# $image = join( '', <FP> );
+# close FP;
+# }
+#
+# return display_form( $q, \@errors, \%field_errors )
+# if ( @errors || scalar keys %field_errors );
+#
+# delete $input{council} if $input{council} eq '-1';
+# my $used_map = $input{skipped} ? 'f' : 't';
+# $input{category} = _('Other') unless $input{category};
+# my ( $id, $out );
+# my $cobrand_data = Cobrand::extra_problem_data( $cobrand, $q );
+# if ( my $token = $input{partial} ) {
+# my $id = mySociety::AuthToken::retrieve( 'partial', $token );
+# if ($id) {
+# dbh()->do(
+# "update problem set postcode=?, latitude=?, longitude=?, title=?, detail=?,
+# name=?, email=?, phone=?, state='confirmed', council=?, used_map='t',
+# anonymous=?, category=?, areas=?, cobrand=?, cobrand_data=?, confirmed=ms_current_timestamp(),
+# lastupdate=ms_current_timestamp() where id=?", {},
+# $input{pc}, $input{latitude}, $input{longitude},
+# $input{title}, $input{detail}, $input{name}, $input{email},
+# $input{phone}, $input{council},
+# $input{anonymous} ? 'f' : 't',
+# $input{category}, $areas, $cobrand, $cobrand_data, $id
+# );
+# Utils::workaround_pg_bytea(
+# 'update problem set photo=? where id=?',
+# 1, $image, $id )
+# if $image;
+# dbh()->commit();
+# $out = $q->p(
+# sprintf(
+# _(
+# 'You have successfully confirmed your report and you can now <a href="%s">view it on the site</a>.'
+# ),
+# "/report/$id"
+# )
+# );
+# my $display_advert = Cobrand::allow_crosssell_adverts($cobrand);
+# if ($display_advert) {
+# $out .=
+# CrossSell::display_advert( $q, $input{email},
+# $input{name} );
+# }
+# }
+# else {
+# $out = $q->p(
+# 'There appears to have been a problem updating the details of your report.
+# Please <a href="/contact">let us know what went on</a> and we\'ll look into it.'
+# );
+# }
+# }
+# else {
+# $id = dbh()->selectrow_array("select nextval('problem_id_seq');");
+# Utils::workaround_pg_bytea(
+# "insert into problem
+# (id, postcode, latitude, longitude, title, detail, name,
+# email, phone, photo, state, council, used_map, anonymous, category, areas, lang, cobrand, cobrand_data)
+# values
+# (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'unconfirmed', ?, ?, ?, ?, ?, ?, ?, ?)",
+# 10,
+# $id, $input{pc}, $input{latitude}, $input{longitude},
+# $input{title},
+# $input{detail}, $input{name}, $input{email}, $input{phone},
+# $image,
+# $input{council}, $used_map, $input{anonymous} ? 'f' : 't',
+# $input{category},
+# $areas, $mySociety::Locale::lang, $cobrand, $cobrand_data
+# );
+# my %h = ();
+# $h{title} = $input{title};
+# $h{detail} = $input{detail};
+# $h{name} = $input{name};
+# my $base = Page::base_url_with_lang( $q, undef, 1 );
+# $h{url} =
+# $base . '/P/' . mySociety::AuthToken::store( 'problem', $id );
+# dbh()->commit();
+#
+# $out =
+# Page::send_email( $q, $input{email}, $input{name}, 'problem',
+# %h );
+#
+# }
+# return $out;
+# }
$c->stash->{report} = $report;
return 1;
}
+=head2 check_form_submitted
+
+ $bool = $c->forward('check_form_submitted');
+
+Returns true if the form has been submitted, false if not. Determines this based
+on the presence of the C<submit_problem> parameter.
+
+=cut
+
+sub check_form_submitted : Private {
+ my ( $self, $c ) = @_;
+ return !!$c->req->param('submit_problem');
+}
+
+=head2 check_for_errors
+
+Examine the user and the report for errors. If found put them on stash and
+return false.
+
+=cut
+
+sub check_for_errors : Private {
+ my ( $self, $c ) = @_;
+
+ # let the model check for errors
+ my %field_errors = (
+ %{ $c->stash->{report_user}->check_for_errors },
+ %{ $c->stash->{report}->check_for_errors }
+ );
+
+ # all good if no errors
+ return 1 unless scalar keys %field_errors;
+
+ $c->stash->{field_errors} = \%field_errors;
+
+ use Data::Dumper;
+ local $Data::Dumper::Sortkeys = 1;
+ warn Dumper( \%field_errors );
+
+ return;
+}
+
+=head2 save_user_and_report
+
+Save the user and the report.
+
+Be smart about the user - only set the name and phone if user did not exist
+before or they are currently logged in. Otherwise discard any changes.
+
+Save the problem as unconfirmed. FIXME - change this behaviour with respect to
+the user's logged in status.
+
+=cut
+
+sub save_user_and_report : Private {
+ my ( $self, $c ) = @_;
+ my $report_user = $c->stash->{report_user};
+ my $report = $c->stash->{report};
+
+ # Save or update the user if appropriate
+ if ( !$report_user->in_storage ) {
+ $report_user->insert(); # FIXME - set user state to 'unconfirmed'
+ }
+ elsif ( $c->user && $report_user->id == $c->user->id ) {
+ $report_user->update();
+ $report->confirmed(1); # as we know the user is genuine
+ }
+ else {
+
+ # user exists and we are not logged in as them. Throw away changes to
+ # the name and phone. FIXME - propagate changes using tokens.
+ $report_user->discard_changes();
+ }
+
+ # add the user to the report
+ $report->user($report_user);
+
+ # save the report;
+ $report->insert();
+
+}
+
=head2 generate_map
Add the html needed to for the map to the stash.
diff --git a/templates/web/default/reports/new/fill_in_details.html b/templates/web/default/reports/new/fill_in_details.html
index ca49571b8..daa73084c 100644
--- a/templates/web/default/reports/new/fill_in_details.html
+++ b/templates/web/default/reports/new/fill_in_details.html
@@ -28,10 +28,6 @@
[% INCLUDE 'reports/new/fill_in_details_text.html' %]
[% END %]
-
-
-
-
<input type="hidden" name="latitude" value="[% latitude | html %]">
<input type="hidden" name="longitude" value="[% longitude | html %]">
@@ -41,11 +37,6 @@
[% '</ul>' IF loop.last %]
[% END %]
-
-<p>FORM</p>
-
-
-
<div id="problem_form">
[% INCLUDE 'reports/new/form_heading.html' %]
@@ -56,31 +47,35 @@
-<!-- {{ if ( $field_errors{category}) {
- "<div class='form-error'>$field_errors{category}</div>";
-} }} -->
+[% IF field_errors.council %]
+ <div class='form-error'>[% field_errors.council %]</div>
+[% END %]
-<div class="form-field">
-<label for="category">[% category_label | html %]</label>
-<select name="category">
-[% FOREACH cat_op IN category_options %]
- <option value="[% cat_op | html %]">[% cat_op | html %]</option>
+[% IF field_errors.category %]
+ <div class='form-error'>[% field_errors.category %]</div>
[% END %]
-</select>
+
+<div class="form-field">
+ <label for="category">[% category_label | html %]</label>
+ <select name="category">
+ [%- FOREACH cat_op IN category_options %]
+ <option value="[% cat_op | html %]"[% ' selected' IF report.category == cat_op %]>[% cat_op | html %]</option>
+ [%- END %]
+ </select>
</div>
-<!-- {{ if ( $field_errors{title}) {
- "<div class='form-error'>$field_errors{title}</div>";
-} }} -->
+[% IF field_errors.title %]
+ <div class='form-error'>[% field_errors.title %]</div>
+[% END %]
<div class="form-field">
<label for="form_title">[% loc('Subject:') %]</label>
<input type="text" value="[% report.title | html %]" name="title" id="form_title" size="25">
</div>
-<!-- {{ if ( $field_errors{detail}) {
- "<div class='form-error'>$field_errors{detail}</div>";
-} }} -->
+[% IF field_errors.detail %]
+ <div class='form-error'>[% field_errors.detail %]</div>
+[% END %]
<div class="form-field">
<label for="form_detail">[% loc('Details:') %]</label>
@@ -96,9 +91,9 @@
<!-- $vars{photo_label} = _('Photo:'); -->
<!-- {{ $photo_field }} -->
-<!-- {{ if ( $field_errors{name}) {
- "<div class='form-error'>$field_errors{name}</div>";
-} }} -->
+[% IF field_errors.name %]
+ <div class='form-error'>[% field_errors.name %]</div>
+[% END %]
<div class='form-field'>
<label for="form_name">[% loc('Name:') %]</label>
@@ -108,17 +103,17 @@
<div class="checkbox">
- <!-- FIXME - sot sure what the title connection is with marking report anonymous -->
- <input type="checkbox" name="may_show_name" id="form_may_show_name" value="1"[% ' checked' IF !report.anonymous %]>
+ [%# if there is nothing in the title field then set check box as default on form %]
+ <input type="checkbox" name="may_show_name" id="form_may_show_name" value="1"[% ' checked' IF !report.anonymous || !report.title %]>
<!-- FIXME - empythomes should be 'Can we show your name on the site?'-->
<label for="form_may_show_name">[% loc('Can we show your name publicly?') %]</label>
<small>[% loc('(we never show your email address or phone number)') %]</small>
</div>
-<!-- {{ if ( $field_errors{email}) {
- "<div class='form-error'>$field_errors{email}</div>";
-} }} -->
+[% IF field_errors.email %]
+ <div class='form-error'>[% field_errors.email %]</div>
+[% END %]
<div class="form-field">
<label for="form_email">[% loc('Email:') %]</label>