$from the site the data comes from (other keys, such as "network", are ignored) * @param array $to the site it goes to * @return array find => replace, longest first; empty when nothing differs */ public static function map(array $from, array $to): array { $map = []; // [from key, to key]; home_url last: it wins where two keys map the same text. $urls = [['content_url', 'content_url'], ['alt_content_url', 'content_url'], ['uploads_url', 'uploads_url'], ['alt_uploads_url', 'uploads_url'], ['site_url', 'site_url'], ['home_url', 'home_url']]; foreach ($urls as [$from_key, $to_key]) { $old = self::split_url((string) ($from[$from_key] ?? '')); $new = self::split_url((string) ($to[$to_key] ?? '')); if ($old === null || $new === null || $old === $new) { continue; } $map['https://' . $old[1]] = $new[0] . '://' . $new[1]; $map['http://' . $old[1]] = $new[0] . '://' . $new[1]; $map['//' . $old[1]] = '//' . $new[1]; // URL-encoded too, as Elementor keeps a dynamic tag's settings (encodeURIComponent: "https%3A%2F%2F…"). foreach (['https://', 'http://'] as $scheme) { $map[rawurlencode($scheme . $old[1])] = rawurlencode($new[0] . '://' . $new[1]); } } foreach (['uploads_dir', 'path'] as $key) { $old_path = rtrim((string) ($from[$key] ?? ''), '/'); $new_path = rtrim((string) ($to[$key] ?? ''), '/'); // A one-segment path such as "/app" could also appear inside URLs, so only real paths are mapped. if (substr_count($old_path, '/') >= 2 && $new_path !== '') { $map[$old_path] = $new_path; } } foreach ($map as $find => $replace) { $map[str_replace('/', '\\/', $find)] = str_replace('/', '\\/', $replace); } $map = array_filter($map, static fn ($replace, $find) => $find !== $replace, ARRAY_FILTER_USE_BOTH); uksort($map, static fn ($a, $b) => strlen($b) <=> strlen($a) ?: strcmp($a, $b)); return $map; } /** @return array{0: string, 1: string}|null scheme and "host[:port][/path]" without a trailing slash */ private static function split_url(string $url): ?array { if (!preg_match('#^(https?)://([^/?\#]+)(/[^?\#]*)?#i', trim($url), $m)) { return null; } return [strtolower($m[1]), strtolower($m[2]) . rtrim($m[3] ?? '', '/')]; } }