Skip to content

Commit d426a84

Browse files
committed
Merge pull request #21 from ryanshoover/master
enhance(safety): Cleaning up the GeoIP gut check to be more stable
2 parents c081fe8 + 6102848 commit d426a84

File tree

3 files changed

+146
-43
lines changed

3 files changed

+146
-43
lines changed

inc/country-list.php

100644100755
File mode changed.

readme.txt

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,70 @@ This will display “Content just for everyone in Texas and California” strict
103103
You can mix and match geography and negative geography options to create verbose logic in a single shortcode:
104104
`[geoip-content country="US" not-city="Austin"]Content for US visitors but not for visitors in Austin[/geoip-content]`
105105

106+
= Limitations =
106107

107-
== Testing Parameters ==
108+
There is a single limitation in the logic that lets you filter content for multiple geographic areas.
109+
110+
You can progressively limit the area that content is shown in. But once your content is hidden from an area, a subset of that area can't be added back in.
111+
112+
For example,
113+
If I limit my image to Europe, then hide my image from Great Britain, I can't go back and show it to London.
114+
115+
== Creative Work Arounds and Hacks ==
116+
117+
=== Limit content to some regions of a country (or some cities of a state) ===
118+
119+
You want to show an offer for free shipping to every state in the US *but* Alaska and Hawaii. You may be inclined to write something like
120+
121+
**BAD**
122+
123+
```
124+
[geoip_content country="US" not_state="AK, HI"]Lorem ipsum dolor sit amet[/geoip_content]
125+
```
126+
127+
Instead, show it to all other 48 states
128+
129+
**GOOD**
130+
131+
```
132+
[geoip_content state="AL, AZ, AR, CA, CO, CT, DE, FL, GA, ID, IL, IN, IA, KS, KY, LA, ME, MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY"]Free shipping on all orders over $50![/geoip_content]
133+
```
134+
135+
=== Duplicate location names ===
136+
137+
You want to show discount airfare on a flight to Paris, France. The content should show to all of the US and France, but not Paris itself.
138+
139+
**BAD**
140+
141+
```
142+
[geoip_content country="US, FR" not_city="Paris"]Fly to Paris for only $199![/geoip_content]
143+
```
144+
145+
The problem here is that Paris, Texas will be hidden. The solution? Just have two geoip_content shortcodes.
146+
147+
**GOOD**
148+
149+
```
150+
[geoip_content country="FR" not_city="Paris"]Fly to Paris for only $199![/geoip_content][geoip_content country="US"]Fly to Paris for only $199![/geoip_content]
151+
```
152+
=== Adding an area into an ommited region ===
153+
154+
You want to show an ad written in Spanish to all of South America except for Brazil. Brasilia, however, has enough Spanish speakers that you want to include Brasilia.
155+
156+
**BAD**
157+
158+
```
159+
[geoip_content continent="SA" not_country="BR" city="Brasilia"]Lorem ipsum dolor sit amet[/geoip_content]
160+
```
161+
162+
**GOOD**
163+
164+
```
165+
[geoip_content continent="SA" not_country="BR"]Venta de la Navidad en los adaptadores USB[/geoip_content]
166+
[geoip_content city="Brasilia"]Venta de la Navidad en los adaptadores USB[/geoip_content]
167+
```
168+
169+
== Testing Parameters ==
108170
You can use the following URL parameters to test how your localized content will appear to visitors from various geographic locations. You can add any of the parameters below to any URL of a page using the GeoIP shortcodes or API calls:
109171

110172
Spoof visitor from the state of Texas:
@@ -153,8 +215,11 @@ Please contact the WP Engine [Support Team](https://my.wpengine.com/support#gene
153215

154216
== Changelog ==
155217

218+
= 1.1.2 =
219+
- Fixes logic for nested parameter selectors in content shortcode
220+
156221
= 1.1.1 =
157-
- Fixes logic for negated parameters in content shortcake
222+
- Fixes logic for negated parameters in content shortcode
158223
- Allows the plugin to run on development sites
159224

160225
= 1.1.0 =
@@ -199,4 +264,4 @@ Please contact the WP Engine [Support Team](https://my.wpengine.com/support#gene
199264
== Upgrade Notice ==
200265

201266
= 1.1.1 =
202-
This version adds the following features: fixed a small issue with the content shortcode filters, allows the plugin to run on development sites. This update is recommended for all GeoIP users.
267+
This version adds the following features: fixed a small issue with the content shortcode filters, allows the plugin to run on development sites. This update is recommended for all GeoIP users.

wpengine-geoip.php

Lines changed: 78 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/*
33
Plugin Name: WP Engine GeoIP
4-
Version: 1.1.1
4+
Version: 1.1.2
55
Description: Create a personalized user experienced based on location.
66
Author: WP Engine
77
Author URI: http://wpengine.com
@@ -96,7 +96,7 @@ public function setup() {
9696

9797
// Get our array of countries and continents
9898
require_once( $this->geoip_path . '/inc/country-list.php' );
99-
99+
100100
$this->countries = apply_filters( 'geoip_country_list', geoip_country_list() );
101101

102102
$this->geos = $this->get_actuals();
@@ -126,6 +126,8 @@ public function get_actuals() {
126126
'postalcode' => getenv( 'HTTP_GEOIP_POSTAL_CODE' ),
127127
);
128128

129+
$geos['active'] = ( isset( $geos['countrycode'] ) && false !== $geos['countrycode'] ) ? true : false;
130+
129131
$geos['continent'] = $this->continent( $geos['countrycode'] );
130132

131133
return $geos;
@@ -412,16 +414,19 @@ function do_shortcode_location( $atts ) {
412414
*/
413415
function do_shortcode_content( $atts, $content = null ) {
414416

415-
$keep = FALSE;
417+
$keep = true;
418+
419+
$test_parameters = array();
416420

417-
foreach( $atts as $geos_label => $value ) {
421+
// Process and organzie the test parameters
422+
foreach( $atts as $label => $value ) {
418423

419424
// Intialize our negation parameters
420425
$negate = 0;
421426
$inline_negate = 0;
422427

423428
// Check to see if the attribute has "not" in it
424-
$negate = preg_match( '/not?[-_]?(.*)/', $geos_label, $matches );
429+
$negate = preg_match( '/not?[-_]?(.*)/', $label, $matches );
425430

426431
// WordPress doesn't like a dash in shortcode parameter labels
427432
// Just in case, check to see if the value has "not-" in it
@@ -430,43 +435,55 @@ function do_shortcode_content( $atts, $content = null ) {
430435
}
431436

432437
// Label after the negation match
433-
$geos_label = $negate ? $matches[1] : $geos_label;
438+
$label = $negate ? $matches[1] : $label;
434439

435-
// Value after the negation match
440+
// Value after the negation match
436441
$value = $inline_negate ? $matches[2] : $value;
437442

438443
// Replace common synonyms with our values
439-
$geos_label = $this->match_label_synonyms( $geos_label );
444+
$label = $this->match_label_synonyms( $label );
440445

441-
// Abort if the geos_label doesn't match
442-
if( !isset( $this->geos[ $geos_label ] ) ) {
446+
// Abort if the label doesn't match
447+
if( !isset( $this->geos[ $label ] ) ) {
443448
continue;
444449
}
445450

446-
// sanitize the match value
447-
$match_value = strtolower( $this->geos[ $geos_label ] );
448-
449-
// find out if the value is comma delimited
451+
// Find out if the value is comma delimited
450452
$test_values = (array) explode( ',', $value );
451453

452-
// If we're checking for a negative, we need to start with TRUE
453-
if( $negate ) {
454-
$keep = TRUE;
455-
}
454+
// Add the value to the test parameters
455+
$test_parameters[ $label ] = array(
456+
'test_values' => $test_values,
457+
'negate' => $negate,
458+
);
459+
}
456460

457-
// Let's run through the test values and see if we get a match
458-
foreach( $test_values as $test_value ) {
461+
// Sort the test parameters by region type – largest to smallest
462+
uksort( $test_parameters, array( $this, 'compare_location_type' ) );
459463

460-
// sanitize the test value
464+
$test_parameters = apply_filters( 'geoip_test_parameters', $test_parameters, $atts );
465+
466+
// Process through parameters, testing to see if we have a match
467+
foreach( $test_parameters as $label => $parameter ) {
468+
469+
$test_values = $parameter['test_values'];
470+
471+
$negate = $parameter['negate'];
472+
473+
// Sanitize the match value
474+
$match_value = strtolower( $this->geos[ $label ] );
475+
476+
// Sanitize the test values
477+
foreach( $test_values as &$test_value ) {
461478
$test_value = strtolower( trim( $test_value, " \t\"." ) );
479+
}
462480

463-
if( ! $negate && $match_value == $test_value ) {
464-
$keep = TRUE;
465-
}
481+
$is_match = in_array( $match_value, $test_values );
466482

467-
if( $negate && $match_value == $test_value ) {
468-
$keep = FALSE;
469-
}
483+
$is_match = ! $negate ? $is_match : ! $is_match;
484+
485+
if( ! $is_match ) {
486+
$keep = false;
470487
}
471488
}
472489

@@ -476,18 +493,42 @@ function do_shortcode_content( $atts, $content = null ) {
476493
return apply_filters( 'geoip_content', $content, $atts );
477494
}
478495

496+
/**
497+
* Compare the location types
498+
*
499+
* Used for sorting location types from largest area to smallest area
500+
*
501+
* @since 1.1.2
502+
*/
503+
public function compare_location_type( $a, $b ) {
504+
$location_types = array(
505+
'continent' => 1,
506+
'countrycode' => 2,
507+
'countrycode3' => 2,
508+
'countryname' => 2,
509+
'region' => 3,
510+
'areacode' => 4,
511+
'city' => 5,
512+
'postalcode' => 6,
513+
);
514+
515+
if( isset( $location_types[ $a ] ) && isset( $location_types[ $b ] ) ) {
516+
return $location_types[ $a ] - $location_types[ $b ];
517+
} else {
518+
return 0;
519+
}
520+
}
521+
479522
/**
480523
* Checks if environment variable depencies are available on the server
481524
*
525+
* @todo Include link to query documentation when available on the Plugin Directory
482526
* @since 0.5.0
483527
*/
484528
public function action_admin_init_check_plugin_dependencies() {
485-
// Check to see if we're in a development environment or the environment variables are present
486-
$is_wpe = getenv( 'HTTP_GEOIP_COUNTRY_CODE' );
487-
$is_dev = preg_match( '/^(.*)(\.dev)$|^(.*)(staging.wpengine.com)$/', get_site_url() );
488529

489-
if( 1 != $is_dev && ( ! isset( $is_wpe ) || empty( $is_wpe ) ) ) {
490-
$this->admin_notices[] = __( 'Please note - this plugin will only function on your <a href="http://wpengine.com/plans/?utm_source=' . self::TEXT_DOMAIN . '">WP Engine account</a>. This will not function outside of the WP Engine environment. Plugin <b>deactivated.</b>', self::TEXT_DOMAIN );
530+
if( ! $this->geos['active'] ) {
531+
$this->admin_notices[] = __( 'WP Engine GeoIP requires a <a href="http://wpengine.com/plans/?utm_source=' . self::TEXT_DOMAIN . '">WP Engine account</a> for full functionality. Only testing queries will work on this site.', self::TEXT_DOMAIN );
491532
}
492533
unset( $is_wpe );
493534
}
@@ -499,24 +540,21 @@ public function action_admin_init_check_plugin_dependencies() {
499540
*/
500541
public function action_admin_notices() {
501542
if( 0 < count( $this->admin_notices ) ) {
502-
// Hide the activation message
503-
echo '<style>.wrap .updated{display:none;}</style>';
504543

505-
// Display the errors
506-
echo '<div class="error">';
544+
// Display the notices
545+
echo '<div class="error notice is-dismissible">';
546+
507547
foreach( $this->admin_notices as $notice ) {
508548
echo "<p>$notice</p>";
509549
}
510-
echo '</div>';
511550

512-
// Disable this plugin
513-
deactivate_plugins( plugin_basename( __FILE__ ) );
551+
echo '</div>';
514552
}
515553
}
516554

517555
/**
518556
* As a favor to users, let's match some common synonyms
519-
*
557+
*
520558
* @since 1.1.0
521559
* @return string label
522560
*/

0 commit comments

Comments
 (0)