Titre : [statistiques] table_objet_sql() reçoit un array dans referenceurs.php → fatal PHP 8
Contexte
- SPIP : x.y.z (prod)
- PHP : 8.x
- Plugins noyau :
statistiques(version livrée avec x.y.z) - Plugins :
statsobjets 2.1.0,referer_spam 1.2.1 - Hébergeur/OS : …
Reproduction
- Activer Statistiques et StatsObjets.
- Aller dans : Activités → Statistiques → Liens entrants.
- Avec certains objets passés par l’interface, l’erreur survient.
Résultat obtenu
table_objet_sql(): Argument #1 ($type) must be of type string, array given
…/ecrire/base/objets.php:1074
appelé depuis …/plugins-dist/statistiques/inc/referenceurs.php:191
Résultat attendu
Affichage normal des référents.
Analyse
referenceurs.php::referes() peut recevoir $objets sous forme de tableau (extraction depuis spip_referers_objets ou appels externes). La boucle foreach ($objets as $objet) envoie ensuite un élément potentiellement tableau à table_objet_sql($objet), qui attend une chaîne.
Correctif proposé (défensif)
- Extraire proprement la colonne
objetdepuissql_allfetsel. - Aplatir/normaliser
$objetsen tableau de chaînes. - Passer chaque
$objetparobjet_type()avanttable_objet_sql().
Diff minimal sur plugins-dist/statistiques/inc/referenceurs.php :
--- a/plugins-dist/statistiques/inc/referenceurs.php
+++ b/plugins-dist/statistiques/inc/referenceurs.php
@@ function referes(string $referermd5, $objets = null, string $serveur = ''): string {
- if ($stats_objets) {
- if ($objets = sql_allfetsel('DISTINCT objet', 'spip_referers_objets')) {
- $objets_par_defaut = array_values($objets);
- }
- }
+ if ($stats_objets) {
+ if ($tmp = sql_allfetsel('DISTINCT objet', 'spip_referers_objets')) {
+ // extraire colonne 'objet', nettoyer et dédupliquer
+ $liste = array_column($tmp, 'objet');
+ $liste = array_filter(array_map('strval', $liste));
+ $liste = array_values(array_unique($liste));
+ $objets_par_defaut = $liste;
+ }
+ }
if (sql_fetsel('*', 'spip_visites_articles', '', '', '', '0,1')) {
$objets_par_defaut[] = 'article';
- // (pas de déduplication ici)
+ $objets_par_defaut = array_values(array_unique($objets_par_defaut));
}
@@
- elseif (is_array($objets)) {
- // laisser tel quel
- }
+ elseif (is_array($objets)) {
+ // aplatir d’éventuels sous-tableaux
+ $flat = [];
+ foreach ($objets as $o) {
+ $flat[] = is_array($o) ? reset($o) : $o;
+ }
+ $objets = array_values(array_unique(array_filter(array_map('strval', $flat))));
+ }
@@
- foreach ($objets as $objet) {
- $table_objet_sql = table_objet_sql($objet);
+ foreach ($objets as $objet) {
+ if (is_array($objet)) {
+ $objet = reset($objet);
+ }
+ $objet = objet_type($objet);
+ $table_objet_sql = table_objet_sql($objet);
$id_table_objet = id_table_objet($objet);
Remarque front/squelettes (optionnel)
Dans prive/squelettes/contenu/stats_referers.html, on peut aussi normaliser côté gabarit pour éviter de passer un tableau :
#SET{objet_norm,#ENV{objet}|table_valeur{0,#ENV{objet}}}
… utiliser #GET{objet_norm} à la place de #ENV{objet} …
Mais le correctif robuste est côté PHP.
Merci.