Files
MageSail/Magesail/Plugin/Store/TunnelStoreBaseUrlPlugin.php
T
2026-03-20 23:48:02 -05:00

92 lines
3.3 KiB
PHP

<?php
declare(strict_types=1);
namespace MageSail\Magesail\Plugin\Store;
use Magento\Framework\App\Request\Http;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\UrlInterface;
use Magento\Store\Model\Store;
use MageSail\Magesail\Model\TunnelRequestDetector;
use MageSail\Magesail\Model\TunnelStoreState;
/**
* With tunnel proxy, HTTP_HOST is dev.myshop.local but store base URLs point at production (e.g. s1.x64.world).
* Rewrite scheme/host for page/link base URLs only — never for static/media/js or asset bases break (404).
* When persisted tunnel base URLs use a different path than production (e.g. no /pub/), use the tunnel path so
* backend URI validation matches the browser.
*/
class TunnelStoreBaseUrlPlugin
{
public function __construct(
private readonly RequestInterface $request,
private readonly TunnelRequestDetector $tunnelRequestDetector,
private readonly TunnelStoreState $tunnelStoreState
) {
}
/**
* @param Store $subject
* @param string $result
* @return string
*/
public function afterGetBaseUrl(Store $subject, $result, $type = null, $secure = null)
{
if (!$this->request instanceof Http || $result === '' || $result === null) {
return $result;
}
$effectiveType = $type ?? UrlInterface::URL_TYPE_LINK;
if (!\in_array($effectiveType, [
UrlInterface::URL_TYPE_LINK,
UrlInterface::URL_TYPE_DIRECT_LINK,
UrlInterface::URL_TYPE_WEB,
], true)) {
return $result;
}
if ($this->tunnelRequestDetector->getTunnelStoreCode($this->request) === null) {
return $result;
}
$parts = parse_url($result);
if ($parts === false || empty($parts['host'])) {
return $result;
}
$requestHost = $this->request->getHttpHost();
if ($requestHost === '' || strcasecmp((string) $parts['host'], $requestHost) === 0) {
return $result;
}
$scheme = $this->request->isSecure() ? 'https' : 'http';
$path = $this->pathForTunnelRewrite($scheme, $parts['path'] ?? '/');
$query = isset($parts['query']) ? '?' . $parts['query'] : '';
$fragment = isset($parts['fragment']) ? '#' . $parts['fragment'] : '';
return $scheme . '://' . $requestHost . $path . $query . $fragment;
}
/**
* Prefer path from persisted tunnel base URL (matches holesail vhost) when production base path differs.
*/
private function pathForTunnelRewrite(string $scheme, string $fallbackPath): string
{
$state = $this->tunnelStoreState->read();
if ($state === null) {
return $fallbackPath;
}
$preferSecure = $scheme === 'https';
$ref = $preferSecure ? $state['secure_base_url'] : $state['unsecure_base_url'];
if (trim($ref) === '') {
$ref = $preferSecure ? $state['unsecure_base_url'] : $state['secure_base_url'];
}
if (trim($ref) === '') {
return $fallbackPath;
}
$parsed = parse_url($ref);
if ($parsed === false) {
return $fallbackPath;
}
$path = $parsed['path'] ?? '';
if ($path === '' || $path === null) {
return '/';
}
return $path;
}
}