Valider dd48fb36 rédigé par cerdic's avatar cerdic
Parcourir les fichiers
gestion generique du champ rang_lien sur les tables de liens dans l'API editer_liens:
* numerotation automatique a l'insertion si un des lien est deja numerote (par defaut non, donc)
* renumerotation a la suppression d'un lien (si les liens sont numerotes)
* renumerotation quand on modifie le rang_lien d'un lien via objet_qualifier_liens() (sauf quand on met a zero un rang)
* prise en compte de la variable postee ordonner_lien dans le formulaires pour permettre de changer le rang d'un lien
* prise en compte de la variable postee desordonner_liens pour remettre tous les rang a zero

Evolution de la balise #RANG pour afficher le rang du lien quand il est disponible dans la boucle, ou dans le formulaire d'edition des liens
Pas d'interface ni d'utilisation dans le core : l'esprit de SPIP n'etant pas de hierarchiser les auteurs on reste par defaut sans ordre, c'est un plugin de la zone qui implemente ca https://zone.spip.net/trac/spip-zone/browser/_plugins_/rang_auteurs
parent 532a6388
Chargement en cours
Chargement en cours
Chargement en cours
Chargement en cours
+103 −1
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -374,7 +374,7 @@ function lien_insert($objet_source, $primary, $table_lien, $id, $objets, $qualif
			roles_trouver_dans_qualif($objet_source, $objet, $qualif);

		foreach ($id_objets as $id_objet) {
			$objet = ($objet == '*') ? $objet : objet_type($objet); # securite
			$objet = (($objet == '*') ? $objet : objet_type($objet)); # securite

			$insertions = array(
				'id_objet' => $id_objet,
@@ -387,6 +387,21 @@ function lien_insert($objet_source, $primary, $table_lien, $id, $objets, $qualif
					$colonne_role => $role
				);
			}

			if (lien_triables($table_lien)) {
				$where = lien_where($primary, $id, $objet, $id_objet);
				// si il y a deja un lien pour ce couple (avec un autre role?) on reprend le meme rang si non nul
				if (!$rang = intval(sql_getfetsel('rang_lien', $table_lien, $where))) {
					$where = lien_where($primary, '*', $objet, $id_objet);
					$rang = intval(sql_getfetsel('max(rang_lien)', $table_lien, $where));
					// si aucun lien n'a de rang, on en introduit pas, on garde zero
					if ($rang>0) {
						$rang = intval($rang) + 1;
					}
				}
				$insertions['rang_lien'] = $rang;
			}

			$args = array(
				'table_lien' => $table_lien,
				'objet_source' => $objet_source,
@@ -413,6 +428,12 @@ function lien_insert($objet_source, $primary, $table_lien, $id, $objets, $qualif
				and !sql_getfetsel($primary, $table_lien, $where)
			) {

				if (lien_triables($table_lien) and isset($insertions['rang_lien']) and intval($insertions['rang_lien'])) {
					// on decale les liens de rang_lien>=la valeur inseree pour faire la place
					$w = lien_where($primary, '*', $objet, $id_objet, array('rang_lien>='.intval($insertions['rang_lien']),"$primary!=".intval($id)));
					sql_update($table_lien, array('rang_lien'=>'rang_lien+1'), $w);
				}

				$e = sql_insertq($table_lien, $insertions);
				if ($e !== false) {
					$ins++;
@@ -431,10 +452,75 @@ function lien_insert($objet_source, $primary, $table_lien, $id, $objets, $qualif
			}
		}
	}
	// si on a fait des insertions, on reordonne les liens concernes
	if ($ins>0) {
		lien_ordonner($objet_source, $primary, $table_lien, $id, $objets);
	}

	return ($echec ? false : $ins);
}


/**
 * Reordonner les liens sur lesquels on est intervenus
 * @param string $objet_source
 * @param string $primary
 * @param string $table_lien
 * @param int $id
 * @param array|string $objets
 */
function lien_ordonner($objet_source, $primary, $table_lien, $id, $objets) {
	if (!lien_triables($table_lien)) {
		return;
	}

	foreach ($objets as $objet => $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

			$where = lien_where($primary, '*', $objet, $id_objet);
			$liens = sql_allfetsel("$primary, id_objet, objet, rang_lien", $table_lien, $where, $primary,"rang_lien");

			$rangs = array_column($liens, 'rang_lien');
			if (max($rangs)>0 or min($rangs)<0) {
				$rang = 1;
				foreach ($liens as $lien) {
					$where = lien_where($primary, $lien[$primary], $objet, $id_objet, array('rang_lien!='.intval($rang)));
					sql_updateq($table_lien, array('rang_lien' => $rang), $where);
					$rang++;
				}
			}
		}
	}
}


/**
 * Une table de lien est-elle triable ?
 * elle doit disposer d'un champ rang_lien pour cela
 * @param $table_lien
 * @return mixed
 */
function lien_triables($table_lien) {
	static $triables = array();
	if (!isset($triables[$table_lien])) {
		$trouver_table = charger_fonction('trouver_table', 'base');
		$desc = $trouver_table($table_lien);
		if ($desc and isset($desc['field']['rang_lien'])) {
			$triables[$table_lien] = true;
		}
		else {
			$triables[$table_lien] = false;
		}
	}
	return $triables[$table_lien];
}


/**
 * Fabriquer la condition where en tenant compte des jokers *
 *
@@ -591,6 +677,10 @@ function lien_delete($objet_source, $primary, $table_lien, $id, $objets, $cond =
			}
		}
	}
	// si on a supprime des liens, on reordonne les liens concernes
	if ($dels) {
		lien_ordonner($objet_source, $primary, $table_lien, $id, $objets);
	}

	pipeline('trig_supprimer_objets_lies', $retire);

@@ -700,6 +790,7 @@ function lien_optimise($objet_source, $primary, $table_lien, $id, $objets) {
function lien_set($objet_source, $primary, $table_lien, $id, $objets, $qualif) {
	$echec = null;
	$ok = 0;
	$reordonner = false;
	if (!$qualif) {
		return false;
	}
@@ -743,6 +834,13 @@ function lien_set($objet_source, $primary, $table_lien, $id, $objets, $qualif) {
			);
			$args['id_objet'] = $id_objet;

			if (lien_triables($table_lien) and isset($qualif['rang_lien']) and intval($qualif['rang_lien'])) {
				// on decale les liens de rang_lien>=la valeur inseree pour faire la place
				$w = lien_where($primary, '*', $objet, $id_objet, array('rang_lien>='.intval($qualif['rang_lien']),"$primary!=".intval($id)));
				sql_update($table_lien, array('rang_lien'=>'rang_lien+1'), $w);
				$reordonner = true;
			}

			$where = lien_where($primary, $id, $objet, $id_objet, $cond);
			$e = sql_updateq($table_lien, $qualif, $where);

@@ -760,6 +858,10 @@ function lien_set($objet_source, $primary, $table_lien, $id, $objets, $qualif) {
			}
		}
	}
	// si on a fait des modif de rang, on reordonne les liens concernes
	if ($reordonner) {
		lien_ordonner($objet_source, $primary, $table_lien, $id, $objets);
	}

	return ($echec ? false : $ok);
}
+95 −10
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -554,6 +554,9 @@ function afficher_plus_info($lien, $titre = "+", $titre_lien = "") {
	}
}




/**
 * Lister les id objet_source associés à l'objet id_objet
 * via la table de lien objet_lien
@@ -567,17 +570,99 @@ function afficher_plus_info($lien, $titre = "+", $titre_lien = "") {
 * @return array
 */
function lister_objets_lies($objet_source, $objet, $id_objet, $objet_lien) {
	$res = lister_objets_liens($objet_source, $objet, $id_objet, $objet_lien);
	if (count($res)) {
		$r = reset($res);
		if (isset($r['rang_lien'])) {
			$l = array_column($res, 'rang_lien', $objet_source);
			asort($l);
			$l = array_keys($l);
		}
		else {
			$l = array_column($res, $objet_source);
		}
	}
	return $l;
}


/**
 * Retrouver le rang du lien entre un objet source et un obet lie
 * utilisable en direct dans un formulaire d'edition des liens, mais #RANG doit faire le travail automatiquement
 * [(#ENV{objet_source}|rang_lien{#ID_AUTEUR,#ENV{objet},#ENV{id_objet},#ENV{_objet_lien}})]
 *
 * @param $objet_source
 * @param $ids
 * @param $objet_lie
 * @param $idl
 * @param $objet_lien
 * @return string
 */
function retrouver_rang_lien($objet_source, $ids, $objet_lie, $idl, $objet_lien){
	$res = lister_objets_liens($objet_source, $objet_lie, $idl, $objet_lien);
	$res = array_column($res, 'rang_lien', $objet_source);

	return (isset($res[$ids]) ? $res[$ids] : '');
}


/**
 * Lister les liens en le memoizant dans une static
 * pour utilisation commune par lister_objets_lies et retrouver_rang_lien dans un formuluaire d'edition de liens
 * (evite de multiplier les requetes)
 *
 * @param $objet_source
 * @param $objet
 * @param $id_objet
 * @param $objet_lien
 * @return mixed
 * @private
 */
function lister_objets_liens($objet_source, $objet, $id_objet, $objet_lien) {
	static $liens = array();
	if (!isset($liens["$objet_source-$objet-$id_objet-$objet_lien"])) {
		include_spip('action/editer_liens');
	$l = array();
		// quand $objet == $objet_lien == $objet_source on reste sur le cas par defaut de $objet_lien == $objet_source
		if ($objet_lien == $objet and $objet_lien !== $objet_source) {
			$res = objet_trouver_liens(array($objet => $id_objet), array($objet_source => '*'));
		} else {
			$res = objet_trouver_liens(array($objet_source => '*'), array($objet => $id_objet));
		}
	while ($row = array_shift($res)) {
		$l[] = $row[$objet_source];

		$liens["$objet_source-$objet-$id_objet-$objet_lien"] = $res;
	}
	return $liens["$objet_source-$objet-$id_objet-$objet_lien"];
}

	return $l;
/**
 * Calculer la balise #RANG
 * quand ce n'est pas un champ rang :
 * peut etre le num titre, le champ rang_lien ou le rang du lien en edition des liens, a retrouver avec les infos du formulaire
 * @param $titre
 * @param $rang_lien
 * @param $objet_source
 * @param $id
 * @param $env
 * @return int|string
 */
function calculer_rang_smart($titre, $rang_lien, $objet_source, $id, $env) {
	// Cas du #RANG utilisé dans #FORMULAIRE_EDITER_LIENS -> attraper le rang du lien
	if (isset($env['form']) and $env['form']
		and isset($env['_objet_lien']) and $env['_objet_lien']
		and (function_exists('lien_triables') or include_spip('action/editer_liens'))
		and $r = objet_associable($env['_objet_lien'])
		and list($p, $table_lien) = $r
	  and lien_triables($table_lien)
	  and isset($env['objet']) and $env['objet']
		and isset($env['id_objet']) and $env['id_objet']
		and $objet_source
		and $id = intval($id)
	) {
		$rang = retrouver_rang_lien($objet_source, $id, $env['objet'], $env['id_objet'], $env['_objet_lien']);
		return ($rang ? $rang : '');
	}
	elseif(!is_null($rang_lien) and strlen($rang_lien)) {
		return $rang_lien;
	}
	return recuperer_numero($titre);
}
+21 −3
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -972,6 +972,8 @@ function balise_RANG_dist($p) {
		// si pas trouve de champ sql rang :
		if (!$_rang or $_rang == "''") {
			$boucle = &$p->boucles[$b];

			// on gere le cas ou #RANG est une extraction du numero dans le titre
			$trouver_table = charger_fonction('trouver_table', 'base');
			$desc = $trouver_table($boucle->id_table);
			$_titre = ''; # où extraire le numero ?
@@ -1004,7 +1006,23 @@ function balise_RANG_dist($p) {
				$_titre = champ_sql('titre', $p);
			}

			$_rang = "recuperer_numero($_titre)";
			// ca peut etre un rang sur le lien
			// (mais pareil, uniquement sur la boucle immediatement englobante uniquement)
			$_rang_lien = champ_sql('rang_lien', $p, '', false);

			// et on recupere aussi les infos de liaison si on est en train d'editer les liens justement
			// cas des formulaires xxx_lies utilises par #FORMULAIRE_EDITER_LIENS
			$type_boucle = $boucle->type_requete;
			$objet = objet_type($type_boucle);
			$id_table_objet = id_table_objet($type_boucle);
			$_primary = champ_sql($id_table_objet, $p, '', false);
			$_env = '$Pile[0]';

			if (!$_titre) {$_titre = "''";}
			if (!$_rang_lien) {$_rang_lien = "''";}
			if (!$_primary) {$_primary = "''";}
			$_rang = "calculer_rang_smart($_titre, $_rang_lien, '$objet', $_primary, $_env)";

		}
		
		$p->code = $_rang;
+33 −0
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -142,6 +142,8 @@ function formulaires_editer_liens_charger_dist($a, $b, $c, $options = array()) {
		'ajouter_lien' => '',
		'supprimer_lien' => '',
		'qualifier_lien' => '',
		'ordonner_lien' => '',
		'desordonner_liens' => '',
		'_roles' => $roles, # description des roles
		'_oups' => _request('_oups'),
		'editable' => $editable,
@@ -160,6 +162,8 @@ function formulaires_editer_liens_charger_dist($a, $b, $c, $options = array()) {
 * - ajouter_lien et supprimer_lien
 * - remplacer_lien
 * - qualifier_lien
 * - ordonner_lien
 * - desordonner_liens
 *
 * Les deux premières peuvent être de trois formes différentes :
 * ajouter_lien[]="objet1-id1-objet2-id2"
@@ -177,6 +181,11 @@ function formulaires_editer_liens_charger_dist($a, $b, $c, $options = array()) {
 * 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")
 *
 * ordonner_lien doit être de la forme, et sert pour trier les liens
 * ordonner_lien[objet1-id1-objet2-id2] = nouveau_rang
 *
 * desordonner_liens n'a pas de forme precise, il doit simplement estre non nul/non vide
 *
 * @param string $a
 * @param string|int $b
 * @param int|string $c
@@ -233,6 +242,12 @@ function formulaires_editer_liens_traiter_dist($a, $b, $c, $options = array()) {

		$supprimer = _request('supprimer_lien');
		$ajouter = _request('ajouter_lien');
		$ordonner = _request('ordonner_lien');

		if (_request('desordonner_liens')) {
			include_spip('action/editer_liens');
			objet_qualifier_liens(array($objet_lien => '*'), array($objet => $id_objet), array('rang_lien' => 0));
		}

		// il est possible de preciser dans une seule variable un remplacement :
		// remplacer_lien[old][new]
@@ -313,6 +328,24 @@ function formulaires_editer_liens_traiter_dist($a, $b, $c, $options = array()) {
				set_request('_oups');
			}
		}

		if ($ordonner) {
			include_spip('action/editer_liens');
			foreach ($ordonner as $k => $rang_lien) {
				if ($lien = lien_verifier_action($k, '')) {
					list($objet1, $ids, $objet2, $idl) = explode('-', $lien);
					$qualif = array('rang_lien' => $rang_lien);

					if ($objet_lien == $objet1) {
						objet_qualifier_liens(array($objet1 => $ids), array($objet2 => $idl), $qualif);
					} else {
						objet_qualifier_liens(array($objet2 => $idl), array($objet1 => $ids), $qualif);
					}
					set_request('id_lien_ajoute', $ids);
					set_request('_oups');
				}
			}
		}
	}