aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/App/Controller/JSON.pm
blob: d3688f19abadb780b7a366134a080f04c60b2f5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package FixMyStreet::App::Controller::JSON;
use Moose;
use namespace::autoclean;

BEGIN { extends 'Catalyst::Controller'; }

use JSON;
use DateTime;
use DateTime::Format::ISO8601;

=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
    $c->stash->{response} =
      $type eq 'new_problems'
      ? Problems::created_in_interval( $start_date, $end_date )
      : Problems::fixed_in_interval( $start_date, $end_date );
}

# If we convert this code to be fully DBIC based then the following snippet is a
# good start. The roadblock to doing it fully is the 'site_restriction' in the
# SQL which is currently provided as SQL, rather than something that could be
# easily added to the DBIC query. The hardest cobrand to change would be the
# cities - so perhaps do it after we know wether that needs to be kept or not.
#
# my $state =
#     $type eq 'new_problems'   ? 'confirmed'
#   : $type eq 'fixed_problems' ? 'fixed_problems'
#   :                             die;
#
# my $one_day = DateTime::Duration->new( days => 1 );
#
# my $problems = $c->model('DB::Problem')->search(
#     {
#         created => {
#             '>=' => $start_dt,
#             '<=' => $end_dt + $one_day,
#         },
#         state => $state,
#         # ------ add is site_restriction here -------
#     },
#     {
#         columns => [
#             'id',       'title', 'council',   'category',
#             'detail',   'name',  'anonymous', 'confirmed',
#             'whensent', 'service',
#         ]
#     }
# );

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;