Files
MageSail/Magesail/Plugin/App/Request/StoreFromMageSailHeaderPlugin.php
T
snxraven cc456a4cfa feat(magesail): multi-tunnel registry, per-tunnel stores, and admin UX
- Add TunnelRegistry (var/magesail_tunnels.json) and TunnelProcessPaths;
  migrate legacy magesail_tunnel_store.json and PID/key files
- Provision unique store codes per tunnel; website/group selection;
  stop vs remove; per-tunnel NGINX map, cron, status/logtail
- Fix log path: use DirectoryList::LOG (not LOG_DIR)
- Ignore missing store codes for MAGE_RUN_* (stale nginx / magesail_tunnel)
- Allow duplicate local ports; Admin port presets 443/80/8080 + custom;
  update docs and system.xml comments
2026-03-21 00:49:07 -05:00

94 lines
3.3 KiB
PHP

<?php
declare(strict_types=1);
namespace MageSail\Magesail\Plugin\App\Request;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Store\Api\StoreRepositoryInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\StoreManager;
use MageSail\Magesail\Model\AdminPathDetector;
use MageSail\Magesail\Model\TunnelRequestDetector;
/**
* When request has X-MageSail-Store-Code header or magesail_store query param (from tunnel proxy),
* make getServerValue return it for MAGE_RUN_CODE and 'store' for MAGE_RUN_TYPE so Magento serves that store.
*
* Admin URLs must not use nginx tunnel map values: StoreResolver is built from MAGE_RUN_* init params; if they
* stay as the tunnel store, admin can 404. For admin paths we force website scope and empty run code so the
* default website is used (same as a normal request without per-host map).
*
* If NGINX still injects a removed store code (e.g. legacy magesail_tunnel), strip it so StoreResolver
* falls back instead of throwing NoSuchEntityException (including on error pages).
*/
class StoreFromMageSailHeaderPlugin
{
public function __construct(
private readonly AdminPathDetector $adminPathDetector,
private readonly TunnelRequestDetector $tunnelRequestDetector,
private readonly StoreRepositoryInterface $storeRepository
) {
}
/**
* Around getServerValue: if MageSail store header is set, return it for MAGE_RUN_CODE / MAGE_RUN_TYPE.
*
* @param Http $subject
* @param callable $proceed
* @param string|null $name
* @param mixed $default
* @return mixed
*/
public function aroundGetServerValue(Http $subject, callable $proceed, $name = null, $default = null)
{
if ($this->adminPathDetector->isAdminPath($subject)) {
if ($name === StoreManager::PARAM_RUN_TYPE) {
return ScopeInterface::SCOPE_WEBSITE;
}
if ($name === StoreManager::PARAM_RUN_CODE) {
return '';
}
return $proceed($name, $default);
}
$tunnelCode = $this->tunnelRequestDetector->getTunnelStoreCode($subject);
$nginxCode = trim((string) $subject->getServer(StoreManager::PARAM_RUN_CODE));
$candidate = ($tunnelCode !== null && $tunnelCode !== '')
? $tunnelCode
: $nginxCode;
if ($candidate !== '' && !$this->storeCodeExists($candidate)) {
if ($name === StoreManager::PARAM_RUN_CODE) {
return '';
}
if ($name === StoreManager::PARAM_RUN_TYPE) {
return ScopeInterface::SCOPE_WEBSITE;
}
return $proceed($name, $default);
}
if ($tunnelCode !== null && $tunnelCode !== '') {
if ($name === StoreManager::PARAM_RUN_CODE) {
return $tunnelCode;
}
if ($name === StoreManager::PARAM_RUN_TYPE) {
return 'store';
}
return $proceed($name, $default);
}
return $proceed($name, $default);
}
private function storeCodeExists(string $code): bool
{
try {
$this->storeRepository->get($code);
return true;
} catch (NoSuchEntityException) {
return false;
}
}
}