You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

637 lines
19 KiB

<?php
/**
* Utilisations de pipelines par le plugin Albums
*
* @plugin Albums
* @copyright 2014
* @author Tetue, Charles Razack
* @licence GNU/GPL
* @package SPIP\Albums\Pipelines
*/
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Ajout de contenu aux fiches des objets.
*
* - Albums liés aux objets activés dans la configuration du plugin
*
* @pipeline afficher_complement_objet
*
* @param array $flux Données du pipeline
* Données du pipeline, tableau associatif :
* - args : contient au minimum `type` et `id`
* - data : contenu html
* @return array Données du pipeline
*/
function albums_afficher_complement_objet($flux) {
include_spip('base/objets');
$texte = '';
$exec = trouver_objet_exec($flux['args']['type'] ?? '');
$objet = ($exec['type'] ?? '');
$id_objet = (int) ($flux['args']['id'] ?? 0);
$edition = ($exec['edition'] ?? false);
// Fiches des objets activés : albums liés
if (
$exec !== false // page d'un objet éditorial
and $edition === false // pas en mode édition
and $objet !== 'album'
and $id_objet
and $tables_config = lire_config('albums/objets') ?: []
and in_array(table_objet_sql($objet), $tables_config)
) {
$texte .= recuperer_fond(
'prive/squelettes/inclure/albums_objet',
[
'objet' => $objet,
'id_objet' => $id_objet,
'ajouter' => _request('ajouter'),
],
[
'ajax' => 'albums',
]
);
}
if ($texte) {
if ($p = strpos($flux['data'], '<!--afficher_complement_objet-->')) {
$flux['data'] = substr_replace($flux['data'], $texte, $p, 0);
} else {
$flux['data'] .= $texte;
}
}
return $flux;
}
/**
* Ajout de contenu sur certaines pages.
*
* - Auteurs sur la fiche d'un album
* - Message sur la fiche d'un album si auteur pas autorisé à modifier (cf. autorisation)
*
* @pipeline affiche_milieu
*
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function albums_affiche_milieu($flux) {
$texte = '';
$exec = trouver_objet_exec($flux['args']['exec'] ?? '');
$edition = ($exec['edition'] ?? false);
$objet = ($exec['type'] ?? '');
$cle_objet = ($exec['id_table_objet'] ?? '');
$table_objet = ($exec['table_objet'] ?? '');
$table_objet_sql = ($exec['table_objet_sql'] ?? '');
$id_objet = intval($flux['args'][$cle_objet] ?? 0);
// Page d'un album pas en édition
if (
$exec !== false
and $edition === false
and $objet == 'album'
and $id_objet
) {
// liste des auteurs liés
$texte .= recuperer_fond('prive/objets/editer/liens', [
'table_source' => 'auteurs',
'objet' => $objet,
'id_objet' => $id_objet
]);
// message si l'auteur n'est pas autorisé à modifier son propre album
// si celui-ci est lié à un objet qu'il ne peut pas modifier
include_spip('action/editer_liens');
include_spip('inc/session');
$ids_auteurs_album = [];
if (is_array($auteurs = objet_trouver_liens(['auteur' => '*'], [$objet => $id_objet]))) {
$ids_auteurs_album = array_column($auteurs, 'id_auteur');
}
if (
$id_auteur = session_get('id_auteur')
and in_array($id_auteur, $ids_auteurs_album)
and !autoriser('modifier', $objet, $id_objet)
) {
$texte .= message_alerte(_T('album:message_album_non_editable'), '', 'info');
}
}
if ($texte) {
if ($p = strpos($flux['data'], '<!--affiche_milieu-->')) {
$flux['data'] = substr_replace($flux['data'], $texte, $p, 0);
} else {
$flux['data'] .= $texte;
}
}
return $flux;
}
/**
* Modifier ou ajouter du contenu dans la colonne de gauche.
*
* - Gestion des albums sur le formulaire d'édition d'un objet
* lorsqu'on peut lui ajouter des albums mais que l'ajout de documents est désactivé.
*
* @note
* Lors d'une première création de l'objet, celui-ci n'ayant pas
* encore d'identifiant tant que le formulaire d'edition n'est pas enregistré,
* les liaisons entre les albums liés et l'objet à créer sauvegardent
* un identifiant d'objet négatif de la valeur de id_auteur (l'auteur
* connecté). Ces liaisons seront corrigées apres validation dans albums_post_insertion()
* cf. plugin Médias.
*
* @pipeline affiche_gauche
*
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function albums_affiche_gauche($flux) {
$texte = '';
$e = trouver_objet_exec($flux['args']['exec']);
// Edition des objets activés : gestion des albums
if (
$e !== false // page d'un objet éditorial
and $e['edition'] !== false // mode édition uniquement
and $type = $e['type']
and $id_table_objet = $e['id_table_objet']
and (
(isset($flux['args'][$id_table_objet]) and $id = intval($flux['args'][$id_table_objet]))
// id non défini pour les nouveaux objets : on met un identifiant negatif
or ($id = 0 - $GLOBALS['visiteur_session']['id_auteur'])
)
and autoriser('ajouteralbum', $type, $id)
and !autoriser('joindredocument', $type, $id) // si les docs sont déjà activés, rien à faire de plus
) {
$texte .= recuperer_fond(
'prive/objets/editer/colonne_document',
['objet' => $type,'id_objet' => $id]
);
}
if ($texte) {
$flux['data'] .= $texte;
}
return $flux;
}
/**
* Actions effectuées après l'insertion d'un nouvel objet en base.
*
* - Mise à jour les liens temporaires avec les albums.
*
* @note
* Lors d'une première création de l'objet, celui-ci n'ayant pas
* encore d'identifiant tant que le formulaire d'edition n'est pas enregistré,
* les liaisions entre les albums liés et l'objet à créer sauvegardent
* un identifiant d'objet négatif de la valeur de id_auteur (l'auteur
* connecté).
* Une fois l'objet inséré en base, il faut rétablir ces liaisons
* avec le vrai identifiant de l'objet.
* cf. plugin Médias.
*
* @pipeline post_insertion
*
* @param array $flux Données du pipeline
* @return array Données du pipeline
**/
function albums_post_insertion($flux) {
include_spip('inc/autoriser');
include_spip('base/objets');
$objet = objet_type($flux['args']['table'] ?? '');
$id_objet = (int) ($flux['args']['id_objet'] ?? 0);
if (
$objet
and $id_objet
and autoriser('ajouteralbum', $objet, $id_objet)
and $id_auteur = (int) $GLOBALS['visiteur_session']['id_auteur']
) {
include_spip('action/editer_liens');
$id_temporaire = 0 - $id_auteur;
$liens = objet_trouver_liens(['album' => '*'], [$objet => $id_temporaire]);
foreach ($liens as $lien) {
$id_album = (int) $lien['id_album'];
// Associer l'album avec le vrai id de l'objet
objet_associer(['album' => $id_album], [$objet => $id_objet]);
}
// Supprimer les liens temporaires
sql_delete('spip_albums_liens', ['id_objet=' . $id_temporaire, 'objet=' . sql_quote($objet)]);
}
return $flux;
}
/**
* Actions effectuées après l'édition d'un objet.
*
* - Vérifier les albums insérés dans le texte et mettre à jour les liens.
* - Publier ou dépublier les rubriques liées aux albums.
*
* @uses marquer_albums_inseres()
* @pipeline post_edition
*
* @param array $flux
* Données du pipeline, tableau associatif :
* - args : contient au minimum `action`, `table` et `id_objet`
* - data : couples champ => valeur modifiés
* @return array
* Données du pipeline
*/
function albums_post_edition($flux) {
$serveur = ($flux['args']['serveur'] ?? '');
$table = ($flux['args']['table'] ?? '');
$objet = (($flux['args']['objet'] ?? '') ?: ($flux['args']['type'] ?? '') ?: objet_type($table, $serveur));
$id_objet = (int) ($flux['args']['id_objet'] ?? 0);
$data = ($flux['data'] ?? []);
$action = ($flux['args']['action'] ?? '');
// Marquer les albums insérés dans le texte
if (
$objet
and $objet !== 'album'
and $action === 'modifier'
and include_spip('inc/autoriser')
and autoriser('autoassocieralbum', $objet, $id_objet)
) {
$objet_marquer_albums_inseres = charger_fonction('objet_marquer_albums_inseres', 'inc');
$objet_marquer_albums_inseres($objet, $id_objet, $data, $serveur);
}
// Publier / dépublier les rubriques liées
if (
$objet === 'album'
and $action === 'instituer'
and $statut = $flux['data']['statut'] ?? ''
and $statut_ancien = $flux['args']['statut_ancien'] ?? ''
and $statut !== $statut_ancien // Au cas-où
and include_spip('action/editer_liens')
and $liens_rubriques = objet_trouver_liens(['album' => $id_objet], ['rubrique' => '*'])
) {
include_spip('inc/rubriques');
$ids_rubriques = array_column($liens_rubriques, 'id_objet');
$ids_rubriques = array_map('intval', $ids_rubriques);
foreach($ids_rubriques as $id_rubrique) {
// On dépublie
if ($statut !== 'publie') {
depublier_branche_rubrique_if($id_rubrique);
// On publie
} else {
publier_branche_rubrique($id_rubrique);
}
}
}
return $flux;
}
/**
* Actions effectuées après l'édition des liens.
*
* - Publier ou dépublier les rubriques liées aux albums.
* (Nb : faudrait un truc générique dans le core ?)
*
* @pipeline post_edition_lien
*
* @param array $flux
* Données du pipeline, tableau associatif :
* - args : contient `action`, `table_lien`, `objet_source`, `id_objet_source`, `objet`, `id_objet`
* - data : valeur de $args['id_objet']
* @return array
* Données du pipeline
*/
function albums_post_edition_lien($flux) {
$action = ($flux['args']['action'] ?? ''); // insert / delete / modifier
$table_lien = ($flux['args']['table_lien'] ?? ''); // spip_albums_liens
$objet_source = ($flux['args']['objet_source'] ?? ''); // album
$id_objet_source = (int) ($flux['args']['id_objet_source'] ?? 0); // id_album
$objet = ($flux['args']['objet'] ?? '');
$id_objet = (int) ($flux['args']['id_objet'] ?? 0);
// Si on associe ou dissocie un album publié d'une rubrique
if (
$objet_source === 'album'
and $objet === 'rubrique'
and include_spip('base/objets')
and objet_test_si_publie('album', $id_objet_source)
) {
switch ($action) {
case 'insert':
include_spip('inc/rubriques');
publier_branche_rubrique($id_objet);
break;
case 'delete':
include_spip('inc/rubriques');
depublier_branche_rubrique_if($id_objet);
break;
}
}
return $flux;
}
/**
* Ajout de feuilles de style CSS sur les pages publiques
*
* @pipeline insert_head_css
*
* @param string $flux Feuilles de styles
* @return string Description complétée des feuilles de styles
*/
function albums_insert_head_css($flux) {
if (!defined('_ALBUMS_INSERT_HEAD_CSS') or !_ALBUMS_INSERT_HEAD_CSS) {
include_spip('inc/config');
if (!function_exists('liste_plugin_actifs')) {
include_spip('inc/plugin');
}
$cfg = (defined('_ALBUMS_INSERT_HEAD_CSS') ? _ALBUMS_INSERT_HEAD_CSS : lire_config('albums/insert_head_css', 1));
if ($cfg) {
// feuille de style minimale de base
$flux .= '<link rel="stylesheet" href="' . direction_css(find_in_path('css/albums.css')) . '" type="text/css" />';
}
}
return $flux;
}
/**
* Compter les albums liés à un objet
*
* Nb : on ne compte que les publiés afin que la publication/dépublication des rubrique fonctionne correctement
*
* @pipeline objet_compte_enfants
*
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function albums_objet_compte_enfants($flux) {
if (
$objet = ($flux['args']['objet'] ?? '')
and $id_objet = (int) ($flux['args']['id_objet'] ?? 0)
) {
// Juste les publiés ?
// $publies_only = ($flux['args']['statut'] ?? '' === 'publie'); // des fois pas là alors que nécessaire ? On bypass
$publies_only = true;
$statuts = ($publies_only ? ['publie'] : ['prepa', 'publie']);
$sql_in = (function_exists('sql_in_quotes') ? 'sql_in_quotes' : 'sql_in');
$flux['data']['album'] = sql_countsel(
'spip_albums A JOIN spip_albums_liens L ON A.id_album = L.id_album',
[
'L.objet = ' . sql_quote($objet),
"L.id_objet = $id_objet",
$sql_in('A.statut', $statuts),
]
);
}
return $flux;
}
/**
* Afficher le nombre d'albums liés publiés dans la boîte infos des rubriques
*
* @pipeline boite_infos
*
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function albums_boite_infos($flux) {
if (
($flux['args']['type'] ?? '') === 'rubrique'
and $id_rubrique = (int) ($flux['args']['id'] ?? 0)
) {
$args_compter = ['args' => ['objet' => 'rubrique', 'id_objet' => $id_rubrique]];
$compter = albums_objet_compte_enfants($args_compter);
$nb = ($compter['data']['album'] ?? 0);
if ($nb) {
$texte = '<div class="nb-albums">' . singulier_ou_pluriel($nb, 'album:info_1_album', 'album:info_nb_albums') . '</div>';
if ($p = strpos($flux['data'], '<!--nb_elements-->')) {
$flux['data'] = substr_replace($flux['data'], $texte, $p, 0);
}
}
}
return $flux;
}
/**
* Optimiser la base de donnée en supprimant les liens orphelins
*
* On supprime :
* - les albums à la poubelle
* - les liens obsolètes
*
* @pipeline optimiser_base_disparus
*
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function albums_optimiser_base_disparus($flux) {
// albums à la poubelle
if (
isset($flux['args']['date']) and $flux['args']['date']
and is_array($ids_albums_poubelle = sql_allfetsel(
'id_album',
table_objet_sql('album'),
"statut='poubelle' AND maj < " . sql_quote(trim($flux['args']['date'], "'"))
))
) {
$ids_albums_poubelle = array_column($ids_albums_poubelle, 'id_album');
include_spip('inc/albums');
supprimer_albums($ids_albums_poubelle);
}
// optimiser les liens morts entre documents et albums
include_spip('action/editer_liens');
$flux['data'] += objet_optimiser_liens(['document' => '*'], ['album' => '*']);
$flux['data'] += objet_optimiser_liens(['album' => '*'], '*');
return $flux;
}
/**
* Compléter les vérifications des valeurs postées dans les formulaires
*
* - configuration des documents : vérifier que les albums sont sélectionnés
*
* @param array $flux
* @return array
*/
function albums_formulaire_verifier(array $flux): array {
// Config des documents
if ($flux['args']['form'] == 'configurer_documents') {
include_spip('albums_administrations');
$objets = _request('documents_objets') ?: [];
$objets_full = albums_verifier_config_documents($objets, false);
set_request('documents_objets', $objets_full);
}
return $flux;
}
/**
* Modifier le résultat du calcul d'un squelette
*
* - privé / inc-upload_document : identifiant unique + wording si utilisé pour un album.
* - privé / portfolio_document : remplacer par un autre squelette pour les albums.
* - privé / colonne-documents : remplacer par un autre squelette
* - privé / document_desc : ajouter un attribut rel pour les albums
* - privé / documents : ajout de la barre d'onglets
* - public / inclure/documents : on ajoute les albums à la suite
*
* @pipeline recuperer_fond
*
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function albums_recuperer_fond($flux) {
$fond = ($flux['args']['fond'] ?? '');
$objet = ($flux['args']['contexte']['objet'] ?? '');
$id_objet = ($flux['args']['contexte']['id_objet'] ?? 0);
// Ajuster le squelette d'upload de document : identifiant unique, wording
if (
$fond === 'formulaires/inc-upload_document'
and $objet === 'album'
) {
// Rendre unique l'identifiant du conteneur
// Définition dans le squelette : _#ENV{mode}|concat{'_',#ENV{id,new}}
$texte = $flux['data']['texte'];
$mode = ($flux['args']['contexte']['mode'] ?? '');
$id = ($id_objet ?: 'new');
$domid = "_{$mode}_{$id}";
$dom_uniqid = $domid . uniqid('_');
$flux['data']['texte'] = str_replace($domid, $dom_uniqid, $texte);
// Remplacer le texte des boutons dans le formulaire « ajouter_album »
if (
isset($flux['args']['contexte']['form'])
and $flux['args']['contexte']['form'] === 'ajouter_album'
) {
$enregistrer = _T('bouton_enregistrer');
$cherche = [
_T('bouton_upload'),
_T('medias:bouton_attacher_document'),
_T('bouton_choisir'),
];
$flux['data']['texte'] = str_replace($cherche, $enregistrer, $texte);
}
}
// Privé : remplacer le squelette de portfolio des documents sur la fiche d'un album
if (
$fond === 'prive/objets/contenu/portfolio_document'
and $objet === 'album'
) {
$flux['data']['texte'] = recuperer_fond(
'prive/squelettes/inclure/portfolio_documents_album',
$flux['args']['contexte'],
['ajax' => 'documents',]
);
}
// Privé : remplacer le squelette des documents en colonne pour l'édition d'un objet
if (
$fond === 'prive/objets/editer/colonne_document'
and empty($flux['args']['contexte']['bypass'])
) {
$flux['data']['texte'] = recuperer_fond(
'prive/objets/editer/colonne_documents_albums',
array_merge($flux['args']['contexte'], ['ajouter' => _request('ajouter')]),
['ajax' => true]
);
}
// Privé : modèles d'aperçu des documents dans les listes : insérer un attribut rel sur le <a> entourant la vignette.
// C'est à priori le seul moyen de faire fonctionner le mode galerie de la mediabox tout en isolant chaque album.
// (ce n'est pas possible avec la config du sélecteur jQuery des galeries).
// Le <a> est produit par la fonction `vignette_automatique()` qu'on ne peut pas surcharger ou étendre.
// On fait donc comme on peut avec un chercher/remplacer à l'arrache.
if (
in_array($fond, ['modeles/document_desc', 'modeles/document_case'])
and $objet === 'album'
) {
// On cherche le `type="image/xxx"` et on s'insert avant
$needles = [
'type=\'image/',
'type="image/',
];
foreach ($needles as $needle) {
$insert = "rel=\"album$id_objet\" ";
if (($pos = strpos($flux['data']['texte'], $needle)) !== false) {
$flux['data']['texte'] = substr_replace($flux['data']['texte'], $insert, $pos, 0);
}
}
}
// Privé : ajout de la barre d'onglets dans la médiathèque
if ($fond === 'prive/squelettes/top/documents') {
include_spip('inc/boutons');
$texte = $flux['data']['texte'];
// On masque visuellement le titre, et on la place avant
if ($pos = strpos($texte, 'grostitre')) {
$texte = substr_replace($texte, 'offscreen', $pos, strlen('grostitre'));
}
$flux['data']['texte'] = barre_onglets('albums_documents', 'mediatheque') . $texte;
}
// Public : portfolio des articles
// On ajoute les albums non insérés dans le texte à la suite
if (
$fond === 'inclure/documents'
and $portfolio_albums = recuperer_fond('inclure/albums_dist', $flux['args']['contexte'] ?? [])
) {
$flux['data']['texte'] .= $portfolio_albums;
}
return $flux;
}
/**
* Ajouter des contenus dans la partie <head> des pages de l’espace privé
*
* - Ajout de l'URL de l'action pour ordonner les albums dans la variable de config globale
* - Ajout du chemin vers le script sortable
*
* @param string $flux
* @return string
*/
function albums_header_prive($flux) {
$js = "\n<script>"
. 'spipConfig.url_action_ordonner_liens_albums="' . generer_url_action('ordonner_liens_albums', '', 1) . "\"\n"
. 'spipConfig.url_script_sortable="' . timestamp(find_in_path('prive/javascript/Sortable.js')) . "\"\n"
. '</script>';
$flux .= $js;
return $flux;
}