-- Les photos : profil d'un compte, facade d'un logement, preuves d'une prestation.
--
-- UNE SEULE TABLE POUR LES TROIS USAGES, et c'est le choix structurant.
--
-- On aurait pu poser une colonne « photo » sur utilisateurs et sur biens — un fichier chacun —
-- et une table separee pour les prestations, qui en portent plusieurs. Trois mecanismes de
-- stockage, trois chemins de suppression, trois facons de se tromper.
--
-- Or la partie DIFFICILE est identique dans les trois cas : recevoir un fichier envoye par un
-- navigateur, refuser ce qui n'est pas une image, la redimensionner, la ranger hors du chemin de
-- deploiement, et la servir avec un controle de portee. Cette partie ne merite d'etre ecrite
-- qu'une fois. Le reste — un ou plusieurs — se decide en PHP.
--
-- OU SONT LES FICHIERS. Dans storage/photos/, et jamais en base : un BLOB de 200 Ko par photo
-- ferait grossir les sauvegardes SQL sans raison, et rendrait chaque lecture couteuse.
--
-- POURQUOI storage/ EST LE BON ENDROIT, verifie et non suppose :
--
--   Deploiement::DOSSIERS vaut ['src', 'views', 'public/assets', 'db/migrations'] — storage/ n'y
--   figure pas. Les photos survivent donc aux deploiements par FTP, ce qui etait LA contrainte
--   annoncee des le depart : rangees sous public/, elles seraient effacees a l'envoi suivant.
--
--   Le seul .htaccess du depot est dans public/, donc la racine web est public/. storage/ est
--   ainsi hors d'atteinte par URL, et les photos ne peuvent PAS etre servies en statique. C'est
--   une contrainte heureuse : elle force le passage par PHP, donc par un controle de portee.
--   Une photo de l'interieur de chez un client n'a rien a faire a une adresse devinable.

CREATE TABLE photos (
    id          BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    -- La reference publique, seule chose qui paraisse dans une URL. Un identifiant sequentiel
    -- s'enumere ; un ULID, non.
    reference   CHAR(26)        NOT NULL,
    -- LE SUJET, EN TYPE + IDENTIFIANT plutot qu'une cle etrangere par espece.
    --
    -- Meme raison que pour notifications.sujet_type : une FK par espece ferait une colonne de
    -- plus a chaque usage, toutes nulles sauf une. Le prix a payer est qu'aucune contrainte ne
    -- garantit la cible — d'ou le nettoyage explicite a la suppression du sujet, et non une
    -- cascade que la base aurait tenue pour nous.
    sujet_type  VARCHAR(20)     NOT NULL,
    sujet_id    BIGINT UNSIGNED NOT NULL,
    -- Le nom du fichier dans storage/photos/, SANS chemin : le dossier se deduit du sujet, et
    -- stocker un chemin complet permettrait a une ligne corrompue de designer n'importe quoi.
    fichier     VARCHAR(64)     NOT NULL,
    -- Les dimensions APRES redimensionnement, pour reserver la place a l'affichage sans lire le
    -- fichier. Un <img> sans dimensions fait sauter la page pendant le chargement.
    largeur     SMALLINT UNSIGNED NOT NULL,
    hauteur     SMALLINT UNSIGNED NOT NULL,
    octets      INT UNSIGNED    NOT NULL,
    -- Qui l'a deposee. NULL possible : un compte supprime ne doit pas emporter la photo d'un
    -- logement, qui appartient au logement.
    cree_par    BIGINT UNSIGNED NULL,
    cree_le     DATETIME        NOT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY uq_photos_reference (reference),
    -- L'index qui porte la seule lecture : les photos d'un sujet, la plus recente d'abord.
    KEY idx_photos_sujet (sujet_type, sujet_id, cree_le),
    CONSTRAINT fk_photos_auteur FOREIGN KEY (cree_par)
        REFERENCES utilisateurs (id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- CE QUI N'EST PAS ICI, ET QU'IL FAUT SAVOIR.
--
-- AUCUNE CONTRAINTE « une seule photo par compte ». utilisateurs et biens n'en portent qu'une en
-- pratique, mais la regle est appliquee en PHP — deposer remplace la precedente. Une UNIQUE sur
-- (sujet_type, sujet_id) l'aurait garantie, au prix d'interdire les photos multiples des
-- prestations dans la meme table. Entre une garantie de base et un seul mecanisme de stockage,
-- on choisit le mecanisme unique : c'est lui qui portait le risque.
--
-- AUCUNE COLONNE « type MIME ». Tout est reencode en JPEG a la reception, sans exception. Ce
-- n'est pas qu'une simplification : le reencodage EFFACE LES METADONNEES EXIF, donc les
-- coordonnees GPS qu'un telephone inscrit dans une photo prise chez un client. Conserver le
-- fichier d'origine aurait diffuse l'adresse exacte du logement a qui sait ouvrir un fichier.
