0

I'm working on a bb-code replacement function when a user wants to post a smiley.

The problem is, that if someone uses a bb-code smiley that doesn't exists, it results in an empty post because the browser will not display the (non-existing) emoticon.

Here's my code so far:

// DO [:smiley:]
  $convert_smiley = preg_match_all('/\[:(.*?):\]/i', $string, $matches);

  if( $convert_smiley )
  {        
    $string = preg_replace('/\[:(.*?):\]/i', "<i class='icon-smiley-$1'></i>", $string, $convert_smiley);
  }

  return $string;

The bb-code for a smiley usually looks like [:smile:] or like [:sad:] or like [:happy:] and so on.

The code above is working well, until someone post a bb-code that doesn't exists, so what I am asking for is a fix for non existing smileys.

Is there a possibility, in example to create an array, like array('smile', 'sad', 'happy') and only bb-code that matches one or more in this array will be converted?

So, after the fix, posting [:test:] or just [::] should not be converted and should be posted as original text while [:happy:] will be converted.

Any ideas? Thanks!

lickmycode
  • 2,069
  • 2
  • 19
  • 20

3 Answers3

1

A simple workaround:

$string ="[:clap:]";

$convert_smiley = preg_match_all('/\[:(.*?):\]/i', $string, $matches);

$emoticons = array("smile","clap","sad"); //array of supported smileys

if(in_array($matches[1][0],$emoticons)){
    //smily  exists
    $string = preg_replace('/\[:(.*?):\]/i', "<i class='icon-smiley-$1'></i>", $string, $convert_smiley);
}
else{
  //smily doesn't exist
}
dlock
  • 9,447
  • 9
  • 47
  • 67
  • That's the most simple workaround and also the closest solution to my question and code, so even the other answers are correct as well, your answer will be marked as correct. Thanks – lickmycode Dec 02 '13 at 01:27
  • Sorry, got to revert it, your solution fails when one smiley is incorrect, but all others are, then no smiley is converted. :/ – lickmycode Dec 02 '13 at 01:35
1

Well, the first issue is you are setting $convert_smiley to the true/false value of the preg_match_all() instead of parsing the results. Here is how I reworked your code:

// Test strings.
$string = ' [:happy:] [:frown:] [:smile:] [:foobar:]';

// Set a list of valid smileys.
$valid_smileys = array('smile', 'sad', 'happy');

// Do a `preg_match_all` against the smiley’s
preg_match_all('/\[:(.*?):\]/i', $string, $matches);

// Check if there are matches.
if (count($matches) > 0) {
  // Loop through the results
  foreach ($matches[1] as $smiley_value) {
    // Validate them against the valid smiley list.
    $pattern = $replacement = '';
    if (in_array($smiley_value, $valid_smileys)) {
      $pattern = sprintf('/\[:%s:\]/i', $smiley_value);
      $replacement = sprintf("<i class='icon-smiley-%s'></i>", $smiley_value);
      $string = preg_replace($pattern, $replacement, $string);
    }
  }
}

echo 'Test Output:';
echo htmlentities($string);

Just note that I chose to use sprintf() for the formatting of content & set $pattern and $replacement as variables. I also chose to use htmlentities() so the HTML DOM elements can easily be read for debugging.

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
1

I put your possible smiley’s in non-grouping parentheses with or symbol in a regexp:

<?php
$string = 'looks like [:smile:] or like [:sad:] or like [:happy:] [:bad-smiley:]';
$string = preg_replace('/\[:((?:smile)|(?:sad)|(?:happy)):\]/i', "<i class='icon-smiley-$1'></i>", $string);

print $string;

Output:

looks like <i class='icon-smiley-smile'></i> or like <i class='icon-smiley-sad'></i> or like <i class='icon-smiley-happy'></i> [:bad-smiley:]

[:bad-smiley:] is ignored.

user4035
  • 22,508
  • 11
  • 59
  • 94