View source
<?php
define('IP_GEOLOC_MAX_NUM_FONT_ICON_LIBS', 10);
define('IP_GEOLOC_CALLBACK_TIMEOUT', 30);
define('IP_GEOLOC_LOCATION_CHECK_INTERVAL', 60);
define('IP_GEOLOC_DEFAULT_PAGE_EXCLUSIONS', "admin/*\nsites/default/*\nsystem/ajax\njs/*");
define('IP_GEOLOC_MAP_DIV_DEFAULT_STYLE', 'height:300px');
define('IP_GEOLOC_CURRENT_VISITOR_MAP_OPTIONS', '{"mapTypeId":"roadmap", "disableDefaultUI":true, "zoom":15, "zoomControl":true}');
define('IP_GEOLOC_RECENT_VISITORS_MAP_OPTIONS', '{"mapTypeId":"roadmap", "disableDefaultUI":true, "zoom":2, "zoomControl":true, "scaleControl":true}');
define('IP_GEOLOC_EXAMPLE_MAP_OPTIONS', '{"mapTypeId":"roadmap", "zoom":10, "separator":", ", styles":[{"featureType":"road", "stylers":[{"saturation":-80}] }] }');
define('IP_GEOLOC_DOC_GOOGLE_MAP_OPTIONS', 'http://code.google.com/apis/maps/documentation/javascript/reference.html#MapOptions');
define('IP_GEOLOC_RANGE_SEPARATOR1', '--');
define('IP_GEOLOC_RANGE_SEPARATOR2', '...');
define('IP_GEOLOC_LEAFLET_MARKERCLUSTER_REGIONBOUND_JS', 'leaflet.markercluster-regionbound.min.js');
define('IP_GEOLOC_THROBBER_PREFIX', '<div class="ajax-progress ajax-progress-throbber"><div class="throbber">');
define('IP_GEOLOC_THROBBER_DEFAULT_TEXT', t('Locating you') . '...');
require_once 'ip_geoloc.session.inc';
require_once 'ip_geoloc_api.inc';
require_once 'ip_geoloc_blocks.inc';
require_once 'theme/ip_geoloc_theme.inc';
include_once 'ip_geoloc.openlayers.inc';
include_once 'ip_geoloc.tokens.inc';
include_once 'ip_geoloc.context.inc';
function ip_geoloc_ctools_plugin_api($module, $api) {
if ($module == 'context') {
return array(
'version' => 3,
);
}
if ($module == 'openlayers' && $api == 'openlayers_layers') {
return array(
'version' => 1,
);
}
}
function ip_geoloc_help($path, $arg) {
if ($path == 'admin/help#ip_geoloc') {
return t('Detailed information is on the <a href="@ip_geoloc">IP Geolocation project page</a> and in the <a href="@README">README</a> file', array(
'@ip_geoloc' => url('http://drupal.org/project/ip_geoloc'),
'@README' => url(drupal_get_path('module', 'ip_geoloc') . '/README.txt'),
));
}
}
function ip_geoloc_library() {
$libraries = array();
$path_fullscreen = libraries_get_path('leaflet-fullscreen') . '/dist';
$libraries['leaflet-fullscreen'] = array(
'title' => 'Leaflet Fullscreen',
'version' => '0.0.3',
'js' => array(
array(
'type' => 'file',
'data' => "{$path_fullscreen}/Leaflet.fullscreen.min.js",
'group' => JS_LIBRARY,
'weight' => 2,
'preprocess' => FALSE,
),
),
'css' => array(
"{$path_fullscreen}/leaflet.fullscreen.css" => array(
'type' => 'file',
'media' => 'screen',
'group' => CSS_DEFAULT,
'weight' => 2,
),
),
);
$path_minimap = libraries_get_path('leaflet-minimap') . '/dist';
$libraries['leaflet-minimap'] = array(
'title' => 'Leaflet MiniMap',
'version' => '2.1.0',
'js' => array(
array(
'type' => 'file',
'data' => "{$path_minimap}/Control.MiniMap.min.js",
'group' => JS_LIBRARY,
'weight' => 2,
'preprocess' => FALSE,
),
),
'css' => array(
"{$path_minimap}/Control.MiniMap.min.css" => array(
'type' => 'file',
'media' => 'screen',
'group' => CSS_DEFAULT,
'weight' => 2,
),
),
);
foreach (ip_geoloc_get_font_icon_libs() as $css_file) {
$css_file = trim($css_file);
if (!empty($css_file)) {
$libraries['ip_geoloc_font_icon_libs']['css'][$css_file] = array(
'type' => 'file',
'media' => 'all',
'group' => -101,
);
}
}
if (!empty($libraries['ip_geoloc_font_icon_libs']['css'])) {
$libraries['ip_geoloc_font_icon_libs']['title'] = t('IPGV&M font icon libraries');
}
return $libraries;
}
function ip_geoloc_library_alter(&$libraries, $module) {
if (isset($libraries['leaflet_markercluster']['js'][0]['data'])) {
$js = $libraries['leaflet_markercluster']['js'][0]['data'];
$last_slash = strrpos($js, '/');
$js_new = drupal_substr($js, 0, $last_slash + 1) . IP_GEOLOC_LEAFLET_MARKERCLUSTER_REGIONBOUND_JS;
if (file_exists($js_new)) {
$libraries['leaflet_markercluster']['js'][0]['data'] = $js_new;
}
}
}
function ip_geoloc_menu() {
$items = array();
$items['admin/config/system/ip_geoloc'] = array(
'title' => 'IP Geolocation Views & Maps',
'description' => 'Configure map markers and how geolocation information is updated.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'ip_geoloc_admin_configure',
),
'access arguments' => array(
'administer site configuration',
),
'file' => 'ip_geoloc.admin.inc',
);
$items['js/ip_geoloc/current_location'] = array(
'title' => 'Current location recipient',
'page callback' => 'ip_geoloc_current_location_ajax_recipient',
'access arguments' => array(
'access content',
),
'type' => MENU_CALLBACK,
);
$items['ip_geoloc/region_autocomplete'] = array(
'title' => '"Set my location" block region autocomplete',
'page callback' => 'ip_geoloc_region_autocomplete',
'access arguments' => array(
'access content',
),
'type' => MENU_CALLBACK,
);
return $items;
}
function ip_geoloc_region_autocomplete($partial_region = '') {
$matches = array();
if (strlen($partial_region) >= 2) {
$geo_vocabulary_id = variable_get('ip_geoloc_geo_vocabulary_id', 0);
foreach (taxonomy_get_tree($geo_vocabulary_id) as $term) {
$term_name = check_plain($term->name);
$is_match = stripos($term_name, $partial_region) !== FALSE;
if ($is_match) {
$matches[$term_name] = $term_name;
}
}
}
drupal_json_output($matches);
}
function ip_geoloc_js_info() {
$dependencies = module_exists('session_cache_file') ? array(
'session_cache',
'session_cache_file',
) : (module_exists('session_cache') ? array(
'session_cache',
) : array());
$js_info = array(
'current_location' => array(
'bootstrap' => module_exists('better_statistics') ? DRUPAL_BOOTSTRAP_FULL : DRUPAL_BOOTSTRAP_SESSION,
'callback function' => 'ip_geoloc_current_location_ajax_recipient',
'dependencies' => $dependencies,
'skip init' => TRUE,
'token' => FALSE,
),
);
return $js_info;
}
function ip_geoloc_init() {
foreach (arg() as $arg) {
if ($arg == 'erase-location') {
$location = ip_geoloc_get_visitor_location();
if (empty($location['is_updated'])) {
_ip_geoloc_set_session_value('location', NULL);
$_GET['q'] = str_replace('/erase-location', '', $_GET['q']);
return;
}
}
}
ip_geoloc_log_errors();
$location = ip_geoloc_get_visitor_location();
$reverse_geocode_client_timeout = _ip_geoloc_reverse_geocode_timeout();
if ($reverse_geocode_client_timeout || ip_geoloc_is_first_click()) {
_ip_geoloc_reinit_location($location, $reverse_geocode_client_timeout);
ip_geoloc_store_location($location);
_ip_geoloc_set_session_value('location', $location);
}
$scheduled_reverse_geocode = _ip_geoloc_check_location($location);
if ($scheduled_reverse_geocode && !variable_get('maintenance_mode', 0)) {
ip_geoloc_get_current_location();
_ip_geoloc_set_session_value('last_position_check', time());
}
}
function ip_geoloc_log_errors() {
if ($error = _ip_geoloc_get_session_value('error')) {
watchdog('IPGV&M', $error, NULL, WATCHDOG_NOTICE);
ip_geoloc_debug('IPGV&M, ' . ip_address() . ': ' . $error, 'warning');
_ip_geoloc_set_session_value('error', NULL);
}
}
function ip_geoloc_is_first_click() {
$last_position_check = _ip_geoloc_get_session_value('last_position_check');
return empty($last_position_check);
}
function _ip_geoloc_reinit_location(&$location, $reverse_geocode_client_timeout) {
$location = array(
'fixed_address' => isset($location['fixed_address']) ? (int) $location['fixed_address'] : NULL,
'regions' => isset($location['regions']) ? $location['regions'] : NULL,
);
if (ip_geoloc_use_smart_ip_if_enabled($location) || ip_geoloc_use_geoip_api_if_enabled($location)) {
if ($reverse_geocode_client_timeout) {
watchdog('IPGV&M', 'Location timeout (waited %sec s). Fallback: %address.', array(
'%sec' => number_format($reverse_geocode_client_timeout, 1),
'%address' => isset($location['formatted_address']) ? $location['formatted_address'] : '',
), WATCHDOG_NOTICE);
}
}
else {
ip_geoloc_debug(t('Smart IP and GeoIP API fallbacks NOT enabled.'));
}
}
function ip_geoloc_current_location_ajax_recipient() {
if (isset($_POST['error'])) {
$error = check_plain($_POST['error']);
_ip_geoloc_set_session_value('error', $error);
drupal_json_output($error);
drupal_exit();
}
$location = array(
'ip_address' => ip_address(),
);
foreach ($_POST as $key => $value) {
if (drupal_substr($key, 0, 3) !== 'js_') {
$location[check_plain($key)] = check_plain($value);
}
}
$location['provider'] = empty($location['country']) ? 'device' : 'device+google';
$since = _ip_geoloc_get_session_value('position_pending_since');
ip_geoloc_debug(t('IPGV&M: returned from position callback in %since s: !location', array(
'%since' => isset($since) ? number_format(microtime(TRUE) - $since, 1) : '?',
'!location' => ip_geoloc_pretty_print($location),
)));
if ($since && module_exists('better_statistics')) {
require_once 'plugins/ip_geoloc.statistics.inc';
_ip_geoloc_statistics_backfill($since, $location);
}
if (ip_geoloc_store_location($location) !== FALSE) {
$location['ip_address'] = NULL;
}
$location['fixed_address'] = 0;
$location['is_updated'] = TRUE;
_ip_geoloc_set_session_value('location', NULL);
_ip_geoloc_set_session_value('location', $location);
_ip_geoloc_set_session_value('position_pending_since', NULL);
drupal_json_output('');
drupal_exit();
}
function ip_geoloc_use_smart_ip_if_enabled(&$location) {
if (variable_get('ip_geoloc_smart_ip_as_backup', FALSE)) {
if (function_exists('smart_ip_get_location')) {
if (empty($location['ip_address'])) {
$location['ip_address'] = ip_address();
}
$fixed_address = isset($location['fixed_address']) ? $location['fixed_address'] : 0;
$region = isset($location['region']) ? $location['region'] : 0;
$location = array(
'provider' => 'smart_ip',
'fixed_address' => $fixed_address,
'region' => $region,
) + smart_ip_get_location($location['ip_address']);
return TRUE;
}
ip_geoloc_debug(t('IPGV&M: Smart IP configured as a backup, but is not enabled.'));
}
return FALSE;
}
function ip_geoloc_use_geoip_api_if_enabled(&$location) {
if (!function_exists('geoip_city')) {
return FALSE;
}
$location['provider'] = 'geoip';
if (empty($location['ip_address'])) {
$location['ip_address'] = ip_address();
}
$geoip_location = (array) geoip_city($location['ip_address']);
if (reset($geoip_location)) {
$geoip_location['country'] = isset($geoip_location['country_name']) ? $geoip_location['country_name'] : '';
unset($geoip_location['country_name']);
$location = array_merge($geoip_location, $location);
ip_geoloc_format_address($location);
}
ip_geoloc_debug(t('IPGV&M: GeoIP API retrieved: !location', array(
'!location' => ip_geoloc_pretty_print($location),
)));
return TRUE;
}
function _ip_geoloc_check_location($location = NULL) {
if (!variable_get('ip_geoloc_google_to_reverse_geocode', FALSE)) {
return FALSE;
}
$path_alias = drupal_get_path_alias();
$include_pages = variable_get('ip_geoloc_include_pages', '*');
if (!drupal_match_path($path_alias, $include_pages)) {
return FALSE;
}
$exclude_pages = variable_get('ip_geoloc_exclude_pages', IP_GEOLOC_DEFAULT_PAGE_EXCLUSIONS);
if (drupal_match_path($path_alias, $exclude_pages)) {
return FALSE;
}
global $user;
$roles_to_reverse_geocode = variable_get('ip_geoloc_roles_to_reverse_geocode', array(
DRUPAL_ANONYMOUS_RID,
DRUPAL_AUTHENTICATED_RID,
));
$roles_applicable = array_intersect($roles_to_reverse_geocode, array_keys($user->roles));
if (empty($roles_applicable)) {
return FALSE;
}
$interval = (int) variable_get('ip_geoloc_location_check_interval', IP_GEOLOC_LOCATION_CHECK_INTERVAL);
if ($interval == 0) {
return !isset($location['latitude']);
}
$last_position_check = _ip_geoloc_get_session_value('last_position_check');
if (isset($last_position_check)) {
$time_elapsed = time() - $last_position_check;
if ($time_elapsed < $interval) {
ip_geoloc_debug(t('IPGV&M: next update scheduled for first click after %seconds seconds (unless overridden or on excluded page).', array(
'%seconds' => $interval - $time_elapsed,
)));
return FALSE;
}
}
return TRUE;
}
function _ip_geoloc_reverse_geocode_timeout() {
$pending_since = _ip_geoloc_get_session_value('position_pending_since');
if (isset($pending_since)) {
$time_elapsed = microtime(TRUE) - $pending_since;
if ($time_elapsed > IP_GEOLOC_CALLBACK_TIMEOUT) {
ip_geoloc_debug(t('IPGV&M timeout: the last reverse-geocode request was @sec s ago.', array(
'@sec' => number_format($time_elapsed, 1),
)));
_ip_geoloc_set_session_value('position_pending_since', NULL);
return $time_elapsed;
}
}
return FALSE;
}
function ip_geoloc_format_address(&$location) {
$location['formatted_address'] = isset($location['city']) ? $location['city'] : '';
if (!empty($location['region'])) {
$location['formatted_address'] .= ' ' . $location['region'];
}
if (!empty($location['postal_code']) && $location['postal_code'] != '-') {
$location['formatted_address'] .= ' ' . $location['postal_code'] . ',';
}
if (!empty($location['country'])) {
$location['formatted_address'] .= ' ' . $location['country'];
}
$location['formatted_address'] = trim($location['formatted_address']);
}
function ip_geoloc_flatten_google_address($google_address, &$ip_geoloc_address) {
if (is_array($google_address) && is_array($google_address['address_components']) && is_array($ip_geoloc_address)) {
$ip_geoloc_address['provider'] = 'google';
foreach ($google_address['address_components'] as $component) {
$long_name = $component['long_name'];
if (!empty($long_name)) {
$type = $component['types'][0];
$ip_geoloc_address[$type] = $long_name;
if ($type == 'country' && !empty($component['short_name'])) {
$ip_geoloc_address['country_code'] = $component['short_name'];
}
}
}
$ip_geoloc_address['formatted_address'] = $google_address['formatted_address'];
$ip_geoloc_address['latitude'] = $google_address['geometry']['location']['lat'];
$ip_geoloc_address['longitude'] = $google_address['geometry']['location']['lng'];
return TRUE;
}
return FALSE;
}
function ip_geoloc_pretty_print($location) {
$t = '';
foreach ($location as $label => $value) {
if (!empty($value)) {
$t .= check_plain($label) . ': <strong>' . check_plain($value) . '</strong> ';
}
}
return empty($t) ? t('nothing') : $t;
}
function ip_geoloc_marker_directory() {
$path = drupal_get_path('module', 'ip_geoloc');
return variable_get('ip_geoloc_marker_directory', "{$path}/" . (module_exists('leaflet') ? 'amarkers' : 'markers'));
}
function ip_geoloc_marker_dimensions() {
$dimensions = variable_get('ip_geoloc_marker_dimensions');
if (empty($dimensions)) {
$directory = ip_geoloc_marker_directory();
$dimensions = strpos($directory, '/amarkers') ? '32 x 42' : '21 x 34';
}
return $dimensions;
}
function ip_geoloc_marker_colors() {
$color_list =& drupal_static(__FUNCTION__);
if (!isset($color_list)) {
$color_list = array(
'' => '<' . t('default') . '>',
0 => '<' . t('no marker') . '>',
);
if ($directory_handle = opendir(ip_geoloc_marker_directory())) {
while (($filename = readdir($directory_handle)) !== FALSE) {
if ($ext_pos = strrpos($filename, '.png')) {
$color = drupal_substr($filename, 0, $ext_pos);
$color_list[$color] = t($color);
}
}
closedir($directory_handle);
}
asort($color_list);
}
return $color_list;
}
function ip_geoloc_openlayers_marker_layers() {
$num_location_marker_layers = variable_get('ip_geoloc_num_location_marker_layers', IP_GEOLOC_DEF_NUM_MARKER_LAYERS);
$marker_layers = array();
for ($layer = 1; $layer <= $num_location_marker_layers; $layer++) {
$marker_layers[$layer] = t('Marker layer') . " #{$layer}";
}
return $marker_layers;
}
function ip_geoloc_form_views_ui_edit_display_form_alter(&$form, &$form_state) {
if (isset($form['options']['style_options']['differentiator'])) {
$form['buttons']['submit']['#submit'][] = 'ip_geoloc_plugin_style_diff_color_ass_submit';
}
}
function ip_geoloc_smart_ip_get_location_alter(&$location) {
if (empty($location['postal_code']) && isset($location['zip'])) {
$location['postal_code'] = $location['zip'];
}
ip_geoloc_format_address($location);
ip_geoloc_debug(t('IPGV&M: Smart IP retrieved: !location', array(
'!location' => ip_geoloc_pretty_print($location),
)));
}
function ip_geoloc_is_in_range($value, $range, $view_args = NULL) {
if (!isset($value) || !isset($range)) {
return FALSE;
}
if (is_array($range)) {
$range = reset($range);
}
$from_to = explode(IP_GEOLOC_RANGE_SEPARATOR1, $range);
if (count($from_to) < 2) {
$from_to = explode(IP_GEOLOC_RANGE_SEPARATOR2, $range);
}
if (($from = _ip_geoloc_extract_value($from_to[0], $view_args)) === NULL) {
return FALSE;
}
if (count($from_to) == 1) {
return trim($value) == trim($from);
}
if (($to = _ip_geoloc_extract_value($from_to[1], $view_args)) === NULL) {
return FALSE;
}
if ($from == '' && $to == '') {
return TRUE;
}
if ($from != '' && $to != '') {
return $value >= $from && $value <= $to;
}
if ($from != '') {
return $value >= $from;
}
return $value <= $to;
}
function _ip_geoloc_extract_value($string, $view_args) {
if (preg_match('/^!([0-9])/', $string, $matches)) {
$arg = $matches[1];
return isset($view_args[$arg - 1]) ? $view_args[$arg - 1] : arg($arg);
}
return $string;
}
function ip_geoloc_range_widget_validate($element, &$form_state) {
$range = $element['#value'];
$from_to = explode(IP_GEOLOC_RANGE_SEPARATOR1, $range);
if (count($from_to) < 2) {
$from_to = explode(IP_GEOLOC_RANGE_SEPARATOR2, $range);
}
if (count($from_to) < 2) {
}
else {
$from = trim($from_to[0]);
$to = trim($from_to[1]);
if (preg_match('/^![0-9]/', $from) || preg_match('/^![0-9]/', $to)) {
return;
}
$ok = TRUE;
if (is_numeric($from) || is_numeric($to)) {
$ok = empty($from) && empty($to) || empty($from) && is_numeric($to) || empty($to) && is_numeric($from) || is_numeric($from) && is_numeric($to) && $from <= $to;
}
elseif (!empty($from) && !empty($to)) {
$ok = $from <= $to;
}
if (!$ok) {
form_error($element, t('Invalid range.'));
}
}
}
function ip_geoloc_get_font_icon_libs() {
$libs = array();
for ($i = 1; $i <= IP_GEOLOC_MAX_NUM_FONT_ICON_LIBS; $i++) {
$file = variable_get("ip_geoloc_font_icon_lib{$i}");
if (!empty($file)) {
$libs[$i] = $file;
}
}
$known_install = 'sites/all/libraries/font-awesome/css/font-awesome.min.css';
if (empty($libs) && file_exists($known_install)) {
$libs[1] = $known_install;
}
return $libs;
}
function ip_geoloc_debug_flag() {
global $user;
$user_names = explode(',', check_plain(variable_get('ip_geoloc_debug')));
foreach ($user_names as $user_name) {
$user_name = drupal_strtolower(trim($user_name));
$match = isset($user->name) ? $user_name == drupal_strtolower(trim($user->name)) : $user_name == 'anon' || $user_name == 'anonymous';
if ($match) {
return TRUE;
}
}
return FALSE;
}
function ip_geoloc_debug($message, $type = 'status') {
if (ip_geoloc_debug_flag()) {
return drupal_set_message($message, $type, FALSE);
}
}
function ip_geoloc_same_path() {
if (empty($_SERVER['HTTP_REFERER'])) {
return FALSE;
}
$referer = $_SERVER['HTTP_REFERER'];
global $base_url;
if (strpos($referer, $base_url) === 0) {
$prev_path = drupal_substr($referer, drupal_strlen($base_url) + 1);
if (empty($prev_path) && drupal_is_front_page()) {
return TRUE;
}
return $prev_path == current_path() || $prev_path == drupal_get_path_alias();
}
return FALSE;
}
function ip_geoloc_ctools_plugin_directory($module, $plugin) {
if ($module == 'ctools' || $module == 'panels') {
return 'plugins/' . $plugin;
}
}
function ip_geoloc_views_post_render(&$view, &$rendered_output) {
if (!isset($view) || !isset($view->style_plugin->plugin_name)) {
return;
}
$name = $view->style_plugin->plugin_name;
if (strpos($name, 'ip_geoloc') === 0 && ($location = ip_geoloc_get_visitor_location())) {
$location['is_updated'] = FALSE;
_ip_geoloc_set_session_value('location', $location);
}
}
function ip_geoloc_views_api() {
return array(
'api' => views_api_version(),
'path' => drupal_get_path('module', 'ip_geoloc') . '/views',
);
}
function ip_geoloc_statistics_api() {
return array(
'version' => 1,
'path' => drupal_get_path('module', 'ip_geoloc') . '/plugins',
'file' => 'ip_geoloc.statistics.inc',
);
}
function ip_geoloc_build_google_api_url() {
$query = array();
switch (variable_get('ip_geoloc_auth_method', 0)) {
case 1:
$key = trim(variable_get('ip_geoloc_apikey', ''));
if (!empty($key)) {
$query['key'] = $key;
}
break;
case 2:
$client_id = trim(variable_get('ip_geoloc_client_id', ''));
if (!empty($client_id)) {
$query['client'] = $client_id;
$signature = trim(variable_get('ip_geoloc_signature', ''));
if (!empty($signature)) {
$query['signature'] = $signature;
}
}
break;
default:
return '';
}
if (!empty($query)) {
$query['v'] = 'weekly';
$query['libraries'] = 'places';
return 'https://maps.googleapis.com/maps/api/js?' . drupal_http_build_query($query);
}
return '';
}
function _ip_geoloc_custom_formatted_address($location, $need_street = FALSE, $need_locality = FALSE, $need_country = FALSE) {
if (!$need_street && !$need_locality && !$need_country) {
return $location['formatted_address'];
}
$address = '';
if ($need_street) {
if (!empty($location['street_number'])) {
$address = $location['street_number'];
}
if (!empty($location['route'])) {
$address .= empty($address) ? $location['route'] : ' ' . $location['route'];
}
}
if ($need_locality) {
if (!empty($address) && !empty($location['locality']) && !empty($location['administrative_area_level_1'])) {
$address .= ', ';
}
if (!empty($location['locality'])) {
$address .= $location['locality'];
}
if (!empty($location['administrative_area_level_1'])) {
$address .= (empty($location['locality']) ? '' : ', ') . $location['administrative_area_level_1'];
}
if (!empty($location['postal_code'])) {
$address .= ' ' . $location['postal_code'];
}
}
if ($need_country) {
if (!empty($address)) {
$address .= ', ';
}
$address .= $location['country'];
}
return $address;
}