asdsad
This commit is contained in:
@@ -10,13 +10,16 @@ final class BaseSchema
|
||||
$driver = (string)$pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
|
||||
if ($driver === 'pgsql') {
|
||||
self::ensurePgsql($pdo);
|
||||
self::seedTimezones($pdo);
|
||||
return;
|
||||
}
|
||||
if ($driver === 'sqlite') {
|
||||
self::ensureSqlite($pdo);
|
||||
self::seedTimezones($pdo);
|
||||
return;
|
||||
}
|
||||
self::ensureGeneric($pdo);
|
||||
self::seedTimezones($pdo);
|
||||
}
|
||||
|
||||
private static function ensurePgsql(\PDO $pdo): void
|
||||
@@ -136,6 +139,15 @@ final class BaseSchema
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)"
|
||||
);
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_timezones (
|
||||
identifier TEXT PRIMARY KEY,
|
||||
label TEXT NOT NULL,
|
||||
group_name TEXT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)"
|
||||
);
|
||||
}
|
||||
|
||||
private static function ensureSqlite(\PDO $pdo): void
|
||||
@@ -255,6 +267,15 @@ final class BaseSchema
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)"
|
||||
);
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_timezones (
|
||||
identifier TEXT PRIMARY KEY,
|
||||
label TEXT NOT NULL,
|
||||
group_name TEXT NULL,
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)"
|
||||
);
|
||||
}
|
||||
|
||||
private static function ensureGeneric(\PDO $pdo): void
|
||||
@@ -374,5 +395,66 @@ final class BaseSchema
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)"
|
||||
);
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_timezones (
|
||||
identifier VARCHAR(190) PRIMARY KEY,
|
||||
label VARCHAR(255) NOT NULL,
|
||||
group_name VARCHAR(190) NULL,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)"
|
||||
);
|
||||
}
|
||||
|
||||
private static function seedTimezones(\PDO $pdo): void
|
||||
{
|
||||
try {
|
||||
$count = (int) $pdo->query("SELECT COUNT(*) FROM nexus_timezones")->fetchColumn();
|
||||
} catch (\Throwable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($count > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$driver = (string) $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
|
||||
$sql = match ($driver) {
|
||||
'pgsql' => "INSERT INTO nexus_timezones (identifier, label, group_name, updated_at)
|
||||
VALUES (:identifier, :label, :group_name, NOW())
|
||||
ON CONFLICT (identifier) DO UPDATE SET
|
||||
label = EXCLUDED.label,
|
||||
group_name = EXCLUDED.group_name,
|
||||
updated_at = NOW()",
|
||||
'sqlite' => "INSERT INTO nexus_timezones (identifier, label, group_name, updated_at)
|
||||
VALUES (:identifier, :label, :group_name, datetime('now'))
|
||||
ON CONFLICT(identifier) DO UPDATE SET
|
||||
label = excluded.label,
|
||||
group_name = excluded.group_name,
|
||||
updated_at = datetime('now')",
|
||||
default => "INSERT INTO nexus_timezones (identifier, label, group_name, updated_at)
|
||||
VALUES (:identifier, :label, :group_name, CURRENT_TIMESTAMP)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
label = VALUES(label),
|
||||
group_name = VALUES(group_name),
|
||||
updated_at = CURRENT_TIMESTAMP",
|
||||
};
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
foreach (timezone_identifiers_list() as $identifier) {
|
||||
$parts = explode('/', $identifier, 2);
|
||||
$group = $parts[0] ?? 'Other';
|
||||
$label = str_replace('_', ' ', $identifier);
|
||||
if ($identifier === 'UTC') {
|
||||
$group = 'UTC';
|
||||
$label = 'UTC';
|
||||
}
|
||||
|
||||
$stmt->execute([
|
||||
'identifier' => $identifier,
|
||||
'label' => $label,
|
||||
'group_name' => $group,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,15 +75,16 @@ final class ModuleCronScheduler
|
||||
|
||||
try {
|
||||
$cron = CronExpression::parse($expression);
|
||||
$previousDueUtc = $cron->previousRun($nowUtc, $timezone);
|
||||
$lastScheduledFor = $this->parseUtc((string) ($state['last_scheduled_for'] ?? ''));
|
||||
$isDue = !empty($config['enabled'])
|
||||
&& !$isLocked
|
||||
&& $previousDueUtc instanceof DateTimeImmutable
|
||||
&& ($lastScheduledFor === null || $previousDueUtc > $lastScheduledFor);
|
||||
$nextDueUtc = $isDue
|
||||
? $previousDueUtc
|
||||
: $cron->nextRun($nowUtc, $timezone);
|
||||
if (!empty($config['enabled'])) {
|
||||
$previousDueUtc = $cron->previousRun($nowUtc, $timezone);
|
||||
$lastScheduledFor = $this->parseUtc((string) ($state['last_scheduled_for'] ?? ''));
|
||||
$isDue = !$isLocked
|
||||
&& $previousDueUtc instanceof DateTimeImmutable
|
||||
&& ($lastScheduledFor === null || $previousDueUtc > $lastScheduledFor);
|
||||
$nextDueUtc = $isDue
|
||||
? $previousDueUtc
|
||||
: $cron->nextRun($nowUtc, $timezone);
|
||||
}
|
||||
} catch (\Throwable $exception) {
|
||||
$parseError = $exception->getMessage();
|
||||
}
|
||||
@@ -94,6 +95,8 @@ final class ModuleCronScheduler
|
||||
'state_key' => $stateKey,
|
||||
'config' => $config,
|
||||
'state' => $state,
|
||||
'last_started_at_local' => ($this->parseUtc((string) ($state['last_started_at'] ?? '')))?->setTimezone($timezone)->format('Y-m-d H:i:s'),
|
||||
'last_success_at_local' => ($this->parseUtc((string) ($state['last_success_at'] ?? '')))?->setTimezone($timezone)->format('Y-m-d H:i:s'),
|
||||
'enabled' => !empty($config['enabled']),
|
||||
'cron_expression' => $expression,
|
||||
'timezone' => $timezone->getName(),
|
||||
|
||||
@@ -128,6 +128,42 @@ final class ModuleManager
|
||||
]);
|
||||
}
|
||||
|
||||
public function timezones(): array
|
||||
{
|
||||
if (!$this->basePdo) {
|
||||
return $this->fallbackTimezones();
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $this->basePdo->query(
|
||||
"SELECT identifier, label, group_name
|
||||
FROM nexus_timezones
|
||||
ORDER BY group_name ASC, identifier ASC"
|
||||
);
|
||||
$rows = $stmt ? $stmt->fetchAll(\PDO::FETCH_ASSOC) : [];
|
||||
if (!is_array($rows) || $rows === []) {
|
||||
return $this->fallbackTimezones();
|
||||
}
|
||||
|
||||
return array_values(array_filter(array_map(
|
||||
static function (array $row): ?array {
|
||||
$identifier = trim((string) ($row['identifier'] ?? ''));
|
||||
if ($identifier === '') {
|
||||
return null;
|
||||
}
|
||||
return [
|
||||
'value' => $identifier,
|
||||
'label' => trim((string) ($row['label'] ?? $identifier)),
|
||||
'group' => trim((string) ($row['group_name'] ?? '')),
|
||||
];
|
||||
},
|
||||
$rows
|
||||
)));
|
||||
} catch (\Throwable) {
|
||||
return $this->fallbackTimezones();
|
||||
}
|
||||
}
|
||||
|
||||
public function modulePdo(string $name, array $fallback = []): ?\PDO
|
||||
{
|
||||
$settings = $this->settings($name);
|
||||
@@ -358,6 +394,20 @@ final class ModuleManager
|
||||
return $enabledByDefault;
|
||||
}
|
||||
|
||||
private function fallbackTimezones(): array
|
||||
{
|
||||
$result = [];
|
||||
foreach (timezone_identifiers_list() as $identifier) {
|
||||
$parts = explode('/', $identifier, 2);
|
||||
$result[] = [
|
||||
'value' => $identifier,
|
||||
'label' => $identifier === 'UTC' ? 'UTC' : str_replace('_', ' ', $identifier),
|
||||
'group' => $parts[0] ?? 'Other',
|
||||
];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function saveAuth(string $name, array $auth): array
|
||||
{
|
||||
if (!preg_match('/^[a-zA-Z0-9_\-]+$/', $name)) {
|
||||
|
||||
Reference in New Issue
Block a user