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.
 
 

240 lines
6.9 KiB

<?php
/**
* Fonctions utiles au plugin Rôles de documents
*
* @plugin Rôles de documents
* @copyright 2015-2018
* @author tcharlss
* @licence GNU/GPL
* @package SPIP\Roles_documents\Fonctions
*/
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Lister les rôles de documents pour un objet : ceux possibles, ceux attribués et non attribués.
*
* - Soit les rôles uniques des documents pour un type d'objet (si $id_document == 0)
* - Soit tous les rôles entre un document et un objet (si $id_document)
*
* @note
* Vaguement basé sur la fonction roles_presents_sur_id() de l'API.
*
* @see
* roles_presents_sur_id()
* roles_presents_liaisons()
*
* @param string $objet
* Type d'objet lié
* @param integer $id_objet
* Numéro de l'objet lié
* @param integer $id_document
* Numéro d'un document pour renvoyer les rôles de ce document précis
* @param null|bool|string $principaux
* null : ne pas filtrer les rôles principaux
* true : ne renvoyer que les rôles principaux
* false ou '' : exclure les rôles principaux
* @return array
* Tableau associatif avec 3 clés
* - possibles : tous les rôles possibles
* - attribues : ceux attribués
* - attribuables : ceux non attribues
*/
function roles_documents_presents_sur_objet($objet, $id_objet, $id_document = 0, $principaux = null) {
static $done = array();
// Stocker le résultat
$hash = "$id_document-$objet-$id_objet-$principaux";
if (isset($done[$hash])) {
return $done[$hash];
}
// Liste de tous les rôles possibles
// Si aucun rôle sur cet objet, on sort
$infos_roles = roles_presents('document', $objet);
if (!$infos_roles) {
return $done['hash'] = false;
}
$roles_possibles = $infos_roles['roles']['choix'];
// Fallback rôles principaux si non déclarés
if (empty($infos_roles['roles']['principaux'])) {
$infos_roles['roles']['principaux'] = array('logo', 'logo_survol');
}
// Liste des rôles attribués
$select = 'distinct(role)';
$where = array(
'objet = ' . sql_quote($objet),
'id_objet = ' . intval($id_objet),
"role != ''",
);
if ($id_document) {
$select = 'role';
$where[] = 'id_document=' . intval($id_document);
}
$res = sql_allfetsel($select, 'spip_documents_liens', $where);
$roles_attribues = array_column($res, 'role');
// On trie les rôles attribués dans le même ordre que les rôles possibles,
// et non dans l'ordre de création des liens dans la base.
$roles_attribues_ordonnes = array();
foreach ($roles_possibles as $role) {
if (in_array($role, $roles_attribues)) {
$roles_attribues_ordonnes[] = $role;
}
}
$roles_attribues = $roles_attribues_ordonnes;
// Liste des rôles non attribués
$roles_attribuables = array_diff($roles_possibles, $roles_attribues);
// On filtre éventuellement les rôles principaux (=logos)
// Note : array_values pour remettre les bonnes clés
if (
!is_null($principaux)
and $roles_principaux = $infos_roles['roles']['principaux']
){
$filtrer = ($principaux ? 'array_intersect' : 'array_diff');
$roles_possibles = array_values($filtrer($roles_possibles, $roles_principaux));
$roles_attribues = array_values($filtrer($roles_attribues, $roles_principaux));
$roles_attribuables = array_values($filtrer($roles_attribuables, $roles_principaux));
}
// On retourne le détail
$roles = array(
'possibles' => $roles_possibles,
'attribues' => $roles_attribues,
'attribuables' => $roles_attribuables,
);
return $done[$hash] = $roles;
}
/**
* Lister tous les rôles de documents déclarés, tous objets confondus
*
* @return array
*/
function roles_documents_presents() {
static $roles_documents = null;
if (is_array($roles_documents)) {
return $roles_documents;
}
$roles_documents = array();
if (
$roles_presents = roles_presents('document')
) {
foreach($roles_presents['roles'] as $objet) {
$roles_documents = array_merge($roles_documents, $objet['choix']);
}
$roles_documents = array_unique($roles_documents);
}
return $roles_documents;
}
/**
* Surcharge du critère `logo`
*
* Tout comme le critère {logo} par défaut, on permet de sélectionner tous les
* objets qui ont un logo, quel qu'il soit, au format historique ou au format
* document.
*
* Un unique paramètre optionnel permet de se restreindre à un rôle
* particulier. Par exemple, {logo accueil} permet de sélectionner les logos
* dont le rôle est 'logo_accueil'.
*
* {!logo} permet d'inverser la sélection, pour avoir les objets qui n'ont PAS
* de logo.
*
* @uses lister_objets_avec_logos()
* Pour obtenir les éléments qui ont un logo enregistrés avec la méthode
* "historique".
*
* @param string $idb Identifiant de la boucle
* @param array $boucles AST du squelette
* @param Critere $crit Paramètres du critère dans cette boucle
* @return void
*/
function critere_logo($idb, &$boucles, $crit) {
$boucle = &$boucles[$idb];
// On interprète le premier paramètre du critère, qui nous donne le type de
// logo
if (count($crit->param)) {
$type_logo = calculer_liste(
array_shift($crit->param),
array(),
$boucles,
$boucle->id_parent
);
$type_logo = trim($type_logo, "'");
}
// Pour ajouter la jointure qu'il nous faut à la boucle, on lui donne le
// premier alias L* qui n'est pas utilisé.
$i = 1;
while (isset($boucle->from["L$i"])) {
$i++;
}
$alias_jointure = "L$i";
$alias_table = $boucle->id_table;
$id_table_objet = $boucle->primary;
// On fait un LEFT JOIN avec les liens de documents qui correspondent au(x)
// rôle(s) cherchés. Cela permet de sélectionner aussi les objets qui n'ont
// pas de logo, dont le rôle sera alors NULL. C'est nécessaire pour pouvoir
// gérer les logos enregistrés avec l'ancienne méthode, et pour {!logo}.
$boucle->from[$alias_jointure] = 'spip_documents_liens';
$boucle->from_type[$alias_jointure] = 'LEFT';
$boucle->join[$alias_jointure] = array(
"'$alias_table'",
"'id_objet'",
"'$id_table_objet'",
"'$alias_jointure.objet='.sql_quote('" . objet_type($alias_table) . "')." .
"' AND $alias_jointure.role LIKE \'logo\_" . ($type_logo ?: '%') . "\''",
);
$boucle->group[] = "$alias_table.$id_table_objet";
// On calcule alors le where qui va bien.
if ($crit->not) {
$where = "$alias_jointure.role IS NULL";
} else {
$where = array(
"'LIKE'",
"'$alias_jointure.role'",
"'\'logo\_" . ($type_logo ?: '%') . "\''",
);
}
// Rétro-compatibilité : Si l'on ne cherche pas un type de logo particulier,
// on retourne aussi les logos enregistrés avec la méthode "historique".
if (! $type_logo) {
$where_historique =
'sql_in('
. "'$alias_table.$id_table_objet', "
. "lister_objets_avec_logos('$id_table_objet'), "
. "'')";
if ($crit->not) {
$where_historique = array("'NOT'", $where_historique);
}
$where = array(
"'OR'",
$where,
$where_historique
);
}
// On ajoute le where à la boucle
$boucle->where[] = $where;
}