| @@ -8,8 +8,9 @@ | ||
| 8 | 8 | namespace WCPOS\WooCommercePOS\Services\Settings; |
| 9 | 9 | |
| 10 | 10 | use WCPOS\WooCommercePOS\Interfaces\Settings_Section_Interface; |
| 11 | 11 | use WP_Error; |
| 12 | +use WP_User; | |
| 12 | 13 | |
| 13 | 14 | /** |
| 14 | 15 | * The Access Settings Section. |
| 15 | 16 | * |
| @@ -44,8 +45,49 @@ | ||
| 44 | 45 | public static function capability_names(): array { |
| 45 | 46 | $caps = self::get_caps(); |
| 46 | 47 | |
| 47 | 48 | return array_merge( $caps['wcpos'], $caps['wc'], $caps['wp'] ); |
| 49 | + } | |
| 50 | + | |
| 51 | + /** | |
| 52 | + * Capabilities the user can actually exercise, in the Access-settings vocabulary. | |
| 53 | + * | |
| 54 | + * The user_can() check is what every REST permission callback asks, so it is the | |
| 55 | + * answer the client must be given; it also runs the `user_has_cap` filter that | |
| 56 | + * role editors such as Members use to make a Deny on one role override a grant | |
| 57 | + * on another. The two singular meta caps (edit_product, delete_product) cannot | |
| 58 | + * go through user_can() without a post, so they are read from allcaps after the | |
| 59 | + * same filter has run. | |
| 60 | + * | |
| 61 | + * @param WP_User $user User to report on. | |
| 62 | + * | |
| 63 | + * @return string[] Capability names, in capability_names() order. | |
| 64 | + */ | |
| 65 | + public static function effective_capabilities( WP_User $user ): array { | |
| 66 | + $names = self::capability_names(); | |
| 67 | + // A multisite super admin holds every capability before the filter runs | |
| 68 | + // (WP_User::has_cap), so mirror that bypass for the two filtered names. | |
| 69 | + $super_admin = is_multisite() && is_super_admin( $user->ID ); | |
| 70 | + | |
| 71 | + return array_values( | |
| 72 | + array_filter( | |
| 73 | + $names, | |
| 74 | + function ( $cap ) use ( $user, $super_admin ) { | |
| 75 | + if ( ! in_array( $cap, array( 'edit_product', 'delete_product' ), true ) ) { | |
| 76 | + return user_can( $user, $cap ); | |
| 77 | + } | |
| 78 | + if ( $super_admin ) { | |
| 79 | + return true; | |
| 80 | + } | |
| 81 | + // Same argument shape as WP_User::has_cap(): the caps being | |
| 82 | + // checked, then the requested cap and user id. | |
| 83 | + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Core capability filter, run so role-editor denies apply. | |
| 84 | + $filtered = apply_filters( 'user_has_cap', $user->allcaps, array( $cap ), array( $cap, $user->ID ), $user ); | |
| 85 | + | |
| 86 | + return ! empty( $filtered[ $cap ] ); | |
| 87 | + } | |
| 88 | + ) | |
| 89 | + ); | |
| 48 | 90 | } |
| 49 | 91 | |
| 50 | 92 | /** |
| 51 | 93 | * Get capabilities grouped by type. |