Retrieving all usernames from a tweet in a PHP function - php

I have this function, which color every #username contained in a string
//color #username
function hashtag_links($string,$id_session) {
preg_match_all('/#(\w+)/',$string,$matches);
foreach ($matches[1] as $match) {
$string = str_replace("#$match", "<span class=color>#$match</span>", "$string");
}
return $string;
}
Everything is good while the usernames are different (#cat,#pencil,#scubadiving), but in case the username starts with the same letters (#cat,#caterpiller,#cattering), the functions only colors the repeated letters in this case (#cat), what to do?

Use preg_replace instead:
//color #username
function hashtag_links($string,$id_session) {
return preg_replace('/#(\w+)/', '<span class=color>#$1</span>', $string);
}

Hmmm... assuming you have a string like this:
$string='Hey there, folks! #bob, #kevin, #bobby, #keverino';
I would try something like:
preg_replace('/(#[A-Za-z0-9]+)/','<span style="color:pink;">\1</span>',$string);
Of course, I don't know what your usernames can contain, so you might have to adjust the regex.

Related

Get characters right after match in a foreach loop

On my site I want to detect if someone mentions a username in a comment, like so: what's up /u/username.
How exactly can I extract the characters following /u/ in a foreach loop?
Something like this:
if (strpos($commentString, '/u/') !== false) {
foreach /u/ in $commentString {
$username = the text immediately after /u/, stopping at anything that isn't a letter or a number
}
}
You can use preg_match_all with a regex of
/u/([a-z0-9]+)
to capture the usernames in the text. For example:
$text = "what's up /u/username have you seen /u/user21 today?";
preg_match_all('#/u/([a-z0-9]+)#i', $text, $matches);
foreach ($matches[1] as $user) {
echo "found user $user\n";
}
Output:
found user username
found user user21
Demo on 3v4l.org

Reduce whole text to some words in PHP

I have a problem. I need a "text reducer".
What i mean: I wrote to text area any words, for example: John Doe is good boy; Then i press some button, and it will get something like:
John Doe
So, it will only output defined worlds, like John Doe, or milk or something like that
Thanks for your help
If you know a black list of words you want to strip out, you could use the array replace function: str_replace:
http://php.net/manual/en/function.str-replace.php
like this:
$blacklist = ['ugly', 'bad', 'censored'];
$yourString = str_replace($yourString, $blacklist, '');
This will remove every word in your blacklist, from your input string.
If you need a whitelist based filter, you could use split your string into an array of words, and then use the array_filter function:
http://php.net/manual/en/function.preg-split.php
http://php.net/manual/en/function.array-filter.php
using something similar to:
$whitelist = ['good', 'neat', 'stuff'];
$tokens = preg_split("/[\s,]+/", $yourString);
$filtered = array_filter($tokens, function ($item) {
return in_array($token, $whitelist);
});
$finalString = implode(' ', $filtered);
Yes you can write a function in this case it receives an array as parameter, but if is static, you could save it on the function.
Also, this could work using a regex with preg_match, but i'll leave that for you.
Currently ignores case thanks to `strtolower', if you don't want to ignore the case, remove this function calls.
function printWhiteListedText($arrWhitelist, $str){
$auxStr = "";
foreach($arrWhitelist as $word){
if(strpos(strtolower($str), strtolower($word)) > -1){
$auxStr .= $word . ' ';
}
}
return trim($auxStr);
}
echo printWhiteListedText(['Hello', 'world'], 'hello this world is great');

php preg_match_all preg_replace array issue

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.

Multiple word search and match using RegEx

I've created a function that highlights single words within a string. It looks like this:
function highlight($input, $keywords) {
preg_match_all('~[\w\'"-]+~', $keywords, $match);
if(!$match) { return $input; }
$result = '~\\b(' . implode('|', $match[0]) . ')\\b~i';
return preg_replace($result, '<strong>$0</strong>', $input);
}
I need the function to work with an array of different words supporting a space in the search.
Example:
$search = array("this needs", "here", "can high-light the text");
$string = "This needs to be in here so that the search variable can high-light the text";
echo highlight($string, $search);
Here's what I have so far to amend the function to work how I need it to:
function highlight($input, $keywords) {
foreach($keywords as $keyword) {
preg_match_all('~[\w\'"-]+~', $keyword, $match);
if(!$match) { return $input; }
$result = '~\\b(' . implode('|', $match[0]) . ')\\b~i';
$output .= preg_replace($result, '<strong>$0</strong>', $keyword);
}
return $output;
}
Obviously this doesn't work and I'm not sure how to get this to work (regular expression are not my strong point).
Another point that may be a problem, how would the function deal with a multiple match? Such as $search = array("in here", "here so"); as the result would be something like:
This needs to be <strong>in <strong>here</strong> so</strong> that the search variable can high-light the text
But this needs to be:
This needs to be <strong>in here so</strong> that the search variable can high-light the text
Description
Can you take your array of terms and join them with a regex or statement | then nest them into a string. The \b's would help ensure you're not capturing word fragments.
\b(this needs|here|can high-light the text)\b
Then run this as a replacement using the capture group \1?
Example
I'm not real familiar with Python, but in PHP I'd do something like this:
<?php
$sourcestring="This needs to be in here so that the search variable can high-light the text";
echo preg_replace('/\b(this needs|here|can high-light the text)\b/i','<strong>\1</strong>',$sourcestring);
?>
$sourcestring after replacement:
<strong>This needs</strong> to be in <strong>here</strong> so that the search variable <strong>can high-light the text</strong>

PHP: How to strip tags in a string with certain attributes that have certain values?

I need a function like this:
function strip_tags_with_attribute_values($string, $allowedTags, $allowedAttribute, $allowedValue) {
...
}
And it must produce results like this:
$str = '<p class="bla">hello1</p><p class='bla2'>hello2</p>';
echo strip_tags_with_attribute_values($str, '<p>', 'class', 'bla');
Must produce:
hello1<p class='bla2'>hello2</p>
Why do I need this?
Users copy and paste text from word into the FCKEditor (in Drupal). I need to strip out all the style attributes from the p and span tags.
In your case, using something as simple as
$str = preg_replace("/<p class=\"(bla)\">(.+?)<\/p>/is", "$2", $str);
Should work. If you want arguments, you could try
function strip_tags_with_attribute_values($str, $tag, $att, $val)
{
$pat = "/<{$tag} {$att}=\"{$val}\">(.+?)<\/{$tag}>/is";
$str = preg_replace($pat, "$1", $str);
return $str;
}
Or something similar. This wont work correctly if a tag has multiple attributes. If that's your case, you'll probably want to try using a DOM object or XPATH to strip those out.

Categories