PHP - replace text with smiley - php

I have this function:
function bb_parse($string) {
$string = $this->quote($string);
$string=nl2br($string);
$string = html_entity_decode(stripslashes(stripslashes($string)));
$tags = 'b|i|u';
while (preg_match_all('`\[('.$tags.')=?(.*?)\](.+?)\[/\1\]`', $string, $matches)) foreach ($matches[0] as $key => $match) {
list($tag, $param, $innertext) = array($matches[1][$key], $matches[2][$key], $matches[3][$key]);
switch ($tag) {
case 'b': $replacement = "<strong>$innertext</strong>"; break;
case 'i': $replacement = "<em>$innertext</em>"; break;
case 'u': $replacement = "<u>$innertext</u>"; break;
}
$string = str_replace($match, $replacement, $string);
}
return $string;
}
As you can see, I can easily make BBCode with bold, italic and underline. Although, I am trying to add smileys to this function as well, but without luck.
I tried to simply just add :) to the $tags, and then add the smiley :) img in the case, but that did not work.
How can I do, so I can also add smilies to this?
Thanks in advance.

Just create a function that does a simple str_replace, I'd say:
<?php
function smilies( $text ) {
$smilies = array(
';)' => '<img src="wink.png" />',
':)' => '<img src="smile.png" />'
);
return str_replace( array_keys( $smilies ), array_values( $smilies ), $text );
}
$string = '[b]hello[/b] smile: :)';
echo smilies( bb_parse( $string ) );

http://php.net/manual/en/function.preg-quote.php
You have to escape your smiley tags.
$tags = 'b|i|u|'.preg_quote(":)");

Related

preg_replace inside loop replacing last match instead of each

Sorry about the title I honestly dont know how to explain it properly.
I am making a small shortcode function that needs to replace shortcodes with html output.
The preg_match_all finds everything I need but the preg_replace is replacing the same match over and over again.
Here is the demo
https://eval.in/139727
I am sure I made a mess in those foreach loops but just cant figure it out.
$text = 'Some text and some [link link="linkhref1" text="Text1"],[link link="linkhref2" text="Text2"]';
function shortcodes($text) {
$shortcodes = array(
'link' => array(
"check" => "[link",
"type" => "link",
"match" => "#\[link(.*?)link\=\"(.*?)\"(.*?)text\=\"(.*?)\"#Ui",
"replace" => "/\[link(.*?)\]/s"
)
);
foreach ($shortcodes as $index => $shortcode) {
if (strpos($text, $shortcode['check']) !== false) {
$text = shortcode_replace($shortcode, $text);
}
}
return $text;
}
function shortcode_replace($shortcode, $text) {
$replacement = '';
preg_match_all($shortcode['match'], $text, $matches);
switch ($shortcode['type']) {
case "link":
foreach ($matches[4] as $index => $match) {
$link = $matches[2][$index];
$linktext = $matches[4][$index];
$replacement .= '' . $linktext . '';
$text = preg_replace($shortcode['replace'], $replacement, $text);
}
}
return $text;
}
echo shortcodes($text);
any help is appreciated!
There was a problem in regex i've changed it. Also you don't need preg_replace there.
<?php
$text = 'Some text and some [link link="linkhref1" text="Text1"],[link link="linkhref2" text="Text2"]';
function shortcodes($text) {
$shortcodes = array(
'link' => array(
"check" => "[link",
"type" => "link",
"match" => "#\[link(\s+)link\=\"([^\"]+)\"(\s+)text\=\"([^\"]+)\"\]#Ui",
"replace" => "/\[link(.*?)\]/s"
)
);
foreach ($shortcodes as $index => $shortcode) {
if (strpos($text, $shortcode['check']) !== false) {
$text = shortcode_replace($shortcode, $text);
}
}
return $text;
}
function shortcode_replace($shortcode, $text) {
$replace = '';
preg_match_all($shortcode['match'], $text, $matches);
switch ($shortcode['type']) {
case "link":
var_dump($matches);
foreach ($matches[4] as $index => $match) {
$link = $matches[2][$index];
$linktext = $matches[4][$index];
$replace = '' . $linktext . '';
$text = str_replace($matches[0][$index], $replace, $text);
}
}
return $text;
}
echo shortcodes($text);
Here is a working version :
<?php
$text = 'Some text and some [link link="linkhref1" text="Text1"],[link link="linkhref2" text="Text2"]';
function shortcodes($text) {
$shortcodes = array(
'link' => array(
"check" => "[link",
"type" => "link",
"match" => "#\[link(.*?)link\=\"(.*?)\"(.*?)text\=\"(.*?)\"#",
"replace" => "/\[link(.*?)\]/s"
)
);
foreach ($shortcodes as $index => $shortcode) {
if (strpos($text, $shortcode['check']) !== false) {
$text = shortcode_replace($shortcode, $text);
}
}
return $text;
}
function shortcode_replace($shortcode, $text) {
$replace = '';
preg_match_all($shortcode['match'], $text, $matches);
switch ($shortcode['type']) {
case "link":
foreach ($matches[4] as $index => $match) {
$link = $matches[2][$index];
$linktext = $matches[4][$index];
$replace .= '' . $linktext . '';
$whatToReplace = '[link link="'.$link.'" text="'.$linktext.'"]';
$text = str_replace($whatToReplace, $replace, $text);
}
}
return $text;
}
echo shortcodes($text);
I'm not very good at RegExp, i modified the "match" to match all the links ( with what you got, it didn't )
You need to identify the exact [link ] to replace, and not all all of them. In my opinion, this is the correct way to identify the link, You can also identify it using strpos() ( getting the start and end of the string) or see where the [link starts and the first ] is .
A better option can be to create a regexp with the unique values for it , which can compensate for extra spaces between tags
Hopefully this is of help to you

Use PHP to Convert Email Text to a Link

Based on a question I had answered here ( Use PHP to Replace HTML with HTML ), I'd like to be able to filter my output text for email addresses, and convert those text emails to "mailto" links.
Here's the PHP code that works, but only for converting some HTML to other HTML. What I've tried to do is have this function look for an email address, and convert it to a "mailto" link. For whatever reason, the code doesn't convert the email addresses. Here's my PHP:
function text_filter($string) {
$search = array('<p>__</p>', '/[a-zA-Z0-9._-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}/');
$replace = array('<hr />', '$2');
$processed_string = str_replace($search, $replace, $string);
echo $processed_string;
}
When I use this function for output, this is what the code looks like:
<?php text_filter( get_the_content() ); ?>
str_replace() doesn't use regular expressions, rewritten with preg_replace().
Added delimiters to first matching expression.
Fixed replacement from $1 to $2.
function text_filter($string) {
$search = array('/<p>__<\/p>/', '/([a-zA-Z0-9._-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})/');
$replace = array('<hr />', '$1');
$processed_string = preg_replace($search, $replace, $string);
echo $processed_string;
}
#Adam Baney - This will work even when used repeatedly.
// EMAILS
$str = preg_replace('~(^|[\s\.,;\n\(])([a-zA-Z0-9._+-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})~',
'$1$2',
$str);
// PHONE NUMBERS
$str = preg_replace_callback('~(^|[\s\.,;\n\(])(?<! )([0-9 \+\(\)]{9,})~', function($m) {
return $m[1].''.$m[2].'';
}, $str);
You can't use str_replace to do a regular expression replace.
You will need to split the actions up.
function text_filter($string) {
$search = array('<p>__</p>');
$replace = array('<hr />');
$processed_string = str_replace($search, $replace, $string);
$processed_string = preg_replace('/[a-zA-Z0-9._-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}/','$2',$processed_string);
echo $processed_string;
}
See: http://www.php.net/manual/en/function.preg-replace.php for preg replacing.
function obfuscate_email($content){
$pattern = '#([0-9a-z]([-_.]?[0-9a-z])*#[0-9a-z]([-.]?[0-9a-z])*\\.';
$pattern .= '[a-wyz][a-z](fo|g|l|m|mes|o|op|pa|ro|seum|t|u|v|z)?)#i';
$replacement = '\\1';
$content = preg_replace($pattern, $replacement, $content);
return $content;
}
And add filter
add_filter( 'the_content', 'obfuscate_email' );
Another way to do it in order so that it would work with existing html links in text:
function html_parse_text($text)
{
$text = preg_replace("/(?<!\")(((f|ht){1}tps?:\/\/)[-a-zA-Z0-9#:%_\+.~#?&\/\/=]+)/",
'<a href="\\1" target=_blank>\\1</a>', $text);
$text = preg_replace("/([[:space:]()[{}])(www.[-a-zA-Z0-9#:%_\+.~#?&\/\/=]+)/",
'\\1<a href="http://\\2" target=_blank>\\2</a>', $text);
$text = preg_replace("/(?<!\")([_\.0-9a-z-]+#([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3})/",
'<a href="mailto:\\1" target=_blank>\\1</a>', $text);
return $text;
}
Here is another version of this that seems to work for me. I've added + char to handle "plus addressing" (like some+email#address.com)
function replaceemail($text) {-
$ex = "/([a-zA-Z0-9._+-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})/";
preg_match_all($ex, $text, $url);
foreach($url[0] as $k=>$v) $text = str_replace($url[0][$k], ''.$url[0][$k].'', $text);
return $text;
}

replace everything except specific words in PHP

Is it possible to use php's preg_replace to remove anything in a string except specific words?
For example:
$text = 'Hello, this is a test string from php.';
I want to remove everything except "test" and "php" so it will be:
$text will be 'test php'
You could always use a callback. Under PHP 5.3:
$keep = array('test'=>1, 'php'=>1);
$text = trim(
preg_replace(
'/[^A-Za-z]+/', ' ',
preg_replace_callback(
'/[A-Za-z]+/',
function ($matched) use (&keep) {
if (isset($keep[$matched[0]])) {
return $matched[0];
}
return '';
}, $text
) ) );
Alternatively:
$text =
array_intersect(
preg_split('/[^A-Za-z]+/', $text),
array('test', 'php')
);
$text = 'Hello, this is a test string from php.';
$words = preg_split('~\W~', $text, -1, PREG_SPLIT_NO_EMPTY);
$allowed_words = array('test'=>1, 'php'=>1);
$output = array();
foreach($words as $word)
{
if(isset($allowed_words[$word]))
{
$output[] = $word;
}
}
print implode(' ', $output);

How to use preg_replace() to apply hilight_string() to content between BBCode-like tags?

I'm trying to run the preg_replace() function to replace the content in between two custom tags (i.e. [xcode]) within the string / content of the page.
What I want to do with the content between these custom tags is to run it through highlight_string() function and to remove those custom tags from the output.
Any idea how to do it?
So you want sort of a BBCode parser. The example below replaces [xcode] tags with whatever markup you like.
<?php
function highlight($text) {
$text = preg_replace('#\[xcode\](.+?)\[\/xcode\]#msi', '<em>\1</em>', $text);
return $text;
}
$text = '[xcode]Lorem ipsum[/xcode] dolor sit [xcode]amet[/xcode].';
echo highlight($text);
?>
Use preg_replace_callback() if you want to pass the matched text to a function:
<?php
function parse($text) {
$text = preg_replace_callback('#\[xcode\](.+?)\[\/xcode\]#msi',
function($matches) {
return highlight_string($matches[1], 1);
}
, $text);
return $text;
}
$text = '[xcode]Lorem ipsum[/xcode] dolor sit [xcode]amet[/xcode].';
echo bbcode($text);
?>
I'll include the source code of a BBCode parser that I made a long time ago. Feel free to use it.
<?php
function bbcode_lists($text) {
$pattern = "#\[list(\=(1|a))?\](.*?)\[\/list\]#msi";
while (preg_match($pattern, $text, $matches)) {
$points = explode("[*]", $matches[3]);
array_shift($points);
for ($i = 0; $i < count($points); $i++) {
$nls = split("[\n]", $points[$i]);
$brs = count($nls) - 2;
$points[$i] = preg_replace("[\r\n]", "<br />", $points[$i], $brs);
}
$replace = ($matches[2] != '1') ? ($matches[2] != 'a') ? '<ul>' : '<ol style="list-style:lower-alpha">' : '<ol style="list-style:decimal">';
$replace .= "<li>";
$replace .= implode("</li><li>", $points);
$replace .= "</li>";
$replace .= ($matches[2] == '1' || $matches[2] == 'a' ) ? '</ol>' : '</ul>';
$text = preg_replace($pattern, $replace, $text, 1);
$text = preg_replace("[\r\n]", "", $text);
}
return $text;
}
function bbcode_parse($text) {
$text = preg_replace("[\r\n]", "<br />", $text);
$smilies = Array(
':)' => 'smile.gif',
':d' => 'tongue2.gif',
':P' => 'tongue.gif',
':lol:' => 'lol.gif',
':D' => 'biggrin.gif',
';)' => 'wink.gif',
':zzz:' => 'zzz.gif',
':confused:' => 'confused.gif'
);
foreach ($smilies as $key => $value) {
$text = str_replace($key, '<img src="/images/smilies/' . $value . '" alt="' . $key . '" />', $text);
}
if (!(!strpos($text, "[") && !strpos($text, "]"))) {
$bbcodes = Array(
'#\[b\](.*?)\[/b\]#si' => '<strong>$1</strong>',
'#\[i\](.*?)\[/i\]#si' => '<em>$1</em>',
'#\[u\](.*?)\[/u\]#si' => '<span class="u">$1</span>',
'#\[s\](.*?)\[/s\]#si' => '<span class="s">$1</span>',
'#\[size=(.*?)\](.*?)\[/size\]#si' => '<span style="font-size:$1">$2</span>',
'#\[color=(.*?)\](.*?)\[/color\]#si' => '<span style="color:$1">$2</span>',
'#\[url=(.*?)\](.*?)\[/url\]#si' => '$2',
'#\[url\](.*?)\[/url\]#si' => '$1',
'#\[img\](.*?)\[/img\]#si' => '<img src="$1" alt="" />',
'#\[code\](.*?)\[/code\]#si' => '<div class="code">$1</div>'
);
$text = preg_replace(array_keys($bbcodes), $bbcodes, $text);
$text = bbcode_lists($text);
$quote_code = Array("'\[quote=(.*?)\](.*?)'i", "'\[quote](.*?)'i", "'\[/quote\]'i");
$quote_html = Array('<blockquote><p class="quotetitle">Quote \1:</p>\2', '<blockquote>\2', '</blockquote>');
$text = preg_replace($quote_code, $quote_html, $text);
}
return $text;
}
?>
basically,
preg_replace_callback('~\[tag\](.+?)\[/tag\]~', function($matches) { whatever }, $text);
this doesn't handle nested tags though
complete example
$text = "hello [xcode] <? echo bar ?> [/xcode] world";
echo preg_replace_callback(
'~\[xcode\](.+?)\[/xcode\]~',
function($matches) {
return highlight_string($matches[1], 1);
},
$text
);
<?php
$string = 'The quick brown fox jumped over the lazy dog.';
$patterns = array();
$patterns[0] = '/quick/';
$patterns[1] = '/brown/';
$patterns[2] = '/fox/';
$replacements = array();
$replacements[2] = 'bear';
$replacements[1] = 'black';
$replacements[0] = 'slow';
echo preg_replace($patterns, $replacements, $string);
?>
The above example will output:
The bear black slow jumped over the lazy dog.
http://php.net/manual/en/function.preg-replace.php
OR
str_replace should help you
http://php.net/manual/en/function.str-replace.php
Thanks to user187291's suggestion and preg_replace_callback specification I've ended up with the following outcome which does the job spot on! :
function parseTagsRecursive($input)
{
$regex = '~\[xcode\](.+?)\[/xcode\]~';
if (is_array($input)) {
$input = highlight_string($input[1], true);
}
return preg_replace_callback($regex, 'parseTagsRecursive', $input);
}
$text = "hello [xcode] <? echo bar ?> [/xcode] world and [xcode] <?php phpinfo(); ?> [/xcode]";
echo parseTagsRecursive($text);
The output of parsing the $text variable through this function is:
hello <? echo bar ?> world and <?php phpinfo(); ?>
Thank you everyone for input!

PHP function bbcode make optional to replace smileys

I want to give the oppurtunity to the user if he wants his smileys to be replaced with image smileys.
I tried this.
bbcode($text, TRUE);
function bbcode($str, $smileys = false)
{
$str = htmlentities($str);
$find = array(
if ($smileys == true) {
':p',
}
'/\[b](.*?)\[\/b]/i',
'/\[u](.*?)\[\/u]/i',
'/\[i](.*?)\[\/i]/i',
'/\[img](.*?)\[\/img]/i',
'/\[url](.*?)\[\/url]/i',
'/\[color=(.*?)\](.*?)\[\/color]/i',
'/\[size=(.*?)\](.*?)\[\/size]/i'
);
$replace = array(
if ($smileys == true) {
'<img src="/img/toungue.gif">',
}
'<strong>$1</strong>',
'<u>$1</u>',
'<i>$1</i>',
'<img src="$1" alt="$1" />',
'$1',
'<span style="color:$1">$2</span>',
'<span style="font-size:$1">$2</span>'
);
$str = preg_replace($find, $replace, $str);
return nl2br($str);
}
I guess u cant have if clause in array.
And i also tried:
function bbcode($str, $smileys = false)
{
$str = htmlentities($str);
$find = array(
'/\[b](.*?)\[\/b]/i',
'/\[u](.*?)\[\/u]/i',
'/\[i](.*?)\[\/i]/i',
'/\[img](.*?)\[\/img]/i',
'/\[url](.*?)\[\/url]/i',
'/\[color=(.*?)\](.*?)\[\/color]/i',
'/\[size=(.*?)\](.*?)\[\/size]/i'
);
$replace = array(
'<strong>$1</strong>',
'<u>$1</u>',
'<i>$1</i>',
'<img src="$1" alt="$1" />',
'$1',
'<span style="color:$1">$2</span>',
'<span style="font-size:$1">$2</span>'
);
if ($smileys == true) {
$find = array(
':p'
);
$replace = array(
'<img src="/img/toungue.gif">'
);
}
$str = preg_replace($find, $replace, $str);
return nl2br($str);
}
Equals to = No ending delimiter ':' found in functions.php on line 68
I guess u cant have if clause in array.
Yes you can, but it's called a ternary.

Categories