static function setTags($tagger, $tagged, $newtags) { $newtags = array_unique($newtags); $oldtags = Profile_tag::getTags($tagger, $tagged); # Delete stuff that's old that not in new $to_delete = array_diff($oldtags, $newtags); # Insert stuff that's in new and not in old $to_insert = array_diff($newtags, $oldtags); $profile_tag = new Profile_tag(); $profile_tag->tagger = $tagger; $profile_tag->tagged = $tagged; $profile_tag->query('BEGIN'); foreach ($to_delete as $deltag) { $profile_tag->tag = $deltag; $result = $profile_tag->delete(); if (!$result) { common_log_db_error($profile_tag, 'DELETE', __FILE__); return false; } } foreach ($to_insert as $instag) { $profile_tag->tag = $instag; $result = $profile_tag->insert(); if (!$result) { common_log_db_error($profile_tag, 'INSERT', __FILE__); return false; } } $profile_tag->query('COMMIT'); return true; }
function showTags() { $tags = Profile_tag::getTags($this->owner->id, $this->profile->id); $this->out->elementStart('dl', 'entity_tags'); $this->out->elementStart('dt'); if ($this->isOwn()) { $this->out->element('a', array('href' => common_local_url('tagother', array('id' => $this->profile->id))), _('Tags')); } else { $this->out->text(_('Tags')); } $this->out->elementEnd('dt'); $this->out->elementStart('dd'); if ($tags) { $this->out->elementStart('ul', 'tags xoxo'); foreach ($tags as $tag) { $this->out->elementStart('li'); $this->out->element('span', 'mark_hash', '#'); $this->out->element('a', array('rel' => 'tag', 'href' => common_local_url($this->action->trimmed('action'), array('nickname' => $this->owner->nickname, 'tag' => $tag))), $tag); $this->out->elementEnd('li'); } $this->out->elementEnd('ul'); } else { $this->out->text(_('(none)')); } $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); }
/** * Remove a user from a list (untag someone) * * @return boolean success */ function handleDelete() { if ($this->auth_user->id != $this->list->tagger) { // TRANS: Client error displayed when trying to remove members from a list without having the right to do so. $this->clientError(_('You are not allowed to remove members from this list.'), 401); } if (!$this->target instanceof Profile) { // TRANS: Client error displayed when trying to modify list members without specifying them. $this->clientError(_('You must specify a member.')); } $args = array('tagger' => $this->auth_user->id, 'tagged' => $this->target->id, 'tag' => $this->list->tag); $ptag = Profile_tag::pkeyGet($args); if (empty($ptag)) { // TRANS: Client error displayed when trying to remove a list member that is not part of a list. $this->clientError(_('The user you are trying to remove from the list is not a member.')); } if (!$ptag->delete()) { // TRANS: Client error displayed when an unknown error occurs viewing list members. $this->clientError(_('An error occured.'), 500); } switch ($this->format) { case 'xml': $this->showSingleXmlList($this->list); break; case 'json': $this->showSingleJsonList($this->list); break; default: // TRANS: Client error displayed when coming across a non-supported API method. $this->clientError(_('API method not found.'), 404); } return true; }
/** * Remove a user from a list (untag someone) * * @return boolean success */ function handleDelete() { if ($this->auth_user->id != $this->list->tagger) { $this->clientError(_('You are not allowed to remove members from this list.'), 401, $this->format); return false; } if ($this->user === false) { $this->clientError(_('You must specify a member.'), 400, $this->format); return false; } $args = array('tagger' => $this->auth_user->id, 'tagged' => $this->user->id, 'tag' => $this->list->tag); $ptag = Profile_tag::pkeyGet($args); if (empty($ptag)) { $this->clientError(_('The user you are trying to remove from the list is not a member.'), 400, $this->format); return false; } $result = $ptag->delete(); if (empty($result)) { $this->clientError(_('An error occured.'), 500, $this->format); return false; } switch ($this->format) { case 'xml': $this->showSingleXmlList($this->list); break; case 'json': $this->showSingleJsonList($this->list); break; default: $this->clientError(_('API method not found.'), 404, $this->format); return false; break; } return true; }
function showTags() { $tags = Profile_tag::getTags($this->owner->id, $this->profile->id); $this->out->elementStart('dl', 'entity_tags'); $this->out->elementStart('dt'); if ($this->isOwn()) { $this->out->element('a', array('href' => common_local_url('tagother', array('id' => $this->profile->id))), _('Tags')); } else { $this->out->text(_('Tags')); } $this->out->elementEnd('dt'); $this->out->elementStart('dd'); if ($tags) { $this->out->elementStart('ul', 'tags xoxo'); foreach ($tags as $tag) { $this->out->elementStart('li'); // Avoid space by using raw output. $pt = '<span class="mark_hash">#</span><a rel="tag" href="' . common_local_url($this->action->trimmed('action'), array('nickname' => $this->owner->nickname, 'tag' => $tag)) . '">' . $tag . '</a>'; $this->out->raw($pt); $this->out->elementEnd('li'); } $this->out->elementEnd('ul'); } else { $this->out->text(_('(None)')); } $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); }
function __construct($out, $tagger, $tagged) { parent::__construct($out); $this->user = common_current_user(); $this->tag = Profile_tag::getTags($tagger->id, $tagged->id, $this->user); $this->tagger = $tagger; $this->tagged = $tagged; }
/** * Handle the request * * @return boolean success flag */ function handle($args) { parent::handle($args); $arr = array('tagger' => $this->list->tagger, 'tag' => $this->list->tag, 'tagged' => $this->user->id); $ptag = Profile_tag::pkeyGet($arr); if (empty($ptag)) { $this->clientError(_('The specified user is not a member of this list.'), 400, $this->format); } $user = $this->twitterUserArray($this->user->getProfile(), true); switch ($this->format) { case 'xml': $this->showTwitterXmlUser($user, 'user', true); break; case 'json': $this->showSingleJsonUser($user); break; default: $this->clientError(_('API method not found.'), 404, $this->format); break; } return true; }
/** * Handle the request * * @return boolean success flag */ protected function handle() { parent::handle(); $arr = array('tagger' => $this->list->tagger, 'tag' => $this->list->tag, 'tagged' => $this->target->id); $ptag = Profile_tag::pkeyGet($arr); if (empty($ptag)) { // TRANS: Client error displayed when referring to a non-list member. $this->clientError(_('The specified user is not a member of this list.')); } $user = $this->twitterUserArray($this->target, true); switch ($this->format) { case 'xml': $this->showTwitterXmlUser($user, 'user', true); break; case 'json': $this->showSingleJsonUser($user); break; default: // TRANS: Client error displayed when coming across a non-supported API method. $this->clientError(_('API method not found.'), 404); } return true; }
function handle($channel) { $profile = $this->getProfile($this->other); $cur = $this->user->getProfile(); if (!$profile) { // TRANS: Client error displayed trying to perform an action related to a non-existing profile. $channel->error($cur, _('No such profile.')); return; } if (!$cur->canTag($profile)) { // TRANS: Error displayed when trying to tag a user that cannot be tagged. $channel->error($cur, _('You cannot tag this user.')); return; } $tags = array_map('common_canonical_tag', preg_split('/[\\s,]+/', $this->tags)); foreach ($tags as $tag) { if (!common_valid_profile_tag($tag)) { // TRANS: Error displayed if a given tag is invalid. // TRANS: %s is the invalid tag. $channel->error($cur, sprintf(_('Invalid tag: "%s"'), $tag)); return; } } try { foreach ($tags as $tag) { Profile_tag::unTag($cur->id, $profile->id, $tag); } } catch (Exception $e) { // TRANS: Error displayed if untagging a user fails. // TRANS: %1$s is the untagged user, %2$s is the error message (no punctuation). $channel->error($cur, sprintf(_('Error untagging %1$s: %2$s'), $profile->nickname, $e->getMessage())); return; } // TRANS: Succes message displayed if untagging a user succeeds. // TRANS: %1$s is the untagged user's nickname, %2$s is a list of tags. // TRANS: Plural is decided based on the number of tags removed (not part of message). $channel->output($cur, sprintf(_m('The following tag was removed from user %1$s: %2$s.', 'The following tags were removed from user %1$s: %2$s.', count($tags)), $profile->nickname, implode(_(', '), $tags))); }
function showProfile() { $this->out->elementStart('li', array('class' => 'profile', 'id' => 'profile-' . $this->profile->id)); $user = common_current_user(); $is_own = !is_null($user) && isset($this->owner) && $user->id === $this->owner->id; $this->out->elementStart('div', 'entity_profile vcard'); $avatar = $this->profile->getAvatar(AVATAR_STREAM_SIZE); $this->out->elementStart('a', array('href' => $this->profile->profileurl, 'class' => 'url')); $this->out->element('img', array('src' => $avatar ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE), 'class' => 'photo avatar', 'width' => AVATAR_STREAM_SIZE, 'height' => AVATAR_STREAM_SIZE, 'alt' => $this->profile->fullname ? $this->profile->fullname : $this->profile->nickname)); $hasFN = $this->profile->fullname !== '' ? 'nickname' : 'fn nickname'; $this->out->elementStart('span', $hasFN); $this->out->raw($this->highlight($this->profile->nickname)); $this->out->elementEnd('span'); $this->out->elementEnd('a'); if (!empty($this->profile->fullname)) { $this->out->elementStart('dl', 'entity_fn'); $this->out->element('dt', null, 'Full name'); $this->out->elementStart('dd'); $this->out->elementStart('span', 'fn'); $this->out->raw($this->highlight($this->profile->fullname)); $this->out->elementEnd('span'); $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } if (!empty($this->profile->location)) { $this->out->elementStart('dl', 'entity_location'); $this->out->element('dt', null, _('Location')); $this->out->elementStart('dd', 'label'); $this->out->raw($this->highlight($this->profile->location)); $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } if (!empty($this->profile->homepage)) { $this->out->elementStart('dl', 'entity_url'); $this->out->element('dt', null, _('URL')); $this->out->elementStart('dd'); $this->out->elementStart('a', array('href' => $this->profile->homepage, 'class' => 'url')); $this->out->raw($this->highlight($this->profile->homepage)); $this->out->elementEnd('a'); $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } if (!empty($this->profile->bio)) { $this->out->elementStart('dl', 'entity_note'); $this->out->element('dt', null, _('Note')); $this->out->elementStart('dd', 'note'); $this->out->raw($this->highlight($this->profile->bio)); $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } # If we're on a list with an owner (subscriptions or subscribers)... if ($this->owner) { # Get tags $tags = Profile_tag::getTags($this->owner->id, $this->profile->id); $this->out->elementStart('dl', 'entity_tags'); $this->out->elementStart('dt'); if ($is_own) { $this->out->element('a', array('href' => common_local_url('tagother', array('id' => $this->profile->id))), _('Tags')); } else { $this->out->text(_('Tags')); } $this->out->elementEnd('dt'); $this->out->elementStart('dd'); if ($tags) { $this->out->elementStart('ul', 'tags xoxo'); foreach ($tags as $tag) { $this->out->elementStart('li'); $this->out->element('span', 'mark_hash', '#'); $this->out->element('a', array('rel' => 'tag', 'href' => common_local_url($this->action->trimmed('action'), array('nickname' => $this->owner->nickname, 'tag' => $tag))), $tag); $this->out->elementEnd('li'); } $this->out->elementEnd('ul'); } else { $this->out->text(_('(none)')); } $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } if ($is_own) { $this->showOwnerControls($this->profile); } $this->out->elementEnd('div'); $this->out->elementStart('div', 'entity_actions'); $this->out->elementStart('ul'); // Is this a logged-in user, looking at someone else's // profile? if (!empty($user) && $this->profile->id != $user->id) { $this->out->elementStart('li', 'entity_subscribe'); if ($user->isSubscribed($this->profile)) { $usf = new UnsubscribeForm($this->out, $this->profile); $usf->show(); } else { $sf = new SubscribeForm($this->out, $this->profile); $sf->show(); } $this->out->elementEnd('li'); $this->out->elementStart('li', 'entity_block'); if ($user->id == $this->owner->id) { $this->showBlockForm(); } $this->out->elementEnd('li'); } $this->out->elementEnd('ul'); $this->out->elementEnd('div'); $this->out->elementEnd('li'); }
function common_find_mentions($text, $notice) { $mentions = array(); $sender = Profile::staticGet('id', $notice->profile_id); if (empty($sender)) { return $mentions; } if (Event::handle('StartFindMentions', array($sender, $text, &$mentions))) { // Get the context of the original notice, if any $originalAuthor = null; $originalNotice = null; $originalMentions = array(); // Is it a reply? if (!empty($notice) && !empty($notice->reply_to)) { $originalNotice = Notice::staticGet('id', $notice->reply_to); if (!empty($originalNotice)) { $originalAuthor = Profile::staticGet('id', $originalNotice->profile_id); $ids = $originalNotice->getReplies(); foreach ($ids as $id) { $repliedTo = Profile::staticGet('id', $id); if (!empty($repliedTo)) { $originalMentions[$repliedTo->nickname] = $repliedTo; } } } } preg_match_all('/^T ([A-Z0-9]{1,64}) /u', $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]); // Try to get a profile for this nickname. // 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]; } else { $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})/u', $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; }
/** * get the cached number of profiles tagged with this * people tag, re-count if the argument is true. * * @param boolean $recount whether to ignore cache * * @return integer count */ function taggedCount($recount = false) { $keypart = sprintf('profile_list:tagged_count:%d:%s', $this->tagger, $this->tag); $count = self::cacheGet($keypart); if ($count === false) { $tags = new Profile_tag(); $tags->tag = $this->tag; $tags->tagger = $this->tagger; $count = $tags->count('distinct tagged'); self::cacheSet($keypart, $count); } return $count; }
/** * Data elements * * @return void */ function formData() { if (Event::handle('StartShowTagProfileFormData', array($this))) { $this->hidden('token', common_session_token()); $this->hidden('id', $this->target->id); $this->elementStart('ul', 'form_data'); $this->elementStart('li'); $tags = Profile_tag::getTagsArray($this->out->getScoped()->id, $this->target->id, $this->out->getScoped()->id); // TRANS: Field label on list form. $this->input('tags', _m('LABEL', 'Lists'), $this->arg('tags') ? $this->arg('tags') : implode(' ', $tags), _('Lists for this user (letters, numbers, -, ., and _), comma- or space- separated.')); $this->elementEnd('li'); $this->elementEnd('ul'); Event::handle('EndShowTagProfileFormData', array($this)); } }
function showContent() { // XXX: cache this $tags = new Profile_tag(); $plist = new Profile_list(); $plist->private = false; $tags->joinAdd($plist); $tags->selectAdd(); $tags->selectAdd('profile_tag.tag'); $tags->selectAdd('count(profile_tag.tag) as weight'); $tags->groupBy('profile_tag.tag'); $tags->orderBy('weight DESC'); $tags->limit(TAGS_PER_PAGE); $cnt = $tags->find(); if ($cnt > 0) { $this->elementStart('div', array('id' => 'tagcloud', 'class' => 'section')); $tw = array(); $sum = 0; while ($tags->fetch()) { $tw[$tags->tag] = $tags->weight; $sum += $tags->weight; } ksort($tw); $this->elementStart('dl'); // TRANS: DT element on on page with public list cloud. $this->element('dt', null, _('List cloud')); $this->elementStart('dd'); $this->elementStart('ul', 'tags xoxo tag-cloud'); foreach ($tw as $tag => $weight) { if ($sum) { $weightedSum = $weight / $sum; } else { $weightedSum = 0.5; } $this->showTag($tag, $weight, $weightedSum); } $this->elementEnd('ul'); $this->elementEnd('dd'); $this->elementEnd('dl'); $this->elementEnd('div'); } else { $this->showEmptyList(); } }
static function moveTag($orig, $new) { $tags = new Profile_tag(); $qry = 'UPDATE profile_tag SET ' . 'tag = "%s", tagger = "%s" ' . 'WHERE tag = "%s" ' . 'AND tagger = "%s"'; $result = $tags->query(sprintf($qry, $tags->escape($new->tag), $tags->escape($new->tagger), $tags->escape($orig->tag), $tags->escape($orig->tagger))); if ($result === false) { common_log_db_error($tags, 'UPDATE', __FILE__); throw new Exception('Could not move Profile_tag, see db log for details.'); } return $result; }
/** * Get a the self-tags associated with this profile * * @return string the concatenated string of tags */ function getTags() { return implode(' ', Profile_tag::getSelfTagsArray($this->profile)); }
/** * Handle request * * Does the tagging and returns results. * * @param Array $args unused. * * @return void */ function handle($args) { // Throws exception on error $ptag = Profile_tag::setTag($this->user->id, $this->tagged->id, $this->peopletag->tag); if (!$ptag) { $user = User::staticGet('id', $id); if ($user) { $this->clientError(sprintf(_('There was an unexpected error while listing %s.'), $user->nickname)); } else { // TRANS: Client error displayed when an unknown error occurs when adding a user to a list. // TRANS: %s is a profile URL. $this->clientError(sprintf(_('There was a problem listing %s. ' . 'The remote server is probably not responding correctly. ' . 'Please try retrying later.'), $this->profile->profileurl)); } return false; } if ($this->boolean('ajax')) { $this->startHTML('text/xml;charset=utf-8'); $this->elementStart('head'); // TRANS: Title after adding a user to a list. $this->element('title', null, _m('TITLE', 'Listed')); $this->elementEnd('head'); $this->elementStart('body'); $unsubscribe = new UntagButton($this, $this->tagged, $this->peopletag); $unsubscribe->show(); $this->elementEnd('body'); $this->elementEnd('html'); } else { $url = common_local_url('subscriptions', array('nickname' => $this->user->nickname)); common_redirect($url, 303); } }
/** * Save fields that should be stored in the main profile object * * XXX: There's a lot of dupe code here from ProfileSettingsAction. * Do not want. */ function saveStandardProfileDetails() { $fullname = $this->trimmed('extprofile-fullname'); $location = $this->trimmed('extprofile-location'); $tagstring = $this->trimmed('extprofile-tags'); $bio = $this->trimmed('extprofile-bio'); if ($tagstring) { $tags = array_map('common_canonical_tag', preg_split('/[\\s,]+/', $tagstring)); } else { $tags = array(); } foreach ($tags as $tag) { if (!common_valid_profile_tag($tag)) { // TRANS: Validation error in form for profile settings. // TRANS: %s is an invalid tag. throw new Exception(sprintf(_m('Invalid tag: "%s".'), $tag)); } } $oldTags = Profile_tag::getSelfTagsArray($this->scoped); $newTags = array_diff($tags, $oldTags); if ($fullname != $this->scoped->getFullname() || $location != $this->scoped->location || !empty($newTags) || $bio != $this->scoped->getDescription()) { $orig = clone $this->scoped; // Skipping nickname change here until we add logic for when the site allows it or not // old Profilesettings will still let us do that. $this->scoped->fullname = $fullname; $this->scoped->bio = $bio; $this->scoped->location = $location; $loc = Location::fromName($location); if (empty($loc)) { $this->scoped->lat = null; $this->scoped->lon = null; $this->scoped->location_id = null; $this->scoped->location_ns = null; } else { $this->scoped->lat = $loc->lat; $this->scoped->lon = $loc->lon; $this->scoped->location_id = $loc->location_id; $this->scoped->location_ns = $loc->location_ns; } $result = $this->scoped->update($orig); if ($result === false) { common_log_db_error($this->scoped, 'UPDATE', __FILE__); // TRANS: Server error thrown when user profile settings could not be saved. throw new ServerException(_m('Could not save profile.')); } // Set the user tags $result = Profile_tag::setSelfTags($this->scoped, $tags); Event::handle('EndProfileSaveForm', array($this)); } }
protected function doPost() { $tagstring = $this->trimmed('tags'); $token = $this->trimmed('token'); if (Event::handle('StartSavePeopletags', array($this, $tagstring))) { $tags = array(); $tag_priv = array(); if (is_string($tagstring) && strlen($tagstring) > 0) { $tags = preg_split('/[\\s,]+/', $tagstring); foreach ($tags as &$tag) { $private = @$tag[0] === '.'; $tag = common_canonical_tag($tag); if (!common_valid_profile_tag($tag)) { // TRANS: Form validation error displayed if a given tag is invalid. // TRANS: %s is the invalid tag. throw new ClientException(sprintf(_('Invalid tag: "%s".'), $tag)); } $tag_priv[$tag] = $private; } } $result = Profile_tag::setTags($this->scoped->getID(), $this->target->getID(), $tags, $tag_priv); if (!$result) { throw new ServerException('The tags could not be saved.'); } if ($this->boolean('ajax')) { $this->startHTML('text/xml;charset=utf-8'); $this->elementStart('head'); $this->element('title', null, _m('TITLE', 'Tags')); $this->elementEnd('head'); $this->elementStart('body'); if ($this->scoped->id == $this->target->id) { $widget = new SelftagsWidget($this, $this->scoped, $this->target); $widget->show(); } else { $widget = new PeopletagsWidget($this, $this->scoped, $this->target); $widget->show(); } $this->elementEnd('body'); $this->endHTML(); } else { // TRANS: Success message if lists are saved. $this->msg = _('Lists saved.'); $this->showForm(); } Event::handle('EndSavePeopletags', array($this, $tagstring)); } }
function saveTags() { $id = $this->trimmed('id'); $tagstring = $this->trimmed('tags'); $token = $this->trimmed('token'); if (!$token || $token != common_session_token()) { $this->showForm(_('There was a problem with your session token.' . ' Try again, please.')); return; } if (is_string($tagstring) && strlen($tagstring) > 0) { $tags = array_map('common_canonical_tag', preg_split('/[\\s,]+/', $tagstring)); foreach ($tags as $tag) { if (!common_valid_profile_tag($tag)) { $this->showForm(sprintf(_('Invalid tag: "%s"'), $tag)); return; } } } else { $tags = array(); } $user = common_current_user(); if (!Subscription::pkeyGet(array('subscriber' => $user->id, 'subscribed' => $this->profile->id)) && !Subscription::pkeyGet(array('subscriber' => $this->profile->id, 'subscribed' => $user->id))) { $this->clientError(_('You can only tag people you are subscribed to or who are subscribed to you.')); return; } $result = Profile_tag::setTags($user->id, $this->profile->id, $tags); if (!$result) { $this->clientError(_('Could not save tags.')); return; } $action = $user->isSubscribed($this->profile) ? 'subscriptions' : 'subscribers'; if ($this->boolean('ajax')) { $this->startHTML('text/xml;charset=utf-8'); $this->elementStart('head'); $this->element('title', null, _('Tags')); $this->elementEnd('head'); $this->elementStart('body'); $this->elementStart('p', 'subtags'); foreach ($tags as $tag) { $this->element('a', array('href' => common_local_url($action, array('nickname' => $user->nickname, 'tag' => $tag))), $tag); } $this->elementEnd('p'); $this->elementEnd('body'); $this->elementEnd('html'); } else { common_redirect(common_local_url($action, array('nickname' => $user->nickname))); } }
function _deleteTags() { $tag = new Profile_tag(); $tag->tagger = $this->id; $tag->delete(); }
function handleUntag() { if ($this->activity->target->type == ActivityObject::_LIST) { if ($this->activity->objects[0]->type != ActivityObject::PERSON) { // TRANS: Client exception. throw new ClientException(_m('Not a person object.')); return false; } // this is a peopletag $tagged = User::staticGet('uri', $this->activity->objects[0]->id); if (empty($tagged)) { // TRANS: Client exception. throw new ClientException(_m('Unidentified profile being untagged.')); } if ($tagged->id !== $this->user->id) { // TRANS: Client exception. throw new ClientException(_m('This user is not the one being untagged.')); } // save the list $tagger = $this->ensureProfile(); $list = Ostatus_profile::ensureActivityObjectProfile($this->activity->target); $ptag = $list->localPeopletag(); $result = Profile_tag::unTag($ptag->tagger, $tagged->id, $ptag->tag); if (!$result) { // TRANS: Client exception. throw new ClientException(_m('The tag could not be deleted.')); } } }
function showProfileTags() { if (Event::handle('StartProfilePageProfileTags', array($this->out, $this->profile))) { $tags = Profile_tag::getTags($this->profile->id, $this->profile->id); if (count($tags) > 0) { $this->out->elementStart('dl', 'entity_tags'); $this->out->element('dt', null, _('Tags')); $this->out->elementStart('dd'); $this->out->elementStart('ul', 'tags xoxo'); foreach ($tags as $tag) { $this->out->elementStart('li'); // Avoid space by using raw output. $pt = '<span class="mark_hash">#</span><a rel="tag" href="' . common_local_url('peopletag', array('tag' => $tag)) . '">' . $tag . '</a>'; $this->out->raw($pt); $this->out->elementEnd('li'); } $this->out->elementEnd('ul'); $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } Event::handle('EndProfilePageProfileTags', array($this->out, $this->profile)); } }
/** * Handle a post * * Validate input and save changes. Reload the form with a success * or error message. * * @return void */ protected function doPost() { if (Event::handle('StartProfileSaveForm', array($this))) { // $nickname will only be set if this changenick value is true. if (common_config('profile', 'changenick') == true) { try { $nickname = Nickname::normalize($this->trimmed('nickname'), true); } catch (NicknameTakenException $e) { // Abort only if the nickname is occupied by _another_ local user profile if (!$this->scoped->sameAs($e->profile)) { throw $e; } // Since the variable wasn't set before the exception was thrown, let's run // the normalize sequence again, but without in-use check this time. $nickname = Nickname::normalize($this->trimmed('nickname')); } } $fullname = $this->trimmed('fullname'); $homepage = $this->trimmed('homepage'); $bio = $this->trimmed('bio'); $location = $this->trimmed('location'); $autosubscribe = $this->booleanintstring('autosubscribe'); $subscribe_policy = $this->trimmed('subscribe_policy'); $private_stream = $this->booleanintstring('private_stream'); $language = $this->trimmed('language'); $timezone = $this->trimmed('timezone'); $tagstring = $this->trimmed('tags'); // Some validation if (!is_null($homepage) && strlen($homepage) > 0 && !common_valid_http_url($homepage)) { // TRANS: Validation error in form for profile settings. throw new ClientException(_('Homepage is not a valid URL.')); } else { if (!is_null($fullname) && mb_strlen($fullname) > 191) { // TRANS: Validation error in form for profile settings. throw new ClientException(_('Full name is too long (maximum 191 characters).')); } else { if (Profile::bioTooLong($bio)) { // TRANS: Validation error in form for profile settings. // TRANS: Plural form is used based on the maximum number of allowed // TRANS: characters for the biography (%d). throw new ClientException(sprintf(_m('Bio is too long (maximum %d character).', 'Bio is too long (maximum %d characters).', Profile::maxBio()), Profile::maxBio())); } else { if (!is_null($location) && mb_strlen($location) > 191) { // TRANS: Validation error in form for profile settings. throw new ClientException(_('Location is too long (maximum 191 characters).')); } else { if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) { // TRANS: Validation error in form for profile settings. throw new ClientException(_('Timezone not selected.')); } else { if (!is_null($language) && strlen($language) > 50) { // TRANS: Validation error in form for profile settings. throw new ClientException(_('Language is too long (maximum 50 characters).')); } } } } } } $tags = array(); $tag_priv = array(); if (is_string($tagstring) && strlen($tagstring) > 0) { $tags = preg_split('/[\\s,]+/', $tagstring); foreach ($tags as &$tag) { $private = @$tag[0] === '.'; $tag = common_canonical_tag($tag); if (!common_valid_profile_tag($tag)) { // TRANS: Validation error in form for profile settings. // TRANS: %s is an invalid tag. throw new ClientException(sprintf(_('Invalid tag: "%s".'), $tag)); } $tag_priv[$tag] = $private; } } $user = $this->scoped->getUser(); $user->query('BEGIN'); // $user->nickname is updated through Profile->update(); // XXX: XOR if ($user->autosubscribe ^ $autosubscribe || $user->private_stream ^ $private_stream || $user->timezone != $timezone || $user->language != $language || $user->subscribe_policy != $subscribe_policy) { $original = clone $user; $user->autosubscribe = $autosubscribe; $user->language = $language; $user->private_stream = $private_stream; $user->subscribe_policy = $subscribe_policy; $user->timezone = $timezone; $result = $user->update($original); if ($result === false) { common_log_db_error($user, 'UPDATE', __FILE__); $user->query('ROLLBACK'); // TRANS: Server error thrown when user profile settings could not be updated to // TRANS: automatically subscribe to any subscriber. throw new ServerException(_('Could not update user for autosubscribe or subscribe_policy.')); } // Re-initialize language environment if it changed common_init_language(); } $original = clone $this->scoped; if (common_config('profile', 'changenick') == true && $this->scoped->getNickname() !== $nickname) { assert(Nickname::normalize($nickname) === $nickname); common_debug("Changing user nickname from '{$this->scoped->getNickname()}' to '{$nickname}'."); $this->scoped->nickname = $nickname; $this->scoped->profileurl = common_profile_url($this->scoped->getNickname()); } $this->scoped->fullname = $fullname; $this->scoped->homepage = $homepage; $this->scoped->bio = $bio; $this->scoped->location = $location; $loc = Location::fromName($location); if (empty($loc)) { $this->scoped->lat = null; $this->scoped->lon = null; $this->scoped->location_id = null; $this->scoped->location_ns = null; } else { $this->scoped->lat = $loc->lat; $this->scoped->lon = $loc->lon; $this->scoped->location_id = $loc->location_id; $this->scoped->location_ns = $loc->location_ns; } if (common_config('location', 'share') == 'user') { $exists = false; $prefs = User_location_prefs::getKV('user_id', $this->scoped->getID()); if (empty($prefs)) { $prefs = new User_location_prefs(); $prefs->user_id = $this->scoped->getID(); $prefs->created = common_sql_now(); } else { $exists = true; $orig = clone $prefs; } $prefs->share_location = $this->booleanintstring('sharelocation'); if ($exists) { $result = $prefs->update($orig); } else { $result = $prefs->insert(); } if ($result === false) { common_log_db_error($prefs, $exists ? 'UPDATE' : 'INSERT', __FILE__); $user->query('ROLLBACK'); // TRANS: Server error thrown when user profile location preference settings could not be updated. throw new ServerException(_('Could not save location prefs.')); } } common_debug('Old profile: ' . common_log_objstring($original), __FILE__); common_debug('New profile: ' . common_log_objstring($this->scoped), __FILE__); $result = $this->scoped->update($original); if ($result === false) { common_log_db_error($this->scoped, 'UPDATE', __FILE__); $user->query('ROLLBACK'); // TRANS: Server error thrown when user profile settings could not be saved. throw new ServerException(_('Could not save profile.')); } // Set the user tags $result = Profile_tag::setSelfTags($this->scoped, $tags, $tag_priv); $user->query('COMMIT'); Event::handle('EndProfileSaveForm', array($this)); // TRANS: Confirmation shown when user profile settings are saved. return _('Settings saved.'); } }
/** * Notify remote user that a people tag has been removed * - untag verb is queued * - the subscription is undone immediately if not required * i.e garbageCollect()'d * * @param Profile_tag $ptag the people tag that was deleted * @return hook return value */ function onEndUntagProfile($ptag) { $oprofile = Ostatus_profile::staticGet('profile_id', $ptag->tagged); if (empty($oprofile)) { return true; } $plist = $ptag->getMeta(); if ($plist->private) { return true; } $act = new Activity(); $tagger = $plist->getTagger(); $tagged = Profile::staticGet('id', $ptag->tagged); $act->verb = ActivityVerb::UNTAG; $act->id = TagURI::mint('untag_profile:%d:%d:%s', $plist->tagger, $plist->id, common_date_iso8601(time())); $act->time = time(); // TRANS: Title for unlisting a remote profile. $act->title = _m('TITLE', 'Unlist'); // TRANS: Success message for remote list removal through OStatus. // TRANS: %1$s is the list creator's name, %2$s is the removed list member, %3$s is the list name. $act->content = sprintf(_m('%1$s removed %2$s from the list %3$s.'), $tagger->getBestName(), $tagged->getBestName(), $plist->getBestName()); $act->actor = ActivityObject::fromProfile($tagger); $act->objects = array(ActivityObject::fromProfile($tagged)); $act->target = ActivityObject::fromPeopletag($plist); $oprofile->notifyDeferred($act, $tagger); // unsubscribe to PuSH feed if no more required $oprofile->garbageCollect(); return true; }
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; } }
static function moveTag($orig, $new) { $tags = new Profile_tag(); $qry = 'UPDATE profile_tag SET ' . 'tag = "%s", tagger = "%s" ' . 'WHERE tag = "%s" ' . 'AND tagger = "%s"'; $result = $tags->query(sprintf($qry, $new->tag, $new->tagger, $orig->tag, $orig->tagger)); if (!$result) { common_log_db_error($tags, 'UPDATE', __FILE__); return false; } return true; }
function initProfileLists() { printfnq("Ensuring all profile tags have a corresponding list..."); $ptag = new Profile_tag(); $ptag->selectAdd(); $ptag->selectAdd('tagger, tag, count(*) as tagged_count'); $ptag->whereAdd('NOT EXISTS (SELECT tagger, tagged from profile_list ' . 'where profile_tag.tagger = profile_list.tagger ' . 'and profile_tag.tag = profile_list.tag)'); $ptag->groupBy('tagger, tag'); $ptag->orderBy('tagger, tag'); if ($ptag->find()) { while ($ptag->fetch()) { $plist = new Profile_list(); $plist->tagger = $ptag->tagger; $plist->tag = $ptag->tag; $plist->private = 0; $plist->created = common_sql_now(); $plist->modified = $plist->created; $plist->mainpage = common_local_url('showprofiletag', array('tagger' => $plist->getTagger()->nickname, 'tag' => $plist->tag)); $plist->tagged_count = $ptag->tagged_count; $plist->subscriber_count = 0; $plist->insert(); $orig = clone $plist; // After insert since it uses auto-generated ID $plist->uri = common_local_url('profiletagbyid', array('id' => $plist->id, 'tagger_id' => $plist->tagger)); $plist->update($orig); } } printfnq("DONE.\n"); }
function showProfile() { $this->elementStart('div', 'entity_profile vcard author'); $this->element('h2', null, _('User profile')); $avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE); $this->elementStart('dl', 'entity_depiction'); $this->element('dt', null, _('Photo')); $this->elementStart('dd'); $this->element('img', array('src' => $avatar ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE), 'class' => 'photo avatar', 'width' => AVATAR_PROFILE_SIZE, 'height' => AVATAR_PROFILE_SIZE, 'alt' => $this->profile->nickname)); $this->elementEnd('dd'); $user = User::staticGet('id', $this->profile->id); $cur = common_current_user(); if ($cur && $cur->id == $user->id) { $this->elementStart('dd'); $this->element('a', array('href' => common_local_url('avatarsettings')), _('Edit Avatar')); $this->elementEnd('dd'); } $this->elementEnd('dl'); $this->elementStart('dl', 'entity_nickname'); $this->element('dt', null, _('Nickname')); $this->elementStart('dd'); $hasFN = $this->profile->fullname ? 'nickname url uid' : 'fn nickname url uid'; $this->element('a', array('href' => $this->profile->profileurl, 'rel' => 'me', 'class' => $hasFN), $this->profile->nickname); $this->elementEnd('dd'); $this->elementEnd('dl'); if ($this->profile->fullname) { $this->elementStart('dl', 'entity_fn'); $this->element('dt', null, _('Full name')); $this->elementStart('dd'); $this->element('span', 'fn', $this->profile->fullname); $this->elementEnd('dd'); $this->elementEnd('dl'); } if ($this->profile->location) { $this->elementStart('dl', 'entity_location'); $this->element('dt', null, _('Location')); $this->element('dd', 'label', $this->profile->location); $this->elementEnd('dl'); } if ($this->profile->homepage) { $this->elementStart('dl', 'entity_url'); $this->element('dt', null, _('URL')); $this->elementStart('dd'); $this->element('a', array('href' => $this->profile->homepage, 'rel' => 'me', 'class' => 'url'), $this->profile->homepage); $this->elementEnd('dd'); $this->elementEnd('dl'); } if ($this->profile->bio) { $this->elementStart('dl', 'entity_note'); $this->element('dt', null, _('Note')); $this->element('dd', 'note', $this->profile->bio); $this->elementEnd('dl'); } $tags = Profile_tag::getTags($this->profile->id, $this->profile->id); if (count($tags) > 0) { $this->elementStart('dl', 'entity_tags'); $this->element('dt', null, _('Tags')); $this->elementStart('dd'); $this->elementStart('ul', 'tags xoxo'); foreach ($tags as $tag) { $this->elementStart('li'); // Avoid space by using raw output. $pt = '<span class="mark_hash">#</span><a rel="tag" href="' . common_local_url('peopletag', array('tag' => $tag)) . '">' . $tag . '</a>'; $this->raw($pt); $this->elementEnd('li'); } $this->elementEnd('ul'); $this->elementEnd('dd'); $this->elementEnd('dl'); } $this->elementEnd('div'); $this->elementStart('div', 'entity_actions'); $this->element('h2', null, _('User actions')); $this->elementStart('ul'); $cur = common_current_user(); if ($cur && $cur->id == $this->profile->id) { $this->elementStart('li', 'entity_edit'); $this->element('a', array('href' => common_local_url('profilesettings'), 'title' => _('Edit profile settings')), _('Edit')); $this->elementEnd('li'); } if ($cur) { if ($cur->id != $this->profile->id) { $this->elementStart('li', 'entity_subscribe'); if ($cur->isSubscribed($this->profile)) { $usf = new UnsubscribeForm($this, $this->profile); $usf->show(); } else { $sf = new SubscribeForm($this, $this->profile); $sf->show(); } $this->elementEnd('li'); } } else { $this->elementStart('li', 'entity_subscribe'); $this->showRemoteSubscribeLink(); $this->elementEnd('li'); } if ($cur && $cur->id != $user->id && $cur->mutuallySubscribed($user)) { $this->elementStart('li', 'entity_send-a-message'); $this->element('a', array('href' => common_local_url('newmessage', array('to' => $user->id)), 'title' => _('Send a direct message to this user')), _('Message')); $this->elementEnd('li'); if ($user->email && $user->emailnotifynudge) { $this->elementStart('li', 'entity_nudge'); $nf = new NudgeForm($this, $user); $nf->show(); $this->elementEnd('li'); } } if ($cur && $cur->id != $this->profile->id) { $blocked = $cur->hasBlocked($this->profile); $this->elementStart('li', 'entity_block'); if ($blocked) { $ubf = new UnblockForm($this, $this->profile); $ubf->show(); } else { $bf = new BlockForm($this, $this->profile); $bf->show(); } $this->elementEnd('li'); } $this->elementEnd('ul'); $this->elementEnd('div'); }
function saveReplies() { // Alternative reply format $tname = false; if (preg_match('/^T ([A-Z0-9]{1,64}) /', $this->content, $match)) { $tname = $match[1]; } // extract all @messages $cnt = preg_match_all('/(?:^|\\s)@([a-z0-9]{1,64})/', $this->content, $match); $names = array(); if ($cnt || $tname) { // XXX: is there another way to make an array copy? $names = $tname ? array_unique(array_merge(array(strtolower($tname)), $match[1])) : array_unique($match[1]); } $sender = Profile::staticGet($this->profile_id); $replied = array(); // store replied only for first @ (what user/notice what the reply directed, // we assume first @ is it) for ($i = 0; $i < count($names); $i++) { $nickname = $names[$i]; $recipient = common_relative_profile($sender, $nickname, $this->created); if (!$recipient) { continue; } if ($i == 0 && $recipient->id != $sender->id && !$this->reply_to) { // Don't save reply to self $reply_for = $recipient; $recipient_notice = $reply_for->getCurrentNotice(); if ($recipient_notice) { $orig = clone $this; $this->reply_to = $recipient_notice->id; $this->update($orig); } } // Don't save replies from blocked profile to local user $recipient_user = User::staticGet('id', $recipient->id); if ($recipient_user && $recipient_user->hasBlocked($sender)) { continue; } $reply = new Reply(); $reply->notice_id = $this->id; $reply->profile_id = $recipient->id; $id = $reply->insert(); if (!$id) { $last_error =& PEAR::getStaticProperty('DB_DataObject', 'lastError'); common_log(LOG_ERR, 'DB error inserting reply: ' . $last_error->message); common_server_error(sprintf(_('DB error inserting reply: %s'), $last_error->message)); return; } else { $replied[$recipient->id] = 1; } } // Hash format replies, too $cnt = preg_match_all('/(?:^|\\s)@#([a-z0-9]{1,64})/', $this->content, $match); if ($cnt) { foreach ($match[1] as $tag) { $tagged = Profile_tag::getTagged($sender->id, $tag); foreach ($tagged as $t) { if (!$replied[$t->id]) { // Don't save replies from blocked profile to local user $t_user = User::staticGet('id', $t->id); if ($t_user && $t_user->hasBlocked($sender)) { continue; } $reply = new Reply(); $reply->notice_id = $this->id; $reply->profile_id = $t->id; $id = $reply->insert(); if (!$id) { common_log_db_error($reply, 'INSERT', __FILE__); return; } else { $replied[$recipient->id] = 1; } } } } } foreach (array_keys($replied) as $recipient) { $user = User::staticGet('id', $recipient); if ($user) { mail_notify_attn($user, $this); } } }