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!

有帮助吗?

解决方案

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.

其他提示

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
}

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top