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

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Lot (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 34
    Points : 13
    Points
    13
    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 éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    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.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

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

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 34
    Points : 13
    Points
    13
    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 éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    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);
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

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

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 34
    Points : 13
    Points
    13
    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 éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    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?
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Lot (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 34
    Points : 13
    Points
    13
    Par défaut
    Alors, tout d'abord, après avoir écris le texte, j'ai un bouton de prévisualisation qui transforme les bbcode via JS !

    Ensuite, quand je l'envois sur ma bdd, et que je la retourne sur une page, toute les balises bbcodes se transforme grace à mon fichier traitementbbcodes.php ou il y a toute mes regex !

    Donc du coup, je ne vois pas comment appliquer ta solution qui est :
    1/ enregistrer les images d'abord pour qu'elles aient le href et ensuite
    2/ mettre la regex des liens !

    (désolé, comme tu peux le voir, je suis assez novice )

  8. #8
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Bon, en fait tu veux faire la même chose que sur le présent forum!

    À ta place moi, je virerai le remplacement via JS pour n'utiliser qu'un seul module php qui se charge de passer de la version du texte saisie (ou stockée en bdd) à la version affichée (en html).
    Ce module devra, dans cet ordre, transformer tous les bbcodes en html et transformer les urls perdus dans le texte en liens.

    Le stockage en bdd ne doit se faire que lors de l'envoi du texte qui doit être stocké en version brut (c à d en BBcode et sans liens html)
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  9. #9
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Lot (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 34
    Points : 13
    Points
    13
    Par défaut
    Donc si je résume pour voir si j'ai bien compris (désolé de t'embeter ! )
    1/ j'écris ma balise
    2/ je traduit la balise en html sauf les liens qui sont en texte brut
    3/ j'insère dans la bdd
    4/ je ressors le texte
    5/ je traduit le lien !

    J'ai bon ? ^^

    (c'est con, mon système etait presque au point ... XD)

  10. #10
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    Par défaut
    non pas vraiment, ce serait plutôt:

    scénario d'envoi:
    1) Le texte est saisie avec du bbcode dans un textarea.
    2) quand je clique sur le bouton "envoyer/valider", le texte est envoyé sans modifications à un script php pour être stocké dans la bdd tel quel.
    3) ce même script php va ensuite transformer le texte en html (transformation des balises bbcode en balises html, puis transformation des urls en liens) juste pour l'afficher.

    scénario de prévisualisation:
    1) Le texte est saisie avec du bbcode dans un textarea.
    2) Je clique sur le bouton "prévisualiser", le texte est renvoyé tel quel dans le textarea (pour pouvoir continuer à l'éditer) mais aussi la version transformé en html pour pouvoir l'afficher en dessous ou au dessus, n'importe.

    En fait ce serait le même fichier qui s'occuperait de l'édition, de la prévisualisation et de l'affichage suivant les valeurs reçues en POST. Exemple de squelette:
    Code page.php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    <html><head>...
    <?php
    // on définit le mode et ses caractéristiques
    if (isset($_POST['mode']) {
        $mode['type'] = $_POST['mode'];
        switch($mode['type']):
            case 'new': $mode['display'] = false; $mode['edit'] = true; break;
            case 'preview': $mode['display'] = true; $mode['edit'] = true; break;
            case 'edit': $mode['display'] = false; $mode['edit'] = true; break;
            case 'display': $mode['display'] = true; $mode['edit'] = false; break;
            case 'save': $mode['display'] = true; $mode['edit'] = false; break;
        endswitch;
    } else {
        $mode['type'] = 'display';
        $mode['display'] = true;
        $mode['edit'] = false;
    }
     
    if ($mode['type'] == 'save') {
        // si le mode est 'save', cela signifie que le message est envoyé et qu'il doit être enregistré tel quel dans la base de données
    }
     
    // on détermine le texte brut en fonction du mode
    if ($mode['type'] == 'preview') { // si il s'agit d'une prévisualisation on récupère le texte brut du textarea via les données POST
        $text['raw'] = $_POST['text'];
    } elseif ($mode['type'] == 'new') {
        $text['raw'] = '';
    } else { // ou il s'agit d'une édition de message, d'un enregistrement ou d'un affichage,  on va alors chercher le texte brut dans la base de données
        // ...
    }
     
    // on charge le javascript et la feuille de style éventuelle nécessaire au formulaire de saisie
    if ($mode['edit']) {
        echo '<script.......</script>';
        echo '<link rel="stylesheet"..../>';
    }
    ?>
    </head><body>...
    <?php
     
    // affichage
    if ($mode['display']) {
        include('bbcodetrans.php'); // on inclut le fichier contenant la définition des deux fonctions suivantes    
        $text['html'] = bbcode2html($text['brut']);
        $text['html'] = url2link($text['html']);
     
        echo $texte['html'];
        if ($mode['type'] == 'display') {
            // on peut aussi afficher des boutons "nouveau" et "edit" dans ce mode pour ajouter ou éditer un message  
        }
    }
     
    // édition
    if ($mode['edit']) {
        // on affiche le formulaire en plaçant $text['raw'] comme valeur par défaut du textarea
    }
    ?>
    ...</body></html>
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  11. #11
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Lot (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 34
    Points : 13
    Points
    13
    Par défaut
    Je tiens à te remercier énormément car a chacune de tes réponses, c'est tout un tas d'explications que tu me donne, précise et complète.
    Toutefois, je trouve cette méthode un poil compliqué (désolé ) du coup, je me suis fait une balise url et ca sera comme ca.



    Mais je me garde toutes tes informations dans un coin de mes favoris (car dans un coin de ma tête, ca risque de se perdre ) car tu as pris le temps de tout développer, et encore une fois, merci !

  12. #12
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    Par défaut
    C'est plutôt une bonne solution, car ça évite d'aller à la pêche à l'url, ça laisse le contrôle à l'utilisateur qui peut choisir si oui ou non il souhaite faire un lien, et ça évite le problème quasi insoluble de vérification du format d'une url.

    Maintenant un conseil, vu que tu débutes, va au bout de ton approche, laisse reposé quelque temps, et puis repense l'architecture (papier, crayon) et recommence tout. Tu verras que tu obtiendras un résultat bien plus efficace et en moins de temps qu'il ne faut pour le dire.

    Bonne continuation.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  13. #13
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Lot (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 34
    Points : 13
    Points
    13
    Par défaut
    D'accord, merci beaucoup pour ton conseils ! ^^

    Ah, si tout les profs pouvaient être comme toi !

+ 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