IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Regex lien cliquable interfère avec BBcode image


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Lot (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 34
    Par défaut Regex lien cliquable interfère avec BBcode image
    Bonjour à vous

    Je viens vous voir, car j'ai un soucis (pour changer ...)

    Mon soucis est que j'ai une regex pour faire des liens cliquables :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $texte = preg_replace('#(https?|ftp)://([\w\/\.\?_=\#\@:~\{\}&;]{20})(.+)([\w\/\.\?_=\#\@:~\{\}&;]{5})#i', ' <a href="$0" target="_blank">$1://$2[...]$4</a> ', $texte);
    Mais j'ai aussi une regex pour demander au balise [img][/img] de transformer le lien d'une image en image :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $texte = preg_replace('#\[img](.+?)\[/img]#si','<a href="$1"><div class="img01"><img class="imageforum" src="$1" /></div></a>',$texte);
    Donc mon soucis est que l'un interfère avec l'autre !

    Comment faire en sorte de demander à la regex lien de laisser tranquille les balises [img][/img] ?

    J'ai trouvé un bout de solutions en rajoutant ceci dans ma regex lien : ([^img]) et ([^/img])

    Mais dès que je les insère dans ma regex, j'ai une erreur :

    Compilation failed: unmatched parentheses at offset 57
    (le chiffre évoluant en fonction des tests !)

    Auriez vous une idée alors pour gérer mon erreur ?
    Merci d'avoir pris le temps de lire mon soucis :]

  2. #2
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Tu peux résoudre le problème avec un test simple.

    Comme toutes les urls de tes images cliquables sont déjà dans placés dans des attributs href ou src, il te suffit dans le vérifier dans la pattern pour les liens:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $texte = preg_replace('#(?<!src="|href=")((?:https?|ftp)://[\w/.?=\#@:~{}&;-]{20})\S+([\w/.?=\#@:~{}&;-]{5})#i',
                          ' <a href="$0" target="_blank">$1[...]$2</a> ', $texte);
    Ici j'utilise un test arrière négatif (negative lookbehind) (?<!...) qui signifie non précédé par ...
    Remarque: Attention, il y a une limite à l'utilisation d'un lookbehind en php. Celui-ci ne peut contenir qu'une sous-pattern de taille constante ou plusieurs sous-patterns de tailles constantes séparer par des pipes |. Ce qui exclut l'utilisation de quantificateurs ou de références à un groupe de capture (backreference).

    À propos des caractères qu'il est inutile d'échapper, mais cette fois-ci dans les classes de caractères. Les seules caractères devant être échappés dans une classe de caractères sont:
    • Le crochet fermant ] sauf s'il est placé en premier dans la classe []abcd], ou après juste après le caret de négation de classe [^]abcd]
    • Le caret ^ si il est en première position dans la classe.
    • Le délimiteur
    • Le tiret - si sa position est ambigüe et qu'il pourrait définir un rang de caractères. En clair, pas besoin de l'échapper s'il est au début ou à la fin de la classe, ou s'il est précédé d'un rang [a-z-2] ou d'une classe de caractère [\s-2]. (par contre un rang qui n'existe pas comme [z-a] générera une erreur.)

    Les moutons à cinq pattes (le parsing des classes de caractères POSIX):
    • si au lieu d'écrire [almnu[:], on a l'idée saugrenue d'écrire [[:alnum:] (ce qui en théorie devrait revenir au même), on a le droit à une jolie erreur de compilation: missing terminating ] for character class. Dans ce cas, on peut rassurer le parser en échappant soit le premier :, soit le crochet ouvrant.
    • Même chose si on écrit une classe POSIX qui n'existe pas [[:toto:] mais cette fois-ci l'erreur est: unknown POSIX class name



    Autre chose, si tu veux raccourcir les urls qui s'affichent en limitant leur taille à une trentaine de caractères, tu devrais plutôt te tourner vers preg_replace_callback qui te permet un traitement plus fin de ce qui a été capturé, car pour le moment ta pattern va passer à coté de toutes les urls de moins de 30 caractères.

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $texte = preg_replace_callback('~(?<!src="|href=")((?:https?|ftp)://)([\w/.?=#@:\~{}&;-]+)~i', function($m) {
        return $m[1] . ((strlen($m[2])<30) ? $m[2] : substr($m[2], 0, 20) . '[...]' . substr($m[2], -5)); 
    }, $texte);
    Au sujet de ton approche pour traiter le BBcode:
    PHP dispose dans son module standard de fonctions pour gérer le BBcode: http://php.net/manual/fr/book.bbcode.php.
    Ces fonctions permettent de créer un parser "en code bien de chez nous", en définissant la syntaxe des éléments du BBcode.

    Si pour une raison quelconque ces fonctions ne convenaient pas et que tu préfères en revenir à ta première approche, tu dois savoir que quand tu passes à preg_replace des tableaux de patterns et de chaînes de remplacement, ton texte est intégralement parcouru une fois pour chaque pattern, ce qui n'est pas super efficace.
    Pour améliorer ça, tu pourrais déjà enlever tout ce qui ne demande pas de traitement spécial de la liste des patterns, soient les balises [i] [b] [u] [s][*] et les balises fermantes [/align] [/color] [/size], et faire ces remplacements avec strtr qui est super rapide et qui ne parcourra le texte qu'une seule fois pour tout le lot:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $trans = array('['.'i]' => '<em>', '['.'/i]' => '</em>',
                   '['.'b]' => '<strong>', '['.'/b]' => '</strong>',
                   '['.'u]' => '<span style="text-decoration:underline;">', '['.'/u]' => '</span>',
                   '['.'s]' => '<span style="text-decoration:line-through;">', '['.'/s]' => '</span>',
                   '['.'*]' => '<li>', // à voir si ce dernier ne demande pas un traitement plus fin pour fermer la balise
                   '['.'/align]' => '</div>', '['.'/color]' => '</span>', '['.'/size]' => '</span>'
     );
     
    $texte = strtr($texte, $trans);
    Pour le reste tu peux construire une pattern commune avec des groupes de capture que tu passeras à preg_replace_callback, comme ça, c'est à la fonction de callback de construire la chaîne de remplacement en fonction du tag, et la chaîne ne sera parcourue qu'une seule fois.

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Lot (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 34
    Par défaut
    Merci beaucoup de m'avoir corrigé ma regex (et grâce à toi, je comprends mieux ce qu'il faut échapper ou non, alors déjà, un grand MERCI )

    Toutefois, j'ai testé ta regex pour pas prendre en compte le lien des images avec leur balise [img], mais cela ne fonctionne point... (j'ai modifié pour tenter d'exclure les liens avec la balise [img] comme tu l'as fait avec href, mais pareil !)

  4. #4
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Il faut placer cette recherche d'url après la transformation du BBcode en html.

    Sinon tu as une solution plus radicale qui consiste à esquiver tout ce que tu veux éviter:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $pattern = '~
      (?:       # dans ce groupe tu places tout ce que tu veux esquiver
          <a\s.*?</a>     # les liens
         |
            <img[^>]*>   # les balises img
      )
      (*SKIP)(*FAIL) # fait échouer la pattern et saute tous les caractères consommés précédemment 
    |
      ((?:https?|ftp)://)([\w/.?=#@:\~{}&;-]+)~isx';
     
    $texte = preg_replace_callback($pattern, function($m) {
        return $m[1] . ((strlen($m[2])<30) ? $m[2] : substr($m[2], 0, 20) . '[...]' . substr($m[2], -5)); 
    }, $texte);

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Lot (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 34
    Par défaut
    Oui, mais sachant que j'ai un fichier traitementbbcodes.php qui transforme tout dans la foulé, comment le placé pour faire en sorte que le lien seul se fasse après la génération d'image ?

  6. #6
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Qu'est ce que tu veux dire par "dans la foulé"? Tu veux dire que ton bbcode est traduit via ajax en html, au fur et à mesure?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. <div> qui interfère avec mes images
    Par darkritual dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 17/12/2012, 14h59
  2. Créer une image cliquable intéractive avec lien - comment faire ?
    Par jerome44600 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 9
    Dernier message: 27/10/2010, 10h09
  3. [RegEx] Lien cliquable et compatibilité bbcode
    Par Fiquet dans le forum Langage
    Réponses: 4
    Dernier message: 26/02/2007, 22h59
  4. [RegEx] regex et lien cliquable
    Par Pallas4 dans le forum Langage
    Réponses: 1
    Dernier message: 22/09/2006, 12h57
  5. Réalisation d'un lien avec une image.
    Par argon dans le forum AWT/Swing
    Réponses: 10
    Dernier message: 05/02/2006, 10h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo