1 ) { $path = rtrim( $path, '/' ); } $path = preg_replace( '#//+#', '/', $path ); return sxanl_str_limit( $path, 512 ); } /** * Extract the registrable-ish host from a referrer URL (lowercased, no www). * * @param string $referrer Referrer URL. * @return string Empty string if not parseable / not http(s). */ function sxanl_referrer_host( $referrer ) { $referrer = (string) $referrer; if ( '' === $referrer ) { return ''; } $scheme = wp_parse_url( $referrer, PHP_URL_SCHEME ); if ( ! in_array( strtolower( (string) $scheme ), array( 'http', 'https' ), true ) ) { return ''; } $host = wp_parse_url( $referrer, PHP_URL_HOST ); if ( ! is_string( $host ) || '' === $host ) { return ''; } $host = strtolower( $host ); if ( 0 === strpos( $host, 'www.' ) ) { $host = substr( $host, 4 ); } return sxanl_str_limit( $host, 255 ); } /** * The site's own host (for "internal referrer" detection). * * @return string */ function sxanl_site_host() { static $host = null; if ( null === $host ) { $host = strtolower( (string) wp_parse_url( home_url(), PHP_URL_HOST ) ); if ( 0 === strpos( $host, 'www.' ) ) { $host = substr( $host, 4 ); } } return $host; } /** * A device-class bucket from a UA string: 'mobile' | 'tablet' | 'desktop'. * * Deliberately crude — we are not building a device database. * * @param string $ua UA string. * @return string */ function sxanl_device_type( $ua ) { $ua = strtolower( (string) $ua ); if ( '' === $ua ) { return 'unknown'; } if ( false !== strpos( $ua, 'ipad' ) || ( false !== strpos( $ua, 'android' ) && false === strpos( $ua, 'mobile' ) ) || false !== strpos( $ua, 'tablet' ) ) { return 'tablet'; } if ( false !== strpos( $ua, 'mobi' ) || false !== strpos( $ua, 'iphone' ) || false !== strpos( $ua, 'ipod' ) || false !== strpos( $ua, 'windows phone' ) ) { return 'mobile'; } return 'desktop'; } /** * A coarse browser family from a UA string. * * @param string $ua UA string. * @return string */ function sxanl_browser_family( $ua ) { $ua = (string) $ua; $map = array( 'Edg/' => 'Edge', 'OPR/' => 'Opera', 'SamsungBrowser' => 'Samsung Internet', 'Firefox/' => 'Firefox', 'Chrome/' => 'Chrome', 'CriOS/' => 'Chrome', 'Version/' => 'Safari', 'MSIE ' => 'Internet Explorer', 'Trident/' => 'Internet Explorer', ); foreach ( $map as $needle => $name ) { if ( false !== strpos( $ua, $needle ) ) { return $name; } } return 'Other'; } /** * A coarse OS family from a UA string. * * @param string $ua UA string. * @return string */ function sxanl_os_family( $ua ) { $ua = (string) $ua; $map = array( 'Windows NT 10' => 'Windows', 'Windows NT' => 'Windows', 'iPhone OS' => 'iOS', 'iPad; CPU OS' => 'iPadOS', 'Mac OS X' => 'macOS', 'Android' => 'Android', 'CrOS' => 'ChromeOS', 'Linux' => 'Linux', ); foreach ( $map as $needle => $name ) { if ( false !== strpos( $ua, $needle ) ) { return $name; } } return 'Other'; } /** * Screen-width bucket label. * * @param int $width Reported CSS pixel width. * @return string */ function sxanl_screen_bucket( $width ) { $width = (int) $width; if ( $width <= 0 ) { return 'unknown'; } if ( $width < 576 ) { return 'xs'; } if ( $width < 768 ) { return 'sm'; } if ( $width < 992 ) { return 'md'; } if ( $width < 1400 ) { return 'lg'; } return 'xl'; } /** * ISO 3166-1 alpha-2 -> English country name map (bundled). * * @return array */ function sxanl_country_names() { static $names = null; if ( null === $names ) { $names = array(); $file = SXANL_DIR . 'data/country-names.json'; if ( is_readable( $file ) ) { $decoded = json_decode( (string) file_get_contents( $file ), true ); // phpcs:ignore WordPress.WP.AlternativeFunctions if ( is_array( $decoded ) ) { $names = $decoded; } } } return $names; } /** * ISO date (Y-m-d) for a unix timestamp in the site's timezone. * * @param int $ts Unix timestamp. Defaults to now. * @return string */ function sxanl_site_date( $ts = null ) { $ts = null === $ts ? time() : (int) $ts; return wp_date( 'Y-m-d', $ts ); }