$ajaxUrl, 'nonces' => array( 'support_request' => $supportNonce, 'support_request_preview' => $previewNonce, ), )); $bootstrap = 'window.ABJ404=window.ABJ404||{};Object.assign(window.ABJ404,' . (is_string($payload) ? $payload : '{}') . ');'; wp_add_inline_script('abj404-support-request-client', $bootstrap, 'before'); }); } } if (!function_exists('abj404_degraded_admin_menu')) { /** @return void */ function abj404_degraded_admin_menu() { $options = abj404_get_settings_options(); $menuName = '404 Solution'; $badge = " !"; if (isset($options['menuLocation']) && $options['menuLocation'] === 'settingsLevel') { add_menu_page('404 Solution', $menuName . $badge, 'manage_options', 'abj404_solution', 'abj404_degraded_admin_page'); } else { $ppSlug = defined('ABJ404_PP') ? ABJ404_PP : 'abj404_solution'; add_submenu_page('options-general.php', '404 Solution', $menuName . $badge, 'manage_options', $ppSlug, 'abj404_degraded_admin_page'); } } } if (!function_exists('abj404_degraded_admin_notice')) { /** @return void */ function abj404_degraded_admin_notice() { if (!current_user_can('manage_options')) { return; } echo '

404 Solution: '; echo 'Plugin files are missing or corrupt. '; $ppSlug = defined('ABJ404_PP') ? ABJ404_PP : 'abj404_solution'; echo 'View details'; echo '

'; } } if (!function_exists('abj404_degraded_admin_page')) { /** @return void */ function abj404_degraded_admin_page() { if (!current_user_can('manage_options')) { echo '
'; echo '

404 Solution

'; echo '

'; echo 'Permission denied. '; echo 'Your user account does not have permission to access this page.'; echo '

'; echo 'Please verify that your WordPress role has the manage_options capability.'; echo '

'; return; } $missingFiles = isset($GLOBALS['abj404_missing_files']) && is_array($GLOBALS['abj404_missing_files']) ? $GLOBALS['abj404_missing_files'] : array(); $bootError = isset($GLOBALS['abj404_boot_error']) ? $GLOBALS['abj404_boot_error'] : ''; $pluginDir = defined('ABJ404_PATH') ? ABJ404_PATH : dirname(dirname(__DIR__)) . '/'; // Check for a stored fatal from a previous request. $fatalInfo = function_exists('get_transient') ? get_transient('abj404_boot_fatal') : false; echo '
'; // allow-em-dash: — entity is user-facing HTML output in the corrupt-install page heading, separating the plugin name from the page subtitle. echo '

404 Solution — Plugin Files Missing

'; echo '

'; echo 'The 404 Solution plugin cannot start because one or more required files are missing or corrupt. '; echo 'This usually happens after a failed plugin update or incomplete file upload.'; echo '

'; if (!empty($missingFiles)) { echo '
'; echo '

Missing Files

'; echo ''; echo '
'; } $bootErrorText = is_scalar($bootError) ? (string)$bootError : ''; if ($bootErrorText !== '') { echo '
'; echo '

Error Details

'; echo '
' . esc_html($bootErrorText) . '
'; echo '
'; } if (is_array($fatalInfo) && !empty($fatalInfo['message'])) { echo '
'; echo '

Fatal Error (previous request)

'; $fatalFileRaw = isset($fatalInfo['file']) && is_scalar($fatalInfo['file']) ? (string)$fatalInfo['file'] : ''; $fatalFile = $fatalFileRaw !== '' ? str_replace($pluginDir, '', $fatalFileRaw) : 'unknown'; $fatalLine = isset($fatalInfo['line']) && is_scalar($fatalInfo['line']) ? (string)$fatalInfo['line'] : '?'; $fatalMessage = isset($fatalInfo['message']) && is_scalar($fatalInfo['message']) ? (string)$fatalInfo['message'] : ''; echo '
' . esc_html($fatalMessage) . "\n" . esc_html($fatalFile) . ':' . esc_html($fatalLine) . '
'; echo '
'; } echo '
'; echo '

How to Fix

'; echo '
    '; echo '
  1. Go to Plugins → Installed Plugins, deactivate 404 Solution, then delete it.
  2. '; echo '
  3. Reinstall from the WordPress plugin directory: '; $installUrl = admin_url('plugin-install.php?s=404+solution&tab=search'); echo 'Search “404 Solution”'; echo '
  4. '; echo '
  5. Activate the fresh copy. Your redirects and settings are stored in the database and will not be lost.
  6. '; echo '
'; echo '
'; // Support-request card. This is the most valuable placement for // the "Send debug log to developer" button: an admin who reached // this screen needs help and may not be able to navigate the // normal plugin UI. When the SupportRequestButton class is // present (most corruption is partial), render the mount div so // the JS component can take over. Always emit a mailto fallback // underneath in case the JS files are themselves among the // missing files. echo '
'; echo '

Need help? Contact the developer

'; echo '

Send the developer a one-time diagnostic report including the missing-file list above. Your redirects and settings are not shared.

'; $missingCount = count($missingFiles); $contextSummary = 'Corrupt install: ' . $missingCount . ' missing file(s)'; $bootErrorForSummary = is_scalar($bootError) ? (string)$bootError : ''; if ($bootErrorForSummary !== '') { $contextSummary .= '. Boot error: ' . substr($bootErrorForSummary, 0, 200); } if (class_exists('ABJ_404_Solution_SupportRequestButton')) { echo ABJ_404_Solution_SupportRequestButton::render('system_corrupt_install', $contextSummary); } $mailEmail = defined('ABJ404_AUTHOR_EMAIL') ? (string)ABJ404_AUTHOR_EMAIL : '404solution@ajexperience.com'; $mailSubject = rawurlencode('404 Solution: corrupt install report'); $homeUrlText = '(unknown)'; if (function_exists('home_url')) { $homeUrlVal = home_url(); $homeUrlText = is_string($homeUrlVal) ? $homeUrlVal : '(unknown)'; } $stringMissingFiles = array(); foreach ($missingFiles as $entry) { $stringMissingFiles[] = is_scalar($entry) ? (string)$entry : ''; } $missingFileLines = implode("\n", $stringMissingFiles); $mailBody = rawurlencode("Site URL: " . $homeUrlText . "\n" . "Missing files (" . (int)$missingCount . "):\n" . $missingFileLines . "\n\nBoot error:\n" . $bootErrorText); echo '

Or email manually: '; echo ''; echo esc_html($mailEmail) . '

'; echo '
'; echo '
'; // .wrap } }