git.gnu.io has moved to IP address 209.51.188.249 -- please double check where you are logging in.

Commit 9b663369 authored by mmn's avatar mmn

Group discovery from text functions polished

Also removed the entirely unused saveGroups function.

Now avoiding multiGet and using listFind in Profile->getGroups()
so we don't have to deal with ArrayWrapper.
parent f8b49e69
......@@ -137,12 +137,11 @@ class UsergroupsAction extends ProfileAction
$groups = $this->user->getGroups($offset, $limit);
if ($groups) {
if ($groups instanceof User_group) {
$gl = new GroupList($groups, $this->user, $this);
$cnt = $gl->show();
if (0 == $cnt) {
$this->showEmptyListMessage();
}
} else {
$this->showEmptyListMessage();
}
$this->pagination($this->page > 1, $cnt > GROUPS_PER_PAGE,
......
......@@ -410,9 +410,8 @@ class Notice extends Managed_DataObject
$notice->url = $url;
// Get the groups here so we can figure out replies and such
if (!isset($groups)) {
$groups = self::groupsFromText($notice->content, $profile);
$groups = User_group::idsFromText($notice->content, $profile);
}
$reply = null;
......@@ -1154,7 +1153,7 @@ class Notice extends Managed_DataObject
$groups = array();
foreach (array_unique($group_ids) as $id) {
$group = User_group::getKV('id', $id);
if ($group) {
if ($group instanceof User_group) {
common_log(LOG_ERR, "Local delivery to group id $id, $group->nickname");
$result = $this->addToGroupInbox($group);
if (!$result) {
......@@ -1181,48 +1180,7 @@ class Notice extends Managed_DataObject
return $groups;
}
/**
* Parse !group delivery and record targets into group_inbox.
* @return array of Group objects
*/
function saveGroups()
{
// Don't save groups for repeats
if (!empty($this->repeat_of)) {
return array();
}
$profile = $this->getProfile();
$groups = self::groupsFromText($this->content, $profile);
/* Add them to the database */
foreach ($groups as $group) {
/* XXX: remote groups. */
if (empty($group)) {
continue;
}
if ($profile->isMember($group)) {
$result = $this->addToGroupInbox($group);
if (!$result) {
common_log_db_error($gi, 'INSERT', __FILE__);
}
$groups[] = clone($group);
}
}
return $groups;
}
function addToGroupInbox($group)
function addToGroupInbox(User_group $group)
{
$gi = Group_inbox::pkeyGet(array('group_id' => $group->id,
'notice_id' => $this->id));
......@@ -1445,7 +1403,7 @@ class Notice extends Managed_DataObject
/**
* Pull list of groups this notice needs to be delivered to,
* as previously recorded by saveGroups() or saveKnownGroups().
* as previously recorded by saveKnownGroups().
*
* @return array of Group objects
*/
......@@ -2500,29 +2458,6 @@ class Notice extends Managed_DataObject
return false;
}
static function groupsFromText($text, $profile)
{
$groups = array();
/* extract all !group */
$count = preg_match_all('/(?:^|\s)!(' . Nickname::DISPLAY_FMT . ')/',
strtolower($text),
$match);
if (!$count) {
return $groups;
}
foreach (array_unique($match[1]) as $nickname) {
$group = User_group::getForNickname($nickname, $profile);
if ($group instanceof User_group && $profile->isMember($group)) {
$groups[] = $group->id;
}
}
return $groups;
}
public function getParent()
{
$parent = Notice::getKV('id', $this->reply_to);
......
......@@ -221,9 +221,8 @@ class Profile extends Managed_DataObject
function isMember($group)
{
$groups = $this->getGroups(0, null);
$gs = $groups->fetchAll();
foreach ($gs as $g) {
if ($group->id == $g->id) {
while ($groups instanceof User_group && $groups->fetch()) {
if ($groups->id == $group->id) {
return true;
}
}
......@@ -272,7 +271,18 @@ class Profile extends Managed_DataObject
$ids = array_slice($ids, $offset, $limit);
}
return User_group::multiGet('id', $ids);
try {
return User_group::listFind('id', $ids);
} catch (NoResultException $e) {
return null; // throw exception when we handle it everywhere
}
}
function getGroupCount() {
$groups = $this->getGroups(0, null);
return $groups instanceof User_group
? $groups->N
: 0;
}
function isTagged($peopletag)
......
......@@ -418,14 +418,14 @@ class User_group extends Managed_DataObject
return true;
}
static function getForNickname($nickname, $profile=null)
static function getForNickname($nickname, Profile $profile=null)
{
$nickname = Nickname::normalize($nickname);
// Are there any matching remote groups this profile's in?
if ($profile) {
if ($profile instanceof Profile) {
$group = $profile->getGroups(0, null);
while ($group->fetch()) {
while ($group instanceof User_group && $group->fetch()) {
if ($group->nickname == $nickname) {
// @fixme is this the best way?
return clone($group);
......@@ -434,13 +434,12 @@ class User_group extends Managed_DataObject
}
// If not, check local groups.
$group = Local_group::getKV('nickname', $nickname);
if (!empty($group)) {
if ($group instanceof Local_group) {
return User_group::getKV('id', $group->group_id);
}
$alias = Group_alias::getKV('alias', $nickname);
if (!empty($alias)) {
if ($alias instanceof Group_alias) {
return User_group::getKV('id', $alias->group_id);
}
return null;
......@@ -822,4 +821,37 @@ class User_group extends Managed_DataObject
return ($this->join_policy == self::JOIN_POLICY_MODERATE &&
$this->force_scope == 1);
}
static function groupsFromText($text, Profile $profile)
{
$groups = array();
/* extract all !group */
$count = preg_match_all('/(?:^|\s)!(' . Nickname::DISPLAY_FMT . ')/',
strtolower($text),
$match);
if (!$count) {
return $groups;
}
foreach (array_unique($match[1]) as $nickname) {
$group = self::getForNickname($nickname, $profile);
if ($group instanceof User_group && $profile->isMember($group)) {
$groups[] = clone($group);
}
}
return $groups;
}
static function idsFromText($text, Profile $profile)
{
$ids = array();
$groups = self::groupsFromText($text, $profile);
foreach ($groups as $group) {
$ids[$group->id] = true;
}
return array_keys($ids);
}
}
......@@ -225,7 +225,7 @@ class ApiAction extends Action
}
$twitter_user['profile_image_url_original'] = $origurl;
$twitter_user['groups_count'] = $profile->getGroups(0, null)->N;
$twitter_user['groups_count'] = $profile->getGroupCount();
foreach (array('linkcolor', 'backgroundcolor') as $key) {
$twitter_user[$key] = Profile_prefs::getConfigData($profile, 'theme', $key);
}
......
......@@ -980,7 +980,7 @@ class GroupsCommand extends Command
{
$group = $this->user->getGroups();
$groups=array();
while ($group->fetch()) {
while ($group instanceof User_group && $group->fetch()) {
$groups[]=$group->nickname;
}
if(count($groups)==0){
......
......@@ -58,7 +58,7 @@ class GroupsNav extends MoreMenu
function haveGroups()
{
return (!empty($this->groups) && ($this->groups->N > 0));
return ($this->groups instanceof User_group && $this->groups->N > 0);
}
function tag()
......@@ -70,7 +70,7 @@ class GroupsNav extends MoreMenu
{
$items = array();
while ($this->groups->fetch()) {
while ($this->groups instanceof User_group && $this->groups->fetch()) {
$items[] = array('placeholder',
array('nickname' => $this->groups->nickname,
'mainpage' => $this->groups->homeUrl()),
......
......@@ -270,13 +270,12 @@ class ProfileAction extends Action
$this->text($this->profile->getGroups(0, null)->N);
$this->elementEnd('h2');
if ($groups) {
if ($groups instanceof User_group) {
$gml = new GroupMiniList($groups, $this->profile, $this);
$cnt = $gml->show();
if ($cnt == 0) {
// TRANS: Text for user user group membership statistics if user is not a member of any group.
$this->element('p', null, _('(None)'));
}
} else {
// TRANS: Text for user user group membership statistics if user is not a member of any group.
$this->element('p', null, _('(None)'));
}
Event::handle('EndShowGroupsMiniList', array($this));
......
......@@ -94,7 +94,7 @@ class ToSelector extends Widget
$groups = $this->user->getGroups();
while ($groups->fetch()) {
while ($groups instanceof User_group && $groups->fetch()) {
$value = 'group:'.$groups->id;
if (($this->to instanceof User_group) && $this->to->id == $groups->id) {
$default = $value;
......
......@@ -320,7 +320,7 @@ function common_set_user($user)
} else if (is_string($user)) {
$nickname = $user;
$user = User::getKV('nickname', $nickname);
} else if (!($user instanceof User)) {
} else if (!$user instanceof User) {
return false;
}
......@@ -433,7 +433,7 @@ function common_remembered_user()
$user = User::getKV('id', $rm->user_id);
if (!$user) {
if (!$user instanceof User) {
common_log(LOG_WARNING, 'No such user for rememberme: ' . $rm->user_id);
common_forgetme();
return null;
......@@ -488,8 +488,8 @@ function common_current_user()
common_ensure_session();
$id = isset($_SESSION['userid']) ? $_SESSION['userid'] : false;
if ($id) {
$user = User::getKV($id);
if ($user) {
$user = User::getKV('id', $id);
if ($user instanceof User) {
$_cur = $user;
return $_cur;
}
......@@ -584,13 +584,10 @@ function common_canonical_email($email)
* @param Notice $notice in whose context we're working
* @return string partially rendered HTML
*/
function common_render_content($text, $notice)
function common_render_content($text, Notice $notice)
{
$r = common_render_text($text);
$id = $notice->profile_id;
$r = common_linkify_mentions($r, $notice);
$r = preg_replace_callback('/(^|[\s\.\,\:\;]+)!(' . Nickname::DISPLAY_FMT . ')/',
function ($m) { return "{$m[1]}!".common_group_link($id, $m[2]); }, $r);
return $r;
}
......@@ -677,35 +674,39 @@ function common_linkify_mention($mention)
*/
function common_find_mentions($text, $notice)
{
$mentions = array();
$sender = Profile::getKV('id', $notice->profile_id);
if (empty($sender)) {
return $mentions;
try {
$sender = Profile::getKV('id', $notice->profile_id);
} catch (NoProfileException $e) {
return array();
}
$mentions = array();
if (Event::handle('StartFindMentions', array($sender, $text, &$mentions))) {
// Get the context of the original notice, if any
$originalAuthor = null;
$originalNotice = null;
$originalMentions = array();
$origAuthor = null;
$origNotice = null;
$origMentions = array();
// Is it a reply?
if (!empty($notice) && !empty($notice->reply_to)) {
$originalNotice = Notice::getKV('id', $notice->reply_to);
if (!empty($originalNotice)) {
$originalAuthor = Profile::getKV('id', $originalNotice->profile_id);
if ($notice instanceof Notice) {
try {
$origNotice = $notice->getParent();
$origAuthor = $origNotice->getProfile();
$ids = $originalNotice->getReplies();
$ids = $origNotice->getReplies();
foreach ($ids as $id) {
$repliedTo = Profile::getKV('id', $id);
if (!empty($repliedTo)) {
$originalMentions[$repliedTo->nickname] = $repliedTo;
if ($repliedTo instanceof Profile) {
$origMentions[$repliedTo->nickname] = $repliedTo;
}
}
} catch (NoProfileException $e) {
common_log(LOG_WARNING, sprintf('Notice %d author profile id %d does not exist', $origNotice->id, $origNotice->profile_id));
} catch (ServerException $e) {
common_log(LOG_WARNING, __METHOD__ . ' got exception: ' . $e->getMessage());
}
}
......@@ -723,19 +724,19 @@ function common_find_mentions($text, $notice)
// Start with conversation context, then go to
// sender context.
if (!empty($originalAuthor) && $originalAuthor->nickname == $nickname) {
$mentioned = $originalAuthor;
} else if (!empty($originalMentions) &&
array_key_exists($nickname, $originalMentions)) {
$mentioned = $originalMentions[$nickname];
if ($origAuthor instanceof Profile && $origAuthor->nickname == $nickname) {
$mentioned = $origAuthor;
} else if (!empty($origMentions) &&
array_key_exists($nickname, $origMentions)) {
$mentioned = $origMentions[$nickname];
} else {
$mentioned = common_relative_profile($sender, $nickname);
}
if (!empty($mentioned)) {
if ($mentioned instanceof Profile) {
$user = User::getKV('id', $mentioned->id);
if ($user) {
if ($user instanceof User) {
$url = common_local_url('userbyid', array('id' => $user->id));
} else {
$url = $mentioned->profileurl;
......@@ -757,26 +758,42 @@ function common_find_mentions($text, $notice)
// @#tag => mention of all subscriptions tagged 'tag'
preg_match_all('/(?:^|[\s\.\,\:\;]+)@#([\pL\pN_\-\.]{1,64})/',
$text,
$hmatches,
PREG_OFFSET_CAPTURE);
$text, $hmatches, PREG_OFFSET_CAPTURE);
foreach ($hmatches[1] as $hmatch) {
$tag = common_canonical_tag($hmatch[0]);
$plist = Profile_list::getByTaggerAndTag($sender->id, $tag);
if (!empty($plist) && !$plist->private) {
$tagged = $sender->getTaggedSubscribers($tag);
if (!$plist instanceof Profile_list || $plist->private) {
continue;
}
$tagged = $sender->getTaggedSubscribers($tag);
$url = common_local_url('showprofiletag',
array('tagger' => $sender->nickname,
'tag' => $tag));
$url = common_local_url('showprofiletag',
array('tagger' => $sender->nickname,
'tag' => $tag));
$mentions[] = array('mentioned' => $tagged,
'text' => $hmatch[0],
'position' => $hmatch[1],
'url' => $url);
}
$mentions[] = array('mentioned' => $tagged,
'text' => $hmatch[0],
'position' => $hmatch[1],
'url' => $url);
preg_match_all('/(?:^|[\s\.\,\:\;]+)!(' . Nickname::DISPLAY_FMT . ')/',
$text, $hmatches, PREG_OFFSET_CAPTURE);
foreach ($hmatches[1] as $hmatch) {
$nickname = Nickname::normalize($hmatch[0]);
$group = User_group::getForNickname($nickname, $sender);
if (!$group instanceof User_group || !$sender->isMember($group)) {
continue;
}
$profile = $group->getProfile();
$mentions[] = array('mentioned' => $profile,
'text' => $hmatch[0],
'position' => $hmatch[1],
'url' => $group->permalink,
'title' => $group->getFancyName());
}
Event::handle('EndFindMentions', array($sender, $text, &$mentions));
......@@ -1146,35 +1163,6 @@ function common_valid_profile_tag($str)
return preg_match('/^[A-Za-z0-9_\-\.]{1,64}$/', $str);
}
/**
*
* @param <type> $sender_id
* @param <type> $nickname
* @return <type>
* @access private
*/
function common_group_link($sender_id, $nickname)
{
$sender = Profile::getKV($sender_id);
$group = User_group::getForNickname($nickname, $sender);
if ($sender && $group && $sender->isMember($group)) {
$attrs = array('href' => $group->permalink(),
'class' => 'url');
if (!empty($group->fullname)) {
$attrs['title'] = $group->getFancyName();
}
$xs = new XMLStringer();
$xs->elementStart('span', 'vcard');
$xs->elementStart('a', $attrs);
$xs->element('span', 'fn nickname group', $nickname);
$xs->elementEnd('a');
$xs->elementEnd('span');
return $xs->getString();
} else {
return $nickname;
}
}
/**
* Resolve an ambiguous profile nickname reference, checking in following order:
* - profiles that $sender subscribes to
......@@ -1222,7 +1210,7 @@ function common_relative_profile($sender, $nickname, $dt=null)
return $recipient;
}
// If this is a local user, try to find a local user with that nickname.
$sender = User::getKV($sender->id);
$sender = User::getKV('id', $sender->id);
if ($sender instanceof User) {
$recipient_user = User::getKV('nickname', $nickname);
if ($recipient_user instanceof User) {
......@@ -2020,8 +2008,8 @@ function common_profile_uri($profile)
if (!empty($profile)) {
if (Event::handle('StartCommonProfileURI', array($profile, &$uri))) {
$user = User::getKV($profile->id);
if (!empty($user)) {
$user = User::getKV('id', $profile->id);
if ($user instanceof User) {
$uri = $user->uri;
}
Event::handle('EndCommonProfileURI', array($profile, &$uri));
......
......@@ -337,7 +337,7 @@ class OStatusPlugin extends Plugin
* @param array &$mention in/out param: set of found mentions
* @return boolean hook return value
*/
function onEndFindMentions($sender, $text, &$mentions)
function onEndFindMentions(Profile $sender, $text, &$mentions)
{
$matches = array();
......
......@@ -163,7 +163,7 @@ function newNotice($i, $tagmax)
if ($in_group == 0) {
$groups = $user->getGroups();
if ($groups->N > 0) {
if ($groups instanceof User_group) {
$gval = rand(0, $groups->N - 1);
$groups->fetch(); // go to 0th
for ($i = 0; $i < $gval; $i++) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment