aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/App/Controller/JSON.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/FixMyStreet/App/Controller/JSON.pm')
-rw-r--r--perllib/FixMyStreet/App/Controller/JSON.pm136
1 files changed, 136 insertions, 0 deletions
diff --git a/perllib/FixMyStreet/App/Controller/JSON.pm b/perllib/FixMyStreet/App/Controller/JSON.pm
new file mode 100644
index 000000000..3a3010911
--- /dev/null
+++ b/perllib/FixMyStreet/App/Controller/JSON.pm
@@ -0,0 +1,136 @@
+package FixMyStreet::App::Controller::JSON;
+use Moose;
+use namespace::autoclean;
+
+BEGIN { extends 'Catalyst::Controller'; }
+
+use JSON;
+use DateTime;
+use DateTime::Format::ISO8601;
+use List::MoreUtils 'uniq';
+
+=head1 NAME
+
+FixMyStreet::App::Controller::JSON - Catalyst Controller
+
+=head1 DESCRIPTION
+
+Provide information as JSON
+
+=head1 METHODS
+
+=head2 problems
+
+Provide JSON of new/fixed problems in a specified time range
+
+=cut
+
+sub problems : Local {
+ my ( $self, $c, $path_type ) = @_;
+
+ # get the type from the path - this is to deal with the historic url
+ # structure. In futur
+ $path_type ||= '';
+ my $type =
+ $path_type eq 'new' ? 'new_problems'
+ : $path_type eq 'fixed' ? 'fixed_problems'
+ : '';
+
+ # gather the parameters
+ my $start_date = $c->req->param('start_date') || '';
+ my $end_date = $c->req->param('end_date') || '';
+
+ my $yyyy_mm_dd = qr{^\d{4}-\d\d-\d\d$};
+ if ( $start_date !~ $yyyy_mm_dd
+ || $end_date !~ $yyyy_mm_dd )
+ {
+ $c->stash->{error} = 'Invalid dates supplied';
+ return;
+ }
+
+ # convert the dates to datetimes and trap errors
+ my $iso8601 = DateTime::Format::ISO8601->new;
+ my $start_dt = eval { $iso8601->parse_datetime($start_date); };
+ my $end_dt = eval { $iso8601->parse_datetime($end_date); };
+ unless ( $start_dt && $end_dt ) {
+ $c->stash->{error} = 'Invalid dates supplied';
+ return;
+ }
+
+ # check that the dates are sane
+ if ( $start_dt > $end_dt ) {
+ $c->stash->{error} = 'Start date after end date';
+ return;
+ }
+
+ # check that the type is supported
+ unless ( $type eq 'new_problems' || $type eq 'fixed_problems' ) {
+ $c->stash->{error} = 'Invalid type supplied';
+ return;
+ }
+
+ # query the database
+ my ( $state, $date_col );
+ if ( $type eq 'new_problems' ) {
+ $state = 'confirmed';
+ $date_col = 'created';
+ } elsif ( $type eq 'fixed_problems' ) {
+ $state = 'fixed';
+ $date_col = 'lastupdate';
+ }
+
+ my $one_day = DateTime::Duration->new( days => 1 );
+ my @problems = $c->cobrand->problems->search( {
+ $date_col => {
+ '>=' => $start_dt,
+ '<=' => $end_dt + $one_day,
+ },
+ state => $state,
+ }, {
+ order_by => { -asc => 'confirmed' },
+ columns => [
+ 'id', 'title', 'council', 'category',
+ 'detail', 'name', 'anonymous', 'confirmed',
+ 'whensent', 'service',
+ ]
+ } );
+
+ my @councils;
+ foreach my $problem (@problems) {
+ $problem->name( '' ) if $problem->anonymous == 1;
+ $problem->service( 'Web interface' ) if $problem->service eq '';
+ if ($problem->council) {
+ (my $council = $problem->council) =~ s/\|.*//g;
+ my @council_ids = split /,/, $council;
+ push(@councils, @council_ids);
+ $problem->council( \@council_ids );
+ }
+ }
+ @councils = uniq @councils;
+ my $areas_info = mySociety::MaPit::call('areas', \@councils);
+ foreach my $problem (@problems) {
+ if ($problem->council) {
+ my @council_names = map { $areas_info->{$_}->{name} } @{$problem->council} ;
+ $problem->council( join(' and ', @council_names) );
+ }
+ }
+
+ @problems = map { { $_->get_columns } } @problems;
+ $c->stash->{response} = \@problems;
+}
+
+sub end : Private {
+ my ( $self, $c ) = @_;
+
+ my $response =
+ $c->stash->{error}
+ ? { error => $c->stash->{error} }
+ : $c->stash->{response};
+
+ $c->res->content_type('application/json; charset=utf-8');
+ $c->res->body( encode_json( $response || {} ) );
+}
+
+__PACKAGE__->meta->make_immutable;
+
+1;