Main update
This commit is contained in:
@@ -436,6 +436,28 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('nexus_cron_timezone_name')) {
|
||||
function nexus_cron_timezone_name(): string
|
||||
{
|
||||
$candidates = [
|
||||
$_COOKIE['desktop_timezone'] ?? null,
|
||||
$_SESSION['desktop_timezone'] ?? null,
|
||||
getenv('DESKTOP_CRON_TIMEZONE') ?: null,
|
||||
getenv('DESKTOP_TIMEZONE') ?: null,
|
||||
'Europe/Berlin',
|
||||
];
|
||||
|
||||
foreach ($candidates as $candidate) {
|
||||
$timezone = trim((string) $candidate);
|
||||
if ($timezone !== '' && in_array($timezone, \DateTimeZone::listIdentifiers(), true)) {
|
||||
return $timezone;
|
||||
}
|
||||
}
|
||||
|
||||
return 'Europe/Berlin';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('auth_enabled')) {
|
||||
function auth_enabled(): bool
|
||||
{
|
||||
|
||||
@@ -8,6 +8,12 @@ final class ModuleRegistry
|
||||
{
|
||||
/** @var array<int, array<string, mixed>>|null */
|
||||
private ?array $desktopApps = null;
|
||||
/** @var array<int, array<string, mixed>>|null */
|
||||
private ?array $widgets = null;
|
||||
/** @var array<int, array<string, mixed>>|null */
|
||||
private ?array $cronJobs = null;
|
||||
/** @var array<string, array<string, mixed>>|null */
|
||||
private ?array $manifests = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly string $modulesPath,
|
||||
@@ -26,6 +32,12 @@ final class ModuleRegistry
|
||||
$apps = [];
|
||||
|
||||
foreach ($this->moduleDirectories() as $moduleName => $modulePath) {
|
||||
$manifest = $this->manifest($moduleName, $modulePath);
|
||||
$desktopMeta = is_array($manifest['desktop'] ?? null) ? $manifest['desktop'] : [];
|
||||
if (array_key_exists('available', $desktopMeta) && !$desktopMeta['available']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$desktopConfigPath = $modulePath . '/desktop.php';
|
||||
if (!is_file($desktopConfigPath)) {
|
||||
continue;
|
||||
@@ -36,7 +48,6 @@ final class ModuleRegistry
|
||||
continue;
|
||||
}
|
||||
|
||||
$manifest = $this->readJson($modulePath . '/module.json');
|
||||
$desktopConfig['module_id'] = $moduleName;
|
||||
$desktopConfig['title'] ??= (string) ($manifest['title'] ?? ucfirst($moduleName));
|
||||
$desktopConfig['summary'] ??= (string) ($manifest['description'] ?? '');
|
||||
@@ -45,12 +56,67 @@ final class ModuleRegistry
|
||||
(array) ($manifest['auth']['groups'] ?? [])
|
||||
));
|
||||
$desktopConfig['enabled_by_default'] ??= (bool) ($manifest['enabled_by_default'] ?? false);
|
||||
$desktopConfig['app_scope'] ??= (string) ($manifest['app_scope'] ?? 'module');
|
||||
$desktopConfig['installable'] ??= array_key_exists('installable', $manifest) ? (bool) $manifest['installable'] : true;
|
||||
$desktopConfig['show_on_desktop'] ??= !array_key_exists('show_on_desktop', $desktopMeta) || (bool) $desktopMeta['show_on_desktop'];
|
||||
$desktopConfig['show_in_start_menu'] ??= !array_key_exists('show_in_start_menu', $desktopMeta) || (bool) $desktopMeta['show_in_start_menu'];
|
||||
$desktopConfig['supports_widget'] ??= $this->moduleWidgetsForManifest($moduleName, $manifest, $desktopConfig) !== [];
|
||||
$desktopConfig['supports_cron'] ??= $this->moduleCronJobsForManifest($moduleName, $manifest, $desktopConfig) !== [];
|
||||
$apps[] = $desktopConfig;
|
||||
}
|
||||
|
||||
return $this->desktopApps = $apps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public function widgets(): array
|
||||
{
|
||||
if ($this->widgets !== null) {
|
||||
return $this->widgets;
|
||||
}
|
||||
|
||||
$widgets = [];
|
||||
foreach ($this->moduleDirectories() as $moduleName => $modulePath) {
|
||||
$manifest = $this->manifest($moduleName, $modulePath);
|
||||
foreach ($this->moduleWidgetsForManifest($moduleName, $manifest, null) as $widget) {
|
||||
$widgets[] = $widget;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->widgets = $widgets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public function cronJobs(): array
|
||||
{
|
||||
if ($this->cronJobs !== null) {
|
||||
return $this->cronJobs;
|
||||
}
|
||||
|
||||
$jobs = [];
|
||||
foreach ($this->moduleDirectories() as $moduleName => $modulePath) {
|
||||
$manifest = $this->manifest($moduleName, $modulePath);
|
||||
$desktopConfig = null;
|
||||
$desktopConfigPath = $modulePath . '/desktop.php';
|
||||
if (is_file($desktopConfigPath)) {
|
||||
$loaded = require $desktopConfigPath;
|
||||
if (is_array($loaded)) {
|
||||
$desktopConfig = $loaded;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->moduleCronJobsForManifest($moduleName, $manifest, $desktopConfig) as $job) {
|
||||
$jobs[] = $job;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->cronJobs = $jobs;
|
||||
}
|
||||
|
||||
public function modulePath(string $moduleName): ?string
|
||||
{
|
||||
$directories = $this->moduleDirectories();
|
||||
@@ -84,6 +150,108 @@ final class ModuleRegistry
|
||||
return $directories;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function manifest(string $moduleName, string $modulePath): array
|
||||
{
|
||||
if ($this->manifests === null) {
|
||||
$this->manifests = [];
|
||||
}
|
||||
|
||||
if (!array_key_exists($moduleName, $this->manifests)) {
|
||||
$this->manifests[$moduleName] = $this->readJson($modulePath . '/module.json');
|
||||
}
|
||||
|
||||
return $this->manifests[$moduleName];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $manifest
|
||||
* @param array<string, mixed>|null $desktopConfig
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function moduleWidgetsForManifest(string $moduleName, array $manifest, ?array $desktopConfig): array
|
||||
{
|
||||
$appId = (string) (($desktopConfig['app_id'] ?? null) ?: ($manifest['app_id'] ?? $moduleName));
|
||||
$widgets = [];
|
||||
|
||||
foreach ((array) ($manifest['widgets'] ?? []) as $widget) {
|
||||
if (!is_array($widget)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$widgetId = trim((string) ($widget['widget_id'] ?? ''));
|
||||
$title = trim((string) ($widget['title'] ?? ''));
|
||||
if ($widgetId === '' || $title === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$widgets[] = [
|
||||
'widget_id' => $widgetId,
|
||||
'title' => $title,
|
||||
'icon' => (string) ($widget['icon'] ?? strtoupper(substr($appId, 0, 2))),
|
||||
'zone' => (string) ($widget['zone'] ?? 'sidebar'),
|
||||
'default_enabled' => (bool) ($widget['default_enabled'] ?? false),
|
||||
'supports_public_home' => (bool) ($widget['supports_public_home'] ?? false),
|
||||
'summary' => (string) ($widget['summary'] ?? ''),
|
||||
'content' => (string) ($widget['content'] ?? ''),
|
||||
'launch_app_id' => (string) ($widget['launch_app_id'] ?? $appId),
|
||||
'action_label' => (string) ($widget['action_label'] ?? 'Oeffnen'),
|
||||
'widget_type' => (string) ($widget['widget_type'] ?? 'default'),
|
||||
'status_api' => isset($widget['status_api']) ? (string) $widget['status_api'] : null,
|
||||
'refresh_api' => isset($widget['refresh_api']) ? (string) $widget['refresh_api'] : null,
|
||||
'source_app_id' => $appId,
|
||||
'source_module_id' => $moduleName,
|
||||
'actions' => is_array($widget['actions'] ?? null) ? array_values($widget['actions']) : [],
|
||||
];
|
||||
}
|
||||
|
||||
return $widgets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $manifest
|
||||
* @param array<string, mixed>|null $desktopConfig
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function moduleCronJobsForManifest(string $moduleName, array $manifest, ?array $desktopConfig): array
|
||||
{
|
||||
$appId = (string) (($desktopConfig['app_id'] ?? null) ?: ($manifest['app_id'] ?? $moduleName));
|
||||
$jobs = [];
|
||||
|
||||
foreach ((array) ($manifest['cron_jobs'] ?? []) as $job) {
|
||||
if (!is_array($job)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$jobId = trim((string) ($job['job_id'] ?? $job['name'] ?? ''));
|
||||
$endpointPath = trim((string) ($job['endpoint_path'] ?? ''));
|
||||
if ($jobId === '' || $endpointPath === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$jobs[] = [
|
||||
'job_key' => $moduleName . '.' . $jobId,
|
||||
'job_id' => $jobId,
|
||||
'module_id' => $moduleName,
|
||||
'app_id' => $appId,
|
||||
'app_scope' => (string) ($manifest['app_scope'] ?? 'module'),
|
||||
'label' => trim((string) ($job['label'] ?? $jobId)),
|
||||
'description' => trim((string) ($job['description'] ?? '')),
|
||||
'endpoint_path' => $endpointPath,
|
||||
'method' => strtoupper(trim((string) ($job['method'] ?? 'POST'))) ?: 'POST',
|
||||
'payload' => is_array($job['payload'] ?? null) ? $job['payload'] : [],
|
||||
'default_enabled' => (bool) ($job['default_enabled'] ?? false),
|
||||
'default_cron' => trim((string) ($job['default_cron'] ?? '0 * * * *')) ?: '0 * * * *',
|
||||
'default_timezone' => trim((string) ($job['default_timezone'] ?? '')) ?: 'Europe/Berlin',
|
||||
'lock_minutes' => max(1, (int) ($job['lock_minutes'] ?? 10)),
|
||||
];
|
||||
}
|
||||
|
||||
return $jobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user