Valider feea64d7 rédigé par cerdic's avatar cerdic
Parcourir les fichiers

Fix #4866 : tous les comptages de rang se font avec un where calcule via la...

Fix #4866 : tous les comptages de rang se font avec un where calcule via la fonction lien_rang_where() qui par defaut calcule un where correspondant a "tous les id_xx associes a objet-id_objet" mais dont le comportement peut etre personalise au cas par cas via une fonction perso lien_rang_where_{$table_lien}()
Par ailleurs si un rang_lien est fourni lors de l'appel a objet_associer() il est directement pris en compte pour l'insertion du lien plutot que de calculer un rang automatique, inserer avec ce rang, puis modifier ensuite
Enfin, dans ce dernier cas, on appelle pas lien_ordonner() immediatement apres l'insertion, mais on laisse d'abord lien_set() faire son job (a savoir eventuellement mettre le meme rang sur les autres liens id_xx/objet/id_objet identiques mais avec un role different), et finalement finir par un lien_ordonner()

Additionnellement, la fonction lien_ordonner() ne presume plus du mode de comptage des rangs :
- elle se repose aussi sur la fonction lien_rang_where()
- elle utilise les infos des liens trouves
- elle note les liens deja ordonnes pour eviter un double recomptage (notamment si on l'appelle avec plusieurs objets/id_objets qui sont tous comptes en une seule fois parce que c'est le primary qui sert de regroupement)

(finger crossed)
parent 25173bd6
Chargement en cours
Chargement en cours
Chargement en cours
Chargement en cours
+71 −23
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -396,16 +396,21 @@ function lien_insert($objet_source, $primary, $table_lien, $id, $objets, $qualif
			}

			if (lien_triables($table_lien)) {
				if (isset($qualif['rang_lien'])) {
					$rang = $qualif['rang_lien'];
				}
				else {
					$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);
						$where = lien_rang_where($table_lien, $primary, $id, $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;
			}

@@ -437,8 +442,11 @@ 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'])) {
					$where_meme_lien = lien_where($primary, $id, $objet, $id_objet);
					$where_meme_lien = implode(' AND ', $where_meme_lien);
					// on decale les liens de rang_lien>=la valeur inseree pour faire la place
					$w = lien_where($primary, '*', $objet, $id_objet, ['rang_lien>=' . intval($insertions['rang_lien']),"$primary!=" . intval($id)]);
					// sauf sur le meme lien avec un role eventuellement different
					$w = lien_rang_where($table_lien, $primary, $id, $objet, $id_objet, ['rang_lien>=' . intval($insertions['rang_lien']), "NOT($where_meme_lien)"]);
					sql_update($table_lien, ['rang_lien' => 'rang_lien+1'], $w);
				}

@@ -462,7 +470,8 @@ 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) {
	// pas la peine si $qualif['rang_lien'] etait fournie, on va passer dans lien_set a suivre et donc finir le recomptage
	if ($ins > 0 and empty($qualif['rang_lien'])) {
		lien_ordonner($objet_source, $primary, $table_lien, $id, $objets);
	}

@@ -483,29 +492,44 @@ function lien_ordonner($objet_source, $primary, $table_lien, $id, $objets) {
		return;
	}

	$deja_reordonne = [];

	foreach ($objets as $objet => $id_objets) {
		if (!is_array($id_objets)) {
			$id_objets = [$id_objets];
		}

		foreach ($id_objets as $id_objet) {
			if (empty($deja_reordonne[$id][$objet][$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');
				$where = lien_rang_where($table_lien, $primary, $id, $objet, $id_objet);
				$liens = sql_allfetsel("$primary, id_objet, objet, rang_lien", $table_lien, $where, '', 'rang_lien');

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

							if (empty($deja_reordonne[$lien[$primary]])) {
								$deja_reordonne[$lien[$primary]] = [];
							}
							if (empty($deja_reordonne[$lien[$primary]][$lien['objet']])) {
								$deja_reordonne[$lien[$primary]][$lien['objet']] = [];
							}
							$deja_reordonne[$lien[$primary]][$lien['objet']][$lien['id_objet']] = $rang;

							$rang++;
						}
					}
				}
			}
		}
	}
}


/**
@@ -590,6 +614,27 @@ function lien_where($primary, $id_source, $objet, $id_objet, $cond = []) {
	return $where;
}

/**
 * Fabriquer la condition where pour compter les rangs
 * @param string $table_lien
 * @param string $primary
 * @param int|string|array $id_source
 * @param string $objet
 * @param int|string|array $id_objet
 * @param array $cond
 * @return array                        Liste des conditions
 */
function lien_rang_where($table_lien, $primary, $id_source, $objet, $id_objet, $cond = []) {

	// si on veut compter les rangs autrement que le core ne le fait par defaut, fournir le where adhoc
	if (function_exists($f = 'lien_rang_where_' . $table_lien)) {
		return $f($primary, $id_source, $objet, $id_objet, $cond);
	}

	// par defaut c'est un rang compté pour tous les id_source d'un couple objet-id_objet
	return lien_where($primary, '*', $objet, $id_objet, $cond);
}

/**
 * Sous fonction suppression
 * qui traite les liens pour un objet source dont la clé primaire
@@ -864,7 +909,10 @@ function lien_set($objet_source, $primary, $table_lien, $id, $objets, $qualif) {
			if (lien_triables($table_lien) and isset($qualif['rang_lien'])) {
				if (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, ['rang_lien>=' . intval($qualif['rang_lien']),"$primary!=" . intval($id)]);
					// sauf sur le meme lien avec un role eventuellement different
					$where_meme_lien = lien_where($primary, $id, $objet, $id_objet);
					$where_meme_lien = implode(' AND ', $where_meme_lien);
					$w = lien_rang_where($table_lien, $primary, $id, $objet, $id_objet, ['rang_lien>=' . intval($qualif['rang_lien']), "NOT($where_meme_lien)"]);
					sql_update($table_lien, ['rang_lien' => 'rang_lien+1'], $w);
				}
				// tous les liens de même rôle recoivent le rang indiqué aussi