Browse Source
Suite à l'intégration dans SPIP de l'API d'édition de liens avec roles,
Suite à l'intégration dans SPIP de l'API d'édition de liens avec roles,
les fichiers surchargés ne sont plus nécessaires, tout comme inc/roles. Cf. https://core.spip.net/projects/spip/repository/revisions/22075svn/root/tags/v2.1.0
5 changed files with 1 additions and 1605 deletions
-
3.gitattributes
-
806action/editer_liens.php
-
435formulaires/editer_liens.php
-
360inc/roles.php
-
2paquet.xml
@ -1,806 +0,0 @@ |
|||
<?php |
|||
|
|||
/***************************************************************************\ |
|||
* SPIP, Systeme de publication pour l'internet * |
|||
* * |
|||
* Copyright (c) 2001-2015 * |
|||
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * |
|||
* * |
|||
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. * |
|||
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * |
|||
\***************************************************************************/ |
|||
|
|||
/** |
|||
* API d'édition de liens |
|||
* |
|||
* Cette API gère la création, modification et suppressions de liens |
|||
* entre deux objets éditoriaux par l'intermédiaire de tables de liaison |
|||
* tel que spip_xx_liens. |
|||
* |
|||
* L'unicité est assurée dans les fonctions sur le trio (id_x, objet, id_objet) |
|||
* par défaut, ce qui correspond à la déclaration de clé primaire. |
|||
* |
|||
* Des rôles peuvent être déclarés pour des liaisons. À ce moment là, |
|||
* une colonne spécifique doit être présente dans la table de liens |
|||
* et l'unicité est alors assurée sur le quatuor (id_x, objet, id_objet, role) |
|||
* et la clé primaire adaptée en conséquence. |
|||
* |
|||
* @package SPIP\Core\Liens\API |
|||
*/ |
|||
|
|||
if (!defined('_ECRIRE_INC_VERSION')) return; |
|||
|
|||
// charger la gestion les rôles sur les objets
|
|||
include_spip('inc/roles'); |
|||
|
|||
|
|||
/** |
|||
* Teste l'existence de la table de liaison xxx_liens d'un objet |
|||
* |
|||
* @api |
|||
* @param string $objet |
|||
* Objet à tester |
|||
* @return array|bool |
|||
* - false si l'objet n'est pas associable. |
|||
* - array(clé primaire, nom de la table de lien) si associable |
|||
*/ |
|||
function objet_associable($objet){ |
|||
$trouver_table = charger_fonction('trouver_table','base'); |
|||
$table_sql = table_objet_sql($objet); |
|||
|
|||
$l=""; |
|||
if ($primary = id_table_objet($objet) |
|||
AND $trouver_table($l = $table_sql."_liens") |
|||
AND !preg_match(',[^\w],',$primary) |
|||
AND !preg_match(',[^\w],',$l)) |
|||
return array($primary,$l); |
|||
|
|||
spip_log("Objet $objet non associable : ne dispose pas d'une cle primaire $primary OU d'une table liens $l"); |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* Associer un ou des objets à des objets listés |
|||
* |
|||
* $objets_source et $objets_lies sont de la forme |
|||
* array($objet=>$id_objets,...) |
|||
* $id_objets peut lui meme etre un scalaire ou un tableau pour une liste d'objets du meme type |
|||
* ou de la forme array("NOT",$id_objets) pour une selection par exclusion |
|||
* |
|||
* Les objets sources sont les pivots qui portent les liens |
|||
* et pour lesquels une table spip_xxx_liens existe |
|||
* (auteurs, documents, mots) |
|||
* |
|||
* on peut passer optionnellement une qualification du (des) lien(s) qui sera |
|||
* alors appliquee dans la foulee. |
|||
* En cas de lot de liens, c'est la meme qualification qui est appliquee a tous |
|||
* |
|||
* @api |
|||
* @param array $objets_source |
|||
* @param array|string $objets_lies |
|||
* @param array $qualif |
|||
* @return bool|int |
|||
*/ |
|||
function objet_associer($objets_source, $objets_lies, $qualif = null){ |
|||
$modifs = objet_traiter_liaisons('lien_insert', $objets_source, $objets_lies, $qualif); |
|||
|
|||
if ($qualif) |
|||
objet_qualifier_liens($objets_source, $objets_lies, $qualif); |
|||
|
|||
return $modifs; // pas d'erreur
|
|||
} |
|||
|
|||
|
|||
/** |
|||
* Dissocier un (ou des) objet(s) des objets listés |
|||
* |
|||
* $objets_source et $objets sont de la forme |
|||
* array($objet=>$id_objets,...) |
|||
* $id_objets peut lui meme etre un scalaire ou un tableau pour une liste d'objets du meme type |
|||
* |
|||
* Les objets sources sont les pivots qui portent les liens |
|||
* et pour lesquels une table spip_xxx_liens existe |
|||
* (auteurs, documents, mots) |
|||
* |
|||
* un * pour $objet,$id_objet permet de traiter par lot |
|||
* seul le type de l'objet source ne peut pas accepter de joker et doit etre explicite |
|||
* |
|||
* S'il y a des rôles possibles entre les 2 objets, et qu'aucune condition |
|||
* sur la colonne du rôle n'est transmise, on ne supprime que les liens |
|||
* avec le rôle par défaut. Si on veut supprimer tous les rôles, |
|||
* il faut spécifier $cond => array('role' => '*') |
|||
* |
|||
* @api |
|||
* @param array $objets_source |
|||
* @param array|string $objets_lies |
|||
* @param array|null $cond |
|||
* Condition du where supplémentaires |
|||
* |
|||
* À l'exception de l'index 'role' qui permet de sélectionner un rôle |
|||
* ou tous les rôles (*), en s'affranchissant du vrai nom de la colonne. |
|||
* @return bool|int |
|||
*/ |
|||
function objet_dissocier($objets_source,$objets_lies, $cond=null){ |
|||
return objet_traiter_liaisons('lien_delete',$objets_source,$objets_lies, $cond); |
|||
} |
|||
|
|||
|
|||
|
|||
/** |
|||
* Qualifier le lien entre un (ou des) objet(s) et des objets listés |
|||
* |
|||
* $objets_source et $objets sont de la forme |
|||
* array($objet=>$id_objets,...) |
|||
* $id_objets peut lui meme etre un scalaire ou un tableau pour une liste d'objets du meme type |
|||
* |
|||
* Les objets sources sont les pivots qui portent les liens |
|||
* et pour lesquels une table spip_xxx_liens existe |
|||
* (auteurs, documents, mots) |
|||
* |
|||
* un * pour $objet,$id_objet permet de traiter par lot |
|||
* seul le type de l'objet source ne peut pas accepter de joker et doit etre explicite |
|||
* |
|||
* @api |
|||
* @param array $objets_source |
|||
* @param array|string $objets_lies |
|||
* @param array $qualif |
|||
* @return bool|int |
|||
*/ |
|||
function objet_qualifier_liens($objets_source,$objets_lies,$qualif){ |
|||
return objet_traiter_liaisons('lien_set',$objets_source,$objets_lies,$qualif); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Trouver les liens entre objets |
|||
* |
|||
* $objets_source et $objets sont de la forme |
|||
* array($objet=>$id_objets,...) |
|||
* $id_objets peut lui meme etre un scalaire ou un tableau pour une liste d'objets du meme type |
|||
* |
|||
* Les objets sources sont les pivots qui portent les liens |
|||
* et pour lesquels une table spip_xxx_liens existe |
|||
* (auteurs, documents, mots) |
|||
* |
|||
* un * pour $objet,$id_objet permet de traiter par lot |
|||
* seul le type de l'objet source ne peut pas accepter de joker et doit etre explicite |
|||
* |
|||
* renvoie une liste de tableaux decrivant chaque lien |
|||
* dans lequel objet_source et objet_lie sont aussi affectes avec l'id de chaque |
|||
* par facilite |
|||
* ex : |
|||
* array( |
|||
* array('id_document'=>23,'objet'=>'article','id_objet'=>12,'vu'=>'oui', |
|||
* 'document'=>23,'article'=>12) |
|||
* ) |
|||
* |
|||
* @api |
|||
* @param array $objets_source Couples (objets_source => identifiants) (objet qui a la table de lien) |
|||
* @param array|string $objets_lies Couples (objets_lies => identifiants) |
|||
* @param array|null $cond Condition du where supplémentaires |
|||
* @return array |
|||
* Liste des trouvailles |
|||
*/ |
|||
function objet_trouver_liens($objets_source,$objets_lies,$cond=null){ |
|||
return objet_traiter_liaisons('lien_find',$objets_source,$objets_lies,$cond); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Nettoyer les liens morts vers des objets qui n'existent plus |
|||
* |
|||
* $objets_source et $objets sont de la forme |
|||
* array($objet=>$id_objets,...) |
|||
* $id_objets peut lui meme etre un scalaire ou un tableau pour une liste d'objets du meme type |
|||
* |
|||
* Les objets sources sont les pivots qui portent les liens |
|||
* et pour lesquels une table spip_xxx_liens existe |
|||
* (auteurs, documents, mots) |
|||
* |
|||
* un * pour $objet,$id_objet permet de traiter par lot |
|||
* seul le type de l'objet source ne peut pas accepter de joker et doit etre explicite |
|||
* |
|||
* @api |
|||
* @param array $objets_source |
|||
* @param array|string $objets_lies |
|||
* @return int |
|||
*/ |
|||
function objet_optimiser_liens($objets_source,$objets_lies){ |
|||
return objet_traiter_liaisons('lien_optimise',$objets_source,$objets_lies); |
|||
} |
|||
|
|||
|
|||
|
|||
/** |
|||
* Dupliquer tous les liens entrant ou sortants d'un objet |
|||
* vers un autre (meme type d'objet, mais id different) |
|||
* si $types est fourni, seuls les liens depuis/vers les types listes seront copies |
|||
* si $exclure_types est fourni, les liens depuis/vers les types listes seront ignores |
|||
* |
|||
* @api |
|||
* @param string $objet |
|||
* @param int $id_source |
|||
* @param int $id_cible |
|||
* @param array $types |
|||
* @param array $exclure_types |
|||
* @return int |
|||
* Nombre de liens copiés |
|||
*/ |
|||
function objet_dupliquer_liens($objet,$id_source,$id_cible,$types=null,$exclure_types=null){ |
|||
include_spip('base/objets'); |
|||
$tables = lister_tables_objets_sql(); |
|||
$n = 0; |
|||
foreach($tables as $table_sql => $infos){ |
|||
if ( |
|||
(is_null($types) OR in_array($infos['type'],$types)) |
|||
AND (is_null($exclure_types) OR !in_array($infos['type'],$exclure_types)) |
|||
){ |
|||
if (objet_associable($infos['type'])){ |
|||
$liens = (($infos['type']==$objet)? |
|||
objet_trouver_liens(array($objet=>$id_source),'*') |
|||
: |
|||
objet_trouver_liens(array($infos['type']=>'*'),array($objet=>$id_source))); |
|||
foreach($liens as $lien){ |
|||
$n++; |
|||
if ($infos['type']==$objet){ |
|||
objet_associer(array($objet=>$id_cible),array($lien['objet']=>$lien[$lien['objet']]),$lien); |
|||
} |
|||
else { |
|||
objet_associer(array($infos['type']=>$lien[$infos['type']]),array($objet=>$id_cible),$lien); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return $n; |
|||
} |
|||
|
|||
/** |
|||
* Fonctions techniques |
|||
* ne pas les appeler directement |
|||
*/ |
|||
|
|||
|
|||
/** |
|||
* Fonction générique qui |
|||
* applique une operation de liaison entre un ou des objets et des objets listés |
|||
* |
|||
* $objets_source et $objets_lies sont de la forme |
|||
* array($objet=>$id_objets,...) |
|||
* $id_objets peut lui meme etre un scalaire ou un tableau pour une liste d'objets du meme type |
|||
* |
|||
* Les objets sources sont les pivots qui portent les liens |
|||
* et pour lesquels une table spip_xxx_liens existe |
|||
* (auteurs, documents, mots) |
|||
* |
|||
* on peut passer optionnellement une qualification du (des) lien(s) qui sera |
|||
* alors appliquee dans la foulee. |
|||
* En cas de lot de liens, c'est la meme qualification qui est appliquee a tous |
|||
* |
|||
* @internal |
|||
* @param string $operation |
|||
* Nom de la fonction PHP qui traitera l'opération |
|||
* @param array $objets_source |
|||
* Liste de ou des objets source |
|||
* De la forme array($objet=>$id_objets,...), où $id_objets peut lui |
|||
* même être un scalaire ou un tableau pour une liste d'objets du même type |
|||
* @param array $objets_lies |
|||
* Liste de ou des objets liés |
|||
* De la forme array($objet=>$id_objets,...), où $id_objets peut lui |
|||
* même être un scalaire ou un tableau pour une liste d'objets du même type |
|||
* @param null|array $set |
|||
* Liste de coupels champs valeur, soit array(champs => valeur) |
|||
* En fonction des opérations il peut servir à différentes utilisations |
|||
* @return bool|int|array |
|||
*/ |
|||
function objet_traiter_liaisons($operation,$objets_source,$objets_lies, $set = null){ |
|||
// accepter une syntaxe minimale pour supprimer tous les liens
|
|||
if ($objets_lies=='*') $objets_lies = array('*'=>'*'); |
|||
$modifs = 0; // compter le nombre de modifications
|
|||
$echec = null; |
|||
foreach($objets_source as $objet=>$ids){ |
|||
if ($a = objet_associable($objet)) { |
|||
list($primary,$l) = $a; |
|||
if (!is_array($ids)) |
|||
$ids = array($ids); |
|||
elseif(reset($ids)=="NOT"){ |
|||
// si on demande un array('NOT',...) => recuperer la liste d'ids correspondants
|
|||
$where = lien_where($primary,$ids,'*','*'); |
|||
$ids = sql_allfetsel($primary,$l,$where); |
|||
$ids = array_map('reset',$ids); |
|||
} |
|||
foreach($ids as $id) { |
|||
$res = $operation($objet,$primary,$l,$id,$objets_lies,$set); |
|||
if ($res===false) { |
|||
spip_log("objet_traiter_liaisons [Echec] : $operation sur $objet/$primary/$l/$id",_LOG_ERREUR); |
|||
$echec = true; |
|||
} |
|||
else |
|||
$modifs=($modifs?(is_array($res)?array_merge($modifs,$res):$modifs+$res):$res); |
|||
} |
|||
} |
|||
else |
|||
$echec = true; |
|||
} |
|||
|
|||
return ($echec?false:$modifs); // pas d'erreur
|
|||
} |
|||
|
|||
|
|||
/** |
|||
* Sous fonction insertion |
|||
* qui traite les liens pour un objet source dont la clé primaire |
|||
* et la table de lien sont fournies |
|||
* |
|||
* $objets et de la forme |
|||
* array($objet=>$id_objets,...) |
|||
* |
|||
* Retourne le nombre d'insertions réalisées |
|||
* |
|||
* @internal |
|||
* @param string $objet_source Objet source de l'insertion (celui qui a la table de liaison) |
|||
* @param string $primary Nom de la clé primaire de cet objet |
|||
* @param string $table_lien Nom de la table de lien de cet objet |
|||
* @param int $id Identifiant de l'objet sur lesquels on va insérer des liaisons |
|||
* @param array $objets Liste des liaisons à faire, de la forme array($objet=>$id_objets) |
|||
* @param array $qualif |
|||
* Liste des qualifications à appliquer (qui seront faites par lien_set()), |
|||
* dont on cherche un rôle à insérer également. |
|||
* Si l'objet dispose d'un champ rôle, on extrait des qualifications |
|||
* le rôle s'il est présent, sinon on applique le rôle par défaut. |
|||
* @return bool|int |
|||
* Nombre d'insertions faites, false si échec. |
|||
*/ |
|||
function lien_insert($objet_source,$primary,$table_lien,$id,$objets,$qualif) { |
|||
$ins = 0; |
|||
$echec = null; |
|||
if (is_null($qualif)) $qualif = array(); |
|||
|
|||
foreach($objets as $objet => $id_objets){ |
|||
if (!is_array($id_objets)) $id_objets = array($id_objets); |
|||
|
|||
// role, colonne, where par défaut
|
|||
list($role, $colonne_role, $cond) = |
|||
roles_trouver_dans_qualif($objet_source, $objet, $qualif); |
|||
|
|||
foreach($id_objets as $id_objet) { |
|||
$objet = ($objet=='*')?$objet:objet_type($objet); # securite
|
|||
|
|||
$insertions = array( |
|||
'id_objet' => $id_objet, |
|||
'objet' => $objet, |
|||
$primary => $id |
|||
); |
|||
// rôle en plus s'il est défini
|
|||
if ($role) $insertions += array( |
|||
$colonne_role => $role |
|||
); |
|||
$args = array( |
|||
'table_lien' => $table_lien, |
|||
'objet_source' => $objet_source, |
|||
'id_objet_source' => $id, |
|||
'objet' => $objet, |
|||
'id_objet' => $id_objet, |
|||
'role' => $role, |
|||
'colonne_role' => $colonne_role, |
|||
'action' => 'insert', |
|||
); |
|||
|
|||
// Envoyer aux plugins
|
|||
$id_objet = pipeline('pre_edition_lien', |
|||
array( |
|||
'args' => $args, |
|||
'data' => $id_objet |
|||
) |
|||
); |
|||
$args['id_objet'] = $id_objet; |
|||
|
|||
$where = lien_where($primary, $id, $objet, $id_objet, $cond); |
|||
|
|||
if ($id_objet=intval($insertions['id_objet']) |
|||
AND !sql_getfetsel($primary, $table_lien, $where)) { |
|||
|
|||
$e = sql_insertq($table_lien, $insertions); |
|||
if ($e!==false) { |
|||
$ins++; |
|||
lien_propage_date_modif($objet,$id_objet); |
|||
lien_propage_date_modif($objet_source,$id); |
|||
// Envoyer aux plugins
|
|||
pipeline('post_edition_lien', |
|||
array( |
|||
'args' => $args, |
|||
'data' => $id_objet |
|||
) |
|||
); |
|||
} |
|||
else |
|||
$echec = true; |
|||
} |
|||
} |
|||
} |
|||
return ($echec?false:$ins); |
|||
} |
|||
|
|||
/** |
|||
* Fabriquer la condition where en tenant compte des jokers * |
|||
* |
|||
* @internal |
|||
* @param string $primary Nom de la clé primaire |
|||
* @param int|string|array $id_source Identifiant de la clé primaire |
|||
* @param string $objet Nom de l'objet lié |
|||
* @param int|string|array $id_objet Identifiant de l'objet lié |
|||
* @param array $cond Conditions par défaut |
|||
* @return array Liste des conditions |
|||
*/ |
|||
function lien_where($primary, $id_source, $objet, $id_objet, $cond=array()){ |
|||
if ((!is_array($id_source) AND !strlen($id_source)) |
|||
OR !strlen($objet) |
|||
OR (!is_array($id_objet) AND !strlen($id_objet))) |
|||
return array("0=1"); // securite
|
|||
|
|||
$not=""; |
|||
if (is_array($id_source) AND reset($id_source)=="NOT"){ |
|||
$not = array_shift($id_source); |
|||
$id_source = reset($id_source); |
|||
} |
|||
|
|||
$where = $cond; |
|||
|
|||
if ($id_source!=='*') |
|||
$where[] = (is_array($id_source)?sql_in(addslashes($primary),array_map('intval',$id_source),$not):addslashes($primary) . ($not?"<>":"=") . intval($id_source)); |
|||
elseif ($not) |
|||
$where[] = "0=1"; // idiot mais quand meme
|
|||
|
|||
$not=""; |
|||
if (is_array($id_objet) AND reset($id_objet)=="NOT"){ |
|||
$not = array_shift($id_objet); |
|||
$id_objet = reset($id_objet); |
|||
} |
|||
|
|||
if ($objet!=='*') |
|||
$where[] = "objet=".sql_quote($objet); |
|||
if ($id_objet!=='*') |
|||
$where[] = (is_array($id_objet)?sql_in('id_objet',array_map('intval',$id_objet),$not):"id_objet" . ($not?"<>":"=") . intval($id_objet)); |
|||
elseif ($not) |
|||
$where[] = "0=1"; // idiot mais quand meme
|
|||
|
|||
return $where; |
|||
} |
|||
|
|||
/** |
|||
* Sous fonction suppression |
|||
* qui traite les liens pour un objet source dont la clé primaire |
|||
* et la table de lien sont fournies |
|||
* |
|||
* $objets et de la forme |
|||
* array($objet=>$id_objets,...) |
|||
* un * pour $id,$objet,$id_objets permet de traiter par lot |
|||
* |
|||
* On supprime tous les liens entre les objets indiqués par défaut, |
|||
* sauf s'il y a des rôles déclarés entre ces 2 objets, auquel cas on ne |
|||
* supprime que les liaisons avec le role déclaré par défaut si rien n'est |
|||
* précisé dans $cond. Il faut alors passer $cond=array('role'=>'*') pour |
|||
* supprimer tous les roles, ou array('role'=>'un_role') pour un role précis. |
|||
* |
|||
* @internal |
|||
* @param string $objet_source |
|||
* @param string $primary |
|||
* @param string $table_lien |
|||
* @param int $id |
|||
* @param array $objets |
|||
* @param array|null $cond |
|||
* Conditions where par défaut. |
|||
* Un cas particulier est géré lorsque l'index 'role' est présent (ou absent) |
|||
* @return bool|int |
|||
*/ |
|||
function lien_delete($objet_source,$primary,$table_lien,$id,$objets,$cond=null){ |
|||
|
|||
$retire = array(); |
|||
$dels = 0; |
|||
$echec = false; |
|||
if (is_null($cond)) $cond = array(); |
|||
|
|||
foreach($objets as $objet => $id_objets){ |
|||
$objet = ($objet=='*')?$objet:objet_type($objet); # securite
|
|||
if (!is_array($id_objets) OR reset($id_objets)=="NOT") $id_objets = array($id_objets); |
|||
foreach($id_objets as $id_objet) { |
|||
list($cond, $colonne_role, $role) = roles_creer_condition_role($objet_source, $objet, $cond); |
|||
// id_objet peut valoir '*'
|
|||
$where = lien_where($primary, $id, $objet, $id_objet, $cond); |
|||
|
|||
// lire les liens existants pour propager la date de modif
|
|||
$select = "$primary,id_objet,objet"; |
|||
if ($colonne_role) $select .= ",$colonne_role"; |
|||
$liens = sql_allfetsel($select,$table_lien,$where); |
|||
|
|||
// iterer sur les liens pour permettre aux plugins de gerer
|
|||
foreach($liens as $l) { |
|||
|
|||
$args = array( |
|||
'table_lien' => $table_lien, |
|||
'objet_source' => $objet_source, |
|||
'id_objet_source' => $l[$primary], |
|||
'objet' => $l['objet'], |
|||
'id_objet' => $l['id_objet'], |
|||
'colonne_role' => $colonne_role, |
|||
'role' => ($colonne_role ? $l[$colonne_role] : ''), |
|||
'action'=>'delete', |
|||
); |
|||
|
|||
// Envoyer aux plugins
|
|||
$id_o = pipeline('pre_edition_lien', |
|||
array( |
|||
'args' => $args, |
|||
'data' => $l['id_objet'] |
|||
) |
|||
); |
|||
$args['id_objet'] = $id_o; |
|||
|
|||
if ($id_o=intval($l['id_objet'])) { |
|||
$where = lien_where($primary, $l[$primary], $l['objet'], $id_o, $cond); |
|||
$e = sql_delete($table_lien, $where); |
|||
if ($e!==false){ |
|||
$dels+=$e; |
|||
lien_propage_date_modif($l['objet'],$id_o); |
|||
lien_propage_date_modif($objet_source,$l[$primary]); |
|||
} |
|||
else |
|||
$echec = true; |
|||
$retire[] = array( |
|||
'source' => array($objet_source=>$l[$primary]), |
|||
'lien' => array($l['objet']=>$id_o), |
|||
'type' => $l['objet'], |
|||
'role' => ($colonne_role ? $l[$colonne_role] : ''), |
|||
'id' => $id_o |
|||
); |
|||
// Envoyer aux plugins
|
|||
pipeline('post_edition_lien', |
|||
array( |
|||
'args' => $args, |
|||
'data' => $id_o |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
pipeline('trig_supprimer_objets_lies',$retire); |
|||
|
|||
return ($echec?false:$dels); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Sous fonction optimisation |
|||
* qui nettoie les liens morts (vers un objet inexistant) |
|||
* pour un objet source dont la clé primaire |
|||
* et la table de lien sont fournies |
|||
* |
|||
* $objets et de la forme |
|||
* array($objet=>$id_objets,...) |
|||
* un * pour $id,$objet,$id_objets permet de traiter par lot |
|||
* |
|||
* @internal |
|||
* @param string $objet_source |
|||
* @param string $primary |
|||
* @param string $table_lien |
|||
* @param int $id |
|||
* @param array $objets |
|||
* @return bool|int |
|||
*/ |
|||
function lien_optimise($objet_source,$primary,$table_lien,$id,$objets){ |
|||
include_spip('genie/optimiser'); |
|||
$echec = false; |
|||
$dels = 0; |
|||
foreach($objets as $objet => $id_objets){ |
|||
$objet = ($objet=='*')?$objet:objet_type($objet); # securite
|
|||
if (!is_array($id_objets) OR reset($id_objets)=="NOT") $id_objets = array($id_objets); |
|||
foreach($id_objets as $id_objet) { |
|||
$where = lien_where($primary, $id, $objet, $id_objet); |
|||
# les liens vers un objet inexistant
|
|||
$r = sql_select("DISTINCT objet",$table_lien,$where); |
|||
while ($t = sql_fetch($r)){ |
|||
$type = $t['objet']; |
|||
$spip_table_objet = table_objet_sql($type); |
|||
$id_table_objet = id_table_objet($type); |
|||
$res = sql_select("L.$primary AS id,L.id_objet", |
|||
// la condition de jointure inclue L.objet='xxx' pour ne joindre que les bonnes lignes
|
|||
// du coups toutes les lignes avec un autre objet ont un id_xxx=NULL puisque LEFT JOIN
|
|||
// il faut les eliminier en repetant la condition dans le where L.objet='xxx'
|
|||
"$table_lien AS L
|
|||
LEFT JOIN $spip_table_objet AS O |
|||
ON (O.$id_table_objet=L.id_objet AND L.objet=".sql_quote($type).")",
|
|||
"L.objet=".sql_quote($type)." AND O.$id_table_objet IS NULL"); |
|||
// sur une cle primaire composee, pas d'autres solutions que de virer un a un
|
|||
while ($row = sql_fetch($res)){ |
|||
$e = sql_delete($table_lien, array("$primary=".$row['id'],"id_objet=".$row['id_objet'],"objet=".sql_quote($type))); |
|||
if ($e!=false){ |
|||
$dels+=$e; |
|||
spip_log("Entree ".$row['id']."/".$row['id_objet']."/$type supprimee dans la table $table_lien", _LOG_INFO_IMPORTANTE); |
|||
} |
|||
} |
|||
} |
|||
|
|||
# les liens depuis un objet inexistant
|
|||
$table_source = table_objet_sql($objet_source); |
|||
// filtrer selon $id, $objet, $id_objet eventuellement fournis
|
|||
// (en general '*' pour chaque)
|
|||
$where = lien_where("L.$primary", $id, $objet, $id_objet); |
|||
$where[] = "O.$primary IS NULL"; |
|||
$res = sql_select("L.$primary AS id", |
|||
"$table_lien AS L LEFT JOIN $table_source AS O ON L.$primary=O.$primary", |
|||
$where); |
|||
$dels+= optimiser_sansref($table_lien, $primary, $res); |
|||
} |
|||
} |
|||
return ($echec?false:$dels); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Sous fonction qualification |
|||
* qui traite les liens pour un objet source dont la clé primaire |
|||
* et la table de lien sont fournies |
|||
* |
|||
* $objets et de la forme |
|||
* array($objet=>$id_objets,...) |
|||
* un * pour $id,$objet,$id_objets permet de traiter par lot |
|||
* |
|||
* exemple : |
|||
* $qualif = array('vu'=>'oui'); |
|||
* |
|||
* @internal |
|||
* @param string $objet_source Objet source de l'insertion (celui qui a la table de liaison) |
|||
* @param string $primary Nom de la clé primaire de cet objet |
|||
* @param string $table_lien Nom de la table de lien de cet objet |
|||
* @param int $id Identifiant de l'objet sur lesquels on va insérer des liaisons |
|||
* @param array $objets Liste des liaisons à faire, de la forme array($objet=>$id_objets) |
|||
* @param array $qualif |
|||
* Liste des qualifications à appliquer. |
|||
* |
|||
* Si l'objet dispose d'un champ rôle, on extrait des qualifications |
|||
* le rôle s'il est présent, sinon on applique les qualifications |
|||
* sur le rôle par défaut. |
|||
* @return bool|int |
|||
* Nombre de modifications faites, false si échec. |
|||
*/ |
|||
function lien_set($objet_source,$primary,$table_lien,$id,$objets,$qualif){ |
|||
$echec = null; |
|||
$ok = 0; |
|||
if (!$qualif) |
|||
return false; |
|||
// nettoyer qualif qui peut venir directement d'un objet_trouver_lien :
|
|||
unset($qualif[$primary]); |
|||
unset($qualif[$objet_source]); |
|||
if (isset($qualif['objet'])) { |
|||
unset($qualif[$qualif['objet']]); |
|||
} |
|||
unset($qualif['objet']); |
|||
unset($qualif['id_objet']); |
|||
foreach($objets as $objet => $id_objets) { |
|||
|
|||
// role, colonne, where par défaut
|
|||
list($role, $colonne_role, $cond) = |
|||
roles_trouver_dans_qualif($objet_source, $objet, $qualif); |
|||
|
|||
$objet = ($objet=='*')?$objet:objet_type($objet); # securite
|
|||
if (!is_array($id_objets) OR reset($id_objets)=="NOT") $id_objets = array($id_objets); |
|||
foreach($id_objets as $id_objet) { |
|||
|
|||
$args = array( |
|||
'table_lien' => $table_lien, |
|||
'objet_source' => $objet_source, |
|||
'id_objet_source' => $id, |
|||
'objet' => $objet, |
|||
'id_objet' => $id_objet, |
|||
'role' => $role, |
|||
'colonne_role' => $colonne_role, |
|||
'action' => 'modifier', |
|||
); |
|||
|
|||
// Envoyer aux plugins
|
|||
$id_objet = pipeline('pre_edition_lien', |
|||
array( |
|||
'args' => $args, |
|||
'data' => $id_objet, |
|||
) |
|||
); |
|||
$args['id_objet'] = $id_objet; |
|||
|
|||
$where = lien_where($primary, $id, $objet, $id_objet, $cond); |
|||
$e = sql_updateq($table_lien,$qualif,$where); |
|||
|
|||
if ($e===false) { |
|||
$echec = true; |
|||
} |
|||
else { |
|||
// Envoyer aux plugins
|
|||
pipeline('post_edition_lien', |
|||
array( |
|||
'args' => $args, |
|||
'data' => $id_objet |
|||
) |
|||
); |
|||
$ok++; |
|||
} |
|||
} |
|||
} |
|||
return ($echec?false:$ok); |
|||
} |
|||
|
|||
/** |
|||
* Sous fonction trouver |
|||
* qui cherche les liens pour un objet source dont la clé primaire |
|||
* et la table de lien sont fournies |
|||
* |
|||
* $objets et de la forme |
|||
* array($objet=>$id_objets,...) |
|||
* un * pour $id,$objet,$id_objets permet de traiter par lot |
|||
* |
|||
* Le tableau de condition peut avoir un index 'role' indiquant de |
|||
* chercher un rôle précis, ou * pour tous les roles (alors équivalent |
|||
* à l'absence de l'index) |
|||
* |
|||
* @internal |
|||
* @param string $objet_source |
|||
* @param string $primary |
|||
* @param string $table_lien |
|||
* @param int $id |
|||
* @param array $objets |
|||
* @param array|null $cond |
|||
* Condition du where par défaut |
|||
* |
|||
* On peut passer un index 'role' pour sélectionner uniquement |
|||
* le role défini dedans (et '*' pour tous les rôles). |
|||
* @return array |
|||
*/ |
|||
function lien_find($objet_source,$primary,$table_lien,$id,$objets,$cond=null){ |
|||
$trouve = array(); |
|||
foreach($objets as $objet => $id_objets){ |
|||
$objet = ($objet=='*')?$objet:objet_type($objet); # securite
|
|||
// gerer les roles s'il y en a dans $cond
|
|||
list($cond) = roles_creer_condition_role($objet_source, $objet, $cond, true); |
|||
// lien_where prend en charge les $id_objets sous forme int ou array
|
|||
$where = lien_where($primary, $id, $objet, $id_objets, $cond); |
|||
$liens = sql_allfetsel('*',$table_lien,$where); |
|||
// ajouter les entrees objet_source et objet cible par convenance
|
|||
foreach($liens as $l) { |
|||
$l[$objet_source] = $l[$primary]; |
|||
$l[$objet] = $l['id_objet']; |
|||
$trouve[] = $l; |
|||
} |
|||
} |
|||
return $trouve; |
|||
} |
|||
|
|||
/** |
|||
* Propager la date_modif sur les objets dont un lien a été modifié |
|||
* |
|||
* @internal |
|||
* @param string $objet |
|||
* @param array|int $ids |
|||
*/ |
|||
function lien_propage_date_modif($objet,$ids){ |
|||
static $done = array(); |
|||
$hash = md5($objet . serialize($ids)); |
|||
|
|||
// sql_updateq, peut être un rien lent.
|
|||
// On évite de l'appeler 2 fois sur les mêmes choses
|
|||
if (isset($done[$hash])) { |
|||
return; |
|||
} |
|||
|
|||
$trouver_table = charger_fonction('trouver_table','base'); |
|||
|
|||
$table = table_objet_sql($objet); |
|||
if ($desc = $trouver_table($table) |
|||
AND isset($desc['field']['date_modif'])){ |
|||
$primary = id_table_objet($objet); |
|||
$where = (is_array($ids)?sql_in($primary, array_map('intval',$ids)):"$primary=".intval($ids)); |
|||
sql_updateq($table, array('date_modif'=>date('Y-m-d H:i:s')), $where); |
|||
} |
|||
|
|||
$done[$hash] = true; |
|||
} |
|||
?>
|
@ -1,435 +0,0 @@ |
|||
<?php |
|||
/***************************************************************************\ |
|||
* SPIP, Systeme de publication pour l'internet * |
|||
* * |
|||
* Copyright (c) 2001-2014 * |
|||
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * |
|||
* * |
|||
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. * |
|||
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * |
|||
* \***************************************************************************/ |
|||
|
|||
/** |
|||
* Gestion du formulaire d'édition de liens |
|||
* |
|||
* @package SPIP\Core\Formulaires |
|||
**/ |
|||
if (!defined('_ECRIRE_INC_VERSION')) return; |
|||
|
|||
|
|||
/** |
|||
* Retrouve la source et l'objet de la liaison |
|||
* |
|||
* À partir des 3 premiers paramètres transmis au formulaire, |
|||
* la fonction retrouve : |
|||
* - l'objet dont on utilise sa table de liaison (table_source) |
|||
* - l'objet et id_objet sur qui on lie des éléments (objet, id_objet) |
|||
* - l'objet que l'on veut lier dessus (objet_lien) |
|||
* |
|||
* @param string $a |
|||
* @param string|int $b |
|||
* @param int|string $c |
|||
* @return array |
|||
* ($table_source,$objet,$id_objet,$objet_lien) |
|||
*/ |
|||
function determine_source_lien_objet($a, $b, $c){ |
|||
$table_source = $objet_lien = $objet = $id_objet = null; |
|||
// auteurs, article, 23 :
|
|||
// associer des auteurs à l'article 23, sur la table pivot spip_auteurs_liens
|
|||
if (is_numeric($c) AND !is_numeric($b)){ |
|||
$table_source = table_objet($a); |
|||
$objet_lien = objet_type($a); |
|||
$objet = objet_type($b); |
|||
$id_objet = $c; |
|||
} |
|||
// article, 23, auteurs
|
|||
// associer des auteurs à l'article 23, sur la table pivot spip_articles_liens
|
|||
if (is_numeric($b) AND !is_numeric($c)){ |
|||
$table_source = table_objet($c); |
|||
$objet_lien = objet_type($a); |
|||
$objet = objet_type($a); |
|||
$id_objet = $b; |
|||
} |
|||
|
|||
return array($table_source, $objet, $id_objet, $objet_lien); |
|||
} |
|||
|
|||
/** |
|||
* Chargement du formulaire d'édition de liens |
|||
* |
|||
* #FORMULAIRE_EDITER_LIENS{auteurs,article,23}
|
|||
* pour associer des auteurs à l'article 23, sur la table pivot spip_auteurs_liens |
|||
* #FORMULAIRE_EDITER_LIENS{article,23,auteurs}
|
|||
* pour associer des auteurs à l'article 23, sur la table pivot spip_articles_liens |
|||
* #FORMULAIRE_EDITER_LIENS{articles,auteur,12}
|
|||
* pour associer des articles à l'auteur 12, sur la table pivot spip_articles_liens |
|||
* #FORMULAIRE_EDITER_LIENS{auteur,12,articles}
|
|||
* pour associer des articles à l'auteur 12, sur la table pivot spip_auteurs_liens |
|||
* |
|||
* @param string $a |
|||
* @param string|int $b |
|||
* @param int|string $c |
|||
* @param array|bool $options |
|||
* - Si array, tableau d'options |
|||
* - Si bool : valeur de l'option 'editable' uniquement |
|||
* |
|||
* @return array |
|||
*/ |
|||
function formulaires_editer_liens_charger_dist($a, $b, $c, $options = array()){ |
|||
|
|||
// compat avec ancienne signature ou le 4eme argument est $editable
|
|||
if (!is_array($options)){ |
|||
$options = array('editable' => $options); |
|||
} elseif (!isset($options['editable'])) { |
|||
$options['editable'] = true; |
|||
} |
|||
|
|||
$editable = $options['editable']; |
|||
|
|||
list($table_source, $objet, $id_objet, $objet_lien) = determine_source_lien_objet($a, $b, $c); |
|||
if (!$table_source OR !$objet OR !$objet_lien OR !$id_objet) |
|||
return false; |
|||
|
|||
$objet_source = objet_type($table_source); |
|||
$table_sql_source = table_objet_sql($objet_source); |
|||
|
|||
// verifier existence de la table xxx_liens
|
|||
include_spip('action/editer_liens'); |
|||
if (!objet_associable($objet_lien)) |
|||
return false; |
|||
|
|||
// L'éditabilité :) est définie par un test permanent (par exemple "associermots") ET le 4ème argument
|
|||
include_spip('inc/autoriser'); |
|||
$editable = ($editable and autoriser('associer' . $table_source, $objet, $id_objet) and autoriser('modifier', $objet, $id_objet)); |
|||
|
|||
if (!$editable AND !count(objet_trouver_liens(array($objet_lien => '*'), array(($objet_lien==$objet_source ? $objet : $objet_source) => '*')))) |
|||
return false; |
|||
|
|||
// squelettes de vue et de d'association
|
|||
// ils sont différents si des rôles sont définis.
|
|||
$skel_vue = $table_source . "_lies"; |
|||
$skel_ajout = $table_source . "_associer"; |
|||
|
|||
// description des roles
|
|||
include_spip('inc/roles'); |
|||
if ($roles = roles_presents($objet_source, $objet)){ |
|||
// on demande de nouveaux squelettes en conséquence
|
|||
$skel_vue = $table_source . "_roles_lies"; |
|||
$skel_ajout = $table_source . "_roles_associer"; |
|||
} |
|||
|
|||
$valeurs = array( |
|||
'id' => "$table_source-$objet-$id_objet-$objet_lien", // identifiant unique pour les id du form
|
|||
'_vue_liee' => $skel_vue, |
|||
'_vue_ajout' => $skel_ajout, |
|||
'_objet_lien' => $objet_lien, |
|||
'id_lien_ajoute' => _request('id_lien_ajoute'), |
|||
'objet' => $objet, |
|||
'id_objet' => $id_objet, |
|||
'objet_source' => $objet_source, |
|||
'table_source' => $table_source, |
|||
'recherche' => '', |
|||
'visible' => 0, |
|||
'ajouter_lien' => '', |
|||
'supprimer_lien' => '', |
|||
'qualifier_lien' => '', |
|||
'_roles' => $roles, # description des roles
|
|||
'_oups' => _request('_oups'), |
|||
'editable' => $editable, |
|||
); |
|||
|
|||
// les options non definies dans $valeurs sont passees telles quelles au formulaire html
|
|||
$valeurs = array_merge($options,$valeurs); |
|||
|
|||
return $valeurs; |
|||
} |
|||
|
|||
/** |
|||
* Traiter le post des informations d'édition de liens |
|||
* |
|||
* Les formulaires peuvent poster dans quatre variables |
|||
* - ajouter_lien et supprimer_lien |
|||
* - remplacer_lien |
|||
* - qualifier_lien |
|||
* |
|||
* Les deux premières peuvent être de trois formes différentes : |
|||
* ajouter_lien[]="objet1-id1-objet2-id2" |
|||
* ajouter_lien[objet1-id1-objet2-id2]="nimportequoi" |
|||
* ajouter_lien['clenonnumerique']="objet1-id1-objet2-id2" |
|||
* Dans ce dernier cas, la valeur ne sera prise en compte |
|||
* que si _request('clenonnumerique') est vrai (submit associé a l'input) |
|||
* |
|||
* remplacer_lien doit être de la forme |
|||
* remplacer_lien[objet1-id1-objet2-id2]="objet3-id3-objet2-id2" |
|||
* ou objet1-id1 est celui qu'on enleve et objet3-id3 celui qu'on ajoute |
|||
* |
|||
* qualifier_lien doit être de la forme, et sert en complément de ajouter_lien |
|||
* qualifier_lien[objet1-id1-objet2-id2][role] = array("role1", "autre_role") |
|||
* qualifier_lien[objet1-id1-objet2-id2][valeur] = array("truc", "chose") |
|||
* produira 2 liens chacun avec array("role"=>"role1","valeur"=>"truc") et array("role"=>"autre_role","valeur"=>"chose") |
|||
* |
|||
* @param string $a |
|||
* @param string|int $b |
|||
* @param int|string $c |
|||
* @param array|bool $options |
|||
* - Si array, tableau d'options |
|||
* - Si bool : valeur de l'option 'editable' uniquement |
|||
* |
|||
* @return array |
|||
*/ |
|||
function formulaires_editer_liens_traiter_dist($a, $b, $c, $options = array()){ |
|||
// compat avec ancienne signature ou le 4eme argument est $editable
|
|||
if (!is_array($options)){ |
|||
$options = array('editable' => $options); |
|||
} elseif (!isset($options['editable'])) { |
|||
$options['editable'] = true; |
|||
} |
|||
|
|||
$editable = $options['editable']; |
|||
|
|||
$res = array('editable' => $editable ? true : false); |
|||
list($table_source, $objet, $id_objet, $objet_lien) = determine_source_lien_objet($a, $b, $c); |
|||
if (!$table_source OR !$objet OR !$objet_lien) |
|||
return $res; |
|||
|
|||
|
|||
if (_request('tout_voir')) |
|||
set_request('recherche', ''); |
|||
|
|||
include_spip('inc/autoriser'); |
|||
if (autoriser('modifier', $objet, $id_objet)){ |
|||
// annuler les suppressions du coup d'avant !
|
|||
if (_request('annuler_oups') |
|||
AND $oups = _request('_oups') |
|||
AND $oups = unserialize($oups) |
|||
){ |
|||
if ($oups_objets = charger_fonction("editer_liens_oups_{$table_source}_{$objet}_{$objet_lien}", "action", true)){ |
|||
$oups_objets($oups); |
|||
} |
|||
else { |
|||
$objet_source = objet_type($table_source); |
|||
include_spip('action/editer_liens'); |
|||
foreach ($oups as $oup) { |
|||
if ($objet_lien==$objet_source) |
|||
objet_associer(array($objet_source => $oup[$objet_source]), array($objet => $oup[$objet]), $oup); |
|||
else |
|||
objet_associer(array($objet => $oup[$objet]), array($objet_source => $oup[$objet_source]), $oup); |
|||
} |
|||
} |
|||
# oups ne persiste que pour la derniere action, si suppression
|
|||
set_request('_oups'); |
|||
} |
|||
|
|||
$supprimer = _request('supprimer_lien'); |
|||
$ajouter = _request('ajouter_lien'); |
|||
|
|||
// il est possible de preciser dans une seule variable un remplacement :
|
|||
// remplacer_lien[old][new]
|
|||
if ($remplacer = _request('remplacer_lien')){ |
|||
foreach ($remplacer as $k => $v){ |
|||
if ($old = lien_verifier_action($k, '')){ |
|||
foreach (is_array($v) ? $v : array($v) as $kn => $vn) |
|||
if ($new = lien_verifier_action($kn, $vn)){ |
|||
$supprimer[$old] = 'x'; |
|||
$ajouter[$new] = '+'; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
if ($supprimer){ |
|||
if ($supprimer_objets = charger_fonction("editer_liens_supprimer_{$table_source}_{$objet}_{$objet_lien}", "action", true)){ |
|||
$oups = $supprimer_objets($supprimer); |
|||
} |
|||
else { |
|||
include_spip('action/editer_liens'); |
|||
$oups = array(); |
|||
|
|||
foreach ($supprimer as $k => $v){ |
|||
if ($lien = lien_verifier_action($k, $v)){ |
|||
$lien = explode("-", $lien); |
|||
list($objet_source, $ids, $objet_lie, $idl, $role) = $lien; |
|||
// appliquer une condition sur le rôle si défini ('*' pour tous les roles)
|
|||
$cond = (!is_null($role) ? array('role' => $role) : array()); |
|||
if ($objet_lien==$objet_source){ |
|||
$oups = array_merge($oups, objet_trouver_liens(array($objet_source => $ids), array($objet_lie => $idl), $cond)); |
|||
objet_dissocier(array($objet_source => $ids), array($objet_lie => $idl), $cond); |
|||
} else { |
|||
$oups = array_merge($oups, objet_trouver_liens(array($objet_lie => $idl), array($objet_source => $ids), $cond)); |
|||
objet_dissocier(array($objet_lie => $idl), array($objet_source => $ids), $cond); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
set_request('_oups', $oups ? serialize($oups) : null); |
|||
} |
|||
|
|||
if ($ajouter){ |
|||
if ($ajouter_objets = charger_fonction("editer_liens_ajouter_{$table_source}_{$objet}_{$objet_lien}", "action", true)){ |
|||
$ajout_ok = $ajouter_objets($ajouter); |
|||
} |
|||
else { |
|||
$ajout_ok = false; |
|||
include_spip('action/editer_liens'); |
|||
foreach ($ajouter as $k => $v){ |
|||
if ($lien = lien_verifier_action($k, $v)){ |
|||
$ajout_ok = true; |
|||
list($objet1, $ids, $objet2, $idl) = explode("-", $lien); |
|||
$qualifs = lien_retrouver_qualif($objet_lien, $lien); |
|||
if ($objet_lien==$objet1){ |
|||
lien_ajouter_liaisons($objet1, $ids, $objet2, $idl, $qualifs); |
|||
} else { |
|||
lien_ajouter_liaisons($objet2, $idl, $objet1, $ids, $qualifs); |
|||
} |
|||
set_request('id_lien_ajoute', $ids); |
|||
} |
|||
} |
|||
} |
|||
# oups ne persiste que pour la derniere action, si suppression
|
|||
# une suppression suivie d'un ajout dans le meme hit est un remplacement
|
|||
# non annulable !
|
|||
if ($ajout_ok) |
|||
set_request('_oups'); |
|||
} |
|||
} |
|||
|
|||
|
|||
return $res; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Retrouver l'action de liaision demandée |
|||
* |
|||
* Les formulaires envoient une action dans un tableau ajouter_lien |
|||
* ou supprimer_lien |
|||
* |
|||
* L'action est de la forme : objet1-id1-objet2-id2 |
|||
* ou de la forme : objet1-id1-objet2-id2-role |
|||
* |
|||
* L'action peut-être indiquée dans la clé ou dans la valeur. |
|||
* Si elle est indiquee dans la valeur et que la clé est non numérique, |
|||
* on ne la prend en compte que si un submit avec la clé a été envoyé |
|||
* |
|||
* @internal |
|||
* @param string $k Clé du tableau |
|||
* @param string $v Valeur du tableau |
|||
* @return string Action demandée si trouvée, sinon '' |
|||
*/ |
|||
function lien_verifier_action($k, $v){ |
|||
$action = ''; |
|||
if (preg_match(",^\w+-[\w*]+-[\w*]+-[\w*]+(-[\w*])?,", $k)) |
|||
$action = $k; |
|||
if (preg_match(",^\w+-[\w*]+-[\w*]+-[\w*]+(-[\w*])?,", $v)){ |
|||
if (is_numeric($k)) |
|||
$action = $v; |
|||
if (_request($k)) |
|||
$action = $v; |
|||
} |
|||
// ajout un role null fictif (plus pratique) si pas défini
|
|||
if ($action and count(explode("-", $action))==4){ |
|||
$action .= '-'; |
|||
} |
|||
return $action; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Retrouve le ou les qualificatifs postés avec une liaison demandée |
|||
* |
|||
* @internal |
|||
* @param string $objet_lien |
|||
* objet qui porte le lien |
|||
* @param string $lien |
|||
* Action du lien |
|||
* @return array |
|||
* Liste des qualifs pour chaque lien. Tableau vide s'il n'y en a pas. |
|||
**/ |
|||
function lien_retrouver_qualif($objet_lien, $lien){ |
|||
// un role est défini dans la liaison
|
|||
$defs = explode('-', $lien); |
|||
list($objet1, , $objet2, , $role) = $defs; |
|||
if ($objet_lien==$objet1){ |
|||
$colonne_role = roles_colonne($objet1, $objet2); |
|||
} |
|||
else { |
|||
$colonne_role = roles_colonne($objet2, $objet1); |
|||
} |
|||
|
|||
// cas ou le role est defini en 5e argument de l'action sur le lien (suppression, ajout rapide sans autre attribut)
|
|||
if ($role) { |
|||
return array( |
|||
// un seul lien avec ce role
|
|||
array($colonne_role=>$role) |
|||
); |
|||
} |
|||
|
|||
// retrouver les rôles postés pour cette liaison, s'il y en a.
|
|||
$qualifier_lien = _request('qualifier_lien'); |
|||
if (!$qualifier_lien OR !is_array($qualifier_lien)){ |
|||
return array(); |
|||
} |
|||
|
|||
// pas avec l'action complete (incluant le role)
|
|||
$qualif = array(); |
|||
if ((!isset($qualifier_lien[$lien]) OR !$qualif = $qualifier_lien[$lien]) |
|||
AND count($defs)==5){ |
|||
// on tente avec l'action sans le role
|
|||
array_pop($defs); |
|||
$lien = implode('-', $defs); |
|||
if (!isset($qualifier_lien[$lien]) OR !$qualif = $qualifier_lien[$lien]){ |
|||
$qualif = array(); |
|||
} |
|||
} |
|||
|
|||
// $qualif de la forme array(role=>array(...),valeur=>array(...),....)
|
|||
// on le reforme en array(array(role=>..,valeur=>..,..),array(role=>..,valeur=>..,..),...)
|
|||
$qualifs = array(); |
|||
while (count($qualif)){ |
|||
$q = array(); |
|||
foreach($qualif as $att=>$values){ |
|||
if (is_array($values)){ |
|||
$q[$att] = array_shift($qualif[$att]); |
|||
if (!count($qualif[$att])){ |
|||
unset($qualif[$att]); |
|||
} |
|||
} |
|||
else { |
|||
$q[$att] = $values; |
|||
unset($qualif[$att]); |
|||
} |
|||
} |
|||
// pas de rôle vide
|
|||
if (!$colonne_role OR !isset($q[$colonne_role]) OR $q[$colonne_role]) |
|||
$qualifs[] = $q; |
|||
} |
|||
|
|||
return $qualifs; |
|||
} |
|||
|
|||
/** |
|||
* Ajoute les liens demandés en prenant éventuellement en compte le rôle |
|||
* |
|||
* Appelle la fonction objet_associer. L'appelle autant de fois qu'il y |
|||
* a de rôles demandés pour cette liaison. |
|||
* |
|||
* @internal |
|||
* @param string $objet_source Objet source de la liaison (qui a la table de liaison) |
|||
* @param array|string $ids Identifiants pour l'objet source |
|||
* @param string $objet_lien Objet à lier |
|||
* @param array|string $idl Identifiants pour l'objet lié |
|||
* @param array $qualifs |
|||
* @return void |
|||
**/ |
|||
function lien_ajouter_liaisons($objet_source, $ids, $objet_lien, $idl, $qualifs){ |
|||
|
|||
// retrouver la colonne de roles s'il y en a a lier
|
|||
if (is_array($qualifs) and count($qualifs)){ |
|||
foreach ($qualifs as $qualif){ |
|||
objet_associer(array($objet_source => $ids), array($objet_lien => $idl), $qualif); |
|||
} |
|||
} else { |
|||
objet_associer(array($objet_source => $ids), array($objet_lien => $idl)); |
|||
} |
|||
} |
|||
|
@ -1,360 +0,0 @@ |
|||
<?php |
|||
|
|||
/** |
|||
* Plugin Rôles |
|||
* (c) 2012 Marcillaud Matthieu |
|||
* Licence GNU/GPL |
|||
* |
|||
* Gestion des rôles |
|||
* |
|||
* Les rôles sont une qualification précise sur une liaison entre |
|||
* deux objets. Ils doivent être définis dans la déclaration d'un objet |
|||
* pour être utilisés. Ils s'appliquent sur une colonne particulière |
|||
* de la table de liaison, par défaut 'role'. |
|||
* |
|||
* Cette table de liaison, lorsqu'elle a des rôles n'a plus sa clé primaire |
|||
* sur le couple (id_x, objet, id_objet) mais sur (id_x, objet, id_objet, colonne_role) |
|||
* de sorte qu'il peut exister plusieurs liens entre 2 objets, mais avec |
|||
* des rôles différents. Chaque ligne de la table lien correspond alors à |
|||
* un des rôles. |
|||
*/ |
|||
|
|||
if (!defined('_ECRIRE_INC_VERSION')) return; |
|||
|
|||
|
|||
|
|||
/** |
|||
* Vérifie qu'un objet dispose de rôles fonctionnels |
|||
* |
|||
* Retourne une description des rôles si c'est le cas |
|||
* |
|||
* @param string $objet |
|||
* Objet source qui possède la table de liaison |
|||
* @param string $objet_destination |
|||
* Objet sur quoi on veut lier |
|||
* Si défini, le retour ne contient que les roles possibles pour cet objet |
|||
* Sinon retourne tous les roles possibles quelque soit l'objet |
|||
* @return bool|array |
|||
* false si rôles indisponibles on non déclarés |
|||
* array : description des roles applicables dans 3 index : colonne, titres, roles |
|||
**/ |
|||
function roles_presents($objet, $objet_destination='') { |
|||
$desc = lister_tables_objets_sql(table_objet_sql($objet)); |
|||
|
|||
// pas de liste de roles, on sort
|
|||
if (!isset($desc['roles_titres']) OR !($titres = $desc['roles_titres'])) { |
|||
return false; |
|||
} |
|||
|
|||
// on vérifie que la table de liaison existe
|
|||
include_spip('action/editer_liens'); |
|||
if (!$lien = objet_associable($objet)) { |
|||
return false; |
|||
} |
|||
|
|||
// on cherche ensuite si la colonne existe bien dans la table de liaison (par défaut 'role')
|
|||
$colonne = isset($desc['roles_colonne']) ? $desc['roles_colonne'] : 'role'; |
|||
$trouver_table = charger_fonction('trouver_table', 'base'); |
|||
list(,$table_lien) = $lien; |
|||
$desc_lien = $trouver_table($table_lien); |
|||
if (!isset($desc_lien['field'][$colonne])) { |
|||
return false; |
|||
} |
|||
|
|||
// sur quoi peuvent s'appliquer nos rôles
|
|||
if (!$application = $desc['roles_objets']) { |
|||
return false; |
|||
} |
|||
|
|||
// destination presente, on restreint si possible
|
|||
if ($objet_destination) { |
|||
$objet_destination = table_objet($objet_destination); |
|||
|
|||
// pour l'objet
|
|||
if (isset($application[$objet_destination])) { |
|||
$application = $application[$objet_destination]; |
|||
// sinon pour tous les objets
|
|||
} elseif (isset($application['*'])) { |
|||
$application = $application['*']; |
|||
} |
|||
// sinon tant pis
|
|||
else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
// tout est ok
|
|||
return array( |
|||
'titres' => $titres, |
|||
'roles' => $application, |
|||
'colonne' => $colonne |
|||
); |
|||
} |
|||
|
|||
/** |
|||
* Retrouve la colonne de liaison d'un rôle si définie entre 2 objets |
|||
* |
|||
* @param string $objet |
|||
* Objet source qui possède la table de liaison |
|||
* @param string $objet_destination |
|||
* Objet sur quoi on veut lier |
|||
* @return string |
|||
* Nom de la colonne, sinon vide |
|||
**/ |
|||
function roles_colonne($objet, $objet_destination) { |
|||
if ($roles = roles_presents($objet, $objet_destination)) { |
|||
return $roles['colonne']; |
|||
} |
|||
return ''; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Extrait le rôle et la colonne de role d'un tableau de qualification |
|||
* |
|||
* Calcule également une condition where pour ce rôle. |
|||
* |
|||
* Pour un objet pouvant recevoir des roles sur sa liaison avec un autre objet, |
|||
* on retrouve le rôle en question dans le tableau de qualification. |
|||
* Si le rôle n'est pas défini dedans, on prend le rôle par défaut |
|||
* déclaré. |
|||
* |
|||
* @param string $objet Objet source de la liaison |
|||
* @param string $objet_destination Objet de destination de la liaison |
|||
* @param array $qualif tableau de qualifications array(champ => valeur) |
|||
* @return array |
|||
* Liste (role, colonne, (array)condition) si role possible |
|||
* Liste ('', '', array()) sinon. |
|||
**/ |
|||
function roles_trouver_dans_qualif($objet, $objet_destination, $qualif = array()) { |
|||
// si des rôles sont possibles, on les utilise
|
|||
$role = $colonne_role = ''; # role défini
|
|||
// condition du where par defaut
|
|||
$cond = array(); |
|||
if ($roles = roles_presents($objet, $objet_destination)) { |
|||
$colonne_role = $roles['colonne']; |
|||
// qu'il n'est pas défini
|
|||
if (!isset($qualif[$colonne_role]) |
|||
OR !($role = $qualif[$colonne_role])) { |
|||
$role = $roles['roles']['defaut']; |
|||
} |
|||
// where
|
|||
$cond = array("$colonne_role=" . sql_quote($role)); |
|||
} |
|||
|
|||
return array($role, $colonne_role, $cond); |
|||
} |
|||
|
|||
/** |
|||
* Gérer l'ajout dans la condition where du rôle |
|||
* |
|||
* On ajoute la condition uniquement si la liaison entre les 2 objets a une colonne de rôle ! |
|||
* |
|||
* @param string $objet_source Objet source (qui possède la table de liens) |
|||
* @param string $objet Objet de destination |
|||
* @param array $cond |
|||
* Tableau de conditions where |
|||
* qui peut avoir un index spécial 'role' définissant le role à appliquer |
|||
* ou valant '*' pour tous les roles. |
|||
* @param bool $tous_si_absent |
|||
* true pour ne pas appliquer une condition sur le rôle s'il n'est pas indiqué |
|||
* dans la liste des conditions entrantes. Autrement dit, on n'applique |
|||
* pas de rôle par défaut si aucun n'est défini. |
|||
* @return array |
|||
* Liste (Tableau de conditions where complété du role, Colonne du role, role utilisé) |
|||
**/ |
|||
function roles_creer_condition_role($objet_source, $objet, $cond, $tous_si_absent = false) { |
|||
// role par défaut, colonne
|
|||
list($role_defaut, $colonne_role) = roles_trouver_dans_qualif($objet_source, $objet); |
|||
|
|||
// chercher d'eventuels rôles transmis
|
|||
$role = (isset($cond['role']) ? $cond['role'] : ($tous_si_absent ? '*' : $role_defaut)); |
|||
unset($cond['role']); // cette condition est particuliere...
|
|||
|
|||
if ($colonne_role) { |
|||
// on ajoute la condition du role aux autres conditions.
|
|||
if ($role != '*') { |
|||
$cond[] = "$colonne_role=" .sql_quote($role); |
|||
} |
|||
} |
|||
return array($cond, $colonne_role, $role); |
|||
} |
|||
|
|||
/** |
|||
* Liste des identifiants dont on ne peut ajouter de rôle |
|||
* |
|||
* Lister les id objet_source associés à l'objet id_objet |
|||
* via la table de lien objet_lien, et détermine dans cette liste |
|||
* lesquels ont les rôles complets, c'est à dire qu'on ne peut leur |
|||
* affecteur d'autres rôles parmi ceux qui existe pour cette liaison. |
|||
* |
|||
* @see lister_objets_lies() |
|||
* |
|||
* @param string $objet_source Objet dont on veut récupérer la liste des identifiants |
|||
* @param string $objet Objet sur lequel est liée la source |
|||
* @param int $id_objet Identifiant d'objet sur lequel est liée la source |
|||
* @param string $objet_lien Objet dont on utilise la table de liaison (c'est forcément soit $objet_source, soit $objet) |
|||
* @return array Liste des identifiants |
|||
*/ |
|||
function roles_complets($objet_source, $objet, $id_objet, $objet_lien) { |
|||
|
|||
$presents = roles_presents_liaisons($objet_source, $objet, $id_objet, $objet_lien); |
|||
// pas de roles sur ces objets => la liste par defaut, comme sans role
|
|||
if ($presents === false) { |
|||
return lister_objets_lies($objet_source, $objet, $id_objet, $objet_lien); |
|||
} |
|||
|
|||
// types de roles possibles
|
|||
$roles_possibles = $presents['roles']['roles']['choix']; |
|||
// couples id / roles
|
|||
$ids = $presents['ids']; |
|||
|
|||
// pour chaque groupe, on fait le diff entre tous les roles possibles
|
|||
// et les roles attribués à l'élément : s'il en reste, c'est que l'élément
|
|||
// n'est pas complet
|
|||
$complets = array(); |
|||
foreach ($ids as $id => $roles_presents) { |
|||
if (!array_diff($roles_possibles, $roles_presents)) { |
|||
$complets[] = $id; |
|||
} |
|||
} |
|||
|
|||
return $complets; |
|||
} |
|||
|
|||
|
|||
|
|||
/** |
|||
* Liste les roles attribués entre 2 objets/id_objet sur une table de liaison donnée |
|||
* |
|||
* @param string $id_objet_source Identifiant de l'objet qu'on lie |
|||
* @param string $objet_source Objet qu'on lie |
|||
* @param string $objet Objet sur lequel est liée la source |
|||
* @param int $id_objet Identifiant d'objet sur lequel est liée la source |
|||
* @param string $objet_lien Objet dont on utilise la table de liaison (c'est forcément soit $objet_source, soit $objet) |
|||
* @return array Liste des roles |
|||
*/ |
|||
function roles_presents_sur_id($id_objet_source, $objet_source, $objet, $id_objet, $objet_lien) { |
|||
|
|||
$presents = roles_presents_liaisons($objet_source, $objet, $id_objet, $objet_lien); |
|||
// pas de roles sur ces objets => la liste par defaut, comme sans role
|
|||
if ($presents === false) { |
|||
return array(); |
|||
} |
|||
|
|||
if (!isset($presents['ids'][$id_objet_source])) { |
|||
return array(); |
|||
} |
|||
|
|||
return $presents['ids'][$id_objet_source]; |
|||
} |
|||
|
|||
|
|||
|
|||
/** |
|||
* Lister des rôles présents sur une liaion, pour un objet sur un autre, |
|||
* classés par identifiant de l'objet |
|||
* |
|||
* Lister les id objet_source associés à l'objet id_objet |
|||
* via la table de lien objet_lien, et groupe cette liste |
|||
* par identifiant (la clé) et ses roles attribués (tableau de valeur) |
|||
* |
|||
* On retourne cette liste dans l'index 'ids' et la description des roles |
|||
* pour la liaison dans l'index 'roles' pour éviter le le faire recalculer |
|||
* aux fonctions utilisant celle ci. |
|||
* |
|||
* @param string $objet_source Objet dont on veut récupérer la liste des identifiants |