diff options
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Bexley.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/Geocode/Bexley.pm | 69 | ||||
-rw-r--r-- | perllib/FixMyStreet/Geocode/OSM.pm | 7 | ||||
-rw-r--r-- | t/cobrand/bexley.t | 36 |
4 files changed, 110 insertions, 4 deletions
diff --git a/perllib/FixMyStreet/Cobrand/Bexley.pm b/perllib/FixMyStreet/Cobrand/Bexley.pm index 1a4b698df..5539e8bfc 100644 --- a/perllib/FixMyStreet/Cobrand/Bexley.pm +++ b/perllib/FixMyStreet/Cobrand/Bexley.pm @@ -8,7 +8,7 @@ sub council_area_id { 2494 } sub council_area { 'Bexley' } sub council_name { 'London Borough of Bexley' } sub council_url { 'bexley' } -sub get_geocoder { 'OSM' } +sub get_geocoder { 'Bexley' } sub map_type { 'Bexley' } sub disambiguate_location { diff --git a/perllib/FixMyStreet/Geocode/Bexley.pm b/perllib/FixMyStreet/Geocode/Bexley.pm new file mode 100644 index 000000000..a70a42cd1 --- /dev/null +++ b/perllib/FixMyStreet/Geocode/Bexley.pm @@ -0,0 +1,69 @@ +package FixMyStreet::Geocode::Bexley; +use parent 'FixMyStreet::Geocode::OSM'; + +use warnings; +use strict; + +use URI::Escape; + +my $base = 'http://tilma.mysociety.org/mapserver/bexley?SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=Streets&outputFormat=geojson&Filter=%3CFilter%3E%3CPropertyIsLike%20wildcard=%27*%27%20singleChar=%27.%27%20escape=%27!%27%3E%3CPropertyName%3EADDRESS%3C/PropertyName%3E%3CLiteral%3E{{str}}%3C/Literal%3E%3C/PropertyIsLike%3E%3C/Filter%3E'; + +# Data is ALL CAPS +sub recase { + my $word = shift; + return $word if $word =~ /FP/; + return lc $word if $word =~ /^(AND|TO)$/; + return ucfirst lc $word; +} + +sub string { + my ($cls, $s, $c) = @_; + + my $osm = $cls->SUPER::string($s, $c); + my $js = query_layer($s); + return $osm unless $js && @{$js->{features}}; + + my ( $error, @valid_locations, $latitude, $longitude, $address ); + foreach (sort { $a->{properties}{ADDRESS} cmp $b->{properties}{ADDRESS} } @{$js->{features}}) { + my @lines = @{$_->{geometry}{coordinates}}; + @lines = ([ @lines ]) if $_->{geometry}{type} eq 'LineString'; + my @points = map { @$_ } @lines; + my $mid = int @points/2; + my $e = $points[$mid][0]; + my $n = $points[$mid][1]; + ( $latitude, $longitude ) = Utils::convert_en_to_latlon_truncated( $e, $n ); + $address = sprintf("%s, %s", $_->{properties}{ADDRESS}, $_->{properties}{TOWN}); + $address =~ s/([\w']+)/recase($1)/ge; + push @$error, { + address => $address, + latitude => $latitude, + longitude => $longitude + }; + push (@valid_locations, $_); + } + + if ($osm->{latitude}) { # one result from OSM + push @$error, { + address => $osm->{address}, + latitude => $osm->{latitude}, + longitude => $osm->{longitude}, + }; + return { error => $error }; + } + + if (ref $osm->{error} eq 'ARRAY') { + push @$error, @{$osm->{error}}; + return { error => $error }; + } + + return { latitude => $latitude, longitude => $longitude, address => $address } + if scalar @valid_locations == 1; + return { error => $error }; +} + +sub query_layer { + my $s = uc shift; + $s = URI::Escape::uri_escape_utf8("*$s*"); + (my $url = $base) =~ s/\{\{str\}\}/$s/; + return FixMyStreet::Geocode::cache('bexley', $url); +} diff --git a/perllib/FixMyStreet/Geocode/OSM.pm b/perllib/FixMyStreet/Geocode/OSM.pm index fb7924c23..a36ae3192 100644 --- a/perllib/FixMyStreet/Geocode/OSM.pm +++ b/perllib/FixMyStreet/Geocode/OSM.pm @@ -52,14 +52,15 @@ sub string { return { error => _('Sorry, we could not find that location.') }; } - my ( $error, @valid_locations, $latitude, $longitude ); + my ( $error, @valid_locations, $latitude, $longitude, $address ); foreach (@$js) { $c->cobrand->call_hook(geocoder_munge_results => $_); ( $latitude, $longitude ) = map { Utils::truncate_coordinate($_) } ( $_->{lat}, $_->{lon} ); + $address = $_->{display_name}; push (@$error, { - address => $_->{display_name}, + address => $address, icon => $_->{icon}, latitude => $latitude, longitude => $longitude @@ -67,7 +68,7 @@ sub string { push (@valid_locations, $_); } - return { latitude => $latitude, longitude => $longitude } if scalar @valid_locations == 1; + return { latitude => $latitude, longitude => $longitude, address => $address } if scalar @valid_locations == 1; return { error => $error }; } diff --git a/t/cobrand/bexley.t b/t/cobrand/bexley.t index b929cbce1..3937129d3 100644 --- a/t/cobrand/bexley.t +++ b/t/cobrand/bexley.t @@ -2,8 +2,10 @@ use CGI::Simple; use Test::MockModule; use FixMyStreet::TestMech; use FixMyStreet::Script::Reports; +use Catalyst::Test 'FixMyStreet::App'; use_ok 'FixMyStreet::Cobrand::Bexley'; +use_ok 'FixMyStreet::Geocode::Bexley'; use_ok 'FixMyStreet::Map::Bexley'; my $ukc = Test::MockModule->new('FixMyStreet::Cobrand::UKCouncils'); @@ -166,4 +168,38 @@ subtest 'correct map tiles used' => sub { } }; +my $geo = Test::MockModule->new('FixMyStreet::Geocode'); +$geo->mock('cache', sub { + my $typ = shift; + return [] if $typ eq 'osm'; + return { + features => [ + { + properties => { ADDRESS => 'BRAMPTON ROAD', TOWN => 'BEXLEY' }, + geometry => { type => 'LineString', coordinates => [ [ 1, 2 ], [ 3, 4] ] }, + }, + { + properties => { ADDRESS => 'FOOTPATH TO BRAMPTON ROAD', TOWN => 'BEXLEY' }, + geometry => { type => 'MultiLineString', coordinates => [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 5, 6 ], [ 7, 8 ] ] ] }, + }, + ], + } if $typ eq 'bexley'; +}); + +subtest 'geocoder' => sub { + my $c = ctx_request('/'); + my $results = FixMyStreet::Geocode::Bexley->string("Brampton Road", $c); + is_deeply $results, { error => [ + { + 'latitude' => '49.766844', + 'longitude' => '-7.557122', + 'address' => 'Brampton Road, Bexley' + }, { + 'address' => 'Footpath to Brampton Road, Bexley', + 'longitude' => '-7.557097', + 'latitude' => '49.766863' + } + ] }; +}; + done_testing(); |