Files
MageSail/Magesail/Block/Adminhtml/Tunnel.php
T
snxraven 80981cfe62 feat(admin): accept hostname-only tunnel URLs (auto http/https)
TunnelStoreProvisioner expands bare hosts to http:// for unsecure and
https:// for optional secure; full URLs still work. Tunnel block strips
scheme for prefill display. Update tunnel template copy, Index error
text, and README/docs.
2026-03-21 00:11:47 -05:00

132 lines
3.5 KiB
PHP

<?php
declare(strict_types=1);
namespace MageSail\Magesail\Block\Adminhtml;
use Magento\Backend\Block\Template;
use Magento\Backend\Block\Template\Context;
use MageSail\Magesail\Model\TunnelStatus;
use MageSail\Magesail\Model\TunnelStoreProvisioner;
class Tunnel extends Template
{
private const LOG_TAIL_BYTES = 8192;
private const LOG_TAIL_LINES = 40;
public function __construct(
Context $context,
private readonly TunnelStatus $tunnelStatus,
private readonly TunnelStoreProvisioner $tunnelStoreProvisioner,
array $data = []
) {
parent::__construct($context, $data);
}
/**
* @return array{running: bool, pid: int|null, key: string|null}
*/
public function getTunnelStatus(): array
{
return $this->tunnelStatus->getStatus();
}
/**
* Persisted tunnel store (present while tunnel is configured; may exist briefly before PID appears).
*
* @return array{store_id: int, store_code: string, unsecure_base_url: string, secure_base_url: string, use_secure_urls: bool}|null
*/
public function getTunnelStoreState(): ?array
{
return $this->tunnelStoreProvisioner->getPersistedState();
}
public function getTunnelStoreCodeConstant(): string
{
return TunnelStoreProvisioner::STORE_CODE;
}
/**
* Strip scheme for display so Admin shows hostname-only; persisted URLs stay full in state.
*/
public function getTunnelHostDisplay(?string $baseUrl): string
{
if ($baseUrl === null || $baseUrl === '') {
return '';
}
$parts = parse_url($baseUrl);
if ($parts === false || empty($parts['host'])) {
return $baseUrl;
}
$out = $parts['host'];
if (!empty($parts['port'])) {
$out .= ':' . $parts['port'];
}
if (!empty($parts['path']) && $parts['path'] !== '/' && $parts['path'] !== '') {
$out .= rtrim($parts['path'], '/');
}
return $out;
}
public function getConfigUrl(): string
{
return $this->getUrl('adminhtml/system_config/edit/section/magesail');
}
public function getStatusUrl(): string
{
return $this->getUrl('*/*/status');
}
public function getIndexUrl(): string
{
return $this->getUrl('*/*/index');
}
public function getLogtailUrl(): string
{
return $this->getUrl('*/*/logtail');
}
public function getFormKey(): string
{
return $this->formKey->getFormKey();
}
public function getLogFilePath(): string
{
return $this->tunnelStatus->getLogFilePath();
}
/**
* @return string[]
*/
public function getRecentLogLines(): array
{
$path = $this->tunnelStatus->getLogFilePath();
if (!\is_readable($path)) {
return [];
}
$size = filesize($path);
if ($size === false || $size === 0) {
return [];
}
$fp = fopen($path, 'rb');
if ($fp === false) {
return [];
}
$start = max(0, $size - self::LOG_TAIL_BYTES);
fseek($fp, $start);
if ($start > 0) {
fgets($fp);
}
$chunk = stream_get_contents($fp) ?: '';
fclose($fp);
$lines = preg_split('/\R/', $chunk) ?: [];
$lines = array_values(array_filter($lines, static fn ($l) => $l !== ''));
if (\count($lines) > self::LOG_TAIL_LINES) {
$lines = \array_slice($lines, -self::LOG_TAIL_LINES);
}
return $lines;
}
}