Skip to content
wiki.fftac.org

Router - Source Excerpt 01

Back to Router

Summary

This source excerpt preserves a bounded section of Antichrist.net/wp-content/plugins/uaix-locale-router/src/Router.php so readers can inspect the evidence without opening the full source file.

**Source path:** Antichrist.net/wp-content/plugins/uaix-locale-router/src/Router.php

<?php

namespace UAIXLocaleRouter;

use UAIXLocaleRouter\Support\Path;


if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class Router {
	/**
	 * Bare public routes that intentionally stay outside locale redirects.
	 *
	 * @return array
	 */
	public static function get_bare_route_exceptions() {
		return array(
			'/robots.txt',
			'/sitemap.xml',
			'/sitemap.html',
		);
	}

	/**
	 * Current URL locale tag.
	 *
	 * @var string
	 */
	private static $current_url_tag = '';

	/**
	 * Original request path before stripping.
	 *
	 * @var string
	 */
	private static $original_request_path = '/';

	/**
	 * Request path without locale prefix.
	 *
	 * @var string
	 */
	private static $stripped_request_path = '/';

	/**
	 * Whether the current request had a locale prefix.
	 *
	 * @var bool
	 */
	private static $had_locale_prefix = false;

	/**
	 * Register hooks.
	 *
	 * @return void
	 */
	public static function register() {
		add_filter( 'do_parse_request', array( __CLASS__, 'bootstrap_request_context_before_parse' ), 0, 3 );
		add_action( 'init', array( __CLASS__, 'register_rewrite_rules' ) );
		add_filter( 'query_vars', array( __CLASS__, 'register_query_vars' ) );
		add_filter( 'request', array( __CLASS__, 'inject_request_locale' ), 0 );
		add_filter( 'pre_determine_locale', array( __CLASS__, 'filter_pre_determine_locale' ), 0 );
		add_filter( 'determine_locale', array( __CLASS__, 'filter_determine_locale' ), 0 );
		add_action( 'template_redirect', array( __CLASS__, 'redirect_bare_urls' ), 1 );
	}

	/**
	 * Prepare locale request context before WordPress parses rewrite rules.
	 *
	 * WordPress resolves pretty permalinks inside WP::parse_request(), which
	 * runs before the init hook. Locale stripping therefore needs to happen
	 * on do_parse_request so requests like /en-us/ are routed as / while still
	 * preserving the active locale in plugin state.
	 *
	 * @param bool        $do_parse_request Whether WordPress should parse the request.
	 * @param \WP         $wp Current WordPress environment instance.
	 * @param array|string $extra_query_vars Extra query vars.
	 * @return bool
	 */
	public static function bootstrap_request_context_before_parse( $do_parse_request, $wp, $extra_query_vars ) {
		unset( $wp, $extra_query_vars );

		self::bootstrap_request_context();

		return $do_parse_request;
	}

	/**
	 * Register rewrite tag.
	 *
	 * @return void
	 */
	public static function register_rewrite_rules() {
		add_rewrite_tag( '%uaix_locale%', '([A-Za-z]{2,8}(?:-[A-Za-z0-9]{2,8})*)' );
		add_rewrite_tag( '%ns12_locale%', '([A-Za-z]{2,8}(?:-[A-Za-z0-9]{2,8})*)' );
	}

	/**
	 * Register custom query vars.
	 *
	 * @param array $query_vars Query vars.
	 * @return array
	 */
	public static function register_query_vars( $query_vars ) {
		$query_vars[] = 'uaix_locale';
		$query_vars[] = 'ns12_locale';

		return array_values( array_unique( $query_vars ) );
	}

	/**
	 * Bootstrap locale request context before WordPress parses the route.
	 *
	 * @return void
	 */
	public static function bootstrap_request_context() {
		self::$current_url_tag       = '';
		self::$had_locale_prefix     = false;
		self::$original_request_path = Path::request_path();
		self::$stripped_request_path = self::$original_request_path;

		if ( ! self::is_plugin_enabled() || self::should_skip_bootstrap() ) {
			return;
		}

		$segments = Path::segments( self::$original_request_path );

		if ( empty( $segments ) ) {
			return;
		}

		$possible_locale = LocaleRepository::normalize_url_tag( $segments[0] );

		if ( ! LocaleRepository::is_enabled_url_tag( $possible_locale ) ) {
			return;
		}

		$remaining_segments = $segments;
		array_shift( $remaining_segments );
		$remaining_path = Path::join_segments( $remaining_segments );

		if ( self::is_excluded_path( $remaining_path ) && ! self::is_prefixed_rest_path( $remaining_path ) ) {
			return;
		}

		self::$current_url_tag      = $possible_locale;
		self::$had_locale_prefix    = true;
		self::$stripped_request_path = $remaining_path;

		$query_string           = isset( $_SERVER['QUERY_STRING'] ) ? (string) wp_unslash( $_SERVER['QUERY_STRING'] ) : '';
		$_SERVER['REQUEST_URI'] = $remaining_path . ( '' !== $query_string ? '?' . $query_string : '' );
	}

	/**
	 * Inject the current URL locale into parsed query vars.
	 *
	 * @param array $query_vars Query vars.
	 * @return array
	 */
	public static function inject_request_locale( $query_vars ) {
		if ( self::$current_url_tag && is_array( $query_vars ) ) {
			$query_vars['uaix_locale'] = self::$current_url_tag;
			$query_vars['ns12_locale'] = self::$current_url_tag;
		}

		return $query_vars;
	}

	/**
	 * Short-circuit locale resolution for localized front-end requests.
	 *
	 * @param mixed $locale Existing pre-determined locale.
	 * @return mixed
	 */
	public static function filter_pre_determine_locale( $locale ) {
		if ( ! self::is_plugin_enabled() || is_admin() || '' === self::$current_url_tag ) {
			return $locale;
		}

		$wp_locale = LocaleRepository::url_tag_to_wp_locale( self::$current_url_tag );

		return '' !== $wp_locale ? $wp_locale : $locale;
	}

	/**
	 * Fallback determine_locale filter.
	 *
	 * @param string $locale Current locale.
	 * @return string
	 */
	public static function filter_determine_locale( $locale ) {
		if ( ! self::is_plugin_enabled() || is_admin() || '' === self::$current_url_tag ) {
			return $locale;
		}

		$wp_locale = LocaleRepository::url_tag_to_wp_locale( self::$current_url_tag );

		return '' !== $wp_locale ? $wp_locale : $locale;
	}

	/**
	 * Return the locale redirect URL for a bare public request.
	 *
	 * Requests that are already locale-prefixed, excluded from localization,
	 * or outside the normal front-end runtime return an empty string.
	 *
	 * @param string $request_path Request path to evaluate.
	 * @param array  $query_args Query arguments to preserve.
	 * @param string $accept_language Browser Accept-Language header.
	 * @return string
	 */
	public static function get_bare_request_redirect_url( $request_path = '', array $query_args = array(), $accept_language = '' ) {
		$settings = Plugin::settings();

		if ( empty( $settings['enabled'] ) || empty( $settings['redirect_bare_urls'] ) ) {
			return '';
		}

		if ( self::should_skip_bootstrap() ) {
			return '';
		}

		$request_path = '' !== $request_path ? Path::normalize_path( $request_path ) : self::$original_request_path;

		if ( self::is_excluded_path( $request_path ) ) {
			return '';
		}

		$segments = Path::segments( $request_path );

		if ( ! empty( $segments ) ) {
			$possible_locale = LocaleRepository::normalize_url_tag( $segments[0] );

			if ( LocaleRepository::is_enabled_url_tag( $possible_locale ) ) {
				return '';
			}
		}

		$redirect_tag = LocaleRepository::get_redirect_url_tag_for_request( $accept_language );

		return Path::build_front_url(
			Path::localize_path( $request_path, $redirect_tag ),
			$query_args
		);
	}

	/**
	 * Redirect bare URLs to the default locale.
	 *
	 * @return void
	 */
	public static function redirect_bare_urls() {
		$settings     = Plugin::settings();

		if ( ! empty( $settings['redirect_bare_urls'] ) ) {
			Plugin::maybe_self_heal_localized_handoff( self::$original_request_path );
		}

		$redirect_url = self::get_bare_request_redirect_url(
			self::$original_request_path,
			Path::current_query_args(),
			isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? (string) wp_unslash( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) : ''
		);

		if ( '' === $redirect_url ) {
			return;
		}
		$status_code  = isset( $settings['redirect_status_code'] ) ? absint( $settings['redirect_status_code'] ) : 301;

		wp_safe_redirect( $redirect_url, $status_code > 0 ? $status_code : 301 );
		exit;
	}

	/**
	 * Active URL tag for the request.
	 *
	 * @return string
	 */
	public static function get_current_url_tag() {
		if ( '' !== self::$current_url_tag ) {
			return self::$current_url_tag;
		}

		$query_var = get_query_var( 'uaix_locale' );

		if ( is_string( $query_var ) && '' !== $query_var ) {
			return LocaleRepository::normalize_url_tag( $query_var );
		}

		$legacy_query_var = get_query_var( 'ns12_locale' );

		if ( is_string( $legacy_query_var ) && '' !== $legacy_query_var ) {
			return LocaleRepository::normalize_url_tag( $legacy_query_var );
		}

		return LocaleRepository::get_default_url_tag();
	}

	/**
	 * Original request path.
	 *
	 * @return string
	 */
	public static function get_original_request_path() {
		return self::$original_request_path;
	}

	/**
	 * Request path without the locale prefix.
	 *
	 * @return string
	 */
	public static function get_stripped_request_path() {
		return self::$stripped_request_path;
	}

	/**