Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
bc77d7c0 TO |
3 | +--------------------------------------------------------------------+ |
4 | | Copyright CiviCRM LLC. All rights reserved. | | |
5 | | | | |
6 | | This work is published under the GNU AGPLv3 license with some | | |
7 | | permitted exceptions and without any warranty. For full license | | |
8 | | and copyright information, see https://civicrm.org/licensing | | |
9 | +--------------------------------------------------------------------+ | |
e70a7fc0 | 10 | */ |
6a488035 TO |
11 | |
12 | /** | |
13 | * | |
14 | * @package CRM | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 TO |
16 | */ |
17 | ||
18 | /** | |
19 | * Class that uses google geocoder | |
20 | */ | |
21 | class CRM_Utils_Geocode_Google { | |
22 | ||
23 | /** | |
100fef9d | 24 | * Server to retrieve the lat/long |
6a488035 TO |
25 | * |
26 | * @var string | |
6a488035 TO |
27 | */ |
28 | static protected $_server = 'maps.googleapis.com'; | |
29 | ||
30 | /** | |
fe482240 | 31 | * Uri of service. |
6a488035 TO |
32 | * |
33 | * @var string | |
6a488035 TO |
34 | */ |
35 | static protected $_uri = '/maps/api/geocode/xml?sensor=false&address='; | |
36 | ||
37 | /** | |
100fef9d | 38 | * Function that takes an address object and gets the latitude / longitude for this |
6a488035 TO |
39 | * address. Note that at a later stage, we could make this function also clean up |
40 | * the address into a more valid format | |
41 | * | |
c490a46a | 42 | * @param array $values |
77b97be7 EM |
43 | * @param bool $stateName |
44 | * | |
bed98343 | 45 | * @return bool |
a6c01b45 | 46 | * true if we modified the address, false otherwise |
6a488035 | 47 | */ |
00be9182 | 48 | public static function format(&$values, $stateName = FALSE) { |
6a488035 | 49 | // we need a valid country, else we ignore |
a7488080 | 50 | if (empty($values['country'])) { |
6a488035 TO |
51 | return FALSE; |
52 | } | |
53 | ||
54 | $config = CRM_Core_Config::singleton(); | |
55 | ||
56 | $add = ''; | |
57 | ||
a7488080 | 58 | if (!empty($values['street_address'])) { |
6a488035 TO |
59 | $add = urlencode(str_replace('', '+', $values['street_address'])); |
60 | $add .= ',+'; | |
61 | } | |
62 | ||
9c1bc317 | 63 | $city = $values['city'] ?? NULL; |
6a488035 TO |
64 | if ($city) { |
65 | $add .= '+' . urlencode(str_replace('', '+', $city)); | |
66 | $add .= ',+'; | |
67 | } | |
68 | ||
f731b3dd | 69 | if (!empty($values['state_province']) || (!empty($values['state_province_id']) && $values['state_province_id'] != 'null')) { |
a7488080 | 70 | if (!empty($values['state_province_id'])) { |
6a488035 TO |
71 | $stateProvince = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_StateProvince', $values['state_province_id']); |
72 | } | |
73 | else { | |
74 | if (!$stateName) { | |
75 | $stateProvince = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_StateProvince', | |
76 | $values['state_province'], | |
77 | 'name', | |
78 | 'abbreviation' | |
79 | ); | |
80 | } | |
81 | else { | |
82 | $stateProvince = $values['state_province']; | |
83 | } | |
84 | } | |
85 | ||
86 | // dont add state twice if replicated in city (happens in NZ and other countries, CRM-2632) | |
87 | if ($stateProvince != $city) { | |
88 | $add .= '+' . urlencode(str_replace('', '+', $stateProvince)); | |
89 | $add .= ',+'; | |
90 | } | |
91 | } | |
92 | ||
a7488080 | 93 | if (!empty($values['postal_code'])) { |
6a488035 TO |
94 | $add .= '+' . urlencode(str_replace('', '+', $values['postal_code'])); |
95 | $add .= ',+'; | |
96 | } | |
97 | ||
a7488080 | 98 | if (!empty($values['country'])) { |
6a488035 TO |
99 | $add .= '+' . urlencode(str_replace('', '+', $values['country'])); |
100 | } | |
101 | ||
6849336a CB |
102 | if (!empty($config->geoAPIKey)) { |
103 | $add .= '&key=' . urlencode($config->geoAPIKey); | |
104 | } | |
105 | ||
106 | $query = 'https://' . self::$_server . self::$_uri . $add; | |
6a488035 TO |
107 | |
108 | require_once 'HTTP/Request.php'; | |
109 | $request = new HTTP_Request($query); | |
110 | $request->sendRequest(); | |
111 | $string = $request->getResponseBody(); | |
112 | ||
113 | libxml_use_internal_errors(TRUE); | |
114 | $xml = @simplexml_load_string($string); | |
9862d91a | 115 | CRM_Utils_Hook::geocoderFormat('Google', $values, $xml); |
6a488035 TO |
116 | if ($xml === FALSE) { |
117 | // account blocked maybe? | |
118 | CRM_Core_Error::debug_var('Geocoding failed. Message from Google:', $string); | |
119 | return FALSE; | |
120 | } | |
121 | ||
122 | if (isset($xml->status)) { | |
123 | if ($xml->status == 'OK' && | |
124 | is_a($xml->result->geometry->location, | |
125 | 'SimpleXMLElement' | |
126 | ) | |
127 | ) { | |
128 | $ret = $xml->result->geometry->location->children(); | |
129 | if ($ret->lat && $ret->lng) { | |
e7292422 TO |
130 | $values['geo_code_1'] = (float) $ret->lat; |
131 | $values['geo_code_2'] = (float) $ret->lng; | |
6a488035 TO |
132 | return TRUE; |
133 | } | |
134 | } | |
a61fce12 TL |
135 | elseif ($xml->status == 'ZERO_RESULTS') { |
136 | // reset the geo code values if we did not get any good values | |
137 | $values['geo_code_1'] = $values['geo_code_2'] = 'null'; | |
138 | return FALSE; | |
139 | } | |
140 | else { | |
141 | CRM_Core_Error::debug_var("Geocoding failed. Message from Google: ({$xml->status})", (string ) $xml->error_message); | |
79f1148d DL |
142 | $values['geo_code_1'] = $values['geo_code_2'] = 'null'; |
143 | $values['geo_code_error'] = $xml->status; | |
144 | return FALSE; | |
6a488035 TO |
145 | } |
146 | } | |
6a488035 | 147 | } |
161af008 | 148 | |
6a488035 | 149 | } |