aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorM Somerville <matthew-github@dracos.co.uk>2020-05-29 11:09:36 +0100
committerMatthew Somerville <matthew@mysociety.org>2020-06-04 21:08:36 +0100
commitabc63a85b47bbc6b9e81c8256a226864ac7fe0ce (patch)
treee3eb1fc9e6f50bc7cc235de626202da084449042
parentce5588038dfafb2db53c7de7e0d34e8c59bed8ba (diff)
Add Open Location Codes support to search box.
-rw-r--r--CHANGELOG.md2
-rw-r--r--cpanfile1
-rw-r--r--cpanfile.snapshot9
-rw-r--r--perllib/FixMyStreet/App/Controller/Location.pm25
-rw-r--r--t/Mock/Nominatim.pm5
-rw-r--r--t/app/controller/around.t25
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
diff --git a/cpanfile b/cpanfile
index 0474f4691..1415a7af5 100644
--- a/cpanfile
+++ b/cpanfile
@@ -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;