--- /dev/null
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008-2010, StatusNet, Inc.
+ *
+ * Action to add a people tag to a user.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5
+ *
+ * @category Action
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/togglepeopletag.php';
+
+/**
+ *
+ * Action to tag a profile with a single tag.
+ *
+ * Takes parameters:
+ *
+ * - tagged: the ID of the profile being tagged
+ * - token: session token to prevent CSRF attacks
+ * - ajax: boolean; whether to return Ajax or full-browser results
+ * - peopletag_id: the ID of the tag being used
+ *
+ * Only works if the current user is logged in.
+ *
+ * @category Action
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link http://status.net/
+ */
+
+class AddpeopletagAction extends Action
+{
+ var $user;
+ var $tagged;
+ var $peopletag;
+
+ /**
+ * Check pre-requisites and instantiate attributes
+ *
+ * @param Array $args array of arguments (URL, GET, POST)
+ *
+ * @return boolean success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ // CSRF protection
+
+ $token = $this->trimmed('token');
+
+ if (!$token || $token != common_session_token()) {
+ $this->clientError(_('There was a problem with your session token.'.
+ ' Try again, please.'));
+ return false;
+ }
+
+ // Only for logged-in users
+
+ $this->user = common_current_user();
+
+ if (empty($this->user)) {
+ $this->clientError(_('Not logged in.'));
+ return false;
+ }
+
+ // Profile to subscribe to
+
+ $tagged_id = $this->arg('tagged');
+
+ $this->tagged = Profile::staticGet('id', $tagged_id);
+
+ if (empty($this->tagged)) {
+ $this->clientError(_('No such profile.'));
+ return false;
+ }
+
+ $id = $this->arg('peopletag_id');
+ $this->peopletag = Profile_list::staticGet('id', $id);
+
+ if (empty($this->peopletag)) {
+ $this->clientError(_('No such peopletag.'));
+ return false;
+ }
+
+ // OMB 0.1 doesn't have a mechanism for local-server-
+ // originated tag.
+
+ $omb01 = Remote_profile::staticGet('id', $tagged_id);
+
+ if (!empty($omb01)) {
+ $this->clientError(_('You cannot tag an OMB 0.1'.
+ ' remote profile with this action.'));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * 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 tagging %s'),
+ $user->nickname));
+ } else {
+ $this->clientError(sprintf(_('There was a problem tagging %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');
+ $this->element('title', null, _('Subscribed'));
+ $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);
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Edit an existing group
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Group
+ * @package StatusNet
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Add a new group
+ *
+ * This is the form for adding a new group
+ *
+ * @category Group
+ * @package StatusNet
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class EditpeopletagAction extends OwnerDesignAction
+{
+
+ var $msg, $confirm, $confirm_args=array();
+
+ function title()
+ {
+ if ($_SERVER['REQUEST_METHOD'] == 'POST' && $this->boolean('delete')) {
+ return sprintf(_('Delete %s people tag'), $this->peopletag->tag);
+ }
+ return sprintf(_('Edit people tag %s'), $this->peopletag->tag);
+ }
+
+ /**
+ * Prepare to run
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ if (!common_logged_in()) {
+ $this->clientError(_('Not logged in.'));
+ return false;
+ }
+
+ $id = $this->arg('id');
+ $tagger_arg = $this->arg('tagger');
+ $tag_arg = $this->arg('tag');
+
+ $tagger = common_canonical_nickname($tagger_arg);
+ $tag = common_canonical_tag($tag_arg);
+
+ $current = common_current_user();
+
+ // Permanent redirect on non-canonical tag
+
+ if ($tagger_arg != $tagger || $tag_arg != $tag) {
+ $args = array('tagger' => $tagger, 'tag' => $tag);
+ common_redirect(common_local_url('editpeopletag', $args), 301);
+ return false;
+ }
+
+ $user = null;
+ if ($id) {
+ $this->peopletag = Profile_list::staticGet('id', $id);
+ if (!empty($this->peopletag)) {
+ $user = User::staticGet('id', $this->peopletag->tagger);
+ }
+ } else {
+ if (!$tagger) {
+ $this->clientError(_('No tagger or ID.'), 404);
+ return false;
+ }
+
+ $user = User::staticGet('nickname', $tagger);
+ $this->peopletag = Profile_list::pkeyGet(array('tagger' => $user->id, 'tag' => $tag));
+ }
+
+ if (!$this->peopletag) {
+ $this->clientError(_('No such peopletag.'), 404);
+ return false;
+ }
+
+ if (!$user) {
+ // This should not be happening
+ $this->clientError(_('Not a local user.'), 404);
+ return false;
+ }
+
+ if ($current->id != $user->id) {
+ $this->clientError(_('You must be the creator of the tag to edit it.'), 404);
+ return false;
+ }
+
+ $this->tagger = $user->getProfile();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * On GET, show the form. On POST, try to save the group.
+ *
+ * @param array $args unused
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ $this->trySave();
+ } else {
+ $this->showForm();
+ }
+ }
+
+ function showConfirm($msg=null, $fwd=null)
+ {
+ $this->confirm = $msg;
+ $this->confirm_args = $fwd;
+ $this->showPage();
+ }
+
+ function showConfirmForm()
+ {
+ $this->elementStart('form', array('id' => 'form_peopletag_edit_confirm',
+ 'class' => 'form_settings',
+ 'method' => 'post',
+ 'action' => common_local_url('editpeopletag',
+ array('tagger' => $this->tagger->nickname,
+ 'tag' => $this->peopletag->tag))));
+ $this->elementStart('fieldset');
+ $this->hidden('token', common_session_token());
+ $this->hidden('id', $this->arg('id'));
+
+ foreach ($this->confirm_args as $key => $val) {
+ $this->hidden($key, $val);
+ }
+
+ $this->submit('form_action-no',
+ _m('BUTTON','No'),
+ 'submit form_action-primary',
+ 'cancel');
+ $this->submit('form_action-yes',
+ _m('BUTTON','Yes'),
+ 'submit form_action-secondary',
+ 'confirm');
+ $this->elementEnd('fieldset');
+ $this->elementEnd('form');
+ }
+
+ function showForm($msg=null)
+ {
+ $this->msg = $msg;
+ $this->showPage();
+ }
+
+ function showLocalNav()
+ {
+ $nav = new PeopletagGroupNav($this, $this->peopletag);
+ $nav->show();
+ }
+
+ function showContent()
+ {
+ if ($this->confirm) {
+ $this->showConfirmForm();
+ return;
+ }
+
+ $form = new PeopletagEditForm($this, $this->peopletag);
+ $form->show();
+
+ $form->showProfileList();
+ }
+
+ function showPageNotice()
+ {
+ if ($this->msg) {
+ $this->element('p', 'error', $this->msg);
+ } else if ($this->confirm) {
+ $this->element('p', 'instructions', $this->confirm);
+ } else {
+ $this->element('p', 'instructions',
+ _('Use this form to edit the people tag.'));
+ }
+ }
+
+ function showScripts()
+ {
+ parent::showScripts();
+ $this->autofocus('tag');
+ }
+
+ function trySave()
+ {
+ $tag = common_canonical_tag($this->trimmed('tag'));
+ $description = $this->trimmed('description');
+ $private = $this->boolean('private');
+ $delete = $this->arg('delete');
+ $confirm = $this->arg('confirm');
+ $cancel = $this->arg('cancel');
+
+ if ($delete && $cancel) {
+ $this->showForm(_('Delete aborted.'));
+ return;
+ }
+
+ $set_private = $private && $this->peopletag->private != $private;
+
+ if ($delete && !$confirm) {
+ $this->showConfirm(_('Deleting this tag will permanantly remove ' .
+ 'all its subscription and membership records. ' .
+ 'Do you still want to continue?'), array('delete' => 1));
+ return;
+ } else if (common_valid_tag($tag)) {
+ $this->showForm(_('Invalid tag.'));
+ return;
+ } else if ($tag != $this->peopletag->tag && $this->tagExists($tag)) {
+ $this->showForm(sprintf(_('You already have a tag named %s.'), $tag));
+ return;
+ } else if (Profile_list::descriptionTooLong($description)) {
+ $this->showForm(sprintf(_('description is too long (max %d chars).'), Profile_list::maxDescription()));
+ return;
+ } else if ($set_private && !$confirm && !$cancel) {
+ $fwd = array('tag' => $tag,
+ 'description' => $description,
+ 'private' => (int) $private);
+
+ $this->showConfirm(_('Setting a public tag as private will ' .
+ 'permanently remove all the existing ' .
+ 'subscriptions to it. Do you still want to continue?'), $fwd);
+ return;
+ }
+
+ $this->peopletag->query('BEGIN');
+
+ $orig = clone($this->peopletag);
+
+ $this->peopletag->tag = $tag;
+ $this->peopletag->description = $description;
+ if (!$set_private || $confirm) {
+ $this->peopletag->private = $private;
+ }
+
+ $result = $this->peopletag->update($orig);
+
+ if (!$result) {
+ common_log_db_error($this->group, 'UPDATE', __FILE__);
+ $this->serverError(_('Could not update peopletag.'));
+ }
+
+ $this->peopletag->query('COMMIT');
+
+ if ($set_private && $confirm) {
+ Profile_tag_subscription::cleanup($this->peopletag);
+ }
+
+ if ($delete) {
+ // This might take quite a bit of time.
+ $this->peopletag->delete();
+ // send home.
+ common_redirect(common_local_url('all',
+ array('nickname' => $this->tagger->nickname)),
+ 303);
+ }
+
+ if ($tag != $orig->tag) {
+ common_redirect(common_local_url('editpeopletag',
+ array('tagger' => $this->tagger->nickname,
+ 'tag' => $tag)),
+ 303);
+ } else {
+ $this->showForm(_('Options saved.'));
+ }
+ }
+
+ function tagExists($tag)
+ {
+ $args = array('tagger' => $this->tagger->id, 'tag' => $tag);
+ $ptag = Profile_list::pkeyGet($args);
+
+ return !empty($ptag);
+ }
+}
/**
* StatusNet, the distributed open-source microblogging tool
*
- * Action for showing profiles self-tagged with a given tag
+ * People tags by a user
*
* PHP version 5
*
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
+ * PHP version 5
+ *
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
- * @category Action
+ * @category Personal
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @author Zach Copley <zach@status.net>
+ * @author Shashi Gowda <connect2shashi@gmail.com>
* @copyright 2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
exit(1);
}
-/**
- * This class outputs a paginated list of profiles self-tagged with a given tag
- *
- * @category Output
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @author Zach Copley <zach@status.net>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- *
- * @see Action
- */
+require_once INSTALLDIR.'/lib/peopletaglist.php';
+// cache 3 pages
+define('PEOPLETAG_CACHE_WINDOW', PEOPLETAGS_PER_PAGE*3 + 1);
class PeopletagAction extends Action
{
-
- var $tag = null;
var $page = null;
+ var $tag = null;
- /**
- * For initializing members of the class.
- *
- * @param array $argarray misc. arguments
- *
- * @return boolean true
- */
- function prepare($argarray)
+ function isReadOnly($args)
{
- parent::prepare($argarray);
-
- $this->tag = $this->trimmed('tag');
-
- if (!common_valid_profile_tag($this->tag)) {
- $this->clientError(sprintf(_('Not a valid people tag: %s.'),
- $this->tag));
- return;
- }
-
- $this->page = ($this->arg('page')) ? $this->arg('page') : 1;
-
- common_set_returnto($this->selfUrl());
-
return true;
}
- /**
- * Handler method
- *
- * @param array $argarray is ignored since it's now passed in in prepare()
- *
- * @return boolean is read only action?
- */
- function handle($argarray)
+ function title()
{
- parent::handle($argarray);
- $this->showPage();
+ if ($this->page == 1) {
+ return sprintf(_("Public people tag %s"), $this->tag);
+ } else {
+ return sprintf(_("Public people tag %s, page %d"), $this->tag, $this->page);
+ }
}
- /**
- * Whips up a query to get a list of profiles based on the provided
- * people tag and page, initalizes a ProfileList widget, and displays
- * it to the user.
- *
- * @return nothing
- */
- function showContent()
+ function prepare($args)
{
+ parent::prepare($args);
+ $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
- $profile = new Profile();
+ $tag_arg = $this->arg('tag');
+ $tag = common_canonical_tag($tag_arg);
- $offset = ($this->page - 1) * PROFILES_PER_PAGE;
- $limit = PROFILES_PER_PAGE + 1;
+ // Permanent redirect on non-canonical nickname
- if (common_config('db', 'type') == 'pgsql') {
- $lim = ' LIMIT ' . $limit . ' OFFSET ' . $offset;
- } else {
- $lim = ' LIMIT ' . $offset . ', ' . $limit;
+ if ($tag_arg != $tag) {
+ $args = array('tag' => $nickname);
+ if ($this->page && $this->page != 1) {
+ $args['page'] = $this->page;
+ }
+ common_redirect(common_local_url('peopletag', $args), 301);
+ return false;
}
+ $this->tag = $tag;
- // XXX: memcached this
-
- $qry = 'SELECT profile.* ' .
- 'FROM profile JOIN profile_tag ' .
- 'ON profile.id = profile_tag.tagger ' .
- 'WHERE profile_tag.tagger = profile_tag.tagged ' .
- "AND tag = '%s' " .
- 'ORDER BY profile_tag.modified DESC%s';
-
- $profile->query(sprintf($qry, $this->tag, $lim));
-
- $ptl = new PeopleTagList($profile, $this); // pass the ammunition
- $cnt = $ptl->show();
-
- $this->pagination($this->page > 1,
- $cnt > PROFILES_PER_PAGE,
- $this->page,
- 'peopletag',
- array('tag' => $this->tag));
+ return true;
}
- /**
- * Returns the page title
- *
- * @return string page title
- */
- function title()
+ function handle($args)
{
- return sprintf(_('Users self-tagged with %1$s - page %2$d'),
- $this->tag, $this->page);
+ parent::handle($args);
+ $this->showPage();
}
-}
+ function showLocalNav()
+ {
+ $nav = new PublicGroupNav($this);
+ $nav->show();
+ }
-class PeopleTagList extends ProfileList
-{
- function newListItem($profile)
+ function showAnonymousMessage()
{
- return new PeopleTagListItem($profile, $this->action);
+ $notice =
+ _('People tags are how you sort similar ' .
+ 'people on %%site.name%%, a [micro-blogging]' .
+ '(http://en.wikipedia.org/wiki/Micro-blogging) service ' .
+ 'based on the Free Software [StatusNet](http://status.net/) tool. ' .
+ 'You can then easily keep track of what they ' .
+ 'are doing by subscribing to the tag\'s timeline.' );
+ $this->elementStart('div', array('id' => 'anon_notice'));
+ $this->raw(common_markup_to_html($notice));
+ $this->elementEnd('div');
}
-}
-class PeopleTagListItem extends ProfileListItem
-{
- function linkAttributes()
+ function showContent()
{
- $aAttrs = parent::linkAttributes();
+ $offset = ($this->page-1) * PEOPLETAGS_PER_PAGE;
+ $limit = PEOPLETAGS_PER_PAGE + 1;
+
+ $ptags = new Profile_list();
+ $ptags->tag = $this->tag;
+
+ $user = common_current_user();
+
+ if (empty($user)) {
+ $ckey = sprintf('profile_list:tag:%s', $this->tag);
+ $ptags->private = false;
+ $ptags->orderBy('profile_list.modified DESC');
+
+ $c = Cache::instance();
+ if ($offset+$limit <= PEOPLETAG_CACHE_WINDOW && !empty($c)) {
+ $cached_ptags = Profile_list::getCached($ckey, $offset, $limit);
+ if ($cached_ptags === false) {
+ $ptags->limit(0, PEOPLETAG_CACHE_WINDOW);
+ $ptags->find();
+
+ Profile_list::setCache($ckey, $ptags, $offset, $limit);
+ } else {
+ $ptags = clone($cached_ptags);
+ }
+ } else {
+ $ptags->limit($offset, $limit);
+ $ptags->find();
+ }
+ } else {
+ $ptags->whereAdd('(profile_list.private = false OR (' .
+ ' profile_list.tagger =' . $user->id .
+ ' AND profile_list.private = true) )');
- if (common_config('nofollow', 'peopletag')) {
- $aAttrs['rel'] .= ' nofollow';
+ $ptags->orderBy('profile_list.modified DESC');
+ $ptags->find();
}
- return $aAttrs;
+ $pl = new PeopletagList($ptags, $this);
+ $cnt = $pl->show();
+
+ $this->pagination($this->page > 1, $cnt > PEOPLETAGS_PER_PAGE,
+ $this->page, 'peopletag', array('tag' => $this->tag));
}
- function homepageAttributes()
+ function showSections()
{
- $aAttrs = parent::linkAttributes();
-
- if (common_config('nofollow', 'peopletag')) {
- $aAttrs['rel'] = 'nofollow';
- }
-
- return $aAttrs;
}
}
-
--- /dev/null
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008-2010, StatusNet, Inc.
+ *
+ * Peopletag autocomple action.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5
+ *
+ * @category Action
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+class PeopletagautocompleteAction extends Action
+{
+ var $user;
+
+ /**
+ * Check pre-requisites and instantiate attributes
+ *
+ * @param Array $args array of arguments (URL, GET, POST)
+ *
+ * @return boolean success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ // Only for logged-in users
+
+ $this->user = common_current_user();
+
+ if (empty($this->user)) {
+ $this->clientError(_('Not logged in.'));
+ return false;
+ }
+
+ // CSRF protection
+
+ $token = $this->trimmed('token');
+
+ if (!$token || $token != common_session_token()) {
+ $this->clientError(_('There was a problem with your session token.'.
+ ' Try again, please.'));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Handle request
+ *
+ * Does the subscription and returns results.
+ *
+ * @param Array $args unused.
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ $profile = $this->user->getProfile();
+ $tags = $profile->getOwnedTags(common_current_user());
+
+ $tags_array = array();
+ while ($tags->fetch()) {
+ $arr = array();
+ $arr['tag'] = $tags->tag;
+ $arr['mode'] = $tags->private ? 'private' : 'public';
+ // $arr['url'] = $tags->homeUrl();
+ $arr['freq'] = $tags->taggedCount();
+
+ $tags_array[] = $arr;
+ }
+
+ $tags->free();
+
+ //common_log(LOG_DEBUG, 'Autocomplete data: ' . json_encode($tags_array));
+ print(json_encode($tags_array));
+ exit(0);
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * List of people tagged by the user with a tag
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Group
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+require_once(INSTALLDIR.'/lib/profilelist.php');
+
+/**
+ * List of people tagged by the user with a tag
+ *
+ * @category Peopletag
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class PeopletaggedAction extends OwnerDesignAction
+{
+ var $page = null;
+ var $peopletag = null;
+ var $tagger = null;
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
+
+ $tagger_arg = $this->arg('tagger');
+ $tag_arg = $this->arg('tag');
+ $tagger = common_canonical_nickname($tagger_arg);
+ $tag = common_canonical_tag($tag_arg);
+
+ // Permanent redirect on non-canonical nickname
+
+ if ($tagger_arg != $tagger || $tag_arg != $tag) {
+ $args = array('tagger' => $nickname, 'tag' => $tag);
+ if ($this->page != 1) {
+ $args['page'] = $this->page;
+ }
+ common_redirect(common_local_url('peopletagged', $args), 301);
+ return false;
+ }
+
+ if (!$tagger) {
+ $this->clientError(_('No tagger.'), 404);
+ return false;
+ }
+
+ $user = User::staticGet('nickname', $tagger);
+
+ if (!$user) {
+ $this->clientError(_('No such user.'), 404);
+ return false;
+ }
+
+ $this->tagger = $user->getProfile();
+ $this->peopletag = Profile_list::pkeyGet(array('tagger' => $user->id, 'tag' => $tag));
+
+ if (!$this->peopletag) {
+ $this->clientError(_('No such peopletag.'), 404);
+ return false;
+ }
+
+ return true;
+ }
+
+ function title()
+ {
+ if ($this->page == 1) {
+ return sprintf(_('People tagged %s by %s'),
+ $this->peopletag->tag, $this->tagger->nickname);
+ } else {
+ return sprintf(_('People tagged %s by %s, page %d'),
+ $this->peopletag->tag, $this->user->nickname,
+ $this->page);
+ }
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showPage();
+ }
+
+ function showPageNotice()
+ {
+ }
+
+ function showLocalNav()
+ {
+ $nav = new PeopletagGroupNav($this, $this->peopletag);
+ $nav->show();
+ }
+
+ function showContent()
+ {
+ $offset = ($this->page-1) * PROFILES_PER_PAGE;
+ $limit = PROFILES_PER_PAGE + 1;
+
+ $cnt = 0;
+
+ $subs = $this->peopletag->getTagged($offset, $limit);
+
+ if ($subs) {
+ $subscriber_list = new PeopletagMemberList($subs, $this->peopletag, $this);
+ $cnt = $subscriber_list->show();
+ }
+
+ $subs->free();
+
+ $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE,
+ $this->page, 'peopletagged',
+ array('tagger' => $this->tagger->nickname,
+ 'tag' => $this->peopletag->tag));
+ }
+}
+
+class PeopletagMemberList extends ProfileList
+{
+ var $peopletag = null;
+
+ function __construct($profile, $peopletag, $action)
+ {
+ parent::__construct($profile, $action);
+
+ $this->peopletag = $peopletag;
+ }
+
+ function newListItem($profile)
+ {
+ return new PeopletagMemberListItem($profile, $this->peopletag, $this->action);
+ }
+}
+
+class PeopletagMemberListItem extends ProfileListItem
+{
+ var $peopletag = null;
+
+ function __construct($profile, $peopletag, $action)
+ {
+ parent::__construct($profile, $action);
+
+ $this->peopletag = $peopletag;
+ }
+
+ function showFullName()
+ {
+ parent::showFullName();
+ if ($this->profile->id == $this->peopletag->tagger) {
+ $this->out->text(' ');
+ $this->out->element('span', 'role', _('Creator'));
+ }
+ }
+
+ function showActions()
+ {
+ $this->startActions();
+ if (Event::handle('StartProfileListItemActionElements', array($this))) {
+ $this->showSubscribeButton();
+ // TODO: Untag button
+ Event::handle('EndProfileListItemActionElements', array($this));
+ }
+ $this->endActions();
+ }
+
+ function linkAttributes()
+ {
+ // tagging people is healthy page-rank flow.
+ return parent::linkAttributes();
+ }
+
+ /**
+ * Fetch necessary return-to arguments for the profile forms
+ * to return to this list when they're done.
+ *
+ * @return array
+ */
+ protected function returnToArgs()
+ {
+ $args = array('action' => 'peopletagged',
+ 'tag' => $this->peopletag->tag,
+ 'tagger' => $this->profile->nickname);
+ $page = $this->out->arg('page');
+ if ($page) {
+ $args['param-page'] = $page;
+ }
+ return $args;
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * People tags by a user
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Personal
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/lib/peopletaglist.php';
+
+class PeopletagsbyuserAction extends OwnerDesignAction
+{
+ var $page = null;
+ var $tagger = null;
+ var $tags = null;
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function title()
+ {
+ if ($this->page == 1) {
+ if ($this->isOwner()) {
+ if ($this->arg('private')) {
+ return _('Private people tags by you');
+ } else if ($this->arg('public')) {
+ return _('Public people tags by you');
+ }
+ return _('People tags by you');
+ }
+ return sprintf(_("People tags by %s"), $this->tagger->nickname);
+ } else {
+ return sprintf(_("People tags by %s, page %d"), $this->tagger->nickname, $this->page);
+ }
+ }
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ if ($this->arg('public') && $this->arg('private')) {
+ $this->args['public'] = $this->args['private'] = false;
+ }
+
+ $nickname_arg = $this->arg('nickname');
+ $nickname = common_canonical_nickname($nickname_arg);
+
+ // Permanent redirect on non-canonical nickname
+
+ if ($nickname_arg != $nickname) {
+ $args = $this->getSelfUrlArgs();
+ if ($this->arg('page') && $this->arg('page') != 1) {
+ $args['page'] = $this->arg['page'];
+ }
+ common_redirect(common_local_url('peopletagsbyuser', $args), 301);
+ return false;
+ }
+
+ $this->user = User::staticGet('nickname', $nickname);
+
+ if (!$this->user) {
+ $this->clientError(_('No such user.'), 404);
+ return false;
+ }
+
+ $this->tagger = $this->user->getProfile();
+
+ if (!$this->tagger) {
+ $this->serverError(_('User has no profile.'));
+ return false;
+ }
+
+ $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
+
+
+ $offset = ($this->page-1) * PEOPLETAGS_PER_PAGE;
+ $limit = PEOPLETAGS_PER_PAGE + 1;
+
+ $user = common_current_user();
+ if ($this->arg('public')) {
+ $this->tags = $this->tagger->getOwnedTags(false, $offset, $limit);
+ } else if ($this->arg('private')) {
+ if (empty($user)) {
+ $this->clientError(_('Not logged in'), 403);
+ }
+
+ if ($this->isOwner()) {
+ $this->tags = $this->tagger->getPrivateTags($offset, $limit);
+ } else {
+ $this->clientError(_('You cannot view others\' private people tags'), 403);
+ }
+ } else {
+ $this->tags = $this->tagger->getOwnedTags(common_current_user(), $offset, $limit);
+ }
+ return true;
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ # Post from the tag dropdown; redirect to a GET
+
+ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ common_redirect(common_local_url('peopletagsbyuser', $this->getSelfUrlArgs()), 303);
+ return;
+ }
+
+ $this->showPage();
+ }
+
+ function showModeSelector()
+ {
+ $this->elementStart('dl', array('id'=>'filter_tags'));
+ $this->element('dt', null, _('Mode'));
+ $this->elementStart('dd');
+ $this->elementStart('ul');
+ $this->elementStart('li', array('id' => 'filter_tags_for',
+ 'class' => 'child_1'));
+ $this->element('a',
+ array('href' =>
+ common_local_url('peopletagsforuser',
+ array('nickname' => $this->user->nickname))),
+ sprintf(_('People tags for %s'), $this->tagger->nickname));
+ $this->elementEnd('li');
+
+ if ($this->isOwner()) {
+ $this->elementStart('li', array('id'=>'filter_tags_item'));
+ $this->elementStart('form', array('name' => 'modeselector',
+ 'id' => 'form_filter_bymode',
+ 'action' => common_local_url('peopletagsbyuser',
+ array('nickname' => $this->tagger->nickname)),
+ 'method' => 'post'));
+ $this->elementStart('fieldset');
+ $this->element('legend', null, _('Select tag to filter'));
+
+ $priv = $this->arg('private');
+ $pub = $this->arg('public');
+
+ if (!$priv && !$pub) {
+ $priv = $pub = true;
+ }
+ $this->checkbox('private', _m('Private'), $priv,
+ _m('Show private tags'));
+ $this->checkbox('public', _m('Public'), $pub,
+ _m('Show public tags'));
+ $this->hidden('nickname', $this->user->nickname);
+ $this->submit('submit', _('Go'));
+ $this->elementEnd('fieldset');
+ $this->elementEnd('form');
+ $this->elementEnd('li');
+ }
+ $this->elementEnd('ul');
+ $this->elementEnd('dd');
+ $this->elementEnd('dl');
+ }
+ function showLocalNav()
+ {
+ $nav = new PersonalGroupNav($this);
+ $nav->show();
+ }
+
+ function showAnonymousMessage()
+ {
+ $notice =
+ sprintf(_('These are people tags created by **%s**. ' .
+ 'People tags are how you sort similar ' .
+ 'people on %%%%site.name%%%%, a [micro-blogging]' .
+ '(http://en.wikipedia.org/wiki/Micro-blogging) service ' .
+ 'based on the Free Software [StatusNet](http://status.net/) tool. ' .
+ 'You can easily keep track of what they ' .
+ 'are doing by subscribing to the tag\'s timeline.' ), $this->tagger->nickname);
+ $this->elementStart('div', array('id' => 'anon_notice'));
+ $this->raw(common_markup_to_html($notice));
+ $this->elementEnd('div');
+ }
+
+ function showPageNotice()
+ {
+ $this->elementStart('div', 'instructions');
+ $this->showModeSelector();
+ $this->elementEnd('div');
+ }
+
+ function showContent()
+ {
+ #TODO: controls here.
+
+ $pl = new PeopletagList($this->tags, $this);
+ $cnt = $pl->show();
+
+ if ($cnt == 0) {
+ $this->showEmptyListMessage();
+ }
+ $this->pagination($this->page > 1, $cnt > PEOPLETAGS_PER_PAGE,
+ $this->page, 'peopletagsbyuser', $this->getSelfUrlArgs());
+ }
+
+ function getSelfUrlArgs()
+ {
+ $args = array();
+ if ($this->arg('private')) {
+ $args['private'] = 1;
+ } else if ($this->arg('public')) {
+ $args['public'] = 1;
+ }
+ $args['nickname'] = $this->trimmed('nickname');
+
+ return $args;
+ }
+
+ function isOwner()
+ {
+ $user = common_current_user();
+ return !empty($user) && $user->id == $this->tagger->id;
+ }
+
+ function showEmptyListMessage()
+ {
+ $message = sprintf(_('%s has not created any [people tags](%%%%doc.tags%%%%) yet.'), $this->tagger->nickname);
+ $this->elementStart('div', 'guide');
+ $this->raw(common_markup_to_html($message));
+ $this->elementEnd('div');
+ }
+
+ function showSections()
+ {
+ #TODO: tags with most subscribers
+ #TODO: tags with most "members"
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * People tags for a user
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Personal
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/lib/peopletaglist.php';
+
+class PeopletagsforuserAction extends OwnerDesignAction
+{
+ var $page = null;
+ var $tagged = null;
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function title()
+ {
+ if ($this->page == 1) {
+ return sprintf(_("People tags for %s"), $this->tagged->nickname);
+ } else {
+ return sprintf(_("People tags for %s, page %d"), $this->tagged->nickname, $this->page);
+ }
+ }
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $nickname_arg = $this->arg('nickname');
+ $nickname = common_canonical_nickname($nickname_arg);
+
+ // Permanent redirect on non-canonical nickname
+
+ if ($nickname_arg != $nickname) {
+ $args = array('nickname' => $nickname);
+ if ($this->arg('page') && $this->arg('page') != 1) {
+ $args['page'] = $this->arg['page'];
+ }
+ common_redirect(common_local_url('peopletagsforuser', $args), 301);
+ return false;
+ }
+
+ $this->user = User::staticGet('nickname', $nickname);
+
+ if (!$this->user) {
+ $this->clientError(_('No such user.'), 404);
+ return false;
+ }
+
+ $this->tagged = $this->user->getProfile();
+
+ if (!$this->tagged) {
+ $this->serverError(_('User has no profile.'));
+ return false;
+ }
+
+ $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
+
+ return true;
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showPage();
+ }
+
+ function showLocalNav()
+ {
+ $nav = new PersonalGroupNav($this);
+ $nav->show();
+ }
+
+ function showAnonymousMessage()
+ {
+ $notice =
+ sprintf(_('These are people tags for **%s**. ' .
+ 'People tags are how you sort similar ' .
+ 'people on %%%%site.name%%%%, a [micro-blogging]' .
+ '(http://en.wikipedia.org/wiki/Micro-blogging) service ' .
+ 'based on the Free Software [StatusNet](http://status.net/) tool. ' .
+ 'You can easily keep track of what they ' .
+ 'are doing by subscribing to the tag\'s timeline.' ), $this->tagged->nickname);
+ $this->elementStart('div', array('id' => 'anon_notice'));
+ $this->raw(common_markup_to_html($notice));
+ $this->elementEnd('div');
+ }
+
+ function showPageNotice()
+ {
+ $this->elementStart('dl', 'filter_tags');
+ $this->elementStart('dd', array('id' => 'filter_tags_for',
+ 'class' => 'child_1'));
+
+ $user = common_current_user();
+ $text = ($this->tagged->id == @$user->id) ? _('People tags by you') :
+ sprintf(_('People tags by %s'), $this->tagged->nickname);
+ $this->element('a',
+ array('href' =>
+ common_local_url('peopletagsbyuser',
+ array('nickname' => $this->tagged->nickname))),
+ $text);
+ $this->elementEnd('dd');
+ $this->elementEnd('dl');
+ }
+
+
+ function showContent()
+ {
+ #TODO: controls here.
+
+ $offset = ($this->page-1) * PEOPLETAGS_PER_PAGE;
+ $limit = PEOPLETAGS_PER_PAGE + 1;
+
+ $ptags = $this->tagged->getOtherTags(common_current_user(), $offset, $limit);
+
+ $pl = new PeopletagList($ptags, $this);
+ $cnt = $pl->show();
+
+ if ($cnt == 0) {
+ $this->showEmptyListMessage();
+ }
+ $this->pagination($this->page > 1, $cnt > PEOPLETAGS_PER_PAGE,
+ $this->page, 'peopletagsforuser', array('nickname' => $this->tagged->id));
+ }
+
+ function showEmptyListMessage()
+ {
+ $message = sprintf(_('%s has not been [tagged](%%%%doc.tags%%%%) by anyone yet.'), $this->tagged->nickname);
+ $this->elementStart('div', 'guide');
+ $this->raw(common_markup_to_html($message));
+ $this->elementEnd('div');
+ }
+
+ function showSections()
+ {
+ #TODO: tags with most subscribers
+ #TODO: tags with most "members"
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * List of peopletag subscribers
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Group
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+require_once(INSTALLDIR.'/lib/profilelist.php');
+
+/**
+ * List of peopletag subscribers
+ *
+ * @category Peopletag
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class PeopletagsubscribersAction extends OwnerDesignAction
+{
+ var $page = null;
+ var $peopletag = null;
+ var $tagger = null;
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
+
+ $tagger_arg = $this->arg('tagger');
+ $tag_arg = $this->arg('tag');
+ $tagger = common_canonical_nickname($tagger_arg);
+ $tag = common_canonical_tag($tag_arg);
+
+ // Permanent redirect on non-canonical nickname
+
+ if ($tagger_arg != $tagger || $tag_arg != $tag) {
+ $args = array('tagger' => $nickname, 'tag' => $tag);
+ if ($this->page != 1) {
+ $args['page'] = $this->page;
+ }
+ common_redirect(common_local_url('peopletagged', $args), 301);
+ return false;
+ }
+
+ if (!$tagger) {
+ $this->clientError(_('No tagger.'), 404);
+ return false;
+ }
+
+ $user = User::staticGet('nickname', $tagger);
+
+ if (!$user) {
+ $this->clientError(_('No such user.'), 404);
+ return false;
+ }
+
+ $this->tagger = $user->getProfile();
+ $this->peopletag = Profile_list::pkeyGet(array('tagger' => $user->id, 'tag' => $tag));
+
+ if (!$this->peopletag) {
+ $this->clientError(_('No such peopletag.'), 404);
+ return false;
+ }
+
+ return true;
+ }
+
+ function title()
+ {
+ if ($this->page == 1) {
+ return sprintf(_('Subscribers of people tagged %s by %s'),
+ $this->peopletag->tag, $this->tagger->nickname);
+ } else {
+ return sprintf(_('Subscribers of people tagged %s by %s, page %d'),
+ $this->peopletag->tag, $this->tagger->nickname,
+ $this->page);
+ }
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showPage();
+ }
+
+ function showPageNotice()
+ {
+ }
+
+ function showLocalNav()
+ {
+ $nav = new PeopletagGroupNav($this);
+ $nav->show();
+ }
+
+ function showContent()
+ {
+ $offset = ($this->page-1) * PROFILES_PER_PAGE;
+ $limit = PROFILES_PER_PAGE + 1;
+
+ $cnt = 0;
+
+ $subs = $this->peopletag->getSubscribers($offset, $limit);
+
+ if ($subs) {
+ $subscriber_list = new PeopletagSubscriberList($subs, $this->peopletag, $this);
+ $cnt = $subscriber_list->show();
+ }
+
+ $subs->free();
+
+ $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE,
+ $this->page, 'peopletagsubscribers',
+ array('tagger' => $this->tagger->nickname,
+ 'tag' => $this->peopletag->tag));
+ }
+}
+
+class PeopletagSubscriberList extends ProfileList
+{
+ var $peopletag = null;
+
+ function __construct($profile, $peopletag, $action)
+ {
+ parent::__construct($profile, $action);
+
+ $this->peopletag = $peopletag;
+ }
+
+ function newListItem($profile)
+ {
+ return new PeopletagSubscriberListItem($profile, $this->peopletag, $this->action);
+ }
+}
+
+class PeopletagSubscriberListItem extends ProfileListItem
+{
+ var $peopletag = null;
+
+ function __construct($profile, $peopletag, $action)
+ {
+ parent::__construct($profile, $action);
+
+ $this->peopletag = $peopletag;
+ }
+
+ function showFullName()
+ {
+ parent::showFullName();
+ if ($this->profile->id == $this->peopletag->tagger) {
+ $this->out->text(' ');
+ $this->out->element('span', 'role', _('Creator'));
+ }
+ }
+
+ function showActions()
+ {
+ $this->startActions();
+ if (Event::handle('StartProfileListItemActionElements', array($this))) {
+ $this->showSubscribeButton();
+ Event::handle('EndProfileListItemActionElements', array($this));
+ }
+ $this->endActions();
+ }
+
+ function linkAttributes()
+ {
+ $aAttrs = parent::linkAttributes();
+
+ if (common_config('nofollow', 'members')) {
+ $aAttrs['rel'] .= ' nofollow';
+ }
+
+ return $aAttrs;
+ }
+
+ function homepageAttributes()
+ {
+ $aAttrs = parent::linkAttributes();
+
+ if (common_config('nofollow', 'members')) {
+ $aAttrs['rel'] = 'nofollow';
+ }
+
+ return $aAttrs;
+ }
+
+ /**
+ * Fetch necessary return-to arguments for the profile forms
+ * to return to this list when they're done.
+ *
+ * @return array
+ */
+ protected function returnToArgs()
+ {
+ $args = array('action' => 'peopletagsubscribers',
+ 'tag' => $this->peopletag->tag,
+ 'tagger' => $this->profile->nickname);
+ $page = $this->out->arg('page');
+ if ($page) {
+ $args['param-page'] = $page;
+ }
+ return $args;
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * People tags subscribed to by a user
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Personal
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/lib/peopletaglist.php';
+
+class PeopletagsubscriptionsAction extends OwnerDesignAction
+{
+ var $page = null;
+ var $profile = null;
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function title()
+ {
+ if ($this->page == 1) {
+ return sprintf(_("People tags subscriptions by %s"), $this->profile->nickname);
+ } else {
+ return sprintf(_("People tags subscriptions by %s, page %d"), $this->profile->nickname, $this->page);
+ }
+ }
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $nickname_arg = $this->arg('nickname');
+ $nickname = common_canonical_nickname($nickname_arg);
+
+ // Permanent redirect on non-canonical nickname
+
+ if ($nickname_arg != $nickname) {
+ $args = array('nickname' => $nickname);
+ if ($this->arg('page') && $this->arg('page') != 1) {
+ $args['page'] = $this->arg['page'];
+ }
+ common_redirect(common_local_url('peopletagsbyuser', $args), 301);
+ return false;
+ }
+
+ $user = User::staticGet('nickname', $nickname);
+
+ if (!$user) {
+ $this->clientError(_('No such user.'), 404);
+ return false;
+ }
+
+ $this->profile = $user->getProfile();
+
+ if (!$this->profile) {
+ $this->serverError(_('User has no profile.'));
+ return false;
+ }
+
+ $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
+
+ return true;
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showPage();
+ }
+
+ function showLocalNav()
+ {
+ $nav = new PersonalGroupNav($this);
+ $nav->show();
+ }
+
+ function showAnonymousMessage()
+ {
+ $notice =
+ sprintf(_('These are people tags subscribed to by **%s**. ' .
+ 'People tags are how you sort similar ' .
+ 'people on %%%%site.name%%%%, a [micro-blogging]' .
+ '(http://en.wikipedia.org/wiki/Micro-blogging) service ' .
+ 'based on the Free Software [StatusNet](http://status.net/) tool. ' .
+ 'You can easily keep track of what they ' .
+ 'are doing by subscribing to the tag\'s timeline.' ), $this->profile->nickname);
+ $this->elementStart('div', array('id' => 'anon_notice'));
+ $this->raw(common_markup_to_html($notice));
+ $this->elementEnd('div');
+ }
+
+ function showContent()
+ {
+ $offset = ($this->page-1) * PEOPLETAGS_PER_PAGE;
+ $limit = PEOPLETAGS_PER_PAGE + 1;
+
+ $ptags = $this->profile->getTagSubscriptions($offset, $limit);
+
+ $pl = new PeopletagList($ptags, $this);
+ $cnt = $pl->show();
+
+ $this->pagination($this->page > 1, $cnt > PEOPLETAGS_PER_PAGE,
+ $this->page, 'peopletagsubscriptions', array('nickname' => $this->profile->id));
+ }
+
+ function showSections()
+ {
+ #TODO: tags with most subscribers
+ #TODO: tags with most "members"
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008-2010, StatusNet, Inc.
+ *
+ * Subscription action.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5
+ *
+ * @category Action
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/peopletageditform.php';
+
+/**
+ * Subscription action
+ *
+ * Subscribing to a profile. Does not work for OMB 0.1 remote subscriptions,
+ * but may work for other remote subscription protocols, like OStatus.
+ *
+ * Takes parameters:
+ *
+ * - subscribeto: a profile ID
+ * - token: session token to prevent CSRF attacks
+ * - ajax: boolean; whether to return Ajax or full-browser results
+ *
+ * Only works if the current user is logged in.
+ *
+ * @category Action
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link http://status.net/
+ */
+
+class ProfilecompletionAction extends Action
+{
+ var $user;
+ var $peopletag;
+ var $field;
+ var $msg;
+
+ /**
+ * Check pre-requisites and instantiate attributes
+ *
+ * @param Array $args array of arguments (URL, GET, POST)
+ *
+ * @return boolean success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ // CSRF protection
+
+ $token = $this->trimmed('token');
+
+ if (!$token || $token != common_session_token()) {
+ $this->clientError(_('There was a problem with your session token.'.
+ ' Try again, please.'));
+ return false;
+ }
+
+ // Only for logged-in users
+
+ $this->user = common_current_user();
+
+ if (empty($this->user)) {
+ $this->clientError(_('Not logged in.'));
+ return false;
+ }
+
+ $id = $this->arg('peopletag_id');
+ $this->peopletag = Profile_list::staticGet('id', $id);
+
+ if (empty($this->peopletag)) {
+ $this->clientError(_('No such peopletag.'));
+ return false;
+ }
+
+ $field = $this->arg('field');
+ if (!in_array($field, array('fulltext', 'nickname', 'fullname', 'description', 'location', 'uri'))) {
+ $this->clientError(sprintf(_('Unidentified field %s'), htmlspecialchars($field)), 404);
+ return false;
+ }
+ $this->field = $field;
+
+ return true;
+ }
+
+ /**
+ * Handle request
+ *
+ * Does the subscription and returns results.
+ *
+ * @param Array $args unused.
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ $this->msg = null;
+
+ $this->startHTML('text/xml;charset=utf-8');
+ $this->elementStart('head');
+ $this->element('title', null, _('Search results'));
+ $this->elementEnd('head');
+ $this->elementStart('body');
+ $profiles = $this->getResults();
+
+ if ($this->msg !== null) {
+ $this->element('p', 'error', $this->msg);
+ } else {
+ if (count($profiles) > 0) {
+ $this->elementStart('ul', array('id' => 'profile_search_results', 'class' => 'profile-lister'));
+ foreach ($profiles as $profile) {
+ $this->showProfileItem($profile);
+ }
+ $this->elementEnd('ul');
+ } else {
+ $this->element('p', 'error', _('No results.'));
+ }
+ }
+ $this->elementEnd('body');
+ $this->elementEnd('html');
+ }
+
+ function getResults()
+ {
+ $profiles = array();
+ $q = $this->arg('q');
+ $q = strtolower($q);
+ if (strlen($q) < 3) {
+ $this->msg = _('The search string must be atleast 3 characters long');
+ }
+ $page = $this->arg('page');
+ $page = (int) (empty($page) ? 1 : $page);
+
+ $profile = new Profile();
+ $search_engine = $profile->getSearchEngine('profile');
+
+ if (Event::handle('StartProfileCompletionSearch', array($this, &$profile, $search_engine))) {
+ $search_engine->set_sort_mode('chron');
+ $search_engine->limit((($page-1)*PROFILES_PER_PAGE), PROFILES_PER_PAGE + 1);
+
+ if (false === $search_engine->query($q)) {
+ $cnt = 0;
+ }
+ else {
+ $cnt = $profile->find();
+ }
+ Event::handle('EndProfileCompletionSearch', $this, &$profile, $search_engine);
+ }
+
+ while ($profile->fetch()) {
+ $profiles[] = clone($profile);
+ }
+ return $this->filter($profiles);
+ }
+
+ function filter($profiles)
+ {
+ $current = $this->user->getProfile();
+ $filtered_profiles = array();
+ foreach ($profiles as $profile) {
+ if ($current->canTag($profile)) {
+ $filtered_profiles[] = $profile;
+ }
+ }
+ return $filtered_profiles;
+ }
+
+ function showProfileItem($profile)
+ {
+ $this->elementStart('li', 'entity_removable_profile');
+ $item = new TaggedProfileItem($this, $profile);
+ $item->show();
+ $this->elementStart('span', 'entity_actions');
+
+ if ($profile->isTagged($this->peopletag)) {
+ $untag = new UntagButton($this, $profile, $this->peopletag);
+ $untag->show();
+ } else {
+ $tag = new TagButton($this, $profile, $this->peopletag);
+ $tag->show();
+ }
+
+ $this->elementEnd('span');
+ $this->elementEnd('li');
+ }
+}
return;
}
- if ($tagstring) {
- $tags = array_map('common_canonical_tag', preg_split('/[\s,]+/', $tagstring));
- } else {
- $tags = array();
- }
+ $tags = array();
+ $tag_priv = array();
+ if (is_string($tagstring) && strlen($tagstring) > 0) {
- foreach ($tags as $tag) {
- if (!common_valid_profile_tag($tag)) {
- // TRANS: Validation error in form for profile settings.
- // TRANS: %s is an invalid tag.
- $this->showForm(sprintf(_('Invalid tag: "%s".'), $tag));
- return;
+ $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.
+ $this->showForm(sprintf(_('Invalid tag: "%s"'), $tag));
+ return;
+ }
+
+ $tag_priv[$tag] = $private;
}
}
}
// Set the user tags
- $result = $user->setSelfTags($tags);
+ $result = $user->setSelfTags($tags, $tag_priv);
if (!$result) {
// TRANS: Server error thrown when user profile settings tags could not be saved.
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Permalink for a peopletag
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Peopletag
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+class ProfiletagbyidAction extends Action
+{
+ /** peopletag we're viewing. */
+ var $peopletag = null;
+
+ /**
+ * Is this page read-only?
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $id = $this->arg('id');
+ $tagger_id = $this->arg('tagger_id');
+
+ if (!$id) {
+ $this->clientError(_('No ID.'));
+ return false;
+ }
+
+ common_debug("Peopletag id $id by user id $tagger_id");
+
+ $this->peopletag = Profile_list::staticGet('id', $id);
+
+ if (!$this->peopletag) {
+ $this->clientError(_('No such people tag.'), 404);
+ return false;
+ }
+
+ $user = User::staticGet('id', $tagger_id);
+ if (!$user) {
+ // remote peopletag, permanently redirect
+ common_redirect($this->peopletag->permalink(), 301);
+ }
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Shows a profile for the group, some controls, and a list of
+ * group notices.
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ common_redirect($this->peopletag->homeUrl(), 303);
+ }
+}
$pop->show();
$gbp = new GroupsByMembersSection($this);
$gbp->show();
+ $ptp = new PeopletagsBySubsSection($this);
+ $ptp->show();
$feat = new FeaturedUsersSection($this);
$feat->show();
}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Public tag cloud for notices
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Public
+ * @package StatusNet
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2008 Mike Cochrane
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
+
+define('TAGS_PER_PAGE', 100);
+
+/**
+ * Public tag cloud for notices
+ *
+ * @category Personal
+ * @package StatusNet
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2008 Mike Cochrane
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @link http://status.net/
+ */
+
+class PublicpeopletagcloudAction extends Action
+{
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function title()
+ {
+ return _('Public people tag cloud');
+ }
+
+ function showPageNotice()
+ {
+ $this->element('p', 'instructions',
+ sprintf(_('These are most used people tags on %s '),
+ common_config('site', 'name')));
+ }
+
+ function showEmptyList()
+ {
+ $message = _('No one has [tagged](%%doc.tags%%) anyone yet.') . ' ';
+
+ if (common_logged_in()) {
+ $message .= _('Be the first to tag someone!');
+ }
+ else {
+ $message .= _('Why not [register an account](%%action.register%%) and be the first to tag someone!');
+ }
+
+ $this->elementStart('div', 'guide');
+ $this->raw(common_markup_to_html($message));
+ $this->elementEnd('div');
+ }
+
+ function showLocalNav()
+ {
+ $nav = new PublicGroupNav($this);
+ $nav->show();
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showPage();
+ }
+
+ 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');
+ $this->element('dt', null, _('People tag 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();
+ }
+ }
+
+ function showTag($tag, $weight, $relative)
+ {
+ if ($relative > 0.1) {
+ $rel = 'tag-cloud-7';
+ } else if ($relative > 0.05) {
+ $rel = 'tag-cloud-6';
+ } else if ($relative > 0.02) {
+ $rel = 'tag-cloud-5';
+ } else if ($relative > 0.01) {
+ $rel = 'tag-cloud-4';
+ } else if ($relative > 0.005) {
+ $rel = 'tag-cloud-3';
+ } else if ($relative > 0.002) {
+ $rel = 'tag-cloud-2';
+ } else {
+ $rel = 'tag-cloud-1';
+ }
+
+ $this->elementStart('li', $rel);
+
+ $count = ($weight == 1) ? '1 person tagged' : '%d people tagged';
+ $this->element('a', array('href' => common_local_url('peopletag', array('tag' => $tag)),
+ 'title' => sprintf(_($count), $weight)), $tag);
+ $this->elementEnd('li');
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008-2010, StatusNet, Inc.
+ *
+ * Subscription action.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * PHP version 5
+ *
+ * @category Action
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/togglepeopletag.php';
+
+/**
+ * Subscription action
+ *
+ * Subscribing to a profile. Does not work for OMB 0.1 remote subscriptions,
+ * but may work for other remote subscription protocols, like OStatus.
+ *
+ * Takes parameters:
+ *
+ * - subscribeto: a profile ID
+ * - token: session token to prevent CSRF attacks
+ * - ajax: boolean; whether to return Ajax or full-browser results
+ *
+ * Only works if the current user is logged in.
+ *
+ * @category Action
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link http://status.net/
+ */
+
+class RemovepeopletagAction extends Action
+{
+ var $user;
+ var $tagged;
+ var $peopletag;
+
+ /**
+ * Check pre-requisites and instantiate attributes
+ *
+ * @param Array $args array of arguments (URL, GET, POST)
+ *
+ * @return boolean success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ // CSRF protection
+
+ $token = $this->trimmed('token');
+
+ if (!$token || $token != common_session_token()) {
+ $this->clientError(_('There was a problem with your session token.'.
+ ' Try again, please.'));
+ return false;
+ }
+
+ // Only for logged-in users
+
+ $this->user = common_current_user();
+
+ if (empty($this->user)) {
+ $this->clientError(_('Not logged in.'));
+ return false;
+ }
+
+ // Profile to subscribe to
+
+ $tagged_id = $this->arg('tagged');
+
+ $this->tagged = Profile::staticGet('id', $tagged_id);
+
+ if (empty($this->tagged)) {
+ $this->clientError(_('No such profile.'));
+ return false;
+ }
+
+ $id = $this->arg('peopletag_id');
+ $this->peopletag = Profile_list::staticGet('id', $id);
+
+ if (empty($this->peopletag)) {
+ $this->clientError(_('No such peopletag.'));
+ return false;
+ }
+
+ // OMB 0.1 doesn't have a mechanism for local-server-
+ // originated tag.
+
+ $omb01 = Remote_profile::staticGet('id', $tagged_id);
+
+ if (!empty($omb01)) {
+ $this->clientError(_('You cannot tag or untag an OMB 0.1'.
+ ' remote profile with this action.'));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Handle request
+ *
+ * Does the subscription and returns results.
+ *
+ * @param Array $args unused.
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ // Throws exception on error
+
+ $ptag = Profile_tag::unTag($this->user->id, $this->tagged->id,
+ $this->peopletag->tag);
+
+ if (!$ptag) {
+ $user = User::staticGet('id', $this->tagged->id);
+ if ($user) {
+ $this->clientError(
+ sprintf(_('There was an unexpected error while tagging %s'),
+ $user->nickname));
+ } else {
+ $this->clientError(sprintf(_('There was a problem tagging %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');
+ $this->element('title', null, _('Untagged'));
+ $this->elementEnd('head');
+ $this->elementStart('body');
+ $unsubscribe = new TagButton($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);
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Action for showing profiles self-tagged with a given tag
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Action
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * This class outputs a paginated list of profiles self-tagged with a given tag
+ *
+ * @category Output
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ *
+ * @see Action
+ */
+
+class SelftagAction extends Action
+{
+
+ var $tag = null;
+ var $page = null;
+
+ /**
+ * For initializing members of the class.
+ *
+ * @param array $argarray misc. arguments
+ *
+ * @return boolean true
+ */
+ function prepare($argarray)
+ {
+ parent::prepare($argarray);
+
+ $this->tag = $this->trimmed('tag');
+
+ if (!common_valid_profile_tag($this->tag)) {
+ $this->clientError(sprintf(_('Not a valid people tag: %s.'),
+ $this->tag));
+ return;
+ }
+
+ $this->page = ($this->arg('page')) ? $this->arg('page') : 1;
+
+ common_set_returnto($this->selfUrl());
+
+ return true;
+ }
+
+ /**
+ * Handler method
+ *
+ * @param array $argarray is ignored since it's now passed in in prepare()
+ *
+ * @return boolean is read only action?
+ */
+ function handle($argarray)
+ {
+ parent::handle($argarray);
+ $this->showPage();
+ }
+
+ /**
+ * Whips up a query to get a list of profiles based on the provided
+ * people tag and page, initalizes a ProfileList widget, and displays
+ * it to the user.
+ *
+ * @return nothing
+ */
+ function showContent()
+ {
+
+ $profile = new Profile();
+
+ $offset = ($this->page - 1) * PROFILES_PER_PAGE;
+ $limit = PROFILES_PER_PAGE + 1;
+
+ if (common_config('db', 'type') == 'pgsql') {
+ $lim = ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+ } else {
+ $lim = ' LIMIT ' . $offset . ', ' . $limit;
+ }
+
+ // XXX: memcached this
+
+ $qry = 'SELECT profile.* ' .
+ 'FROM profile JOIN ( profile_tag, profile_list ) ' .
+ 'ON profile.id = profile_tag.tagger ' .
+ 'AND profile_tag.tagger = profile_list.tagger ' .
+ 'AND profile_list.tag = profile_tag.tag ' .
+ 'WHERE profile_tag.tagger = profile_tag.tagged ' .
+ "AND profile_tag.tag = '%s' ";
+
+ $user = common_current_user();
+ if (empty($user)) {
+ $qry .= 'AND profile_list.private = false ';
+ } else {
+ $qry .= 'AND (profile_list.tagger = ' . $user->id .
+ ' OR profile_list.private = false) ';
+ }
+
+ $qry .= 'ORDER BY profile_tag.modified DESC%s';
+
+ $profile->query(sprintf($qry, $this->tag, $lim));
+
+ $ptl = new SelfTagProfileList($profile, $this); // pass the ammunition
+ $cnt = $ptl->show();
+
+ $this->pagination($this->page > 1,
+ $cnt > PROFILES_PER_PAGE,
+ $this->page,
+ 'selftag',
+ array('tag' => $this->tag));
+ }
+
+ /**
+ * Returns the page title
+ *
+ * @return string page title
+ */
+ function title()
+ {
+ return sprintf(_('Users self-tagged with %1$s - page %2$d'),
+ $this->tag, $this->page);
+ }
+
+}
+
+class SelfTagProfileList extends ProfileList
+{
+ function newListItem($profile)
+ {
+ return new SelfTagProfileListItem($profile, $this->action);
+ }
+}
+
+class SelfTagProfileListItem extends ProfileListItem
+{
+ function linkAttributes()
+ {
+ $aAttrs = parent::linkAttributes();
+
+ if (common_config('nofollow', 'selftag')) {
+ $aAttrs['rel'] .= ' nofollow';
+ }
+
+ return $aAttrs;
+ }
+
+ function homepageAttributes()
+ {
+ $aAttrs = parent::linkAttributes();
+
+ if (common_config('nofollow', 'selftag')) {
+ $aAttrs['rel'] = 'nofollow';
+ }
+
+ return $aAttrs;
+ }
+
+ function showTags()
+ {
+ $selftags = new SelfTagsWidget($this->out, $this->profile, $this->profile);
+ $selftags->show();
+
+ $user = common_current_user();
+
+ if (!empty($user) && $user->id != $this->profile->id &&
+ $user->getProfile()->canTag($this->profile)) {
+ $yourtags = new PeopleTagsWidget($this->out, $user, $this->profile);
+ $yourtags->show();
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Actions
+ * @package Actions
+ * @license GNU Affero General Public License http://www.gnu.org/licenses/
+ * @link http://status.net
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/lib/profileminilist.php';
+require_once INSTALLDIR.'/lib/peopletaglist.php';
+require_once INSTALLDIR.'/lib/noticelist.php';
+require_once INSTALLDIR.'/lib/feedlist.php';
+
+class ShowprofiletagAction extends Action
+{
+ var $notice, $tagger, $peopletag;
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $tagger_arg = $this->arg('tagger');
+ $tag_arg = $this->arg('tag');
+ $tagger = common_canonical_nickname($tagger_arg);
+ $tag = common_canonical_tag($tag_arg);
+
+ // Permanent redirect on non-canonical nickname
+
+ if ($tagger_arg != $tagger || $tag_arg != $tag) {
+ $args = array('tagger' => $nickname, 'tag' => $tag);
+ if ($this->page != 1) {
+ $args['page'] = $this->page;
+ }
+ common_redirect(common_local_url('showprofiletag', $args), 301);
+ return false;
+ }
+
+ if (!$tagger) {
+ $this->clientError(_('No tagger.'), 404);
+ return false;
+ }
+
+ $user = User::staticGet('nickname', $tagger);
+
+ if (!$user) {
+ $this->clientError(_('No such user.'), 404);
+ return false;
+ }
+
+ $this->tagger = $user->getProfile();
+ $this->peopletag = Profile_list::pkeyGet(array('tagger' => $user->id, 'tag' => $tag));
+
+ $current = common_current_user();
+ $can_see = !empty($this->peopletag) && (!$this->peopletag->private ||
+ ($this->peopletag->private && $this->peopletag->tagger === $current->id));
+
+ if (!$can_see) {
+ $this->clientError(_('No such peopletag.'), 404);
+ return false;
+ }
+
+ $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
+ $this->notice = $this->peopletag->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+
+ if ($this->page > 1 && $this->notice->N == 0) {
+ // TRANS: Server error when page not found (404)
+ $this->serverError(_('No such page.'), $code = 404);
+ }
+
+ return true;
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (!$this->peopletag) {
+ $this->clientError(_('No such user.'));
+ return;
+ }
+
+ $this->showPage();
+ }
+
+ function title()
+ {
+ if ($this->page > 1) {
+
+ if($this->peopletag->private) {
+ return sprintf(_('Private timeline for people tagged %s by you, page %d'),
+ $this->peopletag->tag, $this->page);
+ }
+
+ $current = common_current_user();
+ if (!empty($current) && $current->id == $this->peopletag->tagger) {
+ return sprintf(_('Timeline for people tagged %s by you, page %d'),
+ $this->peopletag->tag, $this->page);
+ }
+
+ // TRANS: Page title. %1$s is user nickname, %2$d is page number
+ return sprintf(_('Timeline for people tagged %1$s by %2$s, page %3$d'),
+ $this->peopletag->tag,
+ $this->tagger->nickname,
+ $this->page
+ );
+ } else {
+
+ if($this->peopletag->private) {
+ return sprintf(_('Private timeline of people tagged %s by you'),
+ $this->peopletag->tag, $this->page);
+ }
+
+ $current = common_current_user();
+ if (!empty($current) && $current->id == $this->peopletag->tagger) {
+ return sprintf(_('Timeline for people tagged %s by you'),
+ $this->peopletag->tag, $this->page);
+ }
+
+ // TRANS: Page title. %1$s is user nickname, %2$d is page number
+ return sprintf(_('Timeline for people tagged %1$s by %2$s'),
+ $this->peopletag->tag,
+ $this->tagger->nickname,
+ $this->page
+ );
+ }
+ }
+
+ function getFeeds()
+ {
+ #XXX: make these actually work
+ return array(new Feed(Feed::RSS2,
+ common_local_url(
+ 'ApiTimelineList', array(
+ 'user' => $this->tagger->id,
+ 'id' => $this->peopletag->id,
+ 'format' => 'rss'
+ )
+ ),
+ // TRANS: %1$s is user nickname
+ sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->tagger->nickname)),
+ new Feed(Feed::ATOM,
+ common_local_url(
+ 'ApiTimelineList', array(
+ 'user' => $this->tagger->id,
+ 'id' => $this->peopletag->id,
+ 'format' => 'atom'
+ )
+ ),
+ // TRANS: %1$s is user nickname
+ sprintf(_('Feed for people tagged %s by %s (Atom)'),
+ $this->peopletag->tag, $this->tagger->nickname
+ )
+ )
+ );
+ }
+
+ function showLocalNav()
+ {
+ $nav = new PeopletagGroupNav($this);
+ $nav->show();
+ }
+
+ function showEmptyListMessage()
+ {
+ // TRANS: %1$s is user nickname
+ $message = sprintf(_('This is the timeline for people tagged %s by %s but no one has posted anything yet.'), $this->peopletag->tag, $this->tagger->nickname) . ' ';
+
+ if (common_logged_in()) {
+ $current_user = common_current_user();
+ if ($this->tagger->id == $current_user->id) {
+ $message .= _('Try tagging more people.');
+ }
+ } else {
+ $message .= _('Why not [register an account](%%%%action.register%%%%) and start following this timeline.');
+ }
+
+ $this->elementStart('div', 'guide');
+ $this->raw(common_markup_to_html($message));
+ $this->elementEnd('div');
+ }
+
+ function showContent()
+ {
+ $this->showPeopletag();
+ $this->showNotices();
+ }
+
+ function showPeopletag()
+ {
+ $cur = common_current_user();
+ $tag = new Peopletag($this->peopletag, $cur, $this);
+ $tag->show();
+ }
+
+ function showNotices()
+ {
+ if (Event::handle('StartShowProfileTagContent', array($this))) {
+ $nl = new NoticeList($this->notice, $this);
+
+ $cnt = $nl->show();
+
+ if (0 == $cnt) {
+ $this->showEmptyListMessage();
+ }
+
+ $this->pagination(
+ $this->page > 1, $cnt > NOTICES_PER_PAGE,
+ $this->page, 'showprofiletag', array('tag' => $this->peopletag->tag,
+ 'tagger' => $this->tagger->nickname)
+ );
+
+ Event::handle('EndShowProfileTagContent', array($this));
+ }
+ }
+
+ function showSections()
+ {
+ $this->showTagged();
+ if (!$this->peopletag->private) {
+ $this->showSubscribers();
+ }
+ # $this->showStatistics();
+ }
+
+ function showPageTitle()
+ {
+ $this->element('h1', null, $this->title());
+ }
+
+ function showTagged()
+ {
+ $profile = $this->peopletag->getTagged(0, PROFILES_PER_MINILIST + 1);
+
+ $this->elementStart('div', array('id' => 'entity_tagged',
+ 'class' => 'section'));
+ if (Event::handle('StartShowTaggedProfilesMiniList', array($this))) {
+
+ $title = '';
+
+ $current = common_current_user();
+ if(!empty($current) && $this->peopletag->tagger == $current->id) {
+ $title = sprintf(_('People tagged %s by you'), $this->peopletag->tag);
+ } else {
+ $title = sprintf(_('People tagged %1$s by %2$s'),
+ $this->peopletag->tag,
+ $this->tagger->nickname);
+ }
+
+ $this->element('h2', null, $title);
+
+ $cnt = 0;
+
+ if (!empty($profile)) {
+ $pml = new ProfileMiniList($profile, $this);
+ $cnt = $pml->show();
+ if ($cnt == 0) {
+ $this->element('p', null, _('(None)'));
+ }
+ }
+
+ if ($cnt > PROFILES_PER_MINILIST) {
+ $this->elementStart('p');
+ $this->element('a', array('href' => common_local_url('taggedprofiles',
+ array('nickname' => $this->tagger->nickname,
+ 'profiletag' => $this->peopletag->tag)),
+ 'class' => 'more'),
+ _('Show all'));
+ $this->elementEnd('p');
+ }
+
+ Event::handle('EndShowTaggedProfilesMiniList', array($this));
+ }
+ $this->elementEnd('div');
+ }
+
+ function showSubscribers()
+ {
+ $profile = $this->peopletag->getSubscribers(0, PROFILES_PER_MINILIST + 1);
+
+ $this->elementStart('div', array('id' => 'entity_subscribers',
+ 'class' => 'section'));
+ if (Event::handle('StartShowProfileTagSubscribersMiniList', array($this))) {
+ $this->element('h2', null, _('Subscribers'));
+
+ $cnt = 0;
+
+ if (!empty($profile)) {
+ $pml = new ProfileMiniList($profile, $this);
+ $cnt = $pml->show();
+ if ($cnt == 0) {
+ $this->element('p', null, _('(None)'));
+ }
+ }
+
+ if ($cnt > PROFILES_PER_MINILIST) {
+ $this->elementStart('p');
+ $this->element('a', array('href' => common_local_url('profiletagsubscribers',
+ array('nickname' => $this->tagger->nickname,
+ 'profiletag' => $this->peopletag->tag)),
+ 'class' => 'more'),
+ _('All subscribers'));
+ $this->elementEnd('p');
+ }
+
+ Event::handle('EndShowProfileTagSubscribersMiniList', array($this));
+ }
+ $this->elementEnd('div');
+ }
+}
+
+class Peopletag extends PeopletagListItem
+{
+ function showStart()
+ {
+ $mode = $this->peopletag->private ? 'private' : 'public';
+ $this->out->elementStart('div', array('class' => 'hentry peopletag peopletag-profile mode-'.$mode,
+ 'id' => 'peopletag-' . $this->peopletag->id));
+ }
+
+ function showEnd()
+ {
+ $this->out->elementEnd('div');
+ }
+
+ function showAvatar()
+ {
+ parent::showAvatar(AVATAR_PROFILE_SIZE);
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Subscribe to a peopletag
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Peopletag
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Subscribe to a peopletag
+ *
+ * This is the action for subscribing to a peopletag. It works more or less like the join action
+ * for groups.
+ *
+ * @category Peopletag
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class SubscribepeopletagAction extends Action
+{
+ var $peopletag = null;
+ var $tagger = null;
+
+ /**
+ * Prepare to run
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ if (!common_logged_in()) {
+ $this->clientError(_('You must be logged in to unsubscribe to a peopletag.'));
+ return false;
+ }
+ // Only allow POST requests
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(_('This action only accepts POST requests.'));
+ return false;
+ }
+
+ // CSRF protection
+
+ $token = $this->trimmed('token');
+
+ if (!$token || $token != common_session_token()) {
+ $this->clientError(_('There was a problem with your session token.'.
+ ' Try again, please.'));
+ return false;
+ }
+
+ $tagger_arg = $this->trimmed('tagger');
+ $tag_arg = $this->trimmed('tag');
+
+ $id = intval($this->arg('id'));
+ if ($id) {
+ $this->peopletag = Profile_list::staticGet('id', $id);
+ } else {
+ $this->clientError(_('No ID given.'), 404);
+ return false;
+ }
+
+ if (!$this->peopletag || $this->peopletag->private) {
+ $this->clientError(_('No such peopletag.'), 404);
+ return false;
+ }
+
+ $this->tagger = Profile::staticGet('id', $this->peopletag->tagger);
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * On POST, add the current user to the group
+ *
+ * @param array $args unused
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ $cur = common_current_user();
+
+ try {
+ Profile_tag_subscription::add($this->peopletag, $cur);
+ } catch (Exception $e) {
+ $this->serverError(sprintf(_('Could not subscribe user %1$s to peopletag %2$s.'),
+ $cur->nickname, $this->peopletag->tag) . ' ' . $e->getMessage());
+ }
+
+ if ($this->boolean('ajax')) {
+ $this->startHTML('text/xml;charset=utf-8');
+ $this->elementStart('head');
+ $this->element('title', null, sprintf(_('%1$s subscribed to peopletag %2$s by %3$s'),
+ $cur->nickname,
+ $this->peopletag->tag,
+ $this->tagger->nickname));
+ $this->elementEnd('head');
+ $this->elementStart('body');
+ $lf = new UnsubscribePeopletagForm($this, $this->peopletag);
+ $lf->show();
+ $this->elementEnd('body');
+ $this->elementEnd('html');
+ } else {
+ common_redirect(common_local_url('peopletagsubscribers',
+ array('tagger' => $this->tagger->nickname,
+ 'tag' =>$this->peopletag->tag)),
+ 303);
+ }
+ }
+}
+++ /dev/null
-<?php
-/*
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, StatusNet, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
-
-require_once(INSTALLDIR.'/lib/settingsaction.php');
-
-class TagotherAction extends Action
-{
- var $profile = null;
- var $error = null;
-
- function prepare($args)
- {
- parent::prepare($args);
- if (!common_logged_in()) {
- $this->clientError(_('Not logged in.'), 403);
- return false;
- }
-
- $id = $this->trimmed('id');
- if (!$id) {
- $this->clientError(_('No ID argument.'));
- return false;
- }
-
- $this->profile = Profile::staticGet('id', $id);
-
- if (!$this->profile) {
- $this->clientError(_('No profile with that ID.'));
- return false;
- }
-
- return true;
- }
-
- function handle($args)
- {
- parent::handle($args);
- if ($_SERVER['REQUEST_METHOD'] == 'POST') {
- $this->saveTags();
- } else {
- $this->showForm($profile);
- }
- }
-
- function title()
- {
- return sprintf(_('Tag %s'), $this->profile->nickname);
- }
-
- function showForm($error=null)
- {
- $this->error = $error;
- $this->showPage();
- }
-
- function showContent()
- {
- $this->elementStart('div', 'entity_profile vcard author');
- $this->element('h2', null, _('User profile'));
-
- $avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE);
- $this->element('img', array('src' => ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE),
- 'class' => 'photo avatar entity_depiction',
- 'width' => AVATAR_PROFILE_SIZE,
- 'height' => AVATAR_PROFILE_SIZE,
- 'alt' =>
- ($this->profile->fullname) ? $this->profile->fullname :
- $this->profile->nickname));
-
- $this->element('a', array('href' => $this->profile->profileurl,
- 'class' => 'entity_nickname nickname'),
- $this->profile->nickname);
-
- if ($this->profile->fullname) {
- $this->element('div', 'fn entity_fn', $this->profile->fullname);
- }
-
- if ($this->profile->location) {
- $this->element('div', 'label entity_location', $this->profile->location);
- }
-
- if ($this->profile->homepage) {
- $this->element('a', array('href' => $this->profile->homepage,
- 'rel' => 'me',
- 'class' => 'url entity_url'),
- $this->profile->homepage);
- }
-
- if ($this->profile->bio) {
- $this->element('div', 'note entity_note', $this->profile->bio);
- }
-
- $this->elementEnd('div');
-
- $this->elementStart('form', array('method' => 'post',
- 'id' => 'form_tag_user',
- 'class' => 'form_settings',
- 'name' => 'tagother',
- 'action' => common_local_url('tagother', array('id' => $this->profile->id))));
-
- $this->elementStart('fieldset');
- $this->element('legend', null, _('Tag user'));
- $this->hidden('token', common_session_token());
- $this->hidden('id', $this->profile->id);
-
- $user = common_current_user();
-
- $this->elementStart('ul', 'form_data');
- $this->elementStart('li');
- $this->input('tags', _('Tags'),
- ($this->arg('tags')) ? $this->arg('tags') : implode(' ', Profile_tag::getTags($user->id, $this->profile->id)),
- _('Tags for this user (letters, numbers, -, ., and _), comma- or space- separated'));
- $this->elementEnd('li');
- $this->elementEnd('ul');
- $this->submit('save', _('Save'));
- $this->elementEnd('fieldset');
- $this->elementEnd('form');
- }
-
- 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)),
- 303);
- }
- }
-
- function showPageNotice()
- {
- if ($this->error) {
- $this->element('p', 'error', $this->error);
- } else {
- $this->elementStart('div', 'instructions');
- $this->element('p', null,
- _('Use this form to add tags to your subscribers or subscriptions.'));
- $this->elementEnd('div');
- }
- }
-}
-
--- /dev/null
+<?php
+/*
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
+
+require_once INSTALLDIR . '/lib/settingsaction.php';
+require_once INSTALLDIR . '/lib/peopletags.php';
+
+class TagprofileAction extends Action
+{
+ var $profile = null;
+ var $error = null;
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ if (!common_logged_in()) {
+ common_set_returnto($_SERVER['REQUEST_URI']);
+ if (Event::handle('RedirectToLogin', array($this, null))) {
+ common_redirect(common_local_url('login'), 303);
+ }
+ }
+
+ $id = $this->trimmed('id');
+ if (!$id) {
+ $this->profile = false;
+ } else {
+ $this->profile = Profile::staticGet('id', $id);
+
+ if (!$this->profile) {
+ $this->clientError(_('No profile with that ID.'));
+ return false;
+ }
+ }
+
+ $current = common_current_user()->getProfile();
+ if ($this->profile && !$current->canTag($this->profile)) {
+ $this->clientError(_('You cannot tag this user.'));
+ }
+ return true;
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+ if (Event::handle('StartTagProfileAction', array($this, $this->profile))) {
+ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ $this->saveTags();
+ } else {
+ $this->showForm();
+ }
+ Event::handle('EndTagProfileAction', array($this, $this->profile));
+ }
+ }
+
+ function title()
+ {
+ if (!$this->profile) {
+ return _('Tag a profile');
+ }
+ return sprintf(_('Tag %s'), $this->profile->nickname);
+ }
+
+ function showForm($error=null)
+ {
+ $this->error = $error;
+ if ($this->boolean('ajax')) {
+ $this->startHTML('text/xml;charset=utf-8');
+ $this->elementStart('head');
+ $this->element('title', null, _('Error'));
+ $this->elementEnd('head');
+ $this->elementStart('body');
+ $this->element('p', 'error', $error);
+ $this->elementEnd('body');
+ $this->elementEnd('html');
+ } else {
+ $this->showPage();
+ }
+ }
+
+ function showContent()
+ {
+ if (Event::handle('StartShowTagProfileForm', array($this, $this->profile)) && $this->profile) {
+ $this->elementStart('div', 'entity_profile vcard author');
+ $this->element('h2', null, _('User profile'));
+
+ $avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE);
+ $this->element('img', array('src' => ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE),
+ 'class' => 'photo avatar entity_depiction',
+ 'width' => AVATAR_PROFILE_SIZE,
+ 'height' => AVATAR_PROFILE_SIZE,
+ 'alt' =>
+ ($this->profile->fullname) ? $this->profile->fullname :
+ $this->profile->nickname));
+
+ $this->element('a', array('href' => $this->profile->profileurl,
+ 'class' => 'entity_nickname nickname'),
+ $this->profile->nickname);
+ if ($this->profile->fullname) {
+ $this->element('div', 'fn entity_fn', $this->profile->fullname);
+ }
+
+ if ($this->profile->location) {
+ $this->element('div', 'label entity_location', $this->profile->location);
+ }
+
+ if ($this->profile->homepage) {
+ $this->element('a', array('href' => $this->profile->homepage,
+ 'rel' => 'me',
+ 'class' => 'url entity_url'),
+ $this->profile->homepage);
+ }
+
+ if ($this->profile->bio) {
+ $this->element('div', 'note entity_note', $this->profile->bio);
+ }
+
+ $this->elementEnd('div');
+
+ $this->elementStart('form', array('method' => 'post',
+ 'id' => 'form_tag_user',
+ 'class' => 'form_settings',
+ 'name' => 'tagprofile',
+ 'action' => common_local_url('tagprofile', array('id' => $this->profile->id))));
+
+ $this->elementStart('fieldset');
+ $this->element('legend', null, _('Tag user'));
+ $this->hidden('token', common_session_token());
+ $this->hidden('id', $this->profile->id);
+
+ $user = common_current_user();
+
+ $this->elementStart('ul', 'form_data');
+ $this->elementStart('li');
+
+ $tags = Profile_tag::getTagsArray($user->id, $this->profile->id, $user->id);
+ $this->input('tags', _('Tags'),
+ ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $tags),
+ _('Tags for this user (letters, numbers, -, ., and _), comma- or space- separated'));
+ $this->elementEnd('li');
+ $this->elementEnd('ul');
+ $this->submit('save', _('Save'));
+ $this->elementEnd('fieldset');
+ $this->elementEnd('form');
+
+ Event::handle('EndShowTagProfileForm', array($this, $this->profile));
+ }
+ }
+
+ function saveTags()
+ {
+ $id = $this->trimmed('id');
+ $tagstring = $this->trimmed('tags');
+ $token = $this->trimmed('token');
+
+ if (Event::handle('StartSavePeopletags', array($this, $tagstring))) {
+ if (!$token || $token != common_session_token()) {
+ $this->showForm(_('There was a problem with your session token. '.
+ 'Try again, please.'));
+ return;
+ }
+
+ $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)) {
+ $this->showForm(sprintf(_('Invalid tag: "%s"'), $tag));
+ return;
+ }
+
+ $tag_priv[$tag] = $private;
+ }
+ }
+
+ $user = common_current_user();
+
+ try {
+ $result = Profile_tag::setTags($user->id, $this->profile->id, $tags, $tag_priv);
+ if (!$result) {
+ throw new Exception('The tags could not be saved.');
+ }
+ } catch (Exception $e) {
+ $this->showForm($e->getMessage());
+ return false;
+ }
+
+ 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');
+
+ if ($user->id == $this->profile->id) {
+ $widget = new SelftagsWidget($this, $user, $this->profile);
+ $widget->show();
+ } else {
+ $widget = new PeopletagsWidget($this, $user, $this->profile);
+ $widget->show();
+ }
+
+ $this->elementEnd('body');
+ $this->elementEnd('html');
+ } else {
+ $this->error = 'Tags saved.';
+ $this->showForm();
+ }
+
+ Event::handle('EndSavePeopletags', array($this, $tagstring));
+ }
+ }
+
+ function showPageNotice()
+ {
+ if ($this->error) {
+ $this->element('p', 'error', $this->error);
+ } else {
+ $this->elementStart('div', 'instructions');
+ $this->element('p', null,
+ _('Use this form to add tags to your subscribers or subscriptions.'));
+ $this->elementEnd('div');
+ }
+ }
+}
+
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Unsubscribe to a peopletag
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Peopletag
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Unsubscribe to a peopletag
+ *
+ * This is the action for subscribing to a peopletag. It works more or less like the join action
+ * for groups.
+ *
+ * @category Peopletag
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class UnsubscribepeopletagAction extends Action
+{
+ var $peopletag = null;
+ var $tagger = null;
+
+ /**
+ * Prepare to run
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ if (!common_logged_in()) {
+ $this->clientError(_('You must be logged in to unsubscribe to a peopletag.'));
+ return false;
+ }
+ // Only allow POST requests
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(_('This action only accepts POST requests.'));
+ return false;
+ }
+
+ // CSRF protection
+
+ $token = $this->trimmed('token');
+
+ if (!$token || $token != common_session_token()) {
+ $this->clientError(_('There was a problem with your session token.'.
+ ' Try again, please.'));
+ return false;
+ }
+
+ $tagger_arg = $this->trimmed('tagger');
+ $tag_arg = $this->trimmed('tag');
+
+ $id = intval($this->arg('id'));
+ if ($id) {
+ $this->peopletag = Profile_list::staticGet('id', $id);
+ } else {
+ $this->clientError(_('No ID given.'), 404);
+ return false;
+ }
+
+ if (!$this->peopletag || $this->peopletag->private) {
+ $this->clientError(_('No such peopletag.'), 404);
+ return false;
+ }
+
+ $this->tagger = Profile::staticGet('id', $this->peopletag->tagger);
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * On POST, add the current user to the group
+ *
+ * @param array $args unused
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ $cur = common_current_user();
+
+ Profile_tag_subscription::remove($this->peopletag, $cur);
+
+ if ($this->boolean('ajax')) {
+ $this->startHTML('text/xml;charset=utf-8');
+ $this->elementStart('head');
+ $this->element('title', null, sprintf(_('%1$s unsubscribed to peopletag %2$s by %3$s'),
+ $cur->nickname,
+ $this->peopletag->tag,
+ $this->tagger->nickname));
+ $this->elementEnd('head');
+ $this->elementStart('body');
+ $lf = new SubscribePeopletagForm($this, $this->peopletag);
+ $lf->show();
+ $this->elementEnd('body');
+ $this->elementEnd('html');
+ } else {
+ if (common_get_returnto()) {
+ common_redirect(common_get_returnto(), 303);
+ return true;
+ }
+ common_redirect(common_local_url('peopletagsbyuser',
+ array('nickname' => $this->tagger->nickname)),
+ 303);
+ }
+ }
+}
$this->script('jquery.cookie.min.js');
$this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/json2.min.js').'"); }');
$this->script('jquery.joverlay.min.js');
+ $this->inlineScript('function _loadTagInput(init) { $.getScript("'.common_path('js/jquery.timers.js'). '"); $.getScript("'.common_path('js/jquery.tagInput.js').'", init); } var _peopletagAC = "' . common_local_url('peopletagautocomplete') . '";');
+
Event::handle('EndShowJQueryScripts', array($this));
}
if (Event::handle('StartShowStatusNetScripts', array($this)) &&
$m->connect('main/sup/:seconds', array('action' => 'sup'),
array('seconds' => '[0-9]+'));
- $m->connect('main/tagother/:id', array('action' => 'tagother'));
+ $m->connect('main/tagprofile', array('action' => 'tagprofile'));
+ $m->connect('main/tagprofile/:id', array('action' => 'tagprofile'),
+ array('id' => '[0-9]+'));
$m->connect('main/oembed',
array('action' => 'oembed'));
array('action' => 'tag'),
array('tag' => self::REGEX_TAG));
- $m->connect('peopletag/:tag',
- array('action' => 'peopletag'),
- array('tag' => self::REGEX_TAG));
-
// groups
$m->connect('group/new', array('action' => 'newgroup'));
array('nickname' => Nickname::DISPLAY_FMT));
}
+ // people tags
+
+ $m->connect('peopletags', array('action' => 'publicpeopletagcloud'));
+
+ $m->connect('peopletag/:tag', array('action' => 'peopletag',
+ 'tag' => self::REGEX_TAG));
+
+ $m->connect('selftag/:tag', array('action' => 'selftag',
+ 'tag' => self::REGEX_TAG));
+
+ $m->connect('main/addpeopletag', array('action' => 'addpeopletag'));
+
+ $m->connect('main/removepeopletag', array('action' => 'removepeopletag'));
+
+ $m->connect('main/profilecompletion', array('action' => 'profilecompletion'));
+
+ $m->connect('main/peopletagautocomplete', array('action' => 'peopletagautocomplete'));
+
+ $m->connect(':nickname/peopletags',
+ array('action' => 'peopletagsbyuser',
+ 'nickname' => Nickname::DISPLAY_FMT));
+
+ $m->connect(':nickname/peopletags/private',
+ array('action' => 'peopletagsbyuser',
+ 'nickname' => Nickname::DISPLAY_FMT,
+ 'private' => 1));
+
+ $m->connect(':nickname/peopletags/public',
+ array('action' => 'peopletagsbyuser',
+ 'nickname' => Nickname::DISPLAY_FMT,
+ 'public' => 1));
+
+ $m->connect(':nickname/othertags',
+ array('action' => 'peopletagsforuser',
+ 'nickname' => Nickname::DISPLAY_FMT));
+
+ $m->connect(':nickname/peopletagsubscriptions',
+ array('action' => 'peopletagsubscriptions',
+ 'nickname' => Nickname::DISPLAY_FMT));
+
+ $m->connect(':tagger/all/:tag/subscribers',
+ array('action' => 'peopletagsubscribers',
+ 'tagger' => Nickname::DISPLAY_FMT,
+ 'tag' => self::REGEX_TAG));
+
+ $m->connect(':tagger/all/:tag/tagged',
+ array('action' => 'peopletagged',
+ 'tagger' => Nickname::DISPLAY_FMT,
+ 'tag' => self::REGEX_TAG));
+
+ $m->connect(':tagger/all/:tag/edit',
+ array('action' => 'editpeopletag',
+ 'tagger' => Nickname::DISPLAY_FMT,
+ 'tag' => self::REGEX_TAG));
+
+ foreach(array('subscribe', 'unsubscribe') as $v) {
+ $m->connect('peopletag/:id/'.$v,
+ array('action' => $v.'peopletag',
+ 'id' => '[0-9]{1,64}'));
+ }
+ $m->connect('user/:tagger_id/profiletag/:id/id',
+ array('action' => 'profiletagbyid',
+ 'tagger_id' => '[0-9]+',
+ 'id' => '[0-9]+'));
+
+ $m->connect(':tagger/all/:tag',
+ array('action' => 'showprofiletag',
+ 'tagger' => Nickname::DISPLAY_FMT,
+ 'tag' => self::REGEX_TAG));
+
foreach (array('subscriptions', 'subscribers') as $a) {
$m->connect(':nickname/'.$a.'/:tag',
array('action' => $a),