1 | <?php |
||
2 | /** |
||
3 | * Retour plugin for Craft CMS |
||
4 | * |
||
5 | * Retour allows you to intelligently redirect legacy URLs, so that you don't |
||
6 | * lose SEO value when rebuilding & restructuring a website |
||
7 | * |
||
8 | * @link https://nystudio107.com/ |
||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||
9 | * @copyright Copyright (c) 2020 nystudio107 |
||
0 ignored issues
–
show
|
|||
10 | */ |
||
0 ignored issues
–
show
|
|||
11 | |||
12 | namespace nystudio107\retour\helpers; |
||
13 | |||
14 | use Craft; |
||
15 | use craft\errors\SiteNotFoundException; |
||
16 | use craft\helpers\UrlHelper as CraftUrlHelper; |
||
17 | |||
18 | /** |
||
0 ignored issues
–
show
|
|||
19 | * @author nystudio107 |
||
0 ignored issues
–
show
Content of the @author tag must be in the form "Display Name <[email protected]>"
![]() |
|||
20 | * @package Retour |
||
0 ignored issues
–
show
|
|||
21 | * @since 3.1.34 |
||
0 ignored issues
–
show
|
|||
22 | */ |
||
0 ignored issues
–
show
|
|||
23 | class UrlHelper extends CraftUrlHelper |
||
24 | { |
||
25 | // Public Static Methods |
||
26 | // ========================================================================= |
||
27 | |||
28 | /** |
||
29 | * Returns a query string that is a combination of al of the query strings from |
||
30 | * the passed in $urls |
||
31 | * |
||
32 | * @param ...$urls |
||
0 ignored issues
–
show
|
|||
33 | * @return string |
||
0 ignored issues
–
show
|
|||
34 | */ |
||
35 | public static function combineQueryStringsFromUrls(...$urls): string |
||
36 | { |
||
37 | $queryParams = []; |
||
38 | foreach ($urls as $url) { |
||
39 | $parsedUrl = parse_url($url); |
||
40 | $params = []; |
||
41 | parse_str($parsedUrl['query'] ?? '', $params); |
||
42 | $queryParams[] = $params; |
||
43 | } |
||
44 | $queryParams = array_unique(array_merge([], ...$queryParams), SORT_REGULAR); |
||
45 | |||
46 | return http_build_query($queryParams); |
||
47 | } |
||
48 | |||
49 | /** |
||
50 | * Strip out any site-defined sub-path from the incoming $path |
||
51 | * e.g. if the Site's baseUrl is set to https://example.com/es and $path is /es/blog |
||
52 | * this function will return /blog |
||
53 | * |
||
54 | * @param string $path |
||
0 ignored issues
–
show
|
|||
55 | * @return string |
||
0 ignored issues
–
show
|
|||
56 | */ |
||
57 | public static function stripSitePathPrefix(string $path): string |
||
58 | { |
||
59 | try { |
||
60 | $baseSiteUrl = self::baseSiteUrl(); |
||
61 | } catch (SiteNotFoundException $e) { |
||
62 | $baseSiteUrl = ''; |
||
63 | } |
||
64 | $sitePath = parse_url($baseSiteUrl, PHP_URL_PATH); |
||
65 | $addSlash = str_ends_with($path, '/'); |
||
66 | if (!empty($sitePath)) { |
||
67 | // Normalizes a URI path by trimming leading/ trailing slashes and removing double slashes |
||
68 | $sitePath = '/' . preg_replace('/\/\/+/', '/', trim($sitePath, '/')); |
||
69 | } |
||
70 | // Strip the $sitePath from the incoming $path |
||
71 | if (str_starts_with($path, $sitePath)) { |
||
72 | $path = substr($path, strlen($sitePath)); |
||
73 | $path = '/' . preg_replace('/\/\/+/', '/', trim($path, '/')); |
||
74 | } |
||
75 | $path = $addSlash ? $path . '/' : $path; |
||
76 | |||
77 | return $path; |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * See if the path includes a site prefix for any site |
||
82 | * |
||
83 | * @param string $path |
||
0 ignored issues
–
show
|
|||
84 | * @return bool |
||
0 ignored issues
–
show
|
|||
85 | */ |
||
86 | public static function pathHasSitePrefix(string $path): bool |
||
87 | { |
||
88 | $sites = Craft::$app->getSites()->getAllSites(); |
||
89 | foreach ($sites as $site) { |
||
90 | $sitePath = parse_url($site->baseUrl, PHP_URL_PATH); |
||
91 | if (!empty($sitePath)) { |
||
92 | // Normalizes a URI path by trimming leading/ trailing slashes and removing double slashes |
||
93 | $sitePath = '/' . preg_replace('/\/\/+/', '/', trim($sitePath, '/')); |
||
94 | } |
||
95 | // See if the path begins with a site path prefix |
||
96 | if ($sitePath !== '/' && str_starts_with($path, $sitePath)) { |
||
97 | return true; |
||
98 | } |
||
99 | } |
||
100 | |||
101 | return false; |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * Merge the $url and $path together, combining any overlapping path segments |
||
106 | * |
||
107 | * @param ?string $url |
||
0 ignored issues
–
show
|
|||
108 | * @param ?string $path |
||
0 ignored issues
–
show
|
|||
109 | * @return string |
||
0 ignored issues
–
show
|
|||
110 | */ |
||
111 | public static function mergeUrlWithPath(?string $url, ?string $path): string |
||
112 | { |
||
113 | $overlap = 0; |
||
114 | $url = $url ?? ''; |
||
115 | $path = $path ?? ''; |
||
116 | $url = rtrim($url, '/') . '/'; |
||
117 | $path = '/' . ltrim($path, '/'); |
||
118 | $urlOffset = strlen($url); |
||
119 | $pathLength = strlen($path); |
||
120 | $pathOffset = 0; |
||
121 | while ($urlOffset > 0 && $pathOffset < $pathLength) { |
||
122 | $urlOffset--; |
||
123 | $pathOffset++; |
||
124 | if (str_starts_with($path, substr($url, $urlOffset, $pathOffset))) { |
||
125 | $overlap = $pathOffset; |
||
126 | } |
||
127 | } |
||
128 | |||
129 | return rtrim($url, '/') . '/' . ltrim(substr($path, $overlap), '/'); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Return a sanitized URL |
||
134 | * |
||
135 | * @param string $url |
||
0 ignored issues
–
show
|
|||
136 | * |
||
137 | * @return string |
||
138 | */ |
||
139 | public static function sanitizeUrl(string $url): string |
||
140 | { |
||
141 | // HTML decode the entities, then strip out any tags |
||
142 | $url = html_entity_decode($url, ENT_NOQUOTES, 'UTF-8'); |
||
143 | $url = urldecode($url); |
||
144 | $url = strip_tags($url); |
||
145 | // Remove any Twig tags that somehow are present in the incoming URL |
||
146 | /** @noinspection CallableParameterUseCaseInTypeContextInspection */ |
||
0 ignored issues
–
show
|
|||
147 | $url = preg_replace('/{.*}/', '', $url); |
||
148 | // Remove any linebreaks that may be errantly in the URL |
||
149 | $url = (string)str_replace([ |
||
0 ignored issues
–
show
|
|||
150 | PHP_EOL, |
||
151 | "\r", |
||
152 | "\n", |
||
153 | ] |
||
154 | , '', $url |
||
0 ignored issues
–
show
|
|||
155 | ); |
||
156 | |||
157 | return $url; |
||
158 | } |
||
159 | } |
||
160 |