Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ajax support (old) #46

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions admin-ui.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,14 @@ function geoip_detect_option_page() {

$message = '';

$numeric_options = array('set_css_country', 'has_reverse_proxy', 'disable_pagecache');
$numeric_options = array('set_css_country', 'has_reverse_proxy', 'disable_pagecache', 'ajax_enabled', 'ajax_shortcode');
$text_options = array('external_ip');
$option_names = array_merge($numeric_options, $text_options);

if (geoip_detect_verify_nonce()) {
switch(@$_POST['action'])
{
// Update the automatically installed Lite DB
case 'update':
$registry->setCurrentSource('auto');

Expand All @@ -108,11 +109,12 @@ function geoip_detect_option_page() {

break;

// Choose a datasource
case 'choose':
$registry->setCurrentSource($_POST['options']['source']);
break;

// Save the options of a data source
case 'options-source':
$messages = array();
foreach ($sources as $s) {
Expand All @@ -126,6 +128,7 @@ function geoip_detect_option_page() {

break;

// Save general options
case 'options':
// Empty IP Cache
delete_transient('geoip_detect_external_ip');
Expand Down
153 changes: 153 additions & 0 deletions ajax.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<?php

/**
* Calling the API via AJAX
* ========================
*
* These function make it possible to query the geo-data corresponding to the current visitor via AJAX.
* This can be useful for Site Cache: If the variable content/behavior is injected via JS only, the HTML still can be cached.
*
* WARNING: We cannot completely prevent others from using this functionality, though, as JS requests can be faked.
* To make this harder, we check the referer (so simply embeding the JS in another site won't work).
*/

function geoip_detect_ajax_get_info_from_current_ip() {
// Enabled in preferences? If not, do as if the plugin doesn't even exist.
if (!get_option('geoip-detect-ajax_enabled'))
return;

if (!defined( 'DOING_AJAX' ))
_geoip_detect_ajax_error('This method is for AJAX only.');

// Referer check

$referer = wp_get_referer();
$site_url = get_site_url();
if (strpos($referer, $site_url) !== 0)
_geoip_detect_ajax_error('Incorrect referer.'); // Ajax only works if coming from the same site. No CORS even if headers are enabled.

// Do not cache this response!
if (!headers_sent()) {
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
}

$locales = null;
if (isset($_REQUEST['locales']))
$locales = $_REQUEST['locales'];

$data = _geoip_detect_ajax_get_data($locales);

if ($data['extra']['error'])
http_response_code(400);

echo json_encode($data);
exit;
}

add_action( 'wp_ajax_geoip_detect2_get_info_from_current_ip', 'geoip_detect_ajax_get_info_from_current_ip' );
add_action( 'wp_ajax_nopriv_geoip_detect2_get_info_from_current_ip', 'geoip_detect_ajax_get_info_from_current_ip' );

function _geoip_detect_ajax_error($error) {
http_response_code(412);

$data = array('extra' => array('error' => $error));
echo json_encode($data);

exit;
}

function _geoip_detect_ajax_get_data($locales, $options = array()) {
$info = geoip_detect2_get_info_from_current_ip($locales, $options);
$data = $info->jsonSerialize();

// Add the 'name' field
$locales = apply_filters('geoip_detect2_locales', $locales);
foreach ($data as &$prop) {
if (isset($prop['names']) && is_array($prop['names'])) {
$prop['name'] = _geoip_detect_ajax_get_name($prop['names'], $locales);
}
}

return $data;
}

function _geoip_detect_ajax_get_name($names, $locales)
{
foreach ($locales as $locale) {
if (isset($names[$locale])) {
return $names[$locale];
}
}
// Nothing found ...
return '';
}


function _geoip_detect_register_javascript() {
wp_register_script('geoip-detect-js', GEOIP_DETECT_PLUGIN_URI . 'js/geoip_detect.js', array('jquery'), GEOIP_DETECT_VERSION, true);

$data = array();
$data['ajaxurl'] = admin_url('/admin-ajax.php');
wp_localize_script('geoip-detect-js', 'geoip_detect', $data);
}

add_action('wp_enqueue_scripts', '_geoip_detect_register_javascript');

// Backwards compat for PHP 5.3
if (!function_exists('http_response_code')) {
function http_response_code($code = NULL) {
if ($code !== NULL) {
switch ($code) {
case 100: $text = 'Continue'; break;
case 101: $text = 'Switching Protocols'; break;
case 200: $text = 'OK'; break;
case 201: $text = 'Created'; break;
case 202: $text = 'Accepted'; break;
case 203: $text = 'Non-Authoritative Information'; break;
case 204: $text = 'No Content'; break;
case 205: $text = 'Reset Content'; break;
case 206: $text = 'Partial Content'; break;
case 300: $text = 'Multiple Choices'; break;
case 301: $text = 'Moved Permanently'; break;
case 302: $text = 'Moved Temporarily'; break;
case 303: $text = 'See Other'; break;
case 304: $text = 'Not Modified'; break;
case 305: $text = 'Use Proxy'; break;
case 400: $text = 'Bad Request'; break;
case 401: $text = 'Unauthorized'; break;
case 402: $text = 'Payment Required'; break;
case 403: $text = 'Forbidden'; break;
case 404: $text = 'Not Found'; break;
case 405: $text = 'Method Not Allowed'; break;
case 406: $text = 'Not Acceptable'; break;
case 407: $text = 'Proxy Authentication Required'; break;
case 408: $text = 'Request Time-out'; break;
case 409: $text = 'Conflict'; break;
case 410: $text = 'Gone'; break;
case 411: $text = 'Length Required'; break;
case 412: $text = 'Precondition Failed'; break;
case 413: $text = 'Request Entity Too Large'; break;
case 414: $text = 'Request-URI Too Large'; break;
case 415: $text = 'Unsupported Media Type'; break;
case 500: $text = 'Internal Server Error'; break;
case 501: $text = 'Not Implemented'; break;
case 502: $text = 'Bad Gateway'; break;
case 503: $text = 'Service Unavailable'; break;
case 504: $text = 'Gateway Time-out'; break;
case 505: $text = 'HTTP Version not supported'; break;
default:
exit('Unknown http status code "' . htmlentities($code) . '"');
break;
}

$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
header($protocol . ' ' . $code . ' ' . $text);
$GLOBALS['http_response_code'] = $code;
} else {
$code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);
}
return $code;
}
}
10 changes: 6 additions & 4 deletions api.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@

/**
* Get Geo-Information for a specific IP
* @param string $ip IP-Adress (IPv4 or IPv6). 'me' is the current IP of the server.
* @param array(string) $locales List of locale codes to use in name property
* from most preferred to least preferred. (Default: Site language, en)
* @param array Property names with options.
* @param string $ip IP-Adress (IPv4 or IPv6). 'me' is the current IP of the server.
* @param array(string) |string $locales List of locale codes to use in name property
* from most preferred to least preferred. (Default: Site language, en)
* It is also possible to pass these locales as string ("fr, en")
* @param array Property names with options.
* @param boolean $skipCache TRUE: Do not use cache for this request. (Default: FALSE)
* @param string $source Change the source for this request only. (Valid values: 'auto', 'manual', 'precision', 'header', 'hostinfo')
* @param float $timeout Total transaction timeout in seconds (Precision+HostIP.info API only)
* @param int $connectTimeout Initial connection timeout in seconds (Precision API only)
*
* @return YellowTree\GeoipDetect\DataSources\City GeoInformation. (Actually, this is a subclass of \GeoIp2\Model\City)
*
* @see https://github.com/maxmind/GeoIP2-php API Usage
Expand Down
9 changes: 6 additions & 3 deletions filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ function geoip_detect2_add_body_classes($classes) {
function geoip_detect2_convert_locale_format($locales) {
if (is_string($locales)) {
$locales = explode(',', $locales);
$locales = array_map('trim', $locales);

$locales = array_unique($locales);
} else if (!is_array($locales)) {
$locales = array();
}

$locales = array_map('trim', $locales);
$locales = array_unique($locales);

return $locales;
}
add_filter('geoip_detect2_locales', 'geoip_detect2_convert_locale_format', 7);
Expand Down
4 changes: 3 additions & 1 deletion geoip-detect.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Description: Retrieving Geo-Information using the Maxmind GeoIP (Lite) Database.
Author: Yellow Tree (Benjamin Pick)
Author URI: http://www.yellowtree.de
Version: 2.8.0-beta
Version: 2.8.0-dev
License: GPLv3 or later
License URI: http://www.gnu.org/licenses/gpl-3.0.html
Text Domain: geoip-detect
Expand Down Expand Up @@ -43,6 +43,7 @@
define('GEOIP_PLUGIN_FILE', __FILE__);
define('GEOIP_PLUGIN_DIR', dirname(GEOIP_PLUGIN_FILE));
define('GEOIP_PLUGIN_BASENAME', plugin_basename(GEOIP_PLUGIN_FILE));
define('GEOIP_DETECT_PLUGIN_URI', plugin_dir_url(GEOIP_PLUGIN_FILE));


// Do PHP & WP Version check
Expand All @@ -64,6 +65,7 @@
require_once(GEOIP_PLUGIN_DIR . '/deprecated.php');
require_once(GEOIP_PLUGIN_DIR . '/filter.php');
require_once(GEOIP_PLUGIN_DIR . '/shortcode.php');
require_once(GEOIP_PLUGIN_DIR . '/ajax.php');

require_once(GEOIP_PLUGIN_DIR . '/data-sources/registry.php');
require_once(GEOIP_PLUGIN_DIR . '/data-sources/abstract.php');
Expand Down
97 changes: 97 additions & 0 deletions js/geoip_detect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* Get a jQuery Promise that will delive the AJAX data.
* @param locales Locales to fill in the 'name' field (optional)
* @returns promise
*/

function geoip_detect_ajax_promise(locales) {
locales = locales || '';

var promise = jQuery.ajax(geoip_detect.ajaxurl, {
dataType: 'json',
type: 'GET',
data: {
action: 'geoip_detect2_get_info_from_current_ip',
locales: locales
}
});

return promise;
}

/**
* Get property value from data
*
* @param data
* @param property_name
* @param options
*/
function geoip_detect_get_property_value(data, property_name, options) {
var _get_name = function(names, locales) {
if (typeof(locales) === 'string') {
locales = locales.split(',');
}

for (var l in locales) {
//l = l.trim();
if (typeof(names[l]) != 'undefined' && names[l])
return names[l];
}
return '';
}

var $ = jQuery;
var default_options = {
'locales' : 'en',
'default' : '',
};
options = $.extend(options, default_options);

var properties = property_name.split('.');
var next_property = properties.shift();
if (next_property == 'name' || !next_property) {
if (typeof(data['names']) == 'object') {
return _get_name(data['names'], options.locales);
} else {
return '';
}
}
if (typeof(data[next_property]) == 'undefined')
return options['default'];
if (typeof(data[next_property]) == 'string')
return data[next_property];
return geoip_detect_get_property_value(data[next_property], properties.join('.'), options);
}

function geoip_detect_fill_data_attributes(el) {
var $ = jQuery;
el = $(el);
// Fill in the shortcodes into the HTML
var shortcodes = el.find('[data-geoip]');
if (!shortcodes.length)
return;

var promise = geoip_detect_ajax_promise('en');

promise.done(function(data) {
shortcodes.each(function() {
var options = $(this).data('geoip');
var value = geoip_detect_get_property_value(data, options.property, options);

if ($(this).data('geoip-method') == 'class')
$(this).addClass('geoip-' + value);
else
$(this).text(value);
$(this).trigger('geoip_detect.value.success');
});
}).fail(function(data) {
if (typeof(console) != 'undefined' && typeof(console.log) != 'undefined')
console.log('Error: ' + data.error);
shortcodes.trigger('geoip_detect.value.failure');
});
}


jQuery(document).ready(function($) {
geoip_detect_fill_data_attributes('html');
});
15 changes: 13 additions & 2 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,17 @@ as a shortcode, or via CSS body classes. The city & country names are translated
* Hosting-Provider dependent: [Cloudflare](https://support.cloudflare.com/hc/en-us/articles/200168236-What-does-CloudFlare-IP-Geolocation-do-) or [Amazon AWS CloudFront](https://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/) (Country)
* For the property names, see the results of a specific IP in the wordpress backend (under *Tools > GeoIP Detection*).
* You can include these properties into your posts and pages by using the shortcode `[geoip_detect2 property="country.name" default="(country could not be detected)" lang="en"]` (where 'country.name' can be one of the other property names as well, and 'default' and 'lang' are optional).
* When enabled on the options page, it adds CSS classes to the body tag such as `geoip-country-DE` and `geoip-continent-EU`.
* When enabled on the options page, the client IP respects a reverse proxy of the server.
* If you are using [Contact Form 7](https://wordpress.org/plugins/contact-form-7/), you can use these shortcodes:
* A select input with all countries, the detected country being selected by default `[geoip_detect2_countries mycountry]`
* Tracking information for the email text `[geoip_detect2_user_info]`

These features work if the corresponding options are enabled:
* Adds CSS classes to the body tag such as `geoip-country-DE` and `geoip-continent-EU`.
* Client IP respects a reverse proxy of the server.
* Cache support:
* Calling the PHP functions disables the caching of this page.
* Alternatively, you can use the JS API to inject the dynamic part while still caching the HTML.

See [API Documentation](https://github.com/yellowtree/wp-geoip-detect/wiki/API-Documentation) for more info.

= How can I use these functions? =
Expand Down Expand Up @@ -172,6 +177,11 @@ Fixing automatic weekly updates.

== Changelog ==

= ??? (ajax) =

* NEW: The function geoip_detect2_get_info_from_current_ip($locales) can now be called via JS, if enabled in the options.
This can be useful for cached pages. See [API Documentation](https://github.com/yellowtree/wp-geoip-detect/wiki/API-Documentation) for more infos.

= 2.8.0 =

* FIX: Localhost now always is a trusted proxy (for standard reverse proxy configurations, however the checkbox "uses a reverse proxy" still needs to be activated.)
Expand All @@ -195,6 +205,7 @@ Fixing automatic weekly updates.
* FIX: Timezones of US & Canada are now detected more often (if country+state is known)
* FIX: Shortcode didn't use current sitelang as default, but always english
* Maxmind vendor code was updated to the current version (2.4.2).
>>>>>>> master

= 2.5.7 =
* ADD: Shortcodes can now optionally specifiy the IP: `[geoip_detect2 property="country.isoCode" ip="(ipv4 or ipv6)"]`
Expand Down
Loading