label_nettoyer() et lettres accentuées #4894

Open
opened 2 weeks ago by tcharlss · 8 comments
tcharlss commented 2 weeks ago
Owner

Parfois le filtre label_nettoyer() semble avoir du mal avec certaines lettres accentuées.
Mais pas tout le temps, c'est bizarre.
Exemple dans un squelette tout en utf-8 (charset + encodage du fichier) :

[(#VAL{lettres accentuées àéèâ}|label_nettoyer|var_dump)]
[(#VAL{lettres accentuées àâ}|label_nettoyer|var_dump)]
[(#VAL{lettres accentuées à}|label_nettoyer|var_dump)]
[(#VAL{lettres accentuées éèâà}|label_nettoyer|var_dump)]

Retour :

string 'Lettres accentuées àéèâ' (length=28)
string 'Lettres accentuées àâ' (length=24)
string 'Lettres accentuées �' (length=21)
string 'Lettres accentuées éèâ�' (length=27)

Dans ces exemples, ça se produit uniquement quand la lettre à est à la fin.
Mais si la même lettre est à une autre position : aucun problème !

Parfois le filtre [label_nettoyer()](https://git.spip.net/spip/spip/src/branch/master/ecrire/inc/filtres.php#L5467-L5492) semble avoir du mal avec certaines lettres accentuées. Mais pas tout le temps, c'est bizarre. Exemple dans un squelette tout en utf-8 (charset + encodage du fichier) : ``` [(#VAL{lettres accentuées àéèâ}|label_nettoyer|var_dump)] [(#VAL{lettres accentuées àâ}|label_nettoyer|var_dump)] [(#VAL{lettres accentuées à}|label_nettoyer|var_dump)] [(#VAL{lettres accentuées éèâà}|label_nettoyer|var_dump)] ``` Retour : ``` string 'Lettres accentuées àéèâ' (length=28) string 'Lettres accentuées àâ' (length=24) string 'Lettres accentuées �' (length=21) string 'Lettres accentuées éèâ�' (length=27) ``` Dans ces exemples, ça se produit uniquement quand la lettre `à` est à la fin. Mais si la même lettre est à une autre position : aucun problème !
tcharlss added the
filtres et balises
bug
labels 2 weeks ago
Owner

Alors, label_nettoyer nettoie à droite \xc2\xa0 ("non breaking space") dans le rtrim. Mais ça trimme sur \xc2 et \xa0 distinctement :/

Et bin2hex('à') vaut c3a0; Et paf le chien.

En fait j’ai du vouloir trim les "non breaking space" (\xc2\xa0) mais c’est 2 caractères distincts ici pour trim… En fait il faut mettre \u{a0} à la place dont bin2hex("\u{a0}") vaut bien c2a0.

Alors, label_nettoyer nettoie à droite `\xc2\xa0` ("non breaking space") dans le rtrim. Mais ça trimme sur `\xc2` et `\xa0` distinctement :/ Et `bin2hex('à')` vaut `c3a0`; Et paf le chien. En fait j’ai du vouloir trim les "non breaking space" (`\xc2\xa0`) mais c’est 2 caractères distincts ici pour trim… En fait il faut mettre `\u{a0}` à la place dont bin2hex("\u{a0}") vaut bien c2a0.
Owner

Oui, mais en fait c’est pas mieux. Trim n’est simplement pas multibyte. Alors il faut passer par preg je pense du coup…

Voilà une proposition :

diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php
index c418dd877..c148a24b4 100644
--- a/ecrire/inc/filtres.php
+++ b/ecrire/inc/filtres.php
@@ -5481,10 +5481,8 @@ function identifiant_slug($texte, $type = '', $options = []) {
  * @exemple `<:info_maximum|label_nettoyer:>`
  */
 function label_nettoyer(string $text, bool $ucfirst = true): string {
-       $label = rtrim($text, " : \t\n\r\0\x0B\xc2\xa0");
-       if ($label and $label[-1] === ';') {
-               $label = preg_replace('#(\&nbsp;)+$#', '', $label);
-       }
+       $label = rtrim($text, " : \t\n\r\0\x0B");
+       $label = preg_replace("#(\&nbsp;|\u{a0})+$#u", '', $label);
        if ($ucfirst) {
                $label = spip_ucfirst($label);
        }

J’ai testé sur quelques chaines et ça semble aller.
Note : il faut faire un jeu de tests (des vrais)

Oui, mais en fait c’est pas mieux. Trim n’est simplement pas multibyte. Alors il faut passer par preg je pense du coup… Voilà une proposition : ```diff diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php index c418dd877..c148a24b4 100644 --- a/ecrire/inc/filtres.php +++ b/ecrire/inc/filtres.php @@ -5481,10 +5481,8 @@ function identifiant_slug($texte, $type = '', $options = []) { * @exemple `<:info_maximum|label_nettoyer:>` */ function label_nettoyer(string $text, bool $ucfirst = true): string { - $label = rtrim($text, " : \t\n\r\0\x0B\xc2\xa0"); - if ($label and $label[-1] === ';') { - $label = preg_replace('#(\&nbsp;)+$#', '', $label); - } + $label = rtrim($text, " : \t\n\r\0\x0B"); + $label = preg_replace("#(\&nbsp;|\u{a0})+$#u", '', $label); if ($ucfirst) { $label = spip_ucfirst($label); } ``` J’ai testé sur quelques chaines et ça semble aller. Note : il faut faire un jeu de tests (des vrais)
Owner

Mieux (car sinon là l’ordre importait dans le remplacement).
Mais ça fait donc un preg systématique donc forcément.


diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php
index c418dd877..15c61fdc0 100644
--- a/ecrire/inc/filtres.php
+++ b/ecrire/inc/filtres.php
@@ -5481,10 +5481,7 @@ function identifiant_slug($texte, $type = '', $options = []) {
  * @exemple `<:info_maximum|label_nettoyer:>`
  */
 function label_nettoyer(string $text, bool $ucfirst = true): string {
-       $label = rtrim($text, " : \t\n\r\0\x0B\xc2\xa0");
-       if ($label and $label[-1] === ';') {
-               $label = preg_replace('#(\&nbsp;)+$#', '', $label);
-       }
+       $label = preg_replace('#([\s:\t\n\r\0\x0B]|\xc2\xa0|\&nbsp;)+$#u', '', $text);
        if ($ucfirst) {
                $label = spip_ucfirst($label);
        }
Mieux (car sinon là l’ordre importait dans le remplacement). Mais ça fait donc un preg systématique donc forcément. ```diff diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php index c418dd877..15c61fdc0 100644 --- a/ecrire/inc/filtres.php +++ b/ecrire/inc/filtres.php @@ -5481,10 +5481,7 @@ function identifiant_slug($texte, $type = '', $options = []) { * @exemple `<:info_maximum|label_nettoyer:>` */ function label_nettoyer(string $text, bool $ucfirst = true): string { - $label = rtrim($text, " : \t\n\r\0\x0B\xc2\xa0"); - if ($label and $label[-1] === ';') { - $label = preg_replace('#(\&nbsp;)+$#', '', $label); - } + $label = preg_replace('#([\s:\t\n\r\0\x0B]|\xc2\xa0|\&nbsp;)+$#u', '', $text); if ($ucfirst) { $label = spip_ucfirst($label); } ```
Owner

Ah il semble que \s de preg englobe |\xc2\xa0 (\ua0)

Ah il semble que `\s` de preg englobe `|\xc2\xa0` (`\ua0`)
Owner

Il semble qu’on puisse avoir cette version simplifiée :
$label = preg_replace('#([\s:]|\&nbsp;)+$#u', '', $text);

Car \s englobe déjà pas mal de choses.

Il semble qu’on puisse avoir cette version simplifiée : `$label = preg_replace('#([\s:]|\&nbsp;)+$#u', '', $text);` Car `\s` englobe déjà pas mal de choses.
Owner

#4896 donc.
Auquel il faudra ajouter les tests unitaires

https://git.spip.net/spip/spip/pulls/4896 donc. Auquel il faudra ajouter les tests unitaires
Owner

Au fait, j’ai envoyé des tests cd33920205 (dans la branche dev/refactor (en phpunit))

Au fait, j’ai envoyé des tests https://git.spip.net/spip/tests/commit/cd339202057da380bff5f27660850122e92bdc48 (dans la branche dev/refactor (en phpunit))
Poster
Owner

Top merci @marcimat, je teste dès que possible

Top merci @marcimat, je teste dès que possible
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date

No due date set.

Dependencies

This issue currently doesn't have any dependencies.

Loading…
There is no content yet.