PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 2.3.0
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v2.3.0
2.3.2 2.3.1 2.3.0 2.2.8 2.2.7 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.11.0 1.11.1 1.11.2 1.6 1.7 1.8 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 1.9.10 1.9.11 All 60 releases
merchant / inc / abilities / class-merchant-abilities-permissions.php

class-merchant-abilities-permissions.php in Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant 2.3.0, at inc/abilities/class-merchant-abilities-permissions.php

134 lines 3.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Merchant Abilities Permissions.
4 *
5 * Permission callback functions for WP Abilities API.
6 * Enforces two layers: MCP write access guard + WP capability checks.
7 *
8 * @package Merchant
9 * @since 2.3.0
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 }
15
16 /**
17 * Merchant_Abilities_Permissions
18 *
19 * Provides permission callbacks for each Merchant ability.
20 * Write abilities check the `wpvibe_mcp_write_access` toggle
21 * BEFORE checking WP capabilities. Read abilities bypass
22 * the write access guard entirely.
23 *
24 * Uses Merchant_Option::get() (no filter) for the permission
25 * check — this is a conscious choice to avoid third-party
26 * code overriding the security toggle via the
27 * `merchant_get_option` filter.
28 *
29 * @since 2.3.0
30 */
31 class Merchant_Abilities_Permissions {
32
33 /**
34 * Abilities that require write access to be enabled.
35 *
36 * @var array<int, string>
37 */
38 private static $write_abilities = array(
39 'merchant/toggle-module',
40 'merchant/update-module-settings',
41 'merchant/create-campaign',
42 'merchant/update-campaign',
43 'merchant/delete-campaign',
44 );
45
46 /**
47 * Register an ability id as requiring write access.
48 *
49 * Push-only: appends the id if it isn't already tracked. There is
50 * no counterpart to remove an id — shrinking the write gate is not
51 * exposed, since the contribution hook that calls this can re-fire
52 * on every request and must stay idempotent.
53 *
54 * @param string $id The ability identifier (e.g. 'merchant/create-bundle').
55 *
56 * @return void
57 */
58 public static function register_write_ability( $id ) {
59 if ( ! in_array( $id, self::$write_abilities, true ) ) {
60 self::$write_abilities[] = $id;
61 }
62 }
63
64 /**
65 * Get the abilities currently gated by write access.
66 *
67 * @return array<int, string>
68 */
69 public static function get_write_abilities() {
70 return self::$write_abilities;
71 }
72
73 /**
74 * Check if MCP write access is enabled.
75 *
76 * Reads from Merchant_Option::get() (no filter) to avoid
77 * third-party code overriding this security check.
78 *
79 * @return bool
80 */
81 public static function is_write_access_enabled() {
82 return (bool) Merchant_Option::get( 'global-settings', 'wpvibe_mcp_write_access', false );
83 }
84
85 /**
86 * Permission callback for a given ability.
87 *
88 * @param string $ability_id The ability identifier (e.g. 'merchant/toggle-module').
89 *
90 * @return bool|WP_Error True if allowed, WP_Error if denied.
91 */
92 public static function check( $ability_id ) {
93 // Step 1: Write access guard (before capability check).
94 if ( in_array( $ability_id, self::$write_abilities, true ) && ! self::is_write_access_enabled() ) {
95 return new WP_Error(
96 'write_access_disabled',
97 __( 'MCP write access is disabled. Enable it in Merchant → Global Settings → WPVibe banner.', 'merchant' ),
98 array( 'status' => 403 )
99 );
100 }
101
102 // Step 2: WordPress capability check.
103 $capability = self::get_required_capability( $ability_id );
104
105 if ( ! current_user_can( $capability ) ) {
106 return new WP_Error(
107 'ability_forbidden',
108 __( 'You do not have permission to perform this action.', 'merchant' ),
109 array( 'status' => 403 )
110 );
111 }
112
113 return true;
114 }
115
116 /**
117 * Get the required WordPress capability for an ability.
118 *
119 * toggle-module requires manage_options (system-level).
120 * All other abilities require manage_woocommerce (shop manager scope).
121 *
122 * @param string $ability_id The ability identifier.
123 *
124 * @return string The WordPress capability slug.
125 */
126 private static function get_required_capability( $ability_id ) {
127 if ( 'merchant/toggle-module' === $ability_id ) {
128 return 'manage_options';
129 }
130
131 return 'manage_woocommerce';
132 }
133 }
134