true ) ); } ); /* * Stand down when another copy of this plugin is already loaded. * * WordPress activates a plugin by including its entry file in a request where * the already-active plugins are loaded too (plugin_sandbox_scrape()). Two * copies in two folders -- an upgrade installed alongside the running one, or * Free alongside the paid edition -- therefore reach this file twice in one * process. Without this guard the second include dies on the first function * declaration below with "Cannot redeclare * ai_o_optimiser_meets_minimum_requirements()", and WordPress reports only * "Plugin could not be activated because it triggered a fatal error." * * This is the ordinary-page-load half of the protection; the closure above * is the activation-time half, and covers the case this guard alone cannot: * whichever copy stands down here never reaches its own activation hook, so * without the closure above, activating this edition while the sibling is * already active would succeed silently, with no refusal at all, whenever * this copy happens to be the one that stands down (which the sort-order * mistake above meant was every real install). * * tests/plugin-path-activation-collision.php pins the redeclaration half; * tests/core-pro-addon-coexistence.php pins the sibling-refusal half. */ if ( defined( 'AI_O_Optimiser_VERSION' ) ) { add_action( 'admin_notices', function () { if ( ! current_user_can( 'activate_plugins' ) ) { return; } echo '

' . sprintf( /* translators: 1: version of the copy that is running, 2: file path of the copy that stood down. */ esc_html__( 'Two copies of AI-O Optimiser are installed. Version %1$s loaded first and is running; the copy at %2$s has stood down to avoid a fatal error. Deactivate and delete whichever copy you do not want, then reactivate the other.', 'ai-o-optimiser' ), esc_html( AI_O_Optimiser_VERSION ), esc_html( str_replace( ABSPATH, '', __FILE__ ) ) ) . '

'; } ); return; } define( 'AI_O_Optimiser_MIN_WP_VERSION', '6.9' ); define( 'AI_O_Optimiser_NATIVE_AI_MIN_WP_VERSION', '7.0' ); define( 'AI_O_Optimiser_MIN_PHP_VERSION', '8.0' ); define( 'AI_O_Optimiser_VERSION', '1.39.7' ); define( 'AI_O_Optimiser_PRODUCT_NAME', 'AI-O Optimiser' ); define( 'AI_O_Optimiser_PLUGIN_FILE', __FILE__ ); define( 'AI_O_Optimiser_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); define( 'AI_O_Optimiser_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); define( 'AI_O_Optimiser_TABLE_NAME', 'ai_o_optimiser_crawler_log' ); define( 'AI_O_Optimiser_NIGHTLY_HEALTH_HOOK', 'ai_o_optimiser_nightly_health_check' ); define( 'AI_O_Optimiser_SENSITIVE_CAPABILITY', 'manage_ai_o_optimiser_sensitive' ); // Mirrors AI_O_Optimiser_Migration::STATE_OPTION. Declared here so the upgrade // gate can read it without paying the parse cost of the migration class on // every request. tests/migration-upgrade-ordering.php asserts the two match. define( 'AI_O_Optimiser_MIGRATION_STATE_OPTION', 'ai_o_optimiser_migration_1203' ); /* * Declarations live in the runtime file, not here, so the guard above can work * at all -- see the comment at the top of that file. */ require_once AI_O_Optimiser_PLUGIN_DIR . 'includes/ai-o-optimiser-runtime.php';