diff options
author | M Somerville <matthew-github@dracos.co.uk> | 2020-05-29 11:09:36 +0100 |
---|---|---|
committer | Matthew Somerville <matthew@mysociety.org> | 2020-06-04 21:08:36 +0100 |
commit | abc63a85b47bbc6b9e81c8256a226864ac7fe0ce (patch) | |
tree | e3eb1fc9e6f50bc7cc235de626202da084449042 | |
parent | ce5588038dfafb2db53c7de7e0d34e8c59bed8ba (diff) |
Add Open Location Codes support to search box.
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | cpanfile | 1 | ||||
-rw-r--r-- | cpanfile.snapshot | 9 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Location.pm | 25 | ||||
-rw-r--r-- | t/Mock/Nominatim.pm | 5 | ||||
-rw-r--r-- | t/app/controller/around.t | 25 |
6 files changed, 67 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index d9fe1e282..1bd70243c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## Releases * Unreleased + - New features: + - Add Open Location Codes support to search box. #3047 - Bugfixes: - Fix issue with dashboard report CSV export. #3026 - bin/update-schema PostgreSQL 12 compatibility. #3043 @@ -80,6 +80,7 @@ requires 'Error'; requires 'FCGI'; # Required by e.g. Plack::Handler::FCGI requires 'File::Find'; requires 'File::Path'; +requires 'Geo::OLC'; requires 'Geography::NationalGrid', mirror => 'https://cpan.metacpan.org/'; requires 'Getopt::Long::Descriptive', '0.105'; diff --git a/cpanfile.snapshot b/cpanfile.snapshot index 53ce1f120..edc125960 100644 --- a/cpanfile.snapshot +++ b/cpanfile.snapshot @@ -3116,6 +3116,15 @@ DISTRIBUTIONS perl 5.014000 strict 0 warnings 0 + Geo-OLC-1 + pathname: J/JG/JGREELY/Geo-OLC-1.tar.gz + provides: + Geo::OLC 1 + requirements: + ExtUtils::MakeMaker 0 + List::Util 1 + Test::More 0 + perl 5.010001 Geography-NationalGrid-1.6 pathname: P/PK/PKENT/Geography-NationalGrid-1.6.tar.gz provides: diff --git a/perllib/FixMyStreet/App/Controller/Location.pm b/perllib/FixMyStreet/App/Controller/Location.pm index 416fb942a..3869ef8d3 100644 --- a/perllib/FixMyStreet/App/Controller/Location.pm +++ b/perllib/FixMyStreet/App/Controller/Location.pm @@ -6,6 +6,7 @@ BEGIN {extends 'Catalyst::Controller'; } use Encode; use FixMyStreet::Geocode; +use Geo::OLC; use Try::Tiny; use Utils; @@ -74,6 +75,30 @@ sub determine_location_from_pc : Private { map { Utils::truncate_coordinate($_) } ($1, $2); return $c->forward( 'check_location' ); } + + if (Geo::OLC::is_full($pc)) { + my $ref = Geo::OLC::decode($pc); + ($c->stash->{latitude}, $c->stash->{longitude}) = + map { Utils::truncate_coordinate($_) } @{$ref->{center}}; + return $c->forward( 'check_location' ); + } + + if ($pc =~ /^\s*([2-9CFGHJMPQRVWX]{4,6}\+[2-9CFGHJMPQRVWX]{2,3})\s+(.*)$/i) { + my ($code, $rest) = ($1, $2); + my ($lat, $lon, $error) = FixMyStreet::Geocode::lookup($rest, $c); + if (ref($error) eq 'ARRAY') { # Just take the first result + $lat = $error->[0]{latitude}; + $lon = $error->[0]{longitude}; + } + if (defined $lat && defined $lon) { + $code = Geo::OLC::recover_nearest($code, $lat, $lon); + my $ref = Geo::OLC::decode($code); + ($c->stash->{latitude}, $c->stash->{longitude}) = + map { Utils::truncate_coordinate($_) } @{$ref->{center}}; + return $c->forward( 'check_location' ); + } + } + if ( $c->cobrand->country eq 'GB' && $pc =~ /^([A-Z])([A-Z])([\d\s]{4,})$/i) { if (my $convert = gridref_to_latlon( $1, $2, $3 )) { ($c->stash->{latitude}, $c->stash->{longitude}) = diff --git a/t/Mock/Nominatim.pm b/t/Mock/Nominatim.pm index 806ebbfd3..d108256f5 100644 --- a/t/Mock/Nominatim.pm +++ b/t/Mock/Nominatim.pm @@ -1,6 +1,7 @@ package t::Mock::Nominatim; use JSON::MaybeXS; +use LWP::Protocol::PSGI; use Web::Simple; has json => ( @@ -35,6 +36,10 @@ sub query { {"osm_type"=>"way","osm_id"=>"4684282","lat"=>"55.9504009","lon"=>"-3.1858425","display_name"=>"High Street, Old Town, City of Ed\x{ed}nburgh, Scotland, EH1 1SP, United Kingdom","class"=>"highway","type"=>"tertiary","importance"=>0.55892577838734}, {"osm_type"=>"node","osm_id"=>"27424410","lat"=>"55.8596449","lon"=>"-4.240377","display_name"=>"High Street, Collegelands, Merchant City, Glasgow, Glasgow City, Scotland, G, United Kingdom","class"=>"railway","type"=>"station","importance"=>0.53074299592768} ]; + } elsif ($q eq 'edinburgh') { + return [ + {"osm_type"=>"node","osm_id"=>"17898859","lat"=>"55.9533456","lon"=>"-3.1883749","display_name"=>"Edinburgh","class"=>"place","type"=>"place:city","importance"=>0.676704} + ]; } return []; } diff --git a/t/app/controller/around.t b/t/app/controller/around.t index be8b0df9e..784801517 100644 --- a/t/app/controller/around.t +++ b/t/app/controller/around.t @@ -9,6 +9,7 @@ use constant MIN_ZOOM_LEVEL => 88; package main; use Test::MockModule; +use t::Mock::Nominatim; use FixMyStreet::TestMech; my $mech = FixMyStreet::TestMech->new; @@ -89,6 +90,30 @@ foreach my $test ( }; } +subtest "check lat/lng for full plus code" => sub { + $mech->get_ok('/'); + $mech->submit_form_ok( { with_fields => { pc => "9C7RXR26+R5" } } ); + is_deeply $mech->page_errors, [], "no errors for plus code"; + is_deeply $mech->extract_location, { + pc => "9C7RXR26+R5", + latitude => 55.952063, + longitude => -3.189562, + }, + "got expected location for full plus code"; +}; + +subtest "check lat/lng for short plus code" => sub { + $mech->get_ok('/'); + $mech->submit_form_ok( { with_fields => { pc => "XR26+R5 Edinburgh" } } ); + is_deeply $mech->page_errors, [], "no errors for plus code"; + is_deeply $mech->extract_location, { + pc => "XR26+R5 Edinburgh", + latitude => 55.952063, + longitude => -3.189562, + }, + "got expected location for short plus code"; +}; + my $body_edin_id = $mech->create_body_ok(2651, 'City of Edinburgh Council')->id; my $body_west_id = $mech->create_body_ok(2504, 'Westminster City Council')->id; |