Combine code that finds mentions into one place and add hook points

Combined the code that finds mentions of other profiles into one place.

common_find_mentions() finds mentions and calls hooks to allow
supplemental syntax for mentions (like OStatus).

common_linkify_mentions() links mentions.

common_linkify_mention() links a mention.

Notice::saveReplies() now uses common_find_mentions() instead of
trying to parse everything again.
This commit is contained in:
Evan Prodromou
2010-02-21 16:20:30 -05:00
parent 4209082677
commit ab3db8c899
3 changed files with 184 additions and 119 deletions

View File

@@ -426,13 +426,148 @@ function common_render_content($text, $notice)
{
$r = common_render_text($text);
$id = $notice->profile_id;
$r = preg_replace('/(^|\s+)@(['.NICKNAME_FMT.']{1,64})/e', "'\\1@'.common_at_link($id, '\\2')", $r);
$r = preg_replace('/^T ([A-Z0-9]{1,64}) /e', "'T '.common_at_link($id, '\\1').' '", $r);
$r = preg_replace('/(^|[\s\.\,\:\;]+)@#([A-Za-z0-9]{1,64})/e', "'\\1@#'.common_at_hash_link($id, '\\2')", $r);
$r = common_linkify_mentions($id, $r);
$r = preg_replace('/(^|[\s\.\,\:\;]+)!([A-Za-z0-9]{1,64})/e', "'\\1!'.common_group_link($id, '\\2')", $r);
return $r;
}
function common_linkify_mentions($profile_id, $text)
{
$mentions = common_find_mentions($profile_id, $text);
// We need to go through in reverse order by position,
// so our positions stay valid despite our fudging with the
// string!
$points = array();
foreach ($mentions as $mention)
{
$points[$mention['position']] = $mention;
}
krsort($points);
foreach ($points as $position => $mention) {
$linkText = common_linkify_mention($mention);
$text = substr_replace($text, $linkText, $position, mb_strlen($mention['text']));
}
return $text;
}
function common_linkify_mention($mention)
{
$output = null;
if (Event::handle('StartLinkifyMention', array($mention, &$output))) {
$xs = new XMLStringer(false);
$attrs = array('href' => $mention['url'],
'class' => 'url');
if (!empty($mention['title'])) {
$attrs['title'] = $mention['title'];
}
$xs->elementStart('span', 'vcard');
$xs->elementStart('a', $attrs);
$xs->element('span', 'fn nickname', $mention['text']);
$xs->elementEnd('a');
$xs->elementEnd('span');
$output = $xs->getString();
Event::handle('EndLinkifyMention', array($mention, &$output));
}
return $output;
}
function common_find_mentions($profile_id, $text)
{
$mentions = array();
$sender = Profile::staticGet('id', $profile_id);
if (empty($sender)) {
return $mentions;
}
if (Event::handle('StartFindMentions', array($sender, $text, &$mentions))) {
preg_match_all('/^T ([A-Z0-9]{1,64}) /',
$text,
$tmatches,
PREG_OFFSET_CAPTURE);
preg_match_all('/(?:^|\s+)@(['.NICKNAME_FMT.']{1,64})/',
$text,
$atmatches,
PREG_OFFSET_CAPTURE);
$matches = array_merge($tmatches[1], $atmatches[1]);
foreach ($matches as $match) {
$nickname = common_canonical_nickname($match[0]);
$mentioned = common_relative_profile($sender, $nickname);
if (!empty($mentioned)) {
$user = User::staticGet('id', $mentioned->id);
if ($user) {
$url = common_local_url('userbyid', array('id' => $user->id));
} else {
$url = $mentioned->profileurl;
}
$mention = array('mentioned' => array($mentioned),
'text' => $match[0],
'position' => $match[1],
'url' => $url);
if (!empty($mentioned->fullname)) {
$mention['title'] = $mentioned->fullname;
}
$mentions[] = $mention;
}
}
// @#tag => mention of all subscriptions tagged 'tag'
preg_match_all('/(?:^|[\s\.\,\:\;]+)@#([\pL\pN_\-\.]{1,64})/',
$text,
$hmatches,
PREG_OFFSET_CAPTURE);
foreach ($hmatches[1] as $hmatch) {
$tag = common_canonical_tag($hmatch[0]);
$tagged = Profile_tag::getTagged($sender->id, $tag);
$url = common_local_url('subscriptions',
array('nickname' => $sender->nickname,
'tag' => $tag));
$mentions[] = array('mentioned' => $tagged,
'text' => $hmatch[0],
'position' => $hmatch[1],
'url' => $url);
}
Event::handle('EndFindMentions', array($sender, $text, &$mentions));
}
return $mentions;
}
function common_render_text($text)
{
$r = htmlspecialchars($text);
@@ -663,37 +798,6 @@ function common_valid_profile_tag($str)
return preg_match('/^[A-Za-z0-9_\-\.]{1,64}$/', $str);
}
function common_at_link($sender_id, $nickname)
{
$sender = Profile::staticGet($sender_id);
if (!$sender) {
return $nickname;
}
$recipient = common_relative_profile($sender, common_canonical_nickname($nickname));
if ($recipient) {
$user = User::staticGet('id', $recipient->id);
if ($user) {
$url = common_local_url('userbyid', array('id' => $user->id));
} else {
$url = $recipient->profileurl;
}
$xs = new XMLStringer(false);
$attrs = array('href' => $url,
'class' => 'url');
if (!empty($recipient->fullname)) {
$attrs['title'] = $recipient->fullname . ' (' . $recipient->nickname . ')';
}
$xs->elementStart('span', 'vcard');
$xs->elementStart('a', $attrs);
$xs->element('span', 'fn nickname', $nickname);
$xs->elementEnd('a');
$xs->elementEnd('span');
return $xs->getString();
} else {
return $nickname;
}
}
function common_group_link($sender_id, $nickname)
{
$sender = Profile::staticGet($sender_id);
@@ -716,29 +820,6 @@ function common_group_link($sender_id, $nickname)
}
}
function common_at_hash_link($sender_id, $tag)
{
$user = User::staticGet($sender_id);
if (!$user) {
return $tag;
}
$tagged = Profile_tag::getTagged($user->id, common_canonical_tag($tag));
if ($tagged) {
$url = common_local_url('subscriptions',
array('nickname' => $user->nickname,
'tag' => $tag));
$xs = new XMLStringer();
$xs->elementStart('span', 'tag');
$xs->element('a', array('href' => $url,
'rel' => $tag),
$tag);
$xs->elementEnd('span');
return $xs->getString();
} else {
return $tag;
}
}
function common_relative_profile($sender, $nickname, $dt=null)
{
// Try to find profiles this profile is subscribed to that have this nickname