Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
4.17% covered (danger)
4.17%
4 / 96
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
Geocoders
4.17% covered (danger)
4.17%
4 / 96
0.00% covered (danger)
0.00%
0 / 5
1308.92
0.00% covered (danger)
0.00%
0 / 1
 getCoordinates
57.14% covered (warning)
57.14%
4 / 7
0.00% covered (danger)
0.00%
0 / 1
5.26
 performRequest
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCoordinatesUseGoogle
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
90
 getCoordinatesUseYandex
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
72
 getCoordinatesUseMapquestNominatim
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 1
272
1<?php
2namespace MultiMaps;
3
4use MediaWiki\MediaWikiServices;
5
6/**
7 *
8 *
9 * @file Geocoders.php
10 * @ingroup MultiMaps
11 * @author Pavel Astakhov <pastakhov@yandex.ru>
12 * @license GPL-2.0-or-later
13 */
14
15class Geocoders {
16
17    public static function getCoordinates( $address, $service, $params = null ) {
18        switch ( $service ) {
19            case 'google':
20                return self::getCoordinatesUseGoogle( $address );
21            case 'yandex':
22                return self::getCoordinatesUseYandex( $address );
23            case 'leaflet':
24                return self::getCoordinatesUseMapquestNominatim( $address, $params );
25        }
26        return false;
27    }
28
29    private static function performRequest( $url, $urlArgs ) {
30        return MediaWikiServices::getInstance()->getHttpRequestFactory()->get( $url . wfArrayToCgi( $urlArgs ) );
31    }
32
33    private static function getCoordinatesUseGoogle( $address ) {
34        $return = false;
35
36        $urlArgs = [
37            'sensor' => 'false',
38            'address' => $address,
39            ];
40        $response = self::performRequest( 'https://maps.googleapis.com/maps/api/geocode/json?', $urlArgs );
41
42        if ( $response !== null ) {
43            $data = \FormatJson::decode( $response );
44            if ( $data !== null ) {
45                if ( $data->status == 'OK' ) {
46                    $geometry = $data->results[0]->geometry;
47                    $location = $geometry->location;
48                    $lat = $location->lat;
49                    $lon = $location->lng;
50                    if ( $lat !== null && $lon !== null ) {
51                        $return = [ 'lat' => $lat, 'lon' => $lon ];
52                        $bounds = $geometry->bounds;
53                        if ( $bounds !== null ) {
54                            $bounds_ne = new Point( $bounds->northeast->lat, $bounds->northeast->lng );
55                            $bounds_sw = new Point( $bounds->southwest->lat, $bounds->southwest->lng );
56                            if ( $bounds_ne->isValid() && $bounds_sw->isValid() ) {
57                                $b = new Bounds( [ $bounds_ne, $bounds_sw ] );
58                                $return['bounds'] = $b;
59                            }
60                        }
61                    }
62                }
63            }
64        }
65        return $return;
66    }
67
68    private static function getCoordinatesUseYandex( $address ) {
69        $return = false;
70
71        $urlArgs = [
72            'format' => 'json',
73            'results' => '1',
74            'geocode' => $address,
75            ];
76        $response = self::performRequest( 'https://geocode-maps.yandex.ru/1.x/?', $urlArgs );
77
78        if ( $response !== null ) {
79            $data = \FormatJson::decode( $response );
80            if ( $data !== null ) {
81                $geoObjectCollection = $data->response->GeoObjectCollection;
82                if ( $geoObjectCollection->metaDataProperty->GeocoderResponseMetaData->found > 0 ) {
83                    $geoObject = $geoObjectCollection->featureMember[0]->GeoObject;
84                    [ $lon, $lat ] = explode( ' ', $geoObject->Point->pos );
85                    $point = new Point( $lat, $lon );
86                    if ( $point->isValid() ) {
87                        $return = $point->pos;
88                        $envelope = $geoObject->boundedBy->Envelope;
89                        if ( $envelope !== null ) {
90                            [ $lon, $lat ] = explode( ' ', $envelope->upperCorner );
91                            $bounds_ne = new Point( $lat, $lon );
92                            [ $lon, $lat ] = explode( ' ', $envelope->lowerCorner );
93                            $bounds_sw = new Point( $lat, $lon );
94                            if ( $bounds_ne->isValid() && $bounds_sw->isValid() ) {
95                                $b = new Bounds( [ $bounds_ne, $bounds_sw ] );
96                                $return['bounds'] = $b;
97                            }
98                        }
99                    }
100                }
101            }
102        }
103        return $return;
104    }
105
106    public static function getCoordinatesUseMapquestNominatim( $address, $params ) {
107        $return = false;
108        $param_polygon = ( isset( $params['polygon'] ) && $params['polygon'] === true ) ? true : false;
109
110        $urlArgs = [
111            'format' => 'json',
112            'addressdetails' => '0',
113            'limit' => 1,
114            'q' => $address,
115        ];
116        if ( $param_polygon ) {
117            $urlArgs['polygon'] = '1';
118        }
119        $response = self::performRequest( 'https://open.mapquestapi.com/nominatim/v1/search.php?', $urlArgs );
120
121        if ( $response !== null ) {
122            $data = \FormatJson::decode( $response );
123            if ( isset( $data[0] ) ) {
124                $data = $data[0];
125                $lat = $data->lat;
126                $lon = $data->lon;
127                if ( $lat !== null && $lon !== null ) {
128                    $return = [ 'lat' => $lat, 'lon' => $lon ];
129                    $bounds = $data->boundingbox;
130                    if ( $bounds !== null ) {
131                        $bounds_ne = new Point( $bounds[1], $bounds[3] );
132                        $bounds_sw = new Point( $bounds[0], $bounds[2] );
133                        if ( $bounds_ne->isValid() && $bounds_sw->isValid() ) {
134                            $b = new Bounds( [ $bounds_ne, $bounds_sw ] );
135                            $return['bounds'] = $b;
136                        }
137                    }
138                    if ( $param_polygon ) {
139                        $polygonpoints = $data->polygonpoints;
140                        if ( count( $polygonpoints ) > 1 ) {
141                            $points = [];
142                            foreach ( $polygonpoints as $value ) {
143                                $p = new Point( $value[1], $value[0] );
144                                if ( $p->isValid() ) {
145                                    $points[] = $p;
146                                }
147                            }
148                            if ( count( $points ) > 1 ) {
149                                $return['polygon'] = $points;
150                            }
151                        }
152                    }
153                }
154            }
155        }
156        return $return;
157    }
158
159}