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