Files
MageSail/Magesail/Controller/Adminhtml/Nginx/Map.php
T
2026-03-21 03:01:08 -05:00

279 lines
11 KiB
PHP

<?php
declare(strict_types=1);
namespace MageSail\Magesail\Controller\Adminhtml\Nginx;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Exception\LocalizedException;
use MageSail\Magesail\Model\NginxGlobalMapManager;
use MageSail\Magesail\Model\NginxMapParser;
use MageSail\Magesail\Model\TunnelStoreProvisioner;
class Map extends Action
{
public function __construct(
Context $context,
private readonly NginxGlobalMapManager $nginxMapManager,
private readonly NginxMapParser $mapParser,
private readonly TunnelStoreProvisioner $tunnelStoreProvisioner
) {
parent::__construct($context);
}
public function execute()
{
$action = $this->getRequest()->getParam('action');
$wantJson = $this->isAjaxRequest();
if ($action === 'read') {
return $this->handleRead($wantJson);
}
if ($action === 'write') {
return $this->handleWrite($wantJson);
}
if ($action === 'validate') {
return $this->handleValidate($wantJson);
}
if ($action === 'reload') {
return $this->handleReload($wantJson);
}
if ($action === 'parse') {
return $this->handleParse($wantJson);
}
if ($action === 'save_blocks') {
return $this->handleSaveBlocks($wantJson);
}
if ($action === 'diagnostics') {
return $this->handleDiagnostics($wantJson);
}
$resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
$resultPage->setActiveMenu('MageSail_Magesail::nginx_map');
$resultPage->getConfig()->getTitle()->prepend(__('NGINX Global Map'));
return $resultPage;
}
private function isAjaxRequest(): bool
{
return strtolower((string) $this->getRequest()->getHeader('X-Requested-With')) === 'xmlhttprequest'
|| (string) $this->getRequest()->getParam('ajax') === '1';
}
private function jsonResponse(bool $success, string $message = '', array $data = [])
{
$json = $this->resultFactory->create(ResultFactory::TYPE_JSON);
$json->setData(array_merge([
'success' => $success,
'message' => $message,
], $data));
return $json;
}
private function handleRead(bool $wantJson)
{
try {
$content = $this->nginxMapManager->readMapFile();
if ($wantJson) {
return $this->jsonResponse(true, '', ['content' => $content]);
}
$this->messageManager->addSuccessMessage(__('Map file loaded.'));
return $this->_redirect('*/*/map');
} catch (LocalizedException $e) {
if ($wantJson) {
return $this->jsonResponse(false, (string) $e->getMessage());
}
$this->messageManager->addErrorMessage($e->getMessage());
return $this->_redirect('*/*/map');
}
}
private function handleWrite(bool $wantJson)
{
$content = (string) $this->getRequest()->getParam('content', '');
try {
$this->nginxMapManager->writeMapFile($content);
$validation = $this->nginxMapManager->validateNginxConfig();
if ($wantJson) {
return $this->jsonResponse(
true,
(string) ($validation['valid'] ? __('Map file saved and validated.') : __('Map file saved, but NGINX validation failed.')),
['validation' => $validation]
);
}
if ($validation['valid']) {
$this->messageManager->addSuccessMessage(__('Map file saved and validated.'));
} else {
$this->messageManager->addWarningMessage(__('Map file saved, but NGINX validation failed: %1', $validation['error'] ?? ''));
}
return $this->_redirect('*/*/map');
} catch (LocalizedException $e) {
if ($wantJson) {
return $this->jsonResponse(false, (string) $e->getMessage());
}
$this->messageManager->addErrorMessage($e->getMessage());
return $this->_redirect('*/*/map');
} catch (\Throwable $e) {
if ($wantJson) {
return $this->jsonResponse(false, (string) __('Could not save map file: %1', $e->getMessage()));
}
$this->messageManager->addErrorMessage((string) __('Could not save map file: %1', $e->getMessage()));
return $this->_redirect('*/*/map');
}
}
private function handleValidate(bool $wantJson)
{
$validation = $this->nginxMapManager->validateNginxConfig();
if ($wantJson) {
return $this->jsonResponse($validation['valid'], '', ['validation' => $validation]);
}
if ($validation['valid']) {
$this->messageManager->addSuccessMessage(__('NGINX configuration is valid.'));
} else {
$this->messageManager->addErrorMessage(__('NGINX configuration validation failed: %1', $validation['error'] ?? ''));
}
return $this->_redirect('*/*/map');
}
private function handleReload(bool $wantJson)
{
$validation = $this->nginxMapManager->validateAndReload();
if ($validation['valid'] && $validation['reloaded']) {
$this->tunnelStoreProvisioner->clearNginxPendingReloadFlag();
}
if ($wantJson) {
return $this->jsonResponse(
$validation['valid'] && $validation['reloaded'],
(string) ($validation['valid'] && $validation['reloaded']
? __('NGINX validated and reloaded successfully.')
: ($validation['error'] ?? __('NGINX validation or reload failed.'))),
['validation' => $validation]
);
}
if ($validation['valid'] && $validation['reloaded']) {
$this->messageManager->addSuccessMessage(__('NGINX validated and reloaded successfully.'));
} else {
$this->messageManager->addErrorMessage(__('NGINX validation or reload failed: %1', $validation['error'] ?? ''));
}
return $this->_redirect('*/*/map');
}
private function handleParse(bool $wantJson)
{
try {
$content = $this->nginxMapManager->readMapFile();
$parsed = $this->mapParser->parse($content);
if ($wantJson) {
return $this->jsonResponse(true, '', ['parsed' => $parsed, 'raw' => $content]);
}
return $this->_redirect('*/*/map');
} catch (LocalizedException $e) {
if ($wantJson) {
return $this->jsonResponse(false, (string) $e->getMessage());
}
$this->messageManager->addErrorMessage($e->getMessage());
return $this->_redirect('*/*/map');
}
}
private function handleSaveBlocks(bool $wantJson)
{
try {
$original = $this->nginxMapManager->readMapFile();
$blocksJson = (string) $this->getRequest()->getParam('blocks', '');
$guiBlocks = json_decode($blocksJson, true);
if (!\is_array($guiBlocks)) {
throw new LocalizedException(__('Invalid blocks data (JSON).'));
}
$fileParsed = $this->mapParser->parse($original);
$fileBlocks = $fileParsed['blocks'];
if (\count($guiBlocks) !== \count($fileBlocks)) {
throw new LocalizedException(__(
'Block count mismatch (%1 in editor, %2 in file). Click "Parse & Load Blocks" and try again.',
\count($guiBlocks),
\count($fileBlocks)
));
}
$mergedBlocks = [];
foreach ($fileBlocks as $idx => $fileBlock) {
$g = $guiBlocks[$idx] ?? null;
if (!\is_array($g)) {
throw new LocalizedException(__('Invalid block at index %1.', $idx));
}
$src = (string) ($g['source'] ?? '');
$tgt = (string) ($g['target'] ?? '');
if ($src !== $fileBlock['source'] || $tgt !== $fileBlock['target']) {
throw new LocalizedException(__(
'Map $%1 $%2 no longer matches the file. Click "Parse & Load Blocks" again.',
$src,
$tgt
));
}
$rawEntries = $g['entries'] ?? [];
if (!\is_array($rawEntries)) {
throw new LocalizedException(__('Invalid entries for map $%1 $%2.', $src, $tgt));
}
$entries = [];
foreach ($rawEntries as $e) {
if (!\is_array($e)) {
continue;
}
$entries[] = [
'hostname' => (string) ($e['hostname'] ?? ''),
'value' => (string) ($e['value'] ?? ''),
'comment' => isset($e['comment']) && $e['comment'] !== '' && $e['comment'] !== null
? (string) $e['comment']
: null,
];
}
$mergedBlocks[] = array_merge($fileBlock, ['entries' => $entries]);
}
$newContent = $this->mapParser->rebuild($original, ['blocks' => $mergedBlocks]);
$this->nginxMapManager->writeMapFile($newContent);
$validation = $this->nginxMapManager->validateNginxConfig();
if ($wantJson) {
return $this->jsonResponse(
true,
(string) ($validation['valid'] ? __('Map blocks saved and validated.') : __('Map blocks saved, but NGINX validation failed.')),
['validation' => $validation]
);
}
if ($validation['valid']) {
$this->messageManager->addSuccessMessage(__('Map blocks saved and validated.'));
} else {
$this->messageManager->addWarningMessage(__('Map blocks saved, but NGINX validation failed: %1', $validation['error'] ?? ''));
}
return $this->_redirect('*/*/map');
} catch (LocalizedException $e) {
if ($wantJson) {
return $this->jsonResponse(false, (string) $e->getMessage());
}
$this->messageManager->addErrorMessage($e->getMessage());
return $this->_redirect('*/*/map');
} catch (\Throwable $e) {
if ($wantJson) {
return $this->jsonResponse(false, (string) __('Could not save map blocks: %1', $e->getMessage()));
}
$this->messageManager->addErrorMessage((string) __('Could not save map blocks: %1', $e->getMessage()));
return $this->_redirect('*/*/map');
}
}
private function handleDiagnostics(bool $wantJson)
{
$diag = $this->nginxMapManager->getDiagnostics();
if ($wantJson) {
return $this->jsonResponse(true, '', ['diagnostics' => $diag]);
}
return $this->_redirect('*/*/map');
}
protected function _isAllowed()
{
return $this->_authorization->isAllowed('MageSail_Magesail::config');
}
}