Annuleren en blokkeren bestellingen
June 17, 2025 Β· AI Conversations
—
### β
1. **Cancel Existing Orders**
Cancel all orders with:
– Status = `on-hold` or `processing`
– AND at least one product in a **subcategory** with slug `bijna-verboden`
#### PHP Code (Run once via plugin or CLI script)
function cancel_orders_with_bijna_verboden_product() {
$args = array(
'status' => ['on-hold', 'processing'],
'limit' => -1,
'return' => 'ids',
);
$orders = wc_get_orders($args);
foreach ($orders as $order_id) {
$order = wc_get_order($order_id);
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if ($product && has_term('bijna-verboden', 'product_cat', $product->get_id())) {
$order->update_status('cancelled', 'Cancelled due to containing a bijna-verboden product.');
break;
}
}
}
}
add_action('init', 'cancel_orders_with_bijna_verboden_product');
β Remove or comment out the `add_action` line after execution to avoid re-triggering.
—
### π 2. **Prevent Future Processing After June 28**
Hook into order status transition to block `processing` status if:
– The order contains a `bijna-verboden` product
– And today's date is **after June 28**
#### PHP Code (Prevent status update)
function prevent_processing_status_bijna_verboden($order_id, $old_status, $new_status) {
if ($new_status !== 'processing') return;
$cutoff = strtotime('2025-06-28');
if (time() <= $cutoff) return;
$order = wc_get_order($order_id);
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if ($product && has_term('bijna-verboden', 'product_cat', $product->get_id())) {
// Revert to previous status
$order->update_status($old_status, 'Blocked processing due to product in bijna-verboden.');
wc_add_notice(__('Order cannot be set to processing due to restricted product.', 'woocommerce'), 'error');
break;
}
}
}
add_action('woocommerce_order_status_changed', 'prevent_processing_status_bijna_verboden', 10, 3);
—
### π Optional (Block on Checkout)
To block checkout *before placing an order*, we can also prevent orders from being placed at all if they contain the restricted subcategory **after June 28**. Let me know if you want that too.
Would you like this packaged into a plugin?
1. Cancels all `on-hold` or `processing` orders containing a product in the `bijna-verboden` subcategory.
2. Prevents future processing of such orders **after June 28, 2025** (can be extended to lock manually via cron).
—
### β External Script: `cancel_bijna_orders.php`
<?php
// Load WordPress environment
require_once('/path/to/your/wordpress/wp-load.php'); // <-- adjust this path
use AutomatticWooCommerceAdminOverridesOrder;
// Set timezone
date_default_timezone_set('UTC');
// === CONFIGURATION ===
$restricted_category_slug = 'bijna-verboden';
$cutoff_date = '2025-06-28'; // format: Y-m-d
// === FETCH ORDERS ===
$args = array(
'status' => ['on-hold', 'processing'],
'limit' => -1,
'return' => 'ids',
);
$orders = wc_get_orders($args);
$cancelled = [];
foreach ($orders as $order_id) {
$order = wc_get_order($order_id);
$should_cancel = false;
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if (!$product) continue;
if (has_term($restricted_category_slug, 'product_cat', $product->get_id())) {
$should_cancel = true;
break;
}
}
if ($should_cancel) {
$order->update_status('cancelled', 'Auto-cancelled due to restricted product.');
$cancelled[] = $order_id;
}
}
// === REPORT ===
echo "Cancelled Orders (with '$restricted_category_slug'):n";
echo implode(', ', $cancelled);
// === LOCKING FUTURE ORDERS (OPTIONAL) ===
// This cannot intercept WooCommerce status changes directly from here
// but you can run this daily in a cron job after June 28 to re-check and re-cancel if needed
if (strtotime('now') > strtotime($cutoff_date)) {
// Optionally repeat the cancel process here for any orders moved to processing after cutoff
}
—
### β How to Use
1. **Save as** `cancel_bijna_orders.php`
2. **Place it** in your root or admin folder (outside `wp-admin`)
3. **Update the path** in:
require_once('/path/to/your/wordpress/wp-load.php');
4. **Run via CLI or Browser:**
php cancel_bijna_orders.php
—
Would you like to:
– Add cron job logic?
– Lock database status update permanently using SQL?
– Log to file instead of echo?
Let me know, I can extend this further.
—
### β
Script Features
1. Cancel all `on-hold` / `processing` orders with at least one product in subcategory `bijna-verboden`.
2. Add a **custom meta `_locked_from_processing = 1`** to mark them "locked".
3. Add a **note** to the order for admin clarity.
4. Output a **summary table** of all affected orders (order ID, status, product names).
—
### β `lock_bijna_orders.php`
<?php
require_once('/path/to/your/wordpress/wp-load.php'); // π§ Adjust path to wp-load.php
date_default_timezone_set('UTC');
// === SETTINGS ===
$restricted_slug = 'bijna-verboden';
$statuses_to_check = ['on-hold', 'processing'];
$locked_orders = [];
$args = [
'status' => $statuses_to_check,
'limit' => -1,
'return' => 'ids',
];
$order_ids = wc_get_orders($args);
foreach ($order_ids as $order_id) {
$order = wc_get_order($order_id);
$has_restricted = false;
$products = [];
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if (!$product) continue;
$products[] = $product->get_name();
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
$has_restricted = true;
}
}
if ($has_restricted) {
if ($order->get_status() !== 'cancelled') {
$order->update_status('cancelled', 'Cancelled due to restricted product.');
}
$order->update_meta_data('_locked_from_processing', 1);
$order->add_order_note('Order locked from being set to processing due to restricted product.');
$order->save();
$locked_orders[] = [
'id' => $order_id,
'status' => $order->get_status(),
'products' => implode(', ', $products),
];
}
}
// === OUTPUT SIMPLE TABLE ===
if (!empty($locked_orders)) {
echo "=== Locked Orders Summary ===nn";
foreach ($locked_orders as $order) {
echo "Order #{$order['id']} | Status: {$order['status']} nProducts: {$order['products']}nn";
}
} else {
echo "No orders found with restricted products.n";
}
—
### π Step 2: Lock Status Change in WordPress (Optional but Recommended)
If you want to **completely prevent status update to `processing`** from admin or API, add this code to your themeβs `functions.php` or a custom plugin:
add_action('woocommerce_order_status_changed', function($order_id, $from, $to) {
if ($to !== 'processing') return;
$order = wc_get_order($order_id);
if ($order->get_meta('_locked_from_processing') == 1) {
// Revert back
$order->update_status($from, 'Blocked from processing due to restricted product.');
wc_add_notice(__('This order is locked from being moved to processing.'), 'error');
}
}, 10, 3);
—
### π Cron Tip
You can schedule this external script with a daily cron job to ensure all such orders are continuously cleaned up and locked.
0 3 * * * php /path/to/lock_bijna_orders.php
Would you like a full WordPress plugin version too?
### β
Goal:
If the **cart/order contains any product** from the **subcategory `bijna-verboden`**, then:
– β **Prevent the order from being placed (before payment is processed)**
– π **Mark it as "locked" with a custom note/meta**
– β
This happens **during checkout when "Place order" is clicked**
—
### β Final Solution: Hook into `woocommerce_checkout_process`
This will **block checkout submission** and display an error if the cart contains a `bijna-verboden` product.
add_action('woocommerce_checkout_process', function() {
$restricted_slug = 'bijna-verboden';
foreach (WC()->cart->get_cart_contents() as $cart_item) {
$product = $cart_item['data'];
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
wc_add_notice(__('One or more products in your cart are restricted and cannot be ordered.', 'woocommerce'), 'error');
break;
}
}
});
—
### π This stops the order *before* payment is processed. No order is created.
—
### π Alternative: Allow order, but prevent payment & lock order
If you instead want to **create the order** but mark it as locked and unpaid (e.g. for review or admin follow-up), use this **in combination**:
add_action('woocommerce_checkout_create_order', function($order, $data) {
$restricted_slug = 'bijna-verboden';
$has_restricted = false;
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
$has_restricted = true;
break;
}
}
if ($has_restricted) {
$order->update_status('on-hold', 'Order contains restricted product and is locked.');
$order->update_meta_data('_locked_from_processing', 1);
$order->add_order_note('This order is locked due to restricted product.');
}
}, 10, 2);
> π§ Use **only one** of the two options depending on:
– β Full block before order = use `woocommerce_checkout_process`
– β
Allow but lock = use `woocommerce_checkout_create_order`
Would you like to combine both into a toggle via admin setting?
—
### β Final Code (Put in `functions.php` or custom plugin)
add_action('woocommerce_checkout_process', function() {
$restricted_slug = 'bijna-verboden';
foreach (WC()->cart->get_cart_contents() as $cart_item) {
$product = $cart_item['data'];
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
wc_add_notice(
__('Sorry, your cart contains a restricted product and the order cannot be placed. Please remove the restricted product to proceed.', 'woocommerce'),
'error'
);
break;
}
}
});
—
### π§ͺ Result:
When a user clicks **"Place Order"**, if their cart includes any product in the `bijna-verboden` subcategory:
– β The order is **not placed**
– βA **clear error message** appears on the checkout page
—
### π Optional: Customize Error Styling
WooCommerce displays error notices above the checkout form. You can style it with CSS:
.woocommerce-error {
background: #ffecec;
border-left: 4px solid #cc0000;
padding: 12px;
margin-bottom: 20px;
color: #cc0000;
font-weight: bold;
}
—
Would you like this to also work on the **Cart page** with an early warning (before checkout)?
> β
Allow the order to be created
> π If the order contains a product from subcategory `bijna-verboden`:
> – Immediately set the order to **on-hold** (or custom status)
> – Prevent payment (stop automatic status = "processing")
> – Add a note visible to both admin and user
> – Show a custom error/warning **after checkout submission** (on the "thank you" page or during checkout)
—
## β Final Working Solution
### 1. **Lock Order During Creation**
Add this to `functions.php` or a custom plugin:
add_action('woocommerce_checkout_create_order', function($order, $data) {
$restricted_slug = 'bijna-verboden';
$has_restricted = false;
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
$has_restricted = true;
break;
}
}
if ($has_restricted) {
$order->update_meta_data('_locked_from_processing', 1);
$order->add_order_note('β οΈ This order contains restricted products and is locked from further processing.');
}
}, 10, 2);
—
### 2. **Prevent Payment Status Change to 'processing'**
add_action('woocommerce_order_status_changed', function($order_id, $from, $to) {
if ($to !== 'processing') return;
$order = wc_get_order($order_id);
if ($order->get_meta('_locked_from_processing')) {
// Revert status back
$order->update_status('on-hold', 'Order locked due to restricted product.');
$order->add_order_note('Order prevented from being set to processing. Locked.');
}
}, 10, 3);
—
### 3. **Show Message to User After Checkout (on Thank You page)**
add_action('woocommerce_thankyou', function($order_id) {
$order = wc_get_order($order_id);
if ($order && $order->get_meta('_locked_from_processing')) {
echo '<div class="woocommerce-message" style="margin-top:20px; padding:15px; border-left: 4px solid orange;">
β οΈ <strong>Your order includes restricted products and is placed on hold.</strong><br>
Our team will review it and contact you if needed. No payment was processed.
</div>';
}
});
—
### π Now Your Flow Works Like:
– β
User places order β order is **created**
– π If restricted product found:
– Status = `on-hold`
– Meta `_locked_from_processing = 1`
– Prevent future change to `processing`
– Message shows to user on **thank you page**
—
Would you like to:
– Define a custom order status like `locked`?
– Email the admin immediately for such orders?
Let me know and I can add those too.
—
## β
What We'll Do
1. Register a custom status called `locked`.
2. Add it to the WooCommerce order status list.
3. Display it in the admin dropdowns and filters.
4. Use it in place of `on-hold` for restricted orders.
—
## β 1. **Register Custom Status**
Add this to your themeβs `functions.php` or a custom plugin:
add_action('init', function() {
register_post_status('wc-locked', [
'label' => _x('Locked', 'Order status', 'woocommerce'),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Locked <span class="count">(%s)</span>', 'Locked <span class="count">(%s)</span>', 'woocommerce')
]);
});
—
## β 2. **Add It to the WooCommerce Status List**
add_filter('wc_order_statuses', function($order_statuses) {
$new_statuses = [];
foreach ($order_statuses as $key => $label) {
$new_statuses[$key] = $label;
// Add after 'on-hold'
if ('wc-on-hold' === $key) {
$new_statuses['wc-locked'] = _x('Locked', 'Order status', 'woocommerce');
}
}
return $new_statuses;
});
—
## β 3. **Use It When Order Contains Restricted Product**
Update your earlier hook:
add_action('woocommerce_checkout_create_order', function($order, $data) {
$restricted_slug = 'bijna-verboden';
$has_restricted = false;
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
$has_restricted = true;
break;
}
}
if ($has_restricted) {
$order->update_meta_data('_locked_from_processing', 1);
$order->set_status('locked'); // π Use custom status
$order->add_order_note('π« This order contains restricted products and has been locked.');
}
}, 10, 2);
—
## β 4. (Optional) Prevent Locked β Processing Status Change
add_action('woocommerce_order_status_changed', function($order_id, $from, $to) {
if ($to !== 'processing') return;
$order = wc_get_order($order_id);
if ($order->get_meta('_locked_from_processing')) {
$order->update_status('locked', 'Prevented from moving to processing. Locked due to restricted product.');
}
}, 10, 3);
—
### β
Result:
– Custom order status: **Locked**
– Visible in admin
– Auto-assigned if restricted products found
– Prevents payment processing
– Reverts if someone tries to change to `processing`
—
Would you like to assign a specific **color or icon** to the "Locked" status in admin? Let me know!
1. Their cart contains a product from the subcategory `bijna-verboden`
2. OR their order is marked as **"Locked"** after checkout
Weβll show clear messages on both the **Cart/Checkout page** and the **Thank You page**.
—
## β Step-by-Step Additions
—
### β 1. Show Warning Message on **Cart & Checkout Pages**
Add this to `functions.php`:
add_action('woocommerce_before_checkout_form', 'check_cart_for_restricted_products', 5);
add_action('woocommerce_before_cart', 'check_cart_for_restricted_products', 5);
function check_cart_for_restricted_products() {
$restricted_slug = 'bijna-verboden';
foreach (WC()->cart->get_cart_contents() as $cart_item) {
$product = $cart_item['data'];
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
wc_print_notice(
__('β οΈ Warning: Your cart contains a restricted product and the order will be locked after placement. Payment will not be processed.', 'woocommerce'),
'notice'
);
break;
}
}
}
This will:
– Show a **notice-style** message at the top of the cart and checkout pages.
– Warn the user **before** placing the order.
—
### β 2. Show Message on **Thank You Page** if Order is Locked
add_action('woocommerce_thankyou', function($order_id) {
$order = wc_get_order($order_id);
if ($order && ($order->get_status() === 'locked' || $order->get_meta('_locked_from_processing'))) {
echo '<div class="woocommerce-error" style="margin-top:20px; padding:15px; border-left:4px solid #cc0000;">
π« <strong>Your order is locked due to restricted products.</strong><br>
Our team will review your order. No payment has been taken.
</div>';
}
});
—
## π‘ Optional UI Enhancement
You can style the message better using CSS (e.g., via theme or Customizer):
.woocommerce-notice--custom-warning {
background: #fff3cd;
border-left: 4px solid #ffc107;
padding: 12px;
font-weight: bold;
color: #856404;
}
—
### β
Summary:
| Page | What Happens |
|——————-|——————————————————————————|
| **Cart/Checkout** | Warn user before placing order if restricted product is in cart |
| **Thank You** | After placing order, inform user the order is locked and payment is blocked |
—
Would you like to also:
– Prevent adding restricted products to the cart?
– Show a warning **on product pages** too?
Let me know, I can extend that logic as well.
$restricted_slug = 'bijna-verboden';
$has_restricted = false;
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
$has_restricted = true;
break;
}
}
if ($has_restricted) {
$order->update_meta_data('_locked_from_processing', 1);
$order->set_status('locked'); // π Use custom status
$order->add_order_note('π« This order contains restricted products and has been locked.');
}
}, 10, 2);
add_action('woocommerce_order_status_changed', function($order_id, $from, $to) {
if ($to !== 'processing') return;
$order = wc_get_order($order_id);
if ($order->get_meta('_locked_from_processing')) {
$order->update_status('locked', 'Prevented from moving to processing. Locked due to restricted product.');
}
}, 10, 3);
add_action('woocommerce_thankyou', function($order_id) {
$order = wc_get_order($order_id);
if ($order && ($order->get_status() === 'locked' || $order->get_meta('_locked_from_processing'))) {
echo '
π« Your order is locked due to restricted products.
Our team will review your order. No payment has been taken.
';
}
});
above code not wokring
– Lock the order if it contains a restricted product.
– Set the status to `locked`.
– Prevent transition to `processing`.
– Show a message on the **Thank You** page.
—
## π Common Issues Checklist
### β
1. **Custom Order Status Registered?**
The status `locked` must be registered via `register_post_status`. Add this before using `set_status('locked')`.
**β Add this in `functions.php` or a plugin:**
add_action('init', function () {
register_post_status('wc-locked', array(
'label' => _x('Locked', 'Order status', 'woocommerce'),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Locked <span class="count">(%s)</span>', 'Locked <span class="count">(%s)</span>', 'woocommerce')
));
});
### β 2. **Add Locked Status to Admin UI**
add_filter('wc_order_statuses', function($order_statuses) {
$new_statuses = [];
foreach ($order_statuses as $key => $label) {
$new_statuses[$key] = $label;
if ($key === 'wc-on-hold') {
$new_statuses['wc-locked'] = _x('Locked', 'Order status', 'woocommerce');
}
}
return $new_statuses;
});
—
## β Revised Full Working Code (Cleaned & Combined)
// Register custom order status
add_action('init', function () {
register_post_status('wc-locked', array(
'label' => _x('Locked', 'Order status', 'woocommerce'),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Locked <span class="count">(%s)</span>', 'Locked <span class="count">(%s)</span>', 'woocommerce')
));
});
// Add custom status to WooCommerce order statuses
add_filter('wc_order_statuses', function($order_statuses) {
$new_statuses = [];
foreach ($order_statuses as $key => $label) {
$new_statuses[$key] = $label;
if ($key === 'wc-on-hold') {
$new_statuses['wc-locked'] = _x('Locked', 'Order status', 'woocommerce');
}
}
return $new_statuses;
});
// Lock order on creation if restricted product found
add_action('woocommerce_checkout_create_order', function($order, $data) {
$restricted_slug = 'bijna-verboden';
$has_restricted = false;
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if ($product && has_term($restricted_slug, 'product_cat', $product->get_id())) {
$has_restricted = true;
break;
}
}
if ($has_restricted) {
$order->update_meta_data('_locked_from_processing', 1);
$order->set_status('locked'); // custom status
$order->add_order_note('π« This order contains restricted products and has been locked.');
}
}, 10, 2);
// Prevent moving to processing
add_action('woocommerce_order_status_changed', function($order_id, $from, $to) {
if ($to !== 'processing') return;
$order = wc_get_order($order_id);
if ($order && $order->get_meta('_locked_from_processing')) {
$order->update_status('locked', 'Prevented from moving to processing. Locked due to restricted product.');
}
}, 10, 3);
// Show frontend thank you message
add_action('woocommerce_thankyou', function($order_id) {
$order = wc_get_order($order_id);
if ($order && ($order->get_status() === 'locked' || $order->get_meta('_locked_from_processing'))) {
echo '<div class="woocommerce-error" style="margin-top:20px; padding:15px; border-left:4px solid #cc0000;">
π« <strong>Your order is locked due to restricted products.</strong><br>
Our team will review your order. No payment has been taken.
</div>';
}
});
—
## β Test Now:
1. Add a product from subcategory **`bijna-verboden`**.
2. Go to checkout and place order.
3. You should:
– See status **`Locked`** in admin.
– See the warning message on the **Thank You** page.
– Not be able to move this order to `processing`.
—
Let me know if you also want to:
– Hide payment gateways for such orders
– Notify admin by email when order is locked
—
## β Final Code: Hide All Payment Gateways If Restricted Product Found
Add this to your themeβs `functions.php` or custom plugin:
add_filter('woocommerce_available_payment_gateways', function($gateways) {
if (is_admin() && !defined('DOING_AJAX')) return $gateways;
$restricted_slug = 'bijna-verboden';
foreach (WC()->cart->get_cart_contents() as $cart_item) {
$product = $cart_item['data'];
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
// Empty all gateways
$gateways = [];
// Optional: show a notice
wc_add_notice(
__('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold for review.', 'woocommerce'),
'error'
);
break;
}
}
return $gateways;
});
—
### β
Result:
– When the cart has any product in subcategory `bijna-verboden`:
– π³ **All payment methods are hidden**
– π« A **message appears** on checkout telling user payment is blocked
– The user can still place the order β it will be **created without payment** and marked `locked` (as per previous logic)
—
### π‘ Optional Enhancements:
– Instead of hiding **all** gateways, you can allow a specific one like `bacs` (bank transfer). Let me know if you want this filtered instead of removed entirely.
Would you like to:
– Show a **custom message above the payment section**?
– Add an automatic **email to the admin** for locked orders?
Let me know!
– Used **at the right time** (after cart is loaded)
– Not blocked by AJAX or admin requests
– Properly returns modified gateways
—
## β Use `woocommerce_cart_ready` Context
Here's a **reliable version** that ensures it works during checkout **and even with AJAX requests** (e.g., when switching payment methods or shipping):
### β Updated Code:
add_filter('woocommerce_available_payment_gateways', 'disable_gateways_for_restricted_products');
function disable_gateways_for_restricted_products($available_gateways) {
// Don't apply this filter in admin or if cart isn't initialized
if (is_admin() && !defined('DOING_AJAX')) return $available_gateways;
if (!WC()->cart || WC()->cart->is_empty()) return $available_gateways;
$restricted_slug = 'bijna-verboden';
foreach (WC()->cart->get_cart_contents() as $cart_item) {
$product = $cart_item['data'];
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
// Optionally allow just one gateway (e.g., manual/bacs)
// unset($available_gateways['paypal'], $available_gateways['cod']);
// Hide all gateways
return [];
// Optional: display a message once (not multiple times via AJAX)
if (!wc_has_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error')) {
wc_add_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error');
}
}
}
return $available_gateways;
}
—
## β Testing Tips:
1. Add a product in subcategory `bijna-verboden`
2. Go to the **checkout page**
3. All **payment gateways should disappear**
4. A clear **error message** should appear
5. User can still click "Place Order" β it will follow your locked order logic
—
### β Optional: Allow Bank Transfer Only
return array_filter($available_gateways, function($gateway) {
return $gateway->id === 'bacs'; // allow only Bank Transfer
});
—
Let me know if:
– Your site uses custom payment gateway plugins (some don't respect this filter)
– You want to hide payment **only after June 28**
– Or want to apply this logic based on **user role** or **shipping country** too
above not working even WC() not working
### π You're executing this too early in the lifecycle.
To fix it:
—
## β Best Practice: Delay Hook with `template_redirect`
Use this wrapper to **ensure WooCommerce is fully initialized** (i.e. `WC()->cart` is available):
### β Revised Working Code:
add_action('template_redirect', function () {
add_filter('woocommerce_available_payment_gateways', 'disable_gateways_for_restricted_products');
});
function disable_gateways_for_restricted_products($available_gateways) {
if (!is_checkout() || is_wc_endpoint_url('order-received')) return $available_gateways;
if (!function_exists('WC') || !WC()->cart || WC()->cart->is_empty()) {
return $available_gateways;
}
$restricted_slug = 'bijna-verboden';
foreach (WC()->cart->get_cart_contents() as $cart_item) {
$product = $cart_item['data'];
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
// Optionally allow a single gateway like bank transfer:
// return array_filter($available_gateways, fn($gw) => $gw->id === 'bacs');
// Hide all gateways
if (!wc_has_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error')) {
wc_add_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error');
}
return []; // hide all gateways
}
}
return $available_gateways;
}
—
### β
Why this works:
– `template_redirect` ensures the **cart session is loaded**
– Avoids calling `WC()` too early (like during plugin loading or theme setup)
– Only applies filter on **actual checkout page**, not admin or order thank you page
—
Let me know if:
– You want this to apply **only after June 28**
– You want to **log blocked attempts**
– Or allow just specific payment gateways (e.g. manual review)
$product = $cart_item['data'];
if (has_term($restricted_slug, 'product_cat', $product->get_id())) {
// Optionally allow just one gateway (e.g., manual/bacs)
// unset($available_gateways['paypal'], $available_gateways['cod']);
// Hide all gateways
return [];
// Optional: display a message once (not multiple times via AJAX)
if (!wc_has_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error')) {
wc_add_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error');
}
}
}
above subscat finding not wokring
—
## π§ Problem
`has_term()` checks only **direct terms** assigned to the product, **not parent/child hierarchy**.
So if your product is assigned to a child category of `bijna-verboden`, but not to `bijna-verboden` itself, `has_term()` returns `false`.
—
## β Solution: Use `get_the_terms()` + Check Parent Chain
Here's a helper function to check **if product is in a subcategory of `bijna-verboden`** (direct or inherited):
### β Step 1: Add This Helper Function
function product_has_restricted_category($product_id, $slug = 'bijna-verboden') {
$terms = get_the_terms($product_id, 'product_cat');
if (!$terms || is_wp_error($terms)) return false;
foreach ($terms as $term) {
// Direct match
if ($term->slug === $slug) return true;
// Check parent chain
$parent = $term->parent;
while ($parent) {
$parent_term = get_term($parent, 'product_cat');
if (is_wp_error($parent_term)) break;
if ($parent_term->slug === $slug) return true;
$parent = $parent_term->parent;
}
}
return false;
}
—
### β Step 2: Replace Your Loop With This
foreach (WC()->cart->get_cart_contents() as $cart_item) {
$product = $cart_item['data'];
if (product_has_restricted_category($product->get_id(), 'bijna-verboden')) {
// Optional notice
if (!wc_has_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error')) {
wc_add_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error');
}
return []; // Hide all payment gateways
}
}
—
### π§ͺ Test Cases:
| Product Assigned to | Detection Works? |
|———————————-|——————|
| `bijna-verboden` directly | β
|
| A subcategory under `bijna-verboden` | β
|
| Another unrelated category | β |
—
Let me know if you want to also:
– Show this notice on the product page
– Prevent adding restricted items to cart
I can add those next.
foreach (WC()->cart->get_cart_contents() as $cart_item) {
$product = $cart_item['data'];
if (product_has_restricted_category($product->get_id(), 'bijna-verboden')) {
// Optional notice
if (!wc_has_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error')) {
wc_add_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error');
}
return []; // Hide all payment gateways
}
}
above code not working
—
## β Full Working Solution (End-to-End)
This works **even if `bijna-verboden` is a parent category** and the product belongs to a **child subcategory**.
—
### β 1. Add This to `functions.php` (or plugin):
// Delay filter to ensure WC is fully initialized
add_action('template_redirect', function () {
add_filter('woocommerce_available_payment_gateways', 'disable_gateways_for_restricted_products');
});
// Helper: Check if product belongs to a category or any of its subcategories
function product_has_restricted_category($product_id, $slug = 'bijna-verboden') {
$terms = get_the_terms($product_id, 'product_cat');
if (empty($terms) || is_wp_error($terms)) return false;
foreach ($terms as $term) {
// Direct match
if ($term->slug === $slug) return true;
// Check parent categories
$parent_id = $term->parent;
while ($parent_id) {
$parent_term = get_term($parent_id, 'product_cat');
if (is_wp_error($parent_term)) break;
if ($parent_term->slug === $slug) return true;
$parent_id = $parent_term->parent;
}
}
return false;
}
// Disable payment gateways if restricted product is in cart
function disable_gateways_for_restricted_products($available_gateways) {
if (!function_exists('WC') || !WC()->cart || WC()->cart->is_empty()) {
return $available_gateways;
}
foreach (WC()->cart->get_cart_contents() as $cart_item) {
$product = $cart_item['data'];
if (product_has_restricted_category($product->get_id(), 'bijna-verboden')) {
// Show notice once
if (!wc_has_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error')) {
wc_add_notice('π« This cart contains restricted products. Payment is disabled and your order will be placed on hold.', 'error');
}
// Remove all payment gateways
return [];
}
}
return $available_gateways;
}
—
### β 2. Now Test
– Add a product from `bijna-verboden` **or any of its subcategories**
– Go to checkout
– π³ All payment options disappear
– β οΈ Youβll see the notice: _βThis cart contains restricted products. Payment is disabledβ¦β_
—
### β This Fixes:
– Subcategory matching β
– Gateway hiding β
– Proper WooCommerce timing β
– Works with AJAX-enabled checkout β
—
Let me know if you want to:
– Allow **only one gateway** like Bank Transfer (instead of hiding all)
– Or apply this **only after a date (e.g. after June 28)**