/**
* ---- Storage helpers --------------------------------------------------
* blocked_emails_list is stored as: email => source ('chargeback' | 'manual')
* Entries are permanent once added; they only leave via manual removal.
* Older formats (flat array of emails, or email => array(...)) are migrated on read.
*/
function get_blocked_emails() {
$stored = get_option( 'blocked_emails_list', array() );
$map = array();
foreach ( $stored as $key => $value ) {
if ( is_int( $key ) ) {
// Legacy: flat array of email strings.
$map[ strtolower( $value ) ] = 'chargeback';
} elseif ( is_array( $value ) ) {
// Prior format: email => array( 'source' => ..., 'locked' => ... ).
$map[ strtolower( $key ) ] = isset( $value['source'] ) ? $value['source'] : 'chargeback';
} else {
// Current format: email => source string.
$map[ strtolower( $key ) ] = $value;
}
}
return $map;
}
function save_blocked_emails( $map ) {
update_option( 'blocked_emails_list', $map );
}
/**
* Add a single email to the blocked list (no-op if already present).
*/
function add_blocked_email( $email, $source = 'manual' ) {
$email = strtolower( $email );
if ( ! is_email( $email ) ) {
return false;
}
$map = get_blocked_emails();
if ( ! isset( $map[ $email ] ) ) {
$map[ $email ] = $source;
save_blocked_emails( $map );
return true;
}
return false;
}
/**
* One-time pass to classify the source of legacy blocked emails.
* An email that has a chargeback-status order is labeled 'chargeback'; else 'manual'.
*/
function reconcile_blocked_email_sources() {
$map = get_blocked_emails();
if ( empty( $map ) ) {
return;
}
$orders = wc_get_orders( array( 'status' => 'chargeback', 'limit' => -1 ) );
$chargeback_emails = array();
foreach ( $orders as $order ) {
$email = strtolower( $order->get_billing_email() );
if ( ! empty( $email ) ) {
$chargeback_emails[ $email ] = true;
}
}
foreach ( $map as $email => $source ) {
$map[ $email ] = isset( $chargeback_emails[ $email ] ) ? 'chargeback' : 'manual';
}
save_blocked_emails( $map );
}
/**
* Add-only backfill: pull in any chargeback-status orders missing from the list.
* Never removes anything. Returns the number of new emails added.
*/
function add_existing_chargeback_emails_to_blocked_list() {
$orders = wc_get_orders( array( 'status' => 'chargeback', 'limit' => -1 ) );
$added = 0;
foreach ( $orders as $order ) {
$billing_email = $order->get_billing_email();
if ( empty( $billing_email ) ) {
continue;
}
if ( add_blocked_email( $billing_email, 'chargeback' ) ) {
$added++;
}
}
return $added;
}
// Automatically add email to blocked list when an order is moved to "chargeback".
// Fires on ANY status -> chargeback transition made through the order screen.
add_action( 'woocommerce_order_status_chargeback', 'add_email_to_blocked_list' );
function add_email_to_blocked_list( $order_id ) {
// --- DEBUG: uncomment to confirm the hook fires, then re-comment. ---
// error_log( "CHARGEBACK HOOK FIRED for order $order_id" );
$order = wc_get_order( $order_id );
if ( ! $order ) {
return;
}
$billing_email = $order->get_billing_email();
if ( empty( $billing_email ) ) {
return;
}
add_blocked_email( $billing_email, 'chargeback' );
}
function run_one_time_chargeback_block() {
if ( ! get_option( 'chargeback_emails_added' ) ) {
add_existing_chargeback_emails_to_blocked_list();
update_option( 'chargeback_emails_added', true );
}
}
add_action( 'admin_init', 'run_one_time_chargeback_block' );
// delete_option('chargeback_emails_added'); resets the one-time seed flag
add_action( 'admin_menu', 'blocked_emails_admin_menu' );
function blocked_emails_admin_menu() {
add_submenu_page(
'woocommerce',
'Blocked Emails',
'Blocked Emails',
'manage_woocommerce',
'blocked-emails-list',
'display_blocked_emails_list'
);
}
function display_blocked_emails_list() {
// One-time: classify legacy entries by checking for a real chargeback order.
if ( ! get_option( 'blocked_emails_source_reconciled' ) ) {
reconcile_blocked_email_sources();
update_option( 'blocked_emails_source_reconciled', true );
}
echo '';
// Handle email addition with nonce verification
if ( isset( $_POST['add_blocked_email'] ) && ! empty( $_POST['blocked_email'] ) && check_admin_referer( 'blocked_emails_nonce' ) ) {
$new_email = strtolower( sanitize_email( $_POST['blocked_email'] ) );
if ( is_email( $new_email ) ) {
if ( add_blocked_email( $new_email, 'manual' ) ) {
echo '
Email added successfully.
';
} else {
echo 'This email is already in the blocked list.
';
}
} else {
echo 'Please enter a valid email address.
';
}
}
// Refresh: add-only backfill of chargeback orders.
if ( isset( $_POST['refresh_chargebacks'] ) && check_admin_referer( 'blocked_emails_nonce' ) ) {
$added = add_existing_chargeback_emails_to_blocked_list();
echo '' . esc_html( $added ) . ' new chargeback email(s) added.
';
}
// Bulk Remove Selected Emails (the manual escape hatch).
if ( isset( $_POST['bulk_remove'] ) && ! empty( $_POST['emails_to_remove'] ) && check_admin_referer( 'blocked_emails_nonce' ) ) {
$map = get_blocked_emails();
foreach ( (array) $_POST['emails_to_remove'] as $remove ) {
unset( $map[ strtolower( sanitize_email( $remove ) ) ] );
}
save_blocked_emails( $map );
echo 'Selected emails removed successfully.
';
}
// Clear All Emails
if ( isset( $_POST['clear_all'] ) && check_admin_referer( 'blocked_emails_nonce' ) ) {
save_blocked_emails( array() );
echo 'All blocked emails cleared successfully.
';
}
// Read the (possibly just-updated) list once, after all mutations.
$blocked_emails = get_blocked_emails();
$email_count = count( $blocked_emails );
echo '';
echo '
Blocked Emails ';
// Add new email form with nonce
echo '
';
// Refresh button in its own form so the required email field can't block it
echo '
';
// List + bulk action form
echo '
';
echo '
Total Blocked Emails: ' . esc_html( $email_count ) . '
';
echo '
';
// JavaScript to handle "Select All" checkbox
echo '';
}
/**
* Prevent checkout for blocked email addresses
*/
add_action( 'woocommerce_checkout_process', function () {
$billing_email = strtolower( sanitize_email( $_POST['billing_email'] ?? '' ) );
if ( empty( $billing_email ) ) {
return;
}
$blocked_emails = get_blocked_emails(); // keys are lowercased
if ( isset( $blocked_emails[ $billing_email ] ) ) {
wc_add_notice(
__( 'Sorry, your order could not be completed at this time. Please contact support for assistance.', 'woocommerce' ),
'error'
);
}
});
Events for January 2025
0 events
29
0 events
30
0 events
31
0 events
1
0 events
2
0 events
3
0 events
4
0 events
5
0 events
6
0 events
7
0 events
8
0 events
9
0 events
10
0 events
11
0 events
12
0 events
13
0 events
14
0 events
15
0 events
16
0 events
17
0 events
18
0 events
19
0 events
20
0 events
21
0 events
22
0 events
23
0 events
24
0 events
25
0 events
26
0 events
27
0 events
28
0 events
29
0 events
30
0 events
31
0 events
1