aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/FixMyStreet')
-rw-r--r--perllib/FixMyStreet/App.pm6
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm20
-rw-r--r--perllib/FixMyStreet/App/Controller/Around.pm5
-rw-r--r--perllib/FixMyStreet/App/Controller/Auth.pm13
-rw-r--r--perllib/FixMyStreet/App/Controller/JSON.pm11
-rw-r--r--perllib/FixMyStreet/App/Controller/My.pm4
-rwxr-xr-xperllib/FixMyStreet/App/Controller/Questionnaire.pm1
-rw-r--r--perllib/FixMyStreet/App/Controller/Report.pm3
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm36
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/Update.pm19
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm48
-rwxr-xr-xperllib/FixMyStreet/App/Controller/Rss.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Tilma.pm46
-rw-r--r--perllib/FixMyStreet/App/Controller/Tokens.pm18
-rw-r--r--perllib/FixMyStreet/App/View/Web.pm22
-rw-r--r--perllib/FixMyStreet/Cobrand/Barnet.pm4
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm114
-rw-r--r--perllib/FixMyStreet/Cobrand/EmptyHomes.pm5
-rw-r--r--perllib/FixMyStreet/Cobrand/FiksGataMi.pm46
-rw-r--r--perllib/FixMyStreet/Cobrand/Lichfield.pm81
-rw-r--r--perllib/FixMyStreet/Cobrand/Southampton.pm4
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm19
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/AlertType.pm5
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Problem.pm31
-rw-r--r--perllib/FixMyStreet/Geocode.pm193
-rw-r--r--perllib/FixMyStreet/Geocode/Bing.pm67
-rw-r--r--perllib/FixMyStreet/Geocode/Google.pm85
-rw-r--r--perllib/FixMyStreet/Geocode/OSM.pm116
-rw-r--r--perllib/FixMyStreet/Map.pm15
-rw-r--r--perllib/FixMyStreet/Map/FMS.pm16
-rw-r--r--perllib/FixMyStreet/Map/Tilma/OL/1_10k.pm28
-rw-r--r--perllib/FixMyStreet/Map/Tilma/OL/StreetView.pm28
-rw-r--r--perllib/FixMyStreet/Map/Tilma/OpenLayers.pm35
-rw-r--r--perllib/FixMyStreet/Map/Tilma/Original.pm250
-rw-r--r--perllib/FixMyStreet/Map/Tilma/Original/1_10k.pm28
-rw-r--r--perllib/FixMyStreet/Map/Tilma/Original/StreetView.pm28
36 files changed, 733 insertions, 719 deletions
diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm
index 90f1f24bc..68bfc728b 100644
--- a/perllib/FixMyStreet/App.pm
+++ b/perllib/FixMyStreet/App.pm
@@ -180,7 +180,11 @@ sub setup_request {
Memcached::set_namespace( FixMyStreet->config('BCI_DB_NAME') . ":" );
- my $map = $host =~ /^osm\./ ? 'OSM' : $c->req->param('map');
+ my $map = $host =~ /^osm\./ ? 'OSM' : $c->req->param('map_override');
+ #if ($c->sessionid) {
+ # $map = $c->session->{map};
+ # $map = undef unless $map eq 'OSM';
+ #}
FixMyStreet::Map::set_map_class( $map );
return $c;
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index f38181be6..63d892fc4 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -62,6 +62,7 @@ sub index : Path : Args(0) {
$c->stash->{problems} = \%prob_counts;
$c->stash->{total_problems_live} += $prob_counts{$_}
for ( FixMyStreet::DB::Result::Problem->visible_states() );
+ $c->stash->{total_problems_users} = $c->cobrand->problems->unique_users;
my $comments = $c->model('DB::Comment')->summary_count( $site_restriction );
@@ -108,6 +109,8 @@ sub index : Path : Args(0) {
: _('n/a');
$c->stash->{questionnaires} = \%questionnaire_counts;
+ $c->stash->{categories} = $c->cobrand->problems->categories_summary();
+
return 1;
}
@@ -120,6 +123,7 @@ sub timeline : Path( 'timeline' ) : Args(0) {
my %time;
$c->model('DB')->schema->storage->sql_maker->quote_char( '"' );
+ $c->model('DB')->schema->storage->sql_maker->name_sep( '.' );
my $probs = $c->cobrand->problems->timeline;
@@ -172,15 +176,22 @@ sub questionnaire : Path('questionnaire') : Args(0) {
my %questionnaire_counts = map { $_->get_column( 'reported' ) => $_->get_column( 'questionnaire_count' ) } $questionnaires->all;
-
$questionnaire_counts{1} ||= 0;
$questionnaire_counts{0} ||= 0;
-
$questionnaire_counts{total} = $questionnaire_counts{0} + $questionnaire_counts{1};
- $c->stash->{reported_pc} = ( 100 * $questionnaire_counts{1} ) / $questionnaire_counts{total};
- $c->stash->{not_reported_pc} = ( 100 * $questionnaire_counts{0} ) / $questionnaire_counts{total};
$c->stash->{questionnaires} = \%questionnaire_counts;
+ $c->stash->{state_changes_count} = $c->model('DB::Questionnaire')->search(
+ { whenanswered => \'is not null' }
+ )->count;
+ $c->stash->{state_changes} = $c->model('DB::Questionnaire')->search(
+ { whenanswered => \'is not null' },
+ {
+ group_by => [ 'old_state', 'new_state' ],
+ columns => [ 'old_state', 'new_state', { c => { count => 'id' } } ],
+ },
+ );
+
return 1;
}
@@ -419,6 +430,7 @@ sub search_reports : Path('search_reports') {
# makes PostgreSQL unhappy elsewhere so we only want to do
# it for this query and then switch it off afterwards.
$c->model('DB')->schema->storage->sql_maker->quote_char( '"' );
+ $c->model('DB')->schema->storage->sql_maker->name_sep( '.' );
my $problems = $c->cobrand->problems->search(
{
diff --git a/perllib/FixMyStreet/App/Controller/Around.pm b/perllib/FixMyStreet/App/Controller/Around.pm
index 4ca559fad..660585454 100644
--- a/perllib/FixMyStreet/App/Controller/Around.pm
+++ b/perllib/FixMyStreet/App/Controller/Around.pm
@@ -239,6 +239,11 @@ sub ajax : Path('/ajax') {
my $all_pins = $c->req->param('all_pins') ? 1 : undef;
my $interval = $all_pins ? undef : $c->cobrand->on_map_default_max_pin_age;
+ # Need to be the class that can handle it
+ if ($c->req->param('bbox')) {
+ FixMyStreet::Map::set_map_class( 'OSM' );
+ }
+
# extract the data from the map
my ( $pins, $on_map, $around_map, $dist ) =
FixMyStreet::Map::map_pins( $c, $interval );
diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm
index ebb3510d0..c67de692a 100644
--- a/perllib/FixMyStreet/App/Controller/Auth.pm
+++ b/perllib/FixMyStreet/App/Controller/Auth.pm
@@ -36,7 +36,8 @@ sub general : Path : Args(0) {
return unless $req->method eq 'POST';
# decide which action to take
- $c->detach('email_sign_in') if $req->param('email_sign_in');
+ $c->detach('email_sign_in') if $req->param('email_sign_in')
+ || $c->req->param('name') || $c->req->param('password_register');
$c->forward( 'sign_in' )
&& $c->detach( 'redirect_on_signin', [ $req->param('r') ] );
@@ -107,6 +108,11 @@ sub email_sign_in : Private {
return;
}
+ my $user_params = {};
+ $user_params->{password} = $c->req->param('password_register')
+ if $c->req->param('password_register');
+ my $user = $c->model('DB::User')->new( $user_params );
+
my $token_obj = $c->model('DB::Token') #
->create(
{
@@ -115,7 +121,7 @@ sub email_sign_in : Private {
email => $good_email,
r => $c->req->param('r'),
name => $c->req->param('name'),
- password => $c->req->param('password_register'),
+ password => $user->password,
}
}
);
@@ -157,9 +163,8 @@ sub token : Path('/M') : Args(1) {
# find or create the user related to the token.
my $user = $c->model('DB::User')->find_or_create( { email => $data->{email} } );
$user->name( $data->{name} ) if $data->{name};
- $user->password( $data->{password} ) if $data->{password};
+ $user->password( $data->{password}, 1 ) if $data->{password};
$user->update;
-
$c->authenticate( { email => $user->email }, 'no_password' );
# send the user to their page
diff --git a/perllib/FixMyStreet/App/Controller/JSON.pm b/perllib/FixMyStreet/App/Controller/JSON.pm
index d9baeaaf8..f3607341a 100644
--- a/perllib/FixMyStreet/App/Controller/JSON.pm
+++ b/perllib/FixMyStreet/App/Controller/JSON.pm
@@ -39,6 +39,7 @@ sub problems : Local {
# gather the parameters
my $start_date = $c->req->param('start_date') || '';
my $end_date = $c->req->param('end_date') || '';
+ my $category = $c->req->param('category') || '';
my $yyyy_mm_dd = qr{^\d{4}-\d\d-\d\d$};
if ( $start_date !~ $yyyy_mm_dd
@@ -73,25 +74,29 @@ sub problems : Local {
my ( @state, $date_col );
if ( $type eq 'new_problems' ) {
@state = FixMyStreet::DB::Result::Problem->open_states();
- $date_col = 'created';
+ $date_col = 'confirmed';
} elsif ( $type eq 'fixed_problems' ) {
@state = FixMyStreet::DB::Result::Problem->fixed_states();
$date_col = 'lastupdate';
}
my $one_day = DateTime::Duration->new( days => 1 );
- my @problems = $c->cobrand->problems->search( {
+ my $query = {
$date_col => {
'>=' => $start_dt,
'<=' => $end_dt + $one_day,
},
state => [ @state ],
- }, {
+ };
+ $query->{category} = $category if $category;
+ my @problems = $c->cobrand->problems->search( $query, {
order_by => { -asc => 'confirmed' },
columns => [
'id', 'title', 'council', 'category',
'detail', 'name', 'anonymous', 'confirmed',
'whensent', 'service',
+ 'latitude', 'longitude', 'used_map',
+ 'state', 'lastupdate',
]
} );
diff --git a/perllib/FixMyStreet/App/Controller/My.pm b/perllib/FixMyStreet/App/Controller/My.pm
index b1359ae03..19b3ffee0 100644
--- a/perllib/FixMyStreet/App/Controller/My.pm
+++ b/perllib/FixMyStreet/App/Controller/My.pm
@@ -25,9 +25,6 @@ sub my : Path : Args(0) {
$c->detach( '/auth/redirect' ) unless $c->user;
- # Even though front end doesn't yet have it, have it on this page, it's better!
- FixMyStreet::Map::set_map_class( 'FMS' );
-
my $p_page = $c->req->params->{p} || 1;
my $u_page = $c->req->params->{u} || 1;
@@ -56,6 +53,7 @@ sub my : Path : Args(0) {
$c->stash->{updates} = \@updates;
$c->stash->{updates_pager} = $rs->pager;
+ $c->stash->{page} = 'my';
FixMyStreet::Map::display_map(
$c,
latitude => $pins->[0]{latitude},
diff --git a/perllib/FixMyStreet/App/Controller/Questionnaire.pm b/perllib/FixMyStreet/App/Controller/Questionnaire.pm
index 8de935dd7..d9bdb7108 100755
--- a/perllib/FixMyStreet/App/Controller/Questionnaire.pm
+++ b/perllib/FixMyStreet/App/Controller/Questionnaire.pm
@@ -289,6 +289,7 @@ sub display : Private {
{ order_by => 'confirmed' }
);
+ $c->stash->{page} = 'questionnaire';
FixMyStreet::Map::display_map(
$c,
latitude => $problem->latitude,
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm
index a15ee993f..6596615c6 100644
--- a/perllib/FixMyStreet/App/Controller/Report.pm
+++ b/perllib/FixMyStreet/App/Controller/Report.pm
@@ -108,8 +108,6 @@ sub format_problem_for_display : Private {
map { Utils::truncate_coordinate($_) }
( $problem->latitude, $problem->longitude );
- $c->stash->{report_name} = $c->req->param('name');
-
unless ( $c->req->param('submit_update') ) {
$c->stash->{add_alert} = 1;
}
@@ -124,6 +122,7 @@ sub generate_map_tags : Private {
my $problem = $c->stash->{problem};
+ $c->stash->{page} = 'report';
FixMyStreet::Map::display_map(
$c,
latitude => $problem->latitude,
diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm
index 3a7d18a1c..346dfb377 100644
--- a/perllib/FixMyStreet/App/Controller/Report/New.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/New.pm
@@ -220,13 +220,15 @@ sub report_import : Path('/import') {
anonymous => 0,
category => '',
areas => '',
+ cobrand => $c->cobrand->moniker,
+ lang => $c->stash->{lang_code},
}
);
# If there was a photo add that too
- if ( my $fileid = $c->stash->{upload_fileid} ) {
- my $file = file( $c->config->{UPLOAD_CACHE}, "$fileid.jpg" );
+ if ( $photo ) {
+ my $file = file( $c->config->{UPLOAD_CACHE}, "$photo.jpg" );
my $blob = $file->slurp;
$file->remove;
$report->photo($blob);
@@ -489,7 +491,7 @@ sub setup_categories_and_councils : Private {
next # TODO - move this to the cobrand
if $c->cobrand->moniker eq 'southampton'
- && $contact->category eq 'Street lighting';
+ && $contact->category =~ /Street lighting|Traffic lights/;
next if $contact->category eq _('Other');
@@ -571,9 +573,9 @@ sub process_user : Private {
unless $report->user;
# The user is trying to sign in. We only care about email from the params.
- if ( $c->req->param('submit_sign_in') ) {
+ if ( $c->req->param('submit_sign_in') || $c->req->param('password_sign_in') ) {
unless ( $c->forward( '/auth/sign_in' ) ) {
- $c->stash->{field_errors}->{password} = _('There was a problem with your email/password combination. Please try again.');
+ $c->stash->{field_errors}->{password} = _('There was a problem with your email/password combination. Passwords and user accounts are a brand <strong>new</strong> service, so you probably do not have one yet &ndash; please fill in the right hand side of this form to get one.');
return 1;
}
my $user = $c->user->obj;
@@ -608,6 +610,7 @@ sub process_report : Private {
map { $_ => scalar $c->req->param($_) } #
(
'title', 'detail', 'pc', #
+ 'detail_size', 'detail_depth',
'may_show_name', #
'category', #
'partial', #
@@ -626,8 +629,14 @@ sub process_report : Private {
# clean up text before setting
$report->title( Utils::cleanup_text( $params{title} ) );
- $report->detail(
- Utils::cleanup_text( $params{detail}, { allow_multiline => 1 } ) );
+
+ my $detail = Utils::cleanup_text( $params{detail}, { allow_multiline => 1 } );
+ for my $w ('depth', 'size') {
+ next unless $params{"detail_$w"};
+ next if $params{"detail_$w"} eq '-- Please select --';
+ $detail .= "\n\n\u$w: " . $params{"detail_$w"};
+ }
+ $report->detail( $detail );
# set these straight from the params
$report->category( _ $params{category} );
@@ -845,9 +854,13 @@ sub save_user_and_report : Private {
$report->confirm;
}
else {
-
- # user exists and we are not logged in as them. Throw away changes to
- # the name and phone. TODO - propagate changes using tokens.
+ # User exists and we are not logged in as them.
+ # Store changes in token for when token is validated.
+ $c->stash->{token_data} = {
+ name => $report->user->name,
+ phone => $report->user->phone,
+ password => $report->user->password,
+ };
$report->user->discard_changes();
}
@@ -895,6 +908,7 @@ sub generate_map : Private {
# Don't do anything if the user skipped the map
unless ( $c->req->param('skipped') ) {
+ $c->stash->{page} = 'new';
FixMyStreet::Map::display_map(
$c,
latitude => $latitude,
@@ -932,9 +946,11 @@ sub redirect_or_confirm_creation : Private {
}
# otherwise create a confirm token and email it to them.
+ my $data = $c->stash->{token_data} || {};
my $token = $c->model("DB::Token")->create( {
scope => 'problem',
data => {
+ %$data,
id => $report->id
}
} );
diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm
index 2916e1ee1..add9d1371 100644
--- a/perllib/FixMyStreet/App/Controller/Report/Update.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm
@@ -120,9 +120,9 @@ sub process_user : Private {
unless $update->user;
# The user is trying to sign in. We only care about email from the params.
- if ( $c->req->param('submit_sign_in') ) {
+ if ( $c->req->param('submit_sign_in') || $c->req->param('password_sign_in') ) {
unless ( $c->forward( '/auth/sign_in', [ $email ] ) ) {
- $c->stash->{field_errors}->{password} = _('There was a problem with your email/password combination. Please try again.');
+ $c->stash->{field_errors}->{password} = _('There was a problem with your email/password combination. Passwords and user accounts are a brand <strong>new</strong> service, so you probably do not have one yet &ndash; please fill in the right hand side of this form to get one.');
return 1;
}
my $user = $c->user->obj;
@@ -180,8 +180,7 @@ sub process_update : Private {
if ( $params{state} ) {
$params{state} = 'fixed - council'
- if $params{state} eq 'fixed' && $c->user && $c->user->from_council
- && $c->user->from_council == $update->problem->council;
+ if $params{state} eq 'fixed' && $c->user && $c->user->belongs_to_council( $update->problem->council );
$update->problem_state( $params{state} );
}
@@ -205,7 +204,7 @@ sub check_for_errors : Private {
# they have to be an authority user to update the state
if ( $c->req->param('state') ) {
my $error = 0;
- $error = 1 unless $c->user && $c->user->from_council && $c->user->from_council == $c->stash->{update}->problem->council;
+ $error = 1 unless $c->user && $c->user->belongs_to_council( $c->stash->{update}->problem->council );
my $state = $c->req->param('state');
$error = 1 unless ( grep { $state eq $_ } ( qw/confirmed closed fixed investigating planned/, 'in progress', 'fixed', 'fixed - user', 'fixed - council' ) );
@@ -262,6 +261,14 @@ sub save_update : Private {
# Logged in and same user, so can confirm update straight away
$update->user->update;
$update->confirm;
+ } else {
+ # User exists and we are not logged in as them.
+ # Store changes in token for when token is validated.
+ $c->stash->{token_data} = {
+ name => $update->user->name,
+ password => $update->user->password,
+ };
+ $update->user->discard_changes();
}
# If there was a photo add that too
@@ -303,10 +310,12 @@ sub redirect_or_confirm_creation : Private {
}
# otherwise create a confirm token and email it to them.
+ my $data = $c->stash->{token_data} || {};
my $token = $c->model("DB::Token")->create(
{
scope => 'comment',
data => {
+ %$data,
id => $update->id,
add_alert => ( $c->req->param('add_alert') ? 1 : 0 ),
}
diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm
index 9cec0fdfe..821b650ed 100644
--- a/perllib/FixMyStreet/App/Controller/Reports.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports.pm
@@ -34,10 +34,18 @@ sub index : Path : Args(0) {
$c->response->header('Cache-Control' => 'max-age=3600');
# Fetch all areas of the types we're interested in
- my @area_types = $c->cobrand->area_types;
- my $areas_info = mySociety::MaPit::call('areas', \@area_types,
- min_generation => $c->cobrand->area_min_generation
- );
+ my $areas_info;
+ eval {
+ my @area_types = $c->cobrand->area_types;
+ $areas_info = mySociety::MaPit::call('areas', \@area_types,
+ min_generation => $c->cobrand->area_min_generation
+ );
+ };
+ if ($@) {
+ $c->stash->{message} = _("Unable to look up areas in MaPit. Please try again later.") . ' ' .
+ sprintf(_('The error was: %s'), $@);
+ $c->stash->{template} = 'errors/generic.html';
+ }
# For each area, add its link and perhaps alter its name if we need to for
# places with the same name.
@@ -61,7 +69,8 @@ sub index : Path : Args(0) {
$c->stash->{open} = $j->{open};
};
if ($@) {
- $c->stash->{message} = _("There was a problem showing the All Reports page. Please try again later.");
+ $c->stash->{message} = _("There was a problem showing the All Reports page. Please try again later.") . ' ' .
+ sprintf(_('The error was: %s'), $@);
$c->stash->{template} = 'errors/generic.html';
}
}
@@ -90,6 +99,7 @@ sub ward : Path : Args(2) {
$c->forward( 'ward_check', [ $ward ] )
if $ward;
$c->forward( 'load_parent' );
+ $c->forward( 'check_canonical_url', [ $council ] );
$c->forward( 'load_and_group_problems' );
$c->forward( 'sort_problems' );
@@ -102,8 +112,7 @@ sub ward : Path : Args(2) {
my $pins = $c->stash->{pins};
- # Even though front end doesn't yet have it, have it on this page, it's better!
- FixMyStreet::Map::set_map_class( 'FMS' );
+ $c->stash->{page} = 'reports'; # So the map knows to make clickable pins
FixMyStreet::Map::display_map(
$c,
latitude => @$pins ? $pins->[0]{latitude} : 0,
@@ -227,7 +236,7 @@ sub council_check : Private {
return;
} else {
foreach (keys %$areas) {
- if ($areas->{$_}->{name} eq $q_council || $areas->{$_}->{name} =~ /^\Q$q_council\E (Borough|City|District|County) Council$/) {
+ if (lc($areas->{$_}->{name}) eq lc($q_council) || $areas->{$_}->{name} =~ /^\Q$q_council\E (Borough|City|District|County) Council$/i) {
$c->stash->{council} = $areas->{$_};
return;
}
@@ -252,6 +261,7 @@ sub ward_check : Private {
$ward =~ s/\+/ /g;
$ward =~ s/\.html//;
+ $ward =~ s{_}{/}g;
my $council = $c->stash->{council};
@@ -281,6 +291,22 @@ sub load_parent : Private {
}
}
+=head2 check_canonical_url
+
+Given an already found (case-insensitively) council, check what URL
+we are at and redirect accordingly if different.
+
+=cut
+
+sub check_canonical_url : Private {
+ my ( $self, $c, $q_council ) = @_;
+
+ my $council_short = $c->cobrand->short_name( $c->stash->{council}, $c->stash->{areas_info} );
+ my $url_short = URI::Escape::uri_escape_utf8($q_council);
+ $url_short =~ s/%2B/+/g;
+ $c->detach( 'redirect_area' ) unless $council_short eq $url_short;
+}
+
sub load_and_group_problems : Private {
my ( $self, $c ) = @_;
@@ -290,9 +316,9 @@ sub load_and_group_problems : Private {
state => [ FixMyStreet::DB::Result::Problem->visible_states() ]
};
if ($c->stash->{ward}) {
- $where->{areas} = { 'like', '%' . $c->stash->{ward}->{id} . '%' }; # FIXME Check this is secure
+ $where->{areas} = { 'like', '%,' . $c->stash->{ward}->{id} . ',%' };
} elsif ($c->stash->{council}) {
- $where->{areas} = { 'like', '%' . $c->stash->{council}->{id} . '%' };
+ $where->{areas} = { 'like', '%,' . $c->stash->{council}->{id} . ',%' };
}
my $problems = $c->cobrand->problems->search(
$where,
@@ -369,7 +395,7 @@ sub redirect_area : Private {
my $url = '';
$url .= "/rss" if $c->stash->{rss};
$url .= '/reports';
- $url .= '/' . $c->cobrand->short_name( $c->stash->{council} );
+ $url .= '/' . $c->cobrand->short_name( $c->stash->{council}, $c->stash->{areas_info} );
$url .= '/' . $c->cobrand->short_name( $c->stash->{ward} )
if $c->stash->{ward};
$c->res->redirect( $c->uri_for($url) );
diff --git a/perllib/FixMyStreet/App/Controller/Rss.pm b/perllib/FixMyStreet/App/Controller/Rss.pm
index db4955f06..78793d9c1 100755
--- a/perllib/FixMyStreet/App/Controller/Rss.pm
+++ b/perllib/FixMyStreet/App/Controller/Rss.pm
@@ -217,7 +217,7 @@ sub add_row : Private {
my ( $self, $c, $row ) = @_;
my $alert_type = $c->stash->{alert_type};
- $row->{name} ||= 'anonymous';
+ $row->{name} = 'anonymous' if $row->{anonymous} || !$row->{name};
my $pubDate;
if ($row->{confirmed}) {
diff --git a/perllib/FixMyStreet/App/Controller/Tilma.pm b/perllib/FixMyStreet/App/Controller/Tilma.pm
deleted file mode 100644
index 1be481949..000000000
--- a/perllib/FixMyStreet/App/Controller/Tilma.pm
+++ /dev/null
@@ -1,46 +0,0 @@
-package FixMyStreet::App::Controller::Tilma;
-use Moose;
-use namespace::autoclean;
-
-BEGIN { extends 'Catalyst::Controller'; }
-
-use LWP::UserAgent;
-
-=head1 NAME
-
-FixMyStreet::App::Controller::Tilma - Tilma proxy
-
-=head1 DESCRIPTION
-
-A tilma proxy - only intended to be used during dev. In production the webserver should do this proxying.
-
-=head1 METHODS
-
-=head2 default
-
-Proxy everything through to the tilma servers.
-
-=cut
-
-sub default : Path {
- my ( $self, $c ) = @_;
-
- my $path = $c->req->uri->path_query;
- $path =~ s{/tilma/}{};
-
- my $tilma_uri = URI->new("http://tilma.mysociety.org/$path");
-
- my $tilma_res = LWP::UserAgent->new->get($tilma_uri);
-
- if ( $tilma_res->is_success ) {
- $c->res->content_type( $tilma_res->content_type );
- $c->res->body( $tilma_res->content );
- }
- else {
- die sprintf "Error getting %s: %s", $tilma_uri, $tilma_res->message;
- }
-}
-
-__PACKAGE__->meta->make_immutable;
-
-1;
diff --git a/perllib/FixMyStreet/App/Controller/Tokens.pm b/perllib/FixMyStreet/App/Controller/Tokens.pm
index 1fef0f07e..9abef591d 100644
--- a/perllib/FixMyStreet/App/Controller/Tokens.pm
+++ b/perllib/FixMyStreet/App/Controller/Tokens.pm
@@ -32,7 +32,8 @@ sub confirm_problem : Path('/P') {
$c->forward( 'load_auth_token', [ $token_code, 'problem' ] );
# Load the problem
- my $problem_id = $auth_token->data->{id};
+ my $data = $auth_token->data;
+ my $problem_id = $data->{id};
my $problem = $c->cobrand->problems->find( { id => $problem_id } )
|| $c->detach('token_error');
$c->stash->{problem} = $problem;
@@ -59,6 +60,11 @@ sub confirm_problem : Path('/P') {
$c->forward( '/report/new/create_reporter_alert' );
# log the problem creation user in to the site
+ if ( $data->{name} || $data->{password} ) {
+ $problem->user->name( $data->{name} ) if $data->{name};
+ $problem->user->password( $data->{password}, 1 ) if $data->{password};
+ $problem->user->update;
+ }
$c->authenticate( { email => $problem->user->email }, 'no_password' );
$c->set_session_cookie_expire(0);
@@ -133,8 +139,9 @@ sub confirm_update : Path('/C') {
$c->forward( 'load_auth_token', [ $token_code, 'comment' ] );
# Load the problem
- my $comment_id = $auth_token->data->{id};
- $c->stash->{add_alert} = $auth_token->data->{add_alert};
+ my $data = $auth_token->data;
+ my $comment_id = $data->{id};
+ $c->stash->{add_alert} = $data->{add_alert};
my $comment = $c->model('DB::Comment')->find( { id => $comment_id } )
|| $c->detach('token_error');
@@ -146,6 +153,11 @@ sub confirm_update : Path('/C') {
return;
}
+ if ( $data->{name} || $data->{password} ) {
+ $comment->user->name( $data->{name} ) if $data->{name};
+ $comment->user->password( $data->{password}, 1 ) if $data->{password};
+ $comment->user->update;
+ }
$c->authenticate( { email => $comment->user->email }, 'no_password' );
$c->set_session_cookie_expire(0);
diff --git a/perllib/FixMyStreet/App/View/Web.pm b/perllib/FixMyStreet/App/View/Web.pm
index 358e280c3..df2d0ac20 100644
--- a/perllib/FixMyStreet/App/View/Web.pm
+++ b/perllib/FixMyStreet/App/View/Web.pm
@@ -21,6 +21,9 @@ __PACKAGE__->config(
'loc', 'nget', 'tprintf', 'display_crosssell_advert', 'prettify_epoch',
'add_links',
],
+ FILTERS => {
+ escape_js => \&escape_js,
+ },
);
=head1 NAME
@@ -120,5 +123,24 @@ sub add_links {
return $text;
}
+=head2 escape_js
+
+Used to escape strings that are going to be put inside JavaScript.
+
+=cut
+
+sub escape_js {
+ my $text = shift;
+ my %lookup = (
+ '\\' => 'u005c',
+ '"' => 'u0022',
+ "'" => 'u0027',
+ '<' => 'u003c',
+ '>' => 'u003e',
+ );
+ $text =~ s/([\\"'<>])/\\$lookup{$1}/g;
+ return $text;
+}
+
1;
diff --git a/perllib/FixMyStreet/Cobrand/Barnet.pm b/perllib/FixMyStreet/Cobrand/Barnet.pm
index 9496570ea..a12fa6d06 100644
--- a/perllib/FixMyStreet/Cobrand/Barnet.pm
+++ b/perllib/FixMyStreet/Cobrand/Barnet.pm
@@ -76,9 +76,5 @@ sub recent_photos {
return $self->problems->recent_photos( $num, $lat, $lon, $dist );
}
-sub tilma_mid_point {
- return 189;
-}
-
1;
diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm
index 29061ebd8..69718f613 100644
--- a/perllib/FixMyStreet/Cobrand/Default.pm
+++ b/perllib/FixMyStreet/Cobrand/Default.pm
@@ -7,6 +7,7 @@ use URI;
use Carp;
use mySociety::MaPit;
+use mySociety::PostcodeUtil;
=head2 new
@@ -405,12 +406,9 @@ sub uri {
(my $map_class = $FixMyStreet::Map::map_class) =~ s/^FixMyStreet::Map:://;
return $uri unless $map_class =~ /OSM|FMS/;
- $uri = URI->new( $uri );
$uri->query_param( zoom => 3 )
if $uri->query_param('lat') && !$uri->query_param('zoom');
- # $uri->query_param( map => $map_class ); # FIXME Only on /around, /report?
-
return $uri;
}
@@ -490,6 +488,46 @@ allowing them to report them as offensive.
sub allow_update_reporting { return 0; }
+=head2 geocode_postcode
+
+Given a QUERY, return LAT/LON and/or ERROR.
+
+=cut
+
+sub geocode_postcode {
+ my ( $self, $s ) = @_;
+
+ if ($s =~ /^\d+$/) {
+ return {
+ error => 'FixMyStreet is a UK-based website that currently works in England, Scotland, and Wales. Please enter either a postcode, or a Great British street name and area.'
+ };
+ } elsif (mySociety::PostcodeUtil::is_valid_postcode($s)) {
+ my $location = mySociety::MaPit::call('postcode', $s);
+ if ($location->{error}) {
+ return {
+ error => $location->{code} =~ /^4/
+ ? _('That postcode was not recognised, sorry.')
+ : $location->{error}
+ };
+ }
+ my $island = $location->{coordsyst};
+ if (!$island) {
+ return {
+ error => _("Sorry, that appears to be a Crown dependency postcode, which we don't cover.")
+ };
+ } elsif ($island eq 'I') {
+ return {
+ error => _("We do not currently cover Northern Ireland, I'm afraid.")
+ };
+ }
+ return {
+ latitude => $location->{wgs84_lat},
+ longitude => $location->{wgs84_lon},
+ };
+ }
+ return {};
+}
+
=head2 geocoded_string_check
Parameters are LOCATION, QUERY. Return a boolean indicating whether the
@@ -499,6 +537,44 @@ string LOCATION passes the cobrands checks.
sub geocoded_string_check { return 1; }
+=head2 find_closest
+
+Used by send-reports to attach nearest things to the bottom of the report
+
+=cut
+
+sub find_closest {
+ my ( $self, $latitude, $longitude ) = @_;
+ my $str = '';
+
+ # Get nearest road-type thing from Bing
+ my $key = mySociety::Config::get('BING_MAPS_API_KEY', '');
+ if ($key) {
+ my $url = "http://dev.virtualearth.net/REST/v1/Locations/$latitude,$longitude?c=en-GB&key=$key";
+ my $j = LWP::Simple::get($url);
+ if ($j) {
+ $j = JSON->new->utf8->allow_nonref->decode($j);
+ if ($j->{resourceSets}[0]{resources}[0]{name}) {
+ $str .= sprintf(_("Nearest road to the pin placed on the map (automatically generated by Bing Maps): %s"),
+ $j->{resourceSets}[0]{resources}[0]{name}) . "\n\n";
+ }
+ }
+ }
+
+ # Get nearest postcode from Matthew's random gazetteer (put in MaPit? Or elsewhere?)
+ my $url = "http://gazetteer.dracos.vm.bytemark.co.uk/point/$latitude,$longitude.json";
+ my $j = LWP::Simple::get($url);
+ if ($j) {
+ $j = JSON->new->utf8->allow_nonref->decode($j);
+ if ($j->{postcode}) {
+ $str .= sprintf(_("Nearest postcode to the pin placed on the map (automatically generated): %s (%sm away)"),
+ $j->{postcode}[0], $j->{postcode}[1]) . "\n\n";
+ }
+ }
+
+ return $str;
+}
+
=head2 council_check
Paramters are COUNCILS, QUERY, CONTEXT. Return a boolean indicating whether
@@ -558,16 +634,6 @@ The MaPit types this site handles
sub area_types { return qw(DIS LBO MTD UTA CTY COI); }
sub area_min_generation { 10 }
-=head2 tilma_mid_point
-
-If the map is smaller than the usual, return half its size.
-
-=cut
-
-sub tilma_mid_point {
- return 0;
-}
-
=head2 contact_name, contact_email
Return the contact name or email for the cobranded version of the site (to be
@@ -672,6 +738,7 @@ sub short_name {
$name =~ s/ (Borough|City|District|County) Council$//;
$name =~ s/ Council$//;
$name =~ s/ & / and /;
+ $name =~ s{/}{_}g;
$name = URI::Escape::uri_escape_utf8($name);
$name =~ s/%20/+/g;
return $name;
@@ -687,6 +754,7 @@ Generate a set of options for council rss alerts.
sub council_rss_alert_options {
my $self = shift;
my $all_councils = shift;
+ my $c = shift;
my %councils = map { $_ => 1 } $self->area_types();
@@ -713,7 +781,7 @@ sub council_rss_alert_options {
id => sprintf( 'council:%s:%s', $council->{id}, $council->{id_name} ),
text => sprintf( _('Problems within %s'), $council->{name}),
rss_text => sprintf( _('RSS feed of problems within %s'), $council->{name}),
- uri => $self->uri( '/rss/reports/' . $council->{short_name} ),
+ uri => $c->uri_for( '/rss/reports/' . $council->{short_name} ),
};
push @options,
{
@@ -721,7 +789,7 @@ sub council_rss_alert_options {
id => sprintf( 'ward:%s:%s:%s:%s', $council->{id}, $ward->{id}, $council->{id_name}, $ward->{id_name} ),
rss_text => sprintf( _('RSS feed of problems within %s ward'), $ward->{name}),
text => sprintf( _('Problems within %s ward'), $ward->{name}),
- uri => $self->uri( '/rss/reports/' . $council->{short_name} . '/' . $ward->{short_name} ),
+ uri => $c->uri_for( '/rss/reports/' . $council->{short_name} . '/' . $ward->{short_name} ),
} if $ward;
} elsif ( $num_councils == 4 ) {
# # Two-tier council
@@ -750,28 +818,28 @@ sub council_rss_alert_options {
id => sprintf( 'area:%s:%s', $district->{id}, $district->{id_name} ),
text => $district_name,
rss_text => sprintf( _('RSS feed for %s'), $district_name ),
- uri => $self->uri( '/rss/areas/' . $district->{short_name} )
+ uri => $c->uri_for( '/rss/areas/' . $district->{short_name} )
},
{
type => 'area',
id => sprintf( 'area:%s:%s:%s:%s', $district->{id}, $d_ward->{id}, $district->{id_name}, $d_ward->{id_name} ),
text => sprintf( _('%s ward, %s'), $d_ward_name, $district_name ),
rss_text => sprintf( _('RSS feed for %s ward, %s'), $d_ward_name, $district_name ),
- uri => $self->uri( '/rss/areas/' . $district->{short_name} . '/' . $d_ward->{short_name} )
+ uri => $c->uri_for( '/rss/areas/' . $district->{short_name} . '/' . $d_ward->{short_name} )
},
{
type => 'area',
id => sprintf( 'area:%s:%s', $county->{id}, $county->{id_name} ),
text => $county_name,
rss_text => sprintf( _('RSS feed for %s'), $county_name ),
- uri => $self->uri( '/rss/areas/' . $county->{short_name} )
+ uri => $c->uri_for( '/rss/areas/' . $county->{short_name} )
},
{
type => 'area',
id => sprintf( 'area:%s:%s:%s:%s', $county->{id}, $c_ward->{id}, $county->{id_name}, $c_ward->{id_name} ),
text => sprintf( _('%s ward, %s'), $c_ward_name, $county_name ),
rss_text => sprintf( _('RSS feed for %s ward, %s'), $c_ward_name, $county_name ),
- uri => $self->uri( '/rss/areas/' . $county->{short_name} . '/' . $c_ward->{short_name} )
+ uri => $c->uri_for( '/rss/areas/' . $county->{short_name} . '/' . $c_ward->{short_name} )
};
push @reported_to_options,
@@ -780,28 +848,28 @@ sub council_rss_alert_options {
id => sprintf( 'council:%s:%s', $district->{id}, $district->{id_name} ),
text => $district->{name},
rss_text => sprintf( _('RSS feed of %s'), $district->{name}),
- uri => $self->uri( '/rss/reports/' . $district->{short_name} ),
+ uri => $c->uri_for( '/rss/reports/' . $district->{short_name} ),
},
{
type => 'ward',
id => sprintf( 'ward:%s:%s:%s:%s', $district->{id}, $d_ward->{id}, $district->{id_name}, $d_ward->{id_name} ),
rss_text => sprintf( _('RSS feed of %s, within %s ward'), $district->{name}, $d_ward->{name}),
text => sprintf( _('%s, within %s ward'), $district->{name}, $d_ward->{name}),
- uri => $self->uri( '/rss/reports/' . $district->{short_name} . '/' . $d_ward->{short_name} ),
+ uri => $c->uri_for( '/rss/reports/' . $district->{short_name} . '/' . $d_ward->{short_name} ),
},
{
type => 'council',
id => sprintf( 'council:%s:%s', $county->{id}, $county->{id_name} ),
text => $county->{name},
rss_text => sprintf( _('RSS feed of %s'), $county->{name}),
- uri => $self->uri( '/rss/reports/' . $county->{short_name} ),
+ uri => $c->uri_for( '/rss/reports/' . $county->{short_name} ),
},
{
type => 'ward',
id => sprintf( 'ward:%s:%s:%s:%s', $county->{id}, $c_ward->{id}, $county->{id_name}, $c_ward->{id_name} ),
rss_text => sprintf( _('RSS feed of %s, within %s ward'), $county->{name}, $c_ward->{name}),
text => sprintf( _('%s, within %s ward'), $county->{name}, $c_ward->{name}),
- uri => $self->uri( '/rss/reports/' . $county->{short_name} . '/' . $c_ward->{short_name} ),
+ uri => $c->uri_for( '/rss/reports/' . $county->{short_name} . '/' . $c_ward->{short_name} ),
};
diff --git a/perllib/FixMyStreet/Cobrand/EmptyHomes.pm b/perllib/FixMyStreet/Cobrand/EmptyHomes.pm
index 3694d984b..189daee0c 100644
--- a/perllib/FixMyStreet/Cobrand/EmptyHomes.pm
+++ b/perllib/FixMyStreet/Cobrand/EmptyHomes.pm
@@ -138,6 +138,7 @@ Generate a set of options for council rss alerts.
sub council_rss_alert_options {
my $self = shift;
my $all_councils = shift;
+ my $c = shift;
my %councils = map { $_ => 1 } $self->area_types();
@@ -160,14 +161,14 @@ sub council_rss_alert_options {
id => sprintf( 'council:%s:%s', $council->{id}, $council->{id_name} ),
text => sprintf( _('Problems within %s'), $council->{name}),
rss_text => sprintf( _('RSS feed of problems within %s'), $council->{name}),
- uri => $self->uri( '/rss/reports/' . $council->{short_name} ),
+ uri => $c->uri_for( '/rss/reports/' . $council->{short_name} ),
};
push @options, {
type => 'ward',
id => sprintf( 'ward:%s:%s:%s:%s', $council->{id}, $ward->{id}, $council->{id_name}, $ward->{id_name} ),
rss_text => sprintf( _('RSS feed of problems within %s ward'), $ward->{name}),
text => sprintf( _('Problems within %s ward'), $ward->{name}),
- uri => $self->uri( '/rss/reports/' . $council->{short_name} . '/' . $ward->{short_name} ),
+ uri => $c->uri_for( '/rss/reports/' . $council->{short_name} . '/' . $ward->{short_name} ),
};
return ( \@options, @reported_to_options ? \@reported_to_options : undef );
diff --git a/perllib/FixMyStreet/Cobrand/FiksGataMi.pm b/perllib/FixMyStreet/Cobrand/FiksGataMi.pm
index 3d855cf8e..4f3b975b3 100644
--- a/perllib/FixMyStreet/Cobrand/FiksGataMi.pm
+++ b/perllib/FixMyStreet/Cobrand/FiksGataMi.pm
@@ -6,6 +6,7 @@ use warnings;
use Carp;
use mySociety::MaPit;
+use FixMyStreet::Geocode::OSM;
sub country {
return 'NO';
@@ -35,7 +36,7 @@ sub disambiguate_location {
}
sub area_types {
- return ( 'NKO', 'NFY' );
+ return ( 'NKO', 'NFY', 'NRA' );
}
sub area_min_generation {
@@ -55,19 +56,60 @@ sub writetothem_url {
sub uri {
my ( $self, $uri ) = @_;
- $uri = URI->new( $uri );
$uri->query_param( zoom => 3 )
if $uri->query_param('lat') && !$uri->query_param('zoom');
return $uri;
}
+sub geocode_postcode {
+ my ( $self, $s ) = @_;
+
+ if ($s =~ /^\d{4}$/) {
+ my $location = mySociety::MaPit::call('postcode', $s);
+ if ($location->{error}) {
+ return {
+ error => $location->{code} =~ /^4/
+ ? _('That postcode was not recognised, sorry.')
+ : $location->{error}
+ };
+ }
+ return {
+ latitude => $location->{wgs84_lat},
+ longitude => $location->{wgs84_lon},
+ };
+ }
+ return {};
+}
+
sub geocoded_string_check {
my ( $self, $s ) = @_;
return 1 if $s =~ /, Norge/;
return 0;
}
+sub find_closest {
+ my ( $self, $latitude, $longitude ) = @_;
+ return FixMyStreet::Geocode::OSM::closest_road_text( $self, $latitude, $longitude );
+}
+
+# Used by send-reports, calling find_closest, calling OSM geocoding
+sub guess_road_operator {
+ my ( $self, $inforef ) = @_;
+
+ my $highway = $inforef->{highway} || "unknown";
+ my $refs = $inforef->{ref} || "unknown";
+
+ return "Statens vegvesen"
+ if $highway eq "trunk" || $highway eq "primary";
+
+ for my $ref (split(/;/, $refs)) {
+ return "Statens vegvesen"
+ if $ref =~ m/E ?\d+/ || $ref =~ m/Fv\d+/i;
+ }
+ return '';
+}
+
sub remove_redundant_councils {
my $self = shift;
my $all_councils = shift;
diff --git a/perllib/FixMyStreet/Cobrand/Lichfield.pm b/perllib/FixMyStreet/Cobrand/Lichfield.pm
new file mode 100644
index 000000000..9865bfa7b
--- /dev/null
+++ b/perllib/FixMyStreet/Cobrand/Lichfield.pm
@@ -0,0 +1,81 @@
+package FixMyStreet::Cobrand::Lichfield;
+use base 'FixMyStreet::Cobrand::Default';
+
+use strict;
+use warnings;
+
+use Carp;
+use URI::Escape;
+use mySociety::VotingArea;
+
+sub site_restriction {
+ return ( "and council like '%2434%'", 'lichfield', { council => '2434' } );
+}
+
+sub problems_clause {
+ return { council => { like => '%2434%' } };
+}
+
+sub problems {
+ my $self = shift;
+ return $self->{c}->model('DB::Problem')->search( $self->problems_clause );
+}
+
+sub base_url {
+ my $base_url = mySociety::Config::get('BASE_URL');
+ if ( $base_url !~ /lichfield/ ) {
+ $base_url =~ s{http://(?!www\.)}{http://lichfield.}g;
+ $base_url =~ s{http://www\.}{http://lichfield.}g;
+ }
+ return $base_url;
+}
+
+sub site_title {
+ my ($self) = @_;
+ return 'Lichfield Council FixMyStreet';
+}
+
+sub enter_postcode_text {
+ my ($self) = @_;
+ return 'Enter a Lichfield postcode, or street name and area';
+}
+
+sub council_check {
+ my ( $self, $params, $context ) = @_;
+
+ my $councils = $params->{all_councils};
+ my $council_match = defined $councils->{2434};
+ if ($council_match) {
+ return 1;
+ }
+ my $url = 'http://www.fixmystreet.com/';
+ $url .= 'alert' if $context eq 'alert';
+ $url .= '?pc=' . URI::Escape::uri_escape( $self->{c}->req->param('pc') )
+ if $self->{c}->req->param('pc');
+ my $error_msg = "That location is not covered by Lichfield.
+Please visit <a href=\"$url\">the main FixMyStreet site</a>.";
+ return ( 0, $error_msg );
+}
+
+# All reports page only has the one council.
+sub all_councils_report {
+ return 0;
+}
+
+# FIXME - need to double check this is all correct
+sub disambiguate_location {
+ return {
+ centre => '52.688198,-1.804966',
+ span => '0.1196,0.218675',
+ bounds => [ '52.807793,-1.586291', '52.584891,-1.963232' ],
+ };
+}
+
+sub recent_photos {
+ my ( $self, $num, $lat, $lon, $dist ) = @_;
+ $num = 2 if $num == 3;
+ return $self->problems->recent_photos( $num, $lat, $lon, $dist );
+}
+
+1;
+
diff --git a/perllib/FixMyStreet/Cobrand/Southampton.pm b/perllib/FixMyStreet/Cobrand/Southampton.pm
index abf6e3082..bd461f5e2 100644
--- a/perllib/FixMyStreet/Cobrand/Southampton.pm
+++ b/perllib/FixMyStreet/Cobrand/Southampton.pm
@@ -76,9 +76,5 @@ sub recent_photos {
return $self->problems->recent_photos( $num, $lat, $lon, $dist );
}
-sub tilma_mid_point {
- return 189;
-}
-
1;
diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm
index ada19a406..ceced7267 100644
--- a/perllib/FixMyStreet/DB/Result/User.pm
+++ b/perllib/FixMyStreet/DB/Result/User.pm
@@ -151,4 +151,23 @@ sub council {
return $result;
}
+=head2 belongs_to_council
+
+ $belongs_to_council = $user->belongs_to_council( $council_list );
+
+Returns true if the user belongs to the comma seperated list of council ids passed in
+
+=cut
+
+sub belongs_to_council {
+ my $self = shift;
+ my $council = shift;
+
+ my %councils = map { $_ => 1 } split ',', $council;
+
+ return 1 if $self->from_council && $councils{ $self->from_council };
+
+ return 0;
+}
+
1;
diff --git a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
index a7e6d9736..bf085e32a 100644
--- a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
@@ -27,7 +27,8 @@ sub email_alerts ($) {
alert.cobrand_data as alert_cobrand_data, alert.parameter as alert_parameter, alert.parameter2 as alert_parameter2, ';
if ($head_table) {
$query .= "
- $item_table.id as item_id, $item_table.name as item_name, $item_table.text as item_text,
+ $item_table.id as item_id, $item_table.text as item_text,
+ $item_table.name as item_name, $item_table.anonymous as item_anonymous,
$head_table.*
from alert
inner join $item_table on alert.parameter::integer = $item_table.${head_table}_id
@@ -85,7 +86,7 @@ sub email_alerts ($) {
my $url = $cobrand->base_url_for_emails( $row->{alert_cobrand_data} );
if ($row->{item_text}) {
$data{problem_url} = $url . "/report/" . $row->{id};
- $data{data} .= $row->{item_name} . ' : ' if $row->{item_name};
+ $data{data} .= $row->{item_name} . ' : ' if $row->{item_name} && !$row->{item_anonymous};
$data{data} .= $row->{item_text} . "\n\n------\n\n";
} else {
$data{data} .= $url . "/report/" . $row->{id} . " - $row->{title}\n\n";
diff --git a/perllib/FixMyStreet/DB/ResultSet/Problem.pm b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
index 4de8f2e5f..89f17fa60 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Problem.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
@@ -161,10 +161,10 @@ sub timeline {
}
sub summary_count {
- my ( $rs, $restriction ) = @_;
+ my ( $rs ) = @_;
return $rs->search(
- $restriction,
+ undef,
{
group_by => ['state'],
select => [ 'state', { count => 'id' } ],
@@ -173,4 +173,31 @@ sub summary_count {
);
}
+sub unique_users {
+ my ( $rs ) = @_;
+
+ return $rs->search( {
+ state => [ 'confirmed', 'fixed' ],
+ }, {
+ select => [ { count => { distinct => 'user_id' } } ],
+ as => [ 'count' ]
+ } )->first->get_column('count');
+}
+
+sub categories_summary {
+ my ( $rs ) = @_;
+
+ my $categories = $rs->search( {
+ state => [ 'confirmed', 'fixed' ],
+ whensent => { '<' => \"NOW() - INTERVAL '4 weeks'" },
+ }, {
+ select => [ 'category', { count => 'id' }, { count => \"case when state='fixed' then 1 else null end" } ],
+ as => [ 'category', 'c', 'fixed' ],
+ group_by => [ 'category' ],
+ result_class => 'DBIx::Class::ResultClass::HashRefInflator'
+ } );
+ my %categories = map { $_->{category} => { total => $_->{c}, fixed => $_->{fixed} } } $categories->all;
+ return \%categories;
+}
+
1;
diff --git a/perllib/FixMyStreet/Geocode.pm b/perllib/FixMyStreet/Geocode.pm
index 286a10105..4ae3df368 100644
--- a/perllib/FixMyStreet/Geocode.pm
+++ b/perllib/FixMyStreet/Geocode.pm
@@ -9,53 +9,24 @@
package FixMyStreet::Geocode;
use strict;
-use Encode;
-use File::Slurp;
-use File::Path ();
-use LWP::Simple;
-use Digest::MD5 qw(md5_hex);
use URI::Escape;
-
-use mySociety::Locale;
-use mySociety::MaPit;
-use mySociety::PostcodeUtil;
-use mySociety::Web qw(NewURL);
+use FixMyStreet::Geocode::Bing;
+use FixMyStreet::Geocode::Google;
# lookup STRING CONTEXT
# Given a user-inputted string, try and convert it into co-ordinates using either
-# MaPit if it's a postcode, or Google Maps API otherwise. Returns an array of
+# MaPit if it's a postcode, or some web API otherwise. Returns an array of
# data, including an error if there is one (which includes a location being in
# Northern Ireland). The information in the query may be used by cobranded versions
# of the site to diambiguate locations.
sub lookup {
my ($s, $c) = @_;
- my ($latitude, $longitude, $error);
- if ( $c->cobrand->country eq 'GB') {
- if ($s =~ /^\d+$/) {
- $error = 'FixMyStreet is a UK-based website that currently works in England, Scotland, and Wales. Please enter either a postcode, or a Great British street name and area.';
- } elsif (mySociety::PostcodeUtil::is_valid_postcode($s)) {
- my $location = mySociety::MaPit::call('postcode', $s);
- unless ( $error = mapit_check_error( $c, $location ) ) {
- $latitude = $location->{wgs84_lat};
- $longitude = $location->{wgs84_lon};
- }
- }
- } elsif ( $c->cobrand->country eq 'NO') {
- if ($s =~ /^\d{4}$/) {
- my $location = mySociety::MaPit::call('postcode', $s);
- unless ( $error = mapit_check_error( $c, $location ) ) {
- $latitude = $location->{wgs84_lat};
- $longitude = $location->{wgs84_lon};
- }
- }
- }
- unless ($error || defined $latitude) {
- ($latitude, $longitude, $error) = FixMyStreet::Geocode::string($s, $c);
- }
- unless ($error || defined $latitude) {
- $error = _('Sorry, we could not find that location.');
- }
- return ($latitude, $longitude, $error);
+ my $data = $c->cobrand->geocode_postcode($s);
+ $data = string($s, $c)
+ unless $data->{error} || defined $data->{latitude};
+ $data->{error} = _('Sorry, we could not find that location.')
+ unless $data->{error} || defined $data->{latitude};
+ return ( $data->{latitude}, $data->{longitude}, $data->{error} );
}
# string STRING CONTEXT
@@ -68,148 +39,10 @@ sub string {
$s = URI::Escape::uri_escape_utf8($s);
$s =~ s/%20/+/g;
my $params = $c->cobrand->disambiguate_location();
- if ( FixMyStreet->config('BING_MAPS_API_KEY') ) {
- my $lookup = FixMyStreet::Geocode::string_bing($s, $c, $params);
- return ( $lookup->{latitude}, $lookup->{longitude}, $lookup->{error} );
- }
- if ( FixMyStreet->config('GOOGLE_MAPS_API_KEY') ) {
- my $lookup = FixMyStreet::Geocode::string_google($s, $c, $params);
- return ( $lookup->{latitude}, $lookup->{longitude}, $lookup->{error} );
- }
-}
-
-# string_google STRING CONTEXT
-# Looks up on Google Maps API, and caches, a user-inputted location.
-# Returns array of (LAT, LON, ERROR), where ERROR is either undef, a string, or
-# an array of matches if there are more than one. The information in the query
-# may be used to disambiguate the location in cobranded versions of the site.
-sub string_google {
- my ( $s, $c, $params ) = @_;
-
- my $url = 'http://maps.google.com/maps/geo?q=' . $s;
- $url .= '&ll=' . $params->{centre} if $params->{centre};
- $url .= '&spn=' . $params->{span} if $params->{span};
- $url .= '&gl=' . $params->{country} if $params->{country};
- $url .= '&hl=' . $params->{lang} if $params->{lang};
-
- my $cache_dir = FixMyStreet->config('GEO_CACHE') . 'google/';
- my $cache_file = $cache_dir . md5_hex($url);
- my $js;
- if (-s $cache_file) {
- $js = File::Slurp::read_file($cache_file);
- } else {
- # For some reason adding gl=uk is no longer sufficient to make google
- # think we are in the UK for some locations so we explictly add UK to
- # the address. We do it here so as not to invalidate existing cache
- # entries
- if ( $c->cobrand->country eq 'GB'
- && $url !~ /,\+UK/
- && $url !~ /united\++kingdom$/ )
- {
- if ( $url =~ /&/ ) {
- $url =~ s/&/,+UK&/;
- } else {
- $url .= ',+UK';
- }
- }
- $url .= '&sensor=false&key=' . FixMyStreet->config('GOOGLE_MAPS_API_KEY');
- $js = LWP::Simple::get($url);
- $js = encode_utf8($js) if utf8::is_utf8($js);
- File::Path::mkpath($cache_dir);
- File::Slurp::write_file($cache_file, $js) if $js && $js !~ /"code":6[12]0/;
- }
-
- if (!$js) {
- return { error => _('Sorry, we could not parse that location. Please try again.') };
- } elsif ($js =~ /BT\d/) {
- # Northern Ireland, hopefully
- return { error => _("We do not cover Northern Ireland, I'm afraid, as our licence doesn't include any maps for the region.") };
- }
-
- $js = JSON->new->utf8->allow_nonref->decode($js);
- if ($js->{Status}->{code} ne '200') {
- return { error => _('Sorry, we could not find that location.') };
- }
-
- my $results = $js->{Placemark};
- my ( $error, @valid_locations, $latitude, $longitude );
- foreach (@$results) {
- next unless $_->{AddressDetails}->{Accuracy} >= 4;
- my $address = $_->{address};
- next unless $c->cobrand->geocoded_string_check( $address );
- ( $longitude, $latitude ) = @{ $_->{Point}->{coordinates} };
- push (@$error, $address);
- push (@valid_locations, $_);
- }
- return { latitude => $latitude, longitude => $longitude } if scalar @valid_locations == 1;
- return { error => $error };
-}
-
-# string_bing STRING CONTEXT
-# Looks up on Bing Maps API, and caches, a user-inputted location.
-# Returns array of (LAT, LON, ERROR), where ERROR is either undef, a string, or
-# an array of matches if there are more than one. The information in the query
-# may be used to disambiguate the location in cobranded versions of the site.
-sub string_bing {
- my ( $s, $c, $params ) = @_;
- my $url = "http://dev.virtualearth.net/REST/v1/Locations?q=$s&c=en-GB"; # FIXME nb-NO for Norway
- $url .= '&mapView=' . $params->{bounds}[0] . ',' . $params->{bounds}[1]
- if $params->{bounds};
- $url .= '&userLocation=' . $params->{centre} if $params->{centre};
-
- my $cache_dir = FixMyStreet->config('GEO_CACHE') . 'bing/';
- my $cache_file = $cache_dir . md5_hex($url);
- my $js;
- if (-s $cache_file) {
- $js = File::Slurp::read_file($cache_file);
- } else {
- $url .= '&key=' . FixMyStreet->config('BING_MAPS_API_KEY');
- $js = LWP::Simple::get($url);
- $js = encode_utf8($js) if utf8::is_utf8($js);
- File::Path::mkpath($cache_dir);
- File::Slurp::write_file($cache_file, $js) if $js;
- }
-
- if (!$js) {
- return { error => _('Sorry, we could not parse that location. Please try again.') };
- } elsif ($js =~ /BT\d/) {
- return { error => _("We do not cover Northern Ireland, I'm afraid, as our licence doesn't include any maps for the region.") };
- }
-
- $js = JSON->new->utf8->allow_nonref->decode($js);
- if ($js->{statusCode} ne '200') {
- return { error => _('Sorry, we could not find that location.') };
- }
-
- my $results = $js->{resourceSets}->[0]->{resources};
- my ( $error, @valid_locations, $latitude, $longitude );
- foreach (@$results) {
- my $address = $_->{name};
- next unless $_->{address}->{countryRegion} eq 'United Kingdom'; # FIXME This is UK only
- ( $latitude, $longitude ) = @{ $_->{point}->{coordinates} };
- push (@$error, $address);
- push (@valid_locations, $_);
- }
- return { latitude => $latitude, longitude => $longitude } if scalar @valid_locations == 1;
- return { error => $error };
-}
-
-sub mapit_check_error {
- my ( $c, $location ) = @_;
- if ($location->{error}) {
- return _('That postcode was not recognised, sorry.') if $location->{code} =~ /^4/;
- return $location->{error};
- }
- if ( $c->cobrand->country eq 'GB') {
- my $island = $location->{coordsyst};
- if (!$island) {
- return _("Sorry, that appears to be a Crown dependency postcode, which we don't cover.");
- }
- if ($island eq 'I') {
- return _("We do not cover Northern Ireland, I'm afraid, as our licence doesn't include any maps for the region.");
- }
- }
- return 0;
+ return FixMyStreet::Geocode::Bing::string($s, $c, $params)
+ if FixMyStreet->config('BING_MAPS_API_KEY');
+ return FixMyStreet::Geocode::Google::string($s, $c, $params)
+ if FixMyStreet->config('GOOGLE_MAPS_API_KEY');
}
1;
diff --git a/perllib/FixMyStreet/Geocode/Bing.pm b/perllib/FixMyStreet/Geocode/Bing.pm
new file mode 100644
index 000000000..cfeffc856
--- /dev/null
+++ b/perllib/FixMyStreet/Geocode/Bing.pm
@@ -0,0 +1,67 @@
+#!/usr/bin/perl
+#
+# FixMyStreet::Geocode::Bing
+# Geocoding with Bing for FixMyStreet.
+#
+# Copyright (c) 2011 UK Citizens Online Democracy. All rights reserved.
+# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/
+
+package FixMyStreet::Geocode::Bing;
+
+use strict;
+use Encode;
+use File::Slurp;
+use File::Path ();
+use LWP::Simple;
+use Digest::MD5 qw(md5_hex);
+
+# string STRING CONTEXT
+# Looks up on Bing Maps API, and caches, a user-inputted location.
+# Returns array of (LAT, LON, ERROR), where ERROR is either undef, a string, or
+# an array of matches if there are more than one. The information in the query
+# may be used to disambiguate the location in cobranded versions of the site.
+sub string {
+ my ( $s, $c, $params ) = @_;
+ my $url = "http://dev.virtualearth.net/REST/v1/Locations?q=$s&c=en-GB"; # FIXME nb-NO for Norway
+ $url .= '&mapView=' . $params->{bounds}[0] . ',' . $params->{bounds}[1]
+ if $params->{bounds};
+ $url .= '&userLocation=' . $params->{centre} if $params->{centre};
+
+ my $cache_dir = FixMyStreet->config('GEO_CACHE') . 'bing/';
+ my $cache_file = $cache_dir . md5_hex($url);
+ my $js;
+ if (-s $cache_file) {
+ $js = File::Slurp::read_file($cache_file);
+ } else {
+ $url .= '&key=' . FixMyStreet->config('BING_MAPS_API_KEY');
+ $js = LWP::Simple::get($url);
+ $js = encode_utf8($js) if utf8::is_utf8($js);
+ File::Path::mkpath($cache_dir);
+ File::Slurp::write_file($cache_file, $js) if $js;
+ }
+
+ if (!$js) {
+ return { error => _('Sorry, we could not parse that location. Please try again.') };
+ } elsif ($js =~ /BT\d/) {
+ return { error => _("We do not cover Northern Ireland, I'm afraid, as our licence doesn't include any maps for the region.") };
+ }
+
+ $js = JSON->new->utf8->allow_nonref->decode($js);
+ if ($js->{statusCode} ne '200') {
+ return { error => _('Sorry, we could not find that location.') };
+ }
+
+ my $results = $js->{resourceSets}->[0]->{resources};
+ my ( $error, @valid_locations, $latitude, $longitude );
+ foreach (@$results) {
+ my $address = $_->{name};
+ next unless $_->{address}->{countryRegion} eq 'United Kingdom'; # FIXME This is UK only
+ ( $latitude, $longitude ) = @{ $_->{point}->{coordinates} };
+ push (@$error, $address);
+ push (@valid_locations, $_);
+ }
+ return { latitude => $latitude, longitude => $longitude } if scalar @valid_locations == 1;
+ return { error => $error };
+}
+
+1;
diff --git a/perllib/FixMyStreet/Geocode/Google.pm b/perllib/FixMyStreet/Geocode/Google.pm
new file mode 100644
index 000000000..c37a750a2
--- /dev/null
+++ b/perllib/FixMyStreet/Geocode/Google.pm
@@ -0,0 +1,85 @@
+#!/usr/bin/perl
+#
+# FixMyStreet::Geocode
+# The geocoding functions for FixMyStreet.
+#
+# Copyright (c) 2010 UK Citizens Online Democracy. All rights reserved.
+# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/
+
+package FixMyStreet::Geocode::Google;
+
+use strict;
+use Encode;
+use File::Slurp;
+use File::Path ();
+use LWP::Simple;
+use Digest::MD5 qw(md5_hex);
+
+# string STRING CONTEXT
+# Looks up on Google Maps API, and caches, a user-inputted location.
+# Returns array of (LAT, LON, ERROR), where ERROR is either undef, a string, or
+# an array of matches if there are more than one. The information in the query
+# may be used to disambiguate the location in cobranded versions of the site.
+sub string {
+ my ( $s, $c, $params ) = @_;
+
+ my $url = 'http://maps.google.com/maps/geo?q=' . $s;
+ $url .= '&ll=' . $params->{centre} if $params->{centre};
+ $url .= '&spn=' . $params->{span} if $params->{span};
+ $url .= '&gl=' . $params->{country} if $params->{country};
+ $url .= '&hl=' . $params->{lang} if $params->{lang};
+
+ my $cache_dir = FixMyStreet->config('GEO_CACHE') . 'google/';
+ my $cache_file = $cache_dir . md5_hex($url);
+ my $js;
+ if (-s $cache_file) {
+ $js = File::Slurp::read_file($cache_file);
+ } else {
+ # For some reason adding gl=uk is no longer sufficient to make google
+ # think we are in the UK for some locations so we explictly add UK to
+ # the address. We do it here so as not to invalidate existing cache
+ # entries
+ if ( $c->cobrand->country eq 'GB'
+ && $url !~ /,\+UK/
+ && $url !~ /united\++kingdom$/ )
+ {
+ if ( $url =~ /&/ ) {
+ $url =~ s/&/,+UK&/;
+ } else {
+ $url .= ',+UK';
+ }
+ }
+ $url .= '&sensor=false&key=' . FixMyStreet->config('GOOGLE_MAPS_API_KEY');
+ $js = LWP::Simple::get($url);
+ $js = encode_utf8($js) if utf8::is_utf8($js);
+ File::Path::mkpath($cache_dir);
+ File::Slurp::write_file($cache_file, $js) if $js && $js !~ /"code":6[12]0/;
+ }
+
+ if (!$js) {
+ return { error => _('Sorry, we could not parse that location. Please try again.') };
+ } elsif ($js =~ /BT\d/) {
+ # Northern Ireland, hopefully
+ return { error => _("We do not currently cover Northern Ireland, I'm afraid.") };
+ }
+
+ $js = JSON->new->utf8->allow_nonref->decode($js);
+ if ($js->{Status}->{code} ne '200') {
+ return { error => _('Sorry, we could not find that location.') };
+ }
+
+ my $results = $js->{Placemark};
+ my ( $error, @valid_locations, $latitude, $longitude );
+ foreach (@$results) {
+ next unless $_->{AddressDetails}->{Accuracy} >= 4;
+ my $address = $_->{address};
+ next unless $c->cobrand->geocoded_string_check( $address );
+ ( $longitude, $latitude ) = @{ $_->{Point}->{coordinates} };
+ push (@$error, $address);
+ push (@valid_locations, $_);
+ }
+ return { latitude => $latitude, longitude => $longitude } if scalar @valid_locations == 1;
+ return { error => $error };
+}
+
+1;
diff --git a/perllib/FixMyStreet/Geocode/OSM.pm b/perllib/FixMyStreet/Geocode/OSM.pm
new file mode 100644
index 000000000..b1becaa7a
--- /dev/null
+++ b/perllib/FixMyStreet/Geocode/OSM.pm
@@ -0,0 +1,116 @@
+#!/usr/bin/perl
+#
+# FixMyStreet:Geocode::OSM
+# OpenStreetmap forward and reverse geocoding for FixMyStreet.
+#
+# Copyright (c) 2011 Petter Reinholdtsen. Some rights reserved.
+# Email: pere@hungry.com
+
+package FixMyStreet::Geocode::OSM;
+
+use warnings;
+use strict;
+
+use Memcached;
+use mySociety::Config;
+use LWP::Simple;
+use XML::Simple;
+
+my $osmapibase = "http://www.openstreetmap.org/api/";
+my $nominatimbase = "http://nominatim.openstreetmap.org/";
+
+
+sub lookup_location {
+ my ($latitude, $longitude, $zoom) = @_;
+ my $url =
+ "${nominatimbase}reverse?format=xml&zoom=$zoom&lat=$latitude&lon=$longitude";
+ my $key = "OSM:lookup_location:$url";
+ my $result = Memcached::get($key);
+ unless ($result) {
+ my $j = LWP::Simple::get($url);
+ if ($j) {
+ Memcached::set($key, $j, 3600);
+ my $ref = XMLin($j);
+ return $ref;
+ } else {
+ print STDERR "No reply from $url\n";
+ }
+ return undef;
+ }
+ return XMLin($result);
+}
+
+sub _osmxml_to_hash {
+ my ($xml, $type) = @_;
+ my $ref = XMLin($xml);
+ my %tags;
+ if ('ARRAY' eq ref $ref->{$type}->{tag}) {
+ map { $tags{$_->{'k'}} = $_->{'v'} } @{$ref->{$type}->{tag}};
+ return \%tags;
+ } else {
+ return undef;
+ }
+}
+
+sub get_object_tags {
+ my ($type, $id) = @_;
+ my $url = "${osmapibase}0.6/$type/$id";
+ my $key = "OSM:get_object_tags:$url";
+ my $result = Memcached::get($key);
+ unless ($result) {
+ my $j = LWP::Simple::get($url);
+ if ($j) {
+ Memcached::set($key, $j, 3600);
+ return _osmxml_to_hash($j, $type);
+ } else {
+ print STDERR "No reply from $url\n";
+ }
+ return undef;
+ }
+ return _osmxml_to_hash($result, $type);
+}
+
+# A better alternative might be
+# http://www.geonames.org/maps/osm-reverse-geocoder.html#findNearbyStreetsOSM
+sub get_nearest_road_tags {
+ my ( $cobrand, $latitude, $longitude ) = @_;
+ my $inforef = lookup_location($latitude, $longitude, 16);
+ if (exists $inforef->{result}->{osm_type}
+ && 'way' eq $inforef->{result}->{osm_type}) {
+ my $osmtags = get_object_tags('way',
+ $inforef->{result}->{osm_id});
+ unless ( exists $osmtags->{operator} ) {
+ $osmtags->{operatorguess} = $cobrand->guess_road_operator( $osmtags );
+ }
+ return $osmtags;
+ }
+ return undef;
+}
+
+sub closest_road_text {
+ my ( $cobrand, $latitude, $longitude ) = @_;
+ my $str = '';
+ my $osmtags = get_nearest_road_tags( $cobrand, $latitude, $longitude );
+ if ($osmtags) {
+ my ($name, $ref) = ('','');
+ $name = $osmtags->{name} if exists $osmtags->{name};
+ $ref = " ($osmtags->{ref})" if exists $osmtags->{ref};
+ if ($name || $ref) {
+ $str .= _('The following information about the nearest road might be inaccurate or irrelevant, if the problem is close to several roads or close to a road without a name registered in OpenStreetMap.') . "\n\n";
+ $str .= sprintf(_("Nearest named road to the pin placed on the map (automatically generated using OpenStreetMap): %s%s"),
+ $name, $ref) . "\n\n";
+
+ if (my $operator = $osmtags->{operator}) {
+ $str .= sprintf(_("Road operator for this named road (from OpenStreetMap): %s"),
+ $operator) . "\n\n";
+ } elsif ($operator = $osmtags->{operatorguess}) {
+ $str .= sprintf(_("Road operator for this named road (derived from road reference number and type): %s"),
+ $operator) . "\n\n";
+ }
+ }
+ }
+ return $str;
+}
+
+1;
+
diff --git a/perllib/FixMyStreet/Map.pm b/perllib/FixMyStreet/Map.pm
index 6b5a811a6..825e1cd19 100644
--- a/perllib/FixMyStreet/Map.pm
+++ b/perllib/FixMyStreet/Map.pm
@@ -13,7 +13,6 @@ use strict;
use Module::Pluggable
sub_name => 'maps',
search_path => __PACKAGE__,
- except => 'FixMyStreet::Map::Tilma::Original',
require => 1;
# Get the list of maps we want and load map classes at compile time
@@ -23,6 +22,7 @@ use mySociety::Config;
use mySociety::Gaze;
use mySociety::Locale;
use mySociety::Web qw(ent);
+use Utils;
=head2 allowed_maps
@@ -124,8 +124,19 @@ sub click_to_wgs84 {
return $map_class->click_to_wgs84(@_);
}
+=head2 tile_xy_to_wgs84
+
+Takes the tile x,y and converts to lat, lon. Legacy to deal with old URLs,
+hence hard-coded things.
+
+=cut
+
sub tile_xy_to_wgs84 {
- return $map_class->tile_xy_to_wgs84(@_);
+ my ( $x, $y ) = @_;
+ my $easting = int( $x * (5000/31) + 0.5 );
+ my $northing = int( $y * (5000/31) + 0.5 );
+ my ( $lat, $lon ) = Utils::convert_en_to_latlon( $easting, $northing );
+ return ( $lat, $lon );
}
1;
diff --git a/perllib/FixMyStreet/Map/FMS.pm b/perllib/FixMyStreet/Map/FMS.pm
index c54ee8f3b..2e40bfde3 100644
--- a/perllib/FixMyStreet/Map/FMS.pm
+++ b/perllib/FixMyStreet/Map/FMS.pm
@@ -41,17 +41,17 @@ sub map_tiles {
my ($self, $x, $y, $z) = @_;
if ($z >= 16) {
return [
- "http://a.os.openstreetmap.org/sv/$z/" . ($x-1) . "/" . ($y-1) . ".png",
- "http://b.os.openstreetmap.org/sv/$z/$x/" . ($y-1) . ".png",
- "http://c.os.openstreetmap.org/sv/$z/" . ($x-1) . "/$y.png",
- "http://os.openstreetmap.org/sv/$z/$x/$y.png",
+ "http://a.tilma.mysociety.org/sv/$z/" . ($x-1) . "/" . ($y-1) . ".png",
+ "http://b.tilma.mysociety.org/sv/$z/$x/" . ($y-1) . ".png",
+ "http://c.tilma.mysociety.org/sv/$z/" . ($x-1) . "/$y.png",
+ "http://tilma.mysociety.org/sv/$z/$x/$y.png",
];
} else {
return [
- "http://ecn.t0.tiles.virtualearth.net/tiles/r" . get_quadkey($x-1, $y-1, $z) . ".png?g=587&productSet=mmOS",
- "http://ecn.t1.tiles.virtualearth.net/tiles/r" . get_quadkey($x, $y-1, $z) . ".png?g=587&productSet=mmOS",
- "http://ecn.t2.tiles.virtualearth.net/tiles/r" . get_quadkey($x-1, $y, $z) . ".png?g=587&productSet=mmOS",
- "http://ecn.t3.tiles.virtualearth.net/tiles/r" . get_quadkey($x, $y, $z) . ".png?g=587&productSet=mmOS",
+ "http://ecn.t0.tiles.virtualearth.net/tiles/r" . get_quadkey($x-1, $y-1, $z) . ".png?g=701&productSet=mmOS",
+ "http://ecn.t1.tiles.virtualearth.net/tiles/r" . get_quadkey($x, $y-1, $z) . ".png?g=701&productSet=mmOS",
+ "http://ecn.t2.tiles.virtualearth.net/tiles/r" . get_quadkey($x-1, $y, $z) . ".png?g=701&productSet=mmOS",
+ "http://ecn.t3.tiles.virtualearth.net/tiles/r" . get_quadkey($x, $y, $z) . ".png?g=701&productSet=mmOS",
];
}
}
diff --git a/perllib/FixMyStreet/Map/Tilma/OL/1_10k.pm b/perllib/FixMyStreet/Map/Tilma/OL/1_10k.pm
deleted file mode 100644
index 34df8dc8b..000000000
--- a/perllib/FixMyStreet/Map/Tilma/OL/1_10k.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/perl
-#
-# FixMyStreet:Map::Tilma::1_10k_OL
-# Using tilma.mysociety.org with OpenLayers
-#
-# Copyright (c) 2010 UK Citizens Online Democracy. All rights reserved.
-# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/
-
-package FixMyStreet::Map::Tilma::OL::1_10k;
-use base 'FixMyStreet::Map::Tilma::OpenLayers';
-
-use strict;
-
-sub tile_width { return 254; }
-sub tif_size_m { return 5000; }
-sub tif_size_px { return 7874; }
-sub scale_factor { return tif_size_m() / (tif_size_px() / tile_width()); }
-sub tile_type { return '10k-full'; }
-
-sub copyright {
- return _('&copy; Crown copyright. All rights reserved. Ministry of Justice 100037819&nbsp;2008.');
-}
-
-sub watermark {
- return 1;
-}
-
-1;
diff --git a/perllib/FixMyStreet/Map/Tilma/OL/StreetView.pm b/perllib/FixMyStreet/Map/Tilma/OL/StreetView.pm
deleted file mode 100644
index 2a531766c..000000000
--- a/perllib/FixMyStreet/Map/Tilma/OL/StreetView.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/perl
-#
-# FixMyStreet:Map::TilmaXY
-# Using tilma.mysociety.org but accessing images directly.
-#
-# Copyright (c) 2010 UK Citizens Online Democracy. All rights reserved.
-# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/
-
-package FixMyStreet::Map::Tilma::OL::StreetView;
-use base 'FixMyStreet::Map::Tilma::OpenLayers';
-
-use strict;
-
-sub tile_width { return 250; }
-sub tif_size_m { return 5000; }
-sub tif_size_px { return 5000; }
-sub scale_factor { return tif_size_m() / (tif_size_px() / tile_width()); }
-sub tile_type { return 'streetview'; }
-
-sub copyright {
- return _('Map contains Ordnance Survey data &copy; Crown copyright and database right 2010.');
-}
-
-sub watermark {
- return 0;
-}
-
-1;
diff --git a/perllib/FixMyStreet/Map/Tilma/OpenLayers.pm b/perllib/FixMyStreet/Map/Tilma/OpenLayers.pm
deleted file mode 100644
index 31e9eb096..000000000
--- a/perllib/FixMyStreet/Map/Tilma/OpenLayers.pm
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/perl
-#
-# FixMyStreet:Map::Tilma::1_10k_OL
-# Using tilma.mysociety.org with OpenLayers
-#
-# Copyright (c) 2010 UK Citizens Online Democracy. All rights reserved.
-# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/
-
-package FixMyStreet::Map::Tilma::OpenLayers;
-
-use strict;
-
-sub TILE_WIDTH() { return $FixMyStreet::Map::map_class->tile_width; }
-sub SCALE_FACTOR() { return $FixMyStreet::Map::map_class->scale_factor; }
-sub TILE_TYPE() { return $FixMyStreet::Map::map_class->tile_type; }
-
-# display_map C PARAMS
-# PARAMS include:
-# latitude, longitude for the centre point of the map
-# TYPE is 1 if the map is clickable, 0 otherwise.
-# PINS is array of pins to show, location and colour
-sub display_map {
- my ($self, $c, %params) = @_;
- $c->stash->{map} = {
- %params,
- type => 'tilma/openlayers',
- tile_type => TILE_TYPE,
- tilewidth => TILE_WIDTH,
- watermark => $self->watermark(),
- copyright => $self->copyright(),
- maxResolution => SCALE_FACTOR / TILE_WIDTH,
- };
-}
-
-1;
diff --git a/perllib/FixMyStreet/Map/Tilma/Original.pm b/perllib/FixMyStreet/Map/Tilma/Original.pm
deleted file mode 100644
index 46cf3ad40..000000000
--- a/perllib/FixMyStreet/Map/Tilma/Original.pm
+++ /dev/null
@@ -1,250 +0,0 @@
-#!/usr/bin/perl
-#
-# FixMyStreet:Map
-# Adding the ability to have different maps on FixMyStreet.
-#
-# Copyright (c) 2010 UK Citizens Online Democracy. All rights reserved.
-# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/
-
-package FixMyStreet::Map::Tilma::Original;
-
-use strict;
-use LWP::Simple;
-
-use mySociety::GeoUtil;
-use mySociety::Locale;
-use mySociety::Web qw(ent NewURL);
-use Utils;
-use RABX;
-
-sub TILE_WIDTH() { return $FixMyStreet::Map::map_class->tile_width; }
-sub SCALE_FACTOR() { return $FixMyStreet::Map::map_class->scale_factor; }
-sub TILE_TYPE() { return $FixMyStreet::Map::map_class->tile_type; }
-
-sub _ll_to_en {
- my ($lat, $lon) = @_;
- return Utils::convert_latlon_to_en( $lat, $lon );
-}
-
-# display_map C PARAMS
-# PARAMS include:
-# latitude, longitude for the centre point of the map
-# CLICKABLE is set if the map is clickable
-# PINS is array of pins to show, location and colour
-sub display_map {
- my ($self, $c, %params) = @_;
- my $mid_point = TILE_WIDTH; # Map is 2 TILE_WIDTHs in size, square.
- if (my $mp = $c->cobrand->tilma_mid_point) {
- $mid_point = $mp;
- }
-
- # convert map center point to easting, northing
- ( $params{easting}, $params{northing} ) =
- _ll_to_en( $params{latitude}, $params{longitude} );
-
- # X/Y tile co-ords may be overridden in the query string
- my @vars = qw(x y);
- my %input = map { $_ => $c->req->params->{$_} || '' } @vars;
- ($input{x}) = $input{x} =~ /^(\d+)/; $input{x} ||= 0;
- ($input{y}) = $input{y} =~ /^(\d+)/; $input{y} ||= 0;
-
- my ($x, $y, $px, $py) = os_to_px_with_adjust($c, $params{easting}, $params{northing}, $input{x}, $input{y});
-
- foreach my $pin (@{$params{pins}}) {
- my ( $e, $n ) = _ll_to_en( $pin->{latitude}, $pin->{longitude} );
- $pin->{px} = os_to_px($e, $x);
- $pin->{py} = os_to_px($n, $y, 1);
- }
-
- $px = defined($px) ? $mid_point - $px : 0;
- $py = defined($py) ? $mid_point - $py : 0;
- $x = int($x)<=0 ? 0 : $x;
- $y = int($y)<=0 ? 0 : $y;
- my $url = 'http://tilma.mysociety.org/tileserver/' . TILE_TYPE . '/';
- my $tiles_url = $url . ($x-1) . '-' . $x . ',' . ($y-1) . '-' . $y . '/RABX';
- my $tiles = LWP::Simple::get($tiles_url);
- my $tileids = RABX::unserialise($tiles);
- $c->stash->{map} = {
- %params,
- type => 'tilma/original',
- tiles => $tiles,
- url => $url,
- tileids => $tileids,
- x => $x,
- y => $y,
- px => $px,
- py => $py,
- tile_type => TILE_TYPE,
- tilewidth => TILE_WIDTH,
- watermark => $self->watermark(),
- copyright => $self->copyright(),
- };
-}
-
-sub display_pin {
- my ($c, $px, $py, $col, $id, $title, $num) = @_;
- $num = '' if !$num || $num > 9;
- my $host = $c->cobrand->base_url_with_lang;
- my %cols = (red=>'R', green=>'G', blue=>'B', purple=>'P');
- my $out = '<img class="pin" src="' . $host . '/i/pin' . $cols{$col}
- . $num . '.gif" alt="' . _('Problem') . '" style="top:' . ($py-59)
- . 'px; left:' . ($px) . 'px; position: absolute;">';
- return $out unless $id;
- my $url = $c->uri_for( '/report/' . $id );
- $out = '<a title="' . ent($title) . '" href="' . $url . '">' . $out . '</a>';
- return $out;
-}
-
-sub map_pins {
- my ($self, $c, $interval) = @_;
-
- # Our current X/Y middle of visible map
- my $x = ( $c->req->param('x') || 0 ) + 0;
- my $y = ( $c->req->param('y') || 0 ) + 0;
-
- # Where we started as that's the (0,0) we have to work to
- my $sx = ( $c->req->param('sx') || 0 ) + 0;
- my $sy = ( $c->req->param('sy') || 0 ) + 0;
-
- my $e = tile_to_os($x);
- my $n = tile_to_os($y);
-
- my ( $lat, $lon ) = Utils::convert_en_to_latlon( $e, $n );
-
- my ( $around_map, $around_map_list, $nearby, $dist ) =
- FixMyStreet::Map::map_features( $c, $lat, $lon, $interval );
-
- my $pins = '';
- foreach (@$around_map) {
- my ( $easting, $northing ) =
- _ll_to_en( $_->latitude, $_->longitude );
- my $px = os_to_px($easting, $sx);
- my $py = os_to_px($northing, $sy, 1);
- my $col = exists FixMyStreet::DB::Result::Problem->fixed_states()->{$_->state} ? 'green' : 'red';
- $pins .= display_pin($c, $px, $py, $col, $_->id, $_->title);
- }
-
- foreach (@$nearby) {
- my $p = $_->problem;
- my ( $easting, $northing ) =
- _ll_to_en( $p->latitude, $p->longitude );
- my $px = os_to_px($easting, $sx);
- my $py = os_to_px($northing, $sy, 1);
- my $col = exists FixMyStreet::DB::Result::Problem->fixed_states()->{$p->state} ? 'green' : 'red';
- $pins .= display_pin($c, $px, $py, $col, $p->id, $p->title);
- }
-
- return ($pins, $around_map_list, $nearby, $dist);
-}
-
-# P is easting or northing
-# C is centre tile reference of displayed map
-sub os_to_px {
- my ($p, $c, $invert) = @_;
- return tile_to_px(os_to_tile($p), $c, $invert);
-}
-
-# Convert tile co-ordinates to pixel co-ordinates from top left of map
-# C is centre tile reference of displayed map
-sub tile_to_px {
- my ($p, $c, $invert) = @_;
- $p = TILE_WIDTH * ($p - $c + 1);
- $p = 2 * TILE_WIDTH - $p if $invert;
- $p = int($p + .5 * ($p <=> 0));
- return $p;
-}
-
-# Tile co-ordinates are linear scale of OS E/N
-# Will need more generalising when more zooms appear
-sub os_to_tile {
- return $_[0] / SCALE_FACTOR;
-}
-
-sub tile_to_os {
- return int($_[0] * SCALE_FACTOR + 0.5);
-}
-
-=head2 tile_xy_to_wgs84
-
- ($lat, $lon) = tile_xy_to_wgs84( $x, $y );
-
-Takes the tile x,y and converts to lat, lon.
-
-=cut
-
-sub tile_xy_to_wgs84 {
- my ( $self, $x, $y ) = @_;
-
- my $easting = tile_to_os($x);
- my $northing = tile_to_os($y);
-
- my ( $lat, $lon ) = Utils::convert_en_to_latlon( $easting, $northing );
- return ( $lat, $lon );
-}
-
-
-sub click_to_tile {
- my ($pin_tile, $pin, $invert) = @_;
- $pin -= TILE_WIDTH while $pin > TILE_WIDTH;
- $pin += TILE_WIDTH while $pin < 0;
- $pin = TILE_WIDTH - $pin if $invert; # image submits measured from top down
- return $pin_tile + $pin / TILE_WIDTH;
-}
-
-# Given some click co-ords (the tile they were on, and where in the
-# tile they were), convert to OSGB36 and return.
-sub click_to_os {
- my ($pin_tile_x, $pin_x, $pin_tile_y, $pin_y) = @_;
- my $tile_x = click_to_tile($pin_tile_x, $pin_x);
- my $tile_y = click_to_tile($pin_tile_y, $pin_y, 1);
- my $easting = tile_to_os($tile_x);
- my $northing = tile_to_os($tile_y);
- return ($easting, $northing);
-}
-
-# Given some click co-ords (the tile they were on, and where in the
-# tile they were), convert to WGS84 and return.
-sub click_to_wgs84 {
- my $self = shift;
- my $c = shift;
- my ( $easting, $northing ) = click_to_os(@_);
- my ( $lat, $lon ) = mySociety::GeoUtil::national_grid_to_wgs84( $easting, $northing, 'G' );
- return ( $lat, $lon );
-}
-
-# Given (E,N) and potential override (X,Y), return the X/Y tile for the centre
-# of the map (either to get the point near the middle, or the override X,Y),
-# and the pixel co-ords of the point, relative to that map.
-sub os_to_px_with_adjust {
- my ($c, $easting, $northing, $in_x, $in_y) = @_;
-
- my $x = os_to_tile($easting);
- my $y = os_to_tile($northing);
- my $x_tile = $in_x || int($x);
- my $y_tile = $in_y || int($y);
-
- # Try and have point near centre of map
- if (!$in_x && $x - $x_tile > 0.5) {
- $x_tile += 1;
- }
- if (!$in_y && $y - $y_tile > 0.5) {
- $y_tile += 1;
- }
-
- my $px = os_to_px($easting, $x_tile);
- my $py = os_to_px($northing, $y_tile, 1);
- if ($c->cobrand->tilma_mid_point == 189) { # Map is 380px, so might need to adjust
- if (!$in_x && $px > 380) {
- $x_tile++;
- $px = os_to_px($easting, $x_tile);
- }
- if (!$in_y && $py > 380) {
- $y_tile--;
- $py = os_to_px($northing, $y_tile, 1);
- }
- }
-
- return ($x_tile, $y_tile, $px, $py);
-}
-
-1;
diff --git a/perllib/FixMyStreet/Map/Tilma/Original/1_10k.pm b/perllib/FixMyStreet/Map/Tilma/Original/1_10k.pm
deleted file mode 100644
index 722df2a46..000000000
--- a/perllib/FixMyStreet/Map/Tilma/Original/1_10k.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/perl
-#
-# FixMyStreet:Map
-# Adding the ability to have different maps on FixMyStreet.
-#
-# Copyright (c) 2010 UK Citizens Online Democracy. All rights reserved.
-# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/
-
-package FixMyStreet::Map::Tilma::Original::1_10k;
-use base 'FixMyStreet::Map::Tilma::Original';
-
-use strict;
-
-sub tile_width { return 254; }
-sub tif_size_m { return 5000; }
-sub tif_size_px { return 7874; }
-sub scale_factor { return tif_size_m() / (tif_size_px() / tile_width()); }
-sub tile_type { return '10k-full'; }
-
-sub copyright {
- return _('&copy; Crown copyright. All rights reserved. Ministry of Justice 100037819&nbsp;2008.');
-}
-
-sub watermark {
- return 1;
-}
-
-1;
diff --git a/perllib/FixMyStreet/Map/Tilma/Original/StreetView.pm b/perllib/FixMyStreet/Map/Tilma/Original/StreetView.pm
deleted file mode 100644
index fe03fdb00..000000000
--- a/perllib/FixMyStreet/Map/Tilma/Original/StreetView.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/perl
-#
-# FixMyStreet:Map
-# Adding the ability to have different maps on FixMyStreet.
-#
-# Copyright (c) 2010 UK Citizens Online Democracy. All rights reserved.
-# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/
-
-package FixMyStreet::Map::Tilma::Original::StreetView;
-use base 'FixMyStreet::Map::Tilma::Original';
-
-use strict;
-
-sub tile_width { return 250; }
-sub tif_size_m { return 5000; }
-sub tif_size_px { return 5000; }
-sub scale_factor { return tif_size_m() / (tif_size_px() / tile_width()); }
-sub tile_type { return 'streetview'; }
-
-sub copyright {
- return _('Map contains Ordnance Survey data &copy; Crown copyright and database right 2010.');
-}
-
-sub watermark {
- return 0;
-}
-
-1;