Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
<?php
if ( Advanced_Ads_Geo_Version_Check::is_geo_installed() ) {
Advanced_Ads_Geo_Version_Check::show_deprecated_geo_notice();
if ( Advanced_Ads_Geo_Version_Check::is_geo_active() ) {
return;
}
}
new Advanced_Ads_Geo_Admin();

View File

@@ -0,0 +1,179 @@
window.advads_geo_admin = window.advads_geo_admin || {};
advads_geo_admin.set_mode = function(index, mode){
if (mode == "latlon") {
jQuery( '#advads_geo_classic_' + index ).hide();
jQuery( '#advads_geo_latlon_' + index ).show();
} else {
jQuery( '#advads_geo_classic_' + index ).show();
jQuery( '#advads_geo_latlon_' + index ).hide();
jQuery( '#advads_geo_latlon_by_city_' + index ).hide();
}
}
advads_geo_admin.click_locname = function(index){
jQuery( '#advads_geo_latlon_by_city_' + index ).show();
jQuery( '#advads_geo_latlon_' + index ).hide();
}
advads_geo_admin.search_loc_close = function(index){
jQuery( '#advads_geo_latlon_by_city_' + index ).hide();
jQuery( '#advads_geo_latlon_' + index ).show();
}
advads_geo_admin.search_loc = function(index){
var city = jQuery( '#advads_geo_input_search_city_' + index ).val();
jQuery.get( {
url: 'https://nominatim.openstreetmap.org/search',
data: {format: 'json', q: city, linkedplaces: 0, hierarchy: 0},
dataType: 'json'
} )
.done( function(data){
advads_geo_admin.receive_search_results( index, data );
} )
.fail( function(jqXHR, textStatus, errorThrown){
jQuery( '#advads_geo_latlon_loading_' + index ).hide();
var container = jQuery( '#advads_geo_latlon_results_' + index );
// container[0].innerHTML = '';
var text = advads_geo_translation.could_not_retrieve_city + ' ' + advads_geo_translation.manual_geo_search;
container.append( jQuery( '<div class="advads-notice-inline advads-error"/>' ).html( text ) );
} );
jQuery( '#advads_geo_latlon_loading_' + index ).show();
}
advads_geo_admin.receive_search_results = function(index, data){
jQuery( '#advads_geo_latlon_results_' + index ).show();
jQuery( '#advads_geo_latlon_loading_' + index ).hide();
var container = jQuery( '#advads_geo_latlon_results_' + index );
container[0].innerHTML = '';
if (data.length > 1) {
var text = advads_geo_translation.found_results.replace( '\%1$d', data.length );
container.append( jQuery( '<div>' + text + '</div>' ) );
} else if (data.length == 0) {
container.append( jQuery( '<div>' + advads_geo_translation.no_results + '</div>' ) );
}
for (var i in data) {
var itm = data[i];
var elm = jQuery( '<div style="margin-bottom:5pt;cursor:pointer;" class="inline notice"><strong>' + itm.display_name + '</strong><font class="description">(' + itm.lat + ' / ' + itm.lon + ')</font></div>' )
.mouseover( function(){
jQuery( this ).addClass( 'updated' );
} ).mouseout( function(){
jQuery( this ).removeClass( 'updated' );
} );
elm[0].location = itm;
elm.click( function(){
var itm = jQuery( this )[0].location;
jQuery( '#advads_geo_input_search_city_' + index ).val( itm.display_name );
jQuery( '#advads_geo_input_lat_' + index ).val( itm.lat );
jQuery( '#advads_geo_input_lon_' + index ).val( itm.lon );
container[0].innerHTML = '';
advads_geo_admin.search_loc_close( index );
} );
container.append( elm );
}
};
( () => {
new MutationObserver( function ( mutations ) {
mutations.forEach( mutation => {
if ( mutation.type === 'childList' && mutation.addedNodes.length ) {
for ( const resetButton of document.getElementsByClassName( 'advads-condition-visitor-profile-reset' ) ) {
resetButton.addEventListener( 'click', e => {
window.Advanced_Ads_Admin.set_cookie( 'advanced_ads_visitor', '', 0, window.advads_geo_translation.COOKIEPATH, window.advads_geo_translation.COOKIE_DOMAIN );
e.target.closest( '.advads-condition-visitor-profile' ).remove();
} );
}
}
} );
} ).observe( document, {childList: true, subtree: true} );
} )();
// show/hide settings according to status of MaxMind license key and Database
// phpcs:disable Generic.Formatting.MultipleStatementAlignment.NotSameWarning -- WP PHPCS can't handle ES5 arrow functions alignment
( () => {
const license = document.getElementById( 'advanced-ads-geo-maxmind-licence' );
if ( ! license ) {
return;
}
if ( Boolean( license.dataset.customdb ) ) {
license.closest( 'tr' ).style.display = 'none';
return;
}
const licenseMissingWarning = document.getElementById( 'advanced-ads-geo-license-missing-warning' );
const dataBaseUpdate = document.getElementById( 'advanced-ads-geo-update-database' );
const hasDatabase = dataBaseUpdate.dataset.dbExists || false;
const licenseChange = event => {
const hasLicense = event.target.value.trim() !== '';
let nextSibling = license.closest( 'tr' ).nextElementSibling;
while ( nextSibling ) {
nextSibling.style.display = hasLicense || hasDatabase ? 'table-row' : 'none';
nextSibling = nextSibling.nextElementSibling;
}
licenseMissingWarning.style.display = hasLicense ? 'none' : 'block';
dataBaseUpdate.style.display = hasLicense ? 'block' : 'none';
};
license.addEventListener( 'keyup', licenseChange );
license.addEventListener( 'change', licenseChange );
license.dispatchEvent( new Event( 'change' ) );
} )();
// phpcs:enable
// manually update the database.
jQuery( $ => {
const $downloadButton = $( '#download_geolite' );
const $loader = $( '#advads-geo-loader' );
const $uploadError = $( '#advads-geo-upload-error' );
const $uploadSuccess = $( '#advads-geo-upload-success' );
const $noDbWarning = $( '#advanced-ads-geo-no-database-warning' );
$downloadButton.on( 'click', () => {
$downloadButton
.blur()
.attr( 'disabled', 'disabled' );
$loader.show();
// phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact -- moving each chain link into a new line improves readability immensely.
$.post( ajaxurl, {
action: 'advads_download_geolite_database',
license_key: $( '#advanced-ads-geo-maxmind-licence' ).val(),
locale: $( '[name="advanced-ads-pro[geo][locale]"]' ).val(),
nonce: window.advads_geo_translation.nonce
} )
.done( function ( result ) {
if ( ! $.isPlainObject( result ) ) {
return;
}
$uploadError.hide();
$uploadSuccess.html( result.data ).show();
$noDbWarning.remove();
$downloadButton.remove();
} )
.fail( function ( jqXHR, errorMessage ) {
let responseText;
try {
responseText = jQuery.parseJSON( jqXHR.responseText );
} catch ( e ) {
responseText = null;
}
errorMessage = responseText && responseText.data ? responseText.data : errorMessage;
$uploadError.html( errorMessage ).show();
$uploadSuccess.hide();
$downloadButton.attr( 'disabled', false );
} )
.always( function () {
$loader.hide();
} );
// phpcs:enable
} );
} );

View File

@@ -0,0 +1,94 @@
<?php
/**
* Render the database update form.
*
* @package AdvancedAds\Pro\Modules\Geo
* @author Advanced Ads <info@wpadvancedads.com>
*
* @var bool $correct_databases
* @var string|false $last_update
* @var int $next_update
* @var bool $use_filters
*/
if ( $correct_databases ) : ?>
<p>
<?php esc_html_e( 'Geo Databases found.', 'advanced-ads-pro' ); ?>
</p>
<?php endif; ?>
<?php if ( $use_filters ) : ?>
<div class="advads-notice-inline advads-idea">
<p><?php esc_html_e( 'You are currently using filter hooks to load custom database files.', 'advanced-ads-pro' ); ?></p>
</div>
<?php
return;
endif;
?>
<p id="advanced-ads-geo-license-missing-warning" style="display: none;">
<span class="advads-notice-inline advads-error">
<?php esc_html_e( 'The MaxMind license key is missing.', 'advanced-ads-pro' ); ?>
</span>
<?php
printf(
/* translators: 1: opening <a>-tag to Advanced Ads manual, 2: closing <a>-tag */
esc_html__( 'Please read the %1$sinstallation instructions%2$s.', 'advanced-ads-pro' ),
'<a href="https://wpadvancedads.com/manual/geo-targeting-condition/#Enabling_Geo-Targeting" target="_blank">',
'</a>'
);
?>
</p>
<div id="advanced-ads-geo-update-database" <?php echo $correct_databases ? esc_attr( 'data-db-exists' ) : ''; ?>>
<?php if ( ! $correct_databases ) : ?>
<div id="advanced-ads-geo-no-database-warning">
<p class="advads-notice-inline advads-error">
<?php esc_html_e( 'Geo Databases not found.', 'advanced-ads-pro' ); ?>
</p>
<p>
<?php esc_html_e( 'In order to use Geo Targeting, please download the geo location databases by clicking on the button below.', 'advanced-ads-pro' ); ?>
</p>
</div>
<?php endif; ?>
<?php if ( ! $correct_databases || $this->is_update_available() ) : ?>
<button type="button" id="download_geolite" class="button-secondary">
<?php esc_html_e( 'Update geo location databases', 'advanced-ads-pro' ); ?> (~66MB)
</button>
<span class="advads-loader" id="advads-geo-loader" style="display: none;"></span>
<p class="advads-notice-inline advads-error hidden" id="advads-geo-upload-error"></p>
<p class="advads-notice-inline advads-check hidden" id="advads-geo-upload-success"></p>
<?php endif; ?>
</div>
<?php
if ( $correct_databases ) :
if ( $last_update ) :
?>
<p class="advads-notice-inline advads-check">
<?php
printf(
/* translators: Timestamp in the localized date_format */
esc_html__( 'Last update: %s', 'advanced-ads-pro' ),
esc_html( date_i18n( get_option( 'date_format' ), $last_update ) )
);
?>
</p>
<?php endif; ?>
<p>
<?php
printf(
/* translators: Timestamp in the localized date_format */
esc_html__( 'Next possible update on %s.', 'advanced-ads-pro' ),
esc_html( date_i18n( get_option( 'date_format' ), $next_update ) )
);
?>
</p>
<p class="description">
<?php esc_html_e( 'The databases are updated on the first Tuesday (midnight, GMT) of each month.', 'advanced-ads-pro' ); ?>
</p>
<?php
endif;

View File

@@ -0,0 +1,15 @@
<?php
/**
* @var string $locale
*/
?>
<select name="<?php echo Advanced_Ads_Pro::OPTION_KEY . '[' . Advanced_Ads_Geo_Plugin::OPTIONS_SLUG . '][locale]'; ?>">
<?php
foreach ( Advanced_Ads_Geo_Api::$locales as $_key => $_value ) {
?>
<option value="<?php echo $_key; ?>" <?php selected( $_key, $locale ); ?>><?php echo $_value; ?></option>
<?php
}
?>
</select>
<p class="description"><?php _e( 'Choose the language of the state/region or city entered. If the language is not available in the geo location database, it will check against the English version.', 'advanced-ads-pro' ); ?></p>

View File

@@ -0,0 +1,24 @@
<?php
/**
* View for the MaxMind license key setting.
*
* @package AdvancedAds\Pro\Modules\Geo
* @author Advanced Ads <info@wpadvancedads.com>
*
* @var string $license_key
* @var bool $use_filters
*/
printf(
'<input id="advanced-ads-geo-maxmind-licence" name="%s" type="text" data-customdb="%s" value="%s" />',
esc_attr( Advanced_Ads_Pro::OPTION_KEY . '[' . Advanced_Ads_Geo_Plugin::OPTIONS_SLUG . '][maxmind-license-key]' ),
$use_filters ? 'true' : '',
esc_attr( $license_key )
);
?>
<p class="description">
<a target="_blank" class="advads-external-link" rel="noopener" href="https://support.maxmind.com/hc/en-us/articles/4407111582235-Generate-a-License-Key">
<?php esc_attr_e( 'Manual', 'advanced-ads-pro' ); ?>
</a>
</p>

View File

@@ -0,0 +1,12 @@
<?php
/**
* @var array $methods
* @var string $method
*/
foreach ( $methods as $_key => $_method ) :
?>
<label>
<input type="radio" name="<?php echo Advanced_Ads_Pro::OPTION_KEY . '[' . Advanced_Ads_Geo_Plugin::OPTIONS_SLUG . '][method]'; ?>" value="<?php echo $_key; ?>" <?php checked( $_key, $method ); ?>/>
<?php echo $_method['description']; ?></label><br/>
<?php
endforeach;

View File

@@ -0,0 +1,22 @@
<?php
/**
* Show the visitor information saved to the `advanced_ads_visitor` cookie.
*
* @var Advanced_Ads_Geo_Visitor_Profile $visitor_profile
*/
?>
<p class="advads-condition-visitor-profile">
<strong><?php esc_html_e( 'Location based on your visitor profile cookie:', 'advanced-ads-pro' ); ?></strong>
<br>
<?php printf( '%s, %s, %s', esc_html( $visitor_profile->get_country() ), esc_html( $visitor_profile->region ), esc_html( $visitor_profile->city ) ); ?>
<br>
<?php esc_html_e( 'Coordinates', 'advanced-ads-pro' ); ?>: (<?php echo (float) $visitor_profile->lat; ?> / <?php echo (float) $visitor_profile->lon; ?>)
<br>
<button class="advads-condition-visitor-profile-reset" class="hide-if-no-js" type="button">
<?php esc_html_e( 'Reset Visitor Profile', 'advanced-ads-pro' ); ?>
</button>
</p>

View File

@@ -0,0 +1,66 @@
<?php
/**
* Class to check whether Geo is active and in an old version before the deprecation.
*/
class Advanced_Ads_Geo_Version_Check {
/**
* Whether a version of Advanced Ads Geo is active,
* that does not yet know it's been deprecated.
*
* @return bool
*/
public static function is_geo_active() {
return defined( 'AAGT_VERSION' );
}
/**
* If the loading order of the plugins is not default,
* AAGT_VERSION could be undefined, even though the Geo Targeting add-on is still installed.
* This is an approximation to that issue.
* If a user has renamed the plugin file, this will also fail.
*
* @return bool
*/
public static function is_geo_installed() {
return ! empty( array_filter(
apply_filters( 'active_plugins', get_option( 'active_plugins' ) ),
static function( $plugin ) {
$needle = 'advanced-ads-geo.php';
$len = strlen( $needle );
return substr_compare( $plugin, $needle, -$len, $len ) === 0;
}
) );
}
/**
* Render the admin notice.
*
* @return void
*/
public static function show_deprecated_geo_notice() {
add_action( 'advanced-ads-admin-notices', static function() {
?>
<div class="notice notice-error advads-admin-notice">
<p>
<?php
echo wp_kses(
sprintf(
/* translators: 1 is the opening link to the plugins page, 2 the closing link */
__(
'The geo-targeting visitor condition moved into Advanced Ads Pro. You can remove Geo Targeting %1$shere%2$s.',
'advanced-ads-pro'
),
'<a href="' . admin_url( 'plugins.php' ) . '">',
'</a>'
),
[ 'a' => [ 'href' => true ] ]
);
?>
</p>
</div>
<?php
} );
}
}

View File

@@ -0,0 +1,153 @@
<?php // phpcs:ignore WordPress.Files.FileName
use AdvancedAds\Framework\Utilities\Params;
/**
* Class Advanced_Ads_Geo_Visitor_Profile
*
* @property-read bool $has_visitor_profile
* @property-read string $city
* @property-read string $region
* @property-read string $country_code
* @property-read string $continent_code
* @property-read bool $is_eu_state
* @property-read float $lat
* @property-read float $lon
*/
class Advanced_Ads_Geo_Visitor_Profile {
const VISITOR_INFO_COOKIE_NAME = 'advanced_ads_visitor';
/**
* Whether there is a saved profile.
*
* @var bool
*/
private $has_visitor_profile = false;
/**
* The visitor's city.
*
* @var string
*/
private $city;
/**
* The visitor's region.
*
* @var string
*/
private $region;
/**
* The visitor's country code, ISO-3166-1 alpha-2.
*
* @var string
*/
private $country_code;
/**
* The visitor's continent code, cf. https://www.php.net/manual/en/function.geoip-continent-code-by-name.php.
*
* @var string
*/
private $continent_code;
/**
* Whether the visitor is in the EU.
*
* @var bool
*/
private $is_eu_state;
/**
* The visitor's geolocation latitude.
*
* @var float
*/
private $lat;
/**
* The visitor's geolocation longitude.
*
* @var float
*/
private $lon;
/**
* Check if the cookie is set and in the correct format.
* If not, return early.
*/
public function __construct() {
if ( ! Params::cookie( self::VISITOR_INFO_COOKIE_NAME ) ) {
return;
}
try {
$cookie_value = $this->parse_raw_cookie();
} catch ( RuntimeException $e ) {
return;
}
$this->has_visitor_profile = true;
$this->city = $cookie_value['visitor_city'];
$this->region = $cookie_value['visitor_region'];
$this->country_code = $cookie_value['country_code'];
$this->continent_code = $cookie_value['continent_code'];
$this->is_eu_state = $cookie_value['is_eu_state'];
$this->lat = $cookie_value['current_lat'];
$this->lon = $cookie_value['current_lon'];
}
/**
* Parse the cookie value and see if it contains the keys we expect.
*
* @return array
*
* @throws RuntimeException If cookie has unexpected values.
*/
private function parse_raw_cookie() {
$value = json_decode( wp_unslash( Params::cookie( self::VISITOR_INFO_COOKIE_NAME ) ), true );
if ( array_key_exists( 'conditions', $value ) && array_key_exists( 'geo_targeting', $value['conditions'] ) ) {
// Get the random key inside geo_targeting.
$value = reset( $value['conditions']['geo_targeting'] );
if ( is_array( $value ) && array_key_exists( 'data', $value ) ) {
return $value['data'];
}
}
throw new RuntimeException( 'Cookie does not have expected values' );
}
/**
* Get all values readonly.
*
* @param string $name Name of the property.
*
* @return mixed
*/
public function __get( $name ) {
return $this->{$name};
}
/**
* Check if the saved user location is different from the passed values.
*
* @param float $lat Latitude to check against.
* @param float $lon Longitude to check against.
*
* @return bool
*/
public function is_different_from_current_location( $lat, $lon ) {
return $this->lat !== $lat || $this->lon !== $lon;
}
/**
* Get the full name for ISO-3166-1 alpha-2 country code.
*
* @return string
*/
public function get_country() {
return Advanced_Ads_Geo_Api::get_countries()[ $this->country_code ];
}
}

View File

@@ -0,0 +1,847 @@
<?php // phpcs:ignore WordPress.Files.FileName
/**
* Dashboard helper class
*
* @package AdvancedAds\Pro
* @author Advanced Ads <info@wpadvancedads.com>
*/
use AdvancedAds\Utilities\Conditional;
use AdvancedAds\Framework\Utilities\Params;
use GeoIp2\Exception\AddressNotFoundException;
/**
* WP Admin class for Geo Targeting.
*/
class Advanced_Ads_Geo_Admin {
/**
* Path to view files
*
* @var string
*/
private $views_path;
/**
* Initialize the plugin by loading admin scripts & styles and adding a
* settings page and menu.
*
* @since 1.0.0
*/
public function __construct() {
$this->views_path = plugin_dir_path( __FILE__ ) . '../admin/views';
add_action( 'advanced-ads-settings-init', [ $this, 'settings_init' ] );
// ajax request to download the database.
add_action( 'wp_ajax_advads_download_geolite_database', [ $this, 'download_database' ] );
// Add assets.
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_scripts' ] );
}
/**
* Add settings to settings page
*/
public function settings_init() {
// add new section.
add_settings_section(
'advanced_ads_geo_setting_section',
__( 'Geo Targeting', 'advanced-ads-pro' ),
'__return_empty_string',
Advanced_Ads_Pro::OPTION_KEY . '-settings'
);
// Add license key field.
add_settings_field(
'geo-maxmind-license-key',
__( 'MaxMind license key', 'advanced-ads-pro' ),
[ $this, 'render_settings_license_key_callback' ],
Advanced_Ads_Pro::OPTION_KEY . '-settings',
'advanced_ads_geo_setting_section'
);
// Add database field.
add_settings_field(
'geo-database-update',
__( 'MaxMind Database', 'advanced-ads-pro' ),
[ $this, 'render_settings_database' ],
Advanced_Ads_Pro::OPTION_KEY . '-settings',
'advanced_ads_geo_setting_section'
);
// add field for the targeting method.
if ( count( Advanced_Ads_Geo_Plugin::get_instance()->get_targeting_methods() ) > 1 ) {
add_settings_field(
'geo-license',
__( 'Method', 'advanced-ads-pro' ),
[ $this, 'render_settings_method_callback' ],
Advanced_Ads_Pro::OPTION_KEY . '-settings',
'advanced_ads_geo_setting_section'
);
}
// add assistant setting field.
add_settings_field(
'geo-locale',
__( 'Language of names', 'advanced-ads-pro' ),
[ $this, 'render_settings_locale_option_callback' ],
Advanced_Ads_Pro::OPTION_KEY . '-settings',
'advanced_ads_geo_setting_section'
);
}
/**
* Render MaxMind license key field.
*/
public function render_settings_license_key_callback() {
$use_filters = $this->is_using_custom_database();
$license_key = Advanced_Ads_Geo_Plugin::get_instance()->options( 'maxmind-license-key', '' );
include $this->views_path . '/setting-maxmind-license-key.php';
}
/**
* Render MaxMind database field.
*
* @return void
*/
public function render_settings_database() {
$last_update = get_option( ADVADS_SLUG . '-' . Advanced_Ads_Geo_Plugin::OPTIONS_SLUG . '-last-update-geolite2', false );
$next_update = $this->get_next_first_tuesday_timestamp();
// Check if the database files exist and do not contain errors.
$api = Advanced_Ads_Geo_Api::get_instance();
$correct_databases = $api->get_geo_ip2_city_reader() && $api->get_geo_ip2_country_reader();
$use_filters = $this->is_using_custom_database();
// Render download of the geo database.
include $this->views_path . '/setting-download.php';
}
/**
* Render option for the geo targeting method
*/
public function render_settings_method_callback() {
$method = Advanced_Ads_Geo_Plugin::get_instance()->options( 'method', 'default' );
$methods = Advanced_Ads_Geo_Plugin::get_instance()->get_targeting_methods();
include $this->views_path . '/setting-method.php';
}
/**
* Render option for language of the geo information
*/
public function render_settings_locale_option_callback() {
$locale = Advanced_Ads_Geo_Plugin::get_instance()->options( 'locale', 'en' );
include $this->views_path . '/setting-locale.php';
}
/**
* Allow static method call as visitor condition callback.
*
* @param string $name method name.
* @param mixed $arguments functions arguments.
*/
public static function __callStatic( $name, $arguments ) {
if ( 'metabox_geo' === $name ) {
( new self() )->metabox_geo( ...$arguments );
}
// else fail silently.
}
/**
* Add visitor condition box
*
* @param array $options ad options.
* @param int $index current index in conditions list.
* @param string $form_name form name of current condition.
*
* @return void
* @throws \MaxMind\Db\Reader\InvalidDatabaseException Corrupted DB files.
*/
private function metabox_geo( $options, $index = 0, $form_name = '' ) {
if ( empty( $options['type'] ) ) {
return;
}
$type_options = Advanced_Ads_Visitor_Conditions::get_instance()->conditions;
if ( ! isset( $type_options[ $options['type'] ] ) ) {
return;
}
$method = Advanced_Ads_Geo_Plugin::get_current_targeting_method();
$countries = Advanced_Ads_Geo_Api::get_countries();
// set defaults for all variables.
$my_country = '';
$my_country_iso_code = '';
$my_city = '';
$my_region = '';
$my_lat = 0.0;
$my_lon = 0.0;
switch ( $method ) {
case 'sucuri':
$my_country_iso_code = Advanced_Ads_Geo_Plugin::get_sucuri_country();
$my_country = $countries[ $my_country_iso_code ] ?? ' ';
$current_location = sprintf( '%s (%s)', $my_country, $my_country_iso_code );
break;
default:
// get information from the current user to help him debugging issues.
$api = Advanced_Ads_Geo_Api::get_instance();
$ip = $api->get_real_ip_address();
$error = false;
// get locale.
$locale = Advanced_Ads_Geo_Plugin::get_instance()->options( 'locale', 'en' );
if ( $ip ) {
try {
$reader = $api->get_geo_ip2_city_reader();
if ( $reader ) {
// Look up the IP address.
$record = $reader->city( $ip );
if ( ! empty( $record ) ) {
$my_city = ( $record->city->name ) ? $record->city->name : __( '(unknown city)', 'advanced-ads-pro' );
if ( isset( $record->city->names[ $locale ] ) && $record->city->names[ $locale ] ) {
$my_city = $record->city->names[ $locale ];
}
$my_country = ( isset( $record->country->names[ $locale ] ) && $record->country->names[ $locale ] )
? $record->country->names[ $locale ]
: $record->country->names['en'];
$my_country_iso_code = $record->country->isoCode;
// get first subdivision (region/state).
$my_region = ( isset( $record->subdivisions[0] ) && $record->subdivisions[0]->name ) ? $record->subdivisions[0]->name : __( '(unknown region)', 'advanced-ads-pro' );
if ( isset( $record->subdivisions[0] ) && isset( $record->subdivisions[0]->names[ $locale ] ) && $record->subdivisions[0]->names[ $locale ] ) {
$my_region = $record->subdivisions[0]->names[ $locale ];
}
if ( isset( $record->location ) && isset( $record->location->latitude ) && isset( $record->location->longitude ) ) {
$my_lat = $record->location->latitude;
$my_lon = $record->location->longitude;
}
}
} else {
$error = sprintf(
'%1$s %2$s',
__( 'Geo Databases not found.', 'advanced-ads-pro' ),
sprintf(
/* translators: 1: opening <a>-tag to Advanced Ads manual, 2: closing <a>-tag */
__( 'Please read the %1$sinstallation instructions%2$s.', 'advanced-ads-pro' ),
'<a href="https://wpadvancedads.com/manual/geo-targeting-condition/#Enabling_Geo-Targeting" target="_blank">',
'</a>'
)
);
}
} catch ( AddressNotFoundException $e ) {
$error = $e->getMessage() . ' ' . __( 'Maybe you are working on a local or secured environment.', 'advanced-ads-pro' );
}
} else {
$raw_ip = $api->get_raw_ip_address();
$error = '<span class="advads-notice-inline advads-error">' . __( 'Your IP address format is incorrect', 'advanced-ads-pro' ) . ' (' . $raw_ip . ')</span>';
}
if ( $error ) {
$current_location = '<span class="advads-notice-inline advads-error">' . $error . '</span>';
} else {
$current_location = $ip . ', ' . $my_country . ', ' . $my_region . ', ' . $my_city;
$current_location .= '<br/>' . __( 'Coordinates', 'advanced-ads-pro' ) . ': (' . $my_lat . ' / ' . $my_lon . ')';
}
}
// form name basis.
if ( method_exists( 'Advanced_Ads_Visitor_Conditions', 'get_form_name_with_index' ) ) {
$name = Advanced_Ads_Visitor_Conditions::get_form_name_with_index( $form_name, $index );
} else {
$name = Advanced_Ads_Visitor_Conditions::FORM_NAME . '[' . $index . ']';
}
$operator = isset( $options['operator'] ) ? $options['operator'] : 'is';
$geo_mode = isset( $options['geo_mode'] ) ? $options['geo_mode'] : 'classic';
?>
<input type="hidden" name="<?php echo esc_attr( $name ); ?>[type]" value="<?php echo esc_attr( $options['type'] ); ?>"/>
<input type="hidden" name="<?php echo esc_attr( $name ); ?>[value]" value="1"/>
<style type="text/css">
span.geomode {
display: inline-block;
clear: both;
margin: 0px 0px 5px 0px;
}
span.geomode input[type=radio] {
display: block;
float: left;
margin: 0px 5px 0px 5px;
}
</style>
<div style="margin-bottom: 10pt;">
<span class="geomode">
<?php // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<input id="radio_classic_<?php echo esc_attr( $index ); ?>" type="radio" name="<?php echo esc_attr( $name ); ?>[geo_mode]" <?php checked( $geo_mode, 'classic' ); ?> value="classic" onclick="advads_geo_admin.set_mode(<?php echo $index; ?>, this.value);">
<?php // phpcs:enable ?>
<label for="radio_classic_<?php echo esc_attr( $index ); ?>"><?php esc_html_e( 'by specific location', 'advanced-ads-pro' ); ?></label>
</span>
<span class="geomode">
<?php // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<input class="geomode" id="radio_latlon_<?php echo esc_attr( $index ); ?>" type="radio" name="<?php echo esc_attr( $name ); ?>[geo_mode]" <?php checked( $geo_mode, 'latlon' ); ?> value="latlon" onclick="advads_geo_admin.set_mode(<?php echo $index; ?>, this.value);">
<?php // phpcs:enable ?>
<label for="radio_latlon_<?php echo esc_attr( $index ); ?>"><?php esc_html_e( 'by radius', 'advanced-ads-pro' ); ?></label>
</span>
</div>
<div class="geomode" id="advads_geo_classic_<?php echo esc_attr( $index ); ?>"
<?php
if ( 'classic' !== $geo_mode ) {
echo ' style="display:none;"';
}
?>
>
<select name="<?php echo esc_attr( $name ); ?>[operator]">
<option value="is" <?php selected( 'is', $operator ); ?>><?php esc_html_e( 'is', 'advanced-ads-pro' ); ?></option>
<option value="is_not" <?php selected( 'is_not', $operator ); ?>><?php esc_html_e( 'is not', 'advanced-ads-pro' ); ?></option>
</select>
<?php
switch ( $method ) :
case 'sucuri':
$country = isset( $options['country'] ) ? $options['country'] : $my_country_iso_code;
?>
<div class="advads-conditions-select-wrap"><select name="<?php echo esc_attr( $name ); ?>[country]"><?php foreach ( $countries as $_code => $_title ) : ?>
<option value="<?php echo esc_attr( $_code ); ?>" <?php selected( $_code, $country ); ?>><?php echo esc_html( $_title ); ?></option>
<?php
endforeach;
?>
</select></div>
<?php
break;
default:
$country = isset( $options['country'] ) ? $options['country'] : $my_country_iso_code;
$region = isset( $options['region'] ) ? $options['region'] : '';
$city = isset( $options['city'] ) ? $options['city'] : '';
?>
<div class="advads-conditions-select-wrap"><select name="<?php echo esc_attr( $name ); ?>[country]"><?php foreach ( $countries as $_code => $_title ) : ?>
<option value="<?php echo esc_attr( $_code ); ?>" <?php selected( $_code, $country ); ?>><?php echo esc_html( $_title ); ?></option>
<?php endforeach; ?>
</select></div> <?php esc_html_e( 'or', 'advanced-ads-pro' ); ?>
<input type="text" name="<?php echo esc_attr( $name ); ?>[region]" value="<?php echo esc_attr( $region ); ?>" placeholder="<?php esc_html_e( 'State/Region', 'advanced-ads-pro' ); ?>"/>
<?php esc_html_e( 'or', 'advanced-ads-pro' ); ?>
<input type="text" name="<?php echo esc_attr( $name ); ?>[city]" value="<?php echo esc_attr( $city ); ?>" placeholder="<?php esc_html_e( 'City', 'advanced-ads-pro' ); ?>"/>
<?php
break;
endswitch;
?>
</div>
<div id="advads_geo_latlon_<?php echo esc_attr( $index ); ?>"
<?php
if ( 'latlon' !== $geo_mode ) {
echo ' style="display:none;"';
}
?>
>
<?php
switch ( $method ) :
case 'sucuri':
esc_html_e( 'This option cant be used if your site is using sucuri.net.', 'advanced-ads-pro' );
break;
default:
$lat = isset( $options['lat'] ) ? $options['lat'] : '';
$lon = isset( $options['lon'] ) ? $options['lon'] : '';
$distance = isset( $options['distance'] ) ? $options['distance'] : '';
$distance_condition = isset( $options['distance_condition'] ) ? $options['distance_condition'] : '';
$distance_unit = isset( $options['distance_unit'] ) ? $options['distance_unit'] : '';
?>
<select name="<?php echo esc_attr( $name ); ?>[distance_condition]">
<option value="lte" <?php selected( $distance_condition, 'lte' ); ?>><?php esc_html_e( 'Distance is less than or equal to', 'advanced-ads-pro' ); ?></option>
<option value="gt" <?php selected( $distance_condition, 'gt' ); ?>><?php esc_html_e( 'Distance is greater than', 'advanced-ads-pro' ); ?></option>
</select>
<input type="number" name="<?php echo esc_attr( $name ); ?>[distance]" maxlength="8" style="width:80pt;" value="<?php echo esc_attr( $distance ); ?>" placeholder="<?php esc_attr_e( 'Distance', 'advanced-ads-pro' ); ?>"/>
<select name="<?php echo esc_attr( $name ); ?>[distance_unit]">
<option value="km" <?php selected( $distance_unit, 'km' ); ?>><?php esc_html_e( 'kilometers (km)', 'advanced-ads-pro' ); ?></option>
<option value="mi" <?php selected( $distance_unit, 'mi' ); ?>><?php esc_html_e( 'miles (mi)', 'advanced-ads-pro' ); ?></option>
</select><br/><?php esc_html_e( 'from', 'advanced-ads-pro' ); ?><br/>
<?php // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<button type="button" class="button" onclick="advads_geo_admin.click_locname(<?php echo $index; ?>)"><?php esc_html_e( 'get coordinates', 'advanced-ads-pro' ); ?></button>
<?php // phpcs:enable ?>
<input type="number" step="any" id="advads_geo_input_lat_<?php echo esc_attr( $index ); ?>" style="width:80pt; text-align:right;" name="<?php echo esc_attr( $name ); ?>[lat]" value="<?php echo esc_attr( $lat ); ?>" placeholder="<?php esc_attr_e( 'Latitude', 'advanced-ads-pro' ); ?>" title="<?php esc_attr_e( 'Latitude', 'advanced-ads-pro' ); ?>"/> /
<input type="number" step="any" id="advads_geo_input_lon_<?php echo esc_attr( $index ); ?>" style="width:80pt; text-align:right;" name="<?php echo esc_attr( $name ); ?>[lon]" value="<?php echo esc_attr( $lon ); ?>" placeholder="<?php esc_attr_e( 'Longitude', 'advanced-ads-pro' ); ?>" title="<?php esc_attr_e( 'Longitude', 'advanced-ads-pro' ); ?>"/>
<br>
<?php
if ( '' !== $lat && '' !== $lon && $my_lat && $my_lon ) {
$distance = Advanced_Ads_Geo::calculate_distance( $my_lat, $my_lon, $lat, $lon, $distance_unit );
$current_location .= '<br/>' . esc_html__( 'Distance to center', 'advanced-ads-pro' ) . ' ( ' . $lat . ' / ' . $lon . ' ): ' . round( $distance, 1 ) . ' ' . $distance_unit;
}
break;
endswitch;
?>
</div>
<?php
$latlon_city = isset( $options['latlon_city'] ) ? $options['latlon_city'] : '';
?>
<div id="advads_geo_latlon_by_city_<?php echo esc_attr( $index ); ?>" style="display: none; margin:3pt; padding:3pt;">
<input id="advads_geo_input_search_city_<?php echo esc_attr( $index ); ?>" type="text" name="<?php echo esc_attr( $name ); ?>[latlon_city]" value="<?php echo esc_attr( $latlon_city ); ?>" placeholder="<?php esc_attr_e( 'City', 'advanced-ads-pro' ); ?>">
<?php // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<button type="button" class="button button-primary" onclick="advads_geo_admin.search_loc(<?php echo $index; ?>)"><?php esc_html_e( 'Search', 'advanced-ads-pro' ); ?></button>
<button type="button" class="button" onclick="advads_geo_admin.search_loc_close(<?php echo $index; ?>)"><?php esc_html_e( 'Cancel', 'advanced-ads-pro' ); ?></button>
<?php // phpcs:enable ?>
<p class="description"><?php esc_html_e( 'Enter the name of the city, click the search button and pick one of the results to set the coordinates of the center.', 'advanced-ads-pro' ); ?></p>
<div id="advads_geo_latlon_loading_<?php echo esc_attr( $index ); ?>" class="spinner is-active" style="display:none; float: none;"></div>
<div id="advads_geo_latlon_results_<?php echo esc_attr( $index ); ?>"></div>
</div>
<p class="description">
<?php echo esc_html( $type_options[ $options['type'] ]['description'] ); ?>
<a href="https://wpadvancedads.com/manual/geo-targeting-condition/?utm_source=advanced-ads&utm_medium=link&utm_campaign=condition-geo-location" class="advads-manual-link" target="_blank">
<?php esc_html_e( 'Manual', 'advanced-ads-pro' ); ?>
</a>
</p>
<div class="description">
<p>
<strong><?php esc_html_e( 'Location based on your IP address', 'advanced-ads-pro' ); ?>:</strong>
<br>
<?php
echo wp_kses(
$current_location,
[
'br' => [],
'span' => [ 'class' => true ],
'a' => [
'href' => true,
'target' => true,
],
]
);
?>
</p>
<?php $this->render_visitor_profile_information( $my_lat, $my_lon ); ?>
</div>
<?php
}
/**
* Download database
*
* @since 1.0.0
*/
public function download_database() {
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
if ( ! Conditional::user_can( 'advanced_ads_manage_options' ) ) {
wp_send_json_error( __( 'You are not allowed to do this.', 'advanced-ads-pro' ), 400 );
}
$upload_full = Advanced_Ads_Geo_Plugin::get_instance()->get_upload_full();
if ( ! $upload_full ) {
wp_send_json_error( __( 'The upload dir is not available', 'advanced-ads-pro' ), 400 );
}
$license_key = sanitize_text_field( wp_unslash( Params::request( 'license_key', '' ) ) );
if ( empty( $license_key ) ) {
wp_send_json_error( __( 'Please provide a MaxMind license key', 'advanced-ads-pro' ), 400 );
}
$file_prefix = Advanced_Ads_Geo_Plugin::get_maxmind_file_prefix();
if ( '' === $file_prefix ) {
$file_prefix = $this->create_new_prefix();
$this->remove_obsolete_files();
}
// download source.
$download_urls = [
'city' => 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&suffix=tar.gz&license_key=' . $license_key,
'country' => 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&suffix=tar.gz&license_key=' . $license_key,
];
// Paths where we will save files.
$filepaths = [
'city' => $upload_full . $file_prefix . '-GeoLite2-City.mmdb',
'country' => $upload_full . $file_prefix . '-GeoLite2-Country.mmdb',
];
// Names in the `tar.gz` archives.
$filenames_in_archive = [
'city' => 'GeoLite2-City.mmdb',
'country' => 'GeoLite2-Country.mmdb',
];
// create upload directory if not exists yet.
if ( ! file_exists( $upload_full ) ) {
// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_mkdir
mkdir( $upload_full );
// phpcs:enable
}
// Prevent directory listing.
if ( ! file_exists( $upload_full . 'index.html' ) ) {
// phpcs:disable WordPress.WP.AlternativeFunctions,WordPress.PHP.NoSilencedErrors.Discouraged
$handle = @fopen( $upload_full . 'index.html', 'w' );
fwrite( $handle, '' );
fclose( $handle );
// phpcs:enable
}
if ( function_exists( 'wp_raise_memory_limit' ) ) {
wp_raise_memory_limit();
}
$this->maybe_replace_tmp_dir();
foreach ( $download_urls as $key => $download_url ) {
// variable with the name of the database file to download.
$db_file = $filepaths[ $key ];
$filename = $filenames_in_archive[ $key ];
$result = $this->download_geolite2_database( $download_url, $db_file, $filename );
if ( ! isset( $result['state'] ) || ! $result['state'] ) {
wp_send_json_error( $result['message'], 400 );
}
}
// save geo options on db update.
$pro_plugin = Advanced_Ads_Pro::get_instance();
$pro_options = $pro_plugin->get_options();
if ( ! array_key_exists( Advanced_Ads_Geo_Plugin::OPTIONS_SLUG, $pro_options ) ) {
$pro_options[ Advanced_Ads_Geo_Plugin::OPTIONS_SLUG ] = [];
}
$pro_options[ Advanced_Ads_Geo_Plugin::OPTIONS_SLUG ]['maxmind-license-key'] = $license_key;
$pro_options[ Advanced_Ads_Geo_Plugin::OPTIONS_SLUG ]['locale'] = sanitize_text_field( wp_unslash( Params::request( 'locale', '' ) ) );
$pro_plugin->update_options( $pro_options );
update_option( ADVADS_SLUG . '-' . Advanced_Ads_Geo_Plugin::OPTIONS_SLUG . '-last-update-geolite2', time() );
wp_send_json_success( __( 'Database updated successfully!', 'advanced-ads-pro' ) );
}
/**
* Download GeoLite2 databases
*
* @param string $download_url The download url.
* @param string $db_file The target file.
* @param string $filename The target filename in the archive.
*
* @return array
*/
private function download_geolite2_database( $download_url, $db_file, $filename ) {
// download the file from MaxMind, this places into temporary location.
$temp_file = download_url( $download_url );
$result['state'] = false;
$result['message'] = __( 'Database update failed', 'advanced-ads-pro' );
// If we failed, through a message, otherwise proceed.
if ( is_wp_error( $temp_file ) ) {
$error_code = $temp_file->get_error_data()['code'] ?? '';
$error_body = $temp_file->get_error_data()['body'] ?? '';
$result['message'] = sprintf(
/* translators: 1: The download URL, 2: The HTTP error code, 3: The HTTP header title, 4: The response body */
__( 'Error downloading database from: %1$s - %2$s %3$s - %4$s', 'advanced-ads-pro' ),
wp_parse_url( $download_url, PHP_URL_HOST ), // Do not expose the license key from query string.
$error_code,
$temp_file->get_error_message(),
$error_body
);
error_log( 'Advanced Ads Geo: ' . $result['message'] ); // phpcs:ignore
} else {
// The dir where the archive was downloaded.
$temp_file_dir = dirname( $temp_file );
try {
$archive = new PharData( $temp_file );
// The dir extracted from the archive.
$extracted_dir = trailingslashit( $archive->current()->getFilename() );
// Full path to the dir extracted from the archive.
$extracted_dir_full = trailingslashit( $temp_file_dir ) . $extracted_dir;
$archive->extractTo(
$temp_file_dir,
$extracted_dir . $filename,
true
);
} catch ( Exception $e ) {
$result['message'] = sprintf(
/* translators: an error mesage. */
esc_html__( 'Could not open downloaded database for reading: %s', 'advanced-ads-pro' ),
$temp_file . ', ' . $e->getMessage()
);
error_log( 'Advanced Ads Geo: ' . $result['message'] ); // phpcs:ignore
return $result;
} finally {
wp_delete_file( $temp_file );
}
add_filter( 'filesystem_method', [ $this, 'set_direct_filesystem_method' ] );
WP_Filesystem();
global $wp_filesystem;
if ( ! isset( $wp_filesystem->method ) || 'direct' !== $wp_filesystem->method ) {
$result['message'] = __( 'Could not access filesystem', 'advanced-ads-pro' );
error_log( 'Advanced Ads Geo: ' . $result['message'] ); // phpcs:ignore
return $result;
}
// Move the file.
$renamed = $wp_filesystem->move( $extracted_dir_full . $filename, $db_file, true );
$wp_filesystem->delete( $extracted_dir_full, false, 'd' );
if ( ! $renamed ) {
/* translators: MaxMind database file name. */
$result['message'] = sprintf( __( 'Could not open database for writing %s', 'advanced-ads-pro' ), $db_file );
// Remove corrupted file.
$wp_filesystem->delete( $db_file, false, 'f' );
} else {
$result['message'] = '';
$result['state'] = true;
}
remove_filter( 'filesystem_method', [ $this, 'set_direct_filesystem_method' ] );
}
return $result;
}
/**
* Get timestamp of the next first Tuesday of a month (either this month or the next)
*
* @param string $time timestamp from which to get the next available Tuesday.
*
* @return int of the next Tuesday (midnight GMT)
* @since 1.0.0
*/
public function get_next_first_tuesday_timestamp( $time = 0 ) {
// we actually use Wednesday since it returns midnight.
if ( ! $time ) {
$time = time();
}
// current month.
// phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date
$month = date( 'F', $time );
$year = date( 'Y', $time );
$next_tuesday_t = strtotime( "first Wednesday of $month $year" );
// if this is the past, get first Tuesday of next month.
if ( $next_tuesday_t < time() ) {
$next_month_t = strtotime( 'next month' );
$month = date( 'F', $next_month_t );
$year = date( 'Y', $next_month_t );
$next_tuesday_t = strtotime( "first Tuesday of $month $year" );
}
// phpcs:enable
return $next_tuesday_t;
}
/**
* Check if the databases are working
*/
public function check_database() {
$api = Advanced_Ads_Geo_Api::get_instance();
return $api->get_geo_lite_country_filename() && $api->get_geo_lite_city_filename();
}
/**
* Check if an updated version of the database might already be available
* we use the timestamp of the last update that actually happened and check,
* if the next first Tuesday of a month that followed is already in the past
*
* @return bool true, if update should be available
* @since 1.0.0
*/
public function is_update_available() {
// check if database is available.
if ( ! $this->check_database() ) {
return true;
}
// current time.
$now_t = time();
// get last update from the database.
$last_update_t = get_option( ADVADS_SLUG . '-' . Advanced_Ads_Geo_Plugin::OPTIONS_SLUG . '-last-update-geolite2', $now_t );
// return true, if last update is more than 31 days ago.
$month_in_seconds = 31 * DAY_IN_SECONDS;
if ( $month_in_seconds <= $now_t - $last_update_t ) {
return true;
}
// get next Tuesday following the update.
$next_tuesday_t = $this->get_next_first_tuesday_timestamp( $last_update_t );
if ( $next_tuesday_t < $now_t ) {
return true;
}
return false;
}
/**
* Check if license is valid
*
* @return bool true if license is valid
* @since 1.0.0
*/
public function license_valid() {
$status = Advanced_Ads_Admin_Licenses::get_instance()->get_license_status( 'advanced-ads-geo' );
if ( 'valid' === $status ) {
return true;
}
return false;
}
/**
* Register and enqueue admin-specific scripts.
*
* @return void
*/
public function enqueue_admin_scripts() {
if ( ! Conditional::is_screen_advanced_ads() ) {
return;
}
$handle = ADVADS_SLUG . '-' . Advanced_Ads_Geo_Plugin::OPTIONS_SLUG . '-admin-script';
wp_enqueue_script( $handle, plugin_dir_url( __FILE__ ) . '../admin/assets/admin.js', [], AAP_VERSION, true );
wp_localize_script(
$handle,
'advads_geo_translation',
[
/* translators: 1: The number of search results. */
'found_results' => __( 'Found %1$d results. Please pick the one, you want to use.', 'advanced-ads-pro' ),
'no_results' => __( 'Your search did not return any results.', 'advanced-ads-pro' ),
'could_not_retrieve_city' => __( 'There was an error connecting to the search service.', 'advanced-ads-pro' ),
/* translators: 1: A link to the geo location service. */
'manual_geo_search' => sprintf( __( 'You can search for the geo coordinates manually at %1$s.', 'advanced-ads-pro' ), '<a href="https://nominatim.openstreetmap.org/">nominatim.openstreetmap.org</a>' ),
'COOKIEPATH' => COOKIEPATH,
'COOKIE_DOMAIN' => COOKIE_DOMAIN,
'nonce' => wp_create_nonce( 'advanced-ads-admin-ajax-nonce' ),
]
);
}
/**
* As per MaxMind TOS, databases should not be puclicly accessible. Create a random prefix for that.
*/
private function create_new_prefix() {
$new_prefix = wp_generate_password( 32, false );
update_option( 'advanced-ads-geo-maxmind-file-prefix', $new_prefix );
return $new_prefix;
}
/**
* Remove files prefixed with an obsolete prefix.
*/
public function remove_obsolete_files() {
require_once ABSPATH . 'wp-admin/includes/file.php';
add_filter( 'filesystem_method', [ $this, 'set_direct_filesystem_method' ] );
WP_Filesystem();
global $wp_filesystem;
if ( ! isset( $wp_filesystem->method ) || 'direct' !== $wp_filesystem->method ) {
return;
}
$upload_full = Advanced_Ads_Geo_Plugin::get_instance()->get_upload_full();
if ( ! $upload_full ) {
return;
}
$files = $wp_filesystem->dirlist( $upload_full );
if ( ! $files ) {
return;
}
foreach ( $files as $file ) {
if ( preg_match( '/GeoLite2-.*?\.mmdb$/', $file['name'] )
|| 'tmp-' === substr( $file['name'], 0, 4 )
) {
$wp_filesystem->delete( $upload_full . $file['name'] );
}
}
remove_filter( 'filesystem_method', [ $this, 'set_direct_filesystem_method' ] );
}
/**
* Set direct filesystem method.
*/
public function set_direct_filesystem_method() {
return 'direct';
}
/**
* Create a new tmp dir inside the upload dir if the existing one does not contain enought space.
*/
private function maybe_replace_tmp_dir() {
if ( defined( 'WP_TEMP_DIR' ) ) {
return;
}
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
$available_tmp_space = @disk_free_space( get_temp_dir() );
// We need > 200 MB.
if ( ! $available_tmp_space || ( $available_tmp_space / MB_IN_BYTES ) < 200 ) {
$tmp_dir = Advanced_Ads_Geo_Plugin::get_instance()->get_upload_full()
. 'tmp-'
. Advanced_Ads_Geo_Plugin::get_maxmind_file_prefix();
if ( ! file_exists( $tmp_dir ) ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_mkdir,WordPress.PHP.NoSilencedErrors.Discouraged
@mkdir( $tmp_dir );
}
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
if ( @is_dir( $tmp_dir ) && wp_is_writable( $tmp_dir ) ) {
define( 'WP_TEMP_DIR', $tmp_dir );
}
}
}
/**
* Render a table with the current visitor profile cookie information if available.
*
* @param float $lat User's latitude.
* @param float $lon User's longitude.
*
* @return void
*/
private function render_visitor_profile_information( $lat, $lon ) {
$visitor_profile = new Advanced_Ads_Geo_Visitor_Profile();
if ( $visitor_profile->has_visitor_profile && $visitor_profile->is_different_from_current_location( $lat, $lon ) ) {
require $this->views_path . '/visitor-profile.php';
}
}
/**
* Check if custom database files are used via filters
*
* @return bool
*/
private function is_using_custom_database() {
$api = Advanced_Ads_Geo_Api::get_instance();
return has_filter( 'advanced-ads-geo-maxmind-geolite2-country-db-filepath' )
&& has_filter( 'advanced-ads-geo-maxmind-geolite2-city-db-filepath' )
&& $api->get_geo_ip2_city_reader()
&& $api->get_geo_ip2_country_reader();
}
}

View File

@@ -0,0 +1,648 @@
<?php
/**
* API for geo location based functions
*
* @package AdvancedAds\Pro\Modules\Geo
* @author Advanced Ads <info@wpadvancedads.com>
*/
use GeoIp2\Database\Reader;
use AdvancedAds\Framework\Utilities\Params;
use GeoIp2\Exception\AddressNotFoundException;
/**
* Class Advanced_Ads_Geo_Api
*/
class Advanced_Ads_Geo_Api {
/**
* Save if the city reader was used already
*
* @var bool
*/
public $used_city_reader = false;
/**
* Save ip of current visitor
*
* @var string
*/
protected $current_ip;
/**
* Current visitor continent
*
* @var string
*/
public $current_continent;
/**
* Current visitor country
*
* @var string
*/
public $current_country;
/**
* Current visitor state/region
*
* @var string
*/
public $current_region;
/**
* Current visitor city
*
* @var string
*/
public $current_city;
/**
* Current visitor latitude
*
* @var float
*/
public $current_lat;
/**
* Current visitor longitude
*
* @var float
*/
public $current_lon;
/**
* GST states
*
* @var array
*/
public static $gst_countries = [ 'AU', 'NZ', 'CA', 'CN' ];
/**
* Languages used in the MaxMind database
*
* @var array
*/
public static $locales = [
'en' => 'English',
'de' => 'Deutsch',
'fr' => 'Français',
'es' => 'Español',
'ja' => '日本語',
'pr-BR' => 'Português',
'ru' => 'Русский',
'zh-CN' => '华语',
];
/**
* EU states
*
* @var array
*/
public static $eu_states = [ 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GB', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE' ];
/**
* Get the instance of this class
*
* @return Advanced_Ads_Geo_Api
*/
public static function get_instance() {
static $instance;
if ( null === $instance ) {
$instance = new self();
}
return $instance;
}
/**
* Get country list
*
* @since 1.0.0
*
* @return array $countries list of the available countries
*/
public static function get_countries() {
$countries = [
'' => '',
'US' => __( 'United States', 'advanced-ads-pro' ),
'GB' => __( 'United Kingdom', 'advanced-ads-pro' ),
'EU' => __( 'European Union', 'advanced-ads-pro' ),
'DE' => __( 'Germany', 'advanced-ads-pro' ),
'-' => '---',
'CONT_NA' => __( 'North America', 'advanced-ads-pro' ),
'CONT_SA' => __( 'South America', 'advanced-ads-pro' ),
'CONT_EU' => __( 'Europe', 'advanced-ads-pro' ),
'CONT_AF' => __( 'Africa', 'advanced-ads-pro' ),
'CONT_AS' => __( 'Asia', 'advanced-ads-pro' ),
'CONT_OC' => __( 'Oceania', 'advanced-ads-pro' ),
'--' => '---',
'AF' => __( 'Afghanistan', 'advanced-ads-pro' ),
'AX' => __( '&#197;land Islands', 'advanced-ads-pro' ),
'AL' => __( 'Albania', 'advanced-ads-pro' ),
'DZ' => __( 'Algeria', 'advanced-ads-pro' ),
'AS' => __( 'American Samoa', 'advanced-ads-pro' ),
'AD' => __( 'Andorra', 'advanced-ads-pro' ),
'AO' => __( 'Angola', 'advanced-ads-pro' ),
'AI' => __( 'Anguilla', 'advanced-ads-pro' ),
'AQ' => __( 'Antarctica', 'advanced-ads-pro' ),
'AG' => __( 'Antigua and Barbuda', 'advanced-ads-pro' ),
'AR' => __( 'Argentina', 'advanced-ads-pro' ),
'AM' => __( 'Armenia', 'advanced-ads-pro' ),
'AW' => __( 'Aruba', 'advanced-ads-pro' ),
'AU' => __( 'Australia', 'advanced-ads-pro' ),
'AT' => __( 'Austria', 'advanced-ads-pro' ),
'AZ' => __( 'Azerbaijan', 'advanced-ads-pro' ),
'BS' => __( 'Bahamas', 'advanced-ads-pro' ),
'BH' => __( 'Bahrain', 'advanced-ads-pro' ),
'BD' => __( 'Bangladesh', 'advanced-ads-pro' ),
'BB' => __( 'Barbados', 'advanced-ads-pro' ),
'BY' => __( 'Belarus', 'advanced-ads-pro' ),
'BE' => __( 'Belgium', 'advanced-ads-pro' ),
'BZ' => __( 'Belize', 'advanced-ads-pro' ),
'BJ' => __( 'Benin', 'advanced-ads-pro' ),
'BM' => __( 'Bermuda', 'advanced-ads-pro' ),
'BT' => __( 'Bhutan', 'advanced-ads-pro' ),
'BO' => __( 'Bolivia', 'advanced-ads-pro' ),
'BQ' => __( 'Bonaire, Saint Eustatius and Saba', 'advanced-ads-pro' ),
'BA' => __( 'Bosnia and Herzegovina', 'advanced-ads-pro' ),
'BW' => __( 'Botswana', 'advanced-ads-pro' ),
'BV' => __( 'Bouvet Island', 'advanced-ads-pro' ),
'BR' => __( 'Brazil', 'advanced-ads-pro' ),
'IO' => __( 'British Indian Ocean Territory', 'advanced-ads-pro' ),
'BN' => __( 'Brunei Darrussalam', 'advanced-ads-pro' ),
'BG' => __( 'Bulgaria', 'advanced-ads-pro' ),
'BF' => __( 'Burkina Faso', 'advanced-ads-pro' ),
'BI' => __( 'Burundi', 'advanced-ads-pro' ),
'KH' => __( 'Cambodia', 'advanced-ads-pro' ),
'CM' => __( 'Cameroon', 'advanced-ads-pro' ),
'CA' => __( 'Canada', 'advanced-ads-pro' ),
'CV' => __( 'Cape Verde', 'advanced-ads-pro' ),
'KY' => __( 'Cayman Islands', 'advanced-ads-pro' ),
'CF' => __( 'Central African Republic', 'advanced-ads-pro' ),
'TD' => __( 'Chad', 'advanced-ads-pro' ),
'CL' => __( 'Chile', 'advanced-ads-pro' ),
'CN' => __( 'China', 'advanced-ads-pro' ),
'CX' => __( 'Christmas Island', 'advanced-ads-pro' ),
'CC' => __( 'Cocos Islands', 'advanced-ads-pro' ),
'CO' => __( 'Colombia', 'advanced-ads-pro' ),
'KM' => __( 'Comoros', 'advanced-ads-pro' ),
'CD' => __( 'Congo, Democratic People\'s Republic', 'advanced-ads-pro' ),
'CG' => __( 'Congo, Republic of', 'advanced-ads-pro' ),
'CK' => __( 'Cook Islands', 'advanced-ads-pro' ),
'CR' => __( 'Costa Rica', 'advanced-ads-pro' ),
'CI' => __( 'Cote d\'Ivoire', 'advanced-ads-pro' ),
'HR' => __( 'Croatia/Hrvatska', 'advanced-ads-pro' ),
'CU' => __( 'Cuba', 'advanced-ads-pro' ),
'CW' => __( 'Cura&Ccedil;ao', 'advanced-ads-pro' ),
'CY' => __( 'Cyprus', 'advanced-ads-pro' ),
'CZ' => __( 'Czech Republic', 'advanced-ads-pro' ),
'DK' => __( 'Denmark', 'advanced-ads-pro' ),
'DJ' => __( 'Djibouti', 'advanced-ads-pro' ),
'DM' => __( 'Dominica', 'advanced-ads-pro' ),
'DO' => __( 'Dominican Republic', 'advanced-ads-pro' ),
'TP' => __( 'East Timor', 'advanced-ads-pro' ),
'EC' => __( 'Ecuador', 'advanced-ads-pro' ),
'EG' => __( 'Egypt', 'advanced-ads-pro' ),
'GQ' => __( 'Equatorial Guinea', 'advanced-ads-pro' ),
'SV' => __( 'El Salvador', 'advanced-ads-pro' ),
'ER' => __( 'Eritrea', 'advanced-ads-pro' ),
'EE' => __( 'Estonia', 'advanced-ads-pro' ),
'ET' => __( 'Ethiopia', 'advanced-ads-pro' ),
'FK' => __( 'Falkland Islands', 'advanced-ads-pro' ),
'FO' => __( 'Faroe Islands', 'advanced-ads-pro' ),
'FJ' => __( 'Fiji', 'advanced-ads-pro' ),
'FI' => __( 'Finland', 'advanced-ads-pro' ),
'FR' => __( 'France', 'advanced-ads-pro' ),
'GF' => __( 'French Guiana', 'advanced-ads-pro' ),
'PF' => __( 'French Polynesia', 'advanced-ads-pro' ),
'TF' => __( 'French Southern Territories', 'advanced-ads-pro' ),
'GA' => __( 'Gabon', 'advanced-ads-pro' ),
'GM' => __( 'Gambia', 'advanced-ads-pro' ),
'GE' => __( 'Georgia', 'advanced-ads-pro' ),
'GR' => __( 'Greece', 'advanced-ads-pro' ),
'GH' => __( 'Ghana', 'advanced-ads-pro' ),
'GI' => __( 'Gibraltar', 'advanced-ads-pro' ),
'GL' => __( 'Greenland', 'advanced-ads-pro' ),
'GD' => __( 'Grenada', 'advanced-ads-pro' ),
'GP' => __( 'Guadeloupe', 'advanced-ads-pro' ),
'GU' => __( 'Guam', 'advanced-ads-pro' ),
'GT' => __( 'Guatemala', 'advanced-ads-pro' ),
'GG' => __( 'Guernsey', 'advanced-ads-pro' ),
'GN' => __( 'Guinea', 'advanced-ads-pro' ),
'GW' => __( 'Guinea-Bissau', 'advanced-ads-pro' ),
'GY' => __( 'Guyana', 'advanced-ads-pro' ),
'HT' => __( 'Haiti', 'advanced-ads-pro' ),
'HM' => __( 'Heard and McDonald Islands', 'advanced-ads-pro' ),
'VA' => __( 'Holy See (City Vatican State)', 'advanced-ads-pro' ),
'HN' => __( 'Honduras', 'advanced-ads-pro' ),
'HK' => __( 'Hong Kong', 'advanced-ads-pro' ),
'HU' => __( 'Hungary', 'advanced-ads-pro' ),
'IS' => __( 'Iceland', 'advanced-ads-pro' ),
'IN' => __( 'India', 'advanced-ads-pro' ),
'ID' => __( 'Indonesia', 'advanced-ads-pro' ),
'IR' => __( 'Iran', 'advanced-ads-pro' ),
'IQ' => __( 'Iraq', 'advanced-ads-pro' ),
'IE' => __( 'Ireland', 'advanced-ads-pro' ),
'IM' => __( 'Isle of Man', 'advanced-ads-pro' ),
'IL' => __( 'Israel', 'advanced-ads-pro' ),
'IT' => __( 'Italy', 'advanced-ads-pro' ),
'JM' => __( 'Jamaica', 'advanced-ads-pro' ),
'JP' => __( 'Japan', 'advanced-ads-pro' ),
'JE' => __( 'Jersey', 'advanced-ads-pro' ),
'JO' => __( 'Jordan', 'advanced-ads-pro' ),
'KZ' => __( 'Kazakhstan', 'advanced-ads-pro' ),
'KE' => __( 'Kenya', 'advanced-ads-pro' ),
'KI' => __( 'Kiribati', 'advanced-ads-pro' ),
'KW' => __( 'Kuwait', 'advanced-ads-pro' ),
'KG' => __( 'Kyrgyzstan', 'advanced-ads-pro' ),
'LA' => __( 'Lao People\'s Democratic Republic', 'advanced-ads-pro' ),
'LV' => __( 'Latvia', 'advanced-ads-pro' ),
'LB' => __( 'Lebanon', 'advanced-ads-pro' ),
'LS' => __( 'Lesotho', 'advanced-ads-pro' ),
'LR' => __( 'Liberia', 'advanced-ads-pro' ),
'LY' => __( 'Libyan Arab Jamahiriya', 'advanced-ads-pro' ),
'LI' => __( 'Liechtenstein', 'advanced-ads-pro' ),
'LT' => __( 'Lithuania', 'advanced-ads-pro' ),
'LU' => __( 'Luxembourg', 'advanced-ads-pro' ),
'MO' => __( 'Macau', 'advanced-ads-pro' ),
'MK' => __( 'Macedonia', 'advanced-ads-pro' ),
'MG' => __( 'Madagascar', 'advanced-ads-pro' ),
'MW' => __( 'Malawi', 'advanced-ads-pro' ),
'MY' => __( 'Malaysia', 'advanced-ads-pro' ),
'MV' => __( 'Maldives', 'advanced-ads-pro' ),
'ML' => __( 'Mali', 'advanced-ads-pro' ),
'MT' => __( 'Malta', 'advanced-ads-pro' ),
'MH' => __( 'Marshall Islands', 'advanced-ads-pro' ),
'MQ' => __( 'Martinique', 'advanced-ads-pro' ),
'MR' => __( 'Mauritania', 'advanced-ads-pro' ),
'MU' => __( 'Mauritius', 'advanced-ads-pro' ),
'YT' => __( 'Mayotte', 'advanced-ads-pro' ),
'MX' => __( 'Mexico', 'advanced-ads-pro' ),
'FM' => __( 'Micronesia', 'advanced-ads-pro' ),
'MD' => __( 'Moldova, Republic of', 'advanced-ads-pro' ),
'MC' => __( 'Monaco', 'advanced-ads-pro' ),
'MN' => __( 'Mongolia', 'advanced-ads-pro' ),
'ME' => __( 'Montenegro', 'advanced-ads-pro' ),
'MS' => __( 'Montserrat', 'advanced-ads-pro' ),
'MA' => __( 'Morocco', 'advanced-ads-pro' ),
'MZ' => __( 'Mozambique', 'advanced-ads-pro' ),
'MM' => __( 'Myanmar', 'advanced-ads-pro' ),
'NA' => __( 'Namibia', 'advanced-ads-pro' ),
'NR' => __( 'Nauru', 'advanced-ads-pro' ),
'NP' => __( 'Nepal', 'advanced-ads-pro' ),
'NL' => __( 'Netherlands', 'advanced-ads-pro' ),
'AN' => __( 'Netherlands Antilles', 'advanced-ads-pro' ),
'NC' => __( 'New Caledonia', 'advanced-ads-pro' ),
'NZ' => __( 'New Zealand', 'advanced-ads-pro' ),
'NI' => __( 'Nicaragua', 'advanced-ads-pro' ),
'NE' => __( 'Niger', 'advanced-ads-pro' ),
'NG' => __( 'Nigeria', 'advanced-ads-pro' ),
'NU' => __( 'Niue', 'advanced-ads-pro' ),
'NF' => __( 'Norfolk Island', 'advanced-ads-pro' ),
'KR' => __( 'North Korea', 'advanced-ads-pro' ),
'MP' => __( 'Northern Mariana Islands', 'advanced-ads-pro' ),
'NO' => __( 'Norway', 'advanced-ads-pro' ),
'OM' => __( 'Oman', 'advanced-ads-pro' ),
'PK' => __( 'Pakistan', 'advanced-ads-pro' ),
'PW' => __( 'Palau', 'advanced-ads-pro' ),
'PS' => __( 'Palestinian Territories', 'advanced-ads-pro' ),
'PA' => __( 'Panama', 'advanced-ads-pro' ),
'PG' => __( 'Papua New Guinea', 'advanced-ads-pro' ),
'PY' => __( 'Paraguay', 'advanced-ads-pro' ),
'PE' => __( 'Peru', 'advanced-ads-pro' ),
'PH' => __( 'Phillipines', 'advanced-ads-pro' ),
'PN' => __( 'Pitcairn Island', 'advanced-ads-pro' ),
'PL' => __( 'Poland', 'advanced-ads-pro' ),
'PT' => __( 'Portugal', 'advanced-ads-pro' ),
'PR' => __( 'Puerto Rico', 'advanced-ads-pro' ),
'QA' => __( 'Qatar', 'advanced-ads-pro' ),
'XK' => __( 'Republic of Kosovo', 'advanced-ads-pro' ),
'RE' => __( 'Reunion Island', 'advanced-ads-pro' ),
'RO' => __( 'Romania', 'advanced-ads-pro' ),
'RU' => __( 'Russian Federation', 'advanced-ads-pro' ),
'RW' => __( 'Rwanda', 'advanced-ads-pro' ),
'BL' => __( 'Saint Barth&eacute;lemy', 'advanced-ads-pro' ),
'SH' => __( 'Saint Helena', 'advanced-ads-pro' ),
'KN' => __( 'Saint Kitts and Nevis', 'advanced-ads-pro' ),
'LC' => __( 'Saint Lucia', 'advanced-ads-pro' ),
'MF' => __( 'Saint Martin (French)', 'advanced-ads-pro' ),
'SX' => __( 'Saint Martin (Dutch)', 'advanced-ads-pro' ),
'PM' => __( 'Saint Pierre and Miquelon', 'advanced-ads-pro' ),
'VC' => __( 'Saint Vincent and the Grenadines', 'advanced-ads-pro' ),
'SM' => __( 'San Marino', 'advanced-ads-pro' ),
'ST' => __( 'S&atilde;o Tom&eacute; and Pr&iacute;ncipe', 'advanced-ads-pro' ),
'SA' => __( 'Saudi Arabia', 'advanced-ads-pro' ),
'SN' => __( 'Senegal', 'advanced-ads-pro' ),
'RS' => __( 'Serbia', 'advanced-ads-pro' ),
'SC' => __( 'Seychelles', 'advanced-ads-pro' ),
'SL' => __( 'Sierra Leone', 'advanced-ads-pro' ),
'SG' => __( 'Singapore', 'advanced-ads-pro' ),
'SK' => __( 'Slovak Republic', 'advanced-ads-pro' ),
'SI' => __( 'Slovenia', 'advanced-ads-pro' ),
'SB' => __( 'Solomon Islands', 'advanced-ads-pro' ),
'SO' => __( 'Somalia', 'advanced-ads-pro' ),
'ZA' => __( 'South Africa', 'advanced-ads-pro' ),
'GS' => __( 'South Georgia', 'advanced-ads-pro' ),
'KP' => __( 'South Korea', 'advanced-ads-pro' ),
'SS' => __( 'South Sudan', 'advanced-ads-pro' ),
'ES' => __( 'Spain', 'advanced-ads-pro' ),
'LK' => __( 'Sri Lanka', 'advanced-ads-pro' ),
'SD' => __( 'Sudan', 'advanced-ads-pro' ),
'SR' => __( 'Suriname', 'advanced-ads-pro' ),
'SJ' => __( 'Svalbard and Jan Mayen Islands', 'advanced-ads-pro' ),
'SZ' => __( 'Swaziland', 'advanced-ads-pro' ),
'SE' => __( 'Sweden', 'advanced-ads-pro' ),
'CH' => __( 'Switzerland', 'advanced-ads-pro' ),
'SY' => __( 'Syrian Arab Republic', 'advanced-ads-pro' ),
'TW' => __( 'Taiwan', 'advanced-ads-pro' ),
'TJ' => __( 'Tajikistan', 'advanced-ads-pro' ),
'TZ' => __( 'Tanzania', 'advanced-ads-pro' ),
'TH' => __( 'Thailand', 'advanced-ads-pro' ),
'TL' => __( 'Timor-Leste', 'advanced-ads-pro' ),
'TG' => __( 'Togo', 'advanced-ads-pro' ),
'TK' => __( 'Tokelau', 'advanced-ads-pro' ),
'TO' => __( 'Tonga', 'advanced-ads-pro' ),
'TT' => __( 'Trinidad and Tobago', 'advanced-ads-pro' ),
'TN' => __( 'Tunisia', 'advanced-ads-pro' ),
'TR' => __( 'Turkey', 'advanced-ads-pro' ),
'TM' => __( 'Turkmenistan', 'advanced-ads-pro' ),
'TC' => __( 'Turks and Caicos Islands', 'advanced-ads-pro' ),
'TV' => __( 'Tuvalu', 'advanced-ads-pro' ),
'UG' => __( 'Uganda', 'advanced-ads-pro' ),
'UA' => __( 'Ukraine', 'advanced-ads-pro' ),
'AE' => __( 'United Arab Emirates', 'advanced-ads-pro' ),
'UY' => __( 'Uruguay', 'advanced-ads-pro' ),
'UM' => __( 'US Minor Outlying Islands', 'advanced-ads-pro' ),
'UZ' => __( 'Uzbekistan', 'advanced-ads-pro' ),
'VU' => __( 'Vanuatu', 'advanced-ads-pro' ),
'VE' => __( 'Venezuela', 'advanced-ads-pro' ),
'VN' => __( 'Vietnam', 'advanced-ads-pro' ),
'VG' => __( 'Virgin Islands (British)', 'advanced-ads-pro' ),
'VI' => __( 'Virgin Islands (USA)', 'advanced-ads-pro' ),
'WF' => __( 'Wallis and Futuna Islands', 'advanced-ads-pro' ),
'EH' => __( 'Western Sahara', 'advanced-ads-pro' ),
'WS' => __( 'Western Samoa', 'advanced-ads-pro' ),
'YE' => __( 'Yemen', 'advanced-ads-pro' ),
'ZM' => __( 'Zambia', 'advanced-ads-pro' ),
'ZW' => __( 'Zimbabwe', 'advanced-ads-pro' ),
];
// Remove continents, if Sucuri method is used.
if ( 'sucuri' === Advanced_Ads_Geo_Plugin::get_current_targeting_method() ) {
unset( $countries['CONT_NA'], $countries['CONT_SA'], $countries['CONT_EU'], $countries['CONT_AF'], $countries['CONT_AS'], $countries['CONT_AU'] );
}
return apply_filters( 'advanced-ads-geo-countries', $countries );
}
/**
* Return absolute path to the country file
*
* @return false|string
*/
public function get_geo_lite_country_filename() {
$custom_file = '';
/**
* Allow experienced users to choose an existing MaxMind country database file
*
* @param string $custom_file absolute path to the country file.
*/
$custom_file = apply_filters( 'advanced-ads-geo-maxmind-geolite2-country-db-filepath', $custom_file );
if ( is_string( $custom_file ) && '' !== $custom_file && file_exists( $custom_file ) ) {
return $custom_file;
}
$upload_full = Advanced_Ads_Geo_Plugin::get_instance()->get_upload_full();
if ( ! $upload_full ) {
return false;
}
// Check if prefixed file exists.
$prefix = Advanced_Ads_Geo_Plugin::get_maxmind_file_prefix();
$filename = $upload_full . $prefix . '-GeoLite2-Country.mmdb';
if ( file_exists( $filename ) ) {
return $filename;
}
// Check if unprefixed file exists.
$filename = $upload_full . 'GeoLite2-Country.mmdb';
if ( file_exists( $filename ) ) {
return $filename;
}
return false;
}
/**
* Return absolute path to the city file
*
* @return false|string
*/
public function get_geo_lite_city_filename() {
$custom_file = '';
/**
* Allow experienced users to choose an existing MaxMind city database file
*
* @param string $custom_file absolute path to the city file.
*/
$custom_file = apply_filters( 'advanced-ads-geo-maxmind-geolite2-city-db-filepath', $custom_file );
if ( is_string( $custom_file ) && '' !== $custom_file && file_exists( $custom_file ) ) {
return $custom_file;
}
$upload_full = Advanced_Ads_Geo_Plugin::get_instance()->get_upload_full();
if ( ! $upload_full ) {
return false;
}
// Check if prefixed file exists.
$prefix = Advanced_Ads_Geo_Plugin::get_maxmind_file_prefix();
$filename = $upload_full . $prefix . '-GeoLite2-City.mmdb';
if ( file_exists( $filename ) ) {
return $filename;
}
// Check if unprefixed file exists.
$filename = $upload_full . 'GeoLite2-City.mmdb';
if ( file_exists( $filename ) ) {
return $filename;
}
return false;
}
/**
* Get the country code for a given IP address using the MaxMind GeoIP2 database.
*
* @param string $ip_address The IP address to look up.
* @return string|false The ISO country code if found, or false on failure.
*
* @throws \InvalidArgumentException If the IP address is invalid.
* @throws AddressNotFoundException If the IP address is not found in the database.
* @throws Exception For any other errors.
*/
public function get_geo_ip2_country_code( $ip_address ) {
// Now get the location information from the MaxMind database.
try {
$reader = $this->get_geo_ip2_country_reader();
// todo: return default country.
// Look up the IP address.
$record = $reader->country( $ip_address );
// Get the location.
$location = $record->country->isoCode;
// MaxMind returns a blank for location if it can't find it, but we want to use get shop country to replace it.
// todo: return default country.
return $location;
} catch ( \InvalidArgumentException $e ) {
error_log( 'InvalidArgumentException: ' . $e->getMessage() );
return false;
} catch ( AddressNotFoundException $e ) {
error_log( 'AddressNotFoundException: ' . $e->getMessage() );
return false;
} catch ( Exception $e ) {
return false;
}
}
/**
* Retrieves the GeoIP2 City Reader instance.
*
* This function attempts to create a new Reader instance for the MaxMind GeoLite2 City database.
* It first retrieves the filename of the GeoLite2 City database using the `get_geo_lite_city_filename` method.
* If the filename is valid, it creates and returns a new Reader instance pointing to the database.
* If an exception occurs or the filename is invalid, it returns false.
*
* @return Reader|false The Reader instance if successful, or false on failure.
*/
public function get_geo_ip2_city_reader() {
// Now get the location information from the MaxMind database.
try {
$filename = $this->get_geo_lite_city_filename();
if ( false === $filename ) {
return false;
}
// Create a new Reader and point it to the database.
return new Reader( $filename );
} catch ( Exception $e ) {
return false;
}
}
/**
* Retrieves the GeoIP2 country reader.
*
* This function attempts to get the location information from the MaxMind database.
* It first retrieves the filename of the GeoLite country database. If the filename
* is not found, it returns false. Otherwise, it creates a new Reader instance
* pointing to the database file.
*
* @return Reader|false Returns a Reader instance if successful, or false on failure.
*/
public function get_geo_ip2_country_reader() {
// get the location information from the MaxMind database.
try {
$filename = $this->get_geo_lite_country_filename();
if ( false === $filename ) {
return false;
}
// Create a new Reader and point it to the database.
return new Reader( $filename );
} catch ( Exception $e ) {
return false;
}
}
/**
* Try to find a valid IP address.
*
* If ADVANCED_ADS_GEO_TEST_IP is defined use this.
* Otherwise @see self::get_raw_ip_address().
*
* If there are multiple IP addresses found, split the string and remove potential ports from IPv4 addresses.
* Validate them using the built-in filter_var() function.
* Since each proxy probably appended their IP at the end, use the first IP address in the array.
* Allow the user to filter the IP address and assign it to a class-member, so it will be short-circuited on successive calls.
*
* @return string
*/
public function get_real_ip_address() {
if ( isset( $this->current_ip ) ) {
return $this->current_ip;
}
$ip = defined( 'ADVANCED_ADS_GEO_TEST_IP' ) ? ADVANCED_ADS_GEO_TEST_IP : $this->get_raw_ip_address();
$ip_array = array_map(
function ( $ip ) {
$ip = trim( $ip );
if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
return $ip;
}
return preg_replace( '/([^:]+):\d+/', "$1", $ip );
},
explode( ',', $ip )
);
$ip_array = array_filter(
$ip_array,
function ( $ip ) {
return filter_var( $ip, FILTER_VALIDATE_IP );
}
);
$ip = reset( $ip_array );
/**
* Filter the found IP address.
*
* @param string $ip The last found IP address.
*/
$this->current_ip = (string) apply_filters( 'get-ip-address', $ip );
return $this->current_ip;
}
/**
* Get IP address from various sources
*
* @return string
*/
public function get_raw_ip_address() {
$keys = [
'HTTP_CF_CONNECTING_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_CLIENT_IP',
];
foreach ( $keys as $key ) {
$ip = Params::server( $key );
if ( ! empty( $ip ) ) {
return $ip;
}
}
return Params::server( 'REMOTE_ADDR' );
}
/**
* Check if the given country code belongs to an EU state
*
* @param string $country Two letter country code.
*
* @return bool true if is EU member state
*/
public function is_eu_state( $country = '' ) {
return in_array( $country, self::$eu_states, true );
}
}

View File

@@ -0,0 +1,188 @@
<?php // phpcs:ignore WordPress.Files.FileName
use AdvancedAds\Framework\Utilities\Params;
/**
* Load common and WordPress based resources
*/
class Advanced_Ads_Geo_Plugin {
/**
* Slug for the options
*/
const OPTIONS_SLUG = 'geo';
/**
* Singleton instance of the plugin
*
* @var Advanced_Ads_Geo_Plugin
*/
protected static $instance;
/**
* Plugin options
*
* @var array
*/
protected $options;
/**
* Subdirectory in wp-content/uploads in which the db files are saved
*
* @var string
*/
public $upload_dir = '/advanced-ads-geo';
/**
* Constructor
*/
private function __construct() {
add_filter( 'advanced-ads-visitor-conditions', [ $this, 'visitor_conditions' ] );
}
/**
* Get the singleton instance of the plugin
*
* @return Advanced_Ads_Geo_Plugin
*/
public static function get_instance() {
// If the single instance hasn't been set, set it now.
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Get all options array for Geo or specific option.
*
* @param string $name Only get a specific option.
* @param mixed $default_val If name is set, allow to pass a default value.
*
* @return mixed
*/
public function options( $name = '', $default_val = null ) {
if ( ! isset( $this->options ) ) {
$this->populate_options();
}
if ( ! empty( $name ) ) {
return isset( $this->options[ $name ] ) ? $this->options[ $name ] : $default_val;
}
return $this->options;
}
/**
* Populate the options array
*/
private function populate_options() {
$standalone_prefix = ADVADS_SLUG . '-' . self::OPTIONS_SLUG;
$main_plugin_options = Advanced_Ads::get_instance()->options();
$geo_options = [];
if ( array_key_exists( $standalone_prefix, $main_plugin_options ) ) {
$geo_options = $main_plugin_options[ $standalone_prefix ];
}
$pro_options = Advanced_Ads_Pro::get_instance()->get_options();
if ( array_key_exists( self::OPTIONS_SLUG, $pro_options ) ) {
$geo_options = array_merge( $geo_options, $pro_options[ self::OPTIONS_SLUG ] );
}
$this->options = $geo_options;
}
/**
* Add visitor condition
*
* @param array $conditions Visitor conditions of the main plugin.
*
* @return array
*/
public function visitor_conditions( $conditions ) {
$conditions['geo_targeting'] = [
'label' => __( 'geo location', 'advanced-ads-pro' ),
'description' => __( 'Display ads based on geo location.', 'advanced-ads-pro' ),
'metabox' => [ 'Advanced_Ads_Geo_Admin', 'metabox_geo' ], // callback to generate the visitor condition.
'check' => [ 'Advanced_Ads_Geo', 'check_geo' ], // callback for frontend check.
'passive_info' => [
'hash_fields' => null,
'function' => [ 'Advanced_Ads_Geo', 'get_passive' ],
],
];
return $conditions;
}
/**
* Get available targeting methods
*/
public static function get_targeting_methods() {
$methods = [
'default' => [
'description' => __( 'MaxMind database (default)', 'advanced-ads-pro' ),
],
];
if ( Params::server( 'HTTP_X_SUCURI_COUNTRY' ) ) {
$methods['sucuri'] = [
'description' => __( 'Sucuri Header (country only)', 'advanced-ads-pro' ),
];
}
return $methods;
}
/**
* Get current targeting method
*
* @return string
*/
public static function get_current_targeting_method() {
$methods = self::get_targeting_methods();
$method = self::get_instance()->options( 'method' );
if ( empty( $method ) || ! isset( $methods[ $options[ self::OPTIONS_SLUG ]['method'] ] ) ) {
return 'default';
}
return $method;
}
/**
* Get Sucuri country code
*/
public static function get_sucuri_country() {
return Params::server( 'HTTP_X_SUCURI_COUNTRY', '' );
}
/**
* Get the upload subdirectory
*/
public static function get_upload_dir() {
return apply_filters( 'advanced-ads-geo-upload-dir', self::get_instance()->upload_dir );
}
/**
* Get the full path to the upload subdirectory.
*/
public static function get_upload_full() {
// Get the WordPress upload directory information, which is where we have stored the MaxMind database.
$upload_dir = wp_upload_dir();
if ( ! isset( $upload_dir['basedir'] ) ) {
return false;
}
return $upload_dir['basedir'] . trailingslashit( self::get_upload_dir() );
}
/**
* Get the prefix of the maxmind databases.
*/
public static function get_maxmind_file_prefix() {
$prefix = get_option( 'advanced-ads-geo-maxmind-file-prefix', '' );
// Allow only digits and letters to prevent going up using `../`.
return preg_replace( '/[^a-z0-9]/i', '', $prefix );
}
}

View File

@@ -0,0 +1,399 @@
<?php // phpcs:ignore WordPress.Files.FileName
/**
* Front end helper
*
* @package AdvancedAds\Pro
* @author Advanced Ads <info@wpadvancedads.com>
*/
/**
* Frontend helper class
*/
class Advanced_Ads_Geo {
/**
* Look at the options and check whether they contain valid values for a lat/lon distance check
*
* @param array $options geo options.
*
* @return bool
*/
public static function check_for_valid_lat_lon_options( $options = [] ) {
return isset( $options['lat'] ) && isset( $options['lon'] ) && isset( $options['distance_condition'] ) && isset( $options['distance'] ) && isset( $options['distance_unit'] )
&& is_numeric( $options['lat'] ) && is_numeric( $options['lon'] ) && is_numeric( $options['distance'] ) && '' !== $options['distance_condition'] && '' !== $options['distance_unit'];
}
/**
* Computes the distance between the coordinates and returns the result
*
* @param float $lat1 latitude for position 1.
* @param float $lon1 longitude for position 1.
* @param float $lat2 latitude for position 2.
* @param float $lon2 longitude for position 2.
* @param float $unit unit to use.
*
* @return float
*/
public static function calculate_distance( $lat1, $lon1, $lat2, $lon2, $unit = 'km' ) {
$lat1 = deg2rad( $lat1 );
$lon1 = deg2rad( $lon1 );
$lat2 = deg2rad( $lat2 );
$lon2 = deg2rad( $lon2 );
$d_lon = $lon2 - $lon1;
$a = pow( cos( $lat2 ) * sin( $d_lon ), 2 ) + pow( cos( $lat1 ) * sin( $lat2 ) - sin( $lat1 ) * cos( $lat2 ) * cos( $d_lon ), 2 );
$b = sin( $lat1 ) * sin( $lat2 ) + cos( $lat1 ) * cos( $lat2 ) * cos( $d_lon );
$rad = atan2( sqrt( $a ), $b );
if ( 'mi' === $unit ) {
return $rad * 3958.755865744; // 6371.0 / 1.609344;.
}
return $rad * 6371.0;
}
/**
* Check geo visitor condition
*
* @param array $options visitor condition options.
*
* @return bool true if ad can be displayed.
* @since 1.0.0
*/
public static function check_geo( $options = [] ) {
$method = Advanced_Ads_Geo_Plugin::get_current_targeting_method();
if ( ( ! isset( $options['country'] ) && ! isset( $options['region'] ) && ! isset( $options['city'] ) )
|| ( '' === $options['country'] && '' === $options['region'] && '' === $options['city'] ) ) {
// maybe we got a valid lat/lon condition.
// TODO: this check should also take place when the user creates the condition and raise warnings etc.
$has_valid_latlon_options = self::check_for_valid_lat_lon_options( $options );
if ( ! $has_valid_latlon_options || 'sucuri' === $method ) {
// TODO: right now the lat/lon check is not supported for sucuri.
return true;
}
}
// switch by method.
switch ( $method ) :
case 'sucuri':
return self::check_geo_sucuri( $options );
default:
return self::check_geo_default( $options );
endswitch;
}
/**
* Check geo visitor condition for Sucuri header method
*
* @param array $options geo options.
*
* @return bool
* @since 1.2
*/
public static function check_geo_sucuri( $options = [] ) {
$operator = $options['operator'] ?? 'is';
$country = isset( $options['country'] ) ? trim( $options['country'] ) : '';
$api = Advanced_Ads_Geo_Api::get_instance();
$country_code = Advanced_Ads_Geo_Plugin::get_sucuri_country();
if ( 'is_not' === $operator ) {
// check EU.
if ( 'EU' === $country ) {
return ! $api->is_eu_state( $country_code );
}
// check country.
return $country !== $country_code;
} else {
// check EU.
if ( 'EU' === $country ) {
return $api->is_eu_state( $country_code );
}
// check country.
return $country === $country_code;
}
}
/**
*
* Check geo visitor condition
*
* @param array $options geo ad options.
*
* @return bool
* @since 1.2
*/
public static function check_geo_default( $options = [] ) {
$geo_mode = $options['geo_mode'] ?? 'classic';
$has_valid_latlon_options = self::check_for_valid_lat_lon_options( $options );
$operator = $options['operator'] ?? 'is';
$country = isset( $options['country'] ) ? trim( $options['country'] ) : '';
$region = isset( $options['region'] ) ? trim( $options['region'] ) : '';
$city = isset( $options['city'] ) ? trim( $options['city'] ) : '';
$lat = $options['lat'] ?? null;
$lon = $options['lon'] ?? null;
$distance = $options['distance'] ?? null;
$distance_condition = $options['distance_condition'] ?? null;
$distance_unit = $options['distance_unit'] ?? 'km';
$api = Advanced_Ads_Geo_Api::get_instance();
$ip = $api->get_real_ip_address();
$country_code = '';
$visitor_city = '';
$visitor_region = '';
// get locale.
$locale = Advanced_Ads_Geo_Plugin::get_instance()->options( 'locale', 'en' );
// reuse already existing location information to save db requests on the same page impression.
if ( ! $ip ) {
if ( 'is_not' === $operator ) {
return true;
} else {
return false;
}
} elseif ( $api->used_city_reader && $city && $api->current_city ) {
$continent_code = $api->current_continent;
$country_code = $api->current_country;
$visitor_city = $api->current_city;
} elseif ( $api->used_city_reader && $region && $api->current_region ) {
$continent_code = $api->current_continent;
$country_code = $api->current_country;
$visitor_region = $api->current_region;
} elseif ( ! $city && ! $region && $api->current_country ) {
$continent_code = $api->current_continent;
$country_code = $api->current_country;
} else {
try {
// get correct reader.
if ( $city || $region || $has_valid_latlon_options ) {
$reader = $api->get_geo_ip2_city_reader();
$api->used_city_reader = true;
} else {
$reader = $api->get_geo_ip2_country_reader();
}
if ( $reader ) {
// Look up the IP address.
if ( $city || $region || $has_valid_latlon_options ) {
try {
$record = $reader->city( $ip );
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch,Squiz.Commenting.EmptyCatchComment.Missing
} catch ( Exception $e ) {
}
} else {
try {
$record = $reader->country( $ip );
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch,Squiz.Commenting.EmptyCatchComment.Missing
} catch ( Exception $e ) {
}
}
if ( ! empty( $record ) ) {
$country_code = $record->country->isoCode;
$api->current_country = $country_code;
$continent_code = $record->continent->code;
$api->current_continent = $continent_code;
if ( $city ) {
$visitor_city = isset( $record->city->name ) ? $record->city->name : __( '(unknown city)', 'advanced-ads-pro' );
$api->current_city = $visitor_city;
if ( isset( $record->city->names[ $locale ] ) && $record->city->names[ $locale ] ) {
$visitor_city = $record->city->names[ $locale ];
$api->current_city = $visitor_city;
}
}
if ( $region ) {
$visitor_region = $record->subdivisions[0]->name ?? __( '(unknown region)', 'advanced-ads-pro' );
$api->current_region = $visitor_region;
if ( isset( $record->subdivisions[0]->names[ $locale ] ) && $record->subdivisions[0]->names[ $locale ] ) {
$visitor_region = $record->subdivisions[0]->names[ $locale ];
$api->current_region = $visitor_region;
}
}
if ( isset( $record->location->longitude ) && isset( $record->location->latitude ) ) {
$api->current_lat = $record->location->latitude;
$api->current_lon = $record->location->longitude;
}
}
} else {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
error_log( 'Advanced Ads Geo: ' . __( 'Geo Databases not found', 'advanced-ads-pro' ) );
}
} catch ( Exception $e ) {
if ( defined( 'ADVANCED_ADS_GEO_CHECK_DEBUG' ) ) {
/* translators: an error message. */
$log_content = sprintf( __( 'Address not found: %s', 'advanced-ads-pro' ), $e->getMessage() ) . "\n";
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
error_log( $log_content, 3, WP_CONTENT_DIR . '/geo-check.log' );
}
return false;
}
}
// convert to lower case.
if ( function_exists( 'mb_strtolower' ) ) {
$city = mb_strtolower( $city, 'utf-8' );
$region = mb_strtolower( $region, 'utf-8' );
$visitor_city = mb_strtolower( $visitor_city, 'UTF-8' );
$visitor_region = mb_strtolower( $visitor_region, 'UTF-8' );
}
if ( defined( 'ADVANCED_ADS_GEO_CHECK_DEBUG' ) ) {
$log_content = "GEO CHECK (setting|visitor): COUNTRY {$country}|{$country_code} REGION {$region}|{$visitor_region} CITY {$city}|{$visitor_city}\n";
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
error_log( $log_content, 3, WP_CONTENT_DIR . '/geo-check.log' );
}
// set up data for continent search.
if ( 0 === strpos( $country, 'CONT_' ) ) {
$country_code = 'CONT_' . $continent_code;
}
if ( 'latlon' === $geo_mode ) {
if ( $has_valid_latlon_options ) {
$dst = self::calculate_distance( $api->current_lat, $api->current_lon, $lat, $lon, $distance_unit );
if ( 'gt' === $distance_condition ) {
return $dst > $distance;
}
return $dst <= $distance;
}
return true;
} elseif ( 'is_not' === $operator ) {
if ( $city ) {
// check city.
return $city !== $visitor_city;
} elseif ( $region ) {
// check region.
return $region !== $visitor_region;
}
// check EU.
if ( 'EU' === $country ) {
return ! $api->is_eu_state( $country_code );
}
// check country.
return $country !== $country_code;
} else {
// check city.
if ( $city ) {
return $city === $visitor_city;
} elseif ( $region ) {
return $region === $visitor_region;
}
// check EU.
if ( 'EU' === $country ) {
return $api->is_eu_state( $country_code );
}
// check country.
return $country === $country_code;
}
}
/**
* Get geo information to use in passive cache-busting.
*/
public static function get_passive() {
$method = Advanced_Ads_Geo_Plugin::get_current_targeting_method();
// switch by method.
switch ( $method ) :
case 'sucuri':
return self::get_passive_sucuri();
default:
return self::get_passive_default();
endswitch;
}
/**
* Get geo information to use in passive cache-busting.
* Sucuri header method
*
* @since 1.2
*/
public static function get_passive_sucuri() {
$api = Advanced_Ads_Geo_Api::get_instance();
$country_code = Advanced_Ads_Geo_Plugin::get_sucuri_country();
return [
'country_code' => $country_code,
'is_eu_state' => $api->is_eu_state( $country_code ),
'is_sucuri' => true,
];
}
/**
* Get geo information to use in passive cache-busting.
* Default method.
*
* @param array $options geo ad options.
*
* @return array
*/
public static function get_passive_default( $options = [] ) {
global $locale;
$api = Advanced_Ads_Geo_Api::get_instance();
$ip = $api->get_real_ip_address();
// get locale.
$options = Advanced_Ads_Geo_Plugin::get_instance()->options( 'locale', 'en' );
$r = [];
if ( ! $ip ) {
return $r;
}
// reuse already existing location information to save db requests on the same page impression.
if ( ! $api->used_city_reader || ! $api->current_city || ! $api->current_region || ! $api->current_country ) {
try {
$reader = $api->get_geo_ip2_city_reader();
$api->used_city_reader = true;
if ( $reader ) {
try {
$record = $reader->city( $ip );
} catch ( Exception $e ) {
return $r;
}
if ( ! empty( $record ) ) {
$api->current_country = $record->country->isoCode;
$api->current_continent = $record->continent->code;
$api->current_city = isset( $record->city->name ) ? $record->city->name : __( '(unknown city)', 'advanced-ads-pro' );
if ( isset( $record->city->names[ $locale ] ) && $record->city->names[ $locale ] ) {
$api->current_city = $record->city->names[ $locale ];
}
$api->current_region = $record->subdivisions[0]->name ?? __( '(unknown region)', 'advanced-ads-pro' );
if ( isset( $record->subdivisions[0]->names[ $locale ] ) && $record->subdivisions[0]->names[ $locale ] ) {
$api->current_region = $record->subdivisions[0]->names[ $locale ];
}
if ( isset( $record->location->longitude ) && isset( $record->location->latitude ) ) {
$api->current_lat = $record->location->latitude;
$api->current_lon = $record->location->longitude;
}
}
} else {
return $r;
}
} catch ( Exception $e ) {
return $r;
}
}
$r['visitor_city'] = $api->current_city;
$r['visitor_region'] = $api->current_region;
$r['country_code'] = $api->current_country;
$r['continent_code'] = $api->current_continent;
$r['is_eu_state'] = $api->is_eu_state( $api->current_country );
$r['current_lat'] = $api->current_lat;
$r['current_lon'] = $api->current_lon;
return $r;
}
}

View File

@@ -0,0 +1,8 @@
<?php
if ( Advanced_Ads_Geo_Version_Check::is_geo_active() ) {
return;
}
new Advanced_Ads_Geo();
Advanced_Ads_Geo_Plugin::get_instance();