requireLoginHtml(); $store = new PromptStore($DB_FILE); $languageStore = new LanguageStore($DB_FILE); $userSettings = new UserSettingsStore($DB_FILE); $message = ''; $error = ''; function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } function t($key, $fallback = null) { global $languageStore, $language; return $languageStore->translate($key, $language, $fallback); } function post_value($name, $default = '') { return $_POST[$name] ?? $default; } function get_value($name, $default = '') { return $_GET[$name] ?? $default; } function fmt_time($ts) { if ($ts === null) { return '-'; } return date('Y-m-d H:i:s', (int)$ts); } function prompt_to_array($prompt) { return array( 'id' => $prompt->id(), 'name' => $prompt->name(), 'language' => $prompt->language(), 'content' => $prompt->content(), 'default_key' => $prompt->defaultKey(), 'is_default' => $prompt->isDefault(), 'created_at' => $prompt->createdAt(), 'updated_at' => $prompt->updatedAt(), ); } function version_to_array($version) { return array( 'id' => $version->id(), 'prompt_id' => $version->promptId(), 'version_no' => $version->versionNo(), 'name' => $version->name(), 'language' => $version->language(), 'content' => $version->content(), 'note' => $version->note(), 'created_at' => $version->createdAt(), ); } function resolve_user_language($userSettings, $userId, $allowedLanguages) { $language = isset($_GET['lang']) ? (string)$_GET['lang'] : (string)$userSettings->get($userId, 'language', 'en'); if (!in_array($language, $allowedLanguages, true)) { $language = 'en'; } $userSettings->set($userId, 'language', $language); return $language; } $language = resolve_user_language( $userSettings, $user->id(), $store->supportedLanguages() ); $languageStore->seedDefaults(array( 'prompts.title' => array('en' => 'Prompt administration', 'nl' => 'Promptbeheer'), 'prompts.back' => array('en' => 'Back to Racket sandbox', 'nl' => 'Terug naar Racket sandbox'), 'prompts.your_prompts' => array('en' => 'Your prompts', 'nl' => 'Jouw prompts'), 'prompts.default_admin' => array('en' => 'Default prompt administration', 'nl' => 'Standaardpromptbeheer'), 'prompts.language' => array('en' => 'Language', 'nl' => 'Taal'), 'prompts.available_defaults' => array('en' => 'Available default prompts', 'nl' => 'Beschikbare standaardprompts'), 'prompts.default_admin_badge' => array('en' => 'Admin default prompts', 'nl' => 'Admin standaardprompts'), 'prompts.default_admin_hint' => array( 'en' => 'You are editing global default prompts. Users can copy these to their own prompts.', 'nl' => 'Je bewerkt globale standaardprompts. Gebruikers kunnen deze naar hun eigen prompts kopieren.' ), 'prompts.copy_all' => array('en' => 'Copy all', 'nl' => 'Alles kopieren'), 'prompts.copy' => array('en' => 'copy', 'nl' => 'kopieer'), 'prompts.delete' => array('en' => 'delete', 'nl' => 'verwijder'), 'prompts.create_default' => array('en' => 'Create default prompt', 'nl' => 'Standaardprompt maken'), 'prompts.create_personal' => array('en' => 'Create personal prompt', 'nl' => 'Persoonlijke prompt maken'), 'prompts.name' => array('en' => 'Name', 'nl' => 'Naam'), 'prompts.default_key' => array('en' => 'Default key', 'nl' => 'Standaardsleutel'), 'prompts.prompt_content' => array('en' => 'Prompt content', 'nl' => 'Promptinhoud'), 'prompts.no_defaults' => array('en' => 'No default prompts for this language yet.', 'nl' => 'Nog geen standaardprompts voor deze taal.'), 'prompts.no_personal' => array('en' => 'No personal prompts yet for this language.', 'nl' => 'Nog geen persoonlijke prompts voor deze taal.'), 'prompts.select_prompt' => array('en' => 'Select a prompt on the left to view it.', 'nl' => 'Selecteer links een prompt om deze te bekijken.'), 'prompts.edit' => array('en' => 'Edit', 'nl' => 'Bewerk'), 'prompts.close' => array('en' => 'Close', 'nl' => 'Sluiten'), 'prompts.newer_previous' => array('en' => 'newer previous version', 'nl' => 'nieuwere vorige versie'), 'prompts.older_previous' => array('en' => 'older previous version', 'nl' => 'oudere vorige versie'), 'prompts.diff_view' => array('en' => 'Diff view:', 'nl' => 'Verschilweergave:'), 'prompts.diff_plain' => array('en' => 'text, no diff', 'nl' => 'tekst, geen verschil'), 'prompts.diff_all' => array('en' => 'all diff', 'nl' => 'alle verschillen'), 'prompts.diff_same' => array('en' => 'unchanged only', 'nl' => 'alleen ongewijzigd'), 'prompts.diff_added' => array('en' => 'additions only', 'nl' => 'alleen toevoegingen'), 'prompts.diff_deleted' => array('en' => 'deletions only', 'nl' => 'alleen verwijderingen'), 'prompts.diff_changed' => array('en' => 'changes only', 'nl' => 'alleen wijzigingen'), 'prompts.previous_version' => array('en' => 'Previous version', 'nl' => 'Vorige versie'), 'prompts.store_version' => array('en' => 'store this edit as a new version', 'nl' => 'bewaar deze bewerking als nieuwe versie'), 'prompts.version_note' => array('en' => 'Version note:', 'nl' => 'Versienotitie:'), 'prompts.save' => array('en' => 'Save', 'nl' => 'Opslaan'), 'prompts.store_snapshot' => array('en' => 'Store snapshot', 'nl' => 'Snapshot bewaren'), 'prompts.restore_version' => array('en' => 'Restore selected version', 'nl' => 'Geselecteerde versie herstellen'), 'prompts.delete_version' => array('en' => 'Delete selected version', 'nl' => 'Geselecteerde versie verwijderen'), 'prompts.prompt' => array('en' => 'Prompt', 'nl' => 'Prompt'), 'prompts.prompt_not_found' => array('en' => 'Prompt not found', 'nl' => 'Prompt niet gevonden'), 'prompts.no_previous_versions' => array('en' => 'No previous versions stored.', 'nl' => 'Geen vorige versies opgeslagen.'), 'prompts.no_lines_for_view' => array('en' => 'No lines for this view.', 'nl' => 'Geen regels voor deze weergave.'), 'prompts.restore_version_confirm' => array('en' => 'Restore version', 'nl' => 'Versie herstellen'), 'prompts.delete_version_confirm' => array('en' => 'Delete version', 'nl' => 'Versie verwijderen'), 'prompts.delete_default_confirm' => array('en' => 'Delete default prompt', 'nl' => 'Standaardprompt verwijderen'), 'prompts.delete_prompt_confirm' => array('en' => 'Delete prompt', 'nl' => 'Prompt verwijderen'), 'prompts.default_prompt_prefix' => array('en' => 'Default prompt: ', 'nl' => 'Standaardprompt: '), 'prompts.prompt_prefix' => array('en' => 'Prompt: ', 'nl' => 'Prompt: '), 'prompts.created' => array('en' => 'created', 'nl' => 'gemaakt'), 'prompts.updated' => array('en' => 'updated', 'nl' => 'bijgewerkt'), 'prompts.default_prompt' => array('en' => 'default prompt', 'nl' => 'standaardprompt'), 'prompts.version' => array('en' => 'version', 'nl' => 'versie'), 'prompts.showing_version' => array('en' => 'showing version', 'nl' => 'toont versie'), 'prompts.of' => array('en' => 'of', 'nl' => 'van'), 'prompts.old' => array('en' => 'old', 'nl' => 'oud'), 'prompts.new' => array('en' => 'new', 'nl' => 'nieuw'), 'app.admin' => array('en' => 'admin', 'nl' => 'admin'), 'app.user_management' => array('en' => 'User management', 'nl' => 'Gebruikersbeheer'), 'app.configuration' => array('en' => 'Configuration', 'nl' => 'Configuratie'), 'app.logout' => array('en' => 'Logout', 'nl' => 'Uitloggen'), )); $mode = get_value('mode', 'personal'); if ($mode !== 'personal' && $mode !== 'defaults') { $mode = 'personal'; } if ($mode === 'defaults' && !$user->isAdmin()) { $mode = 'personal'; } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $action = post_value('action'); try { /* * User actions. */ if ($action === 'logout') { $auth->logout(); header('Location: /login.php'); exit; } elseif ($action === 'copy_all_defaults') { $language = post_value('language', 'en'); $created = $store->copyAllDefaultsToUser($user->id(), $language); $message = 'Default prompts copied to your prompts: ' . $created; $mode = 'personal'; } elseif ($action === 'copy_default') { $defaultId = (int)post_value('default_id'); $store->copyDefaultPromptToUser($user->id(), $defaultId); $message = 'Default prompt copied to your prompts.'; $mode = 'personal'; } elseif ($action === 'create_prompt') { $language = post_value('language', 'en'); $store->createPrompt( $user->id(), post_value('name'), $language, post_value('content') ); $message = 'Prompt created.'; $mode = 'personal'; } elseif ($action === 'update_prompt') { $promptId = (int)post_value('prompt_id'); $language = post_value('language', 'en'); $store->updatePrompt( $user->id(), $promptId, post_value('name'), $language, post_value('content'), isset($_POST['create_version']), post_value('version_note') ); $message = 'Prompt updated.'; $mode = 'personal'; } elseif ($action === 'create_version') { $promptId = (int)post_value('prompt_id'); $store->createVersion($user->id(), $promptId, post_value('version_note')); $message = 'Version stored.'; $mode = 'personal'; } elseif ($action === 'restore_version') { $promptId = (int)post_value('prompt_id'); $versionNo = (int)post_value('version_no'); $store->restoreVersion($user->id(), $promptId, $versionNo); $message = 'Version restored.'; $mode = 'personal'; } elseif ($action === 'delete_version') { $promptId = (int)post_value('prompt_id'); $versionNo = (int)post_value('version_no'); $store->deleteVersion($user->id(), $promptId, $versionNo); $message = 'Version deleted.'; $mode = 'personal'; } elseif ($action === 'delete_prompt') { $promptId = (int)post_value('prompt_id'); $store->deletePrompt($user->id(), $promptId); $message = 'Prompt deleted.'; $mode = 'personal'; } /* * Admin-only default prompt actions. */ elseif ($action === 'create_default' || $action === 'update_default' || $action === 'create_default_version' || $action === 'restore_default_version' || $action === 'delete_default_version' || $action === 'delete_default') { if (!$user->isAdmin()) { throw new Exception('Admin rights required.'); } $mode = 'defaults'; if ($action === 'create_default') { $language = post_value('language', 'en'); $store->createDefaultPrompt( post_value('default_key'), post_value('name'), $language, post_value('content') ); $message = 'Default prompt created.'; } elseif ($action === 'update_default') { $defaultId = (int)post_value('default_id'); $language = post_value('language', 'en'); $store->updateDefaultPrompt( $defaultId, post_value('default_key'), post_value('name'), $language, post_value('content'), isset($_POST['create_version']), post_value('version_note') ); $message = 'Default prompt updated.'; } elseif ($action === 'create_default_version') { $defaultId = (int)post_value('default_id'); $store->createDefaultVersion($defaultId, post_value('version_note')); $message = 'Default prompt version stored.'; } elseif ($action === 'restore_default_version') { $defaultId = (int)post_value('default_id'); $versionNo = (int)post_value('version_no'); $store->restoreDefaultVersion($defaultId, $versionNo); $message = 'Default prompt version restored.'; } elseif ($action === 'delete_default_version') { $defaultId = (int)post_value('default_id'); $versionNo = (int)post_value('version_no'); $store->deleteDefaultVersion($defaultId, $versionNo); $message = 'Default prompt version deleted.'; } elseif ($action === 'delete_default') { $defaultId = (int)post_value('default_id'); $store->deleteDefaultPrompt($defaultId); $message = 'Default prompt deleted.'; } } elseif ($action !== '') { throw new Exception('Unknown action: ' . $action); } } catch (Throwable $e) { $error = $e->getMessage(); } } $personalPrompts = $store->listPrompts($user->id(), $language); $defaultPrompts = $store->listDefaultPrompts($language); /* * Full prompt data for the modal editor. */ $allPersonalPrompts = $store->listPrompts($user->id(), null); $allDefaultPrompts = $store->listDefaultPrompts(null); $promptData = array( 'personal' => array(), 'default' => array(), 'can_edit_defaults' => $user->isAdmin(), ); foreach ($allPersonalPrompts as $p) { $promptData['personal'][$p->id()] = prompt_to_array($p); $promptData['personal'][$p->id()]['versions'] = array(); foreach ($store->listVersions($user->id(), $p->id()) as $v) { $promptData['personal'][$p->id()]['versions'][] = version_to_array($v); } } foreach ($allDefaultPrompts as $p) { $promptData['default'][$p->id()] = prompt_to_array($p); $promptData['default'][$p->id()]['versions'] = array(); if ($user->isAdmin()) { foreach ($store->listDefaultVersions($p->id()) as $v) { $promptData['default'][$p->id()]['versions'][] = version_to_array($v); } } } $headerLanguages = array(); foreach ($store->supportedLanguages() as $lang) { $headerLanguages[$lang] = $store->languageLabel($lang); } $headerNavItems = array( array( 'label' => t('prompts.back', 'Back to Racket sandbox'), 'url' => '/', ), ); if ($user->isAdmin()) { $headerNavItems[] = array( 'label' => t('app.user_management', 'User management'), 'url' => '/users?lang=' . rawurlencode($language), 'separator_before' => true, ); $headerNavItems[] = array( 'label' => t('app.configuration', 'Configuration'), 'url' => '/admin-config?lang=' . rawurlencode($language), 'separator_before' => true, ); } $styleVersion = @filemtime(__DIR__ . '/styles.css') ?: time(); $promptEditorVersion = @filemtime(__DIR__ . '/prompt-editor.js') ?: time(); header('Content-Type: text/html; charset=utf-8'); ?>