diff --git a/TODO.md b/TODO.md
index 692871c..5ab051d 100644
--- a/TODO.md
+++ b/TODO.md
@@ -12,3 +12,14 @@
- [x] Fix nginx/SETUP.md manual step to use just manage-admin-users instead of raw htpasswd
- [x] Fix root README.md dead reference to docs/TODO.SECURITY.md
- [x] Update root README.md project structure (remove nginx/scripts/ entry)
+- [x] Form default visibility: "Interne" (access_type_id=2) set at DB insert level
+- [x] New TFE always created unpublished (is_published=0 hardcoded in createThesis)
+- [x] Contact checkbox: `show_contact` column on authors; checkbox in add/edit forms; tfe.php shows contact only if enabled
+- [x] Migration 008: site_settings table + show_contact column + rebuilt views with author_email/author_show_contact/access_type_id
+- [x] Formulaire section in parametres.php: toggle switches for Interdit/Interne/Libre access types
+- [x] Libre option disabled by default (access_type_libre_enabled=0)
+- [x] Add visibility select in add.php, filtered by enabled access types, defaulting to Interne
+- [x] Edit.php: pre-populate contact email from DB; show contact_public checkbox with current state
+- [x] tfe.php: contact shown from author_email+show_contact; baiu_link relabeled as "Lien"
+- [x] actions/settings.php: handler for formulaire settings form
+- [x] CSS: admin-toggle pill switches + admin-settings-toggles layout + admin-form-group
diff --git a/public/admin/actions/settings.php b/public/admin/actions/settings.php
new file mode 100644
index 0000000..36d7920
--- /dev/null
+++ b/public/admin/actions/settings.php
@@ -0,0 +1,32 @@
+setSetting($key, $value);
+ }
+ App::flash('success', "Paramètres du formulaire mis à jour.");
+} else {
+ App::flash('error', "Section inconnue.");
+}
+
+$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
+header('Location: /admin/parametres.php');
+exit;
diff --git a/public/admin/add.php b/public/admin/add.php
index 9837dee..c9546b1 100644
--- a/public/admin/add.php
+++ b/public/admin/add.php
@@ -63,6 +63,16 @@ function wasSelected($key, $value) {
'name']); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
'email']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
+
+
+
+ Si cette case est cochée, votre contact apparaîtra sur la page publique de votre TFE.
+
+
+ $at['id'], 'name' => $at['name']];
+ }, $enabledAccessTypes);
+ // Default: Interne (id=2)
+ $defaultAccessType = 2;
+ $selectedAccessType = isset($formData['access_type_id'])
+ ? (int)$formData['access_type_id']
+ : $defaultAccessType;
+ $name = 'access_type_id';
+ $label = 'Visibilité / Accès :';
+ $options = $accessOptions;
+ $selected = $selectedAccessType;
+ $placeholder = null;
+ $required = true;
+ $attrs = [];
+ include APP_ROOT . '/templates/partials/form/select-field.php';
+ ?>
+
diff --git a/public/admin/edit.php b/public/admin/edit.php
index c5646e7..7772418 100644
--- a/public/admin/edit.php
+++ b/public/admin/edit.php
@@ -45,7 +45,17 @@ try {
'name'], $autofocusField === 'auteurice' ? ['autofocus' => true] : []); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
- 'email']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
+ 'email']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
+
+
+
+
+ Si cette case est cochée, le contact apparaît sur la page publique du TFE.
+
getAllSettings();
+
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
@@ -56,7 +60,58 @@ if (empty($_SESSION['csrf_token'])) {
+
+
+
+ Options de visibilité disponibles dans le formulaire d'ajout de TFE.
+ L'option Libre ne sera activée qu'à partir de l'année académique prochaine.
+
+
+
+
+
Compte administrateur
diff --git a/public/assets/css/admin.css b/public/assets/css/admin.css
index 435a665..5857fa3 100644
--- a/public/assets/css/admin.css
+++ b/public/assets/css/admin.css
@@ -1164,3 +1164,83 @@
height: 50vh;
border: 1px solid var(--border-primary);
}
+
+/* ── Settings: formulaire toggles ──────────────────────────────────────────── */
+.admin-settings-toggles {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-xs);
+ margin-bottom: var(--space-m);
+}
+
+.admin-toggle-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--space-m);
+ background: var(--bg-secondary);
+ border: 1px solid var(--border-primary);
+ border-radius: 4px;
+ padding: var(--space-xs) var(--space-m);
+ cursor: pointer;
+}
+
+.admin-toggle-row--disabled {
+ opacity: 0.6;
+}
+
+.admin-toggle-label {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+}
+
+.admin-toggle-label strong {
+ font-size: var(--step-0);
+}
+
+.admin-toggle-label small {
+ color: var(--text-secondary);
+ font-size: var(--step--2);
+}
+
+/* Native checkbox styled as toggle pill */
+.admin-toggle {
+ appearance: none;
+ -webkit-appearance: none;
+ width: 40px;
+ height: 22px;
+ background: var(--border-primary);
+ border-radius: 11px;
+ position: relative;
+ cursor: pointer;
+ flex-shrink: 0;
+ transition: background 0.2s;
+}
+
+.admin-toggle::after {
+ content: '';
+ position: absolute;
+ top: 3px;
+ left: 3px;
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ background: #fff;
+ transition: transform 0.2s;
+}
+
+.admin-toggle:checked {
+ background: var(--accent-primary);
+}
+
+.admin-toggle:checked::after {
+ transform: translateX(18px);
+}
+
+/* ── Form group (for checkbox inside .admin-form) ──────────────────────────── */
+.admin-form-group {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-3xs);
+}
diff --git a/public/tfe.php b/public/tfe.php
index f429d38..65c8575 100644
--- a/public/tfe.php
+++ b/public/tfe.php
@@ -149,18 +149,42 @@ extract($ctrl->handle());
-
-
+
+
+
+
+
+
diff --git a/src/Database.php b/src/Database.php
index 89831b1..8db1712 100644
--- a/src/Database.php
+++ b/src/Database.php
@@ -809,21 +809,24 @@ class Database {
/**
* Find or create an author
*/
- public function findOrCreateAuthor($name, $email = null) {
+ public function findOrCreateAuthor($name, $email = null, bool $showContact = false) {
$stmt = $this->pdo->prepare("SELECT id FROM authors WHERE name = ?");
$stmt->execute([$name]);
$author = $stmt->fetch();
if ($author) {
if ($email && $email !== '') {
- $updateStmt = $this->pdo->prepare("UPDATE authors SET email = ? WHERE id = ?");
- $updateStmt->execute([$email, $author['id']]);
+ $updateStmt = $this->pdo->prepare("UPDATE authors SET email = ?, show_contact = ? WHERE id = ?");
+ $updateStmt->execute([$email, $showContact ? 1 : 0, $author['id']]);
+ } else {
+ $updateStmt = $this->pdo->prepare("UPDATE authors SET show_contact = ? WHERE id = ?");
+ $updateStmt->execute([$showContact ? 1 : 0, $author['id']]);
}
return $author['id'];
}
- $stmt = $this->pdo->prepare("INSERT INTO authors (name, email) VALUES (?, ?)");
- $stmt->execute([$name, $email]);
+ $stmt = $this->pdo->prepare("INSERT INTO authors (name, email, show_contact) VALUES (?, ?, ?)");
+ $stmt->execute([$name, $email, $showContact ? 1 : 0]);
return $this->pdo->lastInsertId();
}
@@ -1048,6 +1051,77 @@ class Database {
return $stmt->fetchAll();
}
+ // ========================================================================
+ // SITE SETTINGS
+ // ========================================================================
+
+ /**
+ * Get a single site setting value by key. Returns $default if not found.
+ */
+ public function getSetting(string $key, string $default = ''): string {
+ $stmt = $this->pdo->prepare("SELECT value FROM site_settings WHERE key = ? LIMIT 1");
+ $stmt->execute([$key]);
+ $row = $stmt->fetch();
+ return $row ? (string) $row['value'] : $default;
+ }
+
+ /**
+ * Get all site settings as an associative array [ key => value ].
+ */
+ public function getAllSettings(): array {
+ $stmt = $this->pdo->query("SELECT key, value FROM site_settings");
+ $rows = $stmt->fetchAll();
+ $out = [];
+ foreach ($rows as $r) {
+ $out[$r['key']] = $r['value'];
+ }
+ return $out;
+ }
+
+ /**
+ * Upsert a site setting.
+ */
+ public function setSetting(string $key, string $value): void {
+ $this->pdo->prepare(
+ "INSERT INTO site_settings (key, value, updated_at)
+ VALUES (?, ?, CURRENT_TIMESTAMP)
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = CURRENT_TIMESTAMP"
+ )->execute([$key, $value]);
+ }
+
+ /**
+ * Return access types that are enabled in the add-thesis form,
+ * filtered by site_settings toggles.
+ * 'Libre' (id=1) is excluded unless access_type_libre_enabled = '1'.
+ * 'Interne' (id=2) is excluded unless access_type_interne_enabled = '1'.
+ * 'Interdit' (id=3) is excluded unless access_type_interdit_enabled = '1'.
+ */
+ public function getEnabledFormAccessTypes(): array {
+ $settings = $this->getAllSettings();
+ $all = $this->getAccessTypes();
+ $map = [
+ 'Libre' => $settings['access_type_libre_enabled'] ?? '0',
+ 'Interne' => $settings['access_type_interne_enabled'] ?? '1',
+ 'Interdit' => $settings['access_type_interdit_enabled'] ?? '1',
+ ];
+ return array_values(array_filter($all, fn($at) => ($map[$at['name']] ?? '0') === '1'));
+ }
+
+ /**
+ * Update the show_contact flag for the first author of a thesis.
+ */
+ public function setAuthorShowContact(int $thesisId, bool $show): void {
+ $stmt = $this->pdo->prepare(
+ "UPDATE authors SET show_contact = ?
+ WHERE id = (
+ SELECT author_id FROM thesis_authors
+ WHERE thesis_id = ?
+ ORDER BY author_order LIMIT 1
+ )"
+ );
+ $stmt->execute([$show ? 1 : 0, $thesisId]);
+ }
+
// ========================================================================
// JURY METHODS
// ========================================================================
@@ -1439,7 +1513,8 @@ class Database {
foreach ($authors as $index => $author) {
$name = trim($author['name'] ?? '');
if ($name === '') continue;
- $authorId = $this->findOrCreateAuthor($name, $author['email'] ?? null);
+ $showContact = !empty($author['show_contact']);
+ $authorId = $this->findOrCreateAuthor($name, $author['email'] ?? null, $showContact);
$stmt->execute([$thesisId, $authorId, $index + 1]);
}
}
@@ -1453,8 +1528,10 @@ class Database {
orientation_id, ap_program_id, finality_id,
synopsis, file_size_info,
baiu_link, license_id,
+ access_type_id,
+ is_published,
submitted_at
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, CURRENT_TIMESTAMP)
");
$stmt->execute([
@@ -1469,6 +1546,7 @@ class Database {
!empty($data['file_size_info']) ? $data['file_size_info'] : null,
!empty($data['baiu_link']) ? $data['baiu_link'] : null,
isset($data['license_id']) ? $data['license_id'] : null,
+ isset($data['access_type_id']) ? (int)$data['access_type_id'] : 2, // default: Interne
]);
$thesisId = (int)$this->pdo->lastInsertId();
diff --git a/src/ThesisCreateController.php b/src/ThesisCreateController.php
index 6d6ec57..c35f93d 100644
--- a/src/ThesisCreateController.php
+++ b/src/ThesisCreateController.php
@@ -70,12 +70,13 @@ class ThesisCreateController
public function loadFormData(): array
{
return [
- 'orientations' => $this->db->getAllOrientations(),
- 'apPrograms' => $this->db->getAllAPPrograms(),
- 'finalityTypes' => $this->db->getAllFinalityTypes(),
- 'languages' => $this->db->getAllLanguages(),
- 'formatTypes' => $this->db->getAllFormatTypes(),
- 'licenseTypes' => $this->db->getAllLicenseTypes(),
+ 'orientations' => $this->db->getAllOrientations(),
+ 'apPrograms' => $this->db->getAllAPPrograms(),
+ 'finalityTypes' => $this->db->getAllFinalityTypes(),
+ 'languages' => $this->db->getAllLanguages(),
+ 'formatTypes' => $this->db->getAllFormatTypes(),
+ 'licenseTypes' => $this->db->getAllLicenseTypes(),
+ 'enabledAccessTypes' => $this->db->getEnabledFormAccessTypes(),
];
}
@@ -107,7 +108,7 @@ class ThesisCreateController
$data = $this->validateAndSanitise($post);
// ── 2. Find / create author ───────────────────────────────────────────
- $authorId = $this->db->findOrCreateAuthor($data['auteurName'], $data['mail'] ?: null);
+ $authorId = $this->db->findOrCreateAuthor($data['auteurName'], $data['mail'] ?: null, $data['showContact']);
error_log("ThesisCreateController: author ID $authorId");
// ── 3–4. DB writes in a transaction ───────────────────────────────────
@@ -125,6 +126,7 @@ class ThesisCreateController
'file_size_info' => $data['durationInfo'],
'baiu_link' => $data['lien'],
'license_id' => $data['licenseId'],
+ 'access_type_id' => $data['accessTypeId'],
'author_id' => $authorId,
]);
@@ -192,7 +194,8 @@ class ThesisCreateController
'Nom/Prénom/Pseudo'
);
- $mail = !empty($post['mail']) ? $this->sanitiseString($post['mail']) : '';
+ $mail = !empty($post['mail']) ? $this->sanitiseString($post['mail']) : '';
+ $showContact = !empty($post['contact_public']) ? true : false;
$annee = filter_var($post['année'] ?? '', FILTER_VALIDATE_INT);
if ($annee === false || $annee < 2000 || $annee > ((int) date('Y') + 1)) {
@@ -265,6 +268,12 @@ class ThesisCreateController
$licenseId = filter_var($post['license_id'] ?? '', FILTER_VALIDATE_INT) ?: null;
+ // Access type — must be one of the enabled types; default 2 (Interne)
+ $accessTypeId = filter_var($post['access_type_id'] ?? '', FILTER_VALIDATE_INT);
+ if ($accessTypeId === false || $accessTypeId <= 0) {
+ $accessTypeId = 2; // Interne
+ }
+
// External link (optional)
$lien = '';
if (!empty($post['lien'])) {
@@ -275,10 +284,10 @@ class ThesisCreateController
}
return compact(
- 'auteurName', 'mail', 'annee', 'orientationId', 'apProgramId',
+ 'auteurName', 'mail', 'showContact', 'annee', 'orientationId', 'apProgramId',
'finalityId', 'titre', 'subtitle', 'synopsis', 'durationInfo',
'juryMembers', 'keywords', 'languageIds', 'formatIds',
- 'licenseId', 'lien'
+ 'licenseId', 'lien', 'accessTypeId'
);
}
diff --git a/src/ThesisEditController.php b/src/ThesisEditController.php
index 90e7a22..08f3e83 100644
--- a/src/ThesisEditController.php
+++ b/src/ThesisEditController.php
@@ -91,22 +91,28 @@ class ThesisEditController
$currentAccessTypeId = $rawRow['access_type_id'] ?? null;
$currentContextNote = $rawRow['context_note'] ?? '';
+ // Author contact info (from view)
+ $currentAuthorEmail = $thesis['author_email'] ?? '';
+ $currentAuthorShowContact = (bool)($thesis['author_show_contact'] ?? false);
+
return [
- 'thesis' => $thesis,
- 'currentLanguages' => $currentLanguages,
- 'currentFormats' => $currentFormats,
- 'jury' => $jury,
- 'orientations' => $orientations,
- 'apPrograms' => $apPrograms,
- 'finalityTypes' => $finalityTypes,
- 'languages' => $languages,
- 'formatTypes' => $formatTypes,
- 'licenseTypes' => $licenseTypes,
- 'accessTypes' => $accessTypes,
- 'currentLicenseId' => $currentLicenseId,
- 'currentAccessTypeId' => $currentAccessTypeId,
- 'currentContextNote' => $currentContextNote,
- 'pageTitle' => 'Éditer TFE - ' . htmlspecialchars($thesis['title']),
+ 'thesis' => $thesis,
+ 'currentLanguages' => $currentLanguages,
+ 'currentFormats' => $currentFormats,
+ 'jury' => $jury,
+ 'orientations' => $orientations,
+ 'apPrograms' => $apPrograms,
+ 'finalityTypes' => $finalityTypes,
+ 'languages' => $languages,
+ 'formatTypes' => $formatTypes,
+ 'licenseTypes' => $licenseTypes,
+ 'accessTypes' => $accessTypes,
+ 'currentLicenseId' => $currentLicenseId,
+ 'currentAccessTypeId' => $currentAccessTypeId,
+ 'currentContextNote' => $currentContextNote,
+ 'currentAuthorEmail' => $currentAuthorEmail,
+ 'currentAuthorShowContact' => $currentAuthorShowContact,
+ 'pageTitle' => 'Éditer TFE - ' . htmlspecialchars($thesis['title']),
];
}
@@ -162,13 +168,15 @@ class ThesisEditController
// ── 2. Authors ────────────────────────────────────────────────────
$authorsRaw = trim($post['auteurice'] ?? '');
+ $showContact = !empty($post['contact_public']);
$authorEntries = [];
if ($authorsRaw !== '') {
foreach (array_map('trim', explode(',', $authorsRaw)) as $i => $name) {
if ($name !== '') {
$authorEntries[] = [
- 'name' => $name,
- 'email' => $i === 0 ? ($post['mail'] ?? null) : null,
+ 'name' => $name,
+ 'email' => $i === 0 ? ($post['mail'] ?? null) : null,
+ 'show_contact' => $i === 0 ? $showContact : false,
];
}
}
diff --git a/storage/migrations/008_formulaire_settings.sql b/storage/migrations/008_formulaire_settings.sql
new file mode 100644
index 0000000..e46a5c7
--- /dev/null
+++ b/storage/migrations/008_formulaire_settings.sql
@@ -0,0 +1,89 @@
+-- Migration 008: Formulaire settings + contact visibility
+-- Adds site_settings key-value table for admin-configurable options
+-- Adds show_contact column to authors table
+-- Adds author_email + author_show_contact to views
+
+-- ── 1. site_settings ─────────────────────────────────────────────────────────
+CREATE TABLE IF NOT EXISTS site_settings (
+ key TEXT PRIMARY KEY,
+ value TEXT NOT NULL DEFAULT '',
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
+);
+
+-- Default formulaire settings:
+-- access_type_interdit_enabled = 1 (Interdit is available in the add form)
+-- access_type_interne_enabled = 1 (Interne is available in the add form)
+-- access_type_libre_enabled = 0 (Libre is NOT yet available — next academic year)
+INSERT OR IGNORE INTO site_settings (key, value) VALUES
+ ('access_type_interdit_enabled', '1'),
+ ('access_type_interne_enabled', '1'),
+ ('access_type_libre_enabled', '0');
+
+-- ── 2. show_contact on authors ────────────────────────────────────────────────
+-- NOTE: SQLite has no IF NOT EXISTS for ALTER TABLE.
+-- The migrate.sh script guards against re-running; ignore errors on existing DBs.
+ALTER TABLE authors ADD COLUMN show_contact INTEGER NOT NULL DEFAULT 0;
+
+-- ── 3. Rebuild views to expose author_email and author_show_contact ───────────
+DROP VIEW IF EXISTS v_theses_public;
+DROP VIEW IF EXISTS v_theses_full;
+
+CREATE VIEW IF NOT EXISTS v_theses_full AS
+SELECT
+ t.id,
+ t.identifier,
+ t.title,
+ t.subtitle,
+ t.year,
+ t.is_doctoral,
+ o.name as orientation,
+ ap.name as ap_program,
+ ft.name as finality_type,
+ t.synopsis,
+ t.context_note,
+ t.duration_minutes,
+ t.duration_pages,
+ t.file_size_info,
+ at.name as access_type,
+ lt.name as license_type,
+ t.license_id,
+ t.jury_points,
+ t.submitted_at,
+ t.defense_date,
+ t.published_at,
+ t.is_published,
+ t.baiu_link,
+ t.banner_path,
+ t.access_type_id,
+ GROUP_CONCAT(DISTINCT a.name) as authors,
+ GROUP_CONCAT(DISTINCT s.name) as supervisors,
+ GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'president' THEN s.name END) as jury_president,
+ GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' THEN s.name END) as jury_promoteurs,
+ GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' THEN s.name END) as jury_lecteurs,
+ GROUP_CONCAT(DISTINCT l.name) as languages,
+ GROUP_CONCAT(DISTINCT fmt.name) as formats,
+ GROUP_CONCAT(DISTINCT tg.name) as keywords,
+ -- First author's email and contact-visibility flag
+ (SELECT a2.email FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as author_email,
+ (SELECT a2.show_contact FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as author_show_contact
+FROM theses t
+LEFT JOIN orientations o ON t.orientation_id = o.id
+LEFT JOIN ap_programs ap ON t.ap_program_id = ap.id
+LEFT JOIN finality_types ft ON t.finality_id = ft.id
+LEFT JOIN access_types at ON t.access_type_id = at.id
+LEFT JOIN license_types lt ON t.license_id = lt.id
+LEFT JOIN thesis_authors ta ON t.id = ta.thesis_id
+LEFT JOIN authors a ON ta.author_id = a.id
+LEFT JOIN thesis_supervisors ts ON t.id = ts.thesis_id
+LEFT JOIN supervisors s ON ts.supervisor_id = s.id
+LEFT JOIN thesis_languages tl ON t.id = tl.thesis_id
+LEFT JOIN languages l ON tl.language_id = l.id
+LEFT JOIN thesis_formats tf ON t.id = tf.thesis_id
+LEFT JOIN format_types fmt ON tf.format_id = fmt.id
+LEFT JOIN thesis_tags tt ON t.id = tt.thesis_id
+LEFT JOIN tags tg ON tt.tag_id = tg.id
+GROUP BY t.id;
+
+CREATE VIEW IF NOT EXISTS v_theses_public AS
+SELECT * FROM v_theses_full
+WHERE is_published = 1;
diff --git a/storage/posterg.db b/storage/posterg.db
index 84582c7..fdeeabf 100644
Binary files a/storage/posterg.db and b/storage/posterg.db differ
diff --git a/storage/schema.sql b/storage/schema.sql
index 3cb1089..23fa13c 100644
--- a/storage/schema.sql
+++ b/storage/schema.sql
@@ -10,6 +10,7 @@ CREATE TABLE IF NOT EXISTS authors (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT,
+ show_contact INTEGER NOT NULL DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
@@ -278,6 +279,21 @@ CREATE TABLE IF NOT EXISTS thesis_files (
FOREIGN KEY (thesis_id) REFERENCES theses(id) ON DELETE CASCADE
);
+-- ============================================================================
+-- SITE SETTINGS
+-- ============================================================================
+
+CREATE TABLE IF NOT EXISTS site_settings (
+ key TEXT PRIMARY KEY,
+ value TEXT NOT NULL DEFAULT '',
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
+);
+
+INSERT OR IGNORE INTO site_settings (key, value) VALUES
+ ('access_type_interdit_enabled', '1'),
+ ('access_type_interne_enabled', '1'),
+ ('access_type_libre_enabled', '0');
+
-- ============================================================================
-- STATIC PAGES / CONTENT MANAGEMENT
-- ============================================================================
@@ -375,6 +391,7 @@ SELECT
at.name as access_type,
lt.name as license_type,
t.license_id,
+ t.access_type_id,
t.jury_points,
t.submitted_at,
t.defense_date,
@@ -389,7 +406,10 @@ SELECT
GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' THEN s.name END) as jury_lecteurs,
GROUP_CONCAT(DISTINCT l.name) as languages,
GROUP_CONCAT(DISTINCT fmt.name) as formats,
- GROUP_CONCAT(DISTINCT tg.name) as keywords
+ GROUP_CONCAT(DISTINCT tg.name) as keywords,
+ -- First author's email and contact-visibility flag
+ (SELECT a2.email FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as author_email,
+ (SELECT a2.show_contact FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as author_show_contact
FROM theses t
LEFT JOIN orientations o ON t.orientation_id = o.id
LEFT JOIN ap_programs ap ON t.ap_program_id = ap.id