| @@ -38,11 +38,8 @@ | ||
| 38 | 38 | */ |
| 39 | 39 | public function __construct() { |
| 40 | 40 | register_activation_hook( PLUGIN_FILE, array( $this, 'activate' ) ); |
| 41 | 41 | add_action( 'wpmu_new_blog', array( $this, 'activate_new_site' ) ); |
| 42 | - // The staff-account rule (#1918, #2104) must hold even when WooCommerce is | |
| 43 | - // inactive and Init never starts; it depends on nothing from WooCommerce. | |
| 44 | - add_filter( 'map_meta_cap', array( Services\Permission_Rules::class, 'map_user_meta_caps' ), 10, 4 ); | |
| 45 | 42 | add_action( 'plugins_loaded', array( $this, 'init' ) ); |
| 46 | 43 | } |
| 47 | 44 | |
| 48 | 45 | /** |
| @@ -101,28 +98,11 @@ | ||
| 101 | 98 | /** |
| 102 | 99 | * Fired when the plugin is activated. |
| 103 | 100 | * |
| 104 | 101 | * @param bool $install_sync_schema Whether to install the sync schema. |
| 105 | - * @param bool $full_role_sync Whether to repair all default role capabilities. | |
| 106 | 102 | */ |
| 107 | - public function single_activate( bool $install_sync_schema = true, bool $full_role_sync = true ): void { | |
| 108 | - $role_capabilities = self::role_capability_definition(); | |
| 109 | - $capability_names = $role_capabilities; | |
| 110 | - $capability_names['cashier'] = array_merge( array( 'access_woocommerce_pos' ), array_keys( $role_capabilities['cashier'] ) ); | |
| 111 | - $synced = get_option( 'woocommerce_pos_role_caps_synced', false ); | |
| 112 | - if ( ! $full_role_sync && false === $synced && get_option( 'woocommerce_pos_role_caps_fingerprint' ) === $this->role_caps_fingerprint() ) { | |
| 113 | - $synced = $capability_names; | |
| 114 | - } | |
| 115 | - // An upgrade grants only capabilities new to the definition since the | |
| 116 | - // last sync, so a capability the merchant removed on the Access screen | |
| 117 | - // stays removed. Explicit activation still repairs every default. | |
| 118 | - $granted = $capability_names; | |
| 119 | - if ( ! $full_role_sync && \is_array( $synced ) ) { | |
| 120 | - foreach ( $granted as $slug => $capabilities ) { | |
| 121 | - $already = isset( $synced[ $slug ] ) && \is_array( $synced[ $slug ] ) ? $synced[ $slug ] : array(); | |
| 122 | - $granted[ $slug ] = array_values( array_diff( $capabilities, $already ) ); | |
| 123 | - } | |
| 124 | - } | |
| 103 | + public function single_activate( bool $install_sync_schema = true ): void { | |
| 104 | + $role_capabilities = self::role_capability_definition(); | |
| 125 | 105 | |
| 126 | 106 | // Reseed the default template terms on the next request: (re)activation |
| 127 | 107 | // is the repair a merchant reaches for after deleting a term by hand. |
| 128 | 108 | // This also runs once per upgrade (version_check re-activates to sync |
| @@ -135,15 +115,15 @@ | ||
| 135 | 115 | self::autoload_request_latches(); |
| 136 | 116 | Admin\Permalink::ensure_default(); |
| 137 | 117 | |
| 138 | 118 | // create POS specific roles. |
| 139 | - $this->create_pos_roles( $granted['cashier'] ); | |
| 119 | + $this->create_pos_roles(); | |
| 140 | 120 | |
| 141 | 121 | // add pos capabilities to non POS roles. |
| 142 | 122 | $this->add_pos_capability( |
| 143 | 123 | array( |
| 144 | - 'administrator' => $granted['administrator'], | |
| 145 | - 'shop_manager' => $granted['shop_manager'], | |
| 124 | + 'administrator' => $role_capabilities['administrator'], | |
| 125 | + 'shop_manager' => $role_capabilities['shop_manager'], | |
| 146 | 126 | ) |
| 147 | 127 | ); |
| 148 | 128 | |
| 149 | 129 | $stored_roles = get_option( wp_roles()->role_key, array() ); |
| @@ -148,14 +128,13 @@ | ||
| 148 | 128 | |
| 149 | 129 | $stored_roles = get_option( wp_roles()->role_key, array() ); |
| 150 | 130 | $roles_are_persisted = is_array( $stored_roles ); |
| 151 | 131 | if ( $roles_are_persisted ) { |
| 152 | - foreach ( $granted as $slug => $capabilities ) { | |
| 153 | - if ( ! isset( $stored_roles[ $slug ] ) ) { | |
| 154 | - $roles_are_persisted = false; | |
| 155 | - break; | |
| 156 | - } | |
| 157 | - foreach ( $capabilities as $capability ) { | |
| 132 | + foreach ( $role_capabilities as $slug => $capabilities ) { | |
| 133 | + $required_capabilities = 'cashier' === $slug | |
| 134 | + ? array_merge( array( 'access_woocommerce_pos' ), array_keys( $capabilities ) ) | |
| 135 | + : $capabilities; | |
| 136 | + foreach ( $required_capabilities as $capability ) { | |
| 158 | 137 | if ( empty( $stored_roles[ $slug ]['capabilities'][ $capability ] ) ) { |
| 159 | 138 | $roles_are_persisted = false; |
| 160 | 139 | break 2; |
| 161 | 140 | } |
| @@ -164,11 +143,8 @@ | ||
| 164 | 143 | } |
| 165 | 144 | |
| 166 | 145 | $obsolete_customer_create_cap = isset( $role_capabilities['cashier']['create_customers'] ) ? 'promote_users' : 'create_customers'; |
| 167 | 146 | if ( $roles_are_persisted && empty( $stored_roles['cashier']['capabilities'][ $obsolete_customer_create_cap ] ) ) { |
| 168 | - // Snapshot first: a fingerprint that advanced past a failed snapshot | |
| 169 | - // write would never retry it. | |
| 170 | - update_option( 'woocommerce_pos_role_caps_synced', $capability_names, true ); | |
| 171 | 147 | update_option( 'woocommerce_pos_role_caps_fingerprint', $this->role_caps_fingerprint(), true ); |
| 172 | 148 | } |
| 173 | 149 | |
| 174 | 150 | // Flag the consent pop-up for the next admin page load. Done here |
| @@ -336,10 +312,9 @@ | ||
| 336 | 312 | $plugin_needs_upgrade = version_compare( $old, VERSION, '<' ); |
| 337 | 313 | $sync_needs_upgrade = Sync_Api::SCHEMA_VERSION !== get_option( Sync_Api::SCHEMA_OPTION, null ); |
| 338 | 314 | |
| 339 | 315 | $role_caps_fingerprint = $this->role_caps_fingerprint(); |
| 340 | - $role_caps_need_sync = get_option( 'woocommerce_pos_role_caps_fingerprint' ) !== $role_caps_fingerprint | |
| 341 | - || false === get_option( 'woocommerce_pos_role_caps_synced' ); | |
| 316 | + $role_caps_need_sync = get_option( 'woocommerce_pos_role_caps_fingerprint' ) !== $role_caps_fingerprint; | |
| 342 | 317 | if ( ! $plugin_needs_upgrade && ! $sync_needs_upgrade && ! $role_caps_need_sync ) { |
| 343 | 318 | return; |
| 344 | 319 | } |
| 345 | 320 | |
| @@ -351,10 +326,9 @@ | ||
| 351 | 326 | $locked_plugin_needs_upgrade = version_compare( $locked_old, VERSION, '<' ); |
| 352 | 327 | $locked_sync_needs_upgrade = Sync_Api::SCHEMA_VERSION !== get_option( Sync_Api::SCHEMA_OPTION, null ); |
| 353 | 328 | |
| 354 | 329 | $locked_role_caps_fingerprint = $this->role_caps_fingerprint(); |
| 355 | - $locked_role_caps_need_sync = get_option( 'woocommerce_pos_role_caps_fingerprint' ) !== $locked_role_caps_fingerprint | |
| 356 | - || false === get_option( 'woocommerce_pos_role_caps_synced' ); | |
| 330 | + $locked_role_caps_need_sync = get_option( 'woocommerce_pos_role_caps_fingerprint' ) !== $locked_role_caps_fingerprint; | |
| 357 | 331 | if ( ! $locked_plugin_needs_upgrade && ! $locked_sync_needs_upgrade && ! $locked_role_caps_need_sync ) { |
| 358 | 332 | $this->release_db_upgrade_lock(); |
| 359 | 333 | return; |
| 360 | 334 | } |
| @@ -372,9 +346,9 @@ | ||
| 372 | 346 | // requires translations to be loaded (WordPress 6.7+). |
| 373 | 347 | add_action( |
| 374 | 348 | 'init', |
| 375 | 349 | function () { |
| 376 | - $this->single_activate( false, false ); | |
| 350 | + $this->single_activate( false ); | |
| 377 | 351 | } |
| 378 | 352 | ); |
| 379 | 353 | } |
| 380 | 354 | |
| @@ -539,13 +513,10 @@ | ||
| 539 | 513 | } |
| 540 | 514 | |
| 541 | 515 | /** |
| 542 | 516 | * Add POS specific roles. |
| 543 | - * | |
| 544 | - * @param string[]|null $capabilities Capability names to sync onto an existing role, or null for | |
| 545 | - * every default. A missing role is always created with the full set. | |
| 546 | 517 | */ |
| 547 | - private function create_pos_roles( ?array $capabilities = null ): void { | |
| 518 | + private function create_pos_roles(): void { | |
| 548 | 519 | $role_capabilities = self::role_capability_definition(); |
| 549 | 520 | $cashier_capabilities = $role_capabilities['cashier']; |
| 550 | 521 | |
| 551 | 522 | add_role( |
| @@ -551,11 +522,9 @@ | ||
| 551 | 522 | add_role( |
| 552 | 523 | 'cashier', |
| 553 | 524 | /* translators: Plugin activation notice label. */ |
| 554 | 525 | __( 'Cashier', 'woocommerce-pos' ), |
| 555 | - // A missing role is created whole, access gate included, whatever | |
| 556 | - // subset an incremental upgrade asked to sync. | |
| 557 | - array_merge( array( 'access_woocommerce_pos' => true ), $cashier_capabilities ) | |
| 526 | + $cashier_capabilities | |
| 558 | 527 | ); |
| 559 | 528 | |
| 560 | 529 | $obsolete_customer_create_cap = isset( $cashier_capabilities['create_customers'] ) ? 'promote_users' : 'create_customers'; |
| 561 | 530 | $cashier = get_role( 'cashier' ); |
| @@ -562,14 +531,14 @@ | ||
| 562 | 531 | if ( $cashier ) { |
| 563 | 532 | $cashier->remove_cap( $obsolete_customer_create_cap ); |
| 564 | 533 | } |
| 565 | 534 | |
| 566 | - // Sync the requested capabilities to the role. add_role() is a no-op when | |
| 535 | + // Sync all capabilities to the existing role. add_role() is a no-op when | |
| 567 | 536 | // the role already exists, so capabilities added in newer versions would |
| 568 | 537 | // never reach existing installs without this. |
| 569 | 538 | $this->add_pos_capability( |
| 570 | 539 | array( |
| 571 | - 'cashier' => $capabilities ?? array_merge( | |
| 540 | + 'cashier' => array_merge( | |
| 572 | 541 | array( 'access_woocommerce_pos' ), |
| 573 | 542 | array_keys( $cashier_capabilities ) |
| 574 | 543 | ), |
| 575 | 544 | ) |