|
<?php |
|
/** |
|
* Plugin Name: WBCOM – Geo Restrict THCA (AU/NZ via Cloudflare) |
|
* Description: Hides a WooCommerce category, redirects its pages, and blocks add-to-cart/checkout for AU & NZ using CF-IPCountry. |
|
* Author: Wbcom Designs |
|
* Version: 1.0.0 |
|
* Requires at least: 5.8 |
|
* Requires PHP: 7.4 |
|
*/ |
|
|
|
if ( ! defined( 'ABSPATH' ) ) exit; |
|
|
|
/** ============ CONFIG ============ */ |
|
const WBCOM_BLOCKED_COUNTRIES = [ 'AU', 'NZ' ]; |
|
const WBCOM_RESTRICTED_CAT_ID = 369; // product_cat term_id |
|
const WBCOM_RESTRICTED_CAT_SLUG = 'thca-flower'; // product_cat slug |
|
|
|
/** Geo check (Cloudflare) */ |
|
function wbcom_geo_blocked(): bool { |
|
$cc = $_SERVER['HTTP_CF_IPCOUNTRY'] ?? ''; |
|
return in_array( strtoupper( trim( $cc ) ), WBCOM_BLOCKED_COUNTRIES, true ); |
|
} |
|
|
|
/** Resolve the restricted category term IDs */ |
|
function wbcom_restricted_term_ids(): array { |
|
$ids = []; |
|
if ( WBCOM_RESTRICTED_CAT_ID ) { |
|
$t = get_term( WBCOM_RESTRICTED_CAT_ID, 'product_cat' ); |
|
if ( $t && ! is_wp_error( $t ) ) $ids[] = (int) $t->term_id; |
|
} |
|
if ( WBCOM_RESTRICTED_CAT_SLUG ) { |
|
$t = get_term_by( 'slug', WBCOM_RESTRICTED_CAT_SLUG, 'product_cat' ); |
|
if ( $t && ! is_wp_error( $t ) ) $ids[] = (int) $t->term_id; |
|
} |
|
return array_unique( array_filter( $ids ) ); |
|
} |
|
|
|
/** Is this product (or its parent) in the restricted category? */ |
|
function wbcom_is_restricted_product( $product_id ): bool { |
|
if ( ! $product_id ) return false; |
|
$ids = wbcom_restricted_term_ids(); |
|
if ( ! $ids ) return false; |
|
|
|
if ( has_term( $ids, 'product_cat', (int) $product_id ) ) return true; |
|
|
|
$product = wc_get_product( $product_id ); |
|
if ( $product && $product->is_type( 'variation' ) ) { |
|
$parent_id = $product->get_parent_id(); |
|
if ( $parent_id && has_term( $ids, 'product_cat', $parent_id ) ) return true; |
|
} |
|
return false; |
|
} |
|
|
|
/** 1) Hide from main loops: shop, archives, search */ |
|
add_action( 'pre_get_posts', function( $q ) { |
|
if ( is_admin() || ! $q->is_main_query() || ! wbcom_geo_blocked() ) return; |
|
|
|
if ( $q->is_post_type_archive( 'product' ) || $q->is_tax( [ 'product_cat', 'product_tag' ] ) || $q->is_search() ) { |
|
$ids = wbcom_restricted_term_ids(); |
|
if ( $ids ) { |
|
$tax_query = (array) $q->get( 'tax_query' ); |
|
$tax_query[] = [ |
|
'taxonomy' => 'product_cat', |
|
'field' => 'term_id', |
|
'terms' => $ids, |
|
'operator' => 'NOT IN', |
|
]; |
|
$q->set( 'tax_query', $tax_query ); |
|
} |
|
} |
|
}); |
|
|
|
/** 2) Hide from WooCommerce product queries (shortcodes, widgets, blocks) */ |
|
add_action( 'woocommerce_product_query', function( $wcq ) { |
|
if ( ! wbcom_geo_blocked() ) return; |
|
$ids = wbcom_restricted_term_ids(); |
|
if ( ! $ids ) return; |
|
|
|
$tax_query = (array) $wcq->get( 'tax_query' ); |
|
$tax_query[] = [ |
|
'taxonomy' => 'product_cat', |
|
'field' => 'term_id', |
|
'terms' => $ids, |
|
'operator' => 'NOT IN', |
|
]; |
|
$wcq->set( 'tax_query', $tax_query ); |
|
}); |
|
|
|
/** 3) Redirect AU/NZ off the restricted category page and its products */ |
|
add_action( 'template_redirect', function() { |
|
if ( ! wbcom_geo_blocked() ) return; |
|
$ids = wbcom_restricted_term_ids(); |
|
if ( ! $ids ) return; |
|
|
|
// Category page |
|
if ( is_product_category( $ids ) ) { |
|
wp_safe_redirect( wc_get_page_permalink( 'shop' ) ); |
|
exit; |
|
} |
|
|
|
// Single product page |
|
if ( is_product() ) { |
|
global $post; |
|
if ( $post && wbcom_is_restricted_product( $post->ID ) ) { |
|
wp_safe_redirect( wc_get_page_permalink( 'shop' ) ); |
|
exit; |
|
} |
|
} |
|
}); |
|
|
|
/** 4) Block add-to-cart (?add-to-cart=ID, AJAX, buttons, API) */ |
|
add_filter( 'woocommerce_add_to_cart_validation', function( $passed, $product_id, $qty, $variation_id = 0 ) { |
|
if ( ! wbcom_geo_blocked() ) return $passed; |
|
|
|
$check_id = $variation_id ?: $product_id; |
|
if ( wbcom_is_restricted_product( $check_id ) ) { |
|
wc_add_notice( __( 'Sorry, this product is not available in your region.', 'wbcom' ), 'error' ); |
|
return false; |
|
} |
|
return $passed; |
|
}, 10, 4 ); |
|
|
|
/** 5) Sweep cart from session (saved carts, pre-existing items) */ |
|
add_action( 'woocommerce_cart_loaded_from_session', function( $cart ) { |
|
if ( ! wbcom_geo_blocked() || ! $cart ) return; |
|
|
|
$removed = false; |
|
foreach ( $cart->get_cart() as $key => $item ) { |
|
$pid = $item['variation_id'] ?: $item['product_id']; |
|
if ( wbcom_is_restricted_product( $pid ) ) { |
|
$cart->remove_cart_item( $key ); |
|
$removed = true; |
|
} |
|
} |
|
if ( $removed ) { |
|
wc_add_notice( __( 'Some items were removed because they are not available in your region.', 'wbcom' ), 'notice' ); |
|
} |
|
}); |
|
|
|
/** 6) Final guard at checkout */ |
|
add_action( 'woocommerce_check_cart_items', function() { |
|
if ( ! wbcom_geo_blocked() ) return; |
|
|
|
$blocked_found = false; |
|
foreach ( WC()->cart->get_cart() as $key => $item ) { |
|
$pid = $item['variation_id'] ?: $item['product_id']; |
|
if ( wbcom_is_restricted_product( $pid ) ) { |
|
WC()->cart->remove_cart_item( $key ); |
|
$blocked_found = true; |
|
} |
|
} |
|
if ( $blocked_found ) { |
|
wc_add_notice( __( 'Your cart was updated because one or more items are not available in your region.', 'wbcom' ), 'error' ); |
|
} |
|
}); |
|
|
|
/** 7) Cache safety for CF/APO and other caches */ |
|
add_action( 'send_headers', function() { |
|
if ( headers_sent() ) return; |
|
header( 'Vary: CF-IPCountry' ); |
|
}); |