Balise #DISTANCE plus générique #5

Closed
opened 2 years ago by tcharlss · 13 comments
tcharlss commented 2 years ago
Owner

Je ressors de mon chapeau ce bug signalé il y a longtemps, avec une solution qui fonctionne cette fois.

Problème :

Si on a un quelconque objet avec un champ distance, la balise #DISTANCE ne renvoie plus rien en dehors des boucle GIS dès lors que ce dernier est actif.

On peut faire #CHAMP_SQL{distance}, mais bon.

Solution possible :

Ajouter un test dans dans la fonction balise_distance_dist de GIS : ne renvoyer la distance calculée que pour les boucles GIS, et pour les autres, renvoyer simplement la valeur de la colonne.

Je ressors de mon chapeau ce bug signalé il y a longtemps, avec une solution qui fonctionne cette fois. ## Problème : Si on a un quelconque objet avec un champ `distance`, la balise #DISTANCE ne renvoie plus rien en dehors des boucle GIS dès lors que ce dernier est actif. On peut faire `#CHAMP_SQL{distance}`, mais bon. ## Solution possible : Ajouter un test dans dans la fonction `balise_distance_dist` de GIS : ne renvoyer la distance calculée que pour les boucles GIS, et pour les autres, renvoyer simplement la valeur de la colonne.
b_b commented 2 years ago
Collaborator

Bonne idée, mais est-ce que ça ne va pas péter l'usage de la balise distance dans le cas d'usage du criètre distance_from qu'on utilise sur des boucles autres que GIS (cf la doc) ?

Bonne idée, mais est-ce que ça ne va pas péter l'usage de la balise distance dans le cas d'usage du criètre distance_from qu'on utilise sur des boucles autres que GIS (cf la doc) ?

oui c'est pas que sur les boucles (GIS), mais aussi possible sur n'importe quelle boucle qui a le critère {gis} qui sort les infos d'un point associé à tout objet

oui c'est pas que sur les boucles (GIS), mais aussi possible sur n'importe quelle boucle qui a le critère {gis} qui sort les infos d'un point associé à tout objet
Poster
Owner

Ah oui exact le test n'est pas suffisant pour distance_from.

Dans le test en regardant aussi les jointures, ça devrait le faire non ?
C'est à dire :

  • si c'est une boucle gis
  • OU s'il y a une jointure sur spip_gis ET spip_gis_liens

En code :

function balise_distance_dist($p) {
	$index  = index_boucle($p); // <BOUCLE_truc> → _truc
	$boucle = ($index ? $p->boucles[$index] : null);
	$table_objet  = ($boucle ? $boucle->type_requete : ''); // gis, articles, etc.

	// Tests sur les tables
	$is_table_gis = ($table_objet === 'gis');
	$has_jointure_gis = (array_search('gis', array_keys($boucle->join)) !== false);
	$has_jointure_gis_liens = (array_search('gis_liens', array_keys($boucle->join)) !== false);

	// Si c'est la table gis ou qu'il y a une jointure sur celle-ci,
	// on retourne la distance calculée présente sous forme d'alias dans le SELECT.
	if (
		$is_table_gis
		or (
			$has_jointure_gis
			and $has_jointure_gis_liens
		)
	) {
		return rindex_pile($p, 'distance', 'gis');

	// Sinon on retourne simplement la valeur du champ
	} else {
		$p->code = champ_sql('distance', $p);
		return $p;
	}
}

Testé chez moi en local, ça le fait.

Ah oui exact le test n'est pas suffisant pour `distance_from`. Dans le test en regardant aussi les jointures, ça devrait le faire non ? C'est à dire : * si c'est une boucle gis * OU s'il y a une jointure sur spip_gis ET spip_gis_liens En code : ```php function balise_distance_dist($p) { $index = index_boucle($p); // <BOUCLE_truc> → _truc $boucle = ($index ? $p->boucles[$index] : null); $table_objet = ($boucle ? $boucle->type_requete : ''); // gis, articles, etc. // Tests sur les tables $is_table_gis = ($table_objet === 'gis'); $has_jointure_gis = (array_search('gis', array_keys($boucle->join)) !== false); $has_jointure_gis_liens = (array_search('gis_liens', array_keys($boucle->join)) !== false); // Si c'est la table gis ou qu'il y a une jointure sur celle-ci, // on retourne la distance calculée présente sous forme d'alias dans le SELECT. if ( $is_table_gis or ( $has_jointure_gis and $has_jointure_gis_liens ) ) { return rindex_pile($p, 'distance', 'gis'); // Sinon on retourne simplement la valeur du champ } else { $p->code = champ_sql('distance', $p); return $p; } } ``` Testé chez moi en local, ça le fait.
Poster
Owner

NB : ou alors ça pourrait être de tester en plus la présence du critère distancefrom tout simplement plutôt que les jointures, peut-être plus robuste ?

NB : ou alors ça pourrait être de tester en plus la présence du critère `distancefrom` tout simplement plutôt que les jointures, peut-être plus robuste ?
Poster
Owner

Donc oui ça me paraît finalement plus sûr, ça donne ça :

function balise_distance_dist($p) {
	$index       = index_boucle($p); // <BOUCLE_truc> → _truc
	$boucle      = ($index ? $p->boucles[$index] : null);
	$table_objet = ($boucle ? $boucle->type_requete : ''); // gis, articles, etc.
	$criteres    = ($boucle ? $boucle->criteres : array());

	// Tester la présence du critère {distancefrom}
	$critere_distancefrom = false;
	foreach ($criteres as $critere) {
		if ($critere->op === 'distancefrom') {
			$critere_distancefrom = true;
			break;
		}
	}

	// Si c'est la table GIS ou qu'il y a le critère {distancefrom},
	// on retourne la distance calculée présente sous forme d'un alias dans le SELECT.
	if (
		($table_objet === 'gis')
		or $critere_distancefrom
	) {
		return rindex_pile($p, 'distance', 'gis');

	// Sinon on retourne simplement la valeur du champ
	} else {
		$p->code = champ_sql('distance', $p);
		return $p;
	}
}
Donc oui ça me paraît finalement plus sûr, ça donne ça : ```php function balise_distance_dist($p) { $index = index_boucle($p); // <BOUCLE_truc> → _truc $boucle = ($index ? $p->boucles[$index] : null); $table_objet = ($boucle ? $boucle->type_requete : ''); // gis, articles, etc. $criteres = ($boucle ? $boucle->criteres : array()); // Tester la présence du critère {distancefrom} $critere_distancefrom = false; foreach ($criteres as $critere) { if ($critere->op === 'distancefrom') { $critere_distancefrom = true; break; } } // Si c'est la table GIS ou qu'il y a le critère {distancefrom}, // on retourne la distance calculée présente sous forme d'un alias dans le SELECT. if ( ($table_objet === 'gis') or $critere_distancefrom ) { return rindex_pile($p, 'distance', 'gis'); // Sinon on retourne simplement la valeur du champ } else { $p->code = champ_sql('distance', $p); return $p; } } ```
b_b commented 2 years ago
Collaborator

C'est TOP GÉNÉRIQUE, gogogo ;)

C'est **TOP GÉNÉRIQUE**, gogogo ;)
Owner

Et tout simplement

$p->code = champ_sql('distance', $p, rindex_pile($p, 'distance', 'gis'));

qui fait "cherche un champ distance dans une boucle de la pile et sinon prend le champ calcule distance issu du critere gis ?

Ou alors :

$p->code = "(\$dgis=".rindex_pile($p, 'distance', 'gis')."?\$dgis:".champ_sql('distance', $p);

qui fait "si on trouve une distance gis, prends ça, sinon utilise le champ distance ou le env distance" (puisque rindex_pile teste deja la presence d'un critere {gis} dans la pile)

Dans les 2 cas on évite de faire trop de suppositions et ça cassera pas si on introduit un autre critere qui produit distance

Et tout simplement ``` $p->code = champ_sql('distance', $p, rindex_pile($p, 'distance', 'gis')); ``` qui fait "cherche un champ distance dans une boucle de la pile et sinon prend le champ calcule distance issu du critere `gis` ? Ou alors : ``` $p->code = "(\$dgis=".rindex_pile($p, 'distance', 'gis')."?\$dgis:".champ_sql('distance', $p); ``` qui fait "si on trouve une distance gis, prends ça, sinon utilise le champ distance ou le env distance" (puisque rindex_pile teste deja la presence d'un critere `{gis}` dans la pile) Dans les 2 cas on évite de faire trop de suppositions et ça cassera pas si on introduit un autre critere qui produit `distance`
Poster
Owner

Ah oui top, c'est beaucoup plus concis et plus perenne.

À choisir le 2) me semble mieux : prendre en priorité la distance calculée.

Ça fonctionne bien chez moi avec les 3 différents cas : {gis distance} sur une boucle GIS, {distancefrom} sur un autre objet et enfin sur un 3ème objet avec une colonne distance.

function balise_distance_dist($p) {

	// Retourne la distance calculée par GIS si présente,
	// sinon la valeur du champ.
	$p->code = "(\$distance_gis = " . rindex_pile($p, 'distance', 'gis')->code . ") ?"
		. "\$distance_gis : "
		. champ_sql('distance', $p);

	return $p;
}

Nb : manquait juste le ->code après rindex_pile.

Ah oui top, c'est beaucoup plus concis et plus perenne. À choisir le 2) me semble mieux : prendre en priorité la distance calculée. Ça fonctionne bien chez moi avec les 3 différents cas : `{gis distance}` sur une boucle GIS, `{distancefrom}` sur un autre objet et enfin sur un 3ème objet avec une colonne distance. ```php function balise_distance_dist($p) { // Retourne la distance calculée par GIS si présente, // sinon la valeur du champ. $p->code = "(\$distance_gis = " . rindex_pile($p, 'distance', 'gis')->code . ") ?" . "\$distance_gis : " . champ_sql('distance', $p); return $p; } ``` Nb : manquait juste le ->code après rindex_pile.
Owner

ah oui mais alors non, je me suis gouré: le résultat de rindex_pile doit être analysé à la compilation, pas au calcul :

rindex_pile($p, 'distance', 'gis')
if ($p->code === "''") {
	$p->code = champ_sql('distance', $p);
}
return $p;
ah oui mais alors non, je me suis gouré: le résultat de rindex_pile doit être analysé à la compilation, pas au calcul : ``` rindex_pile($p, 'distance', 'gis') if ($p->code === "''") { $p->code = champ_sql('distance', $p); } return $p; ```
Collaborator

rindex_pule ne reçoit pas &$p mais $p donc ne serait-ce pas plutôt $p = rindex_pile (...) ?

rindex_pule ne reçoit pas &$p mais $p donc ne serait-ce pas plutôt `$p = rindex_pile (...)` ?
Owner

si tout à fait, tu as raison

si tout à fait, tu as raison
Poster
Owner

Corrigé, merci jluc.

@b_b ça devrait être bon là, hésite pas à squasher si tu veux.

Corrigé, merci jluc. @b_b ça devrait être bon là, hésite pas à squasher si tu veux.
b_b commented 2 years ago
Collaborator

Done, merci, on ferme :)

Done, merci, on ferme :)
b_b closed this issue 2 years ago
Sign in to join this conversation.
No Milestone
No Assignees
5 Participants
Notifications
Due Date

No due date set.

Dependencies

This issue currently doesn't have any dependencies.

Loading…
There is no content yet.