Why they exist
Every state-changing order action in mam-woocommerce is deny by default: the acting user is resolved server-side (from the app session/token, never from request parameters) and must pass an ownership or role check before anything happens. These filters are the documented escape hatch for site setups the built-in rules don’t fit — e.g. a concierge role that cancels orders for customers.
The default rules
| Scope | Allowed when… |
|---|---|
| (always) | the user has the manage_woocommerce capability |
| customer actions (cancel, feedback, refund) | the user is the order’s customer |
| fulfillment actions (change status, complete) | the user is staff of a vendor that owns one of the order’s line items (Product Vendors stores) |
The filters
All receive the order action’s current answer first and must return a boolean.
| Filter | Signature | Fires |
|---|---|---|
mam_wc_user_can_change_order_status |
( bool $allowed, int $user_id, int $order_id ) |
on every vendor status-change form submission (single and multi-order — once per order). Can grant or veto. |
mam_wc_user_can_complete_order |
( bool $allowed, int $user_id, int $order_id ) |
on the vendor complete-order form submission. Can grant or veto. |
mam_wc_user_can_cancel_order |
( bool $allowed, int $user_id, int $order_id ) |
on a customer cancel-order form submission. Can grant or veto. |
mam_wc_user_can_submit_order_feedback |
( bool $allowed, int $user_id, int $order_id ) |
on a customer feedback submission. Can grant or veto. |
mam_wc_user_can_refund_order |
( bool $allowed, int $user_id, int $order_id ) |
inside the refund-allowed check, only after the ownership/manager checks have failed ($allowed is always false here). Grant-only — the policy checks (order status, Refund settings) still apply afterward. |
mam_wc_user_can_submit_order |
( bool $allowed, int $user_id ) |
at the start of order creation, only when no customer could be resolved for the request ($allowed is false, $user_id is 0 or the unresolved id). Grant-only, and note it has no order id — the order doesn’t exist yet. |
A denial returns a Not authorized failure to the app and suppresses the action’s notifications.
Example — let a support role cancel any order
add_filter( 'mam_wc_user_can_cancel_order', function ( $allowed, $user_id, $order_id ) {
if ( ! $allowed && user_can( $user_id, 'mam_support_agent' ) ) {
$allowed = true;
}
return $allowed;
}, 10, 3 );
Example — veto self-completion under a dollar threshold
add_filter( 'mam_wc_user_can_complete_order', function ( $allowed, $user_id, $order_id ) {
$order = wc_get_order( $order_id );
if ( $allowed && $order && $order->get_total() > 500 && ! user_can( $user_id, 'manage_woocommerce' ) ) {
$allowed = false; // big orders need a manager
}
return $allowed;
}, 10, 3 );
Notes
- Be conservative: these gates are the security boundary for app-driven order changes. Grant on role/capability, never on request data.
$user_idis the server-resolved acting user;0means no user could be resolved.
Related articles
- Plugin: mam-woocommerce
- Hook:
mam_wc_is_refund_allowed - Recipe: Configure the cancel, feedback, and refund forms
Metadata
| Field | Value |
|---|---|
| Article type | Hook Reference |
| Plugin slug | mam-woocommerce |
| Applies to plugin version | 26.19.3+ |
| Category | Extending MAM Suite |
| Hook type | filters |
| Audience | PHP developer |
| Last verified | 2026-06-10 |
