run( ! $network_wide ); delete_transient( self::UPGRADE_ERROR_TRANSIENT ); Permissions::add_capabilities(); }; if ( $network_wide && is_multisite() ) { MultisiteInstaller::for_each_site( $install ); } else { $install(); } } /** * Remove runtime capabilities without deleting merchant data. */ public static function deactivate( $network_wide = false ): void { self::bootstrap(); $deactivate = static function (): void { // A network site may never have initialized Woo's scheduler tables. if ( function_exists( 'as_unschedule_all_actions' ) && ( ! is_multisite() || ! class_exists( 'ActionScheduler_StoreSchema' ) || get_option( 'schema-ActionScheduler_StoreSchema', false ) ) ) { as_unschedule_all_actions( 'ipscmi_order_cart_recovery_tick', [], 'ipscmi_order_cart_recovery' ); } Permissions::remove_capabilities(); }; if ( $network_wide && is_multisite() ) { MultisiteInstaller::for_each_site( $deactivate ); } else { $deactivate(); } } /** * Reconcile additive install tasks after WordPress replaces plugin files. */ public static function maybe_upgrade(): void { self::bootstrap(); $installer = new Installer(); if ( ! $installer->needs_upgrade() ) { delete_transient( self::UPGRADE_ERROR_TRANSIENT ); return; } if ( false !== get_transient( self::UPGRADE_ERROR_TRANSIENT ) ) { self::register_upgrade_failure_notice(); return; } try { $installer->maybe_upgrade(); Permissions::add_capabilities(); delete_transient( self::UPGRADE_ERROR_TRANSIENT ); } catch ( \Throwable $throwable ) { set_transient( self::UPGRADE_ERROR_TRANSIENT, [ 'time' => time(), 'message' => $throwable->getMessage(), ], 5 * MINUTE_IN_SECONDS ); error_log( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log sprintf( 'IPS Order Cart upgrade failed and will be retried: %s', $throwable->getMessage() ) ); self::register_upgrade_failure_notice(); } } /** * Report a retryable schema problem to managers without breaking the shop. */ private static function register_upgrade_failure_notice(): void { add_action( 'admin_notices', static function (): void { if ( ! current_user_can( 'manage_woocommerce' ) ) { return; } echo '

'; echo esc_html__( 'IPS Order Cart could not complete its database update. Storefront requests remain available, and the update will be retried automatically. Check the WooCommerce logs for details.', 'ips-order-cart' ); echo '

'; } ); } /** * Load the Composer graph and register constants required by lifecycle code. */ private static function bootstrap(): void { self::register_constants(); $autoload_file = dirname( __DIR__, 2 ) . '/vendor/autoload.php'; if ( is_readable( $autoload_file ) ) { require_once $autoload_file; } } /** * Register canonical constants before the runtime singleton is constructed. */ private static function register_constants(): void { $plugin_file = defined( 'IPSCMI_ORDER_CART_RUNTIME_FILE' ) ? IPSCMI_ORDER_CART_RUNTIME_FILE : dirname( __DIR__, 2 ) . '/ips-order-cart.php'; $headers = function_exists( 'get_file_data' ) ? get_file_data( $plugin_file, [ 'Version' => 'Version', 'Plugincore' => 'Plugincore', ] ) : []; $version = ! empty( $headers['Version'] ) ? (string) $headers['Version'] : '0.0.0'; $plugin_core = ! empty( $headers['Plugincore'] ) ? (string) $headers['Plugincore'] : '1.0.0'; Constants::register( $version, $plugin_core, $plugin_file ); } }