refactor: rename keywords→tags M2M (migration 001)

- migration 001_rename_keywords_to_tags.sql: CREATE tags/thesis_tags from keywords/thesis_keywords,
  copy data, drop old tables, rebuild indexes and views
- schema.sql: tags table, thesis_tags junction, updated indexes and v_theses_full/v_theses_public
- Database.php: findOrCreateTag(), getUsedTags() with proper JOIN; backwards-compat aliases;
  buildSearchConditions uses EXISTS subquery on thesis_tags+tags with vp. alias throughout
- admin/actions/formulaire.php: INSERT OR IGNORE INTO thesis_tags
- admin/edit.php: DELETE FROM thesis_tags + findOrCreateTag
- search.php: $kw['name'] (was $kw['keyword'])
- fixtures/CreateTestDatabase.php: tags/thesis_tags table names
This commit is contained in:
Pontoporeia
2026-03-24 13:30:53 +01:00
parent cefceb046c
commit 0933137540
9 changed files with 226 additions and 130 deletions

View File

@@ -0,0 +1,106 @@
-- Migration 001: Rename keywords→tags, thesis_keywords→thesis_tags, keyword column→name
-- SQLite does not support ALTER TABLE RENAME COLUMN before 3.25, so we recreate tables.
-- This migration is safe to run after 004 and 005 (no dependency ordering required
-- since SQLite processes this in one transaction).
PRAGMA foreign_keys = OFF;
BEGIN;
-- 1. Create new tags table
CREATE TABLE tags (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 2. Copy data from keywords → tags (keyword column → name)
INSERT INTO tags (id, name, created_at)
SELECT id, keyword, created_at FROM keywords;
-- 3. Create new junction table thesis_tags
CREATE TABLE thesis_tags (
tag_id INTEGER NOT NULL,
thesis_id INTEGER NOT NULL,
PRIMARY KEY (tag_id, thesis_id),
FOREIGN KEY (thesis_id) REFERENCES theses(id) ON DELETE CASCADE,
FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE
);
-- 4. Copy junction data (keyword_id → tag_id)
INSERT INTO thesis_tags (tag_id, thesis_id)
SELECT keyword_id, thesis_id FROM thesis_keywords;
-- 5. Drop old tables
DROP TABLE thesis_keywords;
DROP TABLE keywords;
-- 6. Recreate indexes with canonical names
CREATE INDEX idx_tags_name ON tags(name);
CREATE INDEX idx_thesis_tags_thesis ON thesis_tags(thesis_id);
CREATE INDEX idx_thesis_tags_tag ON thesis_tags(tag_id);
-- 7. Rebuild views to reference new tables
DROP VIEW IF EXISTS v_theses_full;
CREATE VIEW 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,
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
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;
DROP VIEW IF EXISTS v_theses_public;
CREATE VIEW v_theses_public AS
SELECT * FROM v_theses_full
WHERE is_published = 1;
COMMIT;
PRAGMA foreign_keys = ON;