function geocoder_google in Geocoder 7
Process Markup.
1 call to geocoder_google()
- geocoder_google_field in plugins/
geocoder_handler/ google.inc - Plugin callback.
1 string reference to 'geocoder_google'
- google.inc in plugins/
geocoder_handler/ google.inc
File
- plugins/
geocoder_handler/ google.inc, line 30
Code
function geocoder_google($address, $options = array()) {
$delay_trigger =& drupal_static(__FUNCTION__);
$delay = variable_get('geocoder_google_delay', 0);
if ($delay > 0 && $delay_trigger) {
usleep($delay * 1000);
}
geophp_load();
$query = array(
'address' => $address,
);
if (isset($options['extra_query']) && is_array($options['extra_query'])) {
$query += $options['extra_query'];
}
// Add any given biasing.
if (!empty($options['biasing']['bounds'])) {
$query['bounds'] = $options['biasing']['bounds'];
}
if (!empty($options['biasing']['region'])) {
$query['region'] = $options['biasing']['region'];
}
if (!empty($options['biasing']['components'])) {
$query['components'] = $options['biasing']['components'];
}
// Error message in case no key/client ID has been provided.
$msg = t('The current HTTP request to google API does not have a key or client ID to identify your application.');
// Add Google API authentication parameters.
switch (variable_get('geocoder_google_auth_method')) {
// Google Geocoding API Key.
case GEOCODER_GOOGLE_AUTH_KEY:
$geocoder_settings = variable_get("geocoder_settings", array());
if (!empty($geocoder_settings['geocoder_apikey_google'])) {
$query['key'] = $geocoder_settings['geocoder_apikey_google'];
}
else {
throw new Exception($msg, WATCHDOG_ERROR);
}
break;
// Google Maps for Work signature.
case GEOCODER_GOOGLE_AUTH_WORK:
$client_id = variable_get('geocoder_google_client_id', FALSE);
$private_key = variable_get('geocoder_google_private_key', FALSE);
if (!empty($client_id) && !empty($private_key)) {
$google_maps_for_work = TRUE;
$query['client'] = $client_id;
}
else {
throw new Exception($msg, WATCHDOG_ERROR);
}
break;
default:
throw new Exception($msg, WATCHDOG_ERROR);
}
$google_url = 'https://maps.googleapis.com/maps/api/geocode/json';
// Build the URL.
$url = url($google_url, array(
'query' => $query,
));
// If authenticating via Google Maps for Work, add signature.
// @see https://developers.google.com/maps/documentation/business/webservices/auth#generating_valid_signatures
if (!empty($google_maps_for_work)) {
// Strip off the protocol and host for signing.
$parsed = parse_url($url);
$url_to_sign = $parsed['path'] . '?' . $parsed['query'];
// Decode the key in a URL-safe way (RFC 4648 Section 5).
// @see https://www.ietf.org/rfc/rfc4648.txt
$decoded_key = base64_decode(strtr($private_key, '-_', '+/'), TRUE);
// Use HMAC SHA1 to sign the URL with the decoded key.
$signature = hash_hmac('sha1', $url_to_sign, $decoded_key, TRUE);
// Append the signature to the URL's query parameters. Do this manually to
// avoid URL encoding.
$url .= '&signature=' . strtr(base64_encode($signature), '+/', '-_');
}
// Send the request.
$result = drupal_http_request($url);
$delay_trigger = TRUE;
if (isset($result->error)) {
$args = array(
'@code' => $result->code,
'@error' => $result->error,
);
$msg = t("HTTP request to google API failed.\nCode: @code\nError: @error", $args);
throw new Exception($msg);
}
$data = json_decode($result->data);
if ($data->status === 'ZERO_RESULTS') {
return FALSE;
}
elseif ($data->status !== 'OK') {
$args = array(
'@status' => $data->status,
'@message' => !empty($data->error_message) ? $data->error_message : t('No specific message'),
);
$msg = t("Google API returned bad status.\nStatus: @status\nMessage: @message", $args);
throw new Exception($msg);
}
$geometries = array();
foreach ($data->results as $item) {
// Check if we should reject these results.
if (isset($options['reject_results'])) {
if (in_array($item->geometry->location_type, $options['reject_results'], TRUE)) {
continue;
}
}
// Construct a geoPHP Geometry depending on what type of geometry we want
// returned (defaults to point).
if (!isset($options['geometry_type']) || $options['geometry_type'] === 'point') {
$geom = new Point($item->geometry->location->lng, $item->geometry->location->lat);
}
elseif ($options['geometry_type'] === 'bounds') {
if (isset($item->geometry->bounds)) {
$points = array(
new Point($item->geometry->bounds->southwest->lng, $item->geometry->bounds->southwest->lat),
new Point($item->geometry->bounds->southwest->lng, $item->geometry->bounds->northeast->lat),
new Point($item->geometry->bounds->northeast->lng, $item->geometry->bounds->northeast->lat),
new Point($item->geometry->bounds->northeast->lng, $item->geometry->bounds->southwest->lat),
new Point($item->geometry->bounds->southwest->lng, $item->geometry->bounds->southwest->lat),
);
$geom = new Polygon(array(
new LineString($points),
));
}
}
elseif ($options['geometry_type'] === 'viewport') {
$points = array(
new Point($item->geometry->viewport->southwest->lng, $item->geometry->viewport->southwest->lat),
new Point($item->geometry->viewport->southwest->lng, $item->geometry->viewport->northeast->lat),
new Point($item->geometry->viewport->northeast->lng, $item->geometry->viewport->northeast->lat),
new Point($item->geometry->viewport->northeast->lng, $item->geometry->viewport->southwest->lat),
new Point($item->geometry->viewport->southwest->lng, $item->geometry->viewport->southwest->lat),
);
$geom = new Polygon(array(
new LineString($points),
));
}
// Add additional metadata to the geometry - it might be useful!
$geom->data = array();
$geom->data['geocoder_accuracy'] = $item->geometry->location_type;
$geom->data['geocoder_formatted_address'] = $item->formatted_address;
$geom->data['geocoder_address_components'] = $item->address_components;
$geometries[] = $geom;
}
if (empty($geometries)) {
return;
}
// Check if we should return all results as a compound geometry.
if (isset($options['all_results'])) {
if ($options['all_results']) {
return geoPHP::geometryReduce($geometries);
}
}
// The canonical geometry is the first result (best guess)
$geometry = array_shift($geometries);
// If there are any other geometries, these are auxiliary geometries that
// represent "alternatives".
if (count($geometries)) {
$geometry->data['geocoder_alternatives'] = $geometries;
}
return $geometry;
}