Architecture
The plugin uses PHP namespaces (MaxtDesign\DisableRestApi) and strict typing throughout.
Class Structure
class-plugin.php) — Singleton bootstrap. Manages activation, deactivation, and component initialization with dependency injection.class-rest-controller.php) — Core logic. Hooks into rest_authentication_errors at priority 99. Handles authenticated vs unauthenticated request flow.class-settings.php) — Admin settings page. Form handling, endpoint tree rendering, import/export, and input sanitization.class-role-manager.php) — Role queries and per-role restriction helpers.class-logger.php) — Placeholder for future request logging (Tier 2 / Pro feature).Constants
MDRA_VERSION // '1.0.0'
MDRA_PLUGIN_FILE // Main plugin file path
MDRA_PLUGIN_DIR // Plugin directory path
MDRA_PLUGIN_URL // Plugin URL for assets
MDRA_PLUGIN_BASENAME // Plugin basename for hooksAutoloader
PSR-4 style autoloader maps MaxtDesign\DisableRestApi\ClassName to includes/class-classname.php.
Settings Schema
Stored as a single serialized option: mdra_settings (autoloaded)
[
'disable_rest_api' => true, // bool
'error_message' => 'REST API...', // string
'allow_logged_in' => true, // bool
'whitelisted_endpoints' => [], // string[]
'role_restrictions' => [ // array
'subscriber' => [
'restricted' => true, // bool
'whitelisted_endpoints' => [], // string[]
],
],
]Filters
mdra_is_route_whitelisted
Programmatically whitelist routes that aren't in the settings UI.
add_filter('mdra_is_route_whitelisted', function(bool $is_whitelisted, string $route, array $whitelist): bool {
// Always allow a custom endpoint
if (str_starts_with($route, 'my-plugin/v1/')) {
return true;
}
return $is_whitelisted;
}, 10, 3);mdra_rest_error_response
Customize the error response returned to blocked requests.
add_filter('mdra_rest_error_response', function(WP_Error $error, array $settings): WP_Error {
// Change status code to 403
return new WP_Error('forbidden', 'Access denied', ['status' => 403]);
}, 10, 2);mdra_logging_enabled
Enable request logging (future feature, Logger class is a placeholder).
add_filter('mdra_logging_enabled', '__return_true');REST Authentication Flow
The filter runs at priority 99 on rest_authentication_errors:
Request → rest_authentication_errors (priority 99)
├── Previous auth error? → Pass through
├── API disabled? No → Allow
├── Can't determine route? → Allow
├── User logged in?
│ ├── allow_logged_in enabled?
│ │ ├── Check per-role restrictions
│ │ │ ├── Role restricted + route whitelisted → Allow
│ │ │ ├── Role restricted + not whitelisted → Block (401)
│ │ │ └── Role not restricted → Allow
│ │ └── No roles → Allow
│ └── allow_logged_in disabled?
│ ├── Role explicitly unrestricted → Allow
│ ├── Role restricted + whitelisted → Allow
│ └── Otherwise → Check global whitelist
└── Not logged in?
├── Route in global whitelist → Allow
└── Not whitelisted → Block (401)Route Matching
The is_route_whitelisted method supports:
contact-form-7 matches contact-form-7wc/store matches wc/store/cart, wc/store/products, etc.Routes are normalized by stripping leading slashes before comparison.
Asset Loading
Admin CSS and JS load only when $hook_suffix matches the plugin's settings page. No assets load on any other admin page or on the frontend.
Asset handles:
mdra-settings (CSS)mdra-settings (JS)Uninstall
uninstall.php deletes mdra_settings from wp_options. On multisite, iterates all sites and cleans each one.