aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/App/Controller/Alert.pm
diff options
context:
space:
mode:
authorMatthew Somerville <matthew@mysociety.org>2011-06-10 14:56:00 +0100
committerMatthew Somerville <matthew@mysociety.org>2011-06-10 14:56:00 +0100
commit391ca1c469d93bb2c4798cc15e56fc495b5e80dd (patch)
tree6bc90fae589de824095e668fbf510ef259935729 /perllib/FixMyStreet/App/Controller/Alert.pm
parent7c96f8ec61d6eddc211f3f0e71cdb276c6a5f773 (diff)
parent860383f0de3287b0666d64a3ffff3db3a0f087ae (diff)
Merge branch 'migrate_to_catalyst' into reportemptyhomes
Diffstat (limited to 'perllib/FixMyStreet/App/Controller/Alert.pm')
-rw-r--r--perllib/FixMyStreet/App/Controller/Alert.pm506
1 files changed, 506 insertions, 0 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Alert.pm b/perllib/FixMyStreet/App/Controller/Alert.pm
new file mode 100644
index 000000000..e7eab09b8
--- /dev/null
+++ b/perllib/FixMyStreet/App/Controller/Alert.pm
@@ -0,0 +1,506 @@
+package FixMyStreet::App::Controller::Alert;
+use Moose;
+use namespace::autoclean;
+
+BEGIN { extends 'Catalyst::Controller'; }
+
+use mySociety::EmailUtil qw(is_valid_email);
+
+=head1 NAME
+
+FixMyStreet::App::Controller::Alert - Catalyst Controller
+
+=head1 DESCRIPTION
+
+Catalyst Controller.
+
+=head1 METHODS
+
+=cut
+
+=head2 alert
+
+Show the alerts page
+
+=cut
+
+sub index : Path('') : Args(0) {
+ my ( $self, $c ) = @_;
+
+ $c->stash->{cobrand_form_elements} = $c->cobrand->form_elements('alerts');
+
+ unless ( $c->req->referer && $c->req->referer =~ /fixmystreet\.com/ ) {
+ $c->forward( 'add_recent_photos', [10] );
+ }
+}
+
+sub list : Path('list') : Args(0) {
+ my ( $self, $c ) = @_;
+
+ return
+ unless $c->forward('setup_request')
+ && $c->forward('prettify_pc')
+ && $c->forward('determine_location')
+ && $c->forward( 'add_recent_photos', [5] )
+ && $c->forward('setup_council_rss_feeds')
+ && $c->forward('setup_coordinate_rss_feeds');
+}
+
+=head2 subscribe
+
+Target for subscribe form
+
+=cut
+
+sub subscribe : Path('subscribe') : Args(0) {
+ my ( $self, $c ) = @_;
+
+ if ( $c->req->param('rss') ) {
+ $c->detach('rss');
+ }
+ # if it exists then it's been submitted so we should
+ # go to subscribe email and let it work out the next step
+ elsif ( exists $c->req->params->{'rznvy'} ) {
+ $c->detach('subscribe_email');
+ }
+ elsif ( $c->req->params->{'id'} ) {
+ $c->go('updates');
+ }
+
+ # shouldn't get to here but if we have then do something sensible
+ $c->go('index');
+}
+
+=head2 rss
+
+Redirects to relevant RSS feed
+
+=cut
+
+sub rss : Private {
+ my ( $self, $c ) = @_;
+ my $feed = $c->req->params->{feed};
+
+ unless ($feed) {
+ $c->stash->{errors} = [ _('Please select the feed you want') ];
+ $c->go('list');
+ }
+
+ my $url;
+ if ( $feed =~ /^area:(?:\d+:)+(.*)$/ ) {
+ ( my $id = $1 ) =~ tr{:_}{/+};
+ $url = $c->cobrand->base_url() . '/rss/area/' . $id;
+ $c->res->redirect($url);
+ }
+ elsif ( $feed =~ /^(?:council|ward):(?:\d+:)+(.*)$/ ) {
+ ( my $id = $1 ) =~ tr{:_}{/+};
+ $url = $c->cobrand->base_url() . '/rss/reports/' . $id;
+ $c->res->redirect($url);
+ }
+ elsif ( $feed =~ /^local:([\d\.-]+):([\d\.-]+)$/ ) {
+ $url = $c->cobrand->base_url() . '/rss/l/' . $1 . ',' . $2;
+ $c->res->redirect($url);
+ }
+ else {
+ $c->stash->{errors} = [ _('Illegal feed selection') ];
+ $c->go('list');
+ }
+}
+
+=head2 subscribe_email
+
+Sign up to email alerts
+
+=cut
+
+sub subscribe_email : Private {
+ my ( $self, $c ) = @_;
+
+ my $type = $c->req->param('type');
+ $c->stash->{email_type} = 'alert';
+
+ my @errors;
+ push @errors, _('Please enter a valid email address')
+ unless is_valid_email( $c->req->param('rznvy') );
+ push @errors, _('Please select the type of alert you want')
+ if $type && $type eq 'local' && !$c->req->param('feed');
+ if (@errors) {
+ $c->stash->{errors} = \@errors;
+ $c->go('updates') if $type && $type eq 'updates';
+ $c->go('list') if $type && $type eq 'local';
+ $c->go('index');
+ }
+
+ my $email = $c->req->param('rznvy');
+ $c->stash->{email} = $email;
+ $c->forward('process_user');
+
+ if ( $type eq 'updates' ) {
+ $c->forward('set_update_alert_options');
+ }
+ elsif ( $type eq 'local' ) {
+ $c->forward('set_local_alert_options');
+ }
+ else {
+ $c->detach( '/page_error_404_not_found', [ 'Invalid type' ] );
+ }
+
+ $c->forward('create_alert');
+ if ( $c->stash->{alert}->confirmed ) {
+ $c->stash->{confirm_type} = 'created';
+ $c->stash->{template} = 'tokens/confirm_alert.html';
+ } else {
+ $c->forward('send_confirmation_email');
+ }
+}
+
+sub updates : Path('updates') : Args(0) {
+ my ( $self, $c ) = @_;
+
+ $c->stash->{email} = $c->req->param('rznvy');
+ $c->stash->{problem_id} = $c->req->param('id');
+ $c->stash->{cobrand_form_elements} = $c->cobrand->form_elements('alerts');
+}
+
+=head2 confirm
+
+Confirm signup to or unsubscription from an alert. Forwarded here from Tokens.
+
+=cut
+
+sub confirm : Private {
+ my ( $self, $c ) = @_;
+
+ my $alert = $c->stash->{alert};
+
+ if ( $c->stash->{confirm_type} eq 'subscribe' ) {
+ $alert->confirm();
+ }
+ elsif ( $c->stash->{confirm_type} eq 'unsubscribe' ) {
+ $alert->disable();
+ }
+}
+
+=head2 create_alert
+
+Take the alert options from the stash and use these to create a new
+alert. If it finds an existing alert that's the same then use that
+
+=cut
+
+sub create_alert : Private {
+ my ( $self, $c ) = @_;
+
+ my $options = $c->stash->{alert_options};
+
+ my $alert = $c->model('DB::Alert')->find($options);
+
+ unless ($alert) {
+ $options->{cobrand} = $c->cobrand->moniker();
+ $options->{cobrand_data} = $c->cobrand->extra_update_data();
+ $options->{lang} = $c->stash->{lang_code};
+
+ if ( $c->user && $c->stash->{alert_user}->in_storage && $c->user->id == $c->stash->{alert_user}->id ) {
+ $options->{confirmed} = 1;
+ }
+
+ $alert = $c->model('DB::Alert')->new($options);
+ $alert->insert();
+ }
+
+ $c->stash->{alert} = $alert;
+}
+
+=head2 set_update_alert_options
+
+Set up the options in the stash required to create a problem update alert
+
+=cut
+
+sub set_update_alert_options : Private {
+ my ( $self, $c ) = @_;
+
+ my $report_id = $c->req->param('id');
+
+ my $options = {
+ user => $c->stash->{alert_user},
+ alert_type => 'new_updates',
+ parameter => $report_id,
+ };
+
+ $c->stash->{alert_options} = $options;
+}
+
+=head2 set_local_alert_options
+
+Set up the options in the stash required to create a local problems alert
+
+=cut
+
+sub set_local_alert_options : Private {
+ my ( $self, $c ) = @_;
+
+ my $feed = $c->req->param('feed');
+
+ my ( $type, @params, $alert );
+ if ( $feed =~ /^area:(?:\d+:)?(\d+)/ ) {
+ $type = 'area_problems';
+ push @params, $1;
+ }
+ elsif ( $feed =~ /^council:(\d+)/ ) {
+ $type = 'council_problems';
+ push @params, $1, $1;
+ }
+ elsif ( $feed =~ /^ward:(\d+):(\d+)/ ) {
+ $type = 'ward_problems';
+ push @params, $1, $2;
+ }
+ elsif ( $feed =~
+ m{ \A local: ( [\+\-]? \d+ \.? \d* ) : ( [\+\-]? \d+ \.? \d* ) }xms )
+ {
+ $type = 'local_problems';
+ push @params, $2, $1; # Note alert parameters are lon,lat
+ }
+
+ my $options = {
+ user => $c->stash->{alert_user},
+ alert_type => $type
+ };
+
+ if ( scalar @params == 1 ) {
+ $options->{parameter} = $params[0];
+ }
+ elsif ( scalar @params == 2 ) {
+ $options->{parameter} = $params[0];
+ $options->{parameter2} = $params[1];
+ }
+
+ $c->stash->{alert_options} = $options;
+}
+
+=head2 send_confirmation_email
+
+Generate a token and send out an alert subscription confirmation email and
+then display confirmation page.
+
+=cut
+
+sub send_confirmation_email : Private {
+ my ( $self, $c ) = @_;
+
+ my $token = $c->model("DB::Token")->create(
+ {
+ scope => 'alert',
+ data => {
+ id => $c->stash->{alert}->id,
+ type => 'subscribe',
+ email => $c->stash->{alert}->user->email
+ }
+ }
+ );
+
+ $c->stash->{token_url} = $c->uri_for_email( '/A', $token->token );
+
+ $c->send_email( 'alert-confirm.txt', { to => $c->stash->{alert}->user->email } );
+
+ $c->stash->{template} = 'email_sent.html';
+}
+
+=head2 prettify_pc
+
+This will canonicalise and prettify the postcode and stick a pretty_pc and pretty_pc_text in the stash.
+
+=cut
+
+sub prettify_pc : Private {
+ my ( $self, $c ) = @_;
+
+ my $pretty_pc = $c->req->params->{'pc'};
+
+ if ( mySociety::PostcodeUtil::is_valid_postcode( $c->req->params->{'pc'} ) )
+ {
+ $pretty_pc = mySociety::PostcodeUtil::canonicalise_postcode(
+ $c->req->params->{'pc'} );
+ my $pretty_pc_text = $pretty_pc;
+ $pretty_pc_text =~ s/ //g;
+ $c->stash->{pretty_pc_text} = $pretty_pc_text;
+ }
+
+ $c->stash->{pretty_pc} = $pretty_pc;
+
+ return 1;
+}
+
+sub process_user : Private {
+ my ( $self, $c ) = @_;
+
+ my $email = $c->stash->{email};
+ my $alert_user = $c->model('DB::User')->find_or_new( { email => $email } );
+ $c->stash->{alert_user} = $alert_user;
+}
+
+=head2 setup_coordinate_rss_feeds
+
+Takes the latitide and longitude from the stash and uses them to generate uris
+for the local rss feeds
+
+=cut
+
+sub setup_coordinate_rss_feeds : Private {
+ my ( $self, $c ) = @_;
+
+ $c->stash->{rss_feed_id} =
+ sprintf( 'local:%s:%s', $c->stash->{latitude}, $c->stash->{longitude} );
+
+ my $rss_feed;
+ if ( $c->stash->{pretty_pc_text} ) {
+ $rss_feed = $c->uri_for( "/rss/pc/" . $c->stash->{pretty_pc_text} );
+ }
+ else {
+ $rss_feed = $c->uri_for(
+ sprintf( "/rss/l/%s,%s",
+ $c->stash->{latitude},
+ $c->stash->{longitude} )
+ );
+ }
+
+ $c->stash->{rss_feed_uri} = $rss_feed;
+
+ $c->stash->{rss_feed_2k} = $c->uri_for( $rss_feed . '/2' );
+ $c->stash->{rss_feed_5k} = $c->uri_for( $rss_feed . '/5' );
+ $c->stash->{rss_feed_10k} = $c->uri_for( $rss_feed . '/10' );
+ $c->stash->{rss_feed_20k} = $c->uri_for( $rss_feed . '/20' );
+
+ return 1;
+}
+
+=head2 setup_council_rss_feeds
+
+Generate the details required to display the council/ward/area RSS feeds
+
+=cut
+
+sub setup_council_rss_feeds : Private {
+ my ( $self, $c ) = @_;
+
+ $c->stash->{council_check_action} = 'alert';
+ unless ( $c->forward('/council/load_and_check_councils_and_wards') ) {
+ $c->go('index');
+ }
+
+ ( $c->stash->{options}, $c->stash->{reported_to_options} ) =
+ $c->cobrand->council_rss_alert_options( $c->stash->{all_councils}, $c );
+
+ return 1;
+}
+
+=head2 determine_location
+
+Do all the things we need to do to work out where the alert is for
+and to setup the location related things for later
+
+=cut
+
+sub determine_location : Private {
+ my ( $self, $c ) = @_;
+
+ # Try to create a location for whatever we have
+ unless ( $c->forward('/location/determine_location_from_coords')
+ || $c->forward('/location/determine_location_from_pc') )
+ {
+
+ if ( $c->stash->{possible_location_matches} ) {
+ $c->stash->{choose_target_uri} = $c->uri_for('/alert/list');
+ $c->detach('choose');
+ }
+
+ $c->go('index') if $c->stash->{location_error};
+ }
+
+ # truncate the lat,lon for nicer urls
+ ( $c->stash->{latitude}, $c->stash->{longitude} ) =
+ map { Utils::truncate_coordinate($_) }
+ ( $c->stash->{latitude}, $c->stash->{longitude} );
+
+ my $dist =
+ mySociety::Gaze::get_radius_containing_population( $c->stash->{latitude},
+ $c->stash->{longitude}, 200000 );
+ $dist = int( $dist * 10 + 0.5 );
+ $dist = $dist / 10.0;
+ $c->stash->{population_radius} = $dist;
+
+ return 1;
+}
+
+=head2 add_recent_photos
+
+ $c->forward( 'add_recent_photos', [ $num_photos ] );
+
+Adds the most recent $num_photos to the template. If there is coordinate
+and population radius information in the stash uses that to limit it.
+
+=cut
+
+sub add_recent_photos : Private {
+ my ( $self, $c, $num_photos ) = @_;
+
+ if ( $c->stash->{latitude}
+ and $c->stash->{longitude}
+ and $c->stash->{population_radius} )
+ {
+
+ $c->stash->{photos} = $c->cobrand->recent_photos(
+ $num_photos,
+ $c->stash->{latitude},
+ $c->stash->{longitude},
+ $c->stash->{population_radius}
+ );
+ }
+ else {
+ $c->stash->{photos} = $c->cobrand->recent_photos($num_photos);
+ }
+
+ return 1;
+}
+
+sub choose : Private {
+ my ( $self, $c ) = @_;
+ $c->stash->{template} = 'alert/choose.html';
+}
+
+
+=head2 setup_request
+
+Setup the variables we need for the rest of the request
+
+=cut
+
+sub setup_request : Private {
+ my ( $self, $c ) = @_;
+
+ $c->stash->{rznvy} = $c->req->param('rznvy');
+ $c->stash->{selected_feed} = $c->req->param('feed');
+
+ if ( $c->user ) {
+ $c->stash->{rznvy} ||= $c->user->email;
+ }
+
+ $c->stash->{cobrand_form_elements} = $c->cobrand->form_elements('alerts');
+
+ return 1;
+}
+
+=head1 AUTHOR
+
+Struan Donald
+
+=head1 LICENSE
+
+This library is free software. You can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+__PACKAGE__->meta->make_immutable;
+
+1;