@ -3,7 +3,7 @@
/**
* Fonctions utiles au modèle album
*
* Contient notamment des balises destinées uniquement au modèle standard
* Contient principalement des balises destinées au modèle standard
*
* @plugin Albums
* @copyright 2014
@ -22,15 +22,14 @@ if (!defined('_ECRIRE_INC_VERSION')) {
* Compile la balise `#ALBUM_DOC` qui retourne le code HTML
* d'un modèle de document ajusté pour les albums.
*
* Utilise en général un modèle standard sur le quel on ajoute des attributs
* et effectue des traitements sur les images.
* Utilise en général un modèle standard `#DOC` au quel on ajoute des attributs
* et applique des traitements d' images.
*
* Le choix du modèle et les traitements dépendent de la disposition de l'album et du contexte.
*
* S'utilise uniquement dans une boucle documents imbriquée dans une boucle album .
* S'utilise uniquement dans une boucle documents ou documents_liens .
*
* @uses calculer_album_doc()
* @uses calculer_album_params()
* @balise
* @example
* ```
@ -48,20 +47,12 @@ function balise_ALBUM_DOC_dist($p) {
// La boucle document
$index = index_boucle_mere($p); // < BOUCLE_truc > → _truc
$boucle = $p->boucles[$index] ?? null;
$cle_objet = $p->boucles[$index]->primary ?? null; // id_document
// La boucle album parente
$index_parent = $boucle->id_parent ?? null;
$boucle_parent = $p->boucles[$index_parent] ?? null;
$cle_objet_parent = $p->boucles[$index_parent]->primary ?? null; // id_album
// ids
$_id_document = champ_sql($cle_objet, $p);
$_id_album = champ_sql($cle_objet_parent, $p);
$type = $p->boucles[$index]->type_requete ?? null; // documents_liens
// Erreur squelette si hors boucle
$msg = null;
if (
$cle_objet !== 'id_document'
or $cle_objet_parent !== 'id_album'
!$boucle
or !in_array($type, ['documents', 'documents_liens'])
) {
erreur_squelette(
[
@ -74,25 +65,19 @@ function balise_ALBUM_DOC_dist($p) {
// Infos sur le document
$_document = "[
'id_document' => $_id_document ,
'id_document' => " . champ_sql('id_document', $p) . " ,
'media' => " . champ_sql('media', $p) . ",
'titre' => " . champ_sql('titre', $p) . ",
'descriptif' => " . champ_sql('descriptif', $p) . ",
'credits' => " . champ_sql('credits', $p) . ',
]';
// Infos sur l'album
// $_contexte = "\$Pile[0]['args'] ?? []"; // uniquement présent avec #MODELE ?
$_contexte = '$Pile[0]';
$_params = "calculer_album_params($_id_album, $_contexte)";
$_album = "array_merge(
[
'id_album' => $_id_album,
],
$_params
)";
$p->code = "calculer_album_doc($_document, $_album)";
// Contexte
// Les params passés au modèle sont parfois dans une clé `args`, on met à plat
$_contexte = "array_merge(\$Pile[0] ?? [], \$Pile[0]['args'] ?? [])";
$_contexte = "nettoyer_contexte_modele_album($_contexte)";
$p->code = "calculer_album_doc($_document, $_contexte)";
$p->interdire_scripts = false;
return $p;
}
@ -101,35 +86,37 @@ function balise_ALBUM_DOC_dist($p) {
/**
* Fonction privée pour calculer le HTML de la balise #ALBUM_DOC
*
* @see calculer_album_params()
* @uses calculer_album_params()
* @uses calculer_id_modele_album()
*
* @param array $document
* Tableau d'infos sur le document
* array< int id_document , string media , int largeur , int hauteur >
* @param array $album
* Tableau d'infos sur l'album et ses paramètres
* array< int id_album , … >
* @param array $contexte
* Contexte d'appel du modèle, sans les trucs par défaut inutiles (date, date_redac, etc.)
* @return string
*/
function calculer_album_doc(array $document, array $album ): string {
function calculer_album_doc(array $document, array $contexte ): string {
$html = '';
$id_album = (int) $album['id_album'] ?? 0;
$id_document = (int) $document['id_document'] ?? 0;
$id_document = (int) ($document['id_document'] ?? 0);
$media = $document['media'] ?? null;
$titre = trim($document['titre'] ?? null);
$descriptif = trim($document['descriptif'] ?? null);
$credits = trim($document['credits'] ?? null);
// Identifiant unique : id_album ou autre
$uniqid = calculer_id_modele_album($contexte);
// Choix du modèle, et valeurs pour les traitements à appliquer aux images
// Valeurs définies dans calculer_album_params()
$disposition = $album['disposition'];
$modele_doc = $album ['modele_doc'];
$largeur = $album ['largeur'];
$hauteur = $album ['hauteur'];
$recadrer_ratio = $album ['recadrer_ratio'];
$recadrer_sens = $album ['recadrer_sens'];
$images = $album ['images'];
$params = calculer_album_params($contexte);
$disposition = $params ['disposition'];
$modele_doc = $params ['modele_doc'];
$largeur = $params ['largeur'];
$hauteur = $params ['hauteur'];
$recadrer_ratio = $params ['recadrer_ratio'];
$recadrer_sens = $params ['recadrer_sens'];
$images = $params ['images'];
// On récupère le modèle en forçant l'ajout d'un lien.
$contexte_modele = [
@ -143,13 +130,24 @@ function calculer_album_doc(array $document, array $album): string {
$classe = "album__doc album__doc_$media album__doc_$modele_doc album__doc_$classe_caption";
$html = ajouter_class($html, $classe);
// Si c'est une disposition destinée aux images,
// ajouter l'attribut rel au lien afin d'avoir une galerie unique pour l'album
// Mediabox : activer si c'est une image
if (
$images === true
and ($pos_href = strpos($html, 'href=')) !== false
$media === 'image'
and $chercher = 'class="'
and ($pos_class = strpos($html, $chercher)) !== false
) {
$attribut_rel = "rel=\"modele_album$id_album\"" ;
$class_box = 'mediabox ';
$html = substr_replace($html, $class_box, $pos_class + strlen($chercher), 0);
// retirer la class hasbox (d'où elle sort ???)
$html = str_replace('hasbox', '', $html);
}
// Mediabox : identifiant de galerie
if (
($pos_href = strpos($html, 'href=')) !== false
) {
// $attribut_rel = "rel=\"modele_album_$uniqid\" ";
$attribut_rel = "data-box-group=\"modele_album_$uniqid\" ";
$html = substr_replace($html, $attribut_rel, $pos_href, 0);
}
@ -165,7 +163,6 @@ function calculer_album_doc(array $document, array $album): string {
}
}
return $html;
}
@ -174,8 +171,6 @@ function calculer_album_doc(array $document, array $album): string {
* Compile la balise `#ALBUM_PARAMS` qui retourne
* soit un ensemble de valeurs utiles au modèle album, soit une seule.
*
* S'utilise dans une boucle album, ou dans une boucle documents imbriquée dans une boucle album.
*
* @uses calculer_album_params()
* @balise
* @example
@ -190,38 +185,14 @@ function calculer_album_doc(array $document, array $album): string {
* Pile complétée par le code à générer
*/
function balise_ALBUM_PARAMS_dist($p) {
// Les params passés au modèle sont parfois dans une clé `args`, on met à plat
$_contexte = "array_merge(\$Pile[0] ?? [], \$Pile[0]['args'] ?? [])";
$_contexte = "nettoyer_contexte_modele_album($_contexte)";
$_param = interprete_argument_balise(1, $p) ?: null;
$etoile = $p->etoile;
// La boucle
$index = index_boucle_mere($p); // < BOUCLE_truc > → _truc
$boucle = $p->boucles[$index] ?? null;
$cle_objet = $p->boucles[$index]->primary ?? null; // id_document / id_album
// La boucle parente
$index_parent = $boucle->id_parent ?? null;
$boucle_parent = $p->boucles[$index_parent] ?? null;
$cle_objet_parent = $p->boucles[$index_parent]->primary ?? null; // id_album
// Erreur si hors boucle album
if (
!$boucle
or (
$cle_objet !== 'id_album'
and $cle_objet_parent !== 'id_album'
)
) {
erreur_squelette([
'zbug_champ_hors_boucle',
['champ' => zbug_presenter_champ($p)]
], $p);
}
$_id_album = champ_sql('id_album', $p);
// $_contexte = "\$Pile[0]['args'] ?? []"; // uniquement présent avec #MODELE ?
$_contexte = '$Pile[0] ?? []';
$_valeur = interprete_argument_balise(1, $p) ?: null;
$p->code = "calculer_album_params((int) $_id_album, $_contexte, $_valeur)";
$p->code = "calculer_album_params($_contexte, $_param)";
$p->interdire_scripts = false;
return $p;
}
@ -237,21 +208,20 @@ function balise_ALBUM_PARAMS_dist($p) {
*
* @uses albums_decrire_dispositions()
*
* @param integer $id_album
* Numéro de l'album
* @param array $contexte
* Environnement du modèle
* Environnement du modèle, sans les trucs par défaut inutiles (date, date_redac, etc.)
* @param string|null $valeur
* Nom d'un paramètre pour ne retourner que celui-ci
* @return array|string
* Soit un tableau de params : array< string disposition , string modele_doc , string recadrer_ratio , string recadrer_sens , int largeur , int hauteur , bool images >
* Soit une la valeur d'un param
* Soit la valeur d'un param
*/
function calculer_album_params(int $id_album, ? array $contexte = [], ?string $param = null) {
function calculer_album_params(array $contexte = [], ?string $param = null) {
// On fait qu'une seule fois le travail par modèle
// On ne fait qu'une seule fois le travail par modèle
static $memory;
$hash = hash('md5', $id_album . json_encode($contexte, JSON_THROW_ON_ERROR)); // le plus rapide en php 8.1 = xxh3
$uniqid = calculer_id_modele_album($contexte);
$hash = hash('md5', $uniqid.json_encode($contexte, JSON_THROW_ON_ERROR)); // le plus rapide en php 8.1 = xxh3
if (isset($memory[$hash])) {
return ($param ? ($memory[$hash][$param] ?? null) : $memory[$hash]);
}
@ -266,6 +236,9 @@ function calculer_album_params(int $id_album, ?array $contexte = [], ?string $pa
// sinon le test avec `??` est invalide. Ou alors changer la façon de tester.
$set = [];
// À toute fin utile
$set['uniqid'] = $uniqid;
// Disposition
// Priorité : params > constante > config > défaut
$disposition_defaut = array_keys($dispositions)[0]; // 1ère de la liste
@ -322,6 +295,68 @@ function calculer_album_params(int $id_album, ?array $contexte = [], ?string $pa
}
/**
* Nettoyer le contexte pour ne garder que les trucs en rapport avec le modèle
*
* Permet de calculer un hash
*
* @param array|null $contexte
* @return void
*/
function nettoyer_contexte_modele_album(array $contexte = []): array {
$exclure = [
'args', 'date', 'date_redac', 'date_default', 'date_redac_default', 'lang', 'dir_racine', 'wysiwyg', 'espace_prive',
];
$contexte = array_filter($contexte, function ($k) use($exclure) {return !in_array($k, $exclure);}, ARRAY_FILTER_USE_KEY);
return $contexte;
}
/**
* Renvoie un identifiant unique pour le modèle
*
* Dépend de la façon dont sont sélectionnés les documents : soit via id_album, soit id_patate, etc.
*
* @param array|null $contexte
* @return string
* - Si album : < id_album >
* - Si objet : < objet > _< id_objet >
* - si documents : documents_< hash >
*/
function calculer_id_modele_album(array $contexte): string {
static $ids;
$hash = hash('md5', json_encode($contexte, JSON_THROW_ON_ERROR)); // le plus rapide en php 8.1 = xxh3
if (isset($ids[$hash])) {
return $ids[$hash];
}
$ids = [];
// Soit un numéro d'album
if ($id_album = $contexte['id_album'] ?? null) {
$id = (string) $id_album;
// Soit un type et un numéro d'objet
} elseif ($objet = $contexte['objet'] ?? null) {
$id_objet = $contexte['id_objet'] ?? null;
$id = "${objet}_${id_objet}";
// Soit des numéros de documents
} elseif ($id_document = $contexte['id_document'] ?? null) {
$id_document = (is_array($id_document) ? $id_document : explode(',', $id_document));
$id_document = hash('md5', implode('-', $id_document));
$id = "documents_$id_document";
} else {
$id = uniqid();
}
// Ajouter le hash du contexte des fois que le même album soit affiché plusieurs fois
// $id = "${id}_${hash}";
$ids[$hash] = $id;
return $id;
}
/**
* Renvoie une classe correspondant à un ratio
*
@ -368,3 +403,27 @@ function albums_classe_ratio(string $ratio): string {
return $classe;
}
/**
* Compile le critère `{documents_album}`
*
* Rustine pour forcer une jointure en LEFT avec les documents liés.
* Des fois le compilo fait du caca : plusieurs jointures sur la même table,
* et ça pète les conditions dans le WHERE.
*
* @param string $idb Identifiant de la boucle
* @param object $boucles AST du squelette
* @param object $crit Paramètres du critère dans cette boucle
* @return void
*/
function critere_DOCUMENTS_documents_album_dist($idb, & $boucles, $crit) {
$boucle = &$boucles[$idb];
$id_table = $boucle->id_table; // documents
$primary = $boucle->primary; // id_document
$table_join = 'documents_liens';
$table_sql_join = "spip_$table_join";
$boucle->from[$table_join] = $table_sql_join;
$boucle->from_type[$table_join] = 'LEFT';
$boucle->join[$table_join] = ["'$id_table'","'$primary'","'$primary'"];
}