' . esc_html__( 'Two copies of Agent Adapt are installed.', 'agent-adapt' ) . ' ' . esc_html( sprintf( /* translators: 1: the folder that is running, 2: the folder that is dormant */ __( 'Only one can run, so “%1$s” is active and “%2$s” is doing nothing. Deactivate and delete the one you do not want.', 'agent-adapt' ), basename( dirname( AGENTADAPT_FILE ) ), basename( __DIR__ ) ) ) . '

'; } ); return; } define( 'AGENTADAPT_VERSION', '0.6.1' ); // Header + constant + readme.txt Stable tag move together (version-gate). define( 'AGENTADAPT_FILE', __FILE__ ); define( 'AGENTADAPT_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); define( 'AGENTADAPT_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); // The three floors. Each is stated more than once (header, readme, CI matrix, // KB) and ops/ci/wc-floor-check.py compares the copies, because instance #2 // shipped with its WooCommerce header and its gate disagreeing. define( 'AGENTADAPT_MIN_PHP', '8.1' ); define( 'AGENTADAPT_MIN_WP', '6.8' ); define( 'AGENTADAPT_MIN_WC', '10.0' ); /** * Check PHP, WordPress and WooCommerce WITHOUT loading anything else, and * without translating anything: this runs on `plugins_loaded`, before `init`, * where WordPress 6.7+ warns about loading translations. * * @return array|null Null when compatible, else array( what, required, running ). */ function agentadapt_compatibility_problem() { if ( version_compare( PHP_VERSION, AGENTADAPT_MIN_PHP, '<' ) ) { return array( 'php', AGENTADAPT_MIN_PHP, PHP_VERSION ); } if ( version_compare( get_bloginfo( 'version' ), AGENTADAPT_MIN_WP, '<' ) ) { return array( 'wordpress', AGENTADAPT_MIN_WP, get_bloginfo( 'version' ) ); } if ( ! defined( 'WC_VERSION' ) ) { return array( 'woocommerce-missing', AGENTADAPT_MIN_WC, '' ); } if ( version_compare( WC_VERSION, AGENTADAPT_MIN_WC, '<' ) ) { return array( 'woocommerce', AGENTADAPT_MIN_WC, WC_VERSION ); } return null; } /** * The problem as a sentence for an administrator. Translated, so call it only * from `init` onwards (admin notices are). * * @return string Empty string when compatible, else the reason. */ function agentadapt_incompatibility_reason() { $problem = agentadapt_compatibility_problem(); if ( null === $problem ) { return ''; } list( $what, $required, $running ) = $problem; switch ( $what ) { case 'php': /* translators: 1: required PHP version, 2: running PHP version */ return sprintf( __( 'Agent Adapt requires PHP %1$s or newer. This site runs PHP %2$s.', 'agent-adapt' ), $required, $running ); case 'wordpress': /* translators: 1: required WordPress version, 2: running WordPress version */ return sprintf( __( 'Agent Adapt requires WordPress %1$s or newer. This site runs WordPress %2$s.', 'agent-adapt' ), $required, $running ); case 'woocommerce-missing': return __( 'Agent Adapt requires WooCommerce to be installed and active.', 'agent-adapt' ); default: /* translators: 1: required WooCommerce version, 2: running WooCommerce version */ return sprintf( __( 'Agent Adapt requires WooCommerce %1$s or newer. This site runs WooCommerce %2$s.', 'agent-adapt' ), $required, $running ); } } /** * WooCommerce feature compatibility. * * Declared here, not lazily, because WooCommerce reads declarations during * `before_woocommerce_init`, before this plugin boots. HPOS is true by rule: * every order read or write goes through WooCommerce CRUD, never a post query * (CLAUDE.md), and tests/plugin/assertions.php asserts the declaration landed. */ add_action( 'before_woocommerce_init', function () { if ( ! class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) { return; } \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', AGENTADAPT_FILE, true ); \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', AGENTADAPT_FILE, true ); } ); /** * Boot once WooCommerce has loaded: `plugins_loaded` priority 20 is after * WooCommerce defines WC_VERSION and before `init`. */ add_action( 'plugins_loaded', function () { if ( null !== agentadapt_compatibility_problem() ) { add_action( 'admin_notices', function () { // Only on the Plugins screen, where the store owner manages it (Guideline 11). if ( ! current_user_can( 'activate_plugins' ) || 'plugins.php' !== ( $GLOBALS['pagenow'] ?? '' ) ) { return; } echo '

Agent Adapt — ' . esc_html( agentadapt_incompatibility_reason() ) . '

'; } ); return; } require_once AGENTADAPT_PLUGIN_DIR . 'includes/class-agentadapt-plugin.php'; AgentAdapt_Plugin::boot(); }, 20 ); /** * Activation: create the schema. An incompatible environment activates inert; * the admin notice explains why, and the schema is created on the first * compatible boot instead (AgentAdapt_Schema::maybe_upgrade()). */ register_activation_hook( __FILE__, function () { if ( null !== agentadapt_compatibility_problem() ) { return; } require_once AGENTADAPT_PLUGIN_DIR . 'includes/class-agentadapt-plugin.php'; AgentAdapt_Plugin::activate(); } ); register_deactivation_hook( __FILE__, function () { wp_clear_scheduled_hook( 'agentadapt_maintenance' ); } );