PluginProbe ʕ •ᴥ•ʔ
Reviews Feed – Add Testimonials and Customer Reviews From Google Reviews, Yelp, TripAdvisor, and More / trunk
Reviews Feed – Add Testimonials and Customer Reviews From Google Reviews, Yelp, TripAdvisor, and More vtrunk
2.8.0 2.7.0 2.6.7 2.6.8 2.6.5 2.6.4 2.6.3 2.6.2 2.6.0 2.5.5 2.5.4 2.5.3 2.5.2 trunk 1.0 1.0.1 1.0.2 1.0.3 1.1 1.1.1 1.1.2 1.2.0 2.0 2.1.0 2.1.1 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5.0 2.5.1
reviews-feed / class / Common / Support / UrlNormalization.php
reviews-feed / class / Common / Support Last commit date
UrlNormalization.php 2 months ago
UrlNormalization.php
112 lines
1 <?php
2
3 /**
4 * URL Normalization Trait
5 *
6 * @package SmashBalloon\Reviews\Common\Support
7 */
8
9 namespace SmashBalloon\Reviews\Common\Support;
10
11 /**
12 * Byte-stable URL normalization used to compare URLs that may differ only in
13 * casing, scheme, or trailing slash. Mirrors the server-side trait at
14 * `SmashBalloon\Backoffice\Support\UrlNormalization` in sb-relay so that
15 * the plugin's view of a URL matches whatever the relay has on file.
16 *
17 * See SMASH-1274 (server-side) and SMASH-1281 (this plugin-side companion).
18 */
19 trait UrlNormalization
20 {
21 /**
22 * Normalize a URL to a byte-stable form.
23 *
24 * - Lowercases scheme and host
25 * - Preserves any non-default port
26 * - Strips a trailing slash on the path
27 * - Preserves query string verbatim
28 * - Leaves `www.` untouched
29 * - Returns the original string unchanged if the URL is malformed
30 *
31 * @param string $url
32 *
33 * @return string
34 */
35 public function normalize_url($url)
36 {
37 if (!is_string($url) || $url === '') {
38 return '';
39 }
40 $parts = parse_url($url);
41 if ($parts === false || empty($parts['host'])) {
42 return $url;
43 }
44 $scheme = strtolower($parts['scheme'] ?? 'https');
45 $host = strtolower($parts['host']);
46 $port = isset($parts['port']) ? ':' . $parts['port'] : '';
47 $path = rtrim($parts['path'] ?? '', '/');
48 $query = isset($parts['query']) ? '?' . $parts['query'] : '';
49 return "{$scheme}://{$host}{$port}{$path}{$query}";
50 }
51
52 /**
53 * Normalized form with the scheme stripped, so http and https variants
54 * of the same URL compare equal. Used by detect_site_migration.
55 */
56 public function normalize_url_scheme_agnostic($url)
57 {
58 $normalized = $this->normalize_url($url);
59 $stripped = preg_replace('#^https?://#i', '', $normalized);
60 return is_string($stripped) ? $stripped : $normalized;
61 }
62
63 /**
64 * Host-only normalized form: scheme + path + query dropped, plus the
65 * round-8 (Patch B) strip set on the host itself: port (`:80`/`:443`),
66 * leading `www.`, and trailing dot. The port strip is critical for
67 * reverse-proxy environments (Cloudflare, AWS ALB, Nginx with `$host`
68 * vs `$http_host`) where the same site oscillates between `host` and
69 * `host:80` across requests; without it, `detect_site_migration`
70 * would falsely detect a migration on every port-drift request.
71 *
72 * Used by detect_site_migration so:
73 * - WPML/Polylang language path variants (`/pt-br/`, `/en/`, `/de/`)
74 * - reverse-proxy port drift (`:80`/`:443` injected by upstream)
75 * - canonical drift (`www.example.com` ↔ `example.com`)
76 * - FQDN form (`example.com.` ↔ `example.com`)
77 * on the same WordPress install don't register as a migration.
78 *
79 * Multisite subsites stay distinct because each subsite has its own
80 * hostname or its own `sbr_settings` store. Plugin-side this trait
81 * is byte-for-byte semantically identical to the relay's mirror at
82 * `app/Support/UrlNormalization::normalize_url_host_only` so plugin
83 * and relay agree on what counts as the same install.
84 */
85 public function normalize_url_host_only($url)
86 {
87 if (!is_string($url) || $url === '') {
88 return '';
89 }
90 $parts = parse_url($url);
91 if ($parts === false || empty($parts['host'])) {
92 return $url;
93 }
94 // Migration-detection compares site identity, not network endpoints.
95 // Strip:
96 // - port: a reverse-proxy-injected ":80"/":443" (Cloudflare, AWS ALB,
97 // Nginx with $host vs $http_host) is not a migration. This was the
98 // residual SMASH-1274 loop driver — same site oscillating between
99 // "host" and "host:80" depending on request path.
100 // - leading "www.": canonical-URL drift between get_home_url()
101 // returning "www.example.com" on one request and "example.com" on
102 // another (non-canonical permalinks, multisite alias mapping) is
103 // not a migration.
104 // - trailing dot: "example.com." is the same WP install as
105 // "example.com" (FQDN vs short form).
106 $host = strtolower($parts['host']);
107 $host = preg_replace('/^www\./', '', $host);
108 $host = rtrim($host, '.');
109 return $host;
110 }
111 }
112