nexus basic
This commit is contained in:
@@ -230,6 +230,54 @@ final class BaseSchema
|
||||
)"
|
||||
);
|
||||
$pdo->exec("CREATE INDEX IF NOT EXISTS nexus_dashboard_shares_dashboard_idx ON nexus_dashboard_shares (dashboard_id, share_type, share_value)");
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_widget_templates (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
owner_key TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
widget_type TEXT NOT NULL,
|
||||
description TEXT NULL,
|
||||
visibility TEXT NOT NULL DEFAULT 'private',
|
||||
config TEXT NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)"
|
||||
);
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_search_engines (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
owner_key TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
short_code TEXT NOT NULL,
|
||||
engine_type TEXT NOT NULL DEFAULT 'template',
|
||||
template_url TEXT NULL,
|
||||
integration_id BIGINT NULL,
|
||||
visibility TEXT NOT NULL DEFAULT 'private',
|
||||
is_default BOOLEAN NOT NULL DEFAULT false,
|
||||
config TEXT NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)"
|
||||
);
|
||||
$pdo->exec("CREATE UNIQUE INDEX IF NOT EXISTS nexus_search_engines_owner_short_idx ON nexus_search_engines (owner_key, short_code)");
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_apps (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
owner_key TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT NULL,
|
||||
app_url TEXT NOT NULL,
|
||||
icon_url TEXT NULL,
|
||||
integration_id BIGINT NULL,
|
||||
visibility TEXT NOT NULL DEFAULT 'private',
|
||||
config TEXT NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)"
|
||||
);
|
||||
}
|
||||
|
||||
private static function ensureSqlite(\PDO $pdo): void
|
||||
@@ -440,6 +488,54 @@ final class BaseSchema
|
||||
)"
|
||||
);
|
||||
$pdo->exec("CREATE INDEX IF NOT EXISTS nexus_dashboard_shares_dashboard_idx ON nexus_dashboard_shares (dashboard_id, share_type, share_value)");
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_widget_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
owner_key TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
widget_type TEXT NOT NULL,
|
||||
description TEXT NULL,
|
||||
visibility TEXT NOT NULL DEFAULT 'private',
|
||||
config TEXT NOT NULL DEFAULT '{}',
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)"
|
||||
);
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_search_engines (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
owner_key TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
short_code TEXT NOT NULL,
|
||||
engine_type TEXT NOT NULL DEFAULT 'template',
|
||||
template_url TEXT NULL,
|
||||
integration_id INTEGER NULL,
|
||||
visibility TEXT NOT NULL DEFAULT 'private',
|
||||
is_default INTEGER NOT NULL DEFAULT 0,
|
||||
config TEXT NOT NULL DEFAULT '{}',
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)"
|
||||
);
|
||||
$pdo->exec("CREATE UNIQUE INDEX IF NOT EXISTS nexus_search_engines_owner_short_idx ON nexus_search_engines (owner_key, short_code)");
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_apps (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
owner_key TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT NULL,
|
||||
app_url TEXT NOT NULL,
|
||||
icon_url TEXT NULL,
|
||||
integration_id INTEGER NULL,
|
||||
visibility TEXT NOT NULL DEFAULT 'private',
|
||||
config TEXT NOT NULL DEFAULT '{}',
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)"
|
||||
);
|
||||
}
|
||||
|
||||
private static function ensureGeneric(\PDO $pdo): void
|
||||
@@ -650,6 +746,54 @@ final class BaseSchema
|
||||
KEY nexus_dashboard_shares_dashboard_idx (dashboard_id, share_type, share_value)
|
||||
)"
|
||||
);
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_widget_templates (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
owner_key VARCHAR(190) NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
widget_type VARCHAR(64) NOT NULL,
|
||||
description TEXT NULL,
|
||||
visibility VARCHAR(32) NOT NULL DEFAULT 'private',
|
||||
config TEXT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)"
|
||||
);
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_search_engines (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
owner_key VARCHAR(190) NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
short_code VARCHAR(64) NOT NULL,
|
||||
engine_type VARCHAR(32) NOT NULL DEFAULT 'template',
|
||||
template_url TEXT NULL,
|
||||
integration_id BIGINT NULL,
|
||||
visibility VARCHAR(32) NOT NULL DEFAULT 'private',
|
||||
is_default TINYINT NOT NULL DEFAULT 0,
|
||||
config TEXT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY nexus_search_engines_owner_short_idx (owner_key, short_code)
|
||||
)"
|
||||
);
|
||||
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS nexus_apps (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
owner_key VARCHAR(190) NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT NULL,
|
||||
app_url TEXT NOT NULL,
|
||||
icon_url TEXT NULL,
|
||||
integration_id BIGINT NULL,
|
||||
visibility VARCHAR(32) NOT NULL DEFAULT 'private',
|
||||
config TEXT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)"
|
||||
);
|
||||
}
|
||||
|
||||
private static function seedTimezones(\PDO $pdo): void
|
||||
|
||||
@@ -108,6 +108,64 @@ final class NexusDashboardService
|
||||
return $rows;
|
||||
}
|
||||
|
||||
public function resolveHomeDashboard(?string $ownerKey, array $groups, bool $authenticated, int $preferredId = 0): ?array
|
||||
{
|
||||
if (!$this->available()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($authenticated && $ownerKey !== null && $ownerKey !== '') {
|
||||
if ($preferredId > 0) {
|
||||
$preferred = $this->getDashboardById($preferredId);
|
||||
if ($preferred !== null && $this->canAccessDashboard($preferred, $ownerKey, $groups)) {
|
||||
return $preferred;
|
||||
}
|
||||
}
|
||||
|
||||
$dashboards = $this->listAccessibleDashboards($ownerKey, $groups);
|
||||
foreach ($dashboards as $dashboard) {
|
||||
if (!empty($dashboard['is_default']) && $this->canAccessDashboard($dashboard, $ownerKey, $groups)) {
|
||||
return $dashboard;
|
||||
}
|
||||
}
|
||||
foreach ($dashboards as $dashboard) {
|
||||
if ($this->canAccessDashboard($dashboard, $ownerKey, $groups)) {
|
||||
return $dashboard;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$publicId = (int) (($this->settings()['global_home_dashboard_id'] ?? 0));
|
||||
if ($publicId > 0) {
|
||||
$dashboard = $this->getDashboardById($publicId);
|
||||
if ($dashboard !== null && (string) ($dashboard['visibility'] ?? '') === 'public') {
|
||||
return $dashboard;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->listPublicDashboards() as $dashboard) {
|
||||
return $dashboard;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function listPublicDashboards(): array
|
||||
{
|
||||
if (!$this->available()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
"SELECT *
|
||||
FROM nexus_dashboards
|
||||
WHERE visibility = 'public'
|
||||
ORDER BY is_default DESC, sort_order ASC, title ASC, id ASC"
|
||||
);
|
||||
$stmt->execute();
|
||||
return $this->hydrateRows($stmt->fetchAll(\PDO::FETCH_ASSOC) ?: []);
|
||||
}
|
||||
|
||||
public function getDashboardById(int $id): ?array
|
||||
{
|
||||
if (!$this->available() || $id <= 0) {
|
||||
@@ -397,6 +455,63 @@ final class NexusDashboardService
|
||||
return $this->hydrateRows($stmt->fetchAll(\PDO::FETCH_ASSOC) ?: []);
|
||||
}
|
||||
|
||||
public function listAccessiblePageModules(string $ownerKey, array $groups = []): array
|
||||
{
|
||||
if (!$this->available()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$rows = [];
|
||||
$seen = [];
|
||||
foreach ($this->listPageModulesForOwner($ownerKey) as $module) {
|
||||
$id = (int) ($module['id'] ?? 0);
|
||||
if ($id > 0) {
|
||||
$rows[] = $module;
|
||||
$seen[$id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
"SELECT *
|
||||
FROM nexus_page_modules
|
||||
WHERE visibility = 'public'
|
||||
ORDER BY title ASC, id ASC"
|
||||
);
|
||||
$stmt->execute();
|
||||
foreach ($this->hydrateRows($stmt->fetchAll(\PDO::FETCH_ASSOC) ?: []) as $module) {
|
||||
$id = (int) ($module['id'] ?? 0);
|
||||
if ($id > 0 && !isset($seen[$id])) {
|
||||
$rows[] = $module;
|
||||
$seen[$id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$group = trim((string) $group);
|
||||
if ($group === '') {
|
||||
continue;
|
||||
}
|
||||
$stmt = $this->pdo->prepare(
|
||||
"SELECT *
|
||||
FROM nexus_page_modules
|
||||
WHERE visibility = 'group'"
|
||||
);
|
||||
$stmt->execute();
|
||||
foreach ($this->hydrateRows($stmt->fetchAll(\PDO::FETCH_ASSOC) ?: []) as $module) {
|
||||
$id = (int) ($module['id'] ?? 0);
|
||||
if ($id <= 0 || isset($seen[$id])) {
|
||||
continue;
|
||||
}
|
||||
if (in_array($group, (array) ($module['config']['groups'] ?? []), true)) {
|
||||
$rows[] = $module;
|
||||
$seen[$id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
public function createPageModule(string $ownerKey, array $data): int
|
||||
{
|
||||
if (!$this->available() || $ownerKey === '') {
|
||||
@@ -466,6 +581,233 @@ final class NexusDashboardService
|
||||
return null;
|
||||
}
|
||||
|
||||
public function listWidgetTemplates(string $ownerKey, bool $includePublic = true): array
|
||||
{
|
||||
if (!$this->available()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$clauses = [];
|
||||
$params = [];
|
||||
if ($ownerKey !== '') {
|
||||
$clauses[] = 'owner_key = :owner_key';
|
||||
$params['owner_key'] = $ownerKey;
|
||||
}
|
||||
if ($includePublic) {
|
||||
$clauses[] = "visibility = 'public'";
|
||||
}
|
||||
if ($clauses === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT * FROM nexus_widget_templates WHERE ' . implode(' OR ', $clauses) . ' ORDER BY name ASC, id ASC'
|
||||
);
|
||||
$stmt->execute($params);
|
||||
|
||||
$rows = [];
|
||||
$seen = [];
|
||||
foreach ($this->hydrateRows($stmt->fetchAll(\PDO::FETCH_ASSOC) ?: []) as $row) {
|
||||
$id = (int) ($row['id'] ?? 0);
|
||||
if ($id > 0 && !isset($seen[$id])) {
|
||||
$rows[] = $row;
|
||||
$seen[$id] = true;
|
||||
}
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
public function createWidgetTemplate(string $ownerKey, array $data): int
|
||||
{
|
||||
if (!$this->available() || $ownerKey === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
"INSERT INTO nexus_widget_templates
|
||||
(owner_key, name, widget_type, description, visibility, config, created_at, updated_at)
|
||||
VALUES
|
||||
(:owner_key, :name, :widget_type, :description, :visibility, :config, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)"
|
||||
);
|
||||
$stmt->execute([
|
||||
'owner_key' => $ownerKey,
|
||||
'name' => trim((string) ($data['name'] ?? '')) ?: 'Widget',
|
||||
'widget_type' => $this->normalizeItemType((string) ($data['widget_type'] ?? 'link')),
|
||||
'description' => trim((string) ($data['description'] ?? '')),
|
||||
'visibility' => $this->normalizeVisibility((string) ($data['visibility'] ?? 'private')),
|
||||
'config' => $this->encodeJson((array) ($data['config'] ?? [])),
|
||||
]);
|
||||
|
||||
return (int) $this->pdo->lastInsertId();
|
||||
}
|
||||
|
||||
public function deleteWidgetTemplate(int $id, string $ownerKey): void
|
||||
{
|
||||
if (!$this->available() || $id <= 0 || $ownerKey === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare("DELETE FROM nexus_widget_templates WHERE id = :id AND owner_key = :owner_key");
|
||||
$stmt->execute(['id' => $id, 'owner_key' => $ownerKey]);
|
||||
}
|
||||
|
||||
public function listSearchEngines(string $ownerKey, bool $includePublic = true): array
|
||||
{
|
||||
if (!$this->available()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$clauses = [];
|
||||
$params = [];
|
||||
if ($ownerKey !== '') {
|
||||
$clauses[] = 'owner_key = :owner_key';
|
||||
$params['owner_key'] = $ownerKey;
|
||||
}
|
||||
if ($includePublic) {
|
||||
$clauses[] = "visibility = 'public'";
|
||||
}
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT * FROM nexus_search_engines WHERE ' . implode(' OR ', $clauses) . ' ORDER BY is_default DESC, name ASC, id ASC'
|
||||
);
|
||||
$stmt->execute($params);
|
||||
|
||||
$rows = [];
|
||||
$seen = [];
|
||||
foreach ($this->hydrateRows($stmt->fetchAll(\PDO::FETCH_ASSOC) ?: []) as $row) {
|
||||
$id = (int) ($row['id'] ?? 0);
|
||||
if ($id > 0 && !isset($seen[$id])) {
|
||||
$rows[] = $row;
|
||||
$seen[$id] = true;
|
||||
}
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
public function createSearchEngine(string $ownerKey, array $data): int
|
||||
{
|
||||
if (!$this->available() || $ownerKey === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$shortCode = $this->normalizeShortCode((string) ($data['short_code'] ?? ''));
|
||||
if ($shortCode === '') {
|
||||
$shortCode = 's' . random_int(100, 999);
|
||||
}
|
||||
$shortCode = $this->uniqueSearchShortCode($ownerKey, $shortCode, 0);
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
"INSERT INTO nexus_search_engines
|
||||
(owner_key, name, short_code, engine_type, template_url, integration_id, visibility, is_default, config, created_at, updated_at)
|
||||
VALUES
|
||||
(:owner_key, :name, :short_code, :engine_type, :template_url, :integration_id, :visibility, :is_default, :config, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)"
|
||||
);
|
||||
$stmt->execute([
|
||||
'owner_key' => $ownerKey,
|
||||
'name' => trim((string) ($data['name'] ?? '')) ?: 'Suche',
|
||||
'short_code' => $shortCode,
|
||||
'engine_type' => trim((string) ($data['engine_type'] ?? 'template')) ?: 'template',
|
||||
'template_url' => trim((string) ($data['template_url'] ?? '')),
|
||||
'integration_id' => !empty($data['integration_id']) ? (int) $data['integration_id'] : null,
|
||||
'visibility' => $this->normalizeVisibility((string) ($data['visibility'] ?? 'private')),
|
||||
'is_default' => !empty($data['is_default']) ? 1 : 0,
|
||||
'config' => $this->encodeJson((array) ($data['config'] ?? [])),
|
||||
]);
|
||||
$id = (int) $this->pdo->lastInsertId();
|
||||
if (!empty($data['is_default'])) {
|
||||
$this->setDefaultSearchEngine($ownerKey, $id);
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
|
||||
public function setDefaultSearchEngine(string $ownerKey, int $id): void
|
||||
{
|
||||
if (!$this->available() || $ownerKey === '' || $id <= 0) {
|
||||
return;
|
||||
}
|
||||
$stmt = $this->pdo->prepare("UPDATE nexus_search_engines SET is_default = 0, updated_at = CURRENT_TIMESTAMP WHERE owner_key = :owner_key");
|
||||
$stmt->execute(['owner_key' => $ownerKey]);
|
||||
$stmt = $this->pdo->prepare("UPDATE nexus_search_engines SET is_default = 1, updated_at = CURRENT_TIMESTAMP WHERE id = :id AND owner_key = :owner_key");
|
||||
$stmt->execute(['id' => $id, 'owner_key' => $ownerKey]);
|
||||
}
|
||||
|
||||
public function deleteSearchEngine(int $id, string $ownerKey): void
|
||||
{
|
||||
if (!$this->available() || $id <= 0 || $ownerKey === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare("DELETE FROM nexus_search_engines WHERE id = :id AND owner_key = :owner_key");
|
||||
$stmt->execute(['id' => $id, 'owner_key' => $ownerKey]);
|
||||
}
|
||||
|
||||
public function listApps(string $ownerKey, bool $includePublic = true): array
|
||||
{
|
||||
if (!$this->available()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$clauses = [];
|
||||
$params = [];
|
||||
if ($ownerKey !== '') {
|
||||
$clauses[] = 'owner_key = :owner_key';
|
||||
$params['owner_key'] = $ownerKey;
|
||||
}
|
||||
if ($includePublic) {
|
||||
$clauses[] = "visibility = 'public'";
|
||||
}
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT * FROM nexus_apps WHERE ' . implode(' OR ', $clauses) . ' ORDER BY name ASC, id ASC'
|
||||
);
|
||||
$stmt->execute($params);
|
||||
|
||||
$rows = [];
|
||||
$seen = [];
|
||||
foreach ($this->hydrateRows($stmt->fetchAll(\PDO::FETCH_ASSOC) ?: []) as $row) {
|
||||
$id = (int) ($row['id'] ?? 0);
|
||||
if ($id > 0 && !isset($seen[$id])) {
|
||||
$rows[] = $row;
|
||||
$seen[$id] = true;
|
||||
}
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
public function createApp(string $ownerKey, array $data): int
|
||||
{
|
||||
if (!$this->available() || $ownerKey === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
"INSERT INTO nexus_apps
|
||||
(owner_key, name, description, app_url, icon_url, integration_id, visibility, config, created_at, updated_at)
|
||||
VALUES
|
||||
(:owner_key, :name, :description, :app_url, :icon_url, :integration_id, :visibility, :config, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)"
|
||||
);
|
||||
$stmt->execute([
|
||||
'owner_key' => $ownerKey,
|
||||
'name' => trim((string) ($data['name'] ?? '')) ?: 'App',
|
||||
'description' => trim((string) ($data['description'] ?? '')),
|
||||
'app_url' => trim((string) ($data['app_url'] ?? '')),
|
||||
'icon_url' => trim((string) ($data['icon_url'] ?? '')),
|
||||
'integration_id' => !empty($data['integration_id']) ? (int) $data['integration_id'] : null,
|
||||
'visibility' => $this->normalizeVisibility((string) ($data['visibility'] ?? 'private')),
|
||||
'config' => $this->encodeJson((array) ($data['config'] ?? [])),
|
||||
]);
|
||||
|
||||
return (int) $this->pdo->lastInsertId();
|
||||
}
|
||||
|
||||
public function deleteApp(int $id, string $ownerKey): void
|
||||
{
|
||||
if (!$this->available() || $id <= 0 || $ownerKey === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare("DELETE FROM nexus_apps WHERE id = :id AND owner_key = :owner_key");
|
||||
$stmt->execute(['id' => $id, 'owner_key' => $ownerKey]);
|
||||
}
|
||||
|
||||
private function listSharedDashboardIds(string $ownerKey, array $groups): array
|
||||
{
|
||||
$result = [];
|
||||
@@ -566,7 +908,7 @@ final class NexusDashboardService
|
||||
private function normalizeItemType(string $value): string
|
||||
{
|
||||
$value = trim($value);
|
||||
return in_array($value, ['link', 'iframe', 'page_module', 'bookmark_group', 'module_link'], true) ? $value : 'link';
|
||||
return in_array($value, ['link', 'iframe', 'page_module', 'bookmark_group', 'module_link', 'app', 'widget_template'], true) ? $value : 'link';
|
||||
}
|
||||
|
||||
private function normalizePageModuleType(string $value): string
|
||||
@@ -625,4 +967,59 @@ final class NexusDashboardService
|
||||
}
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
private function settings(): array
|
||||
{
|
||||
return function_exists('nexus_settings') ? nexus_settings() : [];
|
||||
}
|
||||
|
||||
private function canAccessDashboard(array $dashboard, string $ownerKey, array $groups): bool
|
||||
{
|
||||
if ((string) ($dashboard['owner_key'] ?? '') === $ownerKey) {
|
||||
return true;
|
||||
}
|
||||
$visibility = (string) ($dashboard['visibility'] ?? 'private');
|
||||
if ($visibility === 'public') {
|
||||
return true;
|
||||
}
|
||||
if ($visibility === 'group') {
|
||||
$sharedIds = $this->listSharedDashboardIds($ownerKey, $groups);
|
||||
return in_array((int) ($dashboard['id'] ?? 0), $sharedIds, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function normalizeShortCode(string $value): string
|
||||
{
|
||||
$value = strtolower(trim($value));
|
||||
$value = preg_replace('/[^a-z0-9_-]+/', '', $value) ?? '';
|
||||
return substr($value, 0, 24);
|
||||
}
|
||||
|
||||
private function uniqueSearchShortCode(string $ownerKey, string $candidate, int $ignoreId): string
|
||||
{
|
||||
$shortCode = $candidate;
|
||||
$suffix = 1;
|
||||
while ($this->searchShortCodeExists($ownerKey, $shortCode, $ignoreId)) {
|
||||
$suffix++;
|
||||
$shortCode = substr($candidate, 0, 20) . $suffix;
|
||||
}
|
||||
return $shortCode;
|
||||
}
|
||||
|
||||
private function searchShortCodeExists(string $ownerKey, string $shortCode, int $ignoreId): bool
|
||||
{
|
||||
$sql = "SELECT id FROM nexus_search_engines WHERE owner_key = :owner_key AND short_code = :short_code";
|
||||
if ($ignoreId > 0) {
|
||||
$sql .= " AND id <> :id";
|
||||
}
|
||||
$sql .= " LIMIT 1";
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$params = ['owner_key' => $ownerKey, 'short_code' => $shortCode];
|
||||
if ($ignoreId > 0) {
|
||||
$params['id'] = $ignoreId;
|
||||
}
|
||||
$stmt->execute($params);
|
||||
return (bool) $stmt->fetchColumn();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user