params= $params; $this->params['language'] = reset($locales); if (empty($this->params['language'])) { $this->params['language'] = 'en'; } $default_options = array( 'timeout' => 1, ); $this->options = $options + $default_options; } protected function locales($locale, $value) { $locales = array('en' => $value); if ($locale != 'en') { $locales[$locale] = $value; } return $locales; } public function city($ip) { $data = $this->api_call($ip); if (!$data) return null; $r = array(); $r['extra']['original'] = $data; if (isset($data['success']) && $data['success'] === false) { throw new \RuntimeException($data['error']['info']); // Example error: /* @see https://ipstack.com/documentation#errors { "success": false, "error": { "code": 104, "type": "monthly_limit_reached", "info": "Your monthly API request volume has been reached. Please upgrade your plan." } } */ } $locale = $this->params['language']; if (!empty($data['continent_name'])) $r['continent']['names'] = $this->locales($locale, $data['continent_name']); if (!empty($data['continent_code'])) $r['continent']['code'] = strtoupper($data['continent_code']); if (!empty($data['country_name'])) $r['country']['names'] = $this->locales($locale, $data['country_name']); if (!empty($data['country_code'])) $r['country']['iso_code'] = strtoupper($data['country_code']); if (!empty($data['region_code'])) { $r['subdivisions'][0] = array( 'iso_code' => $data['region_code'], 'names' => $this->locales($locale, $data['region_name']), ); } if (!empty($data['city'])) $r['city']['names'] = $this->locales($locale, $data['city']); if (!empty($data['latitude'])) $r['location']['latitude'] = $data['latitude']; if (!empty($data['longitude'])) $r['location']['longitude'] = $data['longitude']; if (isset($data['is_eu'])) $r['country']['is_in_european_union'] = $data['is_eu']; if (isset($data['timezone']['id'])) $r['location']['time_zone'] = $data['timezone']['id']; if (isset($data['connection']['asn'])) $r['traits']['autonomous_system_number'] = $data['connection']['asn']; if (isset($data['connection']['isp'])) $r['traits']['isp'] = $data['connection']['isp']; if (isset($data['security']['is_proxy'])) $r['traits']['is_anonymous_vpn'] = $data['security']['is_proxy'] && $data['security']['proxy_type'] == 'vpn'; if (isset($data['security']['is_tor'])) $r['traits']['is_tor_exit_node'] = $data['security']['is_tor']; if (!empty($data['location']['country_flag_emoji'])) $r['extra']['flag'] = strtoupper($data['location']['country_flag_emoji']); $r['traits']['ip_address'] = $ip; $record = new \GeoIp2\Model\City($r, array('en')); return $record; } public function country($ip) { return $this->city($ip); // too much info shouldn't hurt ... } public function close() { } private function build_url($ip) { $url = $this->params['ssl'] ? 'https' : 'http'; $url .= '://' . self::URL . $ip; $params = [ 'access_key' => $this->params['key'], 'language' => $this->params['language'], ]; return $url . '?' . \http_build_query($params); } private function api_call($ip) { try { // Setting timeout limit to speed up sites $context = stream_context_create( array( 'http' => array( 'timeout' => $this->options['timeout'], ), ) ); // Using @file... to supress errors // Example output: {"country_name":"UNITED STATES","country_code":"US","city":"Aurora, TX","ip":"12.215.42.19"} $body = @file_get_contents($this->build_url($ip), false, $context); $data = json_decode($body, true); return $data; } catch (\Exception $e) { // If the API isn't available, we have to do this throw $e; return null; } } } class IpstackSource extends AbstractDataSource { protected $params = array(); public function __construct() { $this->params['key'] = get_option('geoip-detect-ipstack_key', ''); $this->params['ssl'] = get_option('geoip-detect-ipstack_ssl', 0); } public function getId() { return 'ipstack'; } public function getLabel() { return __('Ipstack Web-API', 'geoip-detect'); } public function getDescriptionHTML() { return __('Ipstack', 'geoip-detect'); } public function getStatusInformationHTML() { $html = ''; $html .= \sprintf(__('SSL: %s', 'geoip-detect'), $this->params['ssl'] ? __('Enabled', 'geoip-detect') : __('Disabled', 'geoip-detect')) . '
'; if (!$this->isWorking()) $html .= '
' . __('Ipstack only works with an API key.', 'geoip-detect') . '
'; return $html; } public function getParameterHTML() { $label_key = __('API Access Key:', 'geoip-detect'); $label_ssl = __('Access the API via SSL:', 'geoip-detect'); $key = esc_attr($this->params['key']); $html = <<
$label_ssl '; return $html; } public function saveParameters($post) { $message = ''; if (isset($post['options_ipstack']['key'])) { update_option('geoip-detect-ipstack_key', $post['options_ipstack']['key']); $this->params['key']= $post['options_ipstack']['key']; } if (isset($post['options_ipstack']['ssl'])) { $ssl = (int) $post['options_ipstack']['ssl']; update_option('geoip-detect-ipstack_ssl', $ssl); $this->params['ssl'] = $post['options_ipstack']['ssl']; } if (geoip_detect2_is_source_active('ipstack') && !$this->isWorking()) $message .= __('Ipstack only works with an API key.', 'geoip-detect'); return $message; } public function getReader($locales = array('en'), $options = array()) { return new Reader($this->params, $locales, $options); } public function isWorking() { return !empty($this->params['key']); } } geoip_detect2_register_source(new IpstackSource());