'invalid-host.local.test', 'db_port' => '3306', 'db_user' => 'mailshots', 'db_password' => 'secret', 'mailshots_db_name' => 'mailshots', 'members_db_name' => 'members', 'fen_db_name' => 'fen', ]; if ($key === \FecaMailshots\Admin\SetupAdminPage::OPTION_KEY) { $GLOBALS['feca_setup_option_reads']++; return $config; } if ($key === \FecaMailshots\Infrastructure\MailshotSchemaInstaller::STATE_OPTION_KEY) { $dbConfig = [ 'MYSQL_HOST' => $config['db_host'], 'MYSQL_PORT' => $config['db_port'], 'MYSQL_USER' => $config['db_user'], 'MYSQL_PASSWORD' => $config['db_password'], 'MAILSHOTS_REMOTE_MYSQL_DB' => $config['mailshots_db_name'], 'MEMBERS_REMOTE_MYSQL_DB' => $config['members_db_name'], 'FEN_REMOTE_MYSQL_DB' => $config['fen_db_name'], ]; return \FecaMailshots\Infrastructure\MailshotSchemaInstaller::migrationTarget($dbConfig) + ['status' => 'complete']; } return $default; } function is_admin(): bool { return true; } function add_action(string $hook, callable $callback): void { if (!isset($GLOBALS['feca_bootstrap_actions'][$hook])) { $GLOBALS['feca_bootstrap_actions'][$hook] = []; } $GLOBALS['feca_bootstrap_actions'][$hook][] = $callback; } function add_menu_page(...$args): void { } function add_submenu_page(...$args): void { } require dirname(__DIR__, 2) . '/feca_mailshots_plugin/feca_mailshots_plugin.php'; $actions = $GLOBALS['feca_bootstrap_actions']; if (!isset($actions['admin_post_feca_mailshots_data_sources_api'], $actions['admin_post_feca_mailshots_setup_save'])) { fwrite(STDERR, "Expected normal handlers to register without touching the database\n"); exit(1); } if ($GLOBALS['feca_setup_option_reads'] !== 1) { fwrite(STDERR, "Expected setup configuration to be read exactly once during bootstrap\n"); exit(1); } foreach (get_included_files() as $includedFile) { if (strpos($includedFile, '/vendor/thecodingmachine/safe/') !== false) { fwrite(STDERR, "Composer runtime function files should remain unloaded during admin bootstrap\n"); exit(1); } } echo "Bootstrap full setup no DB touch regression test passed\n";