%s

', esc_html( sprintf( /* translators: 1: required PHP version, 2: current PHP version. */ __( '404 to 301 requires PHP %1$s or higher. Your site is running PHP %2$s.', '404-to-301' ), '7.4', PHP_VERSION ) ) ); } ); return; } /* * Plugin constants. * * Defined once here so every other class can read the plugin's * version, paths and URLs without re-deriving them from `__FILE__`. */ // Plugin version (kept in sync with the `Version:` header above). define( 'D404_VERSION', '4.0.1' ); // Database schema version. Bumped only when migrations change. define( 'D404_DB_VERSION', '4.0.0' ); // Absolute path to this bootstrap file. define( 'D404_FILE', __FILE__ ); // Absolute plugin directory path (with a trailing slash). define( 'D404_DIR', plugin_dir_path( __FILE__ ) ); // Plugin directory URL (with a trailing slash). define( 'D404_URL', plugin_dir_url( __FILE__ ) ); // Plugin base name (e.g. `404-to-301/404-to-301.php`). define( 'D404_BASE_NAME', plugin_basename( __FILE__ ) ); /* * Composer autoloader. * * Generated by `composer install` / `composer dump-autoload -o`. Uses a * classmap (not PSR-4) because the plugin keeps the WordPress-style * `class-foo.php` filenames — Composer scans `includes/` once at build * time and writes a lookup table for every class found. * * If the autoloader is missing (a checkout that has never had * `composer install` run on it), bail with a clear admin notice so the * failure is obvious rather than silent. */ if ( ! file_exists( __DIR__ . '/vendor/autoload.php' ) ) { add_action( 'admin_notices', function () { printf( '

%s

', esc_html__( '404 to 301: Composer dependencies are missing. Run `composer install` inside the plugin directory.', '404-to-301' ) ); } ); return; } require_once __DIR__ . '/vendor/autoload.php'; /* * Global helper functions. * * Loaded here (not via Composer's `files` autoload) so the file is only * included inside a real WordPress request — its `ABSPATH` guard would * otherwise terminate any CLI tool (PHPCS, PHPUnit, …) that loads * vendor/autoload.php outside WordPress. */ require_once __DIR__ . '/includes/functions.php'; // Lifecycle hooks — handled by their dedicated classes inside the Setup namespace. register_activation_hook( __FILE__, array( 'DuckDev\FourNotFour\Setup\Activator', 'run' ) ); register_deactivation_hook( __FILE__, array( 'DuckDev\FourNotFour\Setup\Deactivator', 'run' ) ); /* * Boot the plugin once every other plugin has loaded. * * Hooking on `plugins_loaded` (rather than running at file scope) lets * addons declare themselves as dependencies and reliably hook into the * `404_to_301_init` action that Core fires after boot. */ add_action( 'plugins_loaded', function () { DuckDev\FourNotFour\Core::instance(); } );