diff --git a/ecrire/action/editer_liens.php b/ecrire/action/editer_liens.php index 9b4935e4598918e9918e8fc2c704ab9219100f36..f591c4de29b689077e634b83b4b087d15d4f7500 100644 --- a/ecrire/action/editer_liens.php +++ b/ecrire/action/editer_liens.php @@ -14,6 +14,15 @@ * API d'édition de liens * * @package SPIP\Core\Liens\API + * + * 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. + * + * */ if (!defined('_ECRIRE_INC_VERSION')) return; @@ -61,7 +70,7 @@ function objet_associable($objet){ * 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 @@ -152,9 +161,10 @@ function objet_qualifier_liens($objets_source,$objets_lies,$qualif){ * ) * * @api - * @param array $objets_source - * @param array|string $objets_lies + * @param array $objets_source Couples (objets_source => identifiants) (objet qui a la table de lien) + * @param array|string $objets_lies Couples (objets_lies => identifiants) * @return array + * Liste des trouvailles */ function objet_trouver_liens($objets_source,$objets_lies){ return objet_traiter_liaisons('lien_find',$objets_source,$objets_lies); @@ -185,6 +195,7 @@ function objet_optimiser_liens($objets_source,$objets_lies){ } + /** * Dupliquer tous les liens entrant ou sortants d'un objet * vers un autre (meme type d'objet, mais id different) @@ -238,6 +249,7 @@ function objet_dupliquer_liens($objet,$id_source,$id_cible,$types=null,$exclure_ /** * 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 @@ -252,9 +264,18 @@ function objet_dupliquer_liens($objet,$id_source,$id_cible,$types=null,$exclure_ * * @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 - * @param array $set + * 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){ @@ -299,18 +320,17 @@ function objet_traiter_liaisons($operation,$objets_source,$objets_lies, $set = n * $objets et de la forme * array($objet=>$id_objets,...) * - * Retourne le nombre d'insertions realisees + * Retourne le nombre d'insertions réalisées * - * @pipeline appel pre_edition_lien - * @pipeline appel post_edition_lien - * * @internal - * @param string $objet_source - * @param string $primary - * @param sgring $table_lien - * @param int $id - * @param array $objets + * @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 sgring $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) + * * @return bool|int + * Nombre d'insertions faites, false si échec. */ function lien_insert($objet_source,$primary,$table_lien,$id,$objets) { $ins = 0; @@ -319,20 +339,25 @@ function lien_insert($objet_source,$primary,$table_lien,$id,$objets) { if (!is_array($id_objets)) $id_objets = array($id_objets); foreach($id_objets as $id_objet) { $objet = ($objet=='*')?$objet:objet_type($objet); # securite + + $args = array( + 'table_lien' => $table_lien, + 'objet_source' => $objet_source, + 'id_objet_source' => $id, + 'objet' => $objet, + 'id_objet' => $id_objet, + 'action' => 'insert', + ); + // Envoyer aux plugins $id_objet = pipeline('pre_edition_lien', array( - 'args' => array( - 'table_lien' => $table_lien, - 'objet_source' => $objet_source, - 'id_objet_source' => $id, - 'objet' => $objet, - 'id_objet' => $id_objet, - 'action'=>'insert', - ), + 'args' => $args, 'data' => $id_objet ) ); + $args['id_objet'] = $id_objet; + if ($id_objet=intval($id_objet) AND !sql_getfetsel( $primary, @@ -348,14 +373,7 @@ function lien_insert($objet_source,$primary,$table_lien,$id,$objets) { // Envoyer aux plugins pipeline('post_edition_lien', array( - 'args' => array( - 'table_lien' => $table_lien, - 'objet_source' => $objet_source, - 'id_objet_source' => $id, - 'objet' => $objet, - 'id_objet' => $id_objet, - 'action'=>'insert', - ), + 'args' => $args, 'data' => $id_objet ) ); @@ -372,11 +390,11 @@ function lien_insert($objet_source,$primary,$table_lien,$id,$objets) { * Fabriquer la condition where en tenant compte des jokers * * * @internal - * @param string $primary - * @param int|string|array $id_source - * @param string $objet - * @param int|string|array $id_objet - * @return array + * @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é + * @return array Liste des conditions */ function lien_where($primary, $id_source, $objet, $id_objet){ if ((!is_array($id_source) AND !strlen($id_source)) @@ -420,13 +438,10 @@ function lien_where($primary, $id_source, $objet, $id_objet){ * array($objet=>$id_objets,...) * un * pour $id,$objet,$id_objets permet de traiter par lot * - * @pipeline appel pre_edition_lien - * @pipeline appel post_edition_lien - * * @internal * @param string $objet_source * @param string $primary - * @param sgring $table_lien + * @param string $table_lien * @param int $id * @param array $objets * @return bool|int @@ -442,23 +457,30 @@ function lien_delete($objet_source,$primary,$table_lien,$id,$objets){ // id_objet peut valoir '*' $where = lien_where($primary, $id, $objet, $id_objet); // lire les liens existants pour propager la date de modif - $liens = sql_allfetsel("$primary,id_objet,objet",$table_lien,$where); + $select = "$primary,id_objet,objet"; + $liens = sql_allfetsel($select,$table_lien,$where); + // iterer sur les liens pour permettre aux plugins de gerer - foreach($liens as $l){ + 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'], + 'action'=>'delete', + ); + // Envoyer aux plugins $id_o = pipeline('pre_edition_lien', array( - 'args' => array( - 'table_lien' => $table_lien, - 'objet_source' => $objet_source, - 'id_objet_source' => $l[$primary], - 'objet' => $l['objet'], - 'id_objet' => $l['id_objet'], - 'action'=>'delete', - ), + 'args' => $args, 'data' => $l['id_objet'] ) ); + $args['id_objet'] = $id_o; + if ($id_o=intval($id_o)){ $where = lien_where($primary, $l[$primary], $l['objet'], $id_o); $e = sql_delete($table_lien, $where); @@ -469,18 +491,16 @@ function lien_delete($objet_source,$primary,$table_lien,$id,$objets){ } else $echec = true; - $retire[] = array('source'=>array($objet_source=>$l[$primary]),'lien'=>array($l['objet']=>$id_o),'type'=>$l['objet'],'id'=>$id_o); + $retire[] = array( + 'source' => array($objet_source=>$l[$primary]), + 'lien' => array($l['objet']=>$id_o), + 'type' => $l['objet'], + 'id' => $id_o + ); // Envoyer aux plugins pipeline('post_edition_lien', array( - 'args' => array( - 'table_lien' => $table_lien, - 'objet_source' => $objet_source, - 'id_objet_source' => $l[$primary], - 'objet' => $l['objet'], - 'id_objet' => $id_o, - 'action'=>'delete', - ), + 'args' => $args, 'data' => $id_o ) ); @@ -488,6 +508,7 @@ function lien_delete($objet_source,$primary,$table_lien,$id,$objets){ } } } + pipeline('trig_supprimer_objets_lies',$retire); return ($echec?false:$dels); @@ -540,7 +561,7 @@ function lien_optimise($objet_source,$primary,$table_lien,$id,$objets){ $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); + spip_log("Entree ".$row['id']."/".$row['id_objet']."/$type supprimee dans la table $table_lien", _LOG_INFO_IMPORTANTE); } } } @@ -574,13 +595,15 @@ function lien_optimise($objet_source,$primary,$table_lien,$id,$objets){ * $qualif = array('vu'=>'oui'); * * @internal - * @param string $objet_source - * @param string $primary - * @param sgring $table_lien - * @param int $id - * @param array $objets + * @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. * @return bool|int + * Nombre de modifications faites, false si échec. */ function lien_set($objet_source,$primary,$table_lien,$id,$objets,$qualif){ $echec = null; @@ -599,12 +622,41 @@ function lien_set($objet_source,$primary,$table_lien,$id,$objets,$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, + '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); $e = sql_updateq($table_lien,$qualif,$where); - if ($e===false) + + if ($e===false) { $echec = true; - else - $ok++; + } + else { + // Envoyer aux plugins + pipeline('post_edition_lien', + array( + 'args' => $args, + 'data' => $id_objet + ) + ); + $ok++; + } } } return ($echec?false:$ok); @@ -623,7 +675,7 @@ function lien_set($objet_source,$primary,$table_lien,$id,$objets,$qualif){ * @internal * @param string $objet_source * @param string $primary - * @param sgring $table_lien + * @param string $table_lien * @param int $id * @param array $objets * @return array @@ -653,6 +705,15 @@ function lien_find($objet_source,$primary,$table_lien,$id,$objets){ * @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); @@ -662,5 +723,7 @@ function lien_propage_date_modif($objet,$ids){ $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; } ?>