| @@ -27,26 +27,60 @@ | ||
| 27 | 27 | /** |
| 28 | 28 | * Register client services |
| 29 | 29 | */ |
| 30 | 30 | public function register() { |
| 31 | - // Register actions and filters | |
| 32 | - add_action('after_setup_theme', [$this, 'registerClientRole']); | |
| 33 | - | |
| 31 | + // Register the `customer` role. | |
| 32 | + // | |
| 33 | + // This provider is constructed from easy_invoice_init(), which | |
| 34 | + // itself runs on init:10 — so hooking `after_setup_theme` (the | |
| 35 | + // original code) or `init` at priority 1 (the first fix) both | |
| 36 | + // registered a callback for a point WordPress had already passed, | |
| 37 | + // and the role was never created. On sites without WooCommerce | |
| 38 | + // (which also registers `customer`) the role stayed unregistered: | |
| 39 | + // WP_User::roles filtered it out as unknown, the Clients page fell | |
| 40 | + // back to a "Client" label, and Pro's Client Portal — which | |
| 41 | + // recognises a client by `in_array('customer', $user->roles)` — | |
| 42 | + // could not see the client at all. Register it now when `init` | |
| 43 | + // is already in progress, otherwise on init:1 as before. | |
| 44 | + if (did_action('init')) { | |
| 45 | + $this->registerClientRole(); | |
| 46 | + } else { | |
| 47 | + add_action('init', [$this, 'registerClientRole'], 1); | |
| 48 | + } | |
| 49 | + | |
| 34 | 50 | // Register client repository |
| 35 | 51 | $this->registerClientRepository(); |
| 36 | 52 | } |
| 37 | - | |
| 53 | + | |
| 38 | 54 | /** |
| 39 | - * Register client role if it doesn't exist | |
| 55 | + * Register client role if it doesn't exist. | |
| 56 | + * | |
| 57 | + * Idempotent — short-circuits when WooCommerce (or anything else) | |
| 58 | + * has already registered the role. Two implications worth knowing: | |
| 59 | + * | |
| 60 | + * 1. We register WITHOUT the `read` capability. On a site that | |
| 61 | + * never had WooCommerce, existing 'customer'-role users had no | |
| 62 | + * effective `read` cap because the role wasn't registered at | |
| 63 | + * all (and `WP_User::has_cap` couldn't pull `read` from a role | |
| 64 | + * that didn't exist). Registering with `['read' => true]` here | |
| 65 | + * would silently UPGRADE those users — granting wp-admin access | |
| 66 | + * they never had. We pass `[]` so the registration only fixes | |
| 67 | + * the display label, not the cap surface. | |
| 68 | + * | |
| 69 | + * 2. On a site WITH WooCommerce, WC has already registered | |
| 70 | + * 'customer' with its full cap set (including `read`). Our | |
| 71 | + * add_role() is a no-op there — get_role() returns truthy and | |
| 72 | + * we bail. WC customers retain WC's caps unchanged. | |
| 40 | 73 | */ |
| 41 | 74 | public function registerClientRole() { |
| 42 | - $role = get_role('customer'); | |
| 43 | - | |
| 44 | - if (!$role) { | |
| 45 | - add_role('customer', __('Customer', 'easy-invoice'), [ | |
| 46 | - 'read' => true, | |
| 47 | - ]); | |
| 75 | + if (get_role('customer')) { | |
| 76 | + return; | |
| 48 | 77 | } |
| 78 | + add_role( | |
| 79 | + 'customer', | |
| 80 | + __('Customer', 'easy-invoice'), | |
| 81 | + [] | |
| 82 | + ); | |
| 49 | 83 | } |
| 50 | 84 | |
| 51 | 85 | /** |
| 52 | 86 | * Register client repository |