279 lines
11 KiB
PHP
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');
|
|
}
|
|
}
|