WooCommerce Order Status Role Restrictions
Control which WooCommerce order statuses each WordPress role is allowed or forbidden to select, with admin settings and server-side enforcement.
by Amirreza Shayesteh Far · github.com/amirrezashf/woocommerce-order-status-role-restrictions · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/amirrezashf/woocommerce-order-status-role-restrictions/archive/refs/heads/main.zipReadme
WooCommerce Order Status Role Restrictions
Control which WooCommerce order statuses each WordPress role is not allowed to select.
Overview
WooCommerce Order Status Role Restrictions adds role-based control to WooCommerce order status management.
Administrators with the manage_options capability can define, from a dedicated settings page, which order statuses are forbidden for each WordPress role. The plugin does not contain any hardcoded operational role names. Every available role is read dynamically from WordPress.
Restrictions are applied in two layers:
- Administration interface: prohibited statuses are disabled in WooCommerce's original status selector and supported button-based interfaces.
- Server-side enforcement: the requested status is checked again before WooCommerce saves the order.
The server-side check is important because a user could otherwise remove the HTML disabled attribute, disable JavaScript, or modify the submitted request.
Features
- Dynamic WordPress role detection
- No hardcoded role names
- Per-role restricted order statuses
- Users with
manage_optionsare always exempt - Dedicated settings page under WooCommerce
- Supports default and custom WooCommerce statuses
- Supports users with multiple roles
- Cumulative restrictions for multi-role users
- Disables restricted options in WooCommerce's original selector
- Supports
.fa-order-status-btncustom buttons - Supports
.wc-osb-btnfrom WooCommerce Order Status Buttons - Server-side protection against request manipulation
- Allows unrelated edits when an order already has a restricted status
- Supports classic WooCommerce order storage
- Supports WooCommerce HPOS
- Does not modify roles or capabilities
- Does not create custom database tables
- Stores all rules in one WordPress option
- Single-file plugin architecture
Why UI-Only Restrictions Are Not Enough
A disabled button improves usability but does not provide reliable authorization.
A user may attempt to bypass a visual restriction by:
- Disabling JavaScript
- Editing the page HTML
- Removing the
disabledattribute - Changing the submitted form value
- Sending a handcrafted POST request
- Using another administrative interface
For this reason, the plugin checks the transition again through WooCommerce's order object before the order is saved.
When an unauthorized transition is detected, the plugin restores the persisted order status. Other permitted order changes can still be saved.
Administrator Exemption
Users with the following capability are always exempt:
manage_options
This ensures the site administrator cannot accidentally lock themselves out of order statuses.
Roles that grant manage_options are not displayed on the settings page because restrictions would not affect them.
Settings Page
After activation, open:
WooCommerce → Order Status Access
The page displays an expandable card for every configurable WordPress role.
For each role:
- Open the role card.
- Select the statuses that must be forbidden.
- Save the settings.
A checked status means:
This role cannot select this order status.
The settings page includes:
- Role display name
- Internal role key
- Number of restricted statuses
- Expand and collapse controls
- Select-all control
- Clear-all control
- Status labels
- Internal status keys
- Responsive layout
Example Configuration
A saved configuration may look like:
array(
'shop_manager' => array(
'completed',
'refunded',
),
'support_agent' => array(
'cancelled',
'refunded',
),
);
In this example:
shop_managercannot selectcompletedorrefunded.support_agentcannot selectcancelledorrefunded.
Multi-Role Users
Restrictions are cumulative.
If one assigned role restricts completed and another assigned role restricts refunded, the user is restricted from both statuses.
This conservative behavior prevents a second role from unintentionally expanding access granted by another role.
Supported Order Statuses
Statuses are read through:
wc_get_order_statuses()
This normally includes:
- Pending payment
- Processing
- On hold
- Completed
- Cancelled
- Refunded
- Failed
- Compatible custom statuses
The plugin does not maintain a fixed status list.
Status-Key Normalization
WooCommerce may represent a status with or without the wc- prefix.
Examples:
wc-processing
processing
Both values are normalized to:
processing
This keeps rules consistent between the settings page, classic order storage, HPOS, the original selector, custom buttons, and server-side validation.
Administration Interface Enforcement
For restricted users, prohibited statuses are disabled in WooCommerce's original field:
<select id="order_status">
The plugin also supports these button interfaces:
<button class="fa-order-status-btn" data-value="completed">
<button class="wc-osb-btn" data-value="completed">
Restricted buttons receive:
- Disabled state
- Reduced opacity
aria-disabled- Explanatory tooltip
- Removed pointer interaction
Current Restricted Status
An order may already have a status that is restricted for the current user's role.
The plugin allows the user to save unrelated changes while the order remains in its already-persisted status. This prevents the order edit form from becoming unusable.
The user cannot transition another order into that restricted status.
Server-Side Enforcement Flow
Before WooCommerce saves an order, the plugin:
- Confirms that the request is inside WordPress administration.
- Exempts users with
manage_options. - Checks whether the order status has changed.
- Normalizes the target status key.
- Combines restrictions from all current user roles.
- Loads the persisted order status.
- Determines whether the requested transition is forbidden.
- Restores the persisted status when necessary.
- Allows other order changes to continue.
- Displays an administrator notice.
- Fires an optional action hook for audit integrations.
Supported Order Screens
Classic order storage
wp-admin/post.php?post=123&action=edit
WooCommerce HPOS
wp-admin/admin.php?page=wc-orders&action=edit&id=123
Data Storage
Rules are stored in one WordPress option:
wc_osrr_restriction_rules
The option uses a structure similar to:
array(
'role_key' => array(
'processing',
'completed',
),
);
Autoload is disabled for this option.
Temporary rejection notices use a short-lived transient:
wc_osrr_notice_USER_ID
The transient expires after one minute and is deleted after display.
Information Not Stored
The plugin does not store:
- Customer details
- Order contents
- Order status history
- User activity history
- IP addresses
- Browser information
- Analytics data
- External tracking identifiers
Requirements
- PHP 7.4 or later
- WordPress 6.0 or later
- WooCommerce
- An administrator with
manage_optionsto configure rules
Installation
- Download the plugin ZIP file.
- Open Plugins → Add New Plugin.
- Select Upload Plugin.
- Upload the ZIP file.
- Install and activate the plugin.
- Open WooCommerce → Order Status Access.
- Configure role restrictions.
- Save the settings.
Manual Installation
- Extract the plugin ZIP file.
- Upload the plugin folder to:
wp-content/plugins/
- Activate WooCommerce Order Status Role Restrictions.
- Open the settings page under WooCommerce.
File Structure
WooCommerce-Order-Status-Role-Restrictions/
├── woocommerce-order-status-role-restrictions.php
├── README.md
└── LICENSE
Security
The plugin includes:
- Direct-file access protection
manage_optionsrequirement for settings- WordPress nonce verification
- Sanitized role keys
- Sanitized status keys
- Validation against registered WordPress roles
- Validation against current WooCommerce statuses
- Server-side transition enforcement
- No public AJAX endpoint
- No custom REST API route
- No direct SQL queries
- No direct order-table access
- No modification of roles or capabilities
HPOS Compatibility
The plugin explicitly declares compatibility with WooCommerce High-Performance Order Storage.
All order operations use WooCommerce order objects. The plugin does not query or update order database tables directly.
Performance
Settings CSS and JavaScript load only on the plugin settings page.
Order restriction assets load only when:
- The user is editing an existing WooCommerce order
- The user does not have
manage_options - At least one status is restricted for one of the user's roles
No frontend assets are loaded.
Hooks and Filters
wc_osrr_rules
Filters normalized restriction rules after they are loaded.
add_filter(
'wc_osrr_rules',
static function ( $rules ) {
return $rules;
}
);
wc_osrr_configurable_roles
Filters roles displayed on the settings page.
add_filter(
'wc_osrr_configurable_roles',
static function ( $roles ) {
unset( $roles['subscriber'] );
return $roles;
}
);
wc_osrr_rules_saved
Runs after valid settings are saved.
add_action(
'wc_osrr_rules_saved',
static function ( $rules ) {
// Optional synchronization or audit logic.
}
);
wc_osrr_status_change_rejected
Runs when a forbidden status transition is rejected.
add_action(
'wc_osrr_status_change_rejected',
static function ( $order_id, $user_id, $target_status, $stored_status ) {
// Optional audit integration.
},
10,
4
);
Compatibility Notes
The following button selectors are supported directly:
.fa-order-status-btn
.wc-osb-btn
A different custom status interface may require an additional visual integration.
Server-side enforcement remains active even when a third-party interface is not visually disabled.
Limitations
- Restrictions apply to administrative order editing.
- Users with
manage_optionsare intentionally exempt. - The plugin does not replace WooCommerce capabilities.
- It does not hide orders from users.
- It does not hide status labels.
- It restricts transitions into selected statuses.
- Third-party order editors that bypass WooCommerce order objects may require integration.
- Unsupported custom JavaScript interfaces may need an additional selector for visual disabling.
Troubleshooting
A role does not appear
Roles with manage_options are excluded because they are exempt. A developer may also remove roles through wc_osrr_configurable_roles.
A custom status does not appear
Confirm that the status is registered before wc_get_order_statuses() runs and appears in WooCommerce's normal selector.
A restricted status is still visible
Statuses are disabled rather than removed. This keeps the current stored status stable and prevents broken order forms.
A custom button is not disabled
The custom interface may use another selector. Server-side enforcement still rejects the unauthorized transition.
The order already has a restricted status
The user can save unrelated order changes while the order remains in its current persisted status. The user cannot transition another order into that status.
Changelog
1.0.0
- Initial release
- Removed hardcoded role dependencies
- Added dynamic role discovery
- Added per-role restricted-status settings
- Added
manage_optionsexemption - Added multi-role cumulative restrictions
- Added original WooCommerce selector restrictions
- Added
.fa-order-status-btncompatibility - Added
.wc-osb-btncompatibility - Added server-side transition enforcement
- Added classic order edit-screen support
- Added HPOS order edit-screen support
- Added settings validation and nonce protection
- Added rejection notices
- Added public hooks and filters
License
GPL-3.0
https://www.gnu.org/licenses/gpl-3.0.html
Author
Amirreza Shayesteh Far
- Website: https://amirrezaa.ir/
- GitHub: https://github.com/amirrezashf
- Repository: https://github.com/amirrezashf/WooCommerce-Order-Status-Role-Restrictions
محدودسازی وضعیت سفارش ووکامرس بر اساس نقش
کنترل اینکه هر نقش وردپرس اجازه انتخاب کدام وضعیتهای سفارش ووکامرس را نداشته باشد.
معرفی
افزونه WooCommerce Order Status Role Restrictions امکان تعیین محدودیت وضعیت سفارش بر اساس نقشهای وردپرس را فراهم میکند.
مدیرانی که capability زیر را دارند میتوانند از طریق یک صفحه تنظیمات اختصاصی مشخص کنند که هر نقش از انتخاب کدام وضعیتهای سفارش منع شود:
manage_options
هیچ نام نقشی داخل افزونه hardcode نشده است. تمام نقشها بهصورت داینامیک از وردپرس خوانده میشوند.
محدودیتها در دو سطح اعمال میشوند:
- رابط مدیریت: وضعیتهای ممنوع در select اصلی ووکامرس و رابطهای دکمهای پشتیبانیشده غیرفعال میشوند.
- سمت سرور: پیش از ذخیره سفارش، وضعیت درخواستی دوباره بررسی میشود.
این کنترل سمت سرور مانع دور زدن محدودیت از طریق تغییر HTML، غیرفعال کردن JavaScript یا دستکاری درخواست میشود.
قابلیتها
- شناسایی داینامیک نقشهای وردپرس
- بدون نام نقش ثابت در کد
- تعیین وضعیتهای ممنوع برای هر نقش
- معافیت کاربران دارای
manage_options - صفحه تنظیمات اختصاصی زیرمنوی ووکامرس
- پشتیبانی از وضعیتهای پیشفرض و سفارشی
- پشتیبانی از کاربران دارای چند نقش
- ترکیب محدودیتهای تمام نقشهای کاربر
- غیرفعالسازی وضعیت در select اصلی ووکامرس
- سازگاری با
.fa-order-status-btn - سازگاری با
.wc-osb-btn - کنترل سمت سرور
- جلوگیری از دور زدن با درخواست دستی
- امکان ذخیره سایر تغییرات سفارش در وضعیت فعلی ممنوع
- پشتیبانی از ساختار کلاسیک سفارشها
- پشتیبانی از HPOS
- بدون تغییر role یا capability
- بدون جدول اختصاصی دیتابیس
- ذخیره قوانین در یک option
- معماری تکفایلی