OSSN MENTION USERS COMPONENT
This component enables a user to mention other users in posts and comments by using the syntax @Full Name or conditionally @username and that will send the mentioned user a notification telling them that they were mentioned in a post or comment with a link to that item.
This can be used in conjunction with the Display Username component as of v1.2 if you want to display usernames and mention @username instead of display Full Name and mention @Full Name. It will dynamically switch based whether or not the Display Username component is installed and turned on. You can find more info on it here: https://www.opensource-socialnetwork.org/component/view/3065/display-username
When mentioning usernames using the Display Username component the exact casing must be used to match the user.
When mentioning user full names the casing DOES matter as that can help find uniqueness.
Mentions are not limited to the friends of the user, the entire user base can be mentioned
Multiple mentions can be done in a post or comment.
CHANGE LOG
-------------------1.9.1------------------
Added ability to parse off trailing '(apostrophe) and 's for use in plurals and ownership
Added recommended method and hooks from Z-Man
-------------------1.9--------------------
Added 'ossn:notifications:mention:post:created' to en locale
Added 'ossn:notifications:mention:comment:created' to en locale
Renamed init method from basic name to prevent potential collision with other components
POSSIBLE ENHANCEMENTS
No UI based on prototype having significant cons
?
Hey Z-Man,
I totally missed the part of your comment where you said we dont break till we get exactly one result. I dont mind this approach at all. They are pretty similar in design. My only issue is that for an installation that happens to have two users with the same name that get a mention, those users will never get notified because they will return 2 results at the finest. So I could do something like store off the previous results from the query and say IF at the finest level there is no matches, go back to last set of matches and notify those users. Thoughts? Or should I just stick with the reverse approach which handles this in v1.5. Im excited man, this thing is getting pretty polished for whoever wants to use it.
Bryce,
I don't have the time to really dive into it right now, but I can't see that flaw.
The concatenated 'firstlast' string contains "Bryce Alvord" here. In one case derived from firstname and lastname, in the other case from the first_name column only. So the HAVING firstlast LIKE "Bryce%" AND firstlast LIKE "%Alvord%"
condition is met perfectly, and that would mean we'll get 2 records and we can't simply break.
Z,
Check out the updates to 1.5. The difference between 1.4 and 1.5 is the reverse name lookup if you think that I was on to something with my last post about a potential flaw. Thanks!
Bryce
Z-Man,
The flaw I see in that approach is that if I have two users "Bryce Alvord" and "Bryce Alvord Jones" and my mention is "@Bryce Alvord Jones" then it would find "Bryce Alvord" as a first match and break and send the notification to "Bryce Alvord" and not "Bryce Alvord Jones". Does that make sense? Thats why I started with the full array of words and worked backwards so that it would find "Bryce Alvord Jones" first and break and send that person the notification. Let me know your thoughts because I might just be misunderstanding your approach ya know. Thanks again for your help in all of this, I really appreciate the guidance!
Hi Bryce,
maybe you misunderstood, but actually I simply wasn't able to 'like' anything but a warm bed yesterday night. I just had those new lines of code and posted them to let you know. Even more I think your CONCAT idea is much better than mine, but I wouldn't do that right to left shrinking, but a left to right expanding instead. I just played a with phpmyadmin, and we could start with a
SELECT guid, first_name, last_name, CONCAT(first_name, ' ', last_name) AS firstlast FROM `ossn_users` HAVING firstlast LIKE "1st_part%" AND firstlast LIKE "%2nd_part%"
Since we know we HAVE at least 2 names, this would reduce the number of results already dramatically in opposite of searching for the first name only. Thus, the following logic would be like:
if only one record found -> notify and break
else run a new query with AND firstlast LIKE "%3rd_part%"
... and so on
So (having your 5 selectors in mind) we would have a maximum of 4 queries this way.
Nevermind Z-man, I made some modifications (small) to your code to add in the functionality for the Display Username component and both on and off, it functions well. Great help, thanks! I have uploaded what I believe is going to be a stable version but of course I will address any bugs that might come up.
Hey thanks for the reply Z Man, I'd say thats pretty late! So Im curious, with your latest post does that mean you dont like the approach or reverse searching and comparing using the CONCAT function? Totally fine if you didnt like beta1.3. I did extensive testing on it and it worked great but Im never opposed to refactoring. Did you test yours with a firstname with 2 words and a lastname with 2 words or potentially 1 and 3? Just curious how much I need to test on this solution you have.
Sorry, Bryce ... a little late ... it's 2:00 here ... too tired ;)
got a new approach in the meantime ... a mixture of your first code but matching the first part of the first name in order to reduce the resulting records. Had my doubts about the punctuation part BTW, because we might have names like Martin B. Meyer. And with your code we dont need it. So things are getting much simpler ...
while (($start = strpos($message, '@')) !== false) { // find substring starting after '@'
$substr = substr($message, $start + 1);
$substr_words = explode(" ", $substr); // convert to array of separate words
if(($word_count = count($substr_words)) >= 2) {
// build your own query -> see OssnDatabase->select() ...
$db = new OssnDatabase;
$query['params'] = array(
'guid',
'first_name',
'last_name'
);
$query['from'] = 'ossn_users';
$query['wheres'] = array(
"first_name LIKE '{$substr_words[0]}%'",
);
$members = $db->select($query, true);
if($members) {
// first part of firstname is matching
error_log(ossn_dump($members));
// maybe more than one is matching - so let's loop
foreach($members as $member) {
$real_full_name = $member->first_name . ' ' . $member->last_name;
error_log('substring [' . $substr . ']');
error_log('fullname [' . $real_full_name . ']');
if(mb_strpos($substr, $real_full_name) !== false) {
error_log('Notify!');
// found one!
break;
}
}
}
}
$message = $substr; // try to find another mention in remaining part of original message string
}
Z,
Can you check out my changes and see what you make of them? I kind of did what we talked about however I took a little different approach with the assumption no name is longer than 5 distinct words.
If my post says "@Bryce Alvord Jones is super nerdy and tells Dad jokes" then I grab the 5 words after the @ and work in reverse querying the db for a match to the CONCAT(firstname, ' ', lastname) and then pop the end off the array and search again hoping for a match.
In the DB assume my user is named Bryce (first_name) and Alvord Jones (last_name).
CONCAT(first_name, ' ', last_name) = 'Bryce Alvord Jones'
CONCAT(first_name, ' ', last_name) !== 'Bryce Alvord Jones is super' (5 words)
CONCAT(first_name, ' ', last_name) !== 'Bryce Alvord Jones is' (4 words)
CONCAT(first_name, ' ', last_name) == 'Bryce Alvord Jones' (3 words)
Break; We have a match
Does that make sense? That way Im starting with the most complicated version of the name and working backwards
Well,
I think the most important part is to delete those notification records which are owned by the deleted originator.
This way, the mentioned member will receive no notification any longer which are pointing to a post/comment which isn't available any more.
But to make it completely correct, you should also delete those records if the mentioned member(s) has(ve) been deleted because then they don't make no sense any more.