*/ function abj404_get_settings_options() { $options = get_option('abj404_settings'); return is_array($options) ? $options : array(); } } // Debug whitelist - only includes localhost/development environments by default // WARNING: Only add trusted domains to this list. External domains could be a security risk. // This list is used to enable detailed error logging for debugging purposes. $GLOBALS['abj404_whitelist'] = array('127.0.0.1', '::1', 'localhost'); // Allow filtering the whitelist for advanced users who need to add custom domains // Usage: add_filter('abj404_debug_whitelist', function($whitelist) { $whitelist[] = 'yourdomain.com'; return $whitelist; }); if (has_filter('abj404_debug_whitelist')) { $GLOBALS['abj404_whitelist'] = apply_filters('abj404_debug_whitelist', $GLOBALS['abj404_whitelist']); } /** * @param string $class * @return void */ function abj404_autoloader($class) { // some people were having issues with possibly parent classes not being loaded before their children. $childParentMap = [ 'ABJ_404_Solution_FunctionsMBString' => 'ABJ_404_Solution_Functions', 'ABJ_404_Solution_FunctionsPreg' => 'ABJ_404_Solution_Functions', ]; // only pay attention if it's for us. don't bother for other things. if (substr($class, 0, 16) !== 'ABJ_404_Solution') { return; } // Use a deterministic classmap to avoid runtime glob() scans on real sites. static $abj404_autoLoaderClassMap = null; if ($abj404_autoLoaderClassMap === null) { $mapFile = __DIR__ . '/includes/classmap.php'; $abj404_autoLoaderClassMap = file_exists($mapFile) ? require $mapFile : array(); } if (!array_key_exists($class, $abj404_autoLoaderClassMap)) { return; } // Ensure the parent class is loaded first. if (array_key_exists($class, $childParentMap)) { $parentClass = $childParentMap[$class]; if (!class_exists($parentClass, false) && array_key_exists($parentClass, $abj404_autoLoaderClassMap)) { require_once $abj404_autoLoaderClassMap[$parentClass]; } } require_once $abj404_autoLoaderClassMap[$class]; } spl_autoload_register('abj404_autoloader'); add_action('doing_it_wrong_run', function($function_name, $message, $version) { if (strpos($message, '404-solution') !== false && $function_name == '_load_textdomain_just_in_time') { try { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); // Prepare the plugin path from ABJ404_FILE $pluginPath = trailingslashit(plugin_dir_path(ABJ404_FILE)); // e.g., /var/www/html/wp-content/plugins/404-solution/ $logMessage = ''; $isOurPlugin = false; foreach ($backtrace as $index => $frame) { $file = isset($frame['file']) ? $frame['file'] : '[internal function]'; $line = isset($frame['line']) ? $frame['line'] : ''; $func = $frame['function']; if (!$isOurPlugin && is_string($file) && strpos($file, $pluginPath) !== false) { $isOurPlugin = true; } $logMessage .= "#$index $func at [$file:$line]\n"; } if ($isOurPlugin) { $header = "=== Detected Early Translation ===\n" . "Function: $function_name\n" . "Message: $message\n" . "Version: $version\n"; if (!isset($GLOBALS['abj404_pending_errors'])) { $GLOBALS['abj404_pending_errors'] = []; } $GLOBALS['abj404_pending_errors'][] = $header . $logMessage; } } catch (Throwable $e) { // error_log('Failed to log early translation stack trace: ' . $e->getMessage()); } } }, 10, 3); // shortcode add_shortcode(ABJ404_SHORTCODE_NAME, 'abj404_shortCodeListener'); if (!function_exists('abj404_shortCodeListener')) { /** * @param array|string $atts * @return string */ function abj404_shortCodeListener($atts) { abj404_load_textdomain_if_needed(); require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); /** @var array $safeAtts */ $safeAtts = is_array($atts) ? $atts : array(); return ABJ_404_Solution_ShortCode::shortcodePageSuggestions($safeAtts); } if (!function_exists('abj404_get_required_runtime_files')) { /** * Files required for a healthy runtime/plugin package. * * @return array */ function abj404_get_required_runtime_files() { return array( ABJ404_PATH . 'includes/sql/getPermalinkFromURL.sql', ABJ404_PATH . 'includes/sql/getRedirectsForView.sql', ABJ404_PATH . 'includes/sql/createRedirectsTable.sql', ABJ404_PATH . 'includes/sql/createLogTable.sql', ABJ404_PATH . 'includes/WordPress_Connector.php', ABJ404_PATH . 'includes/FrontendRequestPipeline.php', ABJ404_PATH . 'includes/ImportExportService.php', ); } } if (!function_exists('abj404_verify_runtime_integrity')) { /** * Validate that required plugin files are present. * * @return array Missing file paths. */ function abj404_verify_runtime_integrity() { $missing = array(); foreach (abj404_get_required_runtime_files() as $path) { if (!file_exists($path)) { $missing[] = $path; } } return $missing; } } if (!function_exists('abj404_is_benchmark_request')) { /** * Benchmark instrumentation is disabled by default and only enabled per-request. * * @return bool */ function abj404_is_benchmark_request() { return isset($_GET['abj404_bench']) && (string)$_GET['abj404_bench'] === '1'; } } if (!function_exists('abj404_benchmark_bootstrap_start')) { /** @return void */ function abj404_benchmark_bootstrap_start() { if (!abj404_is_benchmark_request()) { return; } if (!isset($GLOBALS['abj404_benchmark_state']) || !is_array($GLOBALS['abj404_benchmark_state'])) { $GLOBALS['abj404_benchmark_state'] = array( 'start' => microtime(true), 'bootstrap_done' => 0.0, 'db_query_count' => 0, 'db_query_ms' => 0.0, 'redirect_lookup_ms' => 0.0, ); } } } if (!function_exists('abj404_benchmark_mark_bootstrap_done')) { /** @return void */ function abj404_benchmark_mark_bootstrap_done() { if (!abj404_is_benchmark_request() || !isset($GLOBALS['abj404_benchmark_state'])) { return; } $GLOBALS['abj404_benchmark_state']['bootstrap_done'] = microtime(true); } } if (!function_exists('abj404_benchmark_record_db_query')) { /** * @param float $elapsedMs * @return void */ function abj404_benchmark_record_db_query($elapsedMs) { if (!abj404_is_benchmark_request() || !isset($GLOBALS['abj404_benchmark_state'])) { return; } $elapsedMs = max(0.0, (float)$elapsedMs); $GLOBALS['abj404_benchmark_state']['db_query_count']++; $GLOBALS['abj404_benchmark_state']['db_query_ms'] += $elapsedMs; } } if (!function_exists('abj404_benchmark_record_redirect_lookup')) { /** * @param float $elapsedMs * @return void */ function abj404_benchmark_record_redirect_lookup($elapsedMs) { if (!abj404_is_benchmark_request() || !isset($GLOBALS['abj404_benchmark_state'])) { return; } $GLOBALS['abj404_benchmark_state']['redirect_lookup_ms'] += max(0.0, (float)$elapsedMs); } } if (!function_exists('abj404_benchmark_emit_headers')) { /** @return void */ function abj404_benchmark_emit_headers() { if (!abj404_is_benchmark_request() || headers_sent() || !isset($GLOBALS['abj404_benchmark_state'])) { return; } $state = $GLOBALS['abj404_benchmark_state']; $start = isset($state['start']) ? (float)$state['start'] : 0.0; $bootstrapDone = isset($state['bootstrap_done']) ? (float)$state['bootstrap_done'] : 0.0; $now = microtime(true); $totalMs = ($start > 0.0) ? (($now - $start) * 1000.0) : 0.0; $bootstrapMs = ($start > 0.0 && $bootstrapDone > 0.0) ? (($bootstrapDone - $start) * 1000.0) : 0.0; $dbQueryCount = isset($state['db_query_count']) ? (int)$state['db_query_count'] : 0; $dbQueryMs = isset($state['db_query_ms']) ? (float)$state['db_query_ms'] : 0.0; $redirectLookupMs = isset($state['redirect_lookup_ms']) ? (float)$state['redirect_lookup_ms'] : 0.0; header( 'X-ABJ404-Benchmark: ' . 'total_ms=' . round($totalMs, 3) . ';' . 'bootstrap_ms=' . round($bootstrapMs, 3) . ';' . 'db_query_count=' . $dbQueryCount . ';' . 'db_query_ms=' . round($dbQueryMs, 3) . ';' . 'redirect_lookup_ms=' . round($redirectLookupMs, 3) ); } } abj404_benchmark_bootstrap_start(); if (abj404_is_benchmark_request()) { add_action('send_headers', 'abj404_benchmark_emit_headers', PHP_INT_MAX); } } // admin if (is_admin()) { require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); ABJ_404_Solution_WordPress_Connector::init(); ABJ_404_Solution_ViewUpdater::init(); } // ---- // get the plugin priority to use before adding the template_redirect action. $__abj404_options = abj404_get_settings_options(); $__abj404_redirect_priority_raw = isset($__abj404_options['template_redirect_priority']) && is_scalar($__abj404_options['template_redirect_priority']) ? $__abj404_options['template_redirect_priority'] : 9; $__abj404_template_redirect_priority = absint($__abj404_redirect_priority_raw); $__abj404_redirect_all = isset($__abj404_options['redirect_all_requests']) && is_scalar($__abj404_options['redirect_all_requests']) ? (string)$__abj404_options['redirect_all_requests'] : ''; $__abj404_update_suggest = isset($__abj404_options['update_suggest_url']) && is_scalar($__abj404_options['update_suggest_url']) ? (string)$__abj404_options['update_suggest_url'] : ''; $GLOBALS['abj404_frontend_runtime_flags'] = array( 'redirect_all_requests' => ($__abj404_redirect_all === '1'), 'update_suggest_url' => ($__abj404_update_suggest === '1'), ); $__abj404_lang_override = isset($__abj404_options['plugin_language_override']) && is_string($__abj404_options['plugin_language_override']) ? $__abj404_options['plugin_language_override'] : ''; $GLOBALS['abj404_plugin_language_override'] = $__abj404_lang_override; add_action('template_redirect', 'abj404_404listener', $__abj404_template_redirect_priority); unset($__abj404_options); unset($__abj404_template_redirect_priority); abj404_benchmark_mark_bootstrap_done(); // --- // 404 if (!function_exists('abj404_404listener')) { /** @return void */ function abj404_404listener() { $is404 = is_404(); if (!$is404) { // Performance: do NOT load the whole plugin on every frontend request unless we must. if (!empty($GLOBALS['abj404_frontend_runtime_flags']['redirect_all_requests'])) { require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); $connector = ABJ_404_Solution_WordPress_Connector::getInstance(); $connector->processRedirectAllRequests(); return; } $updateSuggestEnabled = !empty($GLOBALS['abj404_frontend_runtime_flags']['update_suggest_url']); $cookieName404 = ABJ404_PP . '_STATUS_404'; $has404StatusCookie = (isset($_COOKIE[$cookieName404]) && $_COOKIE[$cookieName404] == 'true'); // Fast path: if none of the non-404 features are active, bail immediately. if (!$updateSuggestEnabled && !$has404StatusCookie) { return; } /** If we're currently redirecting to a custom 404 page and we are about to show page * suggestions then update the URL displayed to the user. */ $cookieName = ABJ404_PP . '_REQUEST_URI_UPDATE_URL'; $queryParamName = ABJ404_PP . '_ref'; $hasUpdateCookie = !empty($_COOKIE[$cookieName]); $hasUpdateParam = !empty($_GET[$queryParamName]); // Fast path: nothing pending from prior plugin-driven redirects. if (!$hasUpdateCookie && !$hasUpdateParam && !$has404StatusCookie) { return; } if ($has404StatusCookie) { // clear the cookie setcookie($cookieName404, 'false', time() - 5, "/"); // we're going to a custom 404 page so set the status to 404. status_header(404); } if (!$updateSuggestEnabled) { return; } // Check cookie first, then query param fallback (for 301 redirects where cookies don't survive) $originalURL = null; if ($hasUpdateCookie) { $originalURL = $_COOKIE[$cookieName]; } elseif ($hasUpdateParam) { $originalURL = urldecode($_GET[$queryParamName]); } if ($originalURL !== null) { // clear the cookie - sanitize before writing to $_REQUEST $_REQUEST[ABJ404_PP . '_REQUEST_URI'] = sanitize_text_field($originalURL); setcookie($cookieName, '', time() - 5, "/"); require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); add_action('wp_head', 'ABJ_404_Solution_ShortCode::updateURLbarIfNecessary'); } return; } // ignore admin screens and login requests on 404 processing path. // $_SERVER['SCRIPT_NAME'] is not guaranteed (CLI, some test runners, some proxies). // Use a direct script-name check to avoid invoking wp_login_url() filters. $scriptName = $_SERVER['SCRIPT_NAME'] ?? ''; $requestUri = $_SERVER['REQUEST_URI'] ?? ''; $isLoginScreen = ( ($scriptName !== '' && stripos($scriptName, 'wp-login.php') !== false) || ($requestUri !== '' && stripos($requestUri, 'wp-login.php') !== false) ); if (is_admin() || $isLoginScreen) { return; } require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); $connector = ABJ_404_Solution_WordPress_Connector::getInstance(); $connector->process404(); } } if (!function_exists('abj404_is_redirect_all_requests_enabled')) { /** * Small helper for testability and to keep option-parsing logic consistent. * * @param mixed $options Value returned by get_option('abj404_settings') * @return bool */ function abj404_is_redirect_all_requests_enabled($options) { return is_array($options) && array_key_exists('redirect_all_requests', $options) && (string)$options['redirect_all_requests'] === '1'; } } if (!function_exists('abj404_dailyMaintenanceCronJobListener')) { /** @return void */ function abj404_dailyMaintenanceCronJobListener() { require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); $abj404dao = ABJ_404_Solution_DataAccess::getInstance(); $abj404dao->deleteOldRedirectsCron(); $dbUpgrades = ABJ_404_Solution_DatabaseUpgradesEtc::getInstance(); $dbUpgrades->runDatabaseMaintenanceTasks(); } } if (!function_exists('abj404_updateLogsHitsTableListener')) { /** @return void */ function abj404_updateLogsHitsTableListener() { require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); $abj404dao = ABJ_404_Solution_DataAccess::getInstance(); $abj404dao->createRedirectsForViewHitsTable(); } } if (!function_exists('abj404_updatePermalinkCacheListener')) { /** * @param int $maxExecutionTime * @param int $executionCount * @return void */ function abj404_updatePermalinkCacheListener($maxExecutionTime, $executionCount = 1) { require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); $permalinkCache = ABJ_404_Solution_PermalinkCache::getInstance(); $permalinkCache->updatePermalinkCache($maxExecutionTime, $executionCount); } } if (!function_exists('abj404_rebuildNGramCacheListener')) { /** * @param int $offset * @return void */ function abj404_rebuildNGramCacheListener($offset = 0) { require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); $dbUpgrades = ABJ_404_Solution_DatabaseUpgradesEtc::getInstance(); $dbUpgrades->rebuildNGramCacheAsync($offset); } } if (!function_exists('abj404_networkActivationListener')) { /** @return void */ function abj404_networkActivationListener() { require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); ABJ_404_Solution_PluginLogic::networkActivationCronHandler(); } } if (!function_exists('abj404_networkActivationBackgroundListener')) { /** @return void */ function abj404_networkActivationBackgroundListener() { require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); $upgradesEtc = ABJ_404_Solution_DatabaseUpgradesEtc::getInstance(); $upgradesEtc->processMultisiteActivationBatch(); } } if (!function_exists('abj404_networkUpgradeBackgroundListener')) { /** @return void */ function abj404_networkUpgradeBackgroundListener() { require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); $upgradesEtc = ABJ_404_Solution_DatabaseUpgradesEtc::getInstance(); $upgradesEtc->processMultisiteUpgradeBatch(); } } add_action('abj404_cleanupCronAction', 'abj404_dailyMaintenanceCronJobListener'); add_action('abj404_updateLogsHitsTableAction', 'abj404_updateLogsHitsTableListener'); add_action('abj404_updatePermalinkCacheAction', 'abj404_updatePermalinkCacheListener', 10, 2); add_action('abj404_rebuild_ngram_cache_hook', 'abj404_rebuildNGramCacheListener', 10, 1); add_action('abj404_network_activation_hook', 'abj404_networkActivationListener'); add_action('abj404_network_activation_background', 'abj404_networkActivationBackgroundListener'); add_action('abj404_network_upgrade_background', 'abj404_networkUpgradeBackgroundListener'); /** * Override the locale for this plugin if user has configured a language override. * This allows users to use a different language for the 404 Solution plugin * than their WordPress site language or user language preference. * * @param string $locale The current locale. * @param string $domain The text domain. * @return string The locale to use for translation loading. */ if (!function_exists('abj404_override_plugin_locale')) { /** * @param string $locale * @param string $domain * @return string */ function abj404_override_plugin_locale($locale, $domain) { // Only override for our plugin's text domain if ($domain === '404-solution') { $options = abj404_get_settings_options(); // Check if language override is set and not empty if (is_array($options) && !empty($options['plugin_language_override']) && is_string($options['plugin_language_override'])) { return $options['plugin_language_override']; } } return $locale; } } add_filter('plugin_locale', 'abj404_override_plugin_locale', 999, 2); if (!function_exists('abj404_show_runtime_integrity_notice')) { /** @return void */ function abj404_show_runtime_integrity_notice() { if (!is_admin() || !current_user_can('manage_options')) { return; } $page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : ''; if ($page !== ABJ404_PP) { return; } $missing = get_transient('abj404_runtime_missing_files'); if (!is_array($missing) || count($missing) === 0) { return; } echo '

404 Solution: '; echo esc_html(__('Some required plugin files are missing. Please reinstall the plugin package.', '404-solution')); echo '

' . esc_html(implode(', ', array_map('basename', $missing))) . '

'; } } add_action('admin_notices', 'abj404_show_runtime_integrity_notice'); if (!function_exists('abj404_show_plugin_db_notice')) { /** @return void */ function abj404_show_plugin_db_notice() { if (!is_admin() || !current_user_can('manage_options')) { return; } $page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : ''; if ($page !== ABJ404_PP) { return; } $notice = get_transient('abj404_plugin_db_notice'); if (!is_array($notice) || empty($notice['message'])) { return; } $type = isset($notice['type']) ? $notice['type'] : ''; // Collation issues are developer-level; don't show them to the user. if ($type === 'collation') { return; } $guidance = ''; if ($type === 'disk_full') { $guidance = __('Contact your hosting provider. This is usually caused by a database quota, tablespace limit, or full /tmp partition — not necessarily a full disk.', '404-solution'); } elseif ($type === 'read_only') { $guidance = __('Your database is currently in read-only mode. Contact your hosting provider.', '404-solution'); } elseif ($type === 'query_quota') { $guidance = __('Your database query quota was exceeded. This usually resets automatically.', '404-solution'); } elseif ($type === 'corrupted_temp_table') { $guidance = __('A temporary MySQL table was corrupted, usually caused by disk or hardware issues. The plugin cannot repair it. Please contact your hosting provider.', '404-solution'); } elseif ($type === 'log_table_full') { $guidance = __('The 404 Solution log table is full. The plugin automatically trimmed the oldest 1,000 log entries to free space, but logging may still be limited. Please contact your hosting provider about disk space.', '404-solution'); } echo '

404 Solution: ' . esc_html($notice['message']) . '

'; if ($guidance !== '') { echo '

' . esc_html($guidance) . '

'; } if (!empty($notice['error_string'])) { echo '
' . esc_html(__('Show database error details', '404-solution')) . ''; echo '
' . esc_html($notice['error_string']) . '
'; } echo '
'; } } add_action('admin_notices', 'abj404_show_plugin_db_notice'); if (!function_exists('abj404_get_simulated_db_latency_ms')) { /** @return bool */ function abj404_is_local_debug_host() { $serverName = array_key_exists('SERVER_NAME', $_SERVER) ? $_SERVER['SERVER_NAME'] : (array_key_exists('HTTP_HOST', $_SERVER) ? $_SERVER['HTTP_HOST'] : ''); $serverName = strtolower(trim((string)$serverName)); if ($serverName === '') { return false; } $normalizedHost = $serverName; if (strpos($normalizedHost, '[') === 0) { $endBracket = strpos($normalizedHost, ']'); if ($endBracket !== false) { $normalizedHost = substr($normalizedHost, 1, $endBracket - 1); } } else { $colonCount = substr_count($normalizedHost, ':'); if ($colonCount === 1 && preg_match('/:\d+$/', $normalizedHost)) { $normalizedHost = preg_replace('/:\d+$/', '', $normalizedHost); } } $normalizedHost = rtrim((string)$normalizedHost, '.'); return in_array($normalizedHost, array('127.0.0.1', '::1', 'localhost'), true); } /** @return int */ function abj404_get_simulated_db_latency_ms() { if (!abj404_is_local_debug_host()) { return 0; } if (defined('ABJ404_SIMULATED_DB_LATENCY_MS')) { return max(0, min(5000, absint(ABJ404_SIMULATED_DB_LATENCY_MS))); } $value = get_option('abj404_simulated_db_latency_ms', 0); return max(0, min(5000, absint(is_scalar($value) ? $value : 0))); } } if (!function_exists('abj404_show_diagnostic_latency_notice')) { /** @return void */ function abj404_show_diagnostic_latency_notice() { // Intentionally no-op. Simulated latency status is shown in the plugin's // Tools > Diagnostics card to avoid intrusive floating/global notices. return; } } if (!function_exists('abj404_load_textdomain_if_needed')) { /** * Load plugin translations once, lazily. * * @return void */ function abj404_load_textdomain_if_needed() { static $loaded = false; if ($loaded) { return; } $override_locale = ''; if (!empty($GLOBALS['abj404_plugin_language_override'])) { $override_locale = (string)$GLOBALS['abj404_plugin_language_override']; } else { $options = abj404_get_settings_options(); $override_locale = (is_array($options) && !empty($options['plugin_language_override'])) ? $options['plugin_language_override'] : ''; } if (!empty($override_locale)) { $mo_file = ABJ404_PATH . 'languages/404-solution-' . $override_locale . '.mo'; if (file_exists($mo_file)) { load_textdomain('404-solution', $mo_file); } } else { $lang_dir = dirname(plugin_basename(ABJ404_FILE)) . '/languages'; load_plugin_textdomain('404-solution', false, $lang_dir); } $loaded = true; } } if (!function_exists('abj404_maybe_refresh_runtime_integrity_cache')) { /** * Refresh runtime integrity cache at most once per TTL window. * * @param int $ttlSeconds * @return void */ function abj404_maybe_refresh_runtime_integrity_cache($ttlSeconds = 43200) { if (!is_admin()) { return; } $checkedRecently = get_transient('abj404_runtime_integrity_checked'); if ($checkedRecently) { return; } $missingRuntimeFiles = abj404_verify_runtime_integrity(); if (count($missingRuntimeFiles) > 0) { set_transient('abj404_runtime_missing_files', $missingRuntimeFiles, $ttlSeconds); } else { delete_transient('abj404_runtime_missing_files'); } set_transient('abj404_runtime_integrity_checked', 1, $ttlSeconds); } } /** This only runs after WordPress is done enqueuing scripts. */ if (!function_exists('abj404_loadSomethingWhenWordPressIsReady')) { /** @return void */ function abj404_loadSomethingWhenWordPressIsReady() { $isAdminRequest = is_admin(); if ($isAdminRequest) { abj404_load_textdomain_if_needed(); } // make debugging easier on localhost etc if ($isAdminRequest) { $serverName = array_key_exists('SERVER_NAME', $_SERVER) ? $_SERVER['SERVER_NAME'] : (array_key_exists('HTTP_HOST', $_SERVER) ? $_SERVER['HTTP_HOST'] : '(not found)'); $serverNameIsInTheWhiteList = in_array($serverName, $GLOBALS['abj404_whitelist']); // Keep localhost debug helper on admin screens only; frontend requests stay lean. if ($serverNameIsInTheWhiteList && function_exists('wp_get_current_user')) { require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); $abj404logic = ABJ_404_Solution_PluginLogic::getInstance(); if ($abj404logic->userIsPluginAdmin()) { $GLOBALS['abj404_display_errors'] = true; } } } $action = null; if ($isAdminRequest) { $action = isset($_GET['action']) ? sanitize_text_field($_GET['action']) : (isset($_POST['action']) ? sanitize_text_field($_POST['action']) : null); } if ($isAdminRequest && abj404_is_local_debug_host() && current_user_can('manage_options') && isset($_GET['abj404_set_sim_db_ms'])) { $nonceOk = isset($_GET['_wpnonce']) ? wp_verify_nonce($_GET['_wpnonce'], 'abj404_set_sim_db_ms') : false; if ($nonceOk) { $newMs = max(0, min(5000, absint($_GET['abj404_set_sim_db_ms']))); update_option('abj404_simulated_db_latency_ms', $newMs, false); } } $ttl = defined('HOUR_IN_SECONDS') ? (12 * HOUR_IN_SECONDS) : 43200; abj404_maybe_refresh_runtime_integrity_cache($ttl); if ($isAdminRequest && $action === 'exportRedirects') { require_once(plugin_dir_path( __FILE__ ) . "includes/Loader.php"); $abj404logic = ABJ_404_Solution_PluginLogic::getInstance(); $abj404logic->handleActionExport(); } } } add_action('admin_init', 'abj404_loadSomethingWhenWordPressIsReady');