|
14 | 14 | namespace Ymir\Plugin\Subscriber; |
15 | 15 |
|
16 | 16 | use Ymir\Plugin\EventManagement\SubscriberInterface; |
| 17 | +use Ymir\Plugin\Support\Collection; |
17 | 18 |
|
18 | 19 | /** |
19 | 20 | * Subscriber for managing the integration between WordPress and the deployed assets. |
@@ -77,6 +78,7 @@ public static function getSubscribedEvents(): array |
77 | 78 | 'plugins_url' => 'rewritePluginsUrl', |
78 | 79 | 'script_loader_src' => 'replaceSiteUrlWithAssetsUrl', |
79 | 80 | 'style_loader_src' => 'replaceSiteUrlWithAssetsUrl', |
| 81 | + 'the_content' => ['replaceUrlsInContent', 99999], // Make the priority high, but less than 999999 which is the Jetpack Photon hook priority |
80 | 82 | 'wp_resource_hints' => ['addAssetsUrlToDnsPrefetch', 10, 2], |
81 | 83 | ]; |
82 | 84 | } |
@@ -116,42 +118,127 @@ public function replaceSiteUrlWithAssetsUrl(string $url): string |
116 | 118 | } |
117 | 119 |
|
118 | 120 | /** |
119 | | - * Rewrite the wp-content URL so it points to the assets URL. |
| 121 | + * Replace broken URLs in the post content so they correctly point to the current assets URL. |
120 | 122 | */ |
121 | | - public function rewriteContentUrl(string $url): string |
| 123 | + public function replaceUrlsInContent(string $content): string |
122 | 124 | { |
123 | | - $matches = []; |
124 | | - preg_match(sprintf('/https?:\/\/.*(%s.*)/', preg_quote($this->contentDirectory, '/')), $url, $matches); |
| 125 | + if (empty($this->assetsUrl)) { |
| 126 | + return $content; |
| 127 | + } |
125 | 128 |
|
126 | | - if (empty($matches[1])) { |
127 | | - return $url; |
| 129 | + // The assumption is that all URLs are surrounded by either quotes or double quotes. |
| 130 | + $patterns = [ |
| 131 | + '%"(?P<url>https?://[^"]*?)"%is', |
| 132 | + "%'(?P<url>https?://[^']*?)'%is", |
| 133 | + ]; |
| 134 | + $urls = new Collection(); |
| 135 | + |
| 136 | + foreach ($patterns as $pattern) { |
| 137 | + $matches = []; |
| 138 | + |
| 139 | + preg_match_all($pattern, $content, $matches); |
| 140 | + |
| 141 | + $urls = $urls->merge($matches['url'] ?? []); |
| 142 | + } |
| 143 | + |
| 144 | + if ($urls->isEmpty()) { |
| 145 | + return $content; |
128 | 146 | } |
129 | 147 |
|
130 | | - return $this->assetsUrl.$matches[1]; |
| 148 | + $assetsHost = parse_url($this->assetsUrl, PHP_URL_HOST); |
| 149 | + $siteHost = parse_url($this->siteUrl, PHP_URL_HOST); |
| 150 | + $uploadsDirectory = $this->contentDirectory.'/uploads'; |
| 151 | + $urls = $urls->unique(); |
| 152 | + |
| 153 | + // If we have a hardcoded URL to an asset, we want to dynamically update it to the |
| 154 | + // current asset URL. |
| 155 | + $assetsUrls = $urls->filter(function (string $url) use ($assetsHost) { |
| 156 | + return parse_url($url, PHP_URL_HOST) === $assetsHost; |
| 157 | + })->mapWithKeys(function (string $url) { |
| 158 | + return [$url => $this->rewriteAssetsUrl('%https?://[^/]*/assets/[^/]*(.*)%i', $url)]; |
| 159 | + })->all(); |
| 160 | + |
| 161 | + // Get all the URLs pointing to the "/wp-content" directory |
| 162 | + $contentUrls = $urls->filter(function (string $url) use ($siteHost) { |
| 163 | + return parse_url($url, PHP_URL_HOST) === $siteHost; |
| 164 | + })->filter(function (string $url) { |
| 165 | + return 0 === stripos(parse_url($url, PHP_URL_PATH), $this->contentDirectory); |
| 166 | + }); |
| 167 | + |
| 168 | + // Point all non-uploads "/wp-content" URLs to the assets URL. |
| 169 | + $nonUploadsUrls = $contentUrls->filter(function (string $url) use ($uploadsDirectory) { |
| 170 | + return false === stripos(parse_url($url, PHP_URL_PATH), $uploadsDirectory); |
| 171 | + })->mapWithKeys(function (string $url) { |
| 172 | + return [$url => $this->rewriteAssetsUrl(sprintf('%%https?://[^/]*(%s.*)%%', $this->contentDirectory), $url)]; |
| 173 | + })->all(); |
| 174 | + |
| 175 | + // Point all URLs to "/wp-content/uploads" to the uploads URL. |
| 176 | + $uploadsUrls = $contentUrls->filter(function (string $url) use ($uploadsDirectory) { |
| 177 | + return 0 === stripos(parse_url($url, PHP_URL_PATH), $uploadsDirectory); |
| 178 | + })->mapWithKeys(function (string $url) use ($uploadsDirectory) { |
| 179 | + return [$url => $this->rewriteUploadsUrl(sprintf('%%https?://[^/]*%s(.*)%%', $uploadsDirectory), $url)]; |
| 180 | + })->all(); |
| 181 | + |
| 182 | + foreach (array_merge($assetsUrls, $nonUploadsUrls, $uploadsUrls) as $originalUrl => $newUrl) { |
| 183 | + $content = str_replace($originalUrl, $newUrl, $content); |
| 184 | + } |
| 185 | + |
| 186 | + return $content; |
| 187 | + } |
| 188 | + |
| 189 | + /** |
| 190 | + * Rewrite the wp-content URL so it points to the assets URL. |
| 191 | + */ |
| 192 | + public function rewriteContentUrl(string $url): string |
| 193 | + { |
| 194 | + return $this->rewriteAssetsUrl(sprintf('%%https?://.*(%s.*)%%', $this->contentDirectory), $url); |
131 | 195 | } |
132 | 196 |
|
133 | 197 | /** |
134 | 198 | * Rewrite the plugins URL so it points to the assets URL. |
135 | 199 | */ |
136 | 200 | public function rewritePluginsUrl(string $url): string |
| 201 | + { |
| 202 | + return $this->rewriteAssetsUrl('%https?://.*(/[^/]*/plugins.*)%', $url); |
| 203 | + } |
| 204 | + |
| 205 | + /** |
| 206 | + * Check if we need to rewrite the given URL. |
| 207 | + */ |
| 208 | + private function doesUrlNeedRewrite(string $url): bool |
| 209 | + { |
| 210 | + return false !== stripos($url, $this->siteUrl) |
| 211 | + && (!empty($this->assetsUrl) && false === stripos($url, $this->assetsUrl)) |
| 212 | + && (empty($this->uploadsUrl) || false === stripos($url, $this->uploadsUrl)); |
| 213 | + } |
| 214 | + |
| 215 | + /** |
| 216 | + * Rewrite the given URL to point to the assets URL based on the given REGEX pattern. |
| 217 | + */ |
| 218 | + private function rewriteAssetsUrl(string $pattern, string $url): string |
137 | 219 | { |
138 | 220 | $matches = []; |
139 | | - preg_match('/https?:\/\/.*(\/[^\/]*\/plugins.*)/', $url, $matches); |
| 221 | + preg_match($pattern, $url, $matches); |
140 | 222 |
|
141 | 223 | if (empty($matches[1])) { |
142 | 224 | return $url; |
143 | 225 | } |
144 | 226 |
|
145 | | - return $this->assetsUrl.$matches[1]; |
| 227 | + return $this->assetsUrl.'/'.ltrim($matches[1], '/'); |
146 | 228 | } |
147 | 229 |
|
148 | 230 | /** |
149 | | - * Check if we need to rewrite the given URL. |
| 231 | + * Rewrite the given URL to point to the uploads URL based on the given REGEX pattern. |
150 | 232 | */ |
151 | | - private function doesUrlNeedRewrite(string $url): bool |
| 233 | + private function rewriteUploadsUrl(string $pattern, string $url): string |
152 | 234 | { |
153 | | - return false !== stripos($url, $this->siteUrl) |
154 | | - && (!empty($this->assetsUrl) && false === stripos($url, $this->assetsUrl)) |
155 | | - && (empty($this->uploadsUrl) || false === stripos($url, $this->uploadsUrl)); |
| 235 | + $matches = []; |
| 236 | + preg_match($pattern, $url, $matches); |
| 237 | + |
| 238 | + if (empty($matches[1])) { |
| 239 | + return $url; |
| 240 | + } |
| 241 | + |
| 242 | + return $this->uploadsUrl.'/'.ltrim($matches[1], '/'); |
156 | 243 | } |
157 | 244 | } |
0 commit comments