You are here

smart_ip.module in Smart IP 8.2

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.module
View 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\Core\Routing\RouteMatchInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;

/**
 * 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 (&#36;_SESSION) with \n        array key 'smart_ip' and Drupal &#36;user->data object with array key \n        'geoip_location' of the user but optionally it can be disabled (by role) \n        at Smart IP admin page. Other modules can use the function \n        smart_ip_get_location(&#36;ip_address) that returns an array containing \n        the visitor's ISO 3166 2-character country code, longitude, latitude, \n        region, city and postal code. It provides a feature for you to perform \n        your own IP lookup and admin spoofing of an arbitrary IP for testing \n        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) {
  $is_new = $entity
    ->getCreatedTime() == REQUEST_TIME;
  if ($entity
    ->getEntityTypeId() == 'user' && $is_new) {
    $save_user_location = \Drupal::config('smart_ip.settings')
      ->get('save_user_location_creation');
    if ($save_user_location) {
      $data['location'] = SmartIp::query();

      /** @var \Drupal\user\UserData $userData */
      $userData = \Drupal::service('user.data');
      $userData
        ->set('smart_ip', $entity
        ->id(), 'geoip_location_original', $data);
    }
  }
}

/**
 * Implements hook_user_login().
 *
 * Save user's geolocation upon login.
 */
function smart_ip_user_login(AccountInterface $account) {

  // Now check to see if this user has "administer smart_ip" permission
  // and if debug mode set.  If both are TRUE, use debug information
  // instead of real information
  $has_access = \Drupal::currentUser()
    ->hasPermission('administer smart_ip');
  $debug = \Drupal::config('smart_ip.settings')
    ->get('debug_mode');
  if ($has_access && $debug) {
    $ip = \Drupal::config('smart_ip.settings')
      ->get('debug_mode_ip');
    $location = SmartIp::query($ip);
    if (!empty($location)) {
      drupal_set_message(t('Using debug IP: %ip / Country: %country / Region: %region / City: %city / Postal code: %zip / Longitude: %long / Latitude: %lat / Time zone: %time_zone', array(
        '%ip' => $location['ipAddress'],
        '%country' => $location['country'],
        '%region' => $location['region'],
        '%city' => $location['city'],
        '%zip' => $location['zip'],
        '%long' => $location['longitude'],
        '%lat' => $location['latitude'],
        '%time_zone' => $location['timeZone'],
      )));
      \Drupal::service('smart_ip.smart_ip_location')
        ->save();
    }
  }
  else {
    $roles = \Drupal::config('smart_ip.settings')
      ->get('roles_to_geolocate');
    foreach ($roles as $rid) {
      if (in_array($rid, $account
        ->getRoles())) {

        // Save logged in user's location
        SmartIp::query();
        \Drupal::service('smart_ip.smart_ip_location')
          ->save();
        break;
      }
    }
  }
}

/**
 * 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();
  $value = \Drupal\Component\Serialization\Json::encode($data);

  // Make user geolocation available to javascript
  $page['#attached']['html_head'][] = [
    [
      '#tag' => 'script',
      '#value' => "var smartIp = {$value}",
    ],
    'smart_ip_location_javascript_access',
  ];
}

/**
 * Implements hook_theme().
 */
function smart_ip_theme() {
  return array(
    'smart_ip_latitude_dms' => array(
      'variables' => 'latitude',
    ),
    'smart_ip_longitude_dms' => array(
      'variables' => 'longitude',
    ),
  );
}

/**
 * Display latitude.
 */
function theme_smart_ip_latitude_dms($variable) {
  $output = '';
  list($degrees, $minutes, $seconds, $negative) = coordinates_dd_to_dms($variable['latitude']);
  $output .= "{$degrees}&deg; {$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}&deg; {$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 array(
    $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;
}

Functions

Namesort descending 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_page_attachments Implements hook_page_attachments().
smart_ip_theme Implements hook_theme().
smart_ip_user_login Implements hook_user_login().
theme_smart_ip_latitude_dms Display latitude.
theme_smart_ip_longitude_dms Display longitude.