device_geolocation.module in Smart IP 6.2
Same filename and directory in other branches
Provides visitor's geographical location using client device location source that implements W3C Geolocation API and Google Geocoding service.
File
modules/device_geolocation/device_geolocation.moduleView source
<?php
/**
* @file
* Provides visitor's geographical location using client device
* location source that implements W3C Geolocation API and
* Google Geocoding service.
*/
/**
* Implements hook_init().
*/
function device_geolocation_init() {
// Check to see if the page is one of those allowed for geolocation
if (!smart_ip_check_allowed_page()) {
// This page is not on the list to acquire/update user's geolocation
return;
}
$ajax_check = variable_get('device_geolocation_ajax_check', FALSE);
if ($ajax_check || device_geolocation_check_geolocation_attempt()) {
device_geolocation_get_coordinates();
if ($ajax_check) {
// Add javascript app that checks if device geolocation needs refresh via ajax call
drupal_add_js(array(
'device_geolocation' => array(
'ask_geolocate' => FALSE,
),
), 'setting');
drupal_add_js(drupal_get_path('module', 'device_geolocation') . '/js/device_geolocation_check.js', 'module', 'footer');
}
else {
drupal_add_js(array(
'device_geolocation' => array(
'ask_geolocate' => TRUE,
),
), 'setting');
}
$param = '';
$google_map_api = variable_get('device_geolocation_google_map_api', NULL);
$google_region = variable_get('device_geolocation_google_map_region', NULL);
$google_map_language = variable_get('device_geolocation_google_map_language', NULL);
if ($google_map_api) {
$param .= "key={$google_map_api}";
}
if ($google_region) {
$param .= "®ion={$google_region}";
}
if ($google_map_language) {
$param .= "&language={$google_map_language}";
}
drupal_set_html_head('<script type="text/javascript" src="//maps.google.com/maps/api/js?key=' . $param . '"></script>');
drupal_add_js(drupal_get_path('module', 'device_geolocation') . '/js/device_geolocation.js', 'module', 'footer');
}
}
/**
* Implements hook_user_presave().
*/
function device_geolocation_presave(&$edit, $account, $category) {
// Reset the timer for frequency of user's geolocation checking
smart_ip_session_set('device_geolocation_attempt', NULL);
}
/**
* Implements hook_user_login().
*/
function device_geolocation_user_login(&$edit, $account) {
// Reset the timer for frequency of user's geolocation checking
smart_ip_session_set('device_geolocation_attempt', NULL);
}
/**
* Implements hook_block()
*/
function device_geolocation_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
$blocks[0]['info'] = t("Visitor's geolocation");
$blocks[0]['cache'] = BLOCK_CACHE_PER_PAGE | BLOCK_CACHE_PER_ROLE;
return $blocks;
case 'view':
$blocks['subject'] = t('Your Geolocation Details');
$blocks['content'] = device_geolocation_contents();
return $blocks;
}
}
/**
* Device geolocation block content function.
*/
function device_geolocation_contents() {
$location = array();
$smart_ip_session = smart_ip_session_get('smart_ip');
// Smart IP user $_SESSION
if (!is_null($smart_ip_session)) {
$location = $smart_ip_session['location'];
}
else {
global $user;
$user_data = unserialize($user->data);
if (isset($user_data['geoip_location'])) {
$smart_ip_session['location'] = $user_data['geoip_location'];
smart_ip_session_set('smart_ip', $smart_ip_session);
$location = $smart_ip_session['location'];
}
}
return theme('device_geolocation_visitor_info', $location);
}
/**
* Implements hook_theme()
*/
function device_geolocation_theme() {
return array(
'device_geolocation_visitor_info' => array(
'arguments' => array(
'location' => array(),
),
'template' => 'device-geolocation-visitor-info',
'path' => drupal_get_path('module', 'device_geolocation') . '/theme',
),
);
}
/**
* Implements hook_help().
*/
function device_geolocation_help($path, $arg) {
switch ($path) {
case 'admin/help#device_geolocation':
return '<p>' . t("Provides visitor's geographical location using client device location source \n that implements W3C Geolocation API whereas the coordinates are geocoded using \n Google Geocoding service. Google Geocoding returns a more detailed location \n information such as: street number, postal code, route, neighborhood, locality, \n sublocality, establishment, administrative area level 1, administrative area level 2, \n etc.") . '</p><p>' . t("Smart IP is the last fallback if W3C Geolocation API failed. Even if the visitors \n refuses to share their location, the geographical information provided by Smart IP will \n be used to know your visitors' geolocation details. A themeable Block content is \n available to show your visitor's geolocation information. Device Geolocation merges its \n location data (collected at Google Geocoding service) with Smart IP visitor's location \n data storage which is in session variable (@session) with array key 'smart_ip' and \n Drupal @user->data object with array key 'geoip_location'.", array(
'@session' => '$_SESSION',
'@user' => '$user',
)) . '</p>';
break;
}
}
/**
* Implements hook_form_alter()
*/
function device_geolocation_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'smart_ip_admin_settings') {
// Container for Device Geolocation preference forms
$form['device_geolocation_preferences'] = array(
'#type' => 'fieldset',
'#title' => t('Device Geolocation settings'),
'#collapsible' => FALSE,
'#collapsed' => FALSE,
'#weight' => 4,
);
$form['device_geolocation_preferences']['device_geolocation_ajax_check'] = array(
'#type' => 'checkbox',
'#title' => t("Use AJAX in user's geolocation checking (useful if the site or pages listed above are cached)"),
'#default_value' => variable_get('device_geolocation_ajax_check', FALSE),
);
$device_geolocation_check_frequency = variable_get('device_geolocation_check_frequency', NULL);
$form['device_geolocation_preferences']['device_geolocation_check_frequency'] = array(
'#title' => t("Frequency of user's geolocation checking"),
'#type' => 'textfield',
'#size' => 10,
'#description' => t('Specify number of hours will prompt the user for geolocation. Leave it empty to disable.'),
'#default_value' => $device_geolocation_check_frequency === NULL ? '' : $device_geolocation_check_frequency / 3600,
'#field_suffix' => t('hours'),
);
$form['device_geolocation_preferences']['device_geolocation_google_map_api'] = array(
'#title' => t('Google map API key'),
'#type' => 'textfield',
'#description' => t('The use of Google map service requires API key. Get your API key !here.', array(
'!here' => l(t('here'), 'https://developers.google.com/maps/documentation/javascript/get-api-key'),
)),
'#default_value' => variable_get('device_geolocation_google_map_api', NULL),
);
$form['device_geolocation_preferences']['device_geolocation_google_map_region'] = array(
'#type' => 'textfield',
'#title' => t('Google map region'),
'#default_value' => variable_get('device_geolocation_google_map_region', NULL),
'#description' => t("Specify a region code, which alters the Google map service's behavior based on a given country or territory. See !google_localization_region", array(
'!google_localization_region' => l(t('Google Maps API - Localizing the Map (Region localization)'), 'https://developers.google.com/maps/documentation/javascript/localization#Region'),
)),
);
$form['device_geolocation_preferences']['device_geolocation_google_map_language'] = array(
'#type' => 'textfield',
'#title' => t('Google map language'),
'#default_value' => variable_get('device_geolocation_google_map_language', NULL),
'#description' => t('Change the Google map service default language settings. See !google_localization_language', array(
'!google_localization_language' => l(t('Google Maps API - Localizing the Map (Language localization)'), 'https://developers.google.com/maps/documentation/javascript/localization#Language'),
)),
);
$form['#validate'][] = '_device_geolocation_check_frequency_validate';
}
}
/**
* Validation handler to update the "Geolocate on specific pages".
*/
function _device_geolocation_check_frequency_validate($form, &$form_state) {
$value = $form_state['values']['device_geolocation_check_frequency'];
if ($value == '') {
$form_state['values']['device_geolocation_check_frequency'] = NULL;
}
elseif (!is_numeric($value) || $value < 0) {
form_set_error('device_geolocation_check_frequency', t("Frequency of user's geolocation checking must be a positive number."));
}
else {
// Convert from hours to seconds
$form_state['values']['device_geolocation_check_frequency'] = $value * 3600;
}
}
/**
* Implements hook_menu().
*/
function device_geolocation_menu() {
$items['geolocate-user'] = array(
'page callback' => 'device_geolocation_detector_ajax',
'access callback' => 'user_access',
'access arguments' => array(
'access content',
),
'type' => MENU_CALLBACK,
);
$items['check-geolocation-attempt'] = array(
'page callback' => 'device_geolocation_check_geolocation_attempt_ajax',
'access callback' => 'user_access',
'access arguments' => array(
'access content',
),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Google Geocoding ajax callback function data recipient.
*/
function device_geolocation_detector_ajax() {
if (isset($_POST['latitude']) && isset($_POST['longitude'])) {
global $user;
$smart_ip_session = smart_ip_session_get('smart_ip');
$ip_address = $smart_ip_session['location']['ip_address'];
$smart_ip_session['maxmind_location'] = $smart_ip_session['location'];
smart_ip_session_set('device_geolocation', NULL);
unset($smart_ip_session['location']);
$smart_ip_session['location']['ip_address'] = $ip_address;
$smart_ip_session['location']['country'] = '';
$smart_ip_session['location']['country_code'] = '';
$smart_ip_session['location']['region'] = '';
$smart_ip_session['location']['region_code'] = '';
$smart_ip_session['location']['city'] = '';
$smart_ip_session['location']['zip'] = '';
$smart_ip_session['location']['latitude'] = '';
$smart_ip_session['location']['longitude'] = '';
$smart_ip_session['location']['time_zone'] = '';
$smart_ip_session['location']['is_eu_country'] = '';
$smart_ip_session['location']['is_gdpr_country'] = '';
foreach ($_POST as $label => $address) {
if (!empty($address) && is_string($address) && is_string($label)) {
$label = check_plain($label);
if (!is_array($address)) {
$smart_ip_session['location'][$label] = check_plain($address);
}
else {
$smart_ip_session['location'][$label] = $address;
}
smart_ip_session_set('device_geolocation', TRUE);
}
}
$smart_ip_session['location']['timestamp'] = (int) $_SERVER['REQUEST_TIME'];
// Allow other modules to modify result via hook_device_geolocation_detector_ajax_alter()
drupal_alter('device_geolocation_detector_ajax', $smart_ip_session['location']);
if (isset($smart_ip_session['location']) && $user->uid) {
$user_obj = user_load($user->uid);
user_save($user_obj, array(
'geoip_location' => $smart_ip_session['location'],
));
}
smart_ip_session_set('smart_ip', $smart_ip_session);
}
}
/**
* Get Visitor's coordinates.
*/
function device_geolocation_get_coordinates() {
global $user;
$latitude = 0;
$longitude = 0;
$user_data = unserialize($user->data);
$smart_ip_session = smart_ip_session_get('smart_ip');
$is_allowed_page = smart_ip_check_allowed_page();
// Smart IP user $_SESSION
if (!is_null($smart_ip_session) && !empty($smart_ip_session['location']['latitude'])) {
$latitude = $smart_ip_session['location']['latitude'];
$longitude = $smart_ip_session['location']['longitude'];
}
elseif (isset($user_data['geoip_location']) && !empty($user_data['geoip_location']['latitude'])) {
$smart_ip_session['location'] = $user_data['geoip_location'];
$latitude = $smart_ip_session['location']['latitude'];
$longitude = $smart_ip_session['location']['longitude'];
if ($is_allowed_page) {
smart_ip_session_set('smart_ip', $smart_ip_session);
}
}
else {
$smart_ip_session['location'] = smart_ip_get_current_visitor_location_data();
if ($is_allowed_page) {
smart_ip_session_set('smart_ip', $smart_ip_session);
}
if ($user->uid) {
$user_obj = user_load($user->uid);
user_save($user_obj, array(
'geoip_location' => $smart_ip_session['location'],
));
}
if (!empty($smart_ip_session['location']['latitude'])) {
$latitude = $smart_ip_session['location']['latitude'];
$longitude = $smart_ip_session['location']['longitude'];
}
elseif ($is_allowed_page) {
smart_ip_session_set('smart_ip', NULL);
}
}
$debug_mode = is_user_debug_mode();
//$debug_mode = FALSE;
$coordinates = array(
'latitude' => $latitude,
'longitude' => $longitude,
'debug_mode' => $debug_mode,
);
// Send also to javascript
drupal_add_js(array(
'device_geolocation' => $coordinates,
), 'setting');
return $coordinates;
}
/**
* Check for Geolocation attempt ajax callback.
*/
function device_geolocation_check_geolocation_attempt_ajax() {
if (smart_ip_check_allowed_page() && device_geolocation_check_geolocation_attempt()) {
drupal_json(array(
'ask_geolocate' => TRUE,
));
return;
}
drupal_json(array(
'ask_geolocate' => FALSE,
));
}
/**
* Check for Geolocation attempt.
*/
function device_geolocation_check_geolocation_attempt() {
$device_geolocation_check_frequency = variable_get('device_geolocation_check_frequency', NULL);
$timestamp = smart_ip_session_get('device_geolocation_attempt');
$request_time = (int) $_SERVER['REQUEST_TIME'];
if ($device_geolocation_check_frequency === NULL) {
// User's device geolocation checking is set disabled
return FALSE;
}
elseif (is_null(smart_ip_session_get('device_geolocation')) && empty($timestamp)) {
// The user has not allowed to share his/her location yet then return that user's location needs
// update and start the timer.
smart_ip_session_set('device_geolocation_attempt', $request_time);
return TRUE;
}
elseif (!empty($timestamp) && $device_geolocation_check_frequency < $request_time - $timestamp) {
// Return that user's location needs update and reset the timer.
smart_ip_session_set('device_geolocation_attempt', $request_time);
return TRUE;
}
return FALSE;
}
Functions
Name | Description |
---|---|
device_geolocation_block | Implements hook_block() |
device_geolocation_check_geolocation_attempt | Check for Geolocation attempt. |
device_geolocation_check_geolocation_attempt_ajax | Check for Geolocation attempt ajax callback. |
device_geolocation_contents | Device geolocation block content function. |
device_geolocation_detector_ajax | Google Geocoding ajax callback function data recipient. |
device_geolocation_form_alter | Implements hook_form_alter() |
device_geolocation_get_coordinates | Get Visitor's coordinates. |
device_geolocation_help | Implements hook_help(). |
device_geolocation_init | Implements hook_init(). |
device_geolocation_menu | Implements hook_menu(). |
device_geolocation_presave | Implements hook_user_presave(). |
device_geolocation_theme | Implements hook_theme() |
device_geolocation_user_login | Implements hook_user_login(). |
_device_geolocation_check_frequency_validate | Validation handler to update the "Geolocate on specific pages". |