BingMaps::reverseGeocode()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 3
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace LeKoala\GeoTools\Services;
4
5
use Exception;
6
use SimpleXMLElement;
7
use SilverStripe\Core\Environment;
8
use LeKoala\GeoTools\Models\Address;
9
use LeKoala\GeoTools\Models\Country;
10
use LeKoala\GeoTools\Models\Coordinates;
11
12
/**
13
 * @link https://www.bingmapsportal.com/Application
14
 * @link https://learn.microsoft.com/en-us/bingmaps/articles/accessing-the-bing-maps-rest-services-using-php
15
 */
16
class BingMaps implements Geocoder
17
{
18
    const API_URL = 'http://dev.virtualearth.net/REST/v1/Locations/';
19
20
    /**
21
     * @return string|null
22
     */
23
    public static function getApiKey()
24
    {
25
        return Environment::getEnv('BING_MAPS_API_KEY');
26
    }
27
28
    /**
29
     * @param ?string $query
30
     * @param array<int|string,mixed> $params countrycodes
31
     * @return Address
32
     * @throws Exception when there is a problem with the api, otherwise may return an empty address
33
     */
34
    protected function query($query, $params = [])
0 ignored issues
show
Unused Code introduced by
The parameter $params is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

34
    protected function query($query, /** @scrutinizer ignore-unused */ $params = [])

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
35
    {
36
        $key = self::getApiKey();
37
        if (!$key) {
38
            throw new Exception('No api key defined in env');
39
        }
40
41
        $query = str_ireplace(" ", "%20", $query);
0 ignored issues
show
Bug introduced by
It seems like $query can also be of type null; however, parameter $subject of str_ireplace() does only seem to accept array|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

41
        $query = str_ireplace(" ", "%20", /** @scrutinizer ignore-type */ $query);
Loading history...
42
        $findURL = self::API_URL . "/" . $query . "?incl=ciso2&key=" . $key;
0 ignored issues
show
Bug introduced by
Are you sure $query of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

42
        $findURL = self::API_URL . "/" . /** @scrutinizer ignore-type */ $query . "?incl=ciso2&key=" . $key;
Loading history...
43
        $output = file_get_contents($findURL);
44
45
        if (!$output) {
46
            throw new Exception("The api returned no result");
47
        }
48
49
        $result = json_decode($output, true);
50
51
        if (!$result) {
52
            throw new Exception(json_last_error_msg());
53
        }
54
55
        $firstResult = $result['resourceSets'][0]['resources'][0] ?? null;
56
        if (!$firstResult) {
57
            throw new Exception("Empty resultset");
58
        }
59
60
        $point = $firstResult['point']['coordinates'];
61
        $lat = $point[0];
62
        $lon = $point[1];
63
64
        $address = $firstResult['address'];
65
        $countryName = $address['countryRegion'];
66
        $countryCode = $address['countryRegionIso2'];
67
68
        $streetAndNumber = $address['addressLine'] ?? null;
69
        $location = [];
70
        if ($streetAndNumber) {
71
            $number = null;
72
            $street = $streetAndNumber;
73
            $parts = explode(' ', $streetAndNumber, 2);
74
            if (intval($parts[0]) > 0) {
75
                $number = $parts[0];
76
                $street = $parts[1];
77
            }
78
            $location = [
79
                'streetName' => $street,
80
                'streetNumber' => $number,
81
                'postalCode' =>  $address['postalCode'] ?? null,
82
                'locality' =>  $address['locality'] ?? null,
83
            ];
84
        }
85
86
        $country = new Country($countryCode, $countryName);
87
        $coordinates = new Coordinates($lat, $lon);
88
89
        return new Address($location, $country, $coordinates);
90
    }
91
92
    /**
93
     * @inheritDoc
94
     */
95
    public function reverseGeocode($lat, $lon, $params = [])
96
    {
97
        return $this->query("$lat,$lon", $params);
98
    }
99
100
    /**
101
     * @inheritDoc
102
     */
103
    public function geocode($address, $params = [])
104
    {
105
        return $this->query($address, $params);
106
    }
107
}
108