From f446db8e2ae9be8ae7b8489ddffcc04c6074b6f2 Mon Sep 17 00:00:00 2001 From: Shashi Gowda Date: Mon, 7 Mar 2011 00:39:24 +0530 Subject: [PATCH] people tag UI elements --- lib/peopletageditform.php | 200 +++++++++++ lib/peopletaggroupnav.php | 145 ++++++++ lib/peopletaglist.php | 320 +++++++++++++++++ lib/peopletags.php | 191 +++++++++++ lib/peopletagsbysubssection.php | 76 +++++ lib/peopletagsection.php | 139 ++++++++ lib/personalgroupnav.php | 6 + lib/profilelist.php | 19 ++ lib/publicgroupnav.php | 4 + lib/subgroupnav.php | 9 + lib/subscribepeopletagform.php | 114 +++++++ lib/subscriberspeopleselftagcloudsection.php | 2 +- lib/subscriberspeopletagcloudsection.php | 2 +- ...subscriptionspeopleselftagcloudsection.php | 2 +- lib/subscriptionspeopletagcloudsection.php | 2 +- lib/togglepeopletag.php | 322 ++++++++++++++++++ lib/unsubscribepeopletagform.php | 114 +++++++ lib/userprofile.php | 25 +- 18 files changed, 1673 insertions(+), 19 deletions(-) create mode 100644 lib/peopletageditform.php create mode 100644 lib/peopletaggroupnav.php create mode 100644 lib/peopletaglist.php create mode 100644 lib/peopletags.php create mode 100644 lib/peopletagsbysubssection.php create mode 100644 lib/peopletagsection.php create mode 100644 lib/subscribepeopletagform.php create mode 100644 lib/togglepeopletag.php create mode 100644 lib/unsubscribepeopletagform.php diff --git a/lib/peopletageditform.php b/lib/peopletageditform.php new file mode 100644 index 0000000000..d0b867ac37 --- /dev/null +++ b/lib/peopletageditform.php @@ -0,0 +1,200 @@ +. + * + * @category Form + * @package StatusNet + * @author Shashi Gowda + * @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/form.php'; +require_once INSTALLDIR.'/lib/togglepeopletag.php'; + +/** + * Form for editing a peopletag + * + * @category Form + * @package StatusNet + * @author Shashi Gowda + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see GroupEditForm + */ + +class PeopletagEditForm extends Form +{ + /** + * peopletag to edit + */ + + var $peopletag = null; + var $tagger = null; + + /** + * Constructor + * + * @param Action $out output channel + * @param User_group $group group to join + */ + + function __construct($out=null, Profile_list $peopletag=null) + { + parent::__construct($out); + + $this->peopletag = $peopletag; + $this->tagger = Profile::staticGet('id', $peopletag->tagger); + } + + /** + * ID of the form + * + * @return string ID of the form + */ + + function id() + { + return 'form_peopletag_edit-' . $this->peopletag->id; + } + + /** + * class of the form + * + * @return string of the form class + */ + + function formClass() + { + return 'form_settings'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('editpeopletag', + array('tagger' => $this->tagger->nickname, 'tag' => $this->peopletag->tag)); + } + + /** + * Name of the form + * + * @return void + */ + + function formLegend() + { + $this->out->element('legend', null, sprintf(_('Edit peopletag %s'), $this->peopletag->tag)); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $id = $this->peopletag->id; + $tag = $this->peopletag->tag; + $description = $this->peopletag->description; + $private = $this->peopletag->private; + + $this->out->elementStart('ul', 'form_data'); + + $this->out->elementStart('li'); + $this->out->hidden('id', $id); + $this->out->input('tag', _('Tag'), + ($this->out->arg('tag')) ? $this->out->arg('tag') : $tag, + _('Change the tag (letters, numbers, -, ., and _ are allowed)')); + $this->out->elementEnd('li'); + + $this->out->elementStart('li'); + $desclimit = Profile_list::maxDescription(); + if ($desclimit == 0) { + $descinstr = _('Describe the people tag or topic'); + } else { + $descinstr = sprintf(_('Describe the people tag or topic in %d characters'), $desclimit); + } + $this->out->textarea('description', _('Description'), + ($this->out->arg('description')) ? $this->out->arg('description') : $description, + $descinstr); + $this->out->checkbox('private', _('Private'), $private); + $this->out->elementEnd('li'); + $this->out->elementEnd('ul'); + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Save')); + $this->out->submit('form_action-yes', + _m('BUTTON','Delete'), + 'submit', + 'delete', + _('Delete this people tag')); + } + + function showProfileList() + { + $tagged = $this->peopletag->getTagged(); + $this->out->element('h2', null, 'Add or remove people'); + + $this->out->elementStart('div', 'profile_search_wrap'); + $this->out->element('h3', null, 'Add user'); + $search = new SearchProfileForm($this->out, $this->peopletag); + $search->show(); + $this->out->element('ul', array('id' => 'profile_search_results', 'class' => 'empty')); + $this->out->elementEnd('div'); + + $this->out->elementStart('ul', 'profile-lister'); + while ($tagged->fetch()) { + $this->out->elementStart('li', 'entity_removable_profile'); + $this->showProfileItem($tagged); + $this->out->elementStart('span', 'entity_actions'); + $untag = new UntagButton($this->out, $tagged, $this->peopletag); + $untag->show(); + $this->out->elementEnd('span'); + $this->out->elementEnd('li'); + } + $this->out->elementEnd('ul'); + } + + function showProfileItem($profile) + { + $item = new TaggedProfileItem($this->out, $profile); + $item->show(); + } +} diff --git a/lib/peopletaggroupnav.php b/lib/peopletaggroupnav.php new file mode 100644 index 0000000000..2c9a65fd44 --- /dev/null +++ b/lib/peopletaggroupnav.php @@ -0,0 +1,145 @@ +. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @author Sarven Capadisli + * @copyright 2008 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/widget.php'; + +/** + * Base class for all actions + * + * This is the base class for all actions in the package. An action is + * more or less a "view" in an MVC framework. + * + * Actions are responsible for extracting and validating parameters; using + * model classes to read and write to the database; and doing ouput. + * + * @category Output + * @package StatusNet + * @author Evan Prodromou + * @author Sarven Capadisli + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see HTMLOutputter + */ + +class PeopletagGroupNav extends Widget +{ + var $action = null; + + /** + * Construction + * + * @param Action $action current action, used for output + */ + + function __construct($action=null) + { + parent::__construct($action); + $this->action = $action; + } + + /** + * Show the menu + * + * @return void + */ + + function show() + { + $user = null; + + // FIXME: we should probably pass this in + + $action = $this->action->trimmed('action'); + $nickname = $this->action->trimmed('tagger'); + $tag = $this->action->trimmed('tag'); + + if ($nickname) { + $user = User::staticGet('nickname', $nickname); + $user_profile = $user->getProfile(); + + if ($tag) { + $tag = Profile_list::pkeyGet(array('tagger' => $user->id, + 'tag' => $tag)); + } else { + $tag = false; + } + + } else { + $user_profile = false; + } + + $this->out->elementStart('ul', array('class' => 'nav')); + + if (Event::handle('StartPeopletagGroupNav', array($this))) { + // People tag timeline + $this->out->menuItem(common_local_url('showprofiletag', array('tagger' => $user_profile->nickname, + 'tag' => $tag->tag)), + _('People tag'), + sprintf(_('%s tag by %s'), $tag->tag, + (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), + $action == 'showprofiletag', 'nav_timeline_peopletag'); + + // Tagged + $this->out->menuItem(common_local_url('peopletagged', array('tagger' => $user->nickname, + 'tag' => $tag->tag)), + _('Tagged'), + sprintf(_('%s tag by %s'), $tag->tag, + (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), + $action == 'peopletagged', 'nav_peopletag_tagged'); + + // Subscribers + $this->out->menuItem(common_local_url('peopletagsubscribers', array('tagger' => $user->nickname, + 'tag' => $tag->tag)), + _('Subscribers'), + sprintf(_('Subscribers to %s tag by %s'), $tag->tag, + (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), + $action == 'peopletagsubscribers', 'nav_peopletag_subscribers'); + + $cur = common_current_user(); + if (!empty($cur) && $user_profile->id == $cur->id) { + // Edit + $this->out->menuItem(common_local_url('editpeopletag', array('tagger' => $user->nickname, + 'tag' => $tag->tag)), + _('Edit'), + sprintf(_('Edit %s tag by you'), $tag->tag, + (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), + $action == 'editpeopletag', 'nav_peopletag_edit'); + } + + Event::handle('EndPeopletagGroupNav', array($this)); + } + $this->out->elementEnd('ul'); + } +} diff --git a/lib/peopletaglist.php b/lib/peopletaglist.php new file mode 100644 index 0000000000..8a4caf44fe --- /dev/null +++ b/lib/peopletaglist.php @@ -0,0 +1,320 @@ +. + * + * @category Public + * @package StatusNet + * @author Shashi Gowda + * @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/widget.php'; + +define('PEOPLETAGS_PER_PAGE', 20); + +/** + * Widget to show a list of peopletags + * + * @category Public + * @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 PeopletagList extends Widget +{ + /** Current peopletag, peopletag query. */ + var $peopletag = null; + /** current user **/ + var $user = null; + + function __construct($peopletag, $action=null) + { + parent::__construct($action); + + $this->peopletag = $peopletag; + + if (!empty($owner)) { + $this->user = $owner; + } else { + $this->user = common_current_user(); + } + } + + function show() + { + $this->out->elementStart('ul', 'peopletags xoxo hfeed'); + + $cnt = 0; + + while ($this->peopletag->fetch()) { + $cnt++; + if($cnt > PEOPLETAGS_PER_PAGE) { + break; + } + $this->showPeopletag(); + } + + $this->out->elementEnd('ul'); + + return $cnt; + } + + function showPeopletag() + { + $ptag = new PeopletagListItem($this->peopletag, $this->user, $this->out); + $ptag->show(); + } +} + +class PeopletagListItem extends Widget +{ + var $peopletag = null; + var $current = null; + var $profile = null; + + /** + * constructor + * + * Also initializes the owner attribute. + * + * @param Notice $notice The notice we'll display + */ + + function __construct($peopletag, $current, $out=null) + { + parent::__construct($out); + $this->peopletag = $peopletag; + $this->current = $current; + $this->profile = Profile::staticGet('id', $this->peopletag->tagger); + } + + /** + * recipe function for displaying a single peopletag. + * + * This uses all the other methods to correctly display a notice. Override + * it or one of the others to fine-tune the output. + * + * @return void + */ + + function url() + { + return $this->peopletag->homeUrl(); + } + + function show() + { + if (empty($this->peopletag)) { + common_log(LOG_WARNING, "Trying to show missing peopletag; skipping."); + return; + } + + if (Event::handle('StartShowPeopletagItem', array($this))) { + $this->showStart(); + $this->showPeopletag(); + $this->showStats(); + $this->showEnd(); + Event::handle('EndShowPeopletagItem', array($this)); + } + } + + function showStart() + { + $mode = ($this->peopletag->private) ? 'private' : 'public'; + $this->out->elementStart('li', array('class' => 'hentry peopletag mode-' . $mode, + 'id' => 'peopletag-' . $this->peopletag->id)); + } + + function showEnd() + { + $this->out->elementEnd('li'); + } + + function showPeopletag() + { + $this->showCreator(); + $this->showTag(); + $this->showPrivacy(); + $this->showUpdated(); + $this->showActions(); + $this->showDescription(); + } + + function showStats() + { + $this->out->elementStart('div', 'entry-summary entity_statistics'); + $this->out->elementStart('span', 'tagged-count'); + $this->out->element('a', + array('href' => common_local_url('peopletagged', + array('tagger' => $this->profile->nickname, + 'tag' => $this->peopletag->tag))), + _('Tagged')); + $this->out->raw($this->peopletag->taggedCount()); + $this->out->elementEnd('span'); + + $this->out->elementStart('span', 'subscriber-count'); + $this->out->element('a', + array('href' => common_local_url('peopletagsubscribers', + array('tagger' => $this->profile->nickname, + 'tag' => $this->peopletag->tag))), + _('Subscribers')); + $this->out->raw($this->peopletag->subscriberCount()); + $this->out->elementEnd('span'); + $this->out->elementEnd('div'); + } + + function showOwnerOptions() + { + $this->out->elementStart('li', 'entity_edit'); + $this->out->element('a', array('href' => + common_local_url('editpeopletag', array('tagger' => $this->profile->nickname, + 'tag' => $this->peopletag->tag)), + 'title' => _('Edit peopletag settings')), + _('Edit')); + $this->out->elementEnd('li'); + } + + function showSubscribeForm() + { + $this->out->elementStart('li'); + + if (Event::handle('StartSubscribePeopletagForm', array($this->out, $this->peopletag))) { + if ($this->current) { + if ($this->peopletag->hasSubscriber($this->current->id)) { + $form = new UnsubscribePeopletagForm($this->out, $this->peopletag); + $form->show(); + } else { + $form = new SubscribePeopletagForm($this->out, $this->peopletag); + $form->show(); + } + } + Event::handle('EndSubscribePeopletagForm', array($this->out, $this->peopletag)); + } + + $this->out->elementEnd('li'); + } + + function showCreator() + { + $this->out->elementStart('span', 'author vcard'); + $attrs = array(); + $attrs['href'] = $this->profile->profileurl; + $attrs['class'] = 'url'; + $attrs['rel'] = 'contact'; + + if (!empty($this->profile->fullname)) { + $attrs['title'] = $this->profile->fullname . ' (' . $this->profile->nickname . ')'; + } + $this->out->elementStart('a', $attrs); + $this->showAvatar(); + $this->out->text(' '); + $this->out->element('span', 'nickname fn', + htmlspecialchars($this->profile->nickname)); + + $this->out->elementEnd('a'); + $this->out->elementEnd('span'); + } + + function showUpdated() + { + if (!empty($this->peopletag->modified)) { + $this->out->element('abbr', + array('title' => common_date_w3dtf($this->peopletag->modified), + 'class' => 'updated'), + common_date_string($this->peopletag->modified)); + } + } + + function showPrivacy() + { + if ($this->peopletag->private) { + $this->out->elementStart('a', + array('href' => common_local_url('peopletagsbyuser', + array('nickname' => $this->profile->nickname, 'private' => 1)))); + $this->out->element('span', 'privacy_mode', _('Private')); + $this->out->elementEnd('a'); + } + } + + function showTag() + { + $this->out->elementStart('span', 'entry-title tag'); + $this->out->element('a', + array('rel' => 'bookmark', + 'href' => $this->url()), + htmlspecialchars($this->peopletag->tag)); + $this->out->elementEnd('span'); + } + + /** + * show the avatar of the peopletag's creator + * + * This will use the default avatar if no avatar is assigned for the author. + * It makes a link to the author's profile. + * + * @return void + */ + + function showAvatar($size=AVATAR_STREAM_SIZE) + { + $avatar = $this->profile->getAvatar($size); + + $this->out->element('img', array('src' => ($avatar) ? + $avatar->displayUrl() : + Avatar::defaultImage($size), + 'class' => 'avatar photo', + 'width' => $size, + 'height' => $size, + 'alt' => + ($this->profile->fullname) ? + $this->profile->fullname : + $this->profile->nickname)); + } + + function showActions() + { + $this->out->elementStart('div', 'entity_actions'); + $this->out->elementStart('ul'); + + if (!$this->peopletag->private) { + $this->showSubscribeForm(); + } + + if (!empty($this->current) && $this->profile->id == $this->current->id) { + $this->showOwnerOptions(); + } + $this->out->elementEnd('ul'); + $this->out->elementEnd('div'); + } + + function showDescription() + { + $this->out->element('div', 'entry-content description', + $this->peopletag->description); + } +} diff --git a/lib/peopletags.php b/lib/peopletags.php new file mode 100644 index 0000000000..96b85afd4f --- /dev/null +++ b/lib/peopletags.php @@ -0,0 +1,191 @@ +. + * + * @category Action + * @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); +} + +require_once INSTALLDIR.'/lib/widget.php'; + +/* + * Show a bunch of peopletags + * provide ajax editing if the current user owns the tags + * + * @category Action + * @pacage StatusNet + * @author Shashi Gowda + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + */ + +class PeopletagsWidget extends Widget +{ + /* + * the query, current peopletag. + * or an array of strings (tags) + */ + + var $tag=null; + + var $user=null; + var $tagger=null; + var $tagged=null; + + function __construct($out, $tagger, $tagged) + { + parent::__construct($out); + + $this->user = common_current_user(); + $this->tag = Profile_tag::getTags($tagger->id, $tagged->id, $this->user); + $this->tagger = $tagger; + $this->tagged = $tagged; + } + + function show() + { + if (Event::handle('StartShowPeopletags', array($this, $this->tagger, $this->tagged))) { + if ($this->tag->N > 0) { + $this->showTags(); + } + else { + $this->showEmptyList(); + } + Event::handle('EndShowPeopletags', array($this, $this->tagger, $this->tagged)); + } + } + + function url() + { + return $this->tag->homeUrl(); + } + + function label() + { + return _('Tags by you'); + } + + function showTags() + { + $this->out->elementStart('dl', 'entity_tags user_profile_tags'); + $this->out->element('dt', null, $this->label()); + $this->out->elementStart('dd'); + + $class = 'tags xoxo'; + if ($this->isEditable()) { + $class .= ' editable'; + } + + $tags = array(); + $this->out->elementStart('ul', $class); + while ($this->tag->fetch()) { + $mode = $this->tag->private ? 'private' : 'public'; + $tags[] = $this->tag->tag; + + $this->out->elementStart('li', 'hashptag mode-' . $mode); + // Avoid space by using raw output. + $pt = '#'; + $this->out->raw($pt); + $this->out->elementEnd('li'); + } + $this->out->elementEnd('ul'); + + if ($this->isEditable()) { + $this->showEditTagForm($tags); + } + + $this->out->elementEnd('dd'); + $this->out->elementEnd('dl'); + } + + function showEditTagForm($tags=null) + { + $this->out->elementStart('span', 'form_tag_user_wrap'); + $this->out->elementStart('form', array('method' => 'post', + 'class' => 'form_tag_user', + 'name' => 'tagprofile', + 'action' => common_local_url('tagprofile', array('id' => $this->tagged->id)))); + + $this->out->elementStart('fieldset'); + $this->out->element('legend', null, _('Edit tags')); + $this->out->hidden('token', common_session_token()); + $this->out->hidden('id', $this->tagged->id); + + if (!$tags) { + $tags = array(); + } + + $this->out->input('tags', $this->label(), + ($this->out->arg('tags')) ? $this->out->arg('tags') : implode(' ', $tags)); + $this->out->submit('save', _('Save')); + + $this->out->elementEnd('fieldset'); + $this->out->elementEnd('form'); + $this->out->elementEnd('span'); + } + + function showEmptyList() + { + $this->out->elementStart('dl', 'entity_tags user_profile_tags'); + $this->out->element('dt', null, $this->label()); + $this->out->elementStart('dd'); + + $class = 'tags'; + if ($this->isEditable()) { + $class .= ' editable'; + } + + $this->out->elementStart('ul', $class); + $this->out->element('li', null, _('(None)')); + $this->out->elementEnd('ul'); + + if ($this->isEditable()) { + $this->showEditTagForm(); + } + $this->out->elementEnd('dd'); + $this->out->elementEnd('dl'); + } + + function isEditable() + { + return !empty($this->user) && $this->tagger->id == $this->user->id; + } +} + +class SelftagsWidget extends PeopletagsWidget +{ + function url($tag) + { + // link to self tag page + return common_local_url('selftag', array('tag' => $tag)); + } + + function label() + { + return _('Tags'); + } +} diff --git a/lib/peopletagsbysubssection.php b/lib/peopletagsbysubssection.php new file mode 100644 index 0000000000..779e7d8ef9 --- /dev/null +++ b/lib/peopletagsbysubssection.php @@ -0,0 +1,76 @@ +. + * + * @category Widget + * @package StatusNet + * @author Evan Prodromou + * @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); +} + +/** + * Peopletags with the most subscribers section + * + * @category Widget + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class PeopletagsBySubsSection extends PeopletagSection +{ + function getPeopletags() + { + $qry = 'SELECT profile_list.*, subscriber_count as value ' . + 'FROM profile_list WHERE profile_list.private = false ' . + 'ORDER BY value DESC '; + + $limit = PEOPLETAGS_PER_SECTION; + $offset = 0; + + if (common_config('db','type') == 'pgsql') { + $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; + } else { + $qry .= ' LIMIT ' . $offset . ', ' . $limit; + } + + $peopletag = Memcached_DataObject::cachedQuery('Profile_list', + $qry, + 3600); + return $peopletag; + } + + function title() + { + return _('People tags with most subscribers'); + } + + function divId() + { + return 'top_peopletags_by_subs'; + } +} diff --git a/lib/peopletagsection.php b/lib/peopletagsection.php new file mode 100644 index 0000000000..6722f3a149 --- /dev/null +++ b/lib/peopletagsection.php @@ -0,0 +1,139 @@ +. + * + * @category Widget + * @package StatusNet + * @author Shashi Gowda + * @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'; + +define('PEOPLETAGS_PER_SECTION', 6); + +/** + * Base class for sections + * + * These are the widgets that show interesting data about a person + * peopletag, or site. + * + * @category Widget + * @package StatusNet + * @author Shashi Gowda + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class PeopletagSection extends Section +{ + function showContent() + { + $tags = $this->getPeopletags(); + + if (!$tags) { + return false; + } + + $cnt = 0; + + $this->out->elementStart('table', 'peopletag_section'); + + while ($tags->fetch() && ++$cnt <= PEOPLETAGS_PER_SECTION) { + $this->showPeopletag($tags); + } + + $this->out->elementEnd('table'); + + return ($cnt > PEOPLETAGS_PER_SECTION); + } + + function getPeopletags() + { + return null; + } + + function showPeopletag($peopletag) + { + $tag = new PeopletagSectionItem($peopletag, null, $this->out); + $tag->show(); + } +} + +class PeopletagSectionItem extends PeopletagListItem +{ + function showStart() + { + } + + function showEnd() + { + } + + function showPeopletag() + { + $this->showCreator(); + $this->showTag(); + $this->showPrivacy(); + } + + function show() + { + if (empty($this->peopletag)) { + common_log(LOG_WARNING, "Trying to show missing peopletag; skipping."); + return; + } + + $this->out->elementStart('tr'); + + $this->out->elementStart('td', 'peopletag'); + $this->showPeopletag(); + $this->out->elementEnd('td'); + + if ($this->peopletag->value) { + $this->out->element('td', 'value', $this->peopletag->value); + } + $this->out->elementEnd('tr'); + } + + function showTag() + { + $title = _('Tagged: ') . $this->peopletag->taggedCount() . + ' ' . _('Subscribers: ') . $this->peopletag->subscriberCount(); + + $this->out->elementStart('span', 'entry-title tag'); + $this->out->element('a', + array('rel' => 'bookmark', + 'href' => $this->url(), + 'title' => $title), + htmlspecialchars($this->peopletag->tag)); + $this->out->elementEnd('span'); + } + + function showAvatar() + { + parent::showAvatar(AVATAR_MINI_SIZE); + } +} diff --git a/lib/personalgroupnav.php b/lib/personalgroupnav.php index 72d0893af7..ccd4ab506f 100644 --- a/lib/personalgroupnav.php +++ b/lib/personalgroupnav.php @@ -109,6 +109,12 @@ class PersonalGroupNav extends Widget _('Favorites'), sprintf(_('%s\'s favorite notices'), ($user_profile) ? $name : _('User')), $action == 'showfavorites', 'nav_timeline_favorites'); + $this->out->menuItem(common_local_url('peopletagsbyuser', array('nickname' => + $nickname)), + _('People tags'), + sprintf(_('People tags by %s'), ($user_profile) ? $user_profile->getBestName() : _('User')), + in_array($action, array('peopletagsbyuser', 'peopletagsforuser')), + 'nav_timeline_peopletags'); $cur = common_current_user(); diff --git a/lib/profilelist.php b/lib/profilelist.php index b010fb7249..af38fa71d9 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -33,6 +33,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { } require_once INSTALLDIR.'/lib/widget.php'; +require_once INSTALLDIR.'/lib/peopletags.php'; /** * Widget to show a list of profiles @@ -168,6 +169,10 @@ class ProfileListItem extends Widget $this->showBio(); Event::handle('EndProfileListItemBio', array($this)); } + if (Event::handle('StartProfileListItemTags', array($this))) { + $this->showTags(); + Event::handle('EndProfileListItemTags', array($this)); + } Event::handle('EndProfileListItemProfileElements', array($this)); } $this->endProfile(); @@ -238,6 +243,20 @@ class ProfileListItem extends Widget } } + function showTags() + { + $user = common_current_user(); + if (!empty($user)) { + if ($user->id == $this->profile->id) { + $tags = new SelftagsWidget($this->out, $user, $this->profile); + $tags->show(); + } else if ($user->getProfile()->canTag($this->profile)) { + $tags = new PeopletagsWidget($this->out, $user, $this->profile); + $tags->show(); + } + } + } + function endProfile() { $this->out->elementEnd('div'); diff --git a/lib/publicgroupnav.php b/lib/publicgroupnav.php index ae9cbdebb4..c2dc11831a 100644 --- a/lib/publicgroupnav.php +++ b/lib/publicgroupnav.php @@ -84,6 +84,10 @@ class PublicGroupNav extends Widget $this->out->menuItem(common_local_url('publictagcloud'), _('Recent tags'), _('Recent tags'), $action_name == 'publictagcloud', 'nav_recent-tags'); + $this->out->menuItem(common_local_url('publicpeopletagcloud'), _('People tags'), + _('People tags'), in_array($action_name, array('publicpeopletagcloud', + 'peopletag', 'selftag')), 'nav_people-tags'); + if (count(common_config('nickname', 'featured')) > 0) { $this->out->menuItem(common_local_url('featured'), _('Featured'), _('Featured users'), $action_name == 'featured', 'nav_featured'); diff --git a/lib/subgroupnav.php b/lib/subgroupnav.php index be3ba27480..5fccb15744 100644 --- a/lib/subgroupnav.php +++ b/lib/subgroupnav.php @@ -106,6 +106,15 @@ class SubGroupNav extends Widget $this->user->nickname), $action == 'usergroups', 'nav_usergroups'); + $this->out->menuItem(common_local_url('peopletagsbyuser', + array('nickname' => + $this->user->nickname)), + _('People tags'), + sprintf(_('People tags by %s'), + $this->user->nickname), + in_array($action, array('peopletagsbyuser', 'peopletagsforuser')), + 'nav_timeline_peopletags'); + if (common_config('invite', 'enabled') && !is_null($cur) && $this->user->id === $cur->id) { $this->out->menuItem(common_local_url('invite'), _('Invite'), diff --git a/lib/subscribepeopletagform.php b/lib/subscribepeopletagform.php new file mode 100644 index 0000000000..9489b01a1c --- /dev/null +++ b/lib/subscribepeopletagform.php @@ -0,0 +1,114 @@ +. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @author Shashi Gowda + * @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/form.php'; + +/** + * Form for subscribing to a peopletag + * + * @category Form + * @package StatusNet + * @author Shashi Gowda + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see UnsubscribeForm + */ + +class SubscribePeopletagForm extends Form +{ + /** + * peopletag for the user to join + */ + + var $peopletag = null; + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param peopletag $peopletag peopletag to subscribe to + */ + + function __construct($out=null, $peopletag=null) + { + parent::__construct($out); + + $this->peopletag = $peopletag; + } + + /** + * ID of the form + * + * @return string ID of the form + */ + + function id() + { + return 'peopletag-subscribe-' . $this->peopletag->id; + } + + /** + * class of the form + * + * @return string of the form class + */ + + function formClass() + { + return 'form_peopletag_subscribe'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('subscribepeopletag', + array('id' => $this->peopletag->id)); + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Subscribe')); + } +} diff --git a/lib/subscriberspeopleselftagcloudsection.php b/lib/subscriberspeopleselftagcloudsection.php index 5a570ae282..b4ada901c0 100644 --- a/lib/subscriberspeopleselftagcloudsection.php +++ b/lib/subscriberspeopleselftagcloudsection.php @@ -52,7 +52,7 @@ class SubscribersPeopleSelfTagCloudSection extends SubPeopleTagCloudSection // return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged group by tag order by weight desc'; - return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; + return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on profile_list.tag = profile_tag.tag and profile_list.tagger = profile_tag.tagger and profile_tag.tagger = subscriber where subscribed=%d and subscribed != subscriber and profile_tag.tagger = tagged and profile_list.private = false and profile_tag.tag is not null group by profile_tag.tag order by weight desc'; // return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscribed where subscriber=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; diff --git a/lib/subscriberspeopletagcloudsection.php b/lib/subscriberspeopletagcloudsection.php index 284996b591..65c4a4f066 100644 --- a/lib/subscriberspeopletagcloudsection.php +++ b/lib/subscriberspeopletagcloudsection.php @@ -55,7 +55,7 @@ class SubscribersPeopleTagCloudSection extends SubPeopleTagCloudSection function query() { // return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed group by tag order by weight desc'; - return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed and tag is not null group by tag order by weight desc'; + return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on subscriber=profile_tag.tagged and subscribed=profile_tag.tagger and profile_tag.tagger = profile_list.tagger and profile_tag.tag = profile_list.tag where subscribed=%d and subscriber != subscribed and profile_list.private = false and profile_tag.tag is not null group by profile_tag.tag order by weight desc'; } } diff --git a/lib/subscriptionspeopleselftagcloudsection.php b/lib/subscriptionspeopleselftagcloudsection.php index 9be60dfa14..cb87ae0440 100644 --- a/lib/subscriptionspeopleselftagcloudsection.php +++ b/lib/subscriptionspeopleselftagcloudsection.php @@ -53,7 +53,7 @@ class SubscriptionsPeopleSelfTagCloudSection extends SubPeopleTagCloudSection - return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscribed where subscriber=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; + return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on profile_tag.tagger = subscribed and profile_tag.tag = profile_list.tag and profile_tag.tagger = profile_tag.tagger where subscriber=%d and subscribed != subscriber and profile_tag.tagger = profile_tag.tagged and profile_list.private = false and profile_tag.tag is not null group by profile_tag.tag order by weight desc'; // return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; } diff --git a/lib/subscriptionspeopletagcloudsection.php b/lib/subscriptionspeopletagcloudsection.php index fde24b282e..1a42bf90be 100644 --- a/lib/subscriptionspeopletagcloudsection.php +++ b/lib/subscriptionspeopletagcloudsection.php @@ -55,7 +55,7 @@ class SubscriptionsPeopleTagCloudSection extends SubPeopleTagCloudSection function query() { // return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed group by tag order by weight desc'; - return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed and tag is not null group by tag order by weight desc'; + return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on subscriber=profile_tag.tagger and subscribed=tagged and profile_tag.tag = profile_list.tag and profile_tag.tagger = profile_list.tagger where subscriber=%d and subscriber != subscribed and profile_list.private = false and profile_tag.tag is not null group by profile_tag.tag order by weight desc'; } } diff --git a/lib/togglepeopletag.php b/lib/togglepeopletag.php new file mode 100644 index 0000000000..a6e07177fb --- /dev/null +++ b/lib/togglepeopletag.php @@ -0,0 +1,322 @@ +. + * + * @category Form + * @package StatusNet + * @author Shashi Gowda + * @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/form.php'; + +/** + * Form for editing a peopletag + * + * @category Form + * @package StatusNet + * @author Shashi Gowda + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see GroupEditForm + */ + +class SearchProfileForm extends Form +{ + var $peopletag; + + function __construct($out, Profile_list $peopletag) + { + parent::__construct($out); + $this->peopletag = $peopletag; + } + + /** + * ID of the form + * + * @return string ID of the form + */ + + function id() + { + return 'form_peopletag-add-' . $this->peopletag->id; + } + + /** + * class of the form + * + * @return string of the form class + */ + + function formClass() + { + return 'form_peopletag_edit_user_search'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('profilecompletion'); + } + + /** + * Name of the form + * + * @return void + */ + + function formLegend() + { + $this->out->element('legend', null, sprintf(_('Search and list people'))); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $fields = array('fulltext' => 'Everything', + 'nickname' => 'Nickname', + 'fullname' => 'Fullname', + 'description' => 'Description', + 'location' => 'Location', + 'uri' => 'Uri (Remote users)'); + + + $this->out->hidden('peopletag_id', $this->peopletag->id); + $this->out->input('q', null); + $this->out->dropdown('field', _('Search in'), $fields, + _('Choose a field to search'), false, 'fulltext'); + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Search')); + } +} + +class UntagButton extends Form +{ + var $profile; + var $peopletag; + + function __construct($out, Profile $profile, Profile_list $peopletag) + { + parent::__construct($out); + $this->profile = $profile; + $this->peopletag = $peopletag; + } + + /** + * ID of the form + * + * @return string ID of the form + */ + + function id() + { + return 'form_peopletag-' . $this->peopletag->id . '-remove-' . $this->profile->id; + } + + /** + * class of the form + * + * @return string of the form class + */ + + function formClass() + { + return 'form_user_remove_peopletag'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('removepeopletag'); + } + + /** + * Name of the form + * + * @return void + */ + + function formLegend() + { + $this->out->element('legend', null, sprintf(_('Untag %s as %s'), + $this->profile->nickname, $this->peopletag->tag)); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $this->out->hidden('peopletag_id', $this->peopletag->id); + $this->out->hidden('tagged', $this->profile->id); + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Remove')); + } +} + + +class TagButton extends Form +{ + var $profile; + var $peopletag; + + function __construct($out, Profile $profile, Profile_list $peopletag) + { + parent::__construct($out); + $this->profile = $profile; + $this->peopletag = $peopletag; + } + + /** + * ID of the form + * + * @return string ID of the form + */ + + function id() + { + return 'form_peopletag-' . $this->peopletag->id . '-add-' . $this->profile->id; + } + + /** + * class of the form + * + * @return string of the form class + */ + + function formClass() + { + return 'form_user_add_peopletag'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('addpeopletag'); + } + + /** + * Name of the form + * + * @return void + */ + + function formLegend() + { + $this->out->element('legend', null, sprintf(_('Tag %s as %s'), + $this->profile->nickname, $this->peopletag->tag)); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + UntagButton::formData(); + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Add')); + } +} + +class TaggedProfileItem extends Widget +{ + var $profile=null; + + function __construct($out=null, $profile) + { + parent::__construct($out); + $this->profile = $profile; + } + + function show() + { + $this->out->elementStart('a', array('class' => 'url', + 'href' => $this->profile->profileurl, + 'title' => $this->profile->getBestName())); + $avatar = $this->profile->getAvatar(AVATAR_MINI_SIZE); + $this->out->element('img', array('src' => (($avatar) ? $avatar->displayUrl() : + Avatar::defaultImage(AVATAR_MINI_SIZE)), + 'width' => AVATAR_MINI_SIZE, + 'height' => AVATAR_MINI_SIZE, + 'class' => 'avatar photo', + 'alt' => $this->profile->getBestName())); + $this->out->element('span', 'fn nickname', $this->profile->nickname); + $this->out->elementEnd('a'); + } +} diff --git a/lib/unsubscribepeopletagform.php b/lib/unsubscribepeopletagform.php new file mode 100644 index 0000000000..777025c89d --- /dev/null +++ b/lib/unsubscribepeopletagform.php @@ -0,0 +1,114 @@ +. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @author Shashi Gowda + * @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/form.php'; + +/** + * Form for unsubscribing to a peopletag + * + * @category Form + * @package StatusNet + * @author Shashi Gowda + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see UnunsubscribeForm + */ + +class UnsubscribePeopletagForm extends Form +{ + /** + * peopletag for the user to join + */ + + var $peopletag = null; + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param peopletag $peopletag peopletag to unsubscribe to + */ + + function __construct($out=null, $peopletag=null) + { + parent::__construct($out); + + $this->peopletag = $peopletag; + } + + /** + * ID of the form + * + * @return string ID of the form + */ + + function id() + { + return 'peopletag-unsubscribe-' . $this->peopletag->id; + } + + /** + * class of the form + * + * @return string of the form class + */ + + function formClass() + { + return 'form_peopletag_unsubscribe'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('unsubscribepeopletag', + array('id' => $this->peopletag->id)); + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Unsubscribe')); + } +} diff --git a/lib/userprofile.php b/lib/userprofile.php index 0b7efb22fc..66d049e9e5 100644 --- a/lib/userprofile.php +++ b/lib/userprofile.php @@ -33,6 +33,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { } require_once INSTALLDIR.'/lib/widget.php'; +require_once INSTALLDIR.'/lib/peopletags.php'; /** * Profile of a user @@ -188,23 +189,17 @@ class UserProfile extends Widget function showProfileTags() { - if (Event::handle('StartProfilePageProfileTags', array($this->out, $this->profile))) { - $tags = Profile_tag::getTags($this->profile->id, $this->profile->id); + $cur = common_current_user(); - if (count($tags) > 0) { - $this->out->elementStart('ul', 'tags xoxo entity_tags'); - foreach ($tags as $tag) { - $this->out->elementStart('li'); - // Avoid space by using raw output. - $pt = '#'; - $this->out->raw($pt); - $this->out->elementEnd('li'); - } - $this->out->elementEnd('ul'); + $self_tags = new SelftagsWidget($this->out, $this->profile, $this->profile); + $self_tags->show(); + + if ($cur) { + // don't show self-tags again + if ($cur->id != $this->profile->id && $cur->getProfile()->canTag($this->profile)) { + $tags = new PeopletagsWidget($this->out, $cur, $this->profile); + $tags->show(); } - Event::handle('EndProfilePageProfileTags', array($this->out, $this->profile)); } }