A better way to replace emoticons in PHP?
Asked Answered
E

5

7

Right now I am using this function for emoticons:

function emoticons($text) {
        $icons = array(
                ':)'    =>  '<img src="/images/blank.gif" alt="smile" class="icon_smile" />',
                ':-)'   =>  '<img src="/images/blank.gif" alt="smile" class="icon_smile" />',
                ':D'    =>  '<img src="/images/blank.gif" alt="smile" class="icon_laugh" />',
                ':d'    =>  '<img src="/images/blank.gif" alt="laugh" class="icon_laugh" />',
                ';)'    =>  '<img src="/images/blank.gif" alt="wink" class="icon_wink" />',
                ':P'    =>  '<img src="/images/blank.gif" alt="tounge" class="icon_tounge" />',
                ':-P'   =>  '<img src="/images/blank.gif" alt="tounge" class="icon_tounge" />',
                ':-p'   =>  '<img src="/images/blank.gif" alt="tounge" class="icon_tounge" />',
                ':p'    =>  '<img src="/images/blank.gif" alt="tounge" class="icon_tounge" />',
                ':('    =>  '<img src="/images/blank.gif" alt="sad face" class="icon_sad" />',
                ':o'    =>  '<img src="/images/blank.gif" alt="shock" class="icon_shock" />',
                ':O'    =>  '<img src="/images/blank.gif" alt="shock" class="icon_shock" />',
                ':0'    =>  '<img src="/images/blank.gif" alt="shock" class="icon_shack" />',
                ':|'    =>  '<img src="/images/blank.gif" alt="straight face" class="icon_straight" />',
                ':-|'   =>  '<img src="/images/blank.gif" alt="straight face" class="icon_straight" />',
                ':/'    =>  '<img src="/images/blank.gif" alt="straight face" class="icon_straight" />',
                ':-/'   =>  '<img src="/images/blank.gif" alt="straight face" class="icon_straight" />'
        );
        return strtr($text, $icons);
    }

But if you enter a link the :/ part of http:// gets replaced:

enter image description here

Same with code (4 spaces in front of each line to create code box), but for some reason a simple ) gets replaced (with a wink) as well:

enter image description here

Is there a better solution to this than replacing all of the icons like this? It obviously doesn't work good. I have searched on Google a lot and haven't found any better way. I also tried putting a space before each emoticon in the associative array above but that doesn't work if you just enter a :) without anything before it.

Ency answered 11/3, 2012 at 20:46 Comment(0)
O
12

You can use the preg_replace function and then use word boundaries in the regular expression.

 foreach($icons as $icon=>$image) {
      $icon = preg_quote($icon);
      $text = preg_replace("~\b$icon\b~",$image,$text);
 }

You need to use word boundaries and not white space because this will take care of the start and end points to. Needing a space before means that just a :) won't be found.

Obligation answered 11/3, 2012 at 20:48 Comment(6)
+1 for word boundaries - but in the case of 'www' wouldn't http be a word, and / a word boundary, so the :/ would still get filtered?Schism
actually, i take that back - +1 for preg_quote, that's awesome!Schism
So I put this in my function instead of using strtr()? Edit: Hmm, for some reason no icons are being turned into images now. I wonder if there is a way to make no text emoticons turn into images in code boxes?Ency
Gmail chat does it nicely. Do you know if they use regex or some other thing?Ency
Gmail almost certainly does it with regular expressions but they probably do it at the javascript level rather than in php in between the two chatters if I had to guess. There is one thing that maybe you can change to see if it works, instead of | as the bounding character for the regex try something which isn't in any of the emoticons. Srry about that I changed my answer above to reflect this.Obligation
since you are using a tilde should pass it as the second parameter to preg_quote. i.e. preg_quote($icon, '~');Symposium
M
1

Regular expressions are slow for this if the text is big, as much as i like them, you should only insert an icon if it's surrounded by spaces, that way your users won't riot when trying to write urls.

Marsupium answered 11/3, 2012 at 21:0 Comment(0)
C
1

I'm not sure whether it will work or not, but I'd try to put some extra spaces like this:

function emoticons($text) {
    $icons = array(
            ' :) '    =>  ' <img src="/images/blank.gif" alt="smile" class="icon_smile" /> ',
            ' :-) '   =>  ' <img src="/images/blank.gif" alt="smile" class="icon_smile" /> ',
            ' :D '    =>  ' <img src="/images/blank.gif" alt="smile" class="icon_laugh" /> ',
            ' :d '    =>  ' <img src="/images/blank.gif" alt="laugh" class="icon_laugh" /> ',
            ' ;) '    =>  ' <img src="/images/blank.gif" alt="wink" class="icon_wink" /> ',
            ' :P '    =>  ' <img src="/images/blank.gif" alt="tounge" class="icon_tounge" /> ',
            ' :-P '   =>  ' <img src="/images/blank.gif" alt="tounge" class="icon_tounge" /> ',
            ' :-p '   =>  ' <img src="/images/blank.gif" alt="tounge" class="icon_tounge" /> ',
            ' :p '    =>  ' <img src="/images/blank.gif" alt="tounge" class="icon_tounge" /> ',
            ' :( '    =>  ' <img src="/images/blank.gif" alt="sad face" class="icon_sad" /> ',
            ' :o '    =>  ' <img src="/images/blank.gif" alt="shock" class="icon_shock" /> ',
            ' :O '    =>  ' <img src="/images/blank.gif" alt="shock" class="icon_shock" /> ',
            ' :0 '    =>  ' <img src="/images/blank.gif" alt="shock" class="icon_shack" /> ',
            ' :| '    =>  ' <img src="/images/blank.gif" alt="straight face" class="icon_straight" /> ',
            ' :-| '   =>  ' <img src="/images/blank.gif" alt="straight face" class="icon_straight" /> ',
            ' :/ '    =>  ' <img src="/images/blank.gif" alt="straight face" class="icon_straight" /> ',
            ' :-/ '   =>  ' <img src="/images/blank.gif" alt="straight face" class="icon_straight" /> '
    );
    return strtr($text, $icons);
}
Coff answered 11/3, 2012 at 21:17 Comment(1)
This method would work great if you make a tweak on the RETURN portion. return trim(strtr(" $text ",$icons));Divert
G
1

I'd recommend two libraries:

Emojify: https://github.com/HallgrenNetworks/emojify

PHP Emoji: https://github.com/iamcal/php-emoji

These will deal with these cases for you.

Glutinous answered 14/1, 2014 at 9:22 Comment(0)
A
0

I think using regular expressions instead of just defining your emoticons. This could look like

// replaces a :) when it is surrounded by whitespaces
return preg_replace('/\s:)\s/', '<img ...>', $text);
Anabelle answered 11/3, 2012 at 20:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.