feat: derive autoresponder schedule from backend
This commit is contained in:
@@ -108,14 +108,16 @@ final class AppContext
|
||||
|
||||
private function scripts(): string
|
||||
{
|
||||
return <<<'JS'
|
||||
$selectedLabel = json_encode($this->t('Selected'), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
|
||||
return <<<JS
|
||||
(function () {
|
||||
var selectedLabel = {$selectedLabel};
|
||||
document.querySelectorAll('[data-date-value]').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
var target = document.getElementById(btn.getAttribute('data-date-target'));
|
||||
var label = document.getElementById(btn.getAttribute('data-date-label'));
|
||||
if (target) { target.value = btn.getAttribute('data-date-value') || ''; }
|
||||
if (label) { label.textContent = 'Wybrano: ' + (btn.getAttribute('data-date-value') || ''); }
|
||||
if (label) { label.textContent = selectedLabel + ': ' + (btn.getAttribute('data-date-value') || ''); }
|
||||
btn.closest('.br-restore-calendar').querySelectorAll('.br-cal-day').forEach(function (d) { d.classList.remove('is-selected'); });
|
||||
btn.classList.add('is-selected');
|
||||
});
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
final class BackendRuntimeConfig
|
||||
{
|
||||
public static function sync(Settings $settings, string $backendScript, string $statePath = Settings::CONFIG_DIR . '/backend-state.json', string $errorLog = ''): void
|
||||
{
|
||||
$desired = $settings->backendMode();
|
||||
$current = self::currentBackend($statePath);
|
||||
if ($current === $desired) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_file($backendScript) || !is_executable($backendScript)) {
|
||||
self::log($errorLog, 'Backend script not executable: ' . $backendScript);
|
||||
return;
|
||||
}
|
||||
|
||||
$process = proc_open([$backendScript, $desired], [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipes);
|
||||
if (!is_resource($process)) {
|
||||
self::log($errorLog, 'Could not start backend script.');
|
||||
return;
|
||||
}
|
||||
fclose($pipes[0]);
|
||||
stream_get_contents($pipes[1]);
|
||||
$stderr = stream_get_contents($pipes[2]);
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
$code = proc_close($process);
|
||||
if ($code !== 0) {
|
||||
self::log($errorLog, 'Backend script failed with code ' . $code . ': ' . trim($stderr));
|
||||
}
|
||||
}
|
||||
|
||||
private static function currentBackend(string $statePath): string
|
||||
{
|
||||
if (!is_file($statePath)) {
|
||||
return '';
|
||||
}
|
||||
$data = json_decode((string)file_get_contents($statePath), true);
|
||||
return is_array($data) ? (string)($data['active_backend'] ?? '') : '';
|
||||
}
|
||||
|
||||
private static function log(string $errorLog, string $message): void
|
||||
{
|
||||
if ($errorLog === '') {
|
||||
return;
|
||||
}
|
||||
@error_log('[' . date('c') . '] BACKEND_SYNC ' . $message . "\n", 3, $errorLog);
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ final class RuleValidator
|
||||
{
|
||||
$value = trim($value);
|
||||
if ($mode === 'exact_hour') {
|
||||
if (!preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:00$/', $value)) {
|
||||
if (!preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}$/', $value)) {
|
||||
throw new InvalidArgumentException('Nieprawidłowa data lub godzina.');
|
||||
}
|
||||
$dt = DateTimeImmutable::createFromFormat('!Y-m-d\TH:i', $value, $tz);
|
||||
|
||||
@@ -51,7 +51,7 @@ final class Settings
|
||||
'DEFAULT_PLUGIN_LANGUAGE' => 'en',
|
||||
'DEFAULT_ENABLE' => 'true',
|
||||
'GLOBAL_AUTORESPONDER_TIMEZONE' => 'Europe/Warsaw',
|
||||
'GLOBAL_AUTORESPONDER_SCHEDULE_MODE' => 'exact_hour',
|
||||
'GLOBAL_AUTORESPONDER_BACKEND' => 'da',
|
||||
'GLOBAL_AUTORESPONDER_REPLY_EVERY_MESSAGE' => 'false',
|
||||
'GLOBAL_AUTORESPONDER_REPEAT_MINUTES' => '1440',
|
||||
'GLOBAL_AUTORESPONDER_DYNAMIC_MAILBOX_SCOPE' => 'true',
|
||||
@@ -93,9 +93,14 @@ final class Settings
|
||||
return $this->getString('GLOBAL_AUTORESPONDER_TIMEZONE', 'Europe/Warsaw');
|
||||
}
|
||||
|
||||
public function backendMode(): string
|
||||
{
|
||||
return $this->getString('GLOBAL_AUTORESPONDER_BACKEND', 'da');
|
||||
}
|
||||
|
||||
public function scheduleMode(): string
|
||||
{
|
||||
return $this->getString('GLOBAL_AUTORESPONDER_SCHEDULE_MODE', 'exact_hour');
|
||||
return $this->backendMode() === 'da' ? 'directadmin_period' : 'exact_hour';
|
||||
}
|
||||
|
||||
public function replyEveryMessage(): bool
|
||||
@@ -148,8 +153,8 @@ final class Settings
|
||||
} catch (Throwable) {
|
||||
throw new InvalidArgumentException('Invalid timezone: ' . $this->timezone());
|
||||
}
|
||||
if (!in_array($this->scheduleMode(), ['exact_hour', 'directadmin_period'], true)) {
|
||||
throw new InvalidArgumentException('Invalid schedule mode: ' . $this->scheduleMode());
|
||||
if (!in_array($this->backendMode(), ['da', 'exim'], true)) {
|
||||
throw new InvalidArgumentException('Invalid backend mode: ' . $this->backendMode());
|
||||
}
|
||||
if ($this->repeatMinutes() < 0) {
|
||||
throw new InvalidArgumentException('Invalid repeat minutes');
|
||||
|
||||
Reference in New Issue
Block a user