*/ private const SUCCESSORS = [ 'shiftora-support' => 'shiftora-help', 'shiftora-health' => 'shiftora-help', 'shiftora-logs' => 'shiftora-help', 'shiftora-rollback-history' => 'shiftora-backups', ]; /** * Sends a retired slug to its successor, or lets the refusal stand. * * Hooked to `admin_page_access_denied`, which fires just before WordPress * refuses an unregistered `page=`; admin_init is too early to see the slug. */ public function maybe_redirect(): void { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- reading the route of the request, changing nothing. $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; if ( '' === $page || ! isset( self::SUCCESSORS[ $page ] ) ) { return; } // A user who cannot open the successor would get the redirect and then the refusal. if ( ! current_user_can( 'manage_options' ) ) { return; } wp_safe_redirect( admin_url( 'admin.php?page=' . self::SUCCESSORS[ $page ] ) ); exit; } }