smart_ip.module in Smart IP 8.4
Same filename and directory in other branches
Determines country, geo location (longitude/latitude), region, city and postal code of the user, based on IP address
This module uses the IP address that a user is connected from to extract the location information where the user is located. This method is not foolproof, because a user may connect through an anonymizing proxy, or may be in an unusual case, such as getting service from a neighboring country, or using an IP block leased from a company in another country. Additionaly, users accessing a server on a local network may be using an IP that is not assigned to any country (e.g. 192.168.x.x).
@author Roland Michael dela Peña.
File
smart_ip.moduleView source
<?php
/**
* @file
* Determines country, geo location (longitude/latitude), region, city and
* postal code of the user, based on IP address
*
* This module uses the IP address that a user is connected from to extract
* the location information where the user is located. This method is not
* foolproof, because a user may connect through an anonymizing proxy, or may
* be in an unusual case, such as getting service from a neighboring country,
* or using an IP block leased from a company in another country.
* Additionaly, users accessing a server on a local network may be using
* an IP that is not assigned to any country (e.g. 192.168.x.x).
*
* @author Roland Michael dela Peña.
*/
use Drupal\smart_ip\SmartIp;
use Drupal\smart_ip\SmartIpEvents;
use Drupal\smart_ip\SmartIpLocationInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Component\Serialization\Json;
/**
* Implements hook_help().
*/
function smart_ip_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.smart_ip':
return $output = '<p>' . t("Smart IP identify visitor's geographical location (longitude/latitude), \n country, region, city and postal code based on the IP address of the user. \n These information will be stored at session variable ($_SESSION) with \n array key 'smart_ip' and Drupal user data service using the parameters \n 'smart_ip' as module and 'geoip_location' as name of the user but \n optionally it can be disabled (by role) at Smart IP admin page. Other\n modules can use the function \n \\Drupal\\smart_ip\\SmartIp::query($ipAddress) that returns an array \n containing the visitor's ISO 3166 2-character country code, longitude, \n latitude, region, city and postal code. It provides a feature for you to \n perform your own IP lookup and admin spoofing of an arbitrary IP for \n testing purposes.") . '</p>';
return $output;
case 'smart_ip.settings':
$output = '<p>' . t('Configure the Smart IP settings') . '</p>';
return $output;
}
return '';
}
/**
* Implements hook_entity_insert().
*
* Save new user's geolocation upon registration.
*/
function smart_ip_entity_insert(EntityInterface $entity) {
if ($entity
->getEntityTypeId() == 'user') {
$is_new = $entity
->getCreatedTime() == \Drupal::time()
->getRequestTime();
if ($is_new) {
$save_user_location = \Drupal::config('smart_ip.settings')
->get('save_user_location_creation');
if ($save_user_location) {
$data['location'] = SmartIp::query();
// Determine if saving location details of visitor from EU countries are
// permitted.
$euVisitorsDontSave = \Drupal::config('smart_ip.settings')
->get('eu_visitor_dont_save') && $data['location']['isGdprCountry'];
if (!$euVisitorsDontSave) {
/** @var \Drupal\user\UserData $userData */
$userData = \Drupal::service('user.data');
$userData
->set('smart_ip', $entity
->id(), 'geoip_location_original', $data);
}
}
}
}
}
/**
* Implements hook_cron().
*/
function smart_ip_cron() {
/** @var \Drupal\smart_ip\DatabaseFileEvent $event */
$event = \Drupal::service('smart_ip.database_file_event');
// Allow Smart IP source module to act on cron run.
\Drupal::service('event_dispatcher')
->dispatch(SmartIpEvents::CRON_RUN, $event);
}
/**
* Implements hook_page_attachments().
*/
function smart_ip_page_attachments(array &$page) {
if (!\Drupal\smart_ip\SmartIp::checkAllowedPage()) {
// This page is not on the list to access user's geolocation.
return;
}
/** @var \Drupal\smart_ip\SmartIpLocation $location */
$location = \Drupal::service('smart_ip.smart_ip_location');
$data['location'] = $location
->getData(FALSE);
$value = Json::encode($data);
// Make user geolocation available to javascript via "drupalSettings.smartIp".
$page['#attached']['drupalSettings']['smartIp'] = $value;
$page['#attached']['drupalSettings']['smartIpSrc'] = [
'smartIp' => SmartIpLocationInterface::SMART_IP,
'geocodedSmartIp' => SmartIpLocationInterface::GEOCODED_SMART_IP,
'w3c' => SmartIpLocationInterface::W3C,
];
}
/**
* Implements hook_theme().
*/
function smart_ip_theme() {
return [
'smart_ip_latitude_dms' => [
'variables' => [
'latitude' => NULL,
],
],
'smart_ip_longitude_dms' => [
'variables' => [
'longitude' => NULL,
],
],
];
}
/**
* Display latitude.
*/
function theme_smart_ip_latitude_dms($variable) {
$output = '';
list($degrees, $minutes, $seconds, $negative) = coordinates_dd_to_dms($variable['latitude']);
$output .= "{$degrees}° {$minutes}' {$seconds}\" ";
if (!$negative) {
$output .= 'N';
}
else {
$output .= 'S';
}
return $output;
}
/**
* Display longitude.
*/
function theme_smart_ip_longitude_dms($variable) {
$output = '';
list($degrees, $minutes, $seconds, $negative) = coordinates_dd_to_dms($variable['longitude']);
$output .= "{$degrees}° {$minutes}' {$seconds}\" ";
if (!$negative) {
$output .= 'E';
}
else {
$output .= 'W';
}
return $output;
}
/**
* Convert decimal degrees to degrees, minutes, seconds.
*/
function coordinates_dd_to_dms($coord) {
$negative = $coord < 0 ? TRUE : FALSE;
$coord = abs($coord);
$degrees = floor($coord);
$coord -= $degrees;
$coord *= 60;
$minutes = floor($coord);
$coord -= $minutes;
$coord *= 60;
$seconds = round($coord, 6);
return [
$degrees,
$minutes,
$seconds,
$negative,
];
}
/**
* Helper function for grabbing region name (FIPS).
*/
function smart_ip_get_region_static($country_code, $region_code) {
$region =& drupal_static(__FUNCTION__);
if (!isset($region[$country_code][$region_code])) {
module_load_include('inc', 'smart_ip', 'includes/smart_ip.region_lookup');
$region[$country_code][$region_code] = smart_ip_get_region($country_code, $region_code);
}
return $region;
}
/**
* Helper function for checking if EU member country and if country follows
* GDPR.
*
* @see https://gist.github.com/henrik/1688572
* @see https://europa.eu/european-union/about-eu/countries/member-countries_en
*/
function smart_ip_is_eu_gdpr_country($country_code, $eu_member_only = TRUE) {
$eu_gdpr_country =& drupal_static(__FUNCTION__);
if (!isset($eu_gdpr_country[$country_code][$eu_member_only])) {
$eu_member_list = [
'AT' => 'Austria',
'BE' => 'Belgium',
'BG' => 'Bulgaria',
'HR' => 'Croatia',
'CY' => 'Cyprus',
'CZ' => 'Czech Republic',
'DK' => 'Denmark',
'EE' => 'Estonia',
'FI' => 'Finland',
'FR' => 'France',
'DE' => 'Germany',
'GR' => 'Greece',
'HU' => 'Hungary',
'IE' => 'Ireland, Republic of (EIRE)',
'IT' => 'Italy',
'LV' => 'Latvia',
'LT' => 'Lithuania',
'LU' => 'Luxembourg',
'MT' => 'Malta',
'NL' => 'Netherlands',
'PL' => 'Poland',
'PT' => 'Portugal',
'RO' => 'Romania',
'SK' => 'Slovakia',
'SI' => 'Slovenia',
'ES' => 'Spain',
'SE' => 'Sweden',
];
$additional_gdpr_list = [
'GF' => 'French Guiana',
'GP' => 'Guadeloupe',
'MQ' => 'Martinique',
'ME' => 'Montenegro',
'YT' => 'Mayotte',
'RE' => 'Réunion',
'MF' => 'Saint Martin',
'GI' => 'Gibraltar',
'AX' => 'Åland Islands',
'PM' => 'Saint Pierre and Miquelon',
'GL' => 'Greenland',
'BL' => 'Saint Bartelemey',
'SX' => 'Sint Maarten',
'AW' => 'Aruba',
'CW' => 'Curacao',
'WF' => 'Wallis and Futuna',
'PF' => 'French Polynesia',
'NC' => 'New Caledonia',
'TF' => 'French Southern Territories',
'AI' => 'Anguilla',
'BM' => 'Bermuda',
'IO' => 'British Indian Ocean Territory',
'VG' => 'Virgin Islands, British',
'KY' => 'Cayman Islands',
'FK' => 'Falkland Islands (Malvinas)',
'MS' => 'Montserrat',
'PN' => 'Pitcairn',
'SH' => 'Saint Helena',
'GS' => 'South Georgia and the South Sandwich Islands',
'TC' => 'Turks and Caicos Islands',
'AD' => 'Andorra',
'LI' => 'Liechtenstein',
'MC' => 'Monaco',
'SM' => 'San Marino',
'VA' => 'Vatican City',
'JE' => 'Jersey',
'GG' => 'Guernsey',
'GI' => 'Gibraltar',
];
$eu_gdpr_country[$country_code][$eu_member_only] = isset($eu_member_list[$country_code]) ? $eu_member_list[$country_code] : NULL;
if (!$eu_member_only && empty($eu_gdpr_country[$country_code][$eu_member_only])) {
// The country is not EU member now check if the country follows GDPR.
$eu_gdpr_country[$country_code][$eu_member_only] = isset($additional_gdpr_list[$country_code]) ? $additional_gdpr_list[$country_code] : NULL;
}
}
return $eu_gdpr_country[$country_code][$eu_member_only];
}
Functions
Name | Description |
---|---|
coordinates_dd_to_dms | Convert decimal degrees to degrees, minutes, seconds. |
smart_ip_cron | Implements hook_cron(). |
smart_ip_entity_insert | Implements hook_entity_insert(). |
smart_ip_get_region_static | Helper function for grabbing region name (FIPS). |
smart_ip_help | Implements hook_help(). |
smart_ip_is_eu_gdpr_country | Helper function for checking if EU member country and if country follows GDPR. |
smart_ip_page_attachments | Implements hook_page_attachments(). |
smart_ip_theme | Implements hook_theme(). |
theme_smart_ip_latitude_dms | Display latitude. |
theme_smart_ip_longitude_dms | Display longitude. |