[spip-dev] objet_type et le pluriel

Salut,

Dernièrement je tentais de résoudre un bug dans GIS2 qui provoque une erreur SQL lors de la suppression du logo d'un point GIS. Il s'avère que le problème vient de la fonction objet_type() et surtout de sa gestion du pluriel sur les objets.

Sous SPIP 2.1, dans exec/iconifier l'appel à autoriser('iconifier', $type, $id) ne charge pas l'autorisation présente dans GIS2 car $type vaut "gi" et non "gis".

http://core.spip.org/projects/spip/repository/entry/branches/spip-2.1/ecrire/exec/iconifier.php#L28

Du coup on retombe sur l'autorisation par défaut
autoriser_iconifier_dist() qui cherche un champ id_rubrique dans la table spip_gis et cela génère l'erreur SQL que je souhaite régler.

Tout cela vient du fait que la fonction objet_type() de base/connect_sql renvoie "gi" si on lui passe "gis" comme argument. Voici quelques tests effectués sous SPIP 2.1 :

table_objet('gis') => gis
objet_type('gis') => gi
table_objet('gi') => gis

Pour info j'ai déposé un fichier de test unitaire dans gis/trunk/tests/ sur la zone.

Le problème reste le même malgré la déclaration de gis dans le pipeline declarer_tables_objets_surnoms :

function gis_declarer_tables_objets_surnoms($surnoms){
  $surnoms['gis'] = 'gis';
  return $surnoms;
}

En effet, dans objet_type() on supprime d'abord le "s" final de la variable $table_objet (qui du coup vaut "gi"). Ensuite on exécute un test sur table_objet($type)==$table_objet, table_objet() ne trouve alors pas de trace de "gi" dans les éléments renvoyés par le pipeline declarer_tables_objets_surnoms et renvoie preg_replace(',ss$,', 's', $type."s"); avec $type qui vaut "gi" et hop la boucle est bouclée (pour SPIP du moins).

Du coup, il semble déconseillé (ou impossible) d'utiliser pleinement des objets dont le nom au singulier se termine par un "s" (cas, canevas, gis...).

Une solution à ce problème serait d'inverser les deux blocs de test dans objet_type et de tenter en premier lieu de trouver le type en utilisant trouver_table() mais je me demande si c'est bon pour les perfs de SPIP ?

http://core.spip.org/projects/spip/repository/entry/branches/spip-2.1/ecrire/base/connect_sql.php#L308

J'ai aussi testé ce cas de figure sous SPIP 3 avec le plugin TestBuilder et le problème est le même. J'ai retrouvé un message récent de Severo qui propose un patch pour SPIP 3 :

http://comments.gmane.org/gmane.comp.web.spip.devel/61157

En appliquant ce patch et en déclarant 'gis' => 'gis' dans le nouveau pipeline declarer_type_surnoms objet_type('gis') renvoie bien 'gis'. Le bug original semble donc contournable sous SPIP 3 à condition qu'on y intègre le patch de Severo.

Re,

j'avance dans mes recherches. Je propose qu'on modifie id_table_objet() à la ligne suivante :

http://core.spip.org/projects/spip/repository/entry/branches/spip-2.1/ecrire/base/connect_sql.php#L285

Remplacer :

$type = preg_replace(',^spip_|s$,', '', $type);

par :

$type = objet_type($type);

Je viens de déposer des tests unitaires pour le jeu de fonctions de connect_sql et les tests passent tous avec la modification en question.

Du coup, si dans GIS2 je déclare :

function gis_declarer_tables_objets_surnoms($surnoms){
  $surnoms['gis'] = 'gis';
  $surnoms['gi'] = 'prout'; // fourberie pour objet_type('gis') => 'gi'
  return $surnoms;
}

Les tests unitaires de GIS2 passent aussi et mon bug est résolu. Bon c'est pas super propre du côté de GIS, mais ça fonctionne et la modification du core me semble mineure. Qu'en pensez-vous ?

Sur les conseils de Cedric (merci à lui), solution plus propre et moins risquée : report du pipeline declarer_type_surnoms de SPIP 3 dans la fonction objet_type().

En Spip 2.1, je crois qu'il y a encore un souci pour la recherche avec jointures,
dans le cas des singuliers/pluriels bizarres (genre: expositor/expositores)

je dirais que c'est dû a a la ligne 296 dans le fichier
ecrire/inc/rechercher.php, où la clause WHERE est créée par
"sql_in('id_'.${table_liee}" au lieu d'utiliser ce qui est déclaré+
dans l'interface "tables_jointures"

    $s = sql_select("$cle_depart,$cle_arrivee",
       "spip_${table_liee_sql}_${table_sql}", sql_in('id_'.${table_liee},
       array_keys($ids_trouves)), '','','','',$serveur);

Bon, je sais pas trop comment ca doit se réparé, mais je pense que
c'est pas ici qu'il faut chercher.

Severo

Ce dont tu parles concerne les jointures sur recherche.
C'est un cas particulier qui ne passe pas par le compilateur et est très mal géré en 2.1.
C'est un peu amélioré en version 3 mais cela n'utilise toujours pas le compilateur, donc reste assez imparfait.
Cela dit, dans les deux cas, il est possible de déclarer sa propre fonction
inc/rechercher_joints_${table}_${table_liee}
pour faire la recherche jointe sur tous les cas qui ne marchent pas par défaut.

Cédric

Pas de chance, ce coup ci c'était pour un site en 2.1, j'aurais du tenter de le
faire en SPIP3, c'est trop de la balle!

Je vais essayer avec la fonction inc/rechercher_joints_${table}_${table_liee}
Merci!

Oui ,

Ca serait intéressant que tu puisses faire le test sur un SPIP 3 pour voir si ton cas passe ou pas.