Merge branch '1.0.x' into testing
This commit is contained in:
commit
5304373b0b
153
EVENTS.txt
153
EVENTS.txt
@ -1116,6 +1116,156 @@ EndGroupProfileElements: Start showing stuff about the group on its profile page
|
||||
- $action: action being executed (for output and params)
|
||||
- $group: group for the page
|
||||
|
||||
StartShowProfileTagContent: When showing a people tag page
|
||||
- $action: action being executed (for output and params)
|
||||
|
||||
EndShowProfileTagContent: After showing the contents of a people tag page
|
||||
- $action: action being executed (for output and params)
|
||||
|
||||
StartShowTaggedProfilesMiniList: at the start of mini list of tagged profiles
|
||||
- $action: action being executed (for output and params)
|
||||
|
||||
EndShowTaggedProfilesMiniList: at the end of mini list of tagged profiles
|
||||
- $action: action being executed (for output and params)
|
||||
|
||||
StartShowProfileTagSubscribersMiniList: at the start of mini list of people tag subscribers
|
||||
- $action: action being executed (for output and params)
|
||||
|
||||
EndShowProfileTagSubscribersMiniList: at the end of mini list of people tag subscribers
|
||||
- $action: action being executed (for output and params)
|
||||
|
||||
StartTagProfileAction: When starting to show profile tagging page
|
||||
- $action: action being executed (for output and params)
|
||||
- $profile: profile being tagged
|
||||
|
||||
EndTagProfileAction: After showing profile tagging page
|
||||
- $action: action being executed (for output and params)
|
||||
- $profile: profile being tagged
|
||||
|
||||
StartProfileCompletionSearch: When starting a profile search for autocompletion
|
||||
- $action: action being executed (for output and params)
|
||||
- &$profile: result Profile objects
|
||||
- $search_engine: the search engine
|
||||
|
||||
EndProfileCompletionSearch: After search results for profile autocompletion have been found
|
||||
- $action: profilec completion action
|
||||
- &$profile: current result Profile objects
|
||||
- $search_engine: The search engine object
|
||||
|
||||
StartShowTagProfileForm: When showing people tagging form
|
||||
- $action: action being executed (for output and params)
|
||||
- $profile: profile being tagged
|
||||
|
||||
EndShowTagProfileForm: After showing people tagging form
|
||||
- $action: action being executed (for output and params)
|
||||
- $profile: profile being tagged
|
||||
|
||||
StartSavePeopletags: When starting to save people tags
|
||||
- $action: action being executed (for output and params)
|
||||
- $tagstring: string input, a list of tags
|
||||
|
||||
EndSavePeopletags: After saving people tags
|
||||
- $action: action being executed (for output and params)
|
||||
- $tagstring: string input, a list of tags
|
||||
|
||||
StartProfiletagGetUri: when generating the Uri for a people tag
|
||||
- $profile_list: the people tag, a Profile_list object
|
||||
- &$uri: the URI
|
||||
|
||||
EndProfiletagGetUri: after generating the uri for a people tag
|
||||
- $profile_list: the people tag, a Profile_list object
|
||||
- &$uri: the URI
|
||||
|
||||
StartUserPeopletagHomeUrl: when generating the homepage url for a people tag
|
||||
- $profile_list: the people tag, a Profile_list object
|
||||
- &$url: the URL
|
||||
|
||||
EndUserPeopletagHomeUrl: after generating the homepage url for a people tag
|
||||
- $profile_list: the people tag, a Profile_list object
|
||||
- &$url: the URL
|
||||
|
||||
StartProfiletagPermalink: when generating the permalink url for a people tag
|
||||
- $profile_list: the people tag, a Profile_list object
|
||||
- &$url: the URL
|
||||
|
||||
EndProfiletagPermalink: after generating the permalink url for a people tag
|
||||
- $profile_list: the people tag, a Profile_list object
|
||||
- &$url: the URL
|
||||
|
||||
StartTagProfile: when tagging a profile
|
||||
- $tagger: profile tagging
|
||||
- $tagged: profile being tagged
|
||||
- $tag: the tag
|
||||
|
||||
EndTagProfile: after tagging a profile
|
||||
- $newtag: the newly created Profile_tag object
|
||||
|
||||
StartUntagProfile: when deleting a people tag
|
||||
- $ptag: the Profile_tag object being deleted
|
||||
|
||||
EndUntagProfile: after deleting a people tag
|
||||
- $orig: a copy of the deleted Profile_tag object
|
||||
|
||||
StartSubscribePeopletag: when subscribing to a people tag
|
||||
- $peopletag: Profile_list object being subscribed to
|
||||
- $profile: subscriber's profile
|
||||
|
||||
EndSubscribePeopletag: after subscribing to a people tag
|
||||
- $profile_list: the people tag, a Profile_list object: Profile_list object being subscribed to
|
||||
- $profile: subscriber's profile
|
||||
|
||||
StartUnsubscribePeopletag: when unsubscribing to a people tag
|
||||
- $profile_list: the people tag, a Profile_list object: Profile_list object being subscribed to
|
||||
- $profile: subscriber's profile
|
||||
|
||||
EndUnsubscribePeopletag: after unsubscribing to a people tag
|
||||
- $peopletag: Profile_list object being subscribed to
|
||||
- $profile: subscriber's profile
|
||||
|
||||
StartActivityObjectFromPeopletag: while starting to create an ActivityObject from a people tag
|
||||
- $profile_list: the people tag, a Profile_list object
|
||||
- &$object: activity object
|
||||
|
||||
EndActivityObjectFromPeopletag: after making an ActivityObject from a people tag
|
||||
- $profile_list: the people tag, a Profile_list object
|
||||
- &$object: activity object
|
||||
|
||||
StartPeopletagGroupNav: Showing the people tag nav menu
|
||||
- $menu: the menu widget; use $menu->action for output
|
||||
|
||||
EndPeopletagGroupNav: after showing the people tag nav menu
|
||||
- $menu: the menu widget; use $menu->action for output
|
||||
|
||||
StartShowPeopletagItem: when showing a people tag
|
||||
- $widget: PeopletagListItem widget
|
||||
|
||||
EndShowPeopletagItem: after showing a people tag
|
||||
- $widget: PeopletagListItem widget
|
||||
|
||||
StartSubscribePeopletagForm: when showing people tag subscription form
|
||||
- $action: action being executed (for output and params)
|
||||
- $peopletag: people tag being subscribed to
|
||||
|
||||
EndSubscribePeopletagForm: after showing the people tag subscription form
|
||||
- $action: action being executed (for output and params)
|
||||
- $peopletag: people tag being subscribed to
|
||||
|
||||
StartShowPeopletags: when showing a textual list of people tags
|
||||
- $widget: PeopletagsWidget; use $widget->out for output
|
||||
- $tagger: profile of the tagger
|
||||
- $tagged: profile tagged
|
||||
|
||||
EndShowPeopletags: after showing a textual list of people tags
|
||||
- $widget: PeopletagsWidget; use $widget->out for output
|
||||
- $tagger: profile of the tagger
|
||||
- $tagged: profile tagged
|
||||
|
||||
StartProfileListItemTags: when showing people tags in a profile list item widget
|
||||
- $widget: ProfileListItem widget
|
||||
|
||||
EndProfileListItemTags: after showing people tags in a profile list item widget
|
||||
- $widget: ProfileListItem widget
|
||||
|
||||
StartActivityObjectOutputAtom: Called at start of Atom XML output generation for ActivityObject chunks, just inside the <activity:object>. Cancel the event to take over its output completely (you're responsible for calling the matching End event if so)
|
||||
- $obj: ActivityObject
|
||||
- $out: XMLOutputter to append custom output
|
||||
@ -1160,7 +1310,7 @@ StartShowGroupProfileBlock: When showing the profile block for a group
|
||||
- $out: XMLOutputter to append custom output
|
||||
- $profile: the profile being shown
|
||||
|
||||
EndShowGroupProfileBlock: After showing showing the profile block for a group
|
||||
EndShowGroupProfileBlock: After showing the profile block for a group
|
||||
- $out: XMLOutputter to append custom output
|
||||
- $group: the group being shown
|
||||
|
||||
@ -1183,3 +1333,4 @@ EndShowThreadedNoticeSub: when showing a reply to a notice
|
||||
- $nli: parent noticelistitem
|
||||
- $parent: parent notice
|
||||
- $child: child notice
|
||||
|
||||
|
178
actions/addpeopletag.php
Normal file
178
actions/addpeopletag.php
Normal file
@ -0,0 +1,178 @@
|
||||
<?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()) {
|
||||
// TRANS: Client error displayed when the session token does not match or is not given.
|
||||
$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)) {
|
||||
// TRANS: Error message displayed when trying to perform an action that requires a logged in 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)) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing profile.
|
||||
$this->clientError(_('No such profile.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = $this->arg('peopletag_id');
|
||||
$this->peopletag = Profile_list::staticGet('id', $id);
|
||||
|
||||
if (empty($this->peopletag)) {
|
||||
// TRANS: Client error displayed trying to reference a non-existing people tag.
|
||||
$this->clientError(_('No such people tag.'));
|
||||
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)) {
|
||||
// TRANS: Client error displayed trying to tag an OMB 0.1 remote profile.
|
||||
$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(
|
||||
// TRANS: Client error displayed when an unknown error occurs while tagging a user.
|
||||
// TRANS: %s is a username.
|
||||
sprintf(_('There was an unexpected error while tagging %s.'),
|
||||
$user->nickname));
|
||||
} else {
|
||||
// TRANS: Client error displayed when an unknown error occurs while tagging a user.
|
||||
// TRANS: %s is a profile URL.
|
||||
$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');
|
||||
// TRANS: Title after subscribing to a people tag.
|
||||
$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);
|
||||
}
|
||||
}
|
||||
}
|
270
actions/apilist.php
Normal file
270
actions/apilist.php
Normal file
@ -0,0 +1,270 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Show, update or delete a list.
|
||||
*
|
||||
* 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 API
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/lib/apibareauth.php';
|
||||
|
||||
class ApiListAction extends ApiBareAuthAction
|
||||
{
|
||||
/**
|
||||
* The list in question in the current request
|
||||
*/
|
||||
var $list = null;
|
||||
|
||||
/**
|
||||
* Is this an update request?
|
||||
*/
|
||||
var $update = false;
|
||||
|
||||
/**
|
||||
* Is this a delete request?
|
||||
*/
|
||||
var $delete = false;
|
||||
|
||||
/**
|
||||
* Set the flags for handling the request. Show list if this is a GET
|
||||
* request, update it if it is POST, delete list if method is DELETE
|
||||
* or if method is POST and an argument _method is set to DELETE. Act
|
||||
* like we don't know if the current user has no access to the list.
|
||||
*
|
||||
* Takes parameters:
|
||||
* - user: the user id or nickname
|
||||
* - id: the id of the tag or the tag itself
|
||||
*
|
||||
* @return boolean success flag
|
||||
*/
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->delete = ($_SERVER['REQUEST_METHOD'] == 'DELETE' ||
|
||||
($this->trimmed('_method') == 'DELETE' &&
|
||||
$_SERVER['REQUEST_METHOD'] == 'POST'));
|
||||
|
||||
// update list if method is POST or PUT and $this->delete is not true
|
||||
$this->update = (!$this->delete &&
|
||||
in_array($_SERVER['REQUEST_METHOD'], array('POST', 'PUT')));
|
||||
|
||||
$this->user = $this->getTargetUser($this->arg('user'));
|
||||
$this->list = $this->getTargetList($this->arg('user'), $this->arg('id'));
|
||||
|
||||
if (empty($this->list)) {
|
||||
// TRANS: Client error displayed when referring to a non-existing list.
|
||||
$this->clientError(_('List not found.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the request
|
||||
*
|
||||
* @return boolean success flag
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if($this->delete) {
|
||||
$this->handleDelete();
|
||||
return true;
|
||||
}
|
||||
|
||||
if($this->update) {
|
||||
$this->handlePut();
|
||||
return true;
|
||||
}
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showSingleXmlList($this->list);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showSingleJsonList($this->list);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* require authentication if it is a write action or user is ambiguous
|
||||
*
|
||||
*/
|
||||
function requiresAuth()
|
||||
{
|
||||
return parent::requiresAuth() ||
|
||||
$this->create || $this->delete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a list
|
||||
*
|
||||
* @return boolean success
|
||||
*/
|
||||
function handlePut()
|
||||
{
|
||||
if($this->auth_user->id != $this->list->tagger) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when trying to update another user's list.
|
||||
_('You cannot update lists that do not belong to you.'),
|
||||
401,
|
||||
$this->format
|
||||
);
|
||||
}
|
||||
|
||||
$new_list = clone($this->list);
|
||||
$new_list->tag = common_canonical_tag($this->arg('name'));
|
||||
$new_list->description = common_canonical_tag($this->arg('description'));
|
||||
$new_list->private = ($this->arg('mode') === 'private') ? true : false;
|
||||
|
||||
$result = $new_list->update($this->list);
|
||||
|
||||
if(!$result) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when an unknown error occurs updating a list.
|
||||
_('An error occured.'),
|
||||
503,
|
||||
$this->format
|
||||
);
|
||||
}
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showSingleXmlList($new_list);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showSingleJsonList($new_list);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a list
|
||||
*
|
||||
* @return boolean success
|
||||
*/
|
||||
function handleDelete()
|
||||
{
|
||||
if($this->auth_user->id != $this->list->tagger) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when trying to delete another user's list.
|
||||
_('You cannot delete lists that do not belong to you.'),
|
||||
401,
|
||||
$this->format
|
||||
);
|
||||
}
|
||||
|
||||
$record = clone($this->list);
|
||||
$this->list->delete();
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showSingleXmlList($record);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showSingleJsonList($record);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that this resource is not read-only.
|
||||
*
|
||||
* @return boolean is_read-only=false
|
||||
*/
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* When was the list (people tag) last updated?
|
||||
*
|
||||
* @return String time_last_modified
|
||||
*/
|
||||
function lastModified()
|
||||
{
|
||||
if(!empty($this->list)) {
|
||||
return strtotime($this->list->modified);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity tag for this list
|
||||
*
|
||||
* Returns an Etag based on the action name, language, user ID and
|
||||
* timestamps of the first and last list the user has joined
|
||||
*
|
||||
* @return string etag
|
||||
*/
|
||||
function etag()
|
||||
{
|
||||
if (!empty($this->list)) {
|
||||
|
||||
return '"' . implode(
|
||||
':',
|
||||
array($this->arg('action'),
|
||||
common_language(),
|
||||
$this->user->id,
|
||||
strtotime($this->list->created),
|
||||
strtotime($this->list->modified))
|
||||
)
|
||||
. '"';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
125
actions/apilistmember.php
Normal file
125
actions/apilistmember.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* API method to check if a user belongs to a list.
|
||||
*
|
||||
* 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 API
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/lib/apibareauth.php';
|
||||
|
||||
/**
|
||||
* Action handler for Twitter list_memeber methods
|
||||
*
|
||||
* @category API
|
||||
* @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/
|
||||
* @see ApiBareAuthAction
|
||||
*/
|
||||
class ApiListMemberAction extends ApiBareAuthAction
|
||||
{
|
||||
/**
|
||||
* Set the flags for handling the request. Show the profile if this
|
||||
* is a GET request AND the profile is a member of the list, add a member
|
||||
* if it is a POST, remove the profile from the list if method is DELETE
|
||||
* or if method is POST and an argument _method is set to DELETE. Act
|
||||
* like we don't know if the current user has no access to the list.
|
||||
*
|
||||
* Takes parameters:
|
||||
* - user: the user id or nickname
|
||||
* - list_id: the id of the tag or the tag itself
|
||||
* - id: the id of the member being looked for/added/removed
|
||||
*
|
||||
* @return boolean success flag
|
||||
*/
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->user = $this->getTargetUser($this->arg('id'));
|
||||
$this->list = $this->getTargetList($this->arg('user'), $this->arg('list_id'));
|
||||
|
||||
if (empty($this->list)) {
|
||||
// TRANS: Client error displayed when referring to a non-existing list.
|
||||
$this->clientError(_('List not found.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($this->user)) {
|
||||
// TRANS: Client error displayed when referring to a non-existing user.
|
||||
$this->clientError(_('No such user.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the request
|
||||
*
|
||||
* @return boolean success flag
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
$arr = array('tagger' => $this->list->tagger,
|
||||
'tag' => $this->list->tag,
|
||||
'tagged' => $this->user->id);
|
||||
$ptag = Profile_tag::pkeyGet($arr);
|
||||
|
||||
if(empty($ptag)) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when referring to a non-list member.
|
||||
_('The specified user is not a member of this list.'),
|
||||
400,
|
||||
$this->format
|
||||
);
|
||||
}
|
||||
|
||||
$user = $this->twitterUserArray($this->user->getProfile(), true);
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showTwitterXmlUser($user, 'user', true);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showSingleJsonUser($user);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
179
actions/apilistmembers.php
Normal file
179
actions/apilistmembers.php
Normal file
@ -0,0 +1,179 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* List/add/remove list members.
|
||||
*
|
||||
* 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 API
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/lib/apilistusers.php';
|
||||
|
||||
class ApiListMembersAction extends ApiListUsersAction
|
||||
{
|
||||
/**
|
||||
* Add a user to a list (tag someone)
|
||||
*
|
||||
* @return boolean success
|
||||
*/
|
||||
function handlePost()
|
||||
{
|
||||
if($this->auth_user->id != $this->list->tagger) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when trying to add members to a list without having the right to do so.
|
||||
_('You are not allowed to add members to this list.'),
|
||||
401,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->user === false) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when trying to modify list members without specifying them.
|
||||
_('You must specify a member.'),
|
||||
400,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = Profile_tag::setTag($this->auth_user->id,
|
||||
$this->user->id, $this->list->tag);
|
||||
|
||||
if(empty($result)) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when an unknown error occurs viewing list members.
|
||||
_('An error occured.'),
|
||||
500,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showSingleXmlList($this->list);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showSingleJsonList($this->list);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a user from a list (untag someone)
|
||||
*
|
||||
* @return boolean success
|
||||
*/
|
||||
function handleDelete()
|
||||
{
|
||||
if($this->auth_user->id != $this->list->tagger) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when trying to remove members from a list without having the right to do so.
|
||||
_('You are not allowed to remove members from this list.'),
|
||||
401,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->user === false) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when trying to modify list members without specifying them.
|
||||
_('You must specify a member.'),
|
||||
400,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$args = array('tagger' => $this->auth_user->id,
|
||||
'tagged' => $this->user->id,
|
||||
'tag' => $this->list->tag);
|
||||
$ptag = Profile_tag::pkeyGet($args);
|
||||
|
||||
if(empty($ptag)) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when trying to remove a list member that is not part of a list.
|
||||
_('The user you are trying to remove from the list is not a member.'),
|
||||
400,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $ptag->delete();
|
||||
|
||||
if(empty($result)) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when an unknown error occurs viewing list members.
|
||||
_('An error occured.'),
|
||||
500,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showSingleXmlList($this->list);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showSingleJsonList($this->list);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* List the members of a list (people tagged)
|
||||
*/
|
||||
function getUsers()
|
||||
{
|
||||
$fn = array($this->list, 'getTagged');
|
||||
list($this->users, $this->next_cursor, $this->prev_cursor) =
|
||||
Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
|
||||
}
|
||||
}
|
134
actions/apilistmemberships.php
Normal file
134
actions/apilistmemberships.php
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Get a list of lists a user belongs to. (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 API
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/lib/apibareauth.php';
|
||||
|
||||
/**
|
||||
* Action handler for API method to list lists a user belongs to.
|
||||
* (people tags for a user)
|
||||
*
|
||||
* @category API
|
||||
* @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/
|
||||
* @see ApiBareAuthAction
|
||||
*/
|
||||
class ApiListMembershipsAction extends ApiBareAuthAction
|
||||
{
|
||||
var $lists = array();
|
||||
var $cursor = -1;
|
||||
var $next_cursor = 0;
|
||||
var $prev_cursor = 0;
|
||||
|
||||
/**
|
||||
* Prepare for running the action
|
||||
* Take arguments for running:s
|
||||
*
|
||||
* @param array $args $_REQUEST args
|
||||
*
|
||||
* @return boolean success flag
|
||||
*
|
||||
*/
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->cursor = (int) $this->arg('cursor', -1);
|
||||
$this->user = $this->getTargetUser($this->arg('user'));
|
||||
|
||||
if (empty($this->user)) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
||||
$this->clientError(_('No such user.'), 404, $this->format);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->getLists();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the request
|
||||
*
|
||||
* Show the lists
|
||||
*
|
||||
* @param array $args $_REQUEST data (unused)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
400,
|
||||
$this->format
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if read only.
|
||||
*
|
||||
* MAY override
|
||||
*
|
||||
* @param array $args other arguments
|
||||
*
|
||||
* @return boolean is read only action?
|
||||
*/
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
function getLists()
|
||||
{
|
||||
$profile = $this->user->getProfile();
|
||||
$fn = array($profile, 'getOtherTags');
|
||||
|
||||
# 20 lists
|
||||
list($this->lists, $this->next_cursor, $this->prev_cursor) =
|
||||
Profile_list::getAtCursor($fn, array($this->auth_user), $this->cursor, 20);
|
||||
}
|
||||
}
|
240
actions/apilists.php
Normal file
240
actions/apilists.php
Normal file
@ -0,0 +1,240 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* List existing lists or create a new list.
|
||||
*
|
||||
* 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 API
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/lib/apibareauth.php';
|
||||
|
||||
/**
|
||||
* Action handler for Twitter list_memeber methods
|
||||
*
|
||||
* @category API
|
||||
* @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/
|
||||
* @see ApiBareAuthAction
|
||||
*/
|
||||
class ApiListsAction extends ApiBareAuthAction
|
||||
{
|
||||
var $lists = null;
|
||||
var $cursor = 0;
|
||||
var $next_cursor = 0;
|
||||
var $prev_cursor = 0;
|
||||
var $create = false;
|
||||
|
||||
/**
|
||||
* Set the flags for handling the request. List lists created by user if this
|
||||
* is a GET request, create a new list if it is a POST request.
|
||||
*
|
||||
* Takes parameters:
|
||||
* - user: the user id or nickname
|
||||
* Parameters for POST request
|
||||
* - name: name of the new list (the people tag itself)
|
||||
* - mode: (optional) mode for the new list private/public
|
||||
* - description: (optional) description for the list
|
||||
*
|
||||
* @return boolean success flag
|
||||
*/
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->create = ($_SERVER['REQUEST_METHOD'] == 'POST');
|
||||
|
||||
if (!$this->create) {
|
||||
|
||||
$this->user = $this->getTargetUser($this->arg('user'));
|
||||
|
||||
if (empty($this->user)) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
||||
$this->clientError(_('No such user.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
$this->getLists();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* require authentication if it is a write action or user is ambiguous
|
||||
*
|
||||
*/
|
||||
function requiresAuth()
|
||||
{
|
||||
return parent::requiresAuth() ||
|
||||
$this->create || $this->delete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request:
|
||||
* Show the lists the user has created if the request method is GET
|
||||
* Create a new list by diferring to handlePost() if it is POST.
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if($this->create) {
|
||||
return $this->handlePost();
|
||||
}
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new list
|
||||
*
|
||||
* @return boolean success
|
||||
*/
|
||||
function handlePost()
|
||||
{
|
||||
$name=$this->arg('name');
|
||||
if(empty($name)) {
|
||||
// mimick twitter
|
||||
// TRANS: Client error displayed when trying to create a list without a name.
|
||||
print _("A list must have a name.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// twitter creates a new list by appending a number to the end
|
||||
// if the list by the given name already exists
|
||||
// it makes more sense to return the existing list instead
|
||||
|
||||
$private = null;
|
||||
if ($this->arg('mode') === 'public') {
|
||||
$private = false;
|
||||
} else if ($this->arg('mode') === 'private') {
|
||||
$private = true;
|
||||
}
|
||||
|
||||
$list = Profile_list::ensureTag($this->auth_user->id,
|
||||
$this->arg('name'),
|
||||
$this->arg('description'),
|
||||
$private);
|
||||
if (empty($list)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showSingleXmlList($list);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showSingleJsonList($list);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get lists
|
||||
*/
|
||||
function getLists()
|
||||
{
|
||||
$cursor = (int) $this->arg('cursor', -1);
|
||||
|
||||
// twitter fixes count at 20
|
||||
// there is no argument named count
|
||||
$count = 20;
|
||||
$profile = $this->user->getProfile();
|
||||
$fn = array($profile, 'getOwnedTags');
|
||||
|
||||
list($this->lists,
|
||||
$this->next_cursor,
|
||||
$this->prev_cursor) = Profile_list::getAtCursor($fn, array($this->auth_user), $cursor, $count);
|
||||
}
|
||||
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
function lastModified()
|
||||
{
|
||||
if (!$this->create && !empty($this->lists) && (count($this->lists) > 0)) {
|
||||
return strtotime($this->lists[0]->created);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity tag for this list of lists
|
||||
*
|
||||
* Returns an Etag based on the action name, language, user ID and
|
||||
* timestamps of the first and last list the user has joined
|
||||
*
|
||||
* @return string etag
|
||||
*/
|
||||
function etag()
|
||||
{
|
||||
if (!$this->create && !empty($this->lists) && (count($this->lists) > 0)) {
|
||||
|
||||
$last = count($this->lists) - 1;
|
||||
|
||||
return '"' . implode(
|
||||
':',
|
||||
array($this->arg('action'),
|
||||
common_language(),
|
||||
$this->user->id,
|
||||
strtotime($this->lists[0]->created),
|
||||
strtotime($this->lists[$last]->created))
|
||||
)
|
||||
. '"';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
95
actions/apilistsubscriber.php
Normal file
95
actions/apilistsubscriber.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Check if a user is subscribed to a list
|
||||
*
|
||||
* 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 API
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/lib/apiauth.php';
|
||||
|
||||
class ApiListSubscriberAction extends ApiBareAuthAction
|
||||
{
|
||||
var $list = null;
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->user = $this->getTargetUser($this->arg('id'));
|
||||
$this->list = $this->getTargetList($this->arg('user'), $this->arg('list_id'));
|
||||
|
||||
if (empty($this->list)) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing list.
|
||||
$this->clientError(_('List not found.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($this->user)) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
||||
$this->clientError(_('No such user.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
$arr = array('profile_tag_id' => $this->list->id,
|
||||
'profile_id' => $this->user->id);
|
||||
$sub = Profile_tag_subscription::pkeyGet($arr);
|
||||
|
||||
if(empty($sub)) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when a membership check for a user is nagative.
|
||||
_('The specified user is not a subscriber of this list.'),
|
||||
400,
|
||||
$this->format
|
||||
);
|
||||
}
|
||||
|
||||
$user = $this->twitterUserArray($this->user->getProfile(), true);
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showTwitterXmlUser($user, 'user', true);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showSingleJsonUser($user);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
129
actions/apilistsubscribers.php
Normal file
129
actions/apilistsubscribers.php
Normal file
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Show/add/remove list 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 API
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/lib/apilistusers.php';
|
||||
|
||||
class ApiListSubscribersAction extends ApiListUsersAction
|
||||
{
|
||||
/**
|
||||
* Subscribe to list
|
||||
*
|
||||
* @return boolean success
|
||||
*/
|
||||
function handlePost()
|
||||
{
|
||||
$result = Profile_tag_subscription::add($this->list,
|
||||
$this->auth_user);
|
||||
|
||||
if(empty($result)) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when an unknown error occurs in the list subscribers action.
|
||||
_('An error occured.'),
|
||||
500,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showSingleXmlList($this->list);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showSingleJsonList($this->list);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function handleDelete()
|
||||
{
|
||||
$args = array('profile_tag_id' => $this->list->id,
|
||||
'profile_id' => $this->auth_user->id);
|
||||
$ptag = Profile_tag_subscription::pkeyGet($args);
|
||||
|
||||
if(empty($ptag)) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when trying to unsubscribe from a non-subscribed list.
|
||||
_('You are not subscribed to this list.'),
|
||||
400,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
Profile_tag_subscription::remove($this->list, $this->auth_user);
|
||||
|
||||
if(empty($result)) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when an unknown error occurs unsubscribing from a list.
|
||||
_('An error occured.'),
|
||||
500,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showSingleXmlList($this->list);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showSingleJsonList($this->list);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getUsers()
|
||||
{
|
||||
$fn = array($this->list, 'getSubscribers');
|
||||
list($this->users, $this->next_cursor, $this->prev_cursor) =
|
||||
Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
|
||||
}
|
||||
}
|
125
actions/apilistsubscriptions.php
Normal file
125
actions/apilistsubscriptions.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Get a list of lists a user is subscribed to.
|
||||
*
|
||||
* 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 API
|
||||
* @package StatusNet
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/lib/apibareauth.php';
|
||||
|
||||
class ApiListSubscriptionsAction extends ApiBareAuthAction
|
||||
{
|
||||
var $lists = array();
|
||||
var $cursor = -1;
|
||||
var $next_cursor = 0;
|
||||
var $prev_cursor = 0;
|
||||
|
||||
/**
|
||||
* Take arguments for running
|
||||
*
|
||||
* @param array $args $_REQUEST args
|
||||
*
|
||||
* @return boolean success flag
|
||||
*
|
||||
*/
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->cursor = (int) $this->arg('cursor', -1);
|
||||
$this->user = $this->getTargetUser($this->arg('user'));
|
||||
$this->getLists();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the request
|
||||
*
|
||||
* Show the lists
|
||||
*
|
||||
* @param array $args $_REQUEST data (unused)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if (empty($this->user)) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
||||
$this->clientError(_('No such user.'), 404, $this->format);
|
||||
return;
|
||||
}
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
||||
break;
|
||||
case 'json':
|
||||
$this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
400,
|
||||
$this->format
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if read only.
|
||||
*
|
||||
* MAY override
|
||||
*
|
||||
* @param array $args other arguments
|
||||
*
|
||||
* @return boolean is read only action?
|
||||
*/
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
function getLists()
|
||||
{
|
||||
if(empty($this->user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$profile = $this->user->getProfile();
|
||||
$fn = array($profile, 'getTagSubscriptions');
|
||||
# 20 lists
|
||||
list($this->lists, $this->next_cursor, $this->prev_cursor) =
|
||||
Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
|
||||
}
|
||||
}
|
258
actions/apitimelinelist.php
Normal file
258
actions/apitimelinelist.php
Normal file
@ -0,0 +1,258 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Show a list's 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 API
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/lib/apiprivateauth.php';
|
||||
require_once INSTALLDIR . '/lib/atomlistnoticefeed.php';
|
||||
|
||||
/**
|
||||
* Returns the most recent notices (default 20) posted to the list specified by ID
|
||||
*
|
||||
* @category API
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @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/
|
||||
*/
|
||||
class ApiTimelineListAction extends ApiPrivateAuthAction
|
||||
{
|
||||
|
||||
var $list = null;
|
||||
var $notices = array();
|
||||
var $next_cursor = 0;
|
||||
var $prev_cursor = 0;
|
||||
var $cursor = -1;
|
||||
|
||||
/**
|
||||
* Take arguments for running
|
||||
*
|
||||
* @param array $args $_REQUEST args
|
||||
*
|
||||
* @return boolean success flag
|
||||
*
|
||||
*/
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->cursor = (int) $this->arg('cursor', -1);
|
||||
$this->list = $this->getTargetList($this->arg('user'), $this->arg('id'));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the request
|
||||
*
|
||||
* Just show the notices
|
||||
*
|
||||
* @param array $args $_REQUEST data (unused)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if (empty($this->list)) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing list.
|
||||
$this->clientError(_('List not found.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->getNotices();
|
||||
$this->showTimeline();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the timeline of notices
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showTimeline()
|
||||
{
|
||||
// We'll pull common formatting out of this for other formats
|
||||
$atom = new AtomListNoticeFeed($this->list, $this->auth_user);
|
||||
|
||||
$self = $this->getSelfUri();
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->initDocument('xml');
|
||||
$this->elementStart('statuses_list',
|
||||
array('xmlns:statusnet' => 'http://status.net/schema/api/1/'));
|
||||
$this->elementStart('statuses', array('type' => 'array'));
|
||||
|
||||
foreach ($this->notices as $n) {
|
||||
$twitter_status = $this->twitterStatusArray($n);
|
||||
$this->showTwitterXmlStatus($twitter_status);
|
||||
}
|
||||
|
||||
$this->elementEnd('statuses');
|
||||
$this->element('next_cursor', null, $this->next_cursor);
|
||||
$this->element('previous_cursor', null, $this->prev_cursor);
|
||||
$this->elementEnd('statuses_list');
|
||||
$this->endDocument('xml');
|
||||
break;
|
||||
case 'rss':
|
||||
$this->showRssTimeline(
|
||||
$this->notices,
|
||||
$atom->title,
|
||||
$this->list->getUri(),
|
||||
$atom->subtitle,
|
||||
null,
|
||||
$atom->logo,
|
||||
$self
|
||||
);
|
||||
break;
|
||||
case 'atom':
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
|
||||
try {
|
||||
$atom->setId($self);
|
||||
$atom->setSelfLink($self);
|
||||
$atom->addEntryFromNotices($this->notices);
|
||||
$this->raw($atom->getString());
|
||||
} catch (Atom10FeedException $e) {
|
||||
// TRANS: Server error displayed whe trying to get a timeline fails.
|
||||
// TRANS: %s is the error message.
|
||||
$this->serverError( sprintf(_('Could not generate feed for list - %s'),$e->getMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
case 'json':
|
||||
$this->initDocument('json');
|
||||
|
||||
$statuses = array();
|
||||
foreach ($this->notices as $n) {
|
||||
$twitter_status = $this->twitterStatusArray($n);
|
||||
array_push($statuses, $twitter_status);
|
||||
}
|
||||
|
||||
$statuses_list = array('statuses' => $statuses,
|
||||
'next_cursor' => $this->next_cusror,
|
||||
'next_cursor_str' => strval($this->next_cusror),
|
||||
'previous_cursor' => $this->prev_cusror,
|
||||
'previous_cursor_str' => strval($this->prev_cusror)
|
||||
);
|
||||
$this->showJsonObjects($statuses_list);
|
||||
|
||||
$this->initDocument('json');
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notices
|
||||
*
|
||||
* @return array notices
|
||||
*/
|
||||
function getNotices()
|
||||
{
|
||||
$fn = array($this->list, 'getNotices');
|
||||
list($this->notices, $this->next_cursor, $this->prev_cursor) =
|
||||
Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
|
||||
if (!$this->notices) {
|
||||
$this->notices = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this action read only?
|
||||
*
|
||||
* @param array $args other arguments
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* When was this feed last modified?
|
||||
*
|
||||
* @return string datestamp of the latest notice in the stream
|
||||
*/
|
||||
function lastModified()
|
||||
{
|
||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
||||
return strtotime($this->notices[0]->created);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity tag for this stream
|
||||
*
|
||||
* Returns an Etag based on the action name, language, list ID and
|
||||
* timestamps of the first and last notice in the timeline
|
||||
*
|
||||
* @return string etag
|
||||
*/
|
||||
function etag()
|
||||
{
|
||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
||||
|
||||
$last = count($this->notices) - 1;
|
||||
|
||||
return '"' . implode(
|
||||
':',
|
||||
array($this->arg('action'),
|
||||
common_language(),
|
||||
$this->list->id,
|
||||
strtotime($this->notices[0]->created),
|
||||
strtotime($this->notices[$last]->created))
|
||||
)
|
||||
. '"';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
333
actions/editpeopletag.php
Normal file
333
actions/editpeopletag.php
Normal file
@ -0,0 +1,333 @@
|
||||
<?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')) {
|
||||
// TRANS: Title for edit people tag page after deleting a tag.
|
||||
// TRANS: %s is a tag.
|
||||
return sprintf(_('Delete %s people tag'), $this->peopletag->tag);
|
||||
}
|
||||
// TRANS: Title for edit people tag page.
|
||||
// TRANS: %s is a tag.
|
||||
return sprintf(_('Edit people tag %s'), $this->peopletag->tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare to run
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
if (!common_logged_in()) {
|
||||
// TRANS: Error message displayed when trying to perform an action that requires a logged in user.
|
||||
$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) {
|
||||
// TRANS: Error message displayed when trying to perform an action that requires a tagging user or ID.
|
||||
$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) {
|
||||
// TRANS: Client error displayed when referring to a non-exsting people tag.
|
||||
$this->clientError(_('No such people tag.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$user) {
|
||||
// This should not be happening
|
||||
// TRANS: Client error displayed when referring to non-local user.
|
||||
$this->clientError(_('Not a local user.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($current->id != $user->id) {
|
||||
// TRANS: Client error displayed when reting to edit a tag that was not self-created.
|
||||
$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 showObjectNav()
|
||||
{
|
||||
$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',
|
||||
// TRANS: Form instruction for edit people tag form.
|
||||
_('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) {
|
||||
// TRANS: Form validation error displayed if the form data for deleting a tag was incorrect.
|
||||
$this->showForm(_('Delete aborted.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$set_private = $private && $this->peopletag->private != $private;
|
||||
|
||||
if ($delete && !$confirm) {
|
||||
// TRANS: Text in confirmation dialog for deleting a tag.
|
||||
$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)) {
|
||||
// TRANS: Form validation error displayed if a given tag is invalid.
|
||||
$this->showForm(_('Invalid tag.'));
|
||||
return;
|
||||
} else if ($tag != $this->peopletag->tag && $this->tagExists($tag)) {
|
||||
// TRANS: Form validation error displayed if a given tag is already present.
|
||||
// TRANS: %s is the already present tag.
|
||||
$this->showForm(sprintf(_('You already have a tag named %s.'), $tag));
|
||||
return;
|
||||
} else if (Profile_list::descriptionTooLong($description)) {
|
||||
$this->showForm(sprintf(
|
||||
// TRANS: Client error shown when providing too long a description when editing a people tag.
|
||||
// TRANS: %d is the maximum number of allowed characters.
|
||||
_m('Description is too long (maximum %d character).',
|
||||
'Description is too long (maximum %d characters).',
|
||||
Profile_list::maxDescription()),
|
||||
Profile_list::maxDescription()));
|
||||
return;
|
||||
} else if ($set_private && !$confirm && !$cancel) {
|
||||
$fwd = array('tag' => $tag,
|
||||
'description' => $description,
|
||||
'private' => (int) $private);
|
||||
|
||||
// TRANS: Text in confirmation dialog for setting a tag from public to 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__);
|
||||
// TRANS: TRANS: Server error displayed when updating a people tag fails.
|
||||
$this->serverError(_('Could not update people tag.'));
|
||||
}
|
||||
|
||||
$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 {
|
||||
// TRANS: Edit people tag form success message.
|
||||
$this->showForm(_('Options saved.'));
|
||||
}
|
||||
}
|
||||
|
||||
function tagExists($tag)
|
||||
{
|
||||
$args = array('tagger' => $this->tagger->id, 'tag' => $tag);
|
||||
$ptag = Profile_list::pkeyGet($args);
|
||||
|
||||
return !empty($ptag);
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@ -16,13 +16,16 @@
|
||||
* 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/
|
||||
@ -32,150 +35,131 @@ 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
|
||||
*/
|
||||
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)) {
|
||||
// TRANS: Client error displayed when trying to tag a profile with an invalid tag.
|
||||
// TRANS: %s is the invalid tag.
|
||||
$this->clientError(sprintf(_('Not a valid people tag: %s.'),
|
||||
$this->tag));
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->page = ($this->arg('page')) ? $this->arg('page') : 1;
|
||||
function title()
|
||||
{
|
||||
if ($this->page == 1) {
|
||||
// TRANS: Title for people tag page.
|
||||
// TRANS: %s is a tag.
|
||||
return sprintf(_('Public people tag %s'), $this->tag);
|
||||
} else {
|
||||
// TRANS: Title for people tag page.
|
||||
// TRANS: %1$s is a tag, %2$d is a page number.
|
||||
return sprintf(_('Public people tag %1$s, page %2$d'), $this->tag, $this->page);
|
||||
}
|
||||
}
|
||||
|
||||
common_set_returnto($this->selfUrl());
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||
|
||||
$tag_arg = $this->arg('tag');
|
||||
$tag = common_canonical_tag($tag_arg);
|
||||
|
||||
// Permanent redirect on non-canonical nickname
|
||||
|
||||
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;
|
||||
|
||||
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 handle($args)
|
||||
{
|
||||
parent::handle($argarray);
|
||||
parent::handle($args);
|
||||
$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 showLocalNav()
|
||||
{
|
||||
$nav = new PublicGroupNav($this);
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
function showAnonymousMessage()
|
||||
{
|
||||
$notice =
|
||||
// TRANS: Message for anonymous users on people tag page.
|
||||
// TRANS: This message contains Markdown links in the form [description](link).
|
||||
_('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');
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$offset = ($this->page-1) * PEOPLETAGS_PER_PAGE;
|
||||
$limit = PEOPLETAGS_PER_PAGE + 1;
|
||||
|
||||
$profile = new Profile();
|
||||
$ptags = new Profile_list();
|
||||
$ptags->tag = $this->tag;
|
||||
|
||||
$offset = ($this->page - 1) * PROFILES_PER_PAGE;
|
||||
$limit = PROFILES_PER_PAGE + 1;
|
||||
$user = common_current_user();
|
||||
|
||||
if (common_config('db', 'type') == 'pgsql') {
|
||||
$lim = ' LIMIT ' . $limit . ' OFFSET ' . $offset;
|
||||
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 {
|
||||
$lim = ' LIMIT ' . $offset . ', ' . $limit;
|
||||
$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) )');
|
||||
|
||||
$ptags->orderBy('profile_list.modified DESC');
|
||||
$ptags->find();
|
||||
}
|
||||
|
||||
// XXX: memcached this
|
||||
$pl = new PeopletagList($ptags, $this);
|
||||
$cnt = $pl->show();
|
||||
|
||||
$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));
|
||||
$this->pagination($this->page > 1, $cnt > PEOPLETAGS_PER_PAGE,
|
||||
$this->page, 'peopletag', array('tag' => $this->tag));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page title
|
||||
*
|
||||
* @return string page title
|
||||
*/
|
||||
function title()
|
||||
function showSections()
|
||||
{
|
||||
// TRANS: Page title for users with a certain self-tag.
|
||||
// TRANS: %1$s is the tag, %2$s is the page number.
|
||||
return sprintf(_('Users self-tagged with %1$s - page %2$d'),
|
||||
$this->tag, $this->page);
|
||||
}
|
||||
}
|
||||
|
||||
class PeopleTagList extends ProfileList
|
||||
{
|
||||
function newListItem($profile)
|
||||
{
|
||||
return new PeopleTagListItem($profile, $this->action);
|
||||
}
|
||||
}
|
||||
|
||||
class PeopleTagListItem extends ProfileListItem
|
||||
{
|
||||
function linkAttributes()
|
||||
{
|
||||
$aAttrs = parent::linkAttributes();
|
||||
|
||||
if (common_config('nofollow', 'peopletag')) {
|
||||
$aAttrs['rel'] .= ' nofollow';
|
||||
}
|
||||
|
||||
return $aAttrs;
|
||||
}
|
||||
|
||||
function homepageAttributes()
|
||||
{
|
||||
$aAttrs = parent::linkAttributes();
|
||||
|
||||
if (common_config('nofollow', 'peopletag')) {
|
||||
$aAttrs['rel'] = 'nofollow';
|
||||
}
|
||||
|
||||
return $aAttrs;
|
||||
}
|
||||
}
|
||||
|
126
actions/peopletagautocomplete.php
Normal file
126
actions/peopletagautocomplete.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?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;
|
||||
var $tags;
|
||||
var $last_mod;
|
||||
|
||||
/**
|
||||
* 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)) {
|
||||
// TRANS: Error message displayed when trying to perform an action that requires a logged in user.
|
||||
$this->clientError(_('Not logged in.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// CSRF protection
|
||||
|
||||
$token = $this->trimmed('token');
|
||||
|
||||
if (!$token || $token != common_session_token()) {
|
||||
// TRANS: Client error displayed when the session token does not match or is not given.
|
||||
$this->clientError(_('There was a problem with your session token.'.
|
||||
' Try again, please.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$profile = $this->user->getProfile();
|
||||
$tags = $profile->getOwnedTags(common_current_user());
|
||||
|
||||
$this->tags = array();
|
||||
while ($tags->fetch()) {
|
||||
|
||||
if (empty($this->last_mod)) {
|
||||
$this->last_mod = $tags->modified;
|
||||
}
|
||||
|
||||
$arr = array();
|
||||
$arr['tag'] = $tags->tag;
|
||||
$arr['mode'] = $tags->private ? 'private' : 'public';
|
||||
// $arr['url'] = $tags->homeUrl();
|
||||
$arr['freq'] = $tags->taggedCount();
|
||||
|
||||
$this->tags[] = $arr;
|
||||
}
|
||||
|
||||
$tags->free();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Last modified time
|
||||
*
|
||||
* Helps in browser-caching
|
||||
*
|
||||
* @return String time
|
||||
*/
|
||||
function lastModified()
|
||||
{
|
||||
return strtotime($this->last_mod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request
|
||||
*
|
||||
* Print the JSON autocomplete data
|
||||
*
|
||||
* @param Array $args unused.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
//common_log(LOG_DEBUG, 'Autocomplete data: ' . json_encode($this->tags));
|
||||
if ($this->tags) {
|
||||
print(json_encode($this->tags));
|
||||
exit(0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
230
actions/peopletagged.php
Normal file
230
actions/peopletagged.php
Normal file
@ -0,0 +1,230 @@
|
||||
<?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) {
|
||||
// TRANS: Client error displayed when a tagger is expected but not provided.
|
||||
$this->clientError(_('No tagger.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
$user = User::staticGet('nickname', $tagger);
|
||||
|
||||
if (!$user) {
|
||||
// TRANS: Client error displayed when referring to non-existing 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) {
|
||||
// TRANS: Client error displayed when referring to non-existing people tag.
|
||||
$this->clientError(_('No such people tag.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
if ($this->page == 1) {
|
||||
// TRANS: Title for list of people tagged by the user with a tag.
|
||||
// TRANS: %1$s is a tag, %2$s is a username.
|
||||
return sprintf(_('People tagged %1$s by %2$s'),
|
||||
$this->peopletag->tag, $this->tagger->nickname);
|
||||
} else {
|
||||
// TRANS: Title for list of people tagged by the user with a tag.
|
||||
// TRANS: %1$s is a tag, %2$s is a username, %2$s is a page number.
|
||||
return sprintf(_('People tagged %1$s by %2$s, page %3$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(' ');
|
||||
// TRANS: Addition in tag membership list for creator of a tag.
|
||||
$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;
|
||||
}
|
||||
}
|
278
actions/peopletagsbyuser.php
Normal file
278
actions/peopletagsbyuser.php
Normal file
@ -0,0 +1,278 @@
|
||||
<?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')) {
|
||||
// TRANS: Title for people tags by a user page for a private tag.
|
||||
return _('Private people tags by you');
|
||||
} else if ($this->arg('public')) {
|
||||
// TRANS: Title for people tags by a user page for a public tag.
|
||||
return _('Public people tags by you');
|
||||
}
|
||||
// TRANS: Title for people tags by a user page.
|
||||
return _('People tags by you');
|
||||
}
|
||||
// TRANS: Title for people tags by a user page.
|
||||
// TRANS: %s is a user nickname.
|
||||
return sprintf(_('People tags by %s'), $this->tagger->nickname);
|
||||
} else {
|
||||
// TRANS: Title for people tags by a user page.
|
||||
// TRANS: %1$s is a user nickname, %2$d is a page number.
|
||||
return sprintf(_('People tags by %1$s, page %2$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) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
||||
$this->clientError(_('No such user.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->tagger = $this->user->getProfile();
|
||||
|
||||
if (!$this->tagger) {
|
||||
// TRANS: Server error displayed when a user has no profile.
|
||||
$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)) {
|
||||
// TRANS: Error message displayed when trying to perform an action that requires a logged in user.
|
||||
$this->clientError(_('Not logged in.'), 403);
|
||||
}
|
||||
|
||||
if ($this->isOwner()) {
|
||||
$this->tags = $this->tagger->getPrivateTags($offset, $limit);
|
||||
} else {
|
||||
// TRANS: Client error displayed when trying view another user's private people tags.
|
||||
$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'));
|
||||
// TRANS: Mode selector label.
|
||||
$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))),
|
||||
// TRANS: Link text to show people tags for user %s.
|
||||
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');
|
||||
// TRANS: Fieldset legend.
|
||||
$this->element('legend', null, _('Select tag to filter'));
|
||||
|
||||
$priv = $this->arg('private');
|
||||
$pub = $this->arg('public');
|
||||
|
||||
if (!$priv && !$pub) {
|
||||
$priv = $pub = true;
|
||||
}
|
||||
// TRANS: Checkbox label to show private tags.
|
||||
$this->checkbox('private', _m('LABEL','Private'), $priv,
|
||||
// TRANS: Checkbox title.
|
||||
_('Show private tags.'));
|
||||
// TRANS: Checkbox label to show public tags.
|
||||
$this->checkbox('public', _m('LABEL','Public'), $pub,
|
||||
// TRANS: Checkbox title.
|
||||
_('Show public tags.'));
|
||||
$this->hidden('nickname', $this->user->nickname);
|
||||
// TRANS: Submit button text for tag filter form.
|
||||
$this->submit('submit', _m('BUTTON','Go'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
$this->elementEnd('ul');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
|
||||
function showAnonymousMessage()
|
||||
{
|
||||
$notice =
|
||||
// TRANS: Message displayed for anonymous users on page that displays people tags by a user.
|
||||
// TRANS: This message contains Markdown links in the form [description](links).
|
||||
// TRANS: %s is a tagger nickname.
|
||||
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()
|
||||
{
|
||||
// TRANS: Message displayed on page that displays people tags by a user when there are none.
|
||||
// TRANS: This message contains Markdown links in the form [description](links).
|
||||
// TRANS: %s is a tagger nickname.
|
||||
$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"
|
||||
}
|
||||
}
|
176
actions/peopletagsforuser.php
Normal file
176
actions/peopletagsforuser.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?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) {
|
||||
// Page title. %s is a tagged user's nickname.
|
||||
return sprintf(_('People tags for %s'), $this->tagged->nickname);
|
||||
} else {
|
||||
// Page title. %1$s is a tagged user's nickname, %2$s is a page number.
|
||||
return sprintf(_('People tags for %1$s, page %2$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) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
||||
$this->clientError(_('No such user.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->tagged = $this->user->getProfile();
|
||||
|
||||
if (!$this->tagged) {
|
||||
// TRANS: Server error displayed when a user has no 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 showAnonymousMessage()
|
||||
{
|
||||
$notice =
|
||||
// TRANS: Message displayed for anonymous users on page that displays people tags for a user.
|
||||
// TRANS: This message contains Markdown links in the form [description](links).
|
||||
// TRANS: %s is a tagger nickname.
|
||||
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();
|
||||
// TRANS: Page notice.
|
||||
$text = ($this->tagged->id == @$user->id) ? _('People tags by you') :
|
||||
// TRANS: Page notice. %s is a tagger's nickname.
|
||||
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()
|
||||
{
|
||||
// TRANS: Message displayed on page that displays people tags for a user when there are none.
|
||||
// TRANS: This message contains Markdown links in the form [description](links).
|
||||
// TRANS: %s is a tagger nickname.
|
||||
$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"
|
||||
}
|
||||
}
|
245
actions/peopletagsubscribers.php
Normal file
245
actions/peopletagsubscribers.php
Normal file
@ -0,0 +1,245 @@
|
||||
<?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) {
|
||||
// TRANS: Client error displayed when a tagger is expected but not provided.
|
||||
$this->clientError(_('No tagger.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
$user = User::staticGet('nickname', $tagger);
|
||||
|
||||
if (!$user) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing 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) {
|
||||
// TRANS: Client error displayed trying to reference a non-existing people tag.
|
||||
$this->clientError(_('No such people tag.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
if ($this->page == 1) {
|
||||
// TRANS: Page title for list of people tag subscribers.
|
||||
// TRANS: %1$s is a tag, %2$s is a user nickname.
|
||||
return sprintf(_('Subscribers of people tagged %1$s by %2$s'),
|
||||
$this->peopletag->tag, $this->tagger->nickname);
|
||||
} else {
|
||||
// TRANS: Page title for list of people tag subscribers.
|
||||
// TRANS: %1$s is a tag, %2$s is a user nickname, %3$d is a page number.
|
||||
return sprintf(_('Subscribers of people tagged %1$s by %2$s, page %3$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(' ');
|
||||
// TRANS: Addition in tag subscribers list for creator of a tag.
|
||||
$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;
|
||||
}
|
||||
}
|
141
actions/peopletagsubscriptions.php
Normal file
141
actions/peopletagsubscriptions.php
Normal file
@ -0,0 +1,141 @@
|
||||
<?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) {
|
||||
// TRANS: Title for page that displays people tags subscribed to by a user.
|
||||
// TRANS: %s is a profile nickname.
|
||||
return sprintf(_('People tags subscriptions by %s'), $this->profile->nickname);
|
||||
} else {
|
||||
// TRANS: Title for page that displays people tags subscribed to by a user.
|
||||
// TRANS: %1$s is a profile nickname, %2$d is a page number.
|
||||
return sprintf(_('People tags subscriptions by %1$s, page %2$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) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
||||
$this->clientError(_('No such user.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->profile = $user->getProfile();
|
||||
|
||||
if (!$this->profile) {
|
||||
// TRANS: Server error displayed when a user has no 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 showAnonymousMessage()
|
||||
{
|
||||
$notice =
|
||||
// TRANS: Message displayed for anonymous users on page that displays people tags subscribed to by a user.
|
||||
// TRANS: This message contains Markdown links in the form [description](links).
|
||||
// TRANS: %s is a profile nickname.
|
||||
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"
|
||||
}
|
||||
}
|
222
actions/profilecompletion.php
Normal file
222
actions/profilecompletion.php
Normal file
@ -0,0 +1,222 @@
|
||||
<?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()) {
|
||||
// TRANS: Client error displayed when the session token does not match or is not given.
|
||||
$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)) {
|
||||
// TRANS: Error message displayed when trying to perform an action that requires a logged in user.
|
||||
$this->clientError(_('Not logged in.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = $this->arg('peopletag_id');
|
||||
$this->peopletag = Profile_list::staticGet('id', $id);
|
||||
|
||||
if (empty($this->peopletag)) {
|
||||
// TRANS: Client error displayed trying to reference a non-existing people tag.
|
||||
$this->clientError(_('No such people tag.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$field = $this->arg('field');
|
||||
if (!in_array($field, array('fulltext', 'nickname', 'fullname', 'description', 'location', 'uri'))) {
|
||||
// TRANS: Client error displayed when trying to add an unindentified field to profile.
|
||||
// TRANS: %s is a field name.
|
||||
$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');
|
||||
// TRANS: Page title.
|
||||
$this->element('title', null, _m('TITLE','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 {
|
||||
// TRANS: Output when there are no results for a search.
|
||||
$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) {
|
||||
// TRANS: Error message in case a search is shorter than three characters.
|
||||
$this->msg = _('The search string must be at least 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();
|
||||
}
|
||||
// @todo FIXME: Call-time pass-by-reference has been deprecated.
|
||||
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');
|
||||
}
|
||||
}
|
@ -298,19 +298,25 @@ class ProfilesettingsAction extends SettingsAction
|
||||
return;
|
||||
}
|
||||
|
||||
if ($tagstring) {
|
||||
$tags = array_map('common_canonical_tag', preg_split('/[\s,]+/', $tagstring));
|
||||
} else {
|
||||
$tags = array();
|
||||
}
|
||||
$tag_priv = array();
|
||||
if (is_string($tagstring) && strlen($tagstring) > 0) {
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
$user = common_current_user();
|
||||
@ -444,7 +450,7 @@ class ProfilesettingsAction extends SettingsAction
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
92
actions/profiletagbyid.php
Normal file
92
actions/profiletagbyid.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?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) {
|
||||
// TRANS: Client error displayed trying to perform an action without providing an 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) {
|
||||
// TRANS: Client error displayed trying to reference a non-existing people tag.
|
||||
$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);
|
||||
}
|
||||
}
|
@ -223,6 +223,8 @@ class PublicAction extends Action
|
||||
$pop->show();
|
||||
$gbp = new GroupsByMembersSection($this);
|
||||
$gbp->show();
|
||||
$ptp = new PeopletagsBySubsSection($this);
|
||||
$ptp->show();
|
||||
$feat = new FeaturedUsersSection($this);
|
||||
$feat->show();
|
||||
}
|
||||
|
182
actions/publicpeopletagcloud.php
Normal file
182
actions/publicpeopletagcloud.php
Normal file
@ -0,0 +1,182 @@
|
||||
<?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()
|
||||
{
|
||||
// TRANS: Title for page with public people tag cloud.
|
||||
return _('Public people tag cloud');
|
||||
}
|
||||
|
||||
function showPageNotice()
|
||||
{
|
||||
$this->element('p', 'instructions',
|
||||
// TRANS: Page notice for page with public people tag cloud.
|
||||
// TRANS: %s is a StatusNet sitename.
|
||||
sprintf(_('These are most used people tags on %s'),
|
||||
common_config('site', 'name')));
|
||||
}
|
||||
|
||||
function showEmptyList()
|
||||
{
|
||||
// TRANS: Empty list message on page with public people tag cloud.
|
||||
// TRANS: This message contains Markdown links in the form [description](link).
|
||||
$message = _('No one has [tagged](%%doc.tags%%) anyone yet.') . ' ';
|
||||
|
||||
if (common_logged_in()) {
|
||||
// TRANS: Additional empty list message on page with public people tag cloud for logged in users.
|
||||
$message .= _('Be the first to tag someone!');
|
||||
}
|
||||
else {
|
||||
// TRANS: Additional empty list message on page with public people tag cloud for anonymous users.
|
||||
// TRANS: This message contains Markdown links in the form [description](link).
|
||||
$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');
|
||||
// TRANS: DT element on on page with public people tag cloud.
|
||||
$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);
|
||||
|
||||
// TRANS: Link title for number of people tagged. %d is the number of people tagged.
|
||||
$title = sprintf(_m('1 person tagged','%d people tagged',$weight),$weight);
|
||||
$this->element('a', array('href' => common_local_url('peopletag', array('tag' => $tag)),
|
||||
'title' => $title), $tag);
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
}
|
180
actions/removepeopletag.php
Normal file
180
actions/removepeopletag.php
Normal file
@ -0,0 +1,180 @@
|
||||
<?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()) {
|
||||
// TRANS: Client error displayed when the session token does not match or is not given.
|
||||
$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)) {
|
||||
// TRANS: Error message displayed when trying to perform an action that requires a logged in 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)) {
|
||||
// TRANS: Client error displayed when referring to a non-existing profile.
|
||||
$this->clientError(_('No such profile.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = $this->arg('peopletag_id');
|
||||
$this->peopletag = Profile_list::staticGet('id', $id);
|
||||
|
||||
if (empty($this->peopletag)) {
|
||||
// TRANS: Client error displayed trying to reference a non-existing people tag.
|
||||
$this->clientError(_('No such people tag.'));
|
||||
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)) {
|
||||
// TRANS: Client error displayed when trying to (un)tag an OMB 0.1 remote profile.
|
||||
$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(
|
||||
// TRANS: Client error displayed when an unknown error occurs while tagging a user.
|
||||
// TRANS: %s is a username.
|
||||
sprintf(_('There was an unexpected error while tagging %s.'),
|
||||
$user->nickname));
|
||||
} else {
|
||||
// TRANS: Client error displayed when an unknown error occurs while tagging a user.
|
||||
// TRANS: %s is a profile URL.
|
||||
$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');
|
||||
// TRANS: Title after untagging a people tag.
|
||||
$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);
|
||||
}
|
||||
}
|
||||
}
|
204
actions/selftag.php
Normal file
204
actions/selftag.php
Normal file
@ -0,0 +1,204 @@
|
||||
<?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)) {
|
||||
// TRANS: Client error displayed when trying to tag a profile with an invalid tag.
|
||||
// TRANS: %s is the invalid 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()
|
||||
{
|
||||
// TRANS: Page title for page showing self tags.
|
||||
// TRANS: %1$s is a tag, %2$d is a page number.
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
383
actions/showprofiletag.php
Normal file
383
actions/showprofiletag.php
Normal file
@ -0,0 +1,383 @@
|
||||
<?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) {
|
||||
// TRANS: Client error displayed when a tagger is expected but not provided.
|
||||
$this->clientError(_('No tagger.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
$user = User::staticGet('nickname', $tagger);
|
||||
|
||||
if (!$user) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing 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) {
|
||||
// TRANS: Client error displayed trying to reference a non-existing people tag.
|
||||
$this->clientError(_('No such people tag.'), 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) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
||||
$this->clientError(_('No such user.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
if ($this->page > 1) {
|
||||
if($this->peopletag->private) {
|
||||
// TRANS: Title for private people tag timeline.
|
||||
// TRANS: %1$s is a people tag, %2$s is a page number.
|
||||
return sprintf(_('Private timeline for people tagged %1$s by you, page %2$d'),
|
||||
$this->peopletag->tag, $this->page);
|
||||
}
|
||||
|
||||
$current = common_current_user();
|
||||
if (!empty($current) && $current->id == $this->peopletag->tagger) {
|
||||
// TRANS: Title for public people tag timeline where the viewer is the tagger.
|
||||
// TRANS: %1$s is a people tag, %2$s is a page number.
|
||||
return sprintf(_('Timeline for people tagged %1$s by you, page %2$d'),
|
||||
$this->peopletag->tag, $this->page);
|
||||
}
|
||||
|
||||
// TRANS: Title for private people tag timeline.
|
||||
// TRANS: %1$s is a people tag, %2$s is the tagger's nickname, %3$d is a 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) {
|
||||
// TRANS: Title for private people tag timeline.
|
||||
// TRANS: %s is a people tag.
|
||||
return sprintf(_('Private timeline of people tagged %s by you'),
|
||||
$this->peopletag->tag);
|
||||
}
|
||||
|
||||
$current = common_current_user();
|
||||
if (!empty($current) && $current->id == $this->peopletag->tagger) {
|
||||
// TRANS: Title for public people tag timeline where the viewer is the tagger.
|
||||
// TRANS: %s is a people tag.
|
||||
return sprintf(_('Timeline for people tagged %s by you'),
|
||||
$this->peopletag->tag);
|
||||
}
|
||||
|
||||
// TRANS: Title for private people tag timeline.
|
||||
// TRANS: %1$s is a people tag, %2$s is the tagger's nickname.
|
||||
return sprintf(_('Timeline for people tagged %1$s by %2$s'),
|
||||
$this->peopletag->tag,
|
||||
$this->tagger->nickname
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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: Feed title.
|
||||
// TRANS: %s is tagger's 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: Feed title.
|
||||
// TRANS: %1$s is a people tag, %2$s is tagger's nickname.
|
||||
sprintf(_('Feed for people tagged %1$s by %2$s (Atom)'),
|
||||
$this->peopletag->tag, $this->tagger->nickname
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function showObjectNav()
|
||||
{
|
||||
$nav = new PeopletagGroupNav($this);
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
function showEmptyListMessage()
|
||||
{
|
||||
// TRANS: Empty list message for people tag timeline.
|
||||
// TRANS: %1$s is a people tag, %2$s is a tagger's nickname.
|
||||
$message = sprintf(_('This is the timeline for people tagged %1$s by %2$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) {
|
||||
// TRANS: Additional empty list message for people tag timeline for currently logged in user tagged tags.
|
||||
$message .= _('Try tagging more people.');
|
||||
}
|
||||
} else {
|
||||
// TRANS: Additional empty list message for people tag timeline.
|
||||
// TRANS: This message contains Markdown links in the form [description](link).
|
||||
$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) {
|
||||
// TRANS: Header on show profile tag page.
|
||||
// TRANS: %s is a people tag.
|
||||
$title = sprintf(_('People tagged %s by you'), $this->peopletag->tag);
|
||||
} else {
|
||||
// TRANS: Header on show profile tag page.
|
||||
// TRANS: %1$s is a people tag, %2$s is a tagger's nickname.
|
||||
$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) {
|
||||
// TRANS: Content of "People tagged x by a user" if there are no tagged users.
|
||||
$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'),
|
||||
// TRANS: Link for more "People tagged x by a user"
|
||||
// TRANS: if there are more than the mini list's maximum.
|
||||
_('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))) {
|
||||
// TRANS: Header for tag subscribers.
|
||||
$this->element('h2', null, _('Subscribers'));
|
||||
|
||||
$cnt = 0;
|
||||
|
||||
if (!empty($profile)) {
|
||||
$pml = new ProfileMiniList($profile, $this);
|
||||
$cnt = $pml->show();
|
||||
if ($cnt == 0) {
|
||||
// TRANS: Content of "People following tag x" if there are no subscribed users.
|
||||
$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'),
|
||||
// TRANS: Link for more "People following tag x"
|
||||
// TRANS: if there are more than the mini list's maximum.
|
||||
_('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);
|
||||
}
|
||||
}
|
151
actions/subscribepeopletag.php
Normal file
151
actions/subscribepeopletag.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?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()) {
|
||||
// TRANS: Client error displayed when trying to perform an action while not logged in.
|
||||
$this->clientError(_('You must be logged in to unsubscribe to a people tag.'));
|
||||
return false;
|
||||
}
|
||||
// Only allow POST requests
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
|
||||
// TRANS: Client error displayed when trying to use another method than POST.
|
||||
$this->clientError(_('This action only accepts POST requests.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// CSRF protection
|
||||
|
||||
$token = $this->trimmed('token');
|
||||
|
||||
if (!$token || $token != common_session_token()) {
|
||||
// TRANS: Client error displayed when the session token does not match or is not given.
|
||||
$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 {
|
||||
// TRANS: Client error displayed when trying to perform an action without providing an ID.
|
||||
$this->clientError(_('No ID given.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->peopletag || $this->peopletag->private) {
|
||||
// TRANS: Client error displayed trying to reference a non-existing people tag.
|
||||
$this->clientError(_('No such people tag.'), 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) {
|
||||
// TRANS: Server error displayed subscribing to a people tag fails.
|
||||
// TRANS: %1$s is a user nickname, %2$s is a people tag.
|
||||
$this->serverError(sprintf(_('Could not subscribe user %1$s to people tag %2$s.'),
|
||||
$cur->nickname, $this->peopletag->tag) . ' ' . $e->getMessage());
|
||||
}
|
||||
|
||||
if ($this->boolean('ajax')) {
|
||||
$this->startHTML('text/xml;charset=utf-8');
|
||||
$this->elementStart('head');
|
||||
// TRANS: Title of form to subscribe to a people tag.
|
||||
// TRANS: %1%s is a user nickname, %2$s is a people tag, %3$s is a tagger nickname.
|
||||
$this->element('title', null, sprintf(_('%1$s subscribed to people tag %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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,237 +0,0 @@
|
||||
<?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');
|
||||
|
||||
// @todo FIXME: documentation missing.
|
||||
class TagotherAction extends Action
|
||||
{
|
||||
var $profile = null;
|
||||
var $error = null;
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
if (!common_logged_in()) {
|
||||
// TRANS: Error message displayed when trying to perform an action that requires a logged in user.
|
||||
$this->clientError(_('Not logged in.'), 403);
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = $this->trimmed('id');
|
||||
if (!$id) {
|
||||
// TRANS: Client error displayed on user tag page when trying to add tags without providing a user ID.
|
||||
$this->clientError(_('No ID argument.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->profile = Profile::staticGet('id', $id);
|
||||
|
||||
if (!$this->profile) {
|
||||
// TRANS: Client error displayed on user tag page when trying to add tags providing a non-existing user ID.
|
||||
$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()
|
||||
{
|
||||
// TRANS: Title for "tag other users" page.
|
||||
// TRANS: %s is the user nickname.
|
||||
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');
|
||||
// TRANS: Header for user details on "tag other users" page.
|
||||
$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');
|
||||
// TRANS: Fieldset legend on "tag other users" page.
|
||||
$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');
|
||||
// TRANS: Field label for inputting tags on "tag other users" page.
|
||||
$this->input('tags', _('Tags'),
|
||||
($this->arg('tags')) ? $this->arg('tags') : implode(' ', Profile_tag::getTags($user->id, $this->profile->id)),
|
||||
// TRANS: Title for input field for inputting tags on "tag other users" page.
|
||||
_('Tags for this user (letters, numbers, -, ., and _), separated by commas or spaces.'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
// TRANS: Button text for saving tags for other users.
|
||||
$this->submit('save', _m('BUTTON','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()) {
|
||||
// TRANS: Client error displayed when the session token does not match or is not given.
|
||||
$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)) {
|
||||
// TRANS: Form validation error when entering an invalid tag.
|
||||
// TRANS: %s is the invalid 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)))
|
||||
{
|
||||
// TRANS: Client error on "tag other users" page when tagging a user is not possible because of missing mutual subscriptions.
|
||||
$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) {
|
||||
// TRANS: Client error on "tag other users" page when saving tags fails server side.
|
||||
$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');
|
||||
// TRANS: Title of "tag other users" page.
|
||||
$this->element('title', null, _m('TITLE','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,
|
||||
// TRANS: Page notice on "tag other users" page.
|
||||
_('Use this form to add tags to your subscribers or subscriptions.'));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
}
|
||||
}
|
264
actions/tagprofile.php
Normal file
264
actions/tagprofile.php
Normal file
@ -0,0 +1,264 @@
|
||||
<?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) {
|
||||
// TRANS: Client error displayed when referring to non-existing profile ID.
|
||||
$this->clientError(_('No profile with that ID.'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$current = common_current_user()->getProfile();
|
||||
if ($this->profile && !$current->canTag($this->profile)) {
|
||||
// TRANS: Client error displayed when trying to tag a user that cannot be tagged.
|
||||
$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) {
|
||||
// TRANS: Title for people tag form when not on a profile page.
|
||||
return _('Tag a profile');
|
||||
}
|
||||
// TRANS: Title for people tag form when on a profile page.
|
||||
// TRANS: %s is a profile nickname.
|
||||
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');
|
||||
// TRANS: Title for people tag form when an error has occurred.
|
||||
$this->element('title', null, _m('TITLE','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');
|
||||
// TRANS: Header in people tag form.
|
||||
$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');
|
||||
// TRANS: Fieldset legend for people tag form.
|
||||
$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);
|
||||
// TRANS: Field label on people tag form.
|
||||
$this->input('tags', _m('LABEL','Tags'),
|
||||
($this->arg('tags')) ? $this->arg('tags') : implode(' ', $tags),
|
||||
// TRANS: Field title on people tag form.
|
||||
_('Tags for this user (letters, numbers, -, ., and _), comma- or space- separated.'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
// TRANS: Button text to save people tags.
|
||||
$this->submit('save', _m('BUTTON','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()) {
|
||||
// TRANS: Client error displayed when the session token does not match or is not given.
|
||||
$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)) {
|
||||
// TRANS: Form validation error displayed if a given tag is invalid.
|
||||
// TRANS: %s is the invalid 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, _m('TITLE','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 {
|
||||
// TRANS: Success message if people tags are saved.
|
||||
$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,
|
||||
// TRANS: Page notice.
|
||||
_('Use this form to add tags to your subscribers or subscriptions.'));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
}
|
||||
}
|
147
actions/unsubscribepeopletag.php
Normal file
147
actions/unsubscribepeopletag.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?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()) {
|
||||
// TRANS: Client error displayed when trying to perform an action while not logged in.
|
||||
$this->clientError(_('You must be logged in to unsubscribe to a people tag.'));
|
||||
return false;
|
||||
}
|
||||
// Only allow POST requests
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
|
||||
// TRANS: Client error displayed when trying to use another method than POST.
|
||||
$this->clientError(_('This action only accepts POST requests.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// CSRF protection
|
||||
|
||||
$token = $this->trimmed('token');
|
||||
|
||||
if (!$token || $token != common_session_token()) {
|
||||
// TRANS: Client error displayed when the session token does not match or is not given.
|
||||
$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 {
|
||||
// TRANS: Client error displayed when trying to perform an action without providing an ID.
|
||||
$this->clientError(_('No ID given.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->peopletag || $this->peopletag->private) {
|
||||
// TRANS: Client error displayed trying to reference a non-existing people tag.
|
||||
$this->clientError(_('No such people tag.'), 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');
|
||||
// TRANS: Page title for form that allows unsubscribing from a people tag.
|
||||
// TRANS: %1$s is a nickname, %2$s is a people tag, %3$s is a tagger nickname.
|
||||
$this->element('title', null, sprintf(_('%1$s unsubscribed to people tag %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);
|
||||
}
|
||||
}
|
||||
}
|
@ -208,7 +208,7 @@ class Notice extends Memcached_DataObject
|
||||
|
||||
if (!$id) {
|
||||
// TRANS: Server exception. %s are the error details.
|
||||
throw new ServerException(sprintf(_('Database error inserting hashtag: %s'),
|
||||
throw new ServerException(sprintf(_('Database error inserting hashtag: %s.'),
|
||||
$last_error->message));
|
||||
return;
|
||||
}
|
||||
@ -545,6 +545,12 @@ class Notice extends Memcached_DataObject
|
||||
|
||||
$notice->saveKnownGroups($groups);
|
||||
|
||||
if (isset($peopletags)) {
|
||||
$notice->saveProfileTags($peopletags);
|
||||
} else {
|
||||
$notice->saveProfileTags();
|
||||
}
|
||||
|
||||
if (isset($urls)) {
|
||||
$notice->saveKnownUrls($urls);
|
||||
} else {
|
||||
@ -851,6 +857,7 @@ class Notice extends Memcached_DataObject
|
||||
}
|
||||
|
||||
$users = $this->getSubscribedUsers();
|
||||
$ptags = $this->getProfileTags();
|
||||
|
||||
// FIXME: kind of ignoring 'transitional'...
|
||||
// we'll probably stop supporting inboxless mode
|
||||
@ -874,11 +881,22 @@ class Notice extends Memcached_DataObject
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($ptags as $ptag) {
|
||||
$users = $ptag->getUserSubscribers();
|
||||
foreach ($users as $id) {
|
||||
if (!array_key_exists($id, $ni)) {
|
||||
$user = User::staticGet('id', $id);
|
||||
if (!$user->hasBlocked($profile)) {
|
||||
$ni[$id] = NOTICE_INBOX_SOURCE_PROFILE_TAG;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($recipients as $recipient) {
|
||||
if (!array_key_exists($recipient, $ni)) {
|
||||
$ni[$recipient] = NOTICE_INBOX_SOURCE_REPLY;
|
||||
}
|
||||
}
|
||||
|
||||
// Exclude any deleted, non-local, or blocking recipients.
|
||||
$profile = $this->getProfile();
|
||||
@ -897,6 +915,7 @@ class Notice extends Memcached_DataObject
|
||||
unset($ni[$id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Give plugins a chance to filter out...
|
||||
Event::handle('EndNoticeWhoGets', array($this, &$ni));
|
||||
@ -974,6 +993,39 @@ class Notice extends Memcached_DataObject
|
||||
return $ids;
|
||||
}
|
||||
|
||||
function getProfileTags()
|
||||
{
|
||||
// Don't save ptags for repeats, for now.
|
||||
|
||||
if (!empty($this->repeat_of)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// XXX: cache me
|
||||
|
||||
$ptags = array();
|
||||
|
||||
$ptagi = new Profile_tag_inbox();
|
||||
|
||||
$ptagi->selectAdd();
|
||||
$ptagi->selectAdd('profile_tag_id');
|
||||
|
||||
$ptagi->notice_id = $this->id;
|
||||
|
||||
if ($ptagi->find()) {
|
||||
while ($ptagi->fetch()) {
|
||||
$profile_list = Profile_list::staticGet('id', $ptagi->profile_tag_id);
|
||||
if ($profile_list) {
|
||||
$ptags[] = $profile_list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ptagi->free();
|
||||
|
||||
return $ptags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record this notice to the given group inboxes for delivery.
|
||||
* Overrides the regular parsing of !group markup.
|
||||
@ -1086,6 +1138,70 @@ class Notice extends Memcached_DataObject
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* record targets into profile_tag_inbox.
|
||||
* @return array of Profile_list objects
|
||||
*/
|
||||
function saveProfileTags($known=array())
|
||||
{
|
||||
// Don't save ptags for repeats, for now
|
||||
|
||||
if (!empty($this->repeat_of)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (is_array($known)) {
|
||||
$ptags = $known;
|
||||
} else {
|
||||
$ptags = array();
|
||||
}
|
||||
|
||||
$ptag = new Profile_tag();
|
||||
$ptag->tagged = $this->profile_id;
|
||||
|
||||
if($ptag->find()) {
|
||||
while($ptag->fetch()) {
|
||||
$plist = Profile_list::getByTaggerAndTag($ptag->tagger, $ptag->tag);
|
||||
$ptags[] = clone($plist);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($ptags as $target) {
|
||||
$this->addToProfileTagInbox($target);
|
||||
}
|
||||
|
||||
return $ptags;
|
||||
}
|
||||
|
||||
function addToProfileTagInbox($plist)
|
||||
{
|
||||
$ptagi = Profile_tag_inbox::pkeyGet(array('profile_tag_id' => $plist->id,
|
||||
'notice_id' => $this->id));
|
||||
|
||||
if (empty($ptagi)) {
|
||||
|
||||
$ptagi = new Profile_tag_inbox();
|
||||
|
||||
$ptagi->query('BEGIN');
|
||||
$ptagi->profile_tag_id = $plist->id;
|
||||
$ptagi->notice_id = $this->id;
|
||||
$ptagi->created = $this->created;
|
||||
|
||||
$result = $ptagi->insert();
|
||||
if (!$result) {
|
||||
common_log_db_error($ptagi, 'INSERT', __FILE__);
|
||||
// TRANS: Server exception thrown when saving profile_tag inbox fails.
|
||||
throw new ServerException(_('Problem saving profile_tag inbox.'));
|
||||
}
|
||||
|
||||
$ptagi->query('COMMIT');
|
||||
|
||||
self::blow('profile_tag:notice_ids:%d', $ptagi->profile_tag_id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save reply records indicating that this notice needs to be
|
||||
* delivered to the local users with the given URIs.
|
||||
|
@ -272,6 +272,183 @@ class Profile extends Memcached_DataObject
|
||||
return new ArrayWrapper($groups);
|
||||
}
|
||||
|
||||
function isTagged($peopletag)
|
||||
{
|
||||
$tag = Profile_tag::pkeyGet(array('tagger' => $peopletag->tagger,
|
||||
'tagged' => $this->id,
|
||||
'tag' => $peopletag->tag));
|
||||
return !empty($tag);
|
||||
}
|
||||
|
||||
function canTag($tagged)
|
||||
{
|
||||
if (empty($tagged)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($tagged->id == $this->id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$all = common_config('peopletag', 'allow_tagging', 'all');
|
||||
$local = common_config('peopletag', 'allow_tagging', 'local');
|
||||
$remote = common_config('peopletag', 'allow_tagging', 'remote');
|
||||
$subs = common_config('peopletag', 'allow_tagging', 'subs');
|
||||
|
||||
if ($all) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$tagged_user = $tagged->getUser();
|
||||
if (!empty($tagged_user)) {
|
||||
if ($local) {
|
||||
return true;
|
||||
}
|
||||
} else if ($subs) {
|
||||
return (Subscription::exists($this, $tagged) ||
|
||||
Subscription::exists($tagged, $this));
|
||||
} else if ($remote) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getOwnedTags($auth_user, $offset=0, $limit=null, $since_id=0, $max_id=0)
|
||||
{
|
||||
$tags = new Profile_list();
|
||||
$tags->tagger = $this->id;
|
||||
|
||||
if (($auth_user instanceof User || $auth_user instanceof Profile) &&
|
||||
$auth_user->id === $this->id) {
|
||||
// no condition, get both private and public tags
|
||||
} else {
|
||||
$tags->private = false;
|
||||
}
|
||||
|
||||
$tags->selectAdd('id as "cursor"');
|
||||
|
||||
if ($since_id>0) {
|
||||
$tags->whereAdd('id > '.$since_id);
|
||||
}
|
||||
|
||||
if ($max_id>0) {
|
||||
$tags->whereAdd('id <= '.$max_id);
|
||||
}
|
||||
|
||||
if($offset>=0 && !is_null($limit)) {
|
||||
$tags->limit($offset, $limit);
|
||||
}
|
||||
|
||||
$tags->orderBy('id DESC');
|
||||
$tags->find();
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
function getOtherTags($auth_user=null, $offset=0, $limit=null, $since_id=0, $max_id=0)
|
||||
{
|
||||
$lists = new Profile_list();
|
||||
|
||||
$tags = new Profile_tag();
|
||||
$tags->tagged = $this->id;
|
||||
|
||||
$lists->joinAdd($tags);
|
||||
#@fixme: postgres (round(date_part('epoch', my_date)))
|
||||
$lists->selectAdd('unix_timestamp(profile_tag.modified) as "cursor"');
|
||||
|
||||
if ($auth_user instanceof User || $auth_user instanceof Profile) {
|
||||
$lists->whereAdd('( ( profile_list.private = false ) ' .
|
||||
'OR ( profile_list.tagger = ' . $auth_user->id . ' AND ' .
|
||||
'profile_list.private = true ) )');
|
||||
} else {
|
||||
$lists->private = false;
|
||||
}
|
||||
|
||||
if ($since_id>0) {
|
||||
$lists->whereAdd('cursor > '.$since_id);
|
||||
}
|
||||
|
||||
if ($max_id>0) {
|
||||
$lists->whereAdd('cursor <= '.$max_id);
|
||||
}
|
||||
|
||||
if($offset>=0 && !is_null($limit)) {
|
||||
$lists->limit($offset, $limit);
|
||||
}
|
||||
|
||||
$lists->orderBy('profile_tag.modified DESC');
|
||||
$lists->find();
|
||||
|
||||
return $lists;
|
||||
}
|
||||
|
||||
function getPrivateTags($offset=0, $limit=null, $since_id=0, $max_id=0)
|
||||
{
|
||||
$tags = new Profile_list();
|
||||
$tags->private = true;
|
||||
$tags->tagger = $this->id;
|
||||
|
||||
if ($since_id>0) {
|
||||
$tags->whereAdd('id > '.$since_id);
|
||||
}
|
||||
|
||||
if ($max_id>0) {
|
||||
$tags->whereAdd('id <= '.$max_id);
|
||||
}
|
||||
|
||||
if($offset>=0 && !is_null($limit)) {
|
||||
$tags->limit($offset, $limit);
|
||||
}
|
||||
|
||||
$tags->orderBy('id DESC');
|
||||
$tags->find();
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
function hasLocalTags()
|
||||
{
|
||||
$tags = new Profile_tag();
|
||||
|
||||
$tags->joinAdd(array('tagger', 'user:id'));
|
||||
$tags->whereAdd('tagged = '.$this->id);
|
||||
$tags->whereAdd('tagger != '.$this->id);
|
||||
|
||||
$tags->limit(0, 1);
|
||||
$tags->fetch();
|
||||
|
||||
return ($tags->N == 0) ? false : true;
|
||||
}
|
||||
|
||||
function getTagSubscriptions($offset=0, $limit=null, $since_id=0, $max_id=0)
|
||||
{
|
||||
$lists = new Profile_list();
|
||||
$subs = new Profile_tag_subscription();
|
||||
|
||||
$lists->joinAdd($subs);
|
||||
#@fixme: postgres (round(date_part('epoch', my_date)))
|
||||
$lists->selectAdd('unix_timestamp(profile_tag_subscription.created) as "cursor"');
|
||||
|
||||
$lists->whereAdd('profile_tag_subscription.profile_id = '.$this->id);
|
||||
|
||||
if ($since_id>0) {
|
||||
$lists->whereAdd('cursor > '.$since_id);
|
||||
}
|
||||
|
||||
if ($max_id>0) {
|
||||
$lists->whereAdd('cursor <= '.$max_id);
|
||||
}
|
||||
|
||||
if($offset>=0 && !is_null($limit)) {
|
||||
$lists->limit($offset, $limit);
|
||||
}
|
||||
|
||||
$lists->orderBy('"cursor" DESC');
|
||||
$lists->find();
|
||||
|
||||
return $lists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to join the given group.
|
||||
* May throw exceptions on failure.
|
||||
@ -358,6 +535,31 @@ class Profile extends Memcached_DataObject
|
||||
return new ArrayWrapper($profiles);
|
||||
}
|
||||
|
||||
function getTaggedSubscribers($tag)
|
||||
{
|
||||
$qry =
|
||||
'SELECT profile.* ' .
|
||||
'FROM profile JOIN (subscription, profile_tag, profile_list) ' .
|
||||
'ON profile.id = subscription.subscriber ' .
|
||||
'AND profile.id = profile_tag.tagged ' .
|
||||
'AND profile_tag.tagger = profile_list.tagger AND profile_tag.tag = profile_list.tag ' .
|
||||
'WHERE subscription.subscribed = %d ' .
|
||||
'AND subscription.subscribed != subscription.subscriber ' .
|
||||
'AND profile_tag.tagger = %d AND profile_tag.tag = "%s" ' .
|
||||
'AND profile_list.private = false ' .
|
||||
'ORDER BY subscription.created DESC';
|
||||
|
||||
$profile = new Profile();
|
||||
$tagged = array();
|
||||
|
||||
$cnt = $profile->query(sprintf($qry, $this->id, $this->id, $tag));
|
||||
|
||||
while ($profile->fetch()) {
|
||||
$tagged[] = clone($profile);
|
||||
}
|
||||
return $tagged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pending subscribers, who have not yet been approved.
|
||||
*
|
||||
|
931
classes/Profile_list.php
Normal file
931
classes/Profile_list.php
Normal file
@ -0,0 +1,931 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
*
|
||||
* 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 Notices
|
||||
* @package StatusNet
|
||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
||||
* @license GNU Affero General Public License http://www.gnu.org/licenses/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Table Definition for profile_list
|
||||
*/
|
||||
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||
|
||||
class Profile_list extends Memcached_DataObject
|
||||
{
|
||||
###START_AUTOCODE
|
||||
/* the code below is auto generated do not remove the above tag */
|
||||
|
||||
public $__table = 'profile_list'; // table name
|
||||
public $id; // int(4) primary_key not_null
|
||||
public $tagger; // int(4)
|
||||
public $tag; // varchar(64)
|
||||
public $description; // text
|
||||
public $private; // tinyint(1)
|
||||
public $created; // datetime not_null default_0000-00-00%2000%3A00%3A00
|
||||
public $modified; // timestamp not_null default_CURRENT_TIMESTAMP
|
||||
public $uri; // varchar(255) unique_key
|
||||
public $mainpage; // varchar(255)
|
||||
public $tagged_count; // smallint
|
||||
public $subscriber_count; // smallint
|
||||
|
||||
/* Static get */
|
||||
function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('Profile_list',$k,$v); }
|
||||
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
|
||||
/**
|
||||
* return a profile_list record, given its tag and tagger.
|
||||
*
|
||||
* @param array $kv ideally array('tag' => $tag, 'tagger' => $tagger)
|
||||
*
|
||||
* @return Profile_list a Profile_list object with the given tag and tagger.
|
||||
*/
|
||||
|
||||
function pkeyGet($kv)
|
||||
{
|
||||
return Memcached_DataObject::pkeyGet('Profile_list', $kv);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the tagger of this profile_list object
|
||||
*
|
||||
* @return Profile the tagger
|
||||
*/
|
||||
|
||||
function getTagger()
|
||||
{
|
||||
return Profile::staticGet('id', $this->tagger);
|
||||
}
|
||||
|
||||
/**
|
||||
* return a string to identify this
|
||||
* profile_list in the user interface etc.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
|
||||
function getBestName()
|
||||
{
|
||||
return $this->tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a uri string for this profile_list
|
||||
*
|
||||
* @return String uri
|
||||
*/
|
||||
|
||||
function getUri()
|
||||
{
|
||||
$uri = null;
|
||||
if (Event::handle('StartProfiletagGetUri', array($this, &$uri))) {
|
||||
if (!empty($this->uri)) {
|
||||
$uri = $this->uri;
|
||||
} else {
|
||||
$uri = common_local_url('profiletagbyid',
|
||||
array('id' => $this->id, 'tagger_id' => $this->tagger));
|
||||
}
|
||||
}
|
||||
Event::handle('EndProfiletagGetUri', array($this, &$uri));
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a url to the homepage of this item
|
||||
*
|
||||
* @return String home url
|
||||
*/
|
||||
|
||||
function homeUrl()
|
||||
{
|
||||
$url = null;
|
||||
if (Event::handle('StartUserPeopletagHomeUrl', array($this, &$url))) {
|
||||
// normally stored in mainpage, but older ones may be null
|
||||
if (!empty($this->mainpage)) {
|
||||
$url = $this->mainpage;
|
||||
} else {
|
||||
$url = common_local_url('showprofiletag',
|
||||
array('tagger' => $this->getTagger()->nickname,
|
||||
'tag' => $this->tag));
|
||||
}
|
||||
}
|
||||
Event::handle('EndUserPeopletagHomeUrl', array($this, &$url));
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* return an immutable url for this object
|
||||
*
|
||||
* @return String permalink
|
||||
*/
|
||||
|
||||
function permalink()
|
||||
{
|
||||
$url = null;
|
||||
if (Event::handle('StartProfiletagPermalink', array($this, &$url))) {
|
||||
$url = common_local_url('profiletagbyid',
|
||||
array('id' => $this->id));
|
||||
}
|
||||
Event::handle('EndProfiletagPermalink', array($this, &$url));
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query notices by users associated with this tag,
|
||||
* but first check the cache before hitting the DB.
|
||||
*
|
||||
* @param integer $offset offset
|
||||
* @param integer $limit maximum no of results
|
||||
* @param integer $since_id=null since this id
|
||||
* @param integer $max_id=null maximum id in result
|
||||
*
|
||||
* @return Notice the query
|
||||
*/
|
||||
|
||||
function getNotices($offset, $limit, $since_id=null, $max_id=null)
|
||||
{
|
||||
$stream = new PeopletagNoticeStream($this);
|
||||
|
||||
return $stream->getNotices($offset, $limit, $since_id, $max_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query notices by users associated with this tag from the database.
|
||||
*
|
||||
* @param integer $offset offset
|
||||
* @param integer $limit maximum no of results
|
||||
* @param integer $since_id=null since this id
|
||||
* @param integer $max_id=null maximum id in result
|
||||
*
|
||||
* @return array array of notice ids.
|
||||
*/
|
||||
|
||||
function _streamDirect($offset, $limit, $since_id, $max_id)
|
||||
{
|
||||
$inbox = new Profile_tag_inbox();
|
||||
|
||||
$inbox->profile_tag_id = $this->id;
|
||||
|
||||
$inbox->selectAdd();
|
||||
$inbox->selectAdd('notice_id');
|
||||
|
||||
if ($since_id != 0) {
|
||||
$inbox->whereAdd('notice_id > ' . $since_id);
|
||||
}
|
||||
|
||||
if ($max_id != 0) {
|
||||
$inbox->whereAdd('notice_id <= ' . $max_id);
|
||||
}
|
||||
|
||||
$inbox->orderBy('notice_id DESC');
|
||||
|
||||
if (!is_null($offset)) {
|
||||
$inbox->limit($offset, $limit);
|
||||
}
|
||||
|
||||
$ids = array();
|
||||
|
||||
if ($inbox->find()) {
|
||||
while ($inbox->fetch()) {
|
||||
$ids[] = $inbox->notice_id;
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subscribers (local and remote) to this people tag
|
||||
* Order by reverse chronology
|
||||
*
|
||||
* @param integer $offset offset
|
||||
* @param integer $limit maximum no of results
|
||||
* @param integer $since_id=null since unix timestamp
|
||||
* @param integer $upto=null maximum unix timestamp when subscription was made
|
||||
*
|
||||
* @return Profile results
|
||||
*/
|
||||
|
||||
function getSubscribers($offset=0, $limit=null, $since=0, $upto=0)
|
||||
{
|
||||
$subs = new Profile();
|
||||
$sub = new Profile_tag_subscription();
|
||||
$sub->profile_tag_id = $this->id;
|
||||
|
||||
$subs->joinAdd($sub);
|
||||
$subs->selectAdd('unix_timestamp(profile_tag_subscription.' .
|
||||
'created) as "cursor"');
|
||||
|
||||
if ($since != 0) {
|
||||
$subs->whereAdd('cursor > ' . $since);
|
||||
}
|
||||
|
||||
if ($upto != 0) {
|
||||
$subs->whereAdd('cursor <= ' . $upto);
|
||||
}
|
||||
|
||||
if ($limit != null) {
|
||||
$subs->limit($offset, $limit);
|
||||
}
|
||||
|
||||
$subs->orderBy('profile_tag_subscription.created DESC');
|
||||
$subs->find();
|
||||
|
||||
return $subs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all and only local subscribers to this people tag
|
||||
* used for distributing notices to user inboxes.
|
||||
*
|
||||
* @return array ids of users
|
||||
*/
|
||||
|
||||
function getUserSubscribers()
|
||||
{
|
||||
// XXX: cache this
|
||||
|
||||
$user = new User();
|
||||
if(common_config('db','quote_identifiers'))
|
||||
$user_table = '"user"';
|
||||
else $user_table = 'user';
|
||||
|
||||
$qry =
|
||||
'SELECT id ' .
|
||||
'FROM '. $user_table .' JOIN profile_tag_subscription '.
|
||||
'ON '. $user_table .'.id = profile_tag_subscription.profile_id ' .
|
||||
'WHERE profile_tag_subscription.profile_tag_id = %d ';
|
||||
|
||||
$user->query(sprintf($qry, $this->id));
|
||||
|
||||
$ids = array();
|
||||
|
||||
while ($user->fetch()) {
|
||||
$ids[] = $user->id;
|
||||
}
|
||||
|
||||
$user->free();
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a given profile has
|
||||
* subscribed to this people tag's timeline
|
||||
*
|
||||
* @param mixed $id User or Profile object or integer id
|
||||
*
|
||||
* @return boolean subscription status
|
||||
*/
|
||||
|
||||
function hasSubscriber($id)
|
||||
{
|
||||
if (!is_numeric($id)) {
|
||||
$id = $id->id;
|
||||
}
|
||||
|
||||
$sub = Profile_tag_subscription::pkeyGet(array('profile_tag_id' => $this->id,
|
||||
'profile_id' => $id));
|
||||
return !empty($sub);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get profiles tagged with this people tag,
|
||||
* include modified timestamp as a "cursor" field
|
||||
* order by descending order of modified time
|
||||
*
|
||||
* @param integer $offset offset
|
||||
* @param integer $limit maximum no of results
|
||||
* @param integer $since_id=null since unix timestamp
|
||||
* @param integer $upto=null maximum unix timestamp when subscription was made
|
||||
*
|
||||
* @return Profile results
|
||||
*/
|
||||
|
||||
function getTagged($offset=0, $limit=null, $since=0, $upto=0)
|
||||
{
|
||||
$tagged = new Profile();
|
||||
$tagged->joinAdd(array('id', 'profile_tag:tagged'));
|
||||
|
||||
#@fixme: postgres
|
||||
$tagged->selectAdd('unix_timestamp(profile_tag.modified) as "cursor"');
|
||||
$tagged->whereAdd('profile_tag.tagger = '.$this->tagger);
|
||||
$tagged->whereAdd("profile_tag.tag = '{$this->tag}'");
|
||||
|
||||
if ($since != 0) {
|
||||
$tagged->whereAdd('cursor > ' . $since);
|
||||
}
|
||||
|
||||
if ($upto != 0) {
|
||||
$tagged->whereAdd('cursor <= ' . $upto);
|
||||
}
|
||||
|
||||
if ($limit != null) {
|
||||
$tagged->limit($offset, $limit);
|
||||
}
|
||||
|
||||
$tagged->orderBy('profile_tag.modified DESC');
|
||||
$tagged->find();
|
||||
|
||||
return $tagged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gracefully delete one or many people tags
|
||||
* along with their members and subscriptions data
|
||||
*
|
||||
* @return boolean success
|
||||
*/
|
||||
|
||||
function delete()
|
||||
{
|
||||
// force delete one item at a time.
|
||||
if (empty($this->id)) {
|
||||
$this->find();
|
||||
while ($this->fetch()) {
|
||||
$this->delete();
|
||||
}
|
||||
}
|
||||
|
||||
Profile_tag::cleanup($this);
|
||||
Profile_tag_subscription::cleanup($this);
|
||||
|
||||
return parent::delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a people tag gracefully
|
||||
* also change "tag" fields in profile_tag table
|
||||
*
|
||||
* @param Profile_list $orig Object's original form
|
||||
*
|
||||
* @return boolean success
|
||||
*/
|
||||
|
||||
function update($orig=null)
|
||||
{
|
||||
$result = true;
|
||||
|
||||
if (!is_object($orig) && !$orig instanceof Profile_list) {
|
||||
parent::update($orig);
|
||||
}
|
||||
|
||||
// if original tag was different
|
||||
// check to see if the new tag already exists
|
||||
// if not, rename the tag correctly
|
||||
if($orig->tag != $this->tag || $orig->tagger != $this->tagger) {
|
||||
$existing = Profile_list::getByTaggerAndTag($this->tagger, $this->tag);
|
||||
if(!empty($existing)) {
|
||||
// TRANS: Server exception.
|
||||
throw new ServerException(_('The tag you are trying to rename ' .
|
||||
'to already exists.'));
|
||||
}
|
||||
// move the tag
|
||||
// XXX: allow OStatus plugin to send out profile tag
|
||||
$result = Profile_tag::moveTag($orig, $this);
|
||||
}
|
||||
parent::update($orig);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* return an xml string representing this people tag
|
||||
* as the author of an atom feed
|
||||
*
|
||||
* @return string atom author element
|
||||
*/
|
||||
|
||||
function asAtomAuthor()
|
||||
{
|
||||
$xs = new XMLStringer(true);
|
||||
|
||||
$tagger = $this->getTagger();
|
||||
$xs->elementStart('author');
|
||||
$xs->element('name', null, '@' . $tagger->nickname . '/' . $this->tag);
|
||||
$xs->element('uri', null, $this->permalink());
|
||||
$xs->elementEnd('author');
|
||||
|
||||
return $xs->getString();
|
||||
}
|
||||
|
||||
/**
|
||||
* return an xml string to represent this people tag
|
||||
* as the subject of an activitystreams feed.
|
||||
*
|
||||
* @return string activitystreams subject
|
||||
*/
|
||||
|
||||
function asActivitySubject()
|
||||
{
|
||||
return $this->asActivityNoun('subject');
|
||||
}
|
||||
|
||||
/**
|
||||
* return an xml string to represent this people tag
|
||||
* as a noun in an activitystreams feed.
|
||||
*
|
||||
* @param string $element the xml tag
|
||||
*
|
||||
* @return string activitystreams noun
|
||||
*/
|
||||
|
||||
function asActivityNoun($element)
|
||||
{
|
||||
$noun = ActivityObject::fromPeopletag($this);
|
||||
return $noun->asString('activity:' . $element);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the cached number of profiles tagged with this
|
||||
* people tag, re-count if the argument is true.
|
||||
*
|
||||
* @param boolean $recount whether to ignore cache
|
||||
*
|
||||
* @return integer count
|
||||
*/
|
||||
|
||||
function taggedCount($recount=false)
|
||||
{
|
||||
if (!$recount) {
|
||||
return $this->tagged_count;
|
||||
}
|
||||
|
||||
$tags = new Profile_tag();
|
||||
$tags->tag = $this->tag;
|
||||
$tags->tagger = $this->tagger;
|
||||
$orig = clone($this);
|
||||
$this->tagged_count = (int) $tags->count('distinct tagged');
|
||||
$this->update($orig);
|
||||
|
||||
return $this->tagged_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the cached number of profiles subscribed to this
|
||||
* people tag, re-count if the argument is true.
|
||||
*
|
||||
* @param boolean $recount whether to ignore cache
|
||||
*
|
||||
* @return integer count
|
||||
*/
|
||||
|
||||
function subscriberCount($recount=false)
|
||||
{
|
||||
if ($recount) {
|
||||
return $this->subscriber_count;
|
||||
}
|
||||
|
||||
$sub = new Profile_tag_subscription();
|
||||
$sub->profile_tag_id = $this->id;
|
||||
$orig = clone($this);
|
||||
$this->subscriber_count = (int) $sub->count('distinct profile_id');
|
||||
$this->update($orig);
|
||||
|
||||
return $this->subscriber_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the Profile_list object by the
|
||||
* given tagger and with given tag
|
||||
*
|
||||
* @param integer $tagger the id of the creator profile
|
||||
* @param integer $tag the tag
|
||||
*
|
||||
* @return integer count
|
||||
*/
|
||||
|
||||
static function getByTaggerAndTag($tagger, $tag)
|
||||
{
|
||||
$ptag = Profile_list::pkeyGet(array('tagger' => $tagger, 'tag' => $tag));
|
||||
return $ptag;
|
||||
}
|
||||
|
||||
/**
|
||||
* create a profile_list record for a tag, tagger pair
|
||||
* if it doesn't exist, return it.
|
||||
*
|
||||
* @param integer $tagger the tagger
|
||||
* @param string $tag the tag
|
||||
* @param string $description description
|
||||
* @param boolean $private protected or not
|
||||
*
|
||||
* @return Profile_list the people tag object
|
||||
*/
|
||||
|
||||
static function ensureTag($tagger, $tag, $description=null, $private=false)
|
||||
{
|
||||
$ptag = Profile_list::getByTaggerAndTag($tagger, $tag);
|
||||
|
||||
if(empty($ptag->id)) {
|
||||
$args = array(
|
||||
'tag' => $tag,
|
||||
'tagger' => $tagger,
|
||||
'description' => $description,
|
||||
'private' => $private
|
||||
);
|
||||
|
||||
$new_tag = Profile_list::saveNew($args);
|
||||
|
||||
return $new_tag;
|
||||
}
|
||||
return $ptag;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the maximum number of characters
|
||||
* that can be used in the description of
|
||||
* a people tag.
|
||||
*
|
||||
* determined by $config['peopletag']['desclimit']
|
||||
* if not set, falls back to $config['site']['textlimit']
|
||||
*
|
||||
* @return integer maximum number of characters
|
||||
*/
|
||||
|
||||
static function maxDescription()
|
||||
{
|
||||
$desclimit = common_config('peopletag', 'desclimit');
|
||||
// null => use global limit (distinct from 0!)
|
||||
if (is_null($desclimit)) {
|
||||
$desclimit = common_config('site', 'textlimit');
|
||||
}
|
||||
return $desclimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the length of given text exceeds
|
||||
* character limit.
|
||||
*
|
||||
* @param string $desc the description
|
||||
*
|
||||
* @return boolean is the descripition too long?
|
||||
*/
|
||||
|
||||
static function descriptionTooLong($desc)
|
||||
{
|
||||
$desclimit = self::maxDescription();
|
||||
return ($desclimit > 0 && !empty($desc) && (mb_strlen($desc) > $desclimit));
|
||||
}
|
||||
|
||||
/**
|
||||
* save a new people tag, this should be always used
|
||||
* since it makes uri, homeurl, created and modified
|
||||
* timestamps and performs checks.
|
||||
*
|
||||
* @param array $fields an array with fields and their values
|
||||
*
|
||||
* @return mixed Profile_list on success, false on fail
|
||||
*/
|
||||
static function saveNew($fields) {
|
||||
extract($fields);
|
||||
|
||||
$ptag = new Profile_list();
|
||||
|
||||
$ptag->query('BEGIN');
|
||||
|
||||
if (empty($tagger)) {
|
||||
// TRANS: Server exception saving new tag without having a tagger specified.
|
||||
throw new Exception(_('No tagger specified.'));
|
||||
}
|
||||
|
||||
if (empty($tag)) {
|
||||
// TRANS: Server exception saving new tag without having a tag specified.
|
||||
throw new Exception(_('No tag specified.'));
|
||||
}
|
||||
|
||||
if (empty($mainpage)) {
|
||||
$mainpage = null;
|
||||
}
|
||||
|
||||
if (empty($uri)) {
|
||||
// fill in later...
|
||||
$uri = null;
|
||||
}
|
||||
|
||||
if (empty($mainpage)) {
|
||||
$mainpage = null;
|
||||
}
|
||||
|
||||
if (empty($description)) {
|
||||
$description = null;
|
||||
}
|
||||
|
||||
if (empty($private)) {
|
||||
$private = false;
|
||||
}
|
||||
|
||||
$ptag->tagger = $tagger;
|
||||
$ptag->tag = $tag;
|
||||
$ptag->description = $description;
|
||||
$ptag->private = $private;
|
||||
$ptag->uri = $uri;
|
||||
$ptag->mainpage = $mainpage;
|
||||
$ptag->created = common_sql_now();
|
||||
$ptag->modified = common_sql_now();
|
||||
|
||||
$result = $ptag->insert();
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($ptag, 'INSERT', __FILE__);
|
||||
// TRANS: Server exception saving new tag.
|
||||
throw new ServerException(_('Could not create profile tag.'));
|
||||
}
|
||||
|
||||
if (!isset($uri) || empty($uri)) {
|
||||
$orig = clone($ptag);
|
||||
$ptag->uri = common_local_url('profiletagbyid', array('id' => $ptag->id, 'tagger_id' => $ptag->tagger));
|
||||
$result = $ptag->update($orig);
|
||||
if (!$result) {
|
||||
common_log_db_error($ptag, 'UPDATE', __FILE__);
|
||||
// TRANS: Server exception saving new tag.
|
||||
throw new ServerException(_('Could not set profile tag URI.'));
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($mainpage) || empty($mainpage)) {
|
||||
$orig = clone($ptag);
|
||||
$user = User::staticGet('id', $ptag->tagger);
|
||||
if(!empty($user)) {
|
||||
$ptag->mainpage = common_local_url('showprofiletag', array('tag' => $ptag->tag, 'tagger' => $user->nickname));
|
||||
} else {
|
||||
$ptag->mainpage = $uri; // assume this is a remote peopletag and the uri works
|
||||
}
|
||||
|
||||
$result = $ptag->update($orig);
|
||||
if (!$result) {
|
||||
common_log_db_error($ptag, 'UPDATE', __FILE__);
|
||||
// TRANS: Server exception saving new tag.
|
||||
throw new ServerException(_('Could not set profile tag mainpage.'));
|
||||
}
|
||||
}
|
||||
return $ptag;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all items at given cursor position for api
|
||||
*
|
||||
* @param callback $fn a function that takes the following arguments in order:
|
||||
* $offset, $limit, $since_id, $max_id
|
||||
* and returns a Profile_list object after making the DB query
|
||||
* @param array $args arguments required for $fn
|
||||
* @param integer $cursor the cursor
|
||||
* @param integer $count max. number of results
|
||||
*
|
||||
* Algorithm:
|
||||
* - if cursor is 0, return empty list
|
||||
* - if cursor is -1, get first 21 items, next_cursor = 20th prev_cursor = 0
|
||||
* - if cursor is +ve get 22 consecutive items before starting at cursor
|
||||
* - return items[1..20] if items[0] == cursor else return items[0..21]
|
||||
* - prev_cursor = items[1]
|
||||
* - next_cursor = id of the last item being returned
|
||||
*
|
||||
* - if cursor is -ve get 22 consecutive items after cursor starting at cursor
|
||||
* - return items[1..20]
|
||||
*
|
||||
* @returns array (array (mixed items), int next_cursor, int previous_cursor)
|
||||
*/
|
||||
|
||||
// XXX: This should be in Memcached_DataObject... eventually.
|
||||
|
||||
static function getAtCursor($fn, $args, $cursor, $count=20)
|
||||
{
|
||||
$items = array();
|
||||
|
||||
$since_id = 0;
|
||||
$max_id = 0;
|
||||
$next_cursor = 0;
|
||||
$prev_cursor = 0;
|
||||
|
||||
if($cursor > 0) {
|
||||
// if cursor is +ve fetch $count+2 items before cursor starting at cursor
|
||||
$max_id = $cursor;
|
||||
$fn_args = array_merge($args, array(0, $count+2, 0, $max_id));
|
||||
$list = call_user_func_array($fn, $fn_args);
|
||||
while($list->fetch()) {
|
||||
$items[] = clone($list);
|
||||
}
|
||||
|
||||
if ((isset($items[0]->cursor) && $items[0]->cursor == $cursor) ||
|
||||
$items[0]->id == $cursor) {
|
||||
array_shift($items);
|
||||
$prev_cursor = isset($items[0]->cursor) ?
|
||||
-$items[0]->cursor : -$items[0]->id;
|
||||
} else {
|
||||
if (count($items) > $count+1) {
|
||||
array_shift($items);
|
||||
}
|
||||
// this means the cursor item has been deleted, check to see if there are more
|
||||
$fn_args = array_merge($args, array(0, 1, $cursor));
|
||||
$more = call_user_func($fn, $fn_args);
|
||||
if (!$more->fetch() || empty($more)) {
|
||||
// no more items.
|
||||
$prev_cursor = 0;
|
||||
} else {
|
||||
$prev_cursor = isset($items[0]->cursor) ?
|
||||
-$items[0]->cursor : -$items[0]->id;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($items)==$count+1) {
|
||||
// this means there is a next page.
|
||||
$next = array_pop($items);
|
||||
$next_cursor = isset($next->cursor) ?
|
||||
$items[$count-1]->cursor : $items[$count-1]->id;
|
||||
}
|
||||
|
||||
} else if($cursor < -1) {
|
||||
// if cursor is -ve fetch $count+2 items created after -$cursor-1
|
||||
$cursor = abs($cursor);
|
||||
$since_id = $cursor-1;
|
||||
|
||||
$fn_args = array_merge($args, array(0, $count+2, $since_id));
|
||||
$list = call_user_func_array($fn, $fn_args);
|
||||
while($list->fetch()) {
|
||||
$items[] = clone($list);
|
||||
}
|
||||
|
||||
$end = count($items)-1;
|
||||
if ((isset($items[$end]->cursor) && $items[$end]->cursor == $cursor) ||
|
||||
$items[$end]->id == $cursor) {
|
||||
array_pop($items);
|
||||
$next_cursor = isset($items[$end-1]->cursor) ?
|
||||
$items[$end-1]->cursor : $items[$end-1]->id;
|
||||
} else {
|
||||
$next_cursor = isset($items[$end]->cursor) ?
|
||||
$items[$end]->cursor : $items[$end]->id;
|
||||
if ($end > $count) array_pop($items); // excess item.
|
||||
|
||||
// check if there are more items for next page
|
||||
$fn_args = array_merge($args, array(0, 1, 0, $cursor));
|
||||
$more = call_user_func_array($fn, $fn_args);
|
||||
if (!$more->fetch() || empty($more)) {
|
||||
$next_cursor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($items) == $count+1) {
|
||||
// this means there is a previous page.
|
||||
$prev = array_shift($items);
|
||||
$prev_cursor = isset($prev->cursor) ?
|
||||
-$items[0]->cursor : -$items[0]->id;
|
||||
}
|
||||
} else if($cursor == -1) {
|
||||
$fn_args = array_merge($args, array(0, $count+1));
|
||||
$list = call_user_func_array($fn, $fn_args);
|
||||
|
||||
while($list->fetch()) {
|
||||
$items[] = clone($list);
|
||||
}
|
||||
|
||||
if (count($items)==$count+1) {
|
||||
$next = array_pop($items);
|
||||
if(isset($next->cursor)) {
|
||||
$next_cursor = $items[$count-1]->cursor;
|
||||
} else {
|
||||
$next_cursor = $items[$count-1]->id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return array($items, $next_cursor, $prev_cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* save a collection of people tags into the cache
|
||||
*
|
||||
* @param string $ckey cache key
|
||||
* @param Profile_list &$tag the results to store
|
||||
* @param integer $offset offset for slicing results
|
||||
* @param integer $limit maximum number of results
|
||||
*
|
||||
* @return boolean success
|
||||
*/
|
||||
|
||||
static function setCache($ckey, &$tag, $offset=0, $limit=null) {
|
||||
$cache = Cache::instance();
|
||||
if (empty($cache)) {
|
||||
return false;
|
||||
}
|
||||
$str = '';
|
||||
$tags = array();
|
||||
while ($tag->fetch()) {
|
||||
$str .= $tag->tagger . ':' . $tag->tag . ';';
|
||||
$tags[] = clone($tag);
|
||||
}
|
||||
$str = substr($str, 0, -1);
|
||||
if ($offset>=0 && !is_null($limit)) {
|
||||
$tags = array_slice($tags, $offset, $limit);
|
||||
}
|
||||
|
||||
$tag = new ArrayWrapper($tags);
|
||||
|
||||
return self::cacheSet($ckey, $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* get people tags from the cache
|
||||
*
|
||||
* @param string $ckey cache key
|
||||
* @param integer $offset offset for slicing
|
||||
* @param integer $limit limit
|
||||
*
|
||||
* @return Profile_list results
|
||||
*/
|
||||
|
||||
static function getCached($ckey, $offset=0, $limit=null) {
|
||||
|
||||
$keys_str = self::cacheGet($ckey);
|
||||
if ($keys_str === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pairs = explode(';', $keys_str);
|
||||
$keys = array();
|
||||
foreach ($pairs as $pair) {
|
||||
$keys[] = explode(':', $pair);
|
||||
}
|
||||
|
||||
if ($offset>=0 && !is_null($limit)) {
|
||||
$keys = array_slice($keys, $offset, $limit);
|
||||
}
|
||||
return self::getByKeys($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* get Profile_list objects from the database
|
||||
* given their (tag, tagger) key pairs.
|
||||
*
|
||||
* @param array $keys array of array(tagger, tag)
|
||||
*
|
||||
* @return Profile_list results
|
||||
*/
|
||||
|
||||
static function getByKeys($keys) {
|
||||
$cache = Cache::instance();
|
||||
|
||||
if (!empty($cache)) {
|
||||
$tags = array();
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$t = Profile_list::getByTaggerAndTag($key[0], $key[1]);
|
||||
if (!empty($t)) {
|
||||
$tags[] = $t;
|
||||
}
|
||||
}
|
||||
return new ArrayWrapper($tags);
|
||||
} else {
|
||||
$tag = new Profile_list();
|
||||
if (empty($keys)) {
|
||||
//if no IDs requested, just return the tag object
|
||||
return $tag;
|
||||
}
|
||||
|
||||
$pairs = array();
|
||||
foreach ($keys as $key) {
|
||||
$pairs[] = '(' . $key[0] . ', "' . $key[1] . '")';
|
||||
}
|
||||
|
||||
$tag->whereAdd('(tagger, tag) in (' . implode(', ', $pairs) . ')');
|
||||
|
||||
$tag->find();
|
||||
|
||||
$temp = array();
|
||||
|
||||
while ($tag->fetch()) {
|
||||
$temp[$tag->tagger.'-'.$tag->tag] = clone($tag);
|
||||
}
|
||||
|
||||
$wrapped = array();
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$id = $key[0].'-'.$key[1];
|
||||
if (array_key_exists($id, $temp)) {
|
||||
$wrapped[] = $temp[$id];
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayWrapper($wrapped);
|
||||
}
|
||||
}
|
||||
}
|
@ -22,31 +22,91 @@ class Profile_tag extends Memcached_DataObject
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
|
||||
static function getTags($tagger, $tagged) {
|
||||
$tags = array();
|
||||
|
||||
// XXX: store this in memcached
|
||||
|
||||
$profile_tag = new Profile_tag();
|
||||
$profile_tag->tagger = $tagger;
|
||||
$profile_tag->tagged = $tagged;
|
||||
|
||||
$profile_tag->find();
|
||||
|
||||
while ($profile_tag->fetch()) {
|
||||
$tags[] = $profile_tag->tag;
|
||||
function pkeyGet($kv) {
|
||||
return Memcached_DataObject::pkeyGet('Profile_tag', $kv);
|
||||
}
|
||||
|
||||
$profile_tag->free();
|
||||
function links()
|
||||
{
|
||||
return array('tagger,tag' => 'profile_list:tagger,tag');
|
||||
}
|
||||
|
||||
function getMeta()
|
||||
{
|
||||
return Profile_list::pkeyGet(array('tagger' => $this->tagger, 'tag' => $this->tag));
|
||||
}
|
||||
|
||||
static function getTags($tagger, $tagged, $auth_user=null) {
|
||||
|
||||
$profile_list = new Profile_list();
|
||||
$include_priv = 1;
|
||||
|
||||
if (!($auth_user instanceof User ||
|
||||
$auth_user instanceof Profile) ||
|
||||
($auth_user->id !== $tagger)) {
|
||||
|
||||
$profile_list->private = false;
|
||||
$include_priv = 0;
|
||||
}
|
||||
|
||||
$key = sprintf('profile_tag:tagger_tagged_privacy:%d-%d-%d', $tagger, $tagged, $include_priv);
|
||||
$tags = Profile_list::getCached($key);
|
||||
if ($tags !== false) {
|
||||
return $tags;
|
||||
}
|
||||
|
||||
$profile_tag = new Profile_tag();
|
||||
$profile_list->tagger = $tagger;
|
||||
$profile_tag->tagged = $tagged;
|
||||
|
||||
$profile_list->selectAdd();
|
||||
|
||||
// only fetch id, tag, mainpage and
|
||||
// private hoping this will be faster
|
||||
$profile_list->selectAdd('profile_list.id, ' .
|
||||
'profile_list.tag, ' .
|
||||
'profile_list.mainpage, ' .
|
||||
'profile_list.private');
|
||||
$profile_list->joinAdd($profile_tag);
|
||||
$profile_list->find();
|
||||
|
||||
Profile_list::setCache($key, $profile_list);
|
||||
|
||||
return $profile_list;
|
||||
}
|
||||
|
||||
static function getTagsArray($tagger, $tagged, $auth_user_id=null)
|
||||
{
|
||||
$ptag = new Profile_tag();
|
||||
$ptag->tagger = $tagger;
|
||||
$ptag->tagged = $tagged;
|
||||
|
||||
if ($tagger != $auth_user_id) {
|
||||
$list = new Profile_list();
|
||||
$list->private = false;
|
||||
$ptag->joinAdd($list);
|
||||
$ptag->selectAdd();
|
||||
$ptag->selectAdd('profile_tag.tag');
|
||||
}
|
||||
|
||||
$tags = array();
|
||||
$ptag->find();
|
||||
while ($ptag->fetch()) {
|
||||
$tags[] = $ptag->tag;
|
||||
}
|
||||
$ptag->free();
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
static function setTags($tagger, $tagged, $newtags) {
|
||||
$newtags = array_unique($newtags);
|
||||
$oldtags = Profile_tag::getTags($tagger, $tagged);
|
||||
static function setTags($tagger, $tagged, $newtags, $privacy=array()) {
|
||||
|
||||
// Delete stuff that's old that not in new
|
||||
$newtags = array_unique($newtags);
|
||||
$oldtags = self::getTagsArray($tagger, $tagged, $tagger);
|
||||
|
||||
$ptag = new Profile_tag();
|
||||
|
||||
// Delete stuff that's in old and not in new
|
||||
|
||||
$to_delete = array_diff($oldtags, $newtags);
|
||||
|
||||
@ -54,33 +114,164 @@ class Profile_tag extends Memcached_DataObject
|
||||
|
||||
$to_insert = array_diff($newtags, $oldtags);
|
||||
|
||||
$profile_tag = new Profile_tag();
|
||||
|
||||
$profile_tag->tagger = $tagger;
|
||||
$profile_tag->tagged = $tagged;
|
||||
|
||||
$profile_tag->query('BEGIN');
|
||||
|
||||
foreach ($to_delete as $deltag) {
|
||||
$profile_tag->tag = $deltag;
|
||||
$result = $profile_tag->delete();
|
||||
if (!$result) {
|
||||
common_log_db_error($profile_tag, 'DELETE', __FILE__);
|
||||
return false;
|
||||
}
|
||||
self::unTag($tagger, $tagged, $deltag);
|
||||
}
|
||||
|
||||
foreach ($to_insert as $instag) {
|
||||
$profile_tag->tag = $instag;
|
||||
$result = $profile_tag->insert();
|
||||
$private = isset($privacy[$instag]) ? $privacy[$instag] : false;
|
||||
self::setTag($tagger, $tagged, $instag, null, $private);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
# set a single tag
|
||||
static function setTag($tagger, $tagged, $tag, $desc=null, $private=false) {
|
||||
|
||||
$ptag = Profile_tag::pkeyGet(array('tagger' => $tagger,
|
||||
'tagged' => $tagged,
|
||||
'tag' => $tag));
|
||||
|
||||
# if tag already exists, return it
|
||||
if(!empty($ptag)) {
|
||||
return $ptag;
|
||||
}
|
||||
|
||||
$tagger_profile = Profile::staticGet('id', $tagger);
|
||||
$tagged_profile = Profile::staticGet('id', $tagged);
|
||||
|
||||
if (Event::handle('StartTagProfile', array($tagger_profile, $tagged_profile, $tag))) {
|
||||
|
||||
if (!$tagger_profile->canTag($tagged_profile)) {
|
||||
// TRANS: Client exception thrown trying to set a tag for a user that cannot be tagged.
|
||||
throw new ClientException(_('You cannot tag this user.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$tags = new Profile_list();
|
||||
$tags->tagger = $tagger;
|
||||
$count = (int) $tags->count('distinct tag');
|
||||
|
||||
if ($count >= common_config('peopletag', 'maxtags')) {
|
||||
// TRANS: Client exception thrown trying to set more tags than allowed.
|
||||
throw new ClientException(sprintf(_('You already have created %d or more tags ' .
|
||||
'which is the maximum allowed number of tags. ' .
|
||||
'Try using or deleting some existing tags.'),
|
||||
common_config('peopletag', 'maxtags')));
|
||||
return false;
|
||||
}
|
||||
|
||||
$plist = new Profile_list();
|
||||
$plist->query('BEGIN');
|
||||
|
||||
$profile_list = Profile_list::ensureTag($tagger, $tag, $desc, $private);
|
||||
|
||||
if ($profile_list->taggedCount() >= common_config('peopletag', 'maxpeople')) {
|
||||
// TRANS: Client exception thrown trying to set one tag for more people than allowed.
|
||||
throw new ClientException(sprintf(_('You already have %1$d or more people tagged %2$s, ' .
|
||||
'which is the maximum allowed number.' .
|
||||
'Try untagging others with the same tag first.'),
|
||||
common_config('peopletag', 'maxpeople'), $tag));
|
||||
return false;
|
||||
}
|
||||
|
||||
$newtag = new Profile_tag();
|
||||
|
||||
$newtag->tagger = $tagger;
|
||||
$newtag->tagged = $tagged;
|
||||
$newtag->tag = $tag;
|
||||
|
||||
$result = $newtag->insert();
|
||||
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($profile_tag, 'INSERT', __FILE__);
|
||||
common_log_db_error($newtag, 'INSERT', __FILE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$plist->query('COMMIT');
|
||||
Event::handle('EndTagProfile', array($newtag));
|
||||
} catch (Exception $e) {
|
||||
$newtag->delete();
|
||||
$profile_list->delete();
|
||||
throw $e;
|
||||
return false;
|
||||
}
|
||||
|
||||
$profile_list->taggedCount(true);
|
||||
self::blowCaches($tagger, $tagged);
|
||||
}
|
||||
|
||||
return $newtag;
|
||||
}
|
||||
|
||||
static function unTag($tagger, $tagged, $tag) {
|
||||
$ptag = Profile_tag::pkeyGet(array('tagger' => $tagger,
|
||||
'tagged' => $tagged,
|
||||
'tag' => $tag));
|
||||
if (!$ptag) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Event::handle('StartUntagProfile', array($ptag))) {
|
||||
$orig = clone($ptag);
|
||||
$result = $ptag->delete();
|
||||
if (!$result) {
|
||||
common_log_db_error($this, 'DELETE', __FILE__);
|
||||
return false;
|
||||
}
|
||||
Event::handle('EndUntagProfile', array($orig));
|
||||
if ($result) {
|
||||
$profile_list = Profile_list::pkeyGet(array('tag' => $tag, 'tagger' => $tagger));
|
||||
$profile_list->taggedCount(true);
|
||||
self::blowCaches($tagger, $tagged);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$profile_tag->query('COMMIT');
|
||||
// @fixme: move this to Profile_list?
|
||||
static function cleanup($profile_list) {
|
||||
$ptag = new Profile_tag();
|
||||
$ptag->tagger = $profile_list->tagger;
|
||||
$ptag->tag = $profile_list->tag;
|
||||
$ptag->find();
|
||||
|
||||
while($ptag->fetch()) {
|
||||
if (Event::handle('StartUntagProfile', array($ptag))) {
|
||||
$orig = clone($ptag);
|
||||
$result = $ptag->delete();
|
||||
if (!$result) {
|
||||
common_log_db_error($this, 'DELETE', __FILE__);
|
||||
}
|
||||
Event::handle('EndUntagProfile', array($orig));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// move a tag!
|
||||
static function moveTag($orig, $new) {
|
||||
$tags = new Profile_tag();
|
||||
$qry = 'UPDATE profile_tag SET ' .
|
||||
'tag = "%s", tagger = "%s" ' .
|
||||
'WHERE tag = "%s" ' .
|
||||
'AND tagger = "%s"';
|
||||
$result = $tags->query(sprintf($qry, $new->tag, $new->tagger,
|
||||
$orig->tag, $orig->tagger));
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($tags, 'UPDATE', __FILE__);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static function blowCaches($tagger, $tagged) {
|
||||
foreach (array(0, 1) as $perm) {
|
||||
self::blow(sprintf('profile_tag:tagger_tagged_privacy:%d-%d-%d', $tagger, $tagged, $perm));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -96,6 +287,6 @@ class Profile_tag extends Memcached_DataObject
|
||||
while ($profile->fetch()) {
|
||||
$tagged[] = clone($profile);
|
||||
}
|
||||
return $tagged;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
27
classes/Profile_tag_inbox.php
Normal file
27
classes/Profile_tag_inbox.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Table Definition for profile_tag_inbox
|
||||
*/
|
||||
|
||||
class Profile_tag_inbox extends Memcached_DataObject
|
||||
{
|
||||
###START_AUTOCODE
|
||||
/* the code below is auto generated do not remove the above tag */
|
||||
|
||||
public $__table = 'profile_tag_inbox'; // table name
|
||||
public $profile_tag_id; // int(4) primary_key not_null
|
||||
public $notice_id; // int(4) primary_key not_null
|
||||
public $created; // datetime() not_null
|
||||
|
||||
/* Static get */
|
||||
|
||||
function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Profile_tag_inbox',$k,$v); }
|
||||
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
|
||||
function pkeyGet($kv)
|
||||
{
|
||||
return Memcached_DataObject::pkeyGet('Profile_tag_inbox', $kv);
|
||||
}
|
||||
}
|
105
classes/Profile_tag_subscription.php
Normal file
105
classes/Profile_tag_subscription.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* Table Definition for profile_tag_subscription
|
||||
*/
|
||||
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||
|
||||
class Profile_tag_subscription extends Memcached_DataObject
|
||||
{
|
||||
###START_AUTOCODE
|
||||
/* the code below is auto generated do not remove the above tag */
|
||||
|
||||
public $__table = 'profile_tag_subscription'; // table name
|
||||
public $profile_tag_id; // int(4) not_null
|
||||
public $profile_id; // int(4) not_null
|
||||
public $created; // datetime not_null default_0000-00-00%2000%3A00%3A00
|
||||
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
||||
|
||||
/* Static get */
|
||||
function staticGet($k,$v=null)
|
||||
{ return Memcached_DataObject::staticGet('Profile_tag_subscription',$k,$v); }
|
||||
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
|
||||
function pkeyGet($kv)
|
||||
{
|
||||
return Memcached_DataObject::pkeyGet('Profile_tag_subscription', $kv);
|
||||
}
|
||||
|
||||
static function add($peopletag, $profile)
|
||||
{
|
||||
if ($peopletag->private) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Event::handle('StartSubscribePeopletag', array($peopletag, $profile))) {
|
||||
$args = array('profile_tag_id' => $peopletag->id,
|
||||
'profile_id' => $profile->id);
|
||||
$existing = Profile_tag_subscription::pkeyGet($args);
|
||||
if(!empty($existing)) {
|
||||
return $existing;
|
||||
}
|
||||
|
||||
$sub = new Profile_tag_subscription();
|
||||
$sub->profile_tag_id = $peopletag->id;
|
||||
$sub->profile_id = $profile->id;
|
||||
$sub->created = common_sql_now();
|
||||
|
||||
$result = $sub->insert();
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($sub, 'INSERT', __FILE__);
|
||||
// TRANS: Exception thrown when inserting a people tag subscription in the database fails.
|
||||
throw new Exception(_('Adding people tag subscription failed.'));
|
||||
}
|
||||
|
||||
$ptag = Profile_list::staticGet('id', $peopletag->id);
|
||||
$ptag->subscriberCount(true);
|
||||
|
||||
Event::handle('EndSubscribePeopletag', array($peopletag, $profile));
|
||||
return $ptag;
|
||||
}
|
||||
}
|
||||
|
||||
static function remove($peopletag, $profile)
|
||||
{
|
||||
$sub = Profile_tag_subscription::pkeyGet(array('profile_tag_id' => $peopletag->id,
|
||||
'profile_id' => $profile->id));
|
||||
|
||||
if (empty($sub)) {
|
||||
// silence is golden?
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Event::handle('StartUnsubscribePeopletag', array($peopletag, $profile))) {
|
||||
$result = $sub->delete();
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($sub, 'DELETE', __FILE__);
|
||||
// TRANS: Exception thrown when deleting a people tag subscription from the database fails.
|
||||
throw new Exception(_('Removing people tag subscription failed.'));
|
||||
}
|
||||
|
||||
$peopletag->subscriberCount(true);
|
||||
|
||||
Event::handle('EndUnsubscribePeopletag', array($peopletag, $profile));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// called if a tag gets deleted / made private
|
||||
static function cleanup($profile_list) {
|
||||
$subs = new self();
|
||||
$subs->profile_tag_id = $profile_list->id;
|
||||
$subs->find();
|
||||
|
||||
while($subs->fetch()) {
|
||||
$profile = Profile::staticGet('id', $subs->profile_id);
|
||||
Event::handle('StartUnsubscribePeopletag', array($profile_list, $profile));
|
||||
// Delete anyway
|
||||
$subs->delete();
|
||||
Event::handle('StartUnsubscribePeopletag', array($profile_list, $profile));
|
||||
}
|
||||
}
|
||||
}
|
@ -532,12 +532,12 @@ class User extends Memcached_DataObject
|
||||
|
||||
function getSelfTags()
|
||||
{
|
||||
return Profile_tag::getTags($this->id, $this->id);
|
||||
return Profile_tag::getTagsArray($this->id, $this->id, $this->id);
|
||||
}
|
||||
|
||||
function setSelfTags($newtags)
|
||||
function setSelfTags($newtags, $privacy)
|
||||
{
|
||||
return Profile_tag::setTags($this->id, $this->id, $newtags);
|
||||
return Profile_tag::setTags($this->id, $this->id, $newtags, $privacy);
|
||||
}
|
||||
|
||||
function block($other)
|
||||
@ -809,7 +809,8 @@ class User extends Memcached_DataObject
|
||||
|
||||
function repeatedToMe($offset=0, $limit=20, $since_id=null, $max_id=null)
|
||||
{
|
||||
throw new Exception("Not implemented since inbox change.");
|
||||
// TRANS: Exception thrown when trying view "repeated to me".
|
||||
throw new Exception(_('Not implemented since inbox change.'));
|
||||
}
|
||||
|
||||
function shareLocation()
|
||||
|
@ -462,6 +462,43 @@ tagger = K
|
||||
tagged = K
|
||||
tag = K
|
||||
|
||||
[profile_list]
|
||||
id = 129
|
||||
tagger = 129
|
||||
tag = 130
|
||||
description = 34
|
||||
private = 17
|
||||
created = 142
|
||||
modified = 384
|
||||
uri = 130
|
||||
mainpage = 130
|
||||
tagged_count = 129
|
||||
subscriber_count = 129
|
||||
|
||||
[profile_list__keys]
|
||||
id = U
|
||||
tagger = K
|
||||
tag = K
|
||||
|
||||
[profile_tag_inbox]
|
||||
profile_tag_id = 129
|
||||
notice_id = 129
|
||||
created = 142
|
||||
|
||||
[profile_tag_inbox__keys]
|
||||
profile_tag_id = K
|
||||
notice_id = K
|
||||
|
||||
[profile_tag_subscription]
|
||||
profile_tag_id = 129
|
||||
profile_id = 129
|
||||
created = 142
|
||||
modified = 384
|
||||
|
||||
[profile_tag_subscription__keys]
|
||||
profile_tag_id = K
|
||||
profile_id = K
|
||||
|
||||
[queue_item]
|
||||
id = 129
|
||||
frame = 194
|
||||
|
@ -55,3 +55,23 @@ file_id = file:id
|
||||
file_id = file:id
|
||||
post_id = notice:id
|
||||
|
||||
[profile_list]
|
||||
tagger = profile:id
|
||||
|
||||
[profile_tag]
|
||||
tagger = profile:id
|
||||
tagged = profile:id
|
||||
; in class definition:
|
||||
;tag,tagger = profile_list:tag,tagger
|
||||
|
||||
[profile_list]
|
||||
tagger = profile:id
|
||||
|
||||
[profile_tag_inbox]
|
||||
profile_tag_id = profile_list:id
|
||||
notice_id = notice:id
|
||||
|
||||
[profile_tag_subscription]
|
||||
profile_tag_id = profile_list:id
|
||||
profile_id = profile:id
|
||||
|
||||
|
@ -182,6 +182,29 @@ $config['sphinx']['port'] = 3312;
|
||||
// $config['memcached']['server'] = 'localhost';
|
||||
// $config['memcached']['port'] = 11211;
|
||||
|
||||
// People tags
|
||||
// Maximum number of tags a user can create:
|
||||
// $config['peopletag']['maxtags'] = 100;
|
||||
// Maximum number of people can have the same tag by the same user
|
||||
// $config['peopletag']['maxpeople'] = 500;
|
||||
// Types of users one can tag.
|
||||
// Everyone.
|
||||
// $config['peopletag']['allow_tagging']['all'] = true;
|
||||
// Local only.
|
||||
// $config['peopletag']['allow_tagging']['local'] = true;
|
||||
// Subscriptions / Subscribers only (including remote)
|
||||
// $config['peopletag']['allow_tagging']['subs'] = true;
|
||||
// Remote.
|
||||
// $config['peopletag']['allow_tagging']['remote'] = true;
|
||||
// Examples:
|
||||
// The following set of options allows tagging local users and
|
||||
// remote subscribers / subscription.
|
||||
// $config['peopletag']['allow_tagging']['all'] = false;
|
||||
// $config['peopletag']['allow_tagging']['local'] = true;
|
||||
// $config['peopletag']['allow_tagging']['subs'] = true;
|
||||
// Or:
|
||||
// $config['peopletag']['allow_tagging'] = array('local' => true, 'subs' =>true);
|
||||
|
||||
// Disable post-by-email
|
||||
// $config['emailpost']['enabled'] = false;
|
||||
|
||||
|
4
db/095topeopletags.sql
Normal file
4
db/095topeopletags.sql
Normal file
@ -0,0 +1,4 @@
|
||||
/* populate people tags metadata */
|
||||
|
||||
insert into profile_list (tagger, tag, modified, description, private)
|
||||
select distinct tagger, tag, modified, null, false from profile_tag;
|
73
db/core.php
73
db/core.php
@ -610,8 +610,9 @@ $schema['profile_tag'] = array(
|
||||
),
|
||||
'primary key' => array('tagger', 'tagged', 'tag'),
|
||||
'foreign keys' => array(
|
||||
'profile_tag_tagger_fkey' => array('user', array('tagger' => 'id')),
|
||||
'profile_tag_tagger_fkey' => array('profile', array('tagger' => 'id')),
|
||||
'profile_tag_tagged_fkey' => array('profile', array('tagged' => 'id')),
|
||||
'profile_tag_tag_fkey' => array('profile_list', array('tag' => 'tag')),
|
||||
),
|
||||
'indexes' => array(
|
||||
'profile_tag_modified_idx' => array('modified'),
|
||||
@ -620,6 +621,76 @@ $schema['profile_tag'] = array(
|
||||
),
|
||||
);
|
||||
|
||||
$schema['profile_list'] = array(
|
||||
'fields' => array(
|
||||
'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
|
||||
'tagger' => array('type' => 'int', 'not null' => true, 'description' => 'user making the tag'),
|
||||
'tag' => array('type' => 'varchar', 'length' => 64, 'not null' => true, 'description' => 'people tag'),
|
||||
'description' => array('type' => 'text', 'description' => 'description of the people tag'),
|
||||
'private' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'is this tag private'),
|
||||
|
||||
'created' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date the tag was added'),
|
||||
'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date the tag was modified'),
|
||||
|
||||
'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universal identifier'),
|
||||
'mainpage' => array('type' => 'varchar', 'length' => 255, 'description' => 'page to link to'),
|
||||
'tagged_count' => array('type' => 'int', 'default' => 0, 'description' => 'number of people tagged with this tag by this user'),
|
||||
'subscriber_count' => array('type' => 'int', 'default' => 0, 'description' => 'number of subscribers to this tag'),
|
||||
),
|
||||
'primary key' => array('tagger', 'tag'),
|
||||
'unique keys' => array(
|
||||
'profile_list_id_key' => array('id')
|
||||
),
|
||||
'foreign keys' => array(
|
||||
'profile_list_tagger_fkey' => array('profile', array('tagger' => 'id')),
|
||||
),
|
||||
'indexes' => array(
|
||||
'profile_list_modified_idx' => array('modified'),
|
||||
'profile_list_tag_idx' => array('tag'),
|
||||
'profile_list_tagger_tag_idx' => array('tagger', 'tag'),
|
||||
'profile_list_tagged_count_idx' => array('tagged_count'),
|
||||
'profile_list_subscriber_count_idx' => array('subscriber_count'),
|
||||
),
|
||||
);
|
||||
|
||||
$schema['profile_tag_inbox'] = array(
|
||||
'description' => 'Many-many table listing notices associated with people tags.',
|
||||
'fields' => array(
|
||||
'profile_tag_id' => array('type' => 'int', 'not null' => true, 'description' => 'people tag receiving the message'),
|
||||
'notice_id' => array('type' => 'int', 'not null' => true, 'description' => 'notice received'),
|
||||
'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the notice was created'),
|
||||
),
|
||||
'primary key' => array('profile_tag_id', 'notice_id'),
|
||||
'foreign keys' => array(
|
||||
'profile_tag_inbox_profile_list_id_fkey' => array('profile_list', array('profile_tag_id' => 'id')),
|
||||
'profile_tag_inbox_notice_id_fkey' => array('notice', array('notice_id' => 'id')),
|
||||
),
|
||||
'indexes' => array(
|
||||
'profile_tag_inbox_created_idx' => array('created'),
|
||||
'profile_tag_inbox_profile_tag_id_idx' => array('profile_tag_id'),
|
||||
),
|
||||
);
|
||||
|
||||
$schema['profile_tag_subscription'] = array(
|
||||
'fields' => array(
|
||||
'profile_tag_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile_tag'),
|
||||
'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'),
|
||||
|
||||
'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
|
||||
'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
|
||||
),
|
||||
'primary key' => array('profile_tag_id', 'profile_id'),
|
||||
'foreign keys' => array(
|
||||
'profile_tag_subscription_profile_list_id_fkey' => array('profile_list', array('profile_tag_id' => 'id')),
|
||||
'profile_tag_subscription_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
|
||||
),
|
||||
'indexes' => array(
|
||||
// @fixme probably we want a (profile_id, created) index here?
|
||||
'profile_tag_subscription_profile_id_idx' => array('profile_id'),
|
||||
'profile_tag_subscription_created_idx' => array('created'),
|
||||
),
|
||||
);
|
||||
|
||||
$schema['profile_block'] = array(
|
||||
'fields' => array(
|
||||
'blocker' => array('type' => 'int', 'not null' => true, 'description' => 'user making the block'),
|
||||
|
@ -403,7 +403,7 @@ create table notice_inbox (
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table profile_tag (
|
||||
tagger integer not null comment 'user making the tag' references user (id),
|
||||
tagger integer not null comment 'user making the tag' references profile (id),
|
||||
tagged integer not null comment 'profile tagged' references profile (id),
|
||||
tag varchar(64) not null comment 'hash tag associated with this notice',
|
||||
modified timestamp comment 'date the tag was added',
|
||||
@ -414,6 +414,53 @@ create table profile_tag (
|
||||
index profile_tag_tagged_idx (tagged)
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
/* people tag metadata */
|
||||
create table profile_list (
|
||||
id integer auto_increment unique key comment 'unique identifier',
|
||||
tagger integer not null comment 'user making the tag' references profile (id),
|
||||
tag varchar(64) not null comment 'hash tag',
|
||||
description text comment 'description for the tag',
|
||||
private tinyint(1) default 0 comment 'is this list private',
|
||||
|
||||
created datetime not null comment 'date this record was created',
|
||||
modified timestamp comment 'date this record was modified',
|
||||
|
||||
uri varchar(255) unique key comment 'universal identifier',
|
||||
mainpage varchar(255) comment 'page for tag info info to link to',
|
||||
tagged_count smallint not null default 0 comment 'number of people tagged',
|
||||
subscriber_count smallint not null default 0 comment 'number of people subscribing',
|
||||
|
||||
constraint primary key (tagger, tag),
|
||||
index profile_list_tag_idx (tag),
|
||||
index profile_list_tagged_count_idx (tagged_count),
|
||||
index profile_list_modified_idx (modified),
|
||||
index profile_list_subscriber_count_idx (subscriber_count)
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table profile_tag_inbox (
|
||||
profile_tag_id integer not null comment 'peopletag receiving the message' references profile_tag (id),
|
||||
notice_id integer not null comment 'notice received' references notice (id),
|
||||
created datetime not null comment 'date the notice was created',
|
||||
|
||||
constraint primary key (profile_tag_id, notice_id),
|
||||
index profile_tag_inbox_created_idx (created),
|
||||
index profile_tag_inbox_notice_id_idx (notice_id)
|
||||
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table profile_tag_subscription (
|
||||
profile_tag_id integer not null comment 'foreign key to profile_tag' references profile_list (id),
|
||||
|
||||
profile_id integer not null comment 'foreign key to profile table' references profile (id),
|
||||
created datetime not null comment 'date this record was created',
|
||||
modified timestamp comment 'date this record was modified',
|
||||
|
||||
constraint primary key (profile_tag_id, profile_id),
|
||||
index profile_tag_subscription_profile_id_idx (profile_id),
|
||||
index profile_tag_subscription_created_idx (created)
|
||||
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table profile_block (
|
||||
blocker integer not null comment 'user making the block' references user (id),
|
||||
blocked integer not null comment 'profile that is blocked' references profile (id),
|
||||
|
49
doc-src/tags
49
doc-src/tags
@ -25,20 +25,49 @@ Tagging yourself
|
||||
----------------
|
||||
|
||||
You can also add tags for yourself on your [profile
|
||||
settings](%%action.profilesettings%%) page. Use single words to
|
||||
settings](%%action.profilesettings%%) page or by using the edit tags
|
||||
button on your profile page. Use single words to
|
||||
describe yourself, your experiences and your interest. The tags will
|
||||
become links on your profile page to a list of all the users on the
|
||||
site who use that same tag. It can be a nice way to find people who
|
||||
are related to you geographically or who have a common interest.
|
||||
|
||||
Tagging your subscriptions
|
||||
--------------------------
|
||||
Tagging others
|
||||
--------------
|
||||
|
||||
You can also tag your subscriptions, on the subscriptions page. This
|
||||
makes it easy to organize your subscriptions into groups and sort
|
||||
through them separately.
|
||||
You can also tag other users by using the edit tags button next to
|
||||
their profile. Such tags are called *people tags*. Once you have
|
||||
created a people tag, you can add or remove users from it using the
|
||||
tag's edit form. This makes it easy to organize your subscriptions
|
||||
into groups and sort through them separately. Also, it will let
|
||||
you create custom lists of people that others can subscribe to.
|
||||
|
||||
You can also send a notice "to the attention of" your subscribers
|
||||
whom you've marked with a particular tag (note: *not* people who've
|
||||
marked themselves with that tag). "@#family hello" will send a
|
||||
notice to all your subscribers you've marked with the tag 'family'.
|
||||
|
||||
Private and public people tags
|
||||
------------------------------
|
||||
|
||||
A private people tag is only visible to the creator, it cannot be
|
||||
subscribed to, but the timeline can be viewed. To create a new
|
||||
private prepend a '.' to the tag in the tags editing box. To set
|
||||
an existing public tag as private or vice-versa, go to the tag's
|
||||
edit page.
|
||||
|
||||
The most used public tags are displayed in the
|
||||
[public people tag cloud](%%action.publicpeopletagcloud%%). Their
|
||||
size shows their frequency of use.
|
||||
|
||||
Remote people tags
|
||||
------------------
|
||||
|
||||
You can even [tag remote users](%%action.profilesettings%%). Just
|
||||
enter the remote profile's URI and click on the "Fetch" button to
|
||||
fetch the profile, you can then add tags and save them.
|
||||
|
||||
Subscribing to the timeline of a people tag on another server also
|
||||
works. Just copy the URL of the people tag's timeline page to the
|
||||
[OStatus subscription](%%action.ostatussub%%) form.
|
||||
|
||||
You can also send a notice "to the attention of" everyone you've
|
||||
marked with a particular tag (note: *not* people who've marked
|
||||
themselves with that tag). "@#family hello" will send a notice to
|
||||
everyone you've marked with the tag 'family'.
|
187
js/util.js
187
js/util.js
@ -476,6 +476,74 @@ var SN = { // StatusNet
|
||||
});
|
||||
},
|
||||
|
||||
FormProfileSearchXHR: function(form) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
dataType: 'xml',
|
||||
url: form.attr('action'),
|
||||
data: form.serialize() + '&ajax=1',
|
||||
beforeSend: function(xhr) {
|
||||
form
|
||||
.addClass(SN.C.S.Processing)
|
||||
.find('.submit')
|
||||
.addClass(SN.C.S.Disabled)
|
||||
.attr(SN.C.S.Disabled, SN.C.S.Disabled);
|
||||
},
|
||||
error: function (xhr, textStatus, errorThrown) {
|
||||
alert(errorThrown || textStatus);
|
||||
},
|
||||
success: function(data, textStatus) {
|
||||
var results_placeholder = $('#profile_search_results');
|
||||
if (typeof($('ul', data)[0]) != 'undefined') {
|
||||
var list = document._importNode($('ul', data)[0], true);
|
||||
results_placeholder.replaceWith(list);
|
||||
}
|
||||
else {
|
||||
var _error = $('<li/>').append(document._importNode($('p', data)[0], true));
|
||||
results_placeholder.html(_error);
|
||||
}
|
||||
form
|
||||
.removeClass(SN.C.S.Processing)
|
||||
.find('.submit')
|
||||
.removeClass(SN.C.S.Disabled)
|
||||
.attr(SN.C.S.Disabled, false);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
FormPeopletagsXHR: function(form) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
dataType: 'xml',
|
||||
url: form.attr('action'),
|
||||
data: form.serialize() + '&ajax=1',
|
||||
beforeSend: function(xhr) {
|
||||
form.find('.submit')
|
||||
.addClass(SN.C.S.Processing)
|
||||
.addClass(SN.C.S.Disabled)
|
||||
.attr(SN.C.S.Disabled, SN.C.S.Disabled);
|
||||
},
|
||||
error: function (xhr, textStatus, errorThrown) {
|
||||
alert(errorThrown || textStatus);
|
||||
},
|
||||
success: function(data, textStatus) {
|
||||
var results_placeholder = form.parents('.entity_tags');
|
||||
if (typeof($('.entity_tags', data)[0]) != 'undefined') {
|
||||
var tags = document._importNode($('.entity_tags', data)[0], true);
|
||||
$(tags).find('.editable').append($('<button class="peopletags_edit_button"/>'));
|
||||
results_placeholder.replaceWith(tags);
|
||||
} else {
|
||||
results_placeholder.find('p').remove();
|
||||
results_placeholder.append(document._importNode($('p', data)[0], true));
|
||||
form.removeClass(SN.C.S.Processing)
|
||||
.find('.submit')
|
||||
.removeClass(SN.C.S.Disabled)
|
||||
.attr(SN.C.S.Disabled, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
normalizeGeoData: function(form) {
|
||||
SN.C.I.NoticeDataGeo.NLat = form.find('[name=lat]').val();
|
||||
SN.C.I.NoticeDataGeo.NLon = form.find('[name=lon]').val();
|
||||
@ -505,6 +573,7 @@ var SN = { // StatusNet
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch an XML DOM from an XHR's response data.
|
||||
*
|
||||
@ -1430,10 +1499,28 @@ var SN = { // StatusNet
|
||||
*/
|
||||
EntityActions: function() {
|
||||
if ($('body.user_in').length > 0) {
|
||||
$('.form_user_subscribe').live('click', function() { SN.U.FormXHR($(this)); return false; });
|
||||
$('.form_user_unsubscribe').live('click', function() { SN.U.FormXHR($(this)); return false; });
|
||||
$('.form_group_join').live('click', function() { SN.U.FormXHR($(this)); return false; });
|
||||
$('.form_group_leave').live('click', function() { SN.U.FormXHR($(this)); return false; });
|
||||
$('.form_user_nudge').live('click', function() { SN.U.FormXHR($(this)); return false; });
|
||||
$('.form_peopletag_subscribe').live('click', function() { SN.U.FormXHR($(this)); return false; });
|
||||
$('.form_peopletag_unsubscribe').live('click', function() { SN.U.FormXHR($(this)); return false; });
|
||||
$('.form_user_add_peopletag').live('click', function() { SN.U.FormXHR($(this)); return false; });
|
||||
$('.form_user_remove_peopletag').live('click', function() { SN.U.FormXHR($(this)); return false; });
|
||||
|
||||
SN.U.NewDirectMessage();
|
||||
}
|
||||
},
|
||||
|
||||
ProfileSearch: function() {
|
||||
if ($('body.user_in').length > 0) {
|
||||
$('.form_peopletag_edit_user_search input.submit').live('click', function() {
|
||||
SN.U.FormProfileSearchXHR($(this).parents('form')); return false;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Run setup code for login form:
|
||||
*
|
||||
@ -1456,6 +1543,100 @@ var SN = { // StatusNet
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a people tag edit box is shown in the interface
|
||||
*
|
||||
* - loads the jQuery UI autocomplete plugin
|
||||
* - sets event handlers for tag completion
|
||||
*
|
||||
*/
|
||||
PeopletagAutocomplete: function(txtBox) {
|
||||
var split = function(val) {
|
||||
return val.split( /\s+/ );
|
||||
}
|
||||
var extractLast = function(term) {
|
||||
return split(term).pop();
|
||||
}
|
||||
|
||||
// don't navigate away from the field on tab when selecting an item
|
||||
txtBox.live( "keydown", function( event ) {
|
||||
if ( event.keyCode === $.ui.keyCode.TAB &&
|
||||
$(this).data( "autocomplete" ).menu.active ) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}).autocomplete({
|
||||
minLength: 0,
|
||||
source: function(request, response) {
|
||||
// delegate back to autocomplete, but extract the last term
|
||||
response($.ui.autocomplete.filter(
|
||||
SN.C.PtagACData, extractLast(request.term)));
|
||||
},
|
||||
focus: function() {
|
||||
return false;
|
||||
},
|
||||
select: function(event, ui) {
|
||||
var terms = split(this.value);
|
||||
terms.pop();
|
||||
terms.push(ui.item.value);
|
||||
terms.push("");
|
||||
this.value = terms.join(" ");
|
||||
return false;
|
||||
}
|
||||
}).data('autocomplete')._renderItem = function(ul, item) {
|
||||
// FIXME: with jQuery UI you cannot have it highlight the match
|
||||
var _l = '<a class="ptag-ac-line-tag">' + item.tag
|
||||
+ ' <em class="privacy_mode">' + item.mode + '</em>'
|
||||
+ '<span class="freq">' + item.freq + '</span></a>'
|
||||
|
||||
return $("<li/>")
|
||||
.addClass('mode-' + item.mode)
|
||||
.addClass('ptag-ac-line')
|
||||
.data("item.autocomplete", item)
|
||||
.append(_l)
|
||||
.appendTo(ul);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Run setup for the ajax people tags editor
|
||||
*
|
||||
* - show edit button
|
||||
* - set event handle for click on edit button
|
||||
* - loads people tag autocompletion data if not already present
|
||||
* or if it is stale.
|
||||
*
|
||||
*/
|
||||
PeopleTags: function() {
|
||||
$('.user_profile_tags .editable').append($('<button class="peopletags_edit_button"/>'));
|
||||
|
||||
$('.peopletags_edit_button').live('click', function() {
|
||||
var form = $(this).parents('dd').eq(0).find('form');
|
||||
// We can buy time from the above animation
|
||||
|
||||
$.ajax({
|
||||
url: _peopletagAC,
|
||||
dataType: 'json',
|
||||
data: {token: $('#token').val()},
|
||||
ifModified: true,
|
||||
success: function(data) {
|
||||
// item.label is used to match
|
||||
for (i=0; i < data.length; i++) {
|
||||
data[i].label = data[i].tag;
|
||||
}
|
||||
|
||||
SN.C.PtagACData = data;
|
||||
SN.Init.PeopletagAutocomplete(form.find('#tags'));
|
||||
}
|
||||
});
|
||||
|
||||
$(this).parents('ul').eq(0).fadeOut(200, function() {form.fadeIn(200).find('input#tags')});
|
||||
});
|
||||
|
||||
$('.user_profile_tags form .submit').live('click', function() {
|
||||
SN.U.FormPeopletagsXHR($(this).parents('form')); return false;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up any generic 'ajax' form so it submits via AJAX with auto-replacement.
|
||||
*/
|
||||
@ -1548,5 +1729,11 @@ $(document).ready(function(){
|
||||
if ($('#form_login').length > 0) {
|
||||
SN.Init.Login();
|
||||
}
|
||||
if ($('#profile_search_results').length > 0) {
|
||||
SN.Init.ProfileSearch();
|
||||
}
|
||||
if ($('.user_profile_tags .editable').length > 0) {
|
||||
SN.Init.PeopleTags();
|
||||
}
|
||||
});
|
||||
|
||||
|
2
js/util.min.js
vendored
2
js/util.min.js
vendored
File diff suppressed because one or more lines are too long
@ -34,6 +34,8 @@ if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/peopletags.php';
|
||||
|
||||
/**
|
||||
* Profile block to show for an account
|
||||
*
|
||||
@ -92,6 +94,22 @@ class AccountProfileBlock extends ProfileBlock
|
||||
return $this->profile->bio;
|
||||
}
|
||||
|
||||
function showTags()
|
||||
{
|
||||
$cur = common_current_user();
|
||||
|
||||
$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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showActions()
|
||||
{
|
||||
if (Event::handle('StartProfilePageActionsSection', array($this->out, $this->profile))) {
|
||||
|
@ -317,6 +317,7 @@ class Action extends HTMLOutputter // lawsuit
|
||||
$this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/json2.js').'"); }');
|
||||
$this->script('jquery.joverlay.js');
|
||||
}
|
||||
|
||||
Event::handle('EndShowJQueryScripts', array($this));
|
||||
}
|
||||
if (Event::handle('StartShowStatusNetScripts', array($this)) &&
|
||||
@ -328,6 +329,8 @@ class Action extends HTMLOutputter // lawsuit
|
||||
$this->script('xbImportNode.js');
|
||||
$this->script('geometa.js');
|
||||
}
|
||||
$this->inlineScript('var _peopletagAC = "' .
|
||||
common_local_url('peopletagautocomplete') . '";');
|
||||
$this->showScriptMessages();
|
||||
// Frame-busting code to avoid clickjacking attacks.
|
||||
$this->inlineScript('if (window.top !== window.self) { window.top.location.href = window.self.location.href; }');
|
||||
@ -345,7 +348,6 @@ class Action extends HTMLOutputter // lawsuit
|
||||
* events and appending to the array. Try to avoid adding strings that won't be used, as
|
||||
* they'll be added to HTML output.
|
||||
*/
|
||||
|
||||
function showScriptMessages()
|
||||
{
|
||||
$messages = array();
|
||||
@ -743,7 +745,6 @@ class Action extends HTMLOutputter // lawsuit
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
|
||||
function showProfileBlock()
|
||||
{
|
||||
if (common_logged_in()) {
|
||||
|
@ -64,6 +64,7 @@ class ActivityObject
|
||||
const BOOKMARK = 'http://activitystrea.ms/schema/1.0/bookmark';
|
||||
const PERSON = 'http://activitystrea.ms/schema/1.0/person';
|
||||
const GROUP = 'http://activitystrea.ms/schema/1.0/group';
|
||||
const _LIST = 'http://activitystrea.ms/schema/1.0/list'; // LIST is reserved
|
||||
const PLACE = 'http://activitystrea.ms/schema/1.0/place';
|
||||
const COMMENT = 'http://activitystrea.ms/schema/1.0/comment';
|
||||
// ^^^^^^^^^^ tea!
|
||||
@ -92,6 +93,7 @@ class ActivityObject
|
||||
public $title;
|
||||
public $summary;
|
||||
public $content;
|
||||
public $owner;
|
||||
public $link;
|
||||
public $source;
|
||||
public $avatarLinks = array();
|
||||
@ -168,6 +170,10 @@ class ActivityObject
|
||||
Activity::MEDIA
|
||||
);
|
||||
}
|
||||
if ($this->type == self::_LIST) {
|
||||
$owner = ActivityUtils::child($this->element, Activity::AUTHOR, Activity::SPEC);
|
||||
$this->owner = new ActivityObject($owner);
|
||||
}
|
||||
}
|
||||
|
||||
private function _fromAuthor($element)
|
||||
@ -440,7 +446,6 @@ class ActivityObject
|
||||
$object = new ActivityObject();
|
||||
|
||||
if (Event::handle('StartActivityObjectFromProfile', array($profile, &$object))) {
|
||||
|
||||
$object->type = ActivityObject::PERSON;
|
||||
$object->id = $profile->getUri();
|
||||
$object->title = $profile->getBestName();
|
||||
@ -520,13 +525,29 @@ class ActivityObject
|
||||
AVATAR_MINI_SIZE);
|
||||
|
||||
$object->poco = PoCo::fromGroup($group);
|
||||
|
||||
Event::handle('EndActivityObjectFromGroup', array($group, &$object));
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
static function fromPeopletag($ptag)
|
||||
{
|
||||
$object = new ActivityObject();
|
||||
if (Event::handle('StartActivityObjectFromPeopletag', array($ptag, &$object))) {
|
||||
$object->type = ActivityObject::_LIST;
|
||||
|
||||
$object->id = $ptag->getUri();
|
||||
$object->title = $ptag->tag;
|
||||
$object->summary = $ptag->description;
|
||||
$object->link = $ptag->homeUrl();
|
||||
$object->owner = Profile::staticGet('id', $ptag->tagger);
|
||||
$object->poco = PoCo::fromProfile($object->owner);
|
||||
Event::handle('EndActivityObjectFromPeopletag', array($ptag, &$object));
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
|
||||
function outputTo($xo, $tag='activity:object')
|
||||
{
|
||||
if (!empty($tag)) {
|
||||
@ -585,6 +606,11 @@ class ActivityObject
|
||||
);
|
||||
}
|
||||
|
||||
if(!empty($this->owner)) {
|
||||
$owner = $this->owner->asActivityNoun(self::AUTHOR);
|
||||
$xo->raw($owner);
|
||||
}
|
||||
|
||||
if ($this->type == ActivityObject::PERSON
|
||||
|| $this->type == ActivityObject::GROUP) {
|
||||
|
||||
|
@ -59,6 +59,7 @@ class ActivityVerb
|
||||
const UNFAVORITE = 'http://ostatus.org/schema/1.0/unfavorite';
|
||||
const UNFOLLOW = 'http://ostatus.org/schema/1.0/unfollow';
|
||||
const LEAVE = 'http://ostatus.org/schema/1.0/leave';
|
||||
const UNTAG = 'http://ostatus.org/schema/1.0/untag';
|
||||
|
||||
// For simple profile-update pings; no content to share.
|
||||
const UPDATE_PROFILE = 'http://ostatus.org/schema/1.0/update-profile';
|
||||
|
@ -459,6 +459,32 @@ class ApiAction extends Action
|
||||
return $entry;
|
||||
}
|
||||
|
||||
function twitterListArray($list)
|
||||
{
|
||||
$profile = Profile::staticGet('id', $list->tagger);
|
||||
|
||||
$twitter_list = array();
|
||||
$twitter_list['id'] = $list->id;
|
||||
$twitter_list['name'] = $list->tag;
|
||||
$twitter_list['full_name'] = '@'.$profile->nickname.'/'.$list->tag;;
|
||||
$twitter_list['slug'] = $list->tag;
|
||||
$twitter_list['description'] = $list->description;
|
||||
$twitter_list['subscriber_count'] = $list->subscriberCount();
|
||||
$twitter_list['member_count'] = $list->taggedCount();
|
||||
$twitter_list['uri'] = $list->getUri();
|
||||
|
||||
if (isset($this->auth_user)) {
|
||||
$twitter_list['following'] = $list->hasSubscriber($this->auth_user);
|
||||
} else {
|
||||
$twitter_list['following'] = false;
|
||||
}
|
||||
|
||||
$twitter_list['mode'] = ($list->private) ? 'private' : 'public';
|
||||
$twitter_list['user'] = $this->twitterUserArray($profile, false);
|
||||
|
||||
return $twitter_list;
|
||||
}
|
||||
|
||||
function twitterRssEntryArray($notice)
|
||||
{
|
||||
$entry = array();
|
||||
@ -634,6 +660,20 @@ class ApiAction extends Action
|
||||
$this->elementEnd('group');
|
||||
}
|
||||
|
||||
function showTwitterXmlList($twitter_list)
|
||||
{
|
||||
$this->elementStart('list');
|
||||
foreach($twitter_list as $element => $value) {
|
||||
if($element == 'user') {
|
||||
$this->showTwitterXmlUser($value, 'user');
|
||||
}
|
||||
else {
|
||||
$this->element($element, null, $value);
|
||||
}
|
||||
}
|
||||
$this->elementEnd('list');
|
||||
}
|
||||
|
||||
function showTwitterXmlUser($twitter_user, $role='user', $namespaces=false)
|
||||
{
|
||||
$attrs = array();
|
||||
@ -1111,6 +1151,65 @@ class ApiAction extends Action
|
||||
$this->endDocument('xml');
|
||||
}
|
||||
|
||||
function showXmlLists($list, $next_cursor=0, $prev_cursor=0)
|
||||
{
|
||||
|
||||
$this->initDocument('xml');
|
||||
$this->elementStart('lists_list');
|
||||
$this->elementStart('lists', array('type' => 'array'));
|
||||
|
||||
if (is_array($list)) {
|
||||
foreach ($list as $l) {
|
||||
$twitter_list = $this->twitterListArray($l);
|
||||
$this->showTwitterXmlList($twitter_list);
|
||||
}
|
||||
} else {
|
||||
while ($list->fetch()) {
|
||||
$twitter_list = $this->twitterListArray($list);
|
||||
$this->showTwitterXmlList($twitter_list);
|
||||
}
|
||||
}
|
||||
|
||||
$this->elementEnd('lists');
|
||||
|
||||
$this->element('next_cursor', null, $next_cursor);
|
||||
$this->element('previous_cursor', null, $prev_cursor);
|
||||
|
||||
$this->elementEnd('lists_list');
|
||||
$this->endDocument('xml');
|
||||
}
|
||||
|
||||
function showJsonLists($list, $next_cursor=0, $prev_cursor=0)
|
||||
{
|
||||
$this->initDocument('json');
|
||||
|
||||
$lists = array();
|
||||
|
||||
if (is_array($list)) {
|
||||
foreach ($list as $l) {
|
||||
$twitter_list = $this->twitterListArray($l);
|
||||
array_push($lists, $twitter_list);
|
||||
}
|
||||
} else {
|
||||
while ($list->fetch()) {
|
||||
$twitter_list = $this->twitterListArray($list);
|
||||
array_push($lists, $twitter_list);
|
||||
}
|
||||
}
|
||||
|
||||
$lists_list = array(
|
||||
'lists' => $lists,
|
||||
'next_cursor' => $next_cursor,
|
||||
'next_cursor_str' => strval($next_cursor),
|
||||
'previous_cursor' => $prev_cursor,
|
||||
'previous_cursor_str' => strval($prev_cursor)
|
||||
);
|
||||
|
||||
$this->showJsonObjects($lists_list);
|
||||
|
||||
$this->endDocument('json');
|
||||
}
|
||||
|
||||
function showTwitterXmlUsers($user)
|
||||
{
|
||||
$this->initDocument('xml');
|
||||
@ -1172,6 +1271,22 @@ class ApiAction extends Action
|
||||
$this->endDocument('xml');
|
||||
}
|
||||
|
||||
function showSingleJsonList($list)
|
||||
{
|
||||
$this->initDocument('json');
|
||||
$twitter_list = $this->twitterListArray($list);
|
||||
$this->showJsonObjects($twitter_list);
|
||||
$this->endDocument('json');
|
||||
}
|
||||
|
||||
function showSingleXmlList($list)
|
||||
{
|
||||
$this->initDocument('xml');
|
||||
$twitter_list = $this->twitterListArray($list);
|
||||
$this->showTwitterXmlList($twitter_list);
|
||||
$this->endDocument('xml');
|
||||
}
|
||||
|
||||
function dateTwitter($dt)
|
||||
{
|
||||
$dateStr = date('d F Y H:i:s', strtotime($dt));
|
||||
@ -1465,6 +1580,40 @@ class ApiAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
function getTargetList($user=null, $id=null)
|
||||
{
|
||||
$tagger = $this->getTargetUser($user);
|
||||
$list = null;
|
||||
|
||||
if (empty($id)) {
|
||||
$id = $this->arg('id');
|
||||
}
|
||||
|
||||
if($id) {
|
||||
if (is_numeric($id)) {
|
||||
$list = Profile_list::staticGet('id', $id);
|
||||
|
||||
// only if the list with the id belongs to the tagger
|
||||
if(empty($list) || $list->tagger != $tagger->id) {
|
||||
$list = null;
|
||||
}
|
||||
}
|
||||
if (empty($list)) {
|
||||
$tag = common_canonical_tag($id);
|
||||
$list = Profile_list::getByTaggerAndTag($tagger->id, $tag);
|
||||
}
|
||||
|
||||
if (!empty($list) && $list->private) {
|
||||
if ($this->auth_user->id == $list->tagger) {
|
||||
return $list;
|
||||
}
|
||||
} else {
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns query argument or default value if not found. Certain
|
||||
* parameters used throughout the API are lightly scrubbed and
|
||||
|
207
lib/apilistusers.php
Normal file
207
lib/apilistusers.php
Normal file
@ -0,0 +1,207 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Base class for list members and list subscribers api.
|
||||
*
|
||||
* 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 API
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/lib/apibareauth.php';
|
||||
|
||||
class ApiListUsersAction extends ApiBareAuthAction
|
||||
{
|
||||
var $list = null;
|
||||
var $user = false;
|
||||
var $create = false;
|
||||
var $delete = false;
|
||||
var $cursor = -1;
|
||||
var $next_cursor = 0;
|
||||
var $prev_cursor = 0;
|
||||
var $users = null;
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
// delete list member if method is DELETE or if method is POST and an argument
|
||||
// _method is set to DELETE
|
||||
$this->delete = ($_SERVER['REQUEST_METHOD'] == 'DELETE' ||
|
||||
($this->trimmed('_method') == 'DELETE' &&
|
||||
$_SERVER['REQUEST_METHOD'] == 'POST'));
|
||||
|
||||
// add member if method is POST
|
||||
$this->create = (!$this->delete &&
|
||||
$_SERVER['REQUEST_METHOD'] == 'POST');
|
||||
|
||||
if($this->arg('id')) {
|
||||
$this->user = $this->getTargetUser($this->arg('id'));
|
||||
}
|
||||
|
||||
parent::prepare($args);
|
||||
|
||||
$this->list = $this->getTargetList($this->arg('user'), $this->arg('list_id'));
|
||||
|
||||
if (empty($this->list)) {
|
||||
// TRANS: Client error displayed when referring to a non-existing list.
|
||||
$this->clientError(_('List not found.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!$this->create && !$this->delete) {
|
||||
$this->getUsers();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function requiresAuth()
|
||||
{
|
||||
return parent::requiresAuth() ||
|
||||
$this->create || $this->delete;
|
||||
}
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if($this->delete) {
|
||||
return $this->handleDelete();
|
||||
}
|
||||
|
||||
if($this->create) {
|
||||
return $this->handlePost();
|
||||
}
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->initDocument('xml');
|
||||
$this->elementStart('users_list', array('xmlns:statusnet' =>
|
||||
'http://status.net/schema/api/1/'));
|
||||
$this->elementStart('users', array('type' => 'array'));
|
||||
|
||||
if (is_array($this->users)) {
|
||||
foreach ($this->users as $u) {
|
||||
$twitter_user = $this->twitterUserArray($u, true);
|
||||
$this->showTwitterXmlUser($twitter_user);
|
||||
}
|
||||
} else {
|
||||
while ($this->users->fetch()) {
|
||||
$twitter_user = $this->twitterUserArray($this->users, true);
|
||||
$this->showTwitterXmlUser($twitter_user);
|
||||
}
|
||||
}
|
||||
|
||||
$this->elementEnd('users');
|
||||
$this->element('next_cursor', null, $this->next_cursor);
|
||||
$this->element('previous_cursor', null, $this->prev_cursor);
|
||||
$this->elementEnd('users_list');
|
||||
break;
|
||||
case 'json':
|
||||
$this->initDocument('json');
|
||||
|
||||
$users = array();
|
||||
|
||||
if (is_array($this->users)) {
|
||||
foreach ($this->users as $u) {
|
||||
$twitter_user = $this->twitterUserArray($u, true);
|
||||
array_push($users, $twitter_user);
|
||||
}
|
||||
} else {
|
||||
while ($this->users->fetch()) {
|
||||
$twitter_user = $this->twitterUserArray($this->users, true);
|
||||
array_push($users, $twitter_user);
|
||||
}
|
||||
}
|
||||
|
||||
$users_list = array('users' => $users,
|
||||
'next_cursor' => $this->next_cursor,
|
||||
'next_cursor_str' => strval($this->next_cursor),
|
||||
'previous_cursor' => $this->prev_cursor,
|
||||
'previous_cursor_str' => strval($this->prev_cursor));
|
||||
|
||||
$this->showJsonObjects($users_list);
|
||||
|
||||
$this->endDocument('json');
|
||||
break;
|
||||
default:
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||
_('API method not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function handlePost()
|
||||
{
|
||||
}
|
||||
|
||||
function handleDelete()
|
||||
{
|
||||
}
|
||||
|
||||
function getUsers()
|
||||
{
|
||||
}
|
||||
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
function lastModified()
|
||||
{
|
||||
if(!empty($this->list)) {
|
||||
return strtotime($this->list->modified);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity tag for this list
|
||||
*
|
||||
* Returns an Etag based on the action name, language, user ID and
|
||||
* timestamps of the first and last list the user has joined
|
||||
*
|
||||
* @return string etag
|
||||
*/
|
||||
function etag()
|
||||
{
|
||||
if (!empty($this->list)) {
|
||||
|
||||
return '"' . implode(
|
||||
':',
|
||||
array($this->arg('action'),
|
||||
common_language(),
|
||||
$this->list->id,
|
||||
strtotime($this->list->created),
|
||||
strtotime($this->list->modified))
|
||||
)
|
||||
. '"';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
104
lib/atomlistnoticefeed.php
Normal file
104
lib/atomlistnoticefeed.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Class for building an in-memory Atom feed for a particular list's
|
||||
* timeline.
|
||||
*
|
||||
* 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 Feed
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 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'))
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for list notice feeds. May contain a reference to the list.
|
||||
*
|
||||
* @category Feed
|
||||
* @package StatusNet
|
||||
* @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/
|
||||
*/
|
||||
class AtomListNoticeFeed extends AtomNoticeFeed
|
||||
{
|
||||
private $list;
|
||||
private $tagger;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param List $list the list for the feed
|
||||
* @param User $cur the current authenticated user, if any
|
||||
* @param boolean $indent flag to turn indenting on or off
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function __construct($list, $cur = null, $indent = true) {
|
||||
parent::__construct($cur, $indent);
|
||||
$this->list = $list;
|
||||
$this->tagger = Profile::staticGet('id', $list->tagger);
|
||||
|
||||
// TRANS: Title in atom list notice feed. %1$s is a list name, %2$s is a tagger's nickname.
|
||||
$title = sprintf(_('Timeline for people tagged #%1$s by %2$s'), $list->tag, $this->tagger->nickname);
|
||||
$this->setTitle($title);
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
$subtitle = sprintf(
|
||||
// TRANS: Message is used as a subtitle in atom list notice feed.
|
||||
// TRANS: %1$s is a tagger's nickname, %2$s is a list name, %3$s is a site name.
|
||||
_('Updates from %1$s\'s %2$s people tag on %3$s!'),
|
||||
$this->tagger->nickname,
|
||||
$list->tag,
|
||||
$sitename
|
||||
);
|
||||
$this->setSubtitle($subtitle);
|
||||
|
||||
$avatar = $this->tagger->avatarUrl(AVATAR_PROFILE_SIZE);
|
||||
$this->setLogo($avatar);
|
||||
|
||||
$this->setUpdated('now');
|
||||
|
||||
$self = common_local_url('ApiTimelineList',
|
||||
array('user' => $this->tagger->nickname,
|
||||
'id' => $list->tag,
|
||||
'format' => 'atom'));
|
||||
$this->setId($self);
|
||||
$this->setSelfLink($self);
|
||||
|
||||
// FIXME: Stop using activity:subject?
|
||||
$ao = ActivityObject::fromPeopletag($this->list);
|
||||
|
||||
$this->addAuthorRaw($ao->asString('author').
|
||||
$ao->asString('activity:subject'));
|
||||
|
||||
$this->addLink($this->list->getUri());
|
||||
}
|
||||
|
||||
function getList()
|
||||
{
|
||||
return $this->list;
|
||||
}
|
||||
}
|
197
lib/command.php
197
lib/command.php
@ -180,7 +180,7 @@ class UnimplementedCommand extends Command
|
||||
function handle($channel)
|
||||
{
|
||||
// TRANS: Error text shown when an unimplemented command is given.
|
||||
$channel->error($this->user, _("Sorry, this command is not yet implemented."));
|
||||
$channel->error($this->user, _('Sorry, this command is not yet implemented.'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,7 +295,7 @@ class FavCommand extends Command
|
||||
|
||||
if ($fave->fetch()) {
|
||||
// TRANS: Error message text shown when a favorite could not be set because it has already been favorited.
|
||||
$channel->error($this->user, _('Could not create favorite: already favorited.'));
|
||||
$channel->error($this->user, _('Could not create favorite: Already favorited.'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -414,6 +414,121 @@ class DropCommand extends Command
|
||||
}
|
||||
}
|
||||
|
||||
class TagCommand extends Command
|
||||
{
|
||||
var $other = null;
|
||||
var $tags = null;
|
||||
function __construct($user, $other, $tags)
|
||||
{
|
||||
parent::__construct($user);
|
||||
$this->other = $other;
|
||||
$this->tags = $tags;
|
||||
}
|
||||
|
||||
function handle($channel)
|
||||
{
|
||||
$profile = $this->getProfile($this->other);
|
||||
$cur = $this->user->getProfile();
|
||||
|
||||
if (!$profile) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing profile.
|
||||
$channel->error($cur, _('No such profile.'));
|
||||
return;
|
||||
}
|
||||
if (!$cur->canTag($profile)) {
|
||||
// TRANS: Error displayed when trying to tag a user that cannot be tagged.
|
||||
$channel->error($cur, _('You cannot tag this user.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$privs = array();
|
||||
$tags = preg_split('/[\s,]+/', $this->tags);
|
||||
$clean_tags = array();
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
$private = @$tag[0] === '.';
|
||||
$tag = $clean_tags[] = common_canonical_tag($tag);
|
||||
|
||||
if (!common_valid_profile_tag($tag)) {
|
||||
// TRANS: Error displayed if a given tag is invalid.
|
||||
// TRANS: %s is the invalid tag.
|
||||
$channel->error($cur, sprintf(_('Invalid tag: "%s".'), $tag));
|
||||
return;
|
||||
}
|
||||
$privs[$tag] = $private;
|
||||
}
|
||||
|
||||
try {
|
||||
foreach ($clean_tags as $tag) {
|
||||
Profile_tag::setTag($cur->id, $profile->id, $tag, null, $privs[$tag]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// TRANS: Error displayed if tagging a user fails.
|
||||
// TRANS: %1$s is the tagged user, %2$s is the error message (no punctuation).
|
||||
$channel->error($cur, sprintf(_('Error tagging %1$s: %2$s'),
|
||||
$profile->nickname, $e->getMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
// TRANS: Succes message displayed if tagging a user succeeds.
|
||||
// TRANS: %1$s is the tagged user's nickname, %2$s is a list of tags.
|
||||
$channel->output($cur, sprintf(_('%1$s was tagged %2$s'),
|
||||
$profile->nickname,
|
||||
// TRANS: Separator for list of tags.
|
||||
implode(_(', '), $clean_tags)));
|
||||
}
|
||||
}
|
||||
|
||||
class UntagCommand extends TagCommand
|
||||
{
|
||||
function handle($channel)
|
||||
{
|
||||
$profile = $this->getProfile($this->other);
|
||||
$cur = $this->user->getProfile();
|
||||
|
||||
if (!$profile) {
|
||||
// TRANS: Client error displayed trying to perform an action related to a non-existing profile.
|
||||
$channel->error($cur, _('No such profile.'));
|
||||
return;
|
||||
}
|
||||
if (!$cur->canTag($profile)) {
|
||||
// TRANS: Error displayed when trying to tag a user that cannot be tagged.
|
||||
$channel->error($cur, _('You cannot tag this user.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$tags = array_map('common_canonical_tag', preg_split('/[\s,]+/', $this->tags));
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
if (!common_valid_profile_tag($tag)) {
|
||||
// TRANS: Error displayed if a given tag is invalid.
|
||||
// TRANS: %s is the invalid tag.
|
||||
$channel->error($cur, sprintf(_('Invalid tag: "%s"'), $tag));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
foreach ($tags as $tag) {
|
||||
Profile_tag::unTag($cur->id, $profile->id, $tag);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// TRANS: Error displayed if untagging a user fails.
|
||||
// TRANS: %1$s is the untagged user, %2$s is the error message (no punctuation).
|
||||
$channel->error($cur, sprintf(_('Error untagging %1$s: %2$s'),
|
||||
$profile->nickname, $e->getMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
// TRANS: Succes message displayed if untagging a user succeeds.
|
||||
// TRANS: %1$s is the untagged user's nickname, %2$s is a list of tags.
|
||||
$channel->output($cur, sprintf(_('The following tag(s) were removed from user %1$s: %2$s.'),
|
||||
$profile->nickname,
|
||||
// TRANS: Separator for list of tags.
|
||||
implode(_(', '), $tags)));
|
||||
}
|
||||
}
|
||||
|
||||
class WhoisCommand extends Command
|
||||
{
|
||||
var $other = null;
|
||||
@ -893,79 +1008,83 @@ class HelpCommand extends Command
|
||||
{
|
||||
// TRANS: Header line of help text for commands.
|
||||
$out = array(_m('COMMANDHELP', "Commands:"));
|
||||
$commands = array(// TRANS: Help message for IM/SMS command "on"
|
||||
$commands = array(// TRANS: Help message for IM/SMS command "on".
|
||||
"on" => _m('COMMANDHELP', "turn on notifications"),
|
||||
// TRANS: Help message for IM/SMS command "off"
|
||||
// TRANS: Help message for IM/SMS command "off".
|
||||
"off" => _m('COMMANDHELP', "turn off notifications"),
|
||||
// TRANS: Help message for IM/SMS command "help"
|
||||
// TRANS: Help message for IM/SMS command "help".
|
||||
"help" => _m('COMMANDHELP', "show this help"),
|
||||
// TRANS: Help message for IM/SMS command "follow <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "follow <nickname>".
|
||||
"follow <nickname>" => _m('COMMANDHELP', "subscribe to user"),
|
||||
// TRANS: Help message for IM/SMS command "groups"
|
||||
// TRANS: Help message for IM/SMS command "groups".
|
||||
"groups" => _m('COMMANDHELP', "lists the groups you have joined"),
|
||||
// TRANS: Help message for IM/SMS command "subscriptions"
|
||||
// TRANS: Help message for IM/SMS command "tag".
|
||||
"tag <nickname> <tags>" => _m('COMMANDHELP',"tag a user"),
|
||||
// TRANS: Help message for IM/SMS command "untag".
|
||||
"untag <nickname> <tags>" => _m('COMMANDHELP',"untag a user"),
|
||||
// TRANS: Help message for IM/SMS command "subscriptions".
|
||||
"subscriptions" => _m('COMMANDHELP', "list the people you follow"),
|
||||
// TRANS: Help message for IM/SMS command "subscribers"
|
||||
// TRANS: Help message for IM/SMS command "subscribers".
|
||||
"subscribers" => _m('COMMANDHELP', "list the people that follow you"),
|
||||
// TRANS: Help message for IM/SMS command "leave <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "leave <nickname>".
|
||||
"leave <nickname>" => _m('COMMANDHELP', "unsubscribe from user"),
|
||||
// TRANS: Help message for IM/SMS command "d <nickname> <text>"
|
||||
// TRANS: Help message for IM/SMS command "d <nickname> <text>".
|
||||
"d <nickname> <text>" => _m('COMMANDHELP', "direct message to user"),
|
||||
// TRANS: Help message for IM/SMS command "get <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "get <nickname>".
|
||||
"get <nickname>" => _m('COMMANDHELP', "get last notice from user"),
|
||||
// TRANS: Help message for IM/SMS command "whois <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "whois <nickname>".
|
||||
"whois <nickname>" => _m('COMMANDHELP', "get profile info on user"),
|
||||
// TRANS: Help message for IM/SMS command "lose <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "lose <nickname>".
|
||||
"lose <nickname>" => _m('COMMANDHELP', "force user to stop following you"),
|
||||
// TRANS: Help message for IM/SMS command "fav <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "fav <nickname>".
|
||||
"fav <nickname>" => _m('COMMANDHELP', "add user's last notice as a 'fave'"),
|
||||
// TRANS: Help message for IM/SMS command "fav #<notice_id>"
|
||||
// TRANS: Help message for IM/SMS command "fav #<notice_id>".
|
||||
"fav #<notice_id>" => _m('COMMANDHELP', "add notice with the given id as a 'fave'"),
|
||||
// TRANS: Help message for IM/SMS command "repeat #<notice_id>"
|
||||
// TRANS: Help message for IM/SMS command "repeat #<notice_id>".
|
||||
"repeat #<notice_id>" => _m('COMMANDHELP', "repeat a notice with a given id"),
|
||||
// TRANS: Help message for IM/SMS command "repeat <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "repeat <nickname>".
|
||||
"repeat <nickname>" => _m('COMMANDHELP', "repeat the last notice from user"),
|
||||
// TRANS: Help message for IM/SMS command "reply #<notice_id>"
|
||||
// TRANS: Help message for IM/SMS command "reply #<notice_id>".
|
||||
"reply #<notice_id>" => _m('COMMANDHELP', "reply to notice with a given id"),
|
||||
// TRANS: Help message for IM/SMS command "reply <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "reply <nickname>".
|
||||
"reply <nickname>" => _m('COMMANDHELP', "reply to the last notice from user"),
|
||||
// TRANS: Help message for IM/SMS command "join <group>"
|
||||
// TRANS: Help message for IM/SMS command "join <group>".
|
||||
"join <group>" => _m('COMMANDHELP', "join group"),
|
||||
// TRANS: Help message for IM/SMS command "login"
|
||||
// TRANS: Help message for IM/SMS command "login".
|
||||
"login" => _m('COMMANDHELP', "Get a link to login to the web interface"),
|
||||
// TRANS: Help message for IM/SMS command "drop <group>"
|
||||
// TRANS: Help message for IM/SMS command "drop <group>".
|
||||
"drop <group>" => _m('COMMANDHELP', "leave group"),
|
||||
// TRANS: Help message for IM/SMS command "stats"
|
||||
// TRANS: Help message for IM/SMS command "stats".
|
||||
"stats" => _m('COMMANDHELP', "get your stats"),
|
||||
// TRANS: Help message for IM/SMS command "stop"
|
||||
// TRANS: Help message for IM/SMS command "stop".
|
||||
"stop" => _m('COMMANDHELP', "same as 'off'"),
|
||||
// TRANS: Help message for IM/SMS command "quit"
|
||||
// TRANS: Help message for IM/SMS command "quit".
|
||||
"quit" => _m('COMMANDHELP', "same as 'off'"),
|
||||
// TRANS: Help message for IM/SMS command "sub <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "sub <nickname>".
|
||||
"sub <nickname>" => _m('COMMANDHELP', "same as 'follow'"),
|
||||
// TRANS: Help message for IM/SMS command "unsub <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "unsub <nickname>".
|
||||
"unsub <nickname>" => _m('COMMANDHELP', "same as 'leave'"),
|
||||
// TRANS: Help message for IM/SMS command "last <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "last <nickname>".
|
||||
"last <nickname>" => _m('COMMANDHELP', "same as 'get'"),
|
||||
// TRANS: Help message for IM/SMS command "on <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "on <nickname>".
|
||||
"on <nickname>" => _m('COMMANDHELP', "not yet implemented."),
|
||||
// TRANS: Help message for IM/SMS command "off <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "off <nickname>".
|
||||
"off <nickname>" => _m('COMMANDHELP', "not yet implemented."),
|
||||
// TRANS: Help message for IM/SMS command "nudge <nickname>"
|
||||
// TRANS: Help message for IM/SMS command "nudge <nickname>".
|
||||
"nudge <nickname>" => _m('COMMANDHELP', "remind a user to update."),
|
||||
// TRANS: Help message for IM/SMS command "invite <phone number>"
|
||||
// TRANS: Help message for IM/SMS command "invite <phone number>".
|
||||
"invite <phone number>" => _m('COMMANDHELP', "not yet implemented."),
|
||||
// TRANS: Help message for IM/SMS command "track <word>"
|
||||
// TRANS: Help message for IM/SMS command "track <word>".
|
||||
"track <word>" => _m('COMMANDHELP', "not yet implemented."),
|
||||
// TRANS: Help message for IM/SMS command "untrack <word>"
|
||||
// TRANS: Help message for IM/SMS command "untrack <word>".
|
||||
"untrack <word>" => _m('COMMANDHELP', "not yet implemented."),
|
||||
// TRANS: Help message for IM/SMS command "track off"
|
||||
// TRANS: Help message for IM/SMS command "track off".
|
||||
"track off" => _m('COMMANDHELP', "not yet implemented."),
|
||||
// TRANS: Help message for IM/SMS command "untrack all"
|
||||
// TRANS: Help message for IM/SMS command "untrack all".
|
||||
"untrack all" => _m('COMMANDHELP', "not yet implemented."),
|
||||
// TRANS: Help message for IM/SMS command "tracks"
|
||||
// TRANS: Help message for IM/SMS command "tracks".
|
||||
"tracks" => _m('COMMANDHELP', "not yet implemented."),
|
||||
// TRANS: Help message for IM/SMS command "tracking"
|
||||
// TRANS: Help message for IM/SMS command "tracking".
|
||||
"tracking" => _m('COMMANDHELP', "not yet implemented."));
|
||||
|
||||
// Give plugins a chance to add or override...
|
||||
|
@ -274,6 +274,32 @@ class CommandInterpreter
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'list':
|
||||
case 'tag':
|
||||
if (!$arg) {
|
||||
$result = null;
|
||||
break;
|
||||
}
|
||||
list($other, $tags) = $this->split_arg($arg);
|
||||
if (!$tags) {
|
||||
$result = null;
|
||||
} else {
|
||||
$result = new TagCommand($user, $other, $tags);
|
||||
}
|
||||
break;
|
||||
case 'unlist':
|
||||
case 'untag':
|
||||
if (!$arg) {
|
||||
$result = null;
|
||||
break;
|
||||
}
|
||||
list($other, $tags) = $this->split_arg($arg);
|
||||
if (!$tags) {
|
||||
$result = null;
|
||||
} else {
|
||||
$result = new UntagCommand($user, $other, $tags);
|
||||
}
|
||||
break;
|
||||
case 'track':
|
||||
if (!$arg) {
|
||||
$result = null;
|
||||
|
@ -269,6 +269,11 @@ $default =
|
||||
'group' =>
|
||||
array('maxaliases' => 3,
|
||||
'desclimit' => null),
|
||||
'peopletag' =>
|
||||
array('maxtags' => 100, // maximum number of tags a user can create.
|
||||
'maxpeople' => 500, // maximum no. of people with the same tag by the same user
|
||||
'allow_tagging' => array('all' => true), // equivalent to array('local' => true, 'remote' => true)
|
||||
'desclimit' => null),
|
||||
'oembed' =>
|
||||
array('endpoint' => 'http://oohembed.com/oohembed/',
|
||||
'order' => array('built-in', 'well-known', 'service', 'discovery'),
|
||||
|
@ -46,6 +46,7 @@ define('NOTICE_INBOX_SOURCE_SUB', 1);
|
||||
define('NOTICE_INBOX_SOURCE_GROUP', 2);
|
||||
define('NOTICE_INBOX_SOURCE_REPLY', 3);
|
||||
define('NOTICE_INBOX_SOURCE_FORWARD', 4);
|
||||
define('NOTICE_INBOX_SOURCE_PROFILE_TAG', 5);
|
||||
define('NOTICE_INBOX_SOURCE_GATEWAY', -1);
|
||||
|
||||
// append our extlib dir as the last-resort place to find libs
|
||||
|
@ -120,6 +120,9 @@ class GalleryAction extends OwnerDesignAction
|
||||
$content[$t] = $t;
|
||||
}
|
||||
if ($tags) {
|
||||
$this->elementStart('dl', array('id' => 'filter_tags'));
|
||||
$this->element('dt', null, _('Tags'));
|
||||
$this->elementStart('dd');
|
||||
$this->elementStart('ul');
|
||||
$this->elementStart('li', array('id' => 'filter_tags_all',
|
||||
'class' => 'child_1'));
|
||||
@ -150,6 +153,8 @@ class GalleryAction extends OwnerDesignAction
|
||||
$this->elementEnd('form');
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
}
|
||||
|
||||
|
210
lib/peopletageditform.php
Normal file
210
lib/peopletageditform.php
Normal file
@ -0,0 +1,210 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Form for editing 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 Form
|
||||
* @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);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/form.php';
|
||||
require_once INSTALLDIR.'/lib/togglepeopletag.php';
|
||||
|
||||
/**
|
||||
* Form for editing a peopletag
|
||||
*
|
||||
* @category Form
|
||||
* @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/
|
||||
*
|
||||
* @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()
|
||||
{
|
||||
// TRANS: Form legend for people tag edit form.
|
||||
// TRANS: %s is a people tag.
|
||||
$this->out->element('legend', null, sprintf(_('Edit people tag %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);
|
||||
|
||||
// TRANS: Field label for people tag.
|
||||
$this->out->input('tag', _m('LABEL','Tag'),
|
||||
($this->out->arg('tag')) ? $this->out->arg('tag') : $tag,
|
||||
// TRANS: Field title for people tag.
|
||||
_('Change the tag (letters, numbers, -, ., and _ are allowed).'));
|
||||
$this->out->elementEnd('li');
|
||||
|
||||
$this->out->elementStart('li');
|
||||
$desclimit = Profile_list::maxDescription();
|
||||
if ($desclimit == 0) {
|
||||
// TRANS: Field title for description of people tag.
|
||||
$descinstr = _('Describe the people tag or topic.');
|
||||
} else {
|
||||
// TRANS: Field title for description of people tag.
|
||||
// TRANS: %d is the maximum number of characters for the description.
|
||||
$descinstr = sprintf(_m('Describe the people tag or topic in %d character.',
|
||||
'Describe the people tag or topic in %d characters.',
|
||||
$desclimit),
|
||||
$desclimit);
|
||||
}
|
||||
// TRANS: Field label for description of people tag.
|
||||
$this->out->textarea('description', _('Description'),
|
||||
($this->out->arg('description')) ? $this->out->arg('description') : $description,
|
||||
$descinstr);
|
||||
// TRANS: Checkbox label to mark a people tag private.
|
||||
$this->out->checkbox('private', _('Private'), $private);
|
||||
$this->out->elementEnd('li');
|
||||
$this->out->elementEnd('ul');
|
||||
}
|
||||
|
||||
/**
|
||||
* Action elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function formActions()
|
||||
{
|
||||
// TRANS: Button text to save a people tag.
|
||||
$this->out->submit('submit', _('Save'));
|
||||
$this->out->submit('form_action-yes',
|
||||
// TRANS: Button text to delete a people tag.
|
||||
_m('BUTTON','Delete'),
|
||||
'submit',
|
||||
'delete',
|
||||
// TRANS: Button title to delete a people tag.
|
||||
_('Delete this people tag.'));
|
||||
}
|
||||
|
||||
function showProfileList()
|
||||
{
|
||||
$tagged = $this->peopletag->getTagged();
|
||||
// TRANS: Header in people tag edit form.
|
||||
$this->out->element('h2', null, _('Add or remove people'));
|
||||
|
||||
$this->out->elementStart('div', 'profile_search_wrap');
|
||||
// TRANS: Header in people tag edit form.
|
||||
$this->out->element('h3', null, _m('HEADER','Search'));
|
||||
$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();
|
||||
}
|
||||
}
|
154
lib/peopletaggroupnav.php
Normal file
154
lib/peopletaggroupnav.php
Normal file
@ -0,0 +1,154 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Base class for all actions (~views)
|
||||
*
|
||||
* 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 Sarven Capadisli <csarven@status.net>
|
||||
* @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 <evan@status.net>
|
||||
* @author Sarven Capadisli <csarven@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 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)),
|
||||
// TRANS: Menu item in people tag navigation panel.
|
||||
_m('MENU','People tag'),
|
||||
// TRANS: Menu item title in people tag navigation panel.
|
||||
// TRANS: %1$s is a tag, %2$s is a nickname.
|
||||
sprintf(_('%1$s tag by %2$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)),
|
||||
// TRANS: Menu item in people tag navigation panel.
|
||||
_m('MENU','Tagged'),
|
||||
// TRANS: Menu item title in people tag navigation panel.
|
||||
// TRANS: %1$s is a tag, %2$s is a nickname.
|
||||
sprintf(_('%1$s tag by %2$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)),
|
||||
// TRANS: Menu item in people tag navigation panel.
|
||||
_m('MENU','Subscribers'),
|
||||
// TRANS: Menu item title in people tag navigation panel.
|
||||
// TRANS: %1$s is a tag, %2$s is a nickname.
|
||||
sprintf(_('Subscribers to %1$s tag by %2$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)),
|
||||
// TRANS: Menu item in people tag navigation panel.
|
||||
_m('MENU','Edit'),
|
||||
// TRANS: Menu item title in people tag navigation panel.
|
||||
// TRANS: %s is a tag.
|
||||
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');
|
||||
}
|
||||
}
|
321
lib/peopletaglist.php
Normal file
321
lib/peopletaglist.php
Normal file
@ -0,0 +1,321 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Widget to show a list of peopletags
|
||||
*
|
||||
* 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 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/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))),
|
||||
// TRANS: Link description for link to list of users tagged with a 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))),
|
||||
// TRANS: Link description for link to list of users subscribed to a 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)),
|
||||
// TRANS: Title for link to edit people tag settings.
|
||||
'title' => _('Edit people tag settings.')),
|
||||
// TRANS: Text for link to edit people tag 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))));
|
||||
// TRANS: Privacy mode text in people tag list item for private tags.
|
||||
$this->out->element('span', 'privacy_mode', _m('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);
|
||||
}
|
||||
}
|
105
lib/peopletagnoticestream.php
Normal file
105
lib/peopletagnoticestream.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2011, StatusNet, Inc.
|
||||
*
|
||||
* Stream of notices for a people tag
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* 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 Stream
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @copyright 2011 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
// This check helps protect against security problems;
|
||||
// your code file can't be executed directly from the web.
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream of notices for a people tag
|
||||
*
|
||||
* @category Stream
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
||||
* @copyright 2011 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
class PeopletagNoticeStream extends ScopingNoticeStream
|
||||
{
|
||||
function __construct($plist)
|
||||
{
|
||||
parent::__construct(new CachingNoticeStream(new RawPeopletagNoticeStream($plist),
|
||||
'profile_tag:notice_ids:' . $plist->id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream of notices for a people tag
|
||||
*
|
||||
* @category Stream
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
||||
* @copyright 2011 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
class RawPeopletagNoticeStream extends NoticeStream
|
||||
{
|
||||
protected $profile_tag;
|
||||
|
||||
function __construct($profile_tag)
|
||||
{
|
||||
$this->profile_tag = $profile_tag;
|
||||
}
|
||||
|
||||
function getNoticeIds($offset, $limit, $since_id, $max_id)
|
||||
{
|
||||
$inbox = new Profile_tag_inbox();
|
||||
|
||||
$inbox->profile_tag_id = $this->profile_tag->id;
|
||||
|
||||
$inbox->selectAdd();
|
||||
$inbox->selectAdd('notice_id');
|
||||
|
||||
Notice::addWhereSinceId($inbox, $since_id, 'notice_id');
|
||||
Notice::addWhereMaxId($inbox, $max_id, 'notice_id');
|
||||
|
||||
$inbox->orderBy('created DESC, notice_id DESC');
|
||||
|
||||
if (!is_null($offset)) {
|
||||
$inbox->limit($offset, $limit);
|
||||
}
|
||||
|
||||
$ids = array();
|
||||
|
||||
if ($inbox->find()) {
|
||||
while ($inbox->fetch()) {
|
||||
$ids[] = $inbox->notice_id;
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
}
|
195
lib/peopletags.php
Normal file
195
lib/peopletags.php
Normal file
@ -0,0 +1,195 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Tags for a profile
|
||||
*
|
||||
* 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
|
||||
* @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 <connect2shashi@gmail.com>
|
||||
* @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()
|
||||
{
|
||||
// TRANS: Label in people tags widget.
|
||||
return _m('LABEL','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 = '<span class="mark_hash">#</span><a rel="tag" href="' .
|
||||
$this->url($this->tag->tag) .
|
||||
'">' . $this->tag->tag . '</a>';
|
||||
$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');
|
||||
// TRANS: Fieldset legend in people tags widget.
|
||||
$this->out->element('legend', null, _m('LEGEND','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));
|
||||
// TRANS: Button text to save tags for a profile.
|
||||
$this->out->submit('save', _m('BUTTON','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);
|
||||
// TRANS: Empty list message for tags.
|
||||
$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()
|
||||
{
|
||||
// TRANS: Label in self tags widget.
|
||||
return _m('LABEL','Tags');
|
||||
}
|
||||
}
|
76
lib/peopletagsbysubssection.php
Normal file
76
lib/peopletagsbysubssection.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Peopletags with the most subscribers section
|
||||
*
|
||||
* 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 Widget
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Peopletags with the most subscribers section
|
||||
*
|
||||
* @category Widget
|
||||
* @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 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()
|
||||
{
|
||||
// TRANS: Title for section contaning people tags with the most subscribers.
|
||||
return _('People tags with most subscribers');
|
||||
}
|
||||
|
||||
function divId()
|
||||
{
|
||||
return 'top_peopletags_by_subs';
|
||||
}
|
||||
}
|
141
lib/peopletagsection.php
Normal file
141
lib/peopletagsection.php
Normal file
@ -0,0 +1,141 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Base class for sections showing lists of peopletags
|
||||
*
|
||||
* 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 Widget
|
||||
* @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);
|
||||
}
|
||||
|
||||
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 <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 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 (isset($this->peopletag->value)) {
|
||||
$this->out->element('td', 'value', $this->peopletag->value);
|
||||
}
|
||||
$this->out->elementEnd('tr');
|
||||
}
|
||||
|
||||
function showTag()
|
||||
{
|
||||
// TRANS: Tag summary. %1$d is the number of users tagged with the tag,
|
||||
// TRANS: %2$d is the number of subscribers to the tag.
|
||||
$title = sprintf(_('Tagged: %1$d Subscribers: %2$d'),
|
||||
$this->peopletag->taggedCount(),
|
||||
$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);
|
||||
}
|
||||
}
|
89
lib/peopletagsforusersection.php
Normal file
89
lib/peopletagsforusersection.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* People tags a user has been tagged with
|
||||
*
|
||||
* 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 Widget
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* People tags a user has been tagged with
|
||||
*
|
||||
* @category Widget
|
||||
* @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 PeopletagsForUserSection extends PeopletagSection
|
||||
{
|
||||
var $profile=null;
|
||||
|
||||
function __construct($out, Profile $profile)
|
||||
{
|
||||
parent::__construct($out);
|
||||
$this->profile = $profile;
|
||||
}
|
||||
|
||||
function getPeopletags()
|
||||
{
|
||||
$limit = PEOPLETAGS_PER_SECTION+1;
|
||||
$offset = 0;
|
||||
|
||||
$auth_user = common_current_user();
|
||||
$ptags = $this->profile->getOtherTags($auth_user, $offset, $limit);
|
||||
|
||||
return $ptags;
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
$name = $this->profile->getBestName();
|
||||
if ($this->profile->id == common_current_user()->id) {
|
||||
$name = 'you';
|
||||
}
|
||||
// TRANS: Title for page that displays which people tags a user has been tagged with.
|
||||
// TRANS: %s is a profile name.
|
||||
return sprintf(_('People tags for %s'), $name);
|
||||
}
|
||||
|
||||
function link()
|
||||
{
|
||||
return common_local_url('peopletagsforuser',
|
||||
array('nickname' => $this->profile->nickname));
|
||||
}
|
||||
|
||||
function moreUrl()
|
||||
{
|
||||
return $this->link();
|
||||
}
|
||||
|
||||
function divId()
|
||||
{
|
||||
return 'peopletag_subscriptions';
|
||||
}
|
||||
}
|
83
lib/peopletagsubscriptionssection.php
Normal file
83
lib/peopletagsubscriptionssection.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Peopletags a user has subscribed to
|
||||
*
|
||||
* 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 Widget
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Peopletags a user has subscribed to
|
||||
*
|
||||
* @category Widget
|
||||
* @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 PeopletagSubscriptionsSection extends PeopletagSection
|
||||
{
|
||||
var $profile=null;
|
||||
|
||||
function __construct($out, Profile $profile)
|
||||
{
|
||||
parent::__construct($out);
|
||||
$this->profile = $profile;
|
||||
}
|
||||
|
||||
function getPeopletags()
|
||||
{
|
||||
$limit = PEOPLETAGS_PER_SECTION+1;
|
||||
$offset = 0;
|
||||
|
||||
$ptags = $this->profile->getTagSubscriptions($offset, $limit);
|
||||
|
||||
return $ptags;
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
// TRANS: Title for page that displays people tags a user has subscribed to.
|
||||
return _('People tag subscriptions');
|
||||
}
|
||||
|
||||
function link()
|
||||
{
|
||||
return common_local_url('peopletagsubscriptions',
|
||||
array('nickname' => $this->profile->nickname));
|
||||
}
|
||||
|
||||
function moreUrl()
|
||||
{
|
||||
return $this->link();
|
||||
}
|
||||
|
||||
function divId()
|
||||
{
|
||||
return 'peopletag_subscriptions';
|
||||
}
|
||||
}
|
@ -103,6 +103,18 @@ class PersonalGroupNav extends Menu
|
||||
// TRANS: Replaces %s in '%s\'s favorite notices'. (Yes, we know we need to fix this.)
|
||||
($user_profile) ? $name : _m('FIXME','User')),
|
||||
$mine && $action =='showfavorites', 'nav_timeline_favorites');
|
||||
$this->out->menuItem(common_local_url('peopletagsbyuser', array('nickname' =>
|
||||
$nickname)),
|
||||
// TRANS: Menu item in personal group navigation menu.
|
||||
_m('MENU','People tags'),
|
||||
// @todo i18n FIXME: Need to make this two messages.
|
||||
// TRANS: Menu item title in personal group navigation menu.
|
||||
// TRANS: %s is a username.
|
||||
sprintf(_('People tags by %s'),
|
||||
// TRANS: Replaces %s in 'People tags by %s'. (Yes, we know we need to fix this.)
|
||||
($user_profile) ? $name : _('User')),
|
||||
in_array($action, array('peopletagsbyuser', 'peopletagsforuser')),
|
||||
'nav_timeline_peopletags');
|
||||
|
||||
$cur = common_current_user();
|
||||
|
||||
|
@ -97,6 +97,8 @@ class ProfileAction extends OwnerDesignAction
|
||||
$this->showSubscriptions();
|
||||
$this->showSubscribers();
|
||||
$this->showGroups();
|
||||
$this->showPeopletagSubs();
|
||||
$this->showPeopletags();
|
||||
$this->showStatistics();
|
||||
}
|
||||
|
||||
@ -188,6 +190,32 @@ class ProfileAction extends OwnerDesignAction
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showPeopletagSubs()
|
||||
{
|
||||
$user = common_current_user();
|
||||
if (!empty($user) && $this->profile->id == $user->id) {
|
||||
if (Event::handle('StartShowPeopletagSubscriptionsSection', array($this))) {
|
||||
|
||||
$profile = $user->getProfile();
|
||||
$section = new PeopletagSubscriptionsSection($this, $profile);
|
||||
$section->show();
|
||||
|
||||
Event::handle('EndShowPeopletagSubscriptionsSection', array($this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showPeopletags()
|
||||
{
|
||||
if (Event::handle('StartShowPeopletagsSection', array($this))) {
|
||||
|
||||
$section = new PeopletagsForUserSection($this, $this->profile);
|
||||
$section->show();
|
||||
|
||||
Event::handle('EndShowPeopletagsSection', array($this));
|
||||
}
|
||||
}
|
||||
|
||||
function showStatistics()
|
||||
{
|
||||
$notice_count = $this->profile->noticeCount();
|
||||
|
@ -62,6 +62,7 @@ abstract class ProfileBlock extends Widget
|
||||
$this->showLocation();
|
||||
$this->showHomepage();
|
||||
$this->showDescription();
|
||||
$this->showTags();
|
||||
}
|
||||
|
||||
function showAvatar()
|
||||
@ -131,6 +132,10 @@ abstract class ProfileBlock extends Widget
|
||||
return AVATAR_PROFILE_SIZE;
|
||||
}
|
||||
|
||||
function showTags()
|
||||
{
|
||||
}
|
||||
|
||||
function showActions()
|
||||
{
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
@ -33,6 +32,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
|
||||
@ -44,7 +44,6 @@ require_once INSTALLDIR.'/lib/widget.php';
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
class ProfileList extends Widget
|
||||
{
|
||||
/** Current profile, profile query. */
|
||||
@ -168,6 +167,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 +241,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');
|
||||
|
@ -74,6 +74,12 @@ class PublicGroupNav extends Menu
|
||||
// TRANS: Menu item title in search group navigation panel.
|
||||
_('Recent tags'), $action_name == 'publictagcloud', 'nav_recent-tags');
|
||||
|
||||
// TRANS: Menu item in search group navigation panel.
|
||||
$this->out->menuItem(common_local_url('publicpeopletagcloud'), _m('MENU','People tags'),
|
||||
// TRANS: Menu item title in search group navigation panel.
|
||||
_('People tags'), in_array($action_name, array('publicpeopletagcloud',
|
||||
'peopletag', 'selftag')), 'nav_people-tags');
|
||||
|
||||
if (count(common_config('nickname', 'featured')) > 0) {
|
||||
// TRANS: Menu item in search group navigation panel.
|
||||
$this->out->menuItem(common_local_url('featured'), _m('MENU','Featured'),
|
||||
|
144
lib/router.php
144
lib/router.php
@ -228,7 +228,9 @@ class Router
|
||||
$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'));
|
||||
@ -359,10 +361,6 @@ class Router
|
||||
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'));
|
||||
@ -774,6 +772,72 @@ class Router
|
||||
'id' => '[a-zA-Z0-9]+',
|
||||
'format' => '(xml|json)'));
|
||||
|
||||
// Lists (people tags)
|
||||
|
||||
$m->connect('api/lists/memberships.:format',
|
||||
array('action' => 'ApiListMemberships',
|
||||
'format' => '(xml|json)'));
|
||||
|
||||
$m->connect('api/:user/lists/memberships.:format',
|
||||
array('action' => 'ApiListMemberships',
|
||||
'user' => '[a-zA-Z0-9]+',
|
||||
'format' => '(xml|json)'));
|
||||
|
||||
$m->connect('api/lists/subscriptions.:format',
|
||||
array('action' => 'ApiListSubscriptions',
|
||||
'format' => '(xml|json)'));
|
||||
|
||||
$m->connect('api/:user/lists/subscriptions.:format',
|
||||
array('action' => 'ApiListSubscriptions',
|
||||
'user' => '[a-zA-Z0-9]+',
|
||||
'format' => '(xml|json)'));
|
||||
$m->connect('api/lists.:format',
|
||||
array('action' => 'ApiLists',
|
||||
'format' => '(xml|json)'));
|
||||
|
||||
$m->connect('api/:user/lists.:format',
|
||||
array('action' => 'ApiLists',
|
||||
'user' => '[a-zA-Z0-9]+',
|
||||
'format' => '(xml|json)'));
|
||||
|
||||
$m->connect('api/:user/lists/:id.:format',
|
||||
array('action' => 'ApiList',
|
||||
'user' => '[a-zA-Z0-9]+',
|
||||
'id' => '[a-zA-Z0-9]+',
|
||||
'format' => '(xml|json)'));
|
||||
|
||||
$m->connect('api/:user/lists/:id/statuses.:format',
|
||||
array('action' => 'ApiTimelineList',
|
||||
'user' => '[a-zA-Z0-9]+',
|
||||
'id' => '[a-zA-Z0-9]+',
|
||||
'format' => '(xml|json|rss|atom)'));
|
||||
|
||||
$m->connect('api/:user/:list_id/members.:format',
|
||||
array('action' => 'ApiListMembers',
|
||||
'user' => '[a-zA-Z0-9]+',
|
||||
'list_id' => '[a-zA-Z0-9]+',
|
||||
'format' => '(xml|json)'));
|
||||
|
||||
$m->connect('api/:user/:list_id/subscribers.:format',
|
||||
array('action' => 'ApiListSubscribers',
|
||||
'user' => '[a-zA-Z0-9]+',
|
||||
'list_id' => '[a-zA-Z0-9]+',
|
||||
'format' => '(xml|json)'));
|
||||
|
||||
$m->connect('api/:user/:list_id/members/:id.:format',
|
||||
array('action' => 'ApiListMember',
|
||||
'user' => '[a-zA-Z0-9]+',
|
||||
'list_id' => '[a-zA-Z0-9]+',
|
||||
'id' => '[a-zA-Z0-9]+',
|
||||
'format' => '(xml|json)'));
|
||||
|
||||
$m->connect('api/:user/:list_id/subscribers/:id.:format',
|
||||
array('action' => 'ApiListSubscriber',
|
||||
'user' => '[a-zA-Z0-9]+',
|
||||
'list_id' => '[a-zA-Z0-9]+',
|
||||
'id' => '[a-zA-Z0-9]+',
|
||||
'format' => '(xml|json)'));
|
||||
|
||||
// Tags
|
||||
$m->connect('api/statusnet/tags/timeline/:tag.:format',
|
||||
array('action' => 'ApiTimelineTag',
|
||||
@ -908,6 +972,76 @@ class Router
|
||||
array('action' => 'subqueue'),
|
||||
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),
|
||||
|
@ -61,8 +61,15 @@ class Section extends Widget
|
||||
array('id' => $this->divId(),
|
||||
'class' => 'section'));
|
||||
|
||||
$link = $this->link();
|
||||
if (!empty($link)) {
|
||||
$this->out->elementStart('h2');
|
||||
$this->out->element('a', array('href' => $link), $this->title());
|
||||
$this->out->elementEnd('h2');
|
||||
} else {
|
||||
$this->out->element('h2', null,
|
||||
$this->title());
|
||||
}
|
||||
|
||||
$have_more = $this->showContent();
|
||||
|
||||
@ -88,6 +95,11 @@ class Section extends Widget
|
||||
return _('Untitled section');
|
||||
}
|
||||
|
||||
function link()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$this->out->element('p', null,
|
||||
|
@ -128,6 +128,18 @@ class SubGroupNav extends Menu
|
||||
$this->user->nickname),
|
||||
$action == 'usergroups',
|
||||
'nav_usergroups');
|
||||
$this->out->menuItem(common_local_url('peopletagsbyuser',
|
||||
array('nickname' =>
|
||||
$this->user->nickname)),
|
||||
// TRANS: Menu item title in local navigation menu.
|
||||
_m('MENU','People tags'),
|
||||
// TRANS: Menu item title in local navigation menu.
|
||||
// TRANS: %s is a user nickname.
|
||||
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'),
|
||||
// TRANS: Menu item in local navigation menu.
|
||||
|
108
lib/subscribepeopletagform.php
Normal file
108
lib/subscribepeopletagform.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Form for subscribing 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 Form
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @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);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/form.php';
|
||||
|
||||
/**
|
||||
* Form for subscribing to a peopletag
|
||||
*
|
||||
* @category Form
|
||||
* @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/
|
||||
*
|
||||
* @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()
|
||||
{
|
||||
// TRANS: Button text for subscribing to a people tag.
|
||||
$this->out->submit('submit', m('BUTTON','Subscribe'));
|
||||
}
|
||||
}
|
@ -50,7 +50,9 @@ class SubscribersPeopleSelfTagCloudSection extends SubPeopleTagCloudSection
|
||||
|
||||
function query() {
|
||||
// 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';
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,6 @@ 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';
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,6 @@ require_once INSTALLDIR.'/lib/profilelist.php';
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
class SubscriptionList extends ProfileList
|
||||
{
|
||||
/** Owner of this list */
|
||||
@ -92,37 +91,4 @@ class SubscriptionListItem extends ProfileListItem
|
||||
$user = common_current_user();
|
||||
return (!empty($user) && ($this->owner->id == $user->id));
|
||||
}
|
||||
|
||||
function showTags()
|
||||
{
|
||||
$tags = Profile_tag::getTags($this->owner->id, $this->profile->id);
|
||||
|
||||
if ($this->isOwn()) {
|
||||
$this->out->element('a', array('href' => common_local_url('tagother',
|
||||
array('id' => $this->profile->id))),
|
||||
// TRANS: Description for link to "tag other users" in widget to show a list of profiles.
|
||||
_('Tags'));
|
||||
} else {
|
||||
// TRANS: Text widget to show a list of profiles with their tags.
|
||||
$this->out->text(_('Tags'));
|
||||
}
|
||||
if ($tags) {
|
||||
$this->out->elementStart('ul', 'tags xoxo entity_tags');
|
||||
foreach ($tags as $tag) {
|
||||
$this->out->elementStart('li');
|
||||
// Avoid space by using raw output.
|
||||
$pt = '<span class="mark_hash">#</span><a rel="tag" href="' .
|
||||
common_local_url($this->action->trimmed('action'),
|
||||
array('nickname' => $this->owner->nickname,
|
||||
'tag' => $tag)) .
|
||||
'">' . $tag . '</a>';
|
||||
$this->out->raw($pt);
|
||||
$this->out->elementEnd('li');
|
||||
}
|
||||
$this->out->elementEnd('ul');
|
||||
} else {
|
||||
// TRANS: Text if there are no tags in widget to show a list of profiles by tag.
|
||||
$this->out->text(_('(None)'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,9 @@ class SubscriptionsPeopleSelfTagCloudSection extends SubPeopleTagCloudSection
|
||||
|
||||
function query() {
|
||||
// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscriber != subscribed 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 = 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';
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,6 @@ 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';
|
||||
}
|
||||
}
|
||||
|
319
lib/togglepeopletag.php
Normal file
319
lib/togglepeopletag.php
Normal file
@ -0,0 +1,319 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Form for editing 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 Form
|
||||
* @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);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/form.php';
|
||||
|
||||
/**
|
||||
* Form for editing a peopletag
|
||||
*
|
||||
* @category Form
|
||||
* @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/
|
||||
*
|
||||
* @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()
|
||||
{
|
||||
// TRANS: Form legend.
|
||||
$this->out->element('legend', null, sprintf(_('Search and list people')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data elements of the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function formData()
|
||||
{
|
||||
// TRANS: Dropdown option for searching in profiles.
|
||||
$fields = array('fulltext' => _('Everything'),
|
||||
// TRANS: Dropdown option for searching in profiles.
|
||||
'nickname' => _('Nickname'),
|
||||
// TRANS: Dropdown option for searching in profiles.
|
||||
'fullname' => _('Fullname'),
|
||||
// TRANS: Dropdown option for searching in profiles.
|
||||
'description' => _('Description'),
|
||||
// TRANS: Dropdown option for searching in profiles.
|
||||
'location' => _('Location'),
|
||||
// TRANS: Dropdown option for searching in profiles.
|
||||
'uri' => _('URI (Remote users)'));
|
||||
|
||||
|
||||
$this->out->hidden('peopletag_id', $this->peopletag->id);
|
||||
$this->out->input('q', null);
|
||||
// TRANS: Dropdown field label.
|
||||
$this->out->dropdown('field', _m('LABEL','Search in'), $fields,
|
||||
// TRANS: Dropdown field title.
|
||||
_('Choose a field to search.'), false, 'fulltext');
|
||||
}
|
||||
|
||||
/**
|
||||
* Action elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function formActions()
|
||||
{
|
||||
// TRANS: Button text to search profiles.
|
||||
$this->out->submit('submit', _m('BUTTON','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()
|
||||
{
|
||||
// TRANS: Form legend.
|
||||
// TRANS: %1$s is a nickname, $2$s is a people tag.
|
||||
$this->out->element('legend', null, sprintf(_('Untag %1$s as %2$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()
|
||||
{
|
||||
// TRANS: Button text to untag a profile.
|
||||
$this->out->submit('submit', _m('BUTTON','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()
|
||||
{
|
||||
// TRANS: Legend on form to add a tag to a profile.
|
||||
// TRANS: %1$s is a nickname, %2$s ia a people tag.
|
||||
$this->out->element('legend', null, sprintf(_('Tag %1$s as %2$s'),
|
||||
$this->profile->nickname, $this->peopletag->tag));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data elements of the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function formData()
|
||||
{
|
||||
UntagButton::formData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Action elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function formActions()
|
||||
{
|
||||
// TRANS: Button text to tag a profile.
|
||||
$this->out->submit('submit', _m('BUTTON','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');
|
||||
}
|
||||
}
|
108
lib/unsubscribepeopletagform.php
Normal file
108
lib/unsubscribepeopletagform.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Form for unsubscribing 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 Form
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @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);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/form.php';
|
||||
|
||||
/**
|
||||
* Form for unsubscribing to a peopletag
|
||||
*
|
||||
* @category Form
|
||||
* @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/
|
||||
*
|
||||
* @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()
|
||||
{
|
||||
// TRANS: Button text for unsubscribing from a people tag.
|
||||
$this->out->submit('submit', _m('BUTTON','Unsubscribe'));
|
||||
}
|
||||
}
|
10
lib/util.php
10
lib/util.php
@ -754,11 +754,12 @@ function common_find_mentions($text, $notice)
|
||||
foreach ($hmatches[1] as $hmatch) {
|
||||
|
||||
$tag = common_canonical_tag($hmatch[0]);
|
||||
$plist = Profile_list::getByTaggerAndTag($sender->id, $tag);
|
||||
if (!empty($plist) && !$plist->private) {
|
||||
$tagged = $sender->getTaggedSubscribers($tag);
|
||||
|
||||
$tagged = Profile_tag::getTagged($sender->id, $tag);
|
||||
|
||||
$url = common_local_url('subscriptions',
|
||||
array('nickname' => $sender->nickname,
|
||||
$url = common_local_url('showprofiletag',
|
||||
array('tagger' => $sender->nickname,
|
||||
'tag' => $tag));
|
||||
|
||||
$mentions[] = array('mentioned' => $tagged,
|
||||
@ -766,6 +767,7 @@ function common_find_mentions($text, $notice)
|
||||
'position' => $hmatch[1],
|
||||
'url' => $url);
|
||||
}
|
||||
}
|
||||
|
||||
Event::handle('EndFindMentions', array($sender, $text, &$mentions));
|
||||
}
|
||||
|
@ -126,6 +126,8 @@ class BlacklistPlugin extends Plugin
|
||||
} else if (is_string($config)) {
|
||||
return explode("\r\n", $config);
|
||||
} else {
|
||||
// TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
// TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
throw new Exception(sprintf(_m('Unknown data type for config %1$s + %2$s.'),$section, $setting));
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -16,83 +16,85 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: BlacklistPlugin.php:129
|
||||
#. TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
#. TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
#: BlacklistPlugin.php:131
|
||||
#, php-format
|
||||
msgid "Unknown data type for config %1$s + %2$s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Validation failure for URL. %s is the URL.
|
||||
#: BlacklistPlugin.php:149
|
||||
#: BlacklistPlugin.php:151
|
||||
#, php-format
|
||||
msgid "You may not register with homepage \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Validation failure for nickname. %s is the nickname.
|
||||
#: BlacklistPlugin.php:160
|
||||
#: BlacklistPlugin.php:162
|
||||
#, php-format
|
||||
msgid "You may not register with nickname \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Validation failure for URL. %s is the URL.
|
||||
#: BlacklistPlugin.php:185
|
||||
#: BlacklistPlugin.php:187
|
||||
#, php-format
|
||||
msgid "You may not use homepage \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Validation failure for nickname. %s is the nickname.
|
||||
#: BlacklistPlugin.php:196
|
||||
#: BlacklistPlugin.php:198
|
||||
#, php-format
|
||||
msgid "You may not use nickname \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Validation failure for URL. %s is the URL.
|
||||
#: BlacklistPlugin.php:239
|
||||
#: BlacklistPlugin.php:241
|
||||
#, php-format
|
||||
msgid "You may not use URL \"%s\" in notices."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Plugin description.
|
||||
#: BlacklistPlugin.php:344
|
||||
#: BlacklistPlugin.php:346
|
||||
msgid "Keeps a blacklist of forbidden nickname and URL patterns."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Menu item in admin panel.
|
||||
#: BlacklistPlugin.php:382
|
||||
#: BlacklistPlugin.php:384
|
||||
msgctxt "MENU"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Tooltip for menu item in admin panel.
|
||||
#: BlacklistPlugin.php:384
|
||||
#: BlacklistPlugin.php:386
|
||||
msgctxt "TOOLTIP"
|
||||
msgid "Blacklist configuration."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Checkbox label in the blacklist user form.
|
||||
#: BlacklistPlugin.php:411
|
||||
#: BlacklistPlugin.php:413
|
||||
msgid "Add this nickname pattern to blacklist"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Checkbox label in the blacklist user form.
|
||||
#: BlacklistPlugin.php:421
|
||||
#: BlacklistPlugin.php:423
|
||||
msgid "Add this homepage pattern to blacklist"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception thrown trying to post a notice while having set a blocked homepage URL. %s is the blocked URL.
|
||||
#. TRANS: Client exception thrown trying to subscribe to a person with a blocked homepage or site URL. %s is the blocked URL.
|
||||
#: BlacklistPlugin.php:500 BlacklistPlugin.php:535
|
||||
#: BlacklistPlugin.php:502 BlacklistPlugin.php:537
|
||||
#, php-format
|
||||
msgid "Users from \"%s\" are blocked."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception thrown trying to post a notice while having a blocked nickname. %s is the blocked nickname.
|
||||
#: BlacklistPlugin.php:511
|
||||
#: BlacklistPlugin.php:513
|
||||
#, php-format
|
||||
msgid "Notices from nickname \"%s\" disallowed."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception thrown trying to subscribe to a person with a blocked nickname. %s is the blocked nickname.
|
||||
#: BlacklistPlugin.php:546
|
||||
#: BlacklistPlugin.php:548
|
||||
#, php-format
|
||||
msgid "Cannot subscribe to nickname \"%s\"."
|
||||
msgstr ""
|
||||
|
@ -10,19 +10,21 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - Blacklist\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:39+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:12+0000\n"
|
||||
"Language-Team: Belarusian (Taraškievica orthography) <http://translatewiki."
|
||||
"net/wiki/Portal:be-tarask>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-03-18 20:06:03+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:57:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: be-tarask\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-blacklist\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
#. TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
#, php-format
|
||||
msgid "Unknown data type for config %1$s + %2$s."
|
||||
msgstr ""
|
||||
|
@ -9,18 +9,20 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - Blacklist\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:39+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:12+0000\n"
|
||||
"Language-Team: German <http://translatewiki.net/wiki/Portal:de>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-03-18 20:06:03+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:57:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: de\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-blacklist\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
#. TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
#, php-format
|
||||
msgid "Unknown data type for config %1$s + %2$s."
|
||||
msgstr ""
|
||||
|
@ -10,18 +10,20 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - Blacklist\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:39+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:12+0000\n"
|
||||
"Language-Team: French <http://translatewiki.net/wiki/Portal:fr>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-03-18 20:06:03+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:57:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: fr\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-blacklist\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#. TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
#. TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
#, php-format
|
||||
msgid "Unknown data type for config %1$s + %2$s."
|
||||
msgstr ""
|
||||
|
@ -9,21 +9,23 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - Blacklist\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:39+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:12+0000\n"
|
||||
"Language-Team: Interlingua <http://translatewiki.net/wiki/Portal:ia>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-03-18 20:06:03+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:57:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: ia\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-blacklist\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
#. TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
#, php-format
|
||||
msgid "Unknown data type for config %1$s + %2$s."
|
||||
msgstr ""
|
||||
msgstr "Typo de datos incognite pro configuration %1$s + %2$s."
|
||||
|
||||
#. TRANS: Validation failure for URL. %s is the URL.
|
||||
#, php-format
|
||||
@ -61,10 +63,9 @@ msgid "Blacklist"
|
||||
msgstr "Lista nigre"
|
||||
|
||||
#. TRANS: Tooltip for menu item in admin panel.
|
||||
#, fuzzy
|
||||
msgctxt "TOOLTIP"
|
||||
msgid "Blacklist configuration."
|
||||
msgstr "Configuration del lista nigre"
|
||||
msgstr "Configuration del lista nigre."
|
||||
|
||||
#. TRANS: Checkbox label in the blacklist user form.
|
||||
msgid "Add this nickname pattern to blacklist"
|
||||
@ -76,22 +77,21 @@ msgstr "Adder iste patrono de pagina personal al lista nigre"
|
||||
|
||||
#. TRANS: Exception thrown trying to post a notice while having set a blocked homepage URL. %s is the blocked URL.
|
||||
#. TRANS: Client exception thrown trying to subscribe to a person with a blocked homepage or site URL. %s is the blocked URL.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Users from \"%s\" are blocked."
|
||||
msgstr "Usatores de \"%s\" blocate."
|
||||
msgstr "Le usatores de \"%s\" es blocate."
|
||||
|
||||
#. TRANS: Exception thrown trying to post a notice while having a blocked nickname. %s is the blocked nickname.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Notices from nickname \"%s\" disallowed."
|
||||
msgstr "Notas del pseudonymo \"%s\" non permittite."
|
||||
|
||||
#. TRANS: Client exception thrown trying to subscribe to a person with a blocked nickname. %s is the blocked nickname.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Cannot subscribe to nickname \"%s\"."
|
||||
msgstr "Non pote subscriber al pseudonymo \"%s\"."
|
||||
|
||||
#. TRANS: Title of blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgctxt "TITLE"
|
||||
msgid "Blacklist"
|
||||
msgstr "Lista nigre"
|
||||
@ -105,26 +105,22 @@ msgid "Nicknames"
|
||||
msgstr "Pseudonymos"
|
||||
|
||||
#. TRANS: Field title in blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgid "Patterns of nicknames to block, one per line."
|
||||
msgstr "Patronos de pseudonymos a blocar, un per linea"
|
||||
msgstr "Patronos de pseudonymos a blocar, un per linea."
|
||||
|
||||
#. TRANS: Field label in blacklist plugin administration panel.
|
||||
msgid "URLs"
|
||||
msgstr "Adresses URL"
|
||||
|
||||
#. TRANS: Field title in blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgid "Patterns of URLs to block, one per line."
|
||||
msgstr "Patronos de adresses URL a blocar, un per linea"
|
||||
msgstr "Patronos de adresses URL a blocar, un per linea."
|
||||
|
||||
#. TRANS: Button text in blacklist plugin administration panel to save settings.
|
||||
#, fuzzy
|
||||
msgctxt "BUTTON"
|
||||
msgid "Save"
|
||||
msgstr "Salveguardar"
|
||||
|
||||
#. TRANS: Button title in blacklist plugin administration panel to save settings.
|
||||
#, fuzzy
|
||||
msgid "Save site settings."
|
||||
msgstr "Salveguardar configurationes del sito"
|
||||
msgstr "Salveguardar configurationes del sito."
|
||||
|
@ -9,21 +9,23 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - Blacklist\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:39+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:12+0000\n"
|
||||
"Language-Team: Macedonian <http://translatewiki.net/wiki/Portal:mk>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-03-18 20:06:03+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:57:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: mk\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-blacklist\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n == 1 || n%10 == 1) ? 0 : 1;\n"
|
||||
|
||||
#. TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
#. TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
#, php-format
|
||||
msgid "Unknown data type for config %1$s + %2$s."
|
||||
msgstr ""
|
||||
msgstr "Непознат податочен тип за config %1$s + %2$s."
|
||||
|
||||
#. TRANS: Validation failure for URL. %s is the URL.
|
||||
#, php-format
|
||||
@ -60,10 +62,9 @@ msgid "Blacklist"
|
||||
msgstr "Црн список"
|
||||
|
||||
#. TRANS: Tooltip for menu item in admin panel.
|
||||
#, fuzzy
|
||||
msgctxt "TOOLTIP"
|
||||
msgid "Blacklist configuration."
|
||||
msgstr "Поставки за црниот список"
|
||||
msgstr "Поставки за црниот список."
|
||||
|
||||
#. TRANS: Checkbox label in the blacklist user form.
|
||||
msgid "Add this nickname pattern to blacklist"
|
||||
@ -75,22 +76,21 @@ msgstr "Додај го овој вид домашна страница во ц
|
||||
|
||||
#. TRANS: Exception thrown trying to post a notice while having set a blocked homepage URL. %s is the blocked URL.
|
||||
#. TRANS: Client exception thrown trying to subscribe to a person with a blocked homepage or site URL. %s is the blocked URL.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Users from \"%s\" are blocked."
|
||||
msgstr "Корисниците од „%s“ се блокирани."
|
||||
|
||||
#. TRANS: Exception thrown trying to post a notice while having a blocked nickname. %s is the blocked nickname.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Notices from nickname \"%s\" disallowed."
|
||||
msgstr "Објавите од прекарот „%s“ не се дозволени."
|
||||
msgstr "Забелешките од прекарот „%s“ не се дозволени."
|
||||
|
||||
#. TRANS: Client exception thrown trying to subscribe to a person with a blocked nickname. %s is the blocked nickname.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Cannot subscribe to nickname \"%s\"."
|
||||
msgstr "Не можете да се претплатите на прекарот „%s“."
|
||||
|
||||
#. TRANS: Title of blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgctxt "TITLE"
|
||||
msgid "Blacklist"
|
||||
msgstr "Црн список"
|
||||
@ -104,26 +104,22 @@ msgid "Nicknames"
|
||||
msgstr "Прекари"
|
||||
|
||||
#. TRANS: Field title in blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgid "Patterns of nicknames to block, one per line."
|
||||
msgstr "Видови прекари за блокирање, по еден во секој ред"
|
||||
msgstr "Видови прекари за блокирање, по еден во секој ред."
|
||||
|
||||
#. TRANS: Field label in blacklist plugin administration panel.
|
||||
msgid "URLs"
|
||||
msgstr "URL-адреси"
|
||||
|
||||
#. TRANS: Field title in blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgid "Patterns of URLs to block, one per line."
|
||||
msgstr "Видови URL-адреси за блокирање, по една во секој ред"
|
||||
msgstr "Видови URL-адреси за блокирање, по една во секој ред."
|
||||
|
||||
#. TRANS: Button text in blacklist plugin administration panel to save settings.
|
||||
#, fuzzy
|
||||
msgctxt "BUTTON"
|
||||
msgid "Save"
|
||||
msgstr "Зачувај"
|
||||
|
||||
#. TRANS: Button title in blacklist plugin administration panel to save settings.
|
||||
#, fuzzy
|
||||
msgid "Save site settings."
|
||||
msgstr "Зачувај поставки на мреж. место"
|
||||
msgstr "Зачувај поставки на мреж. место."
|
||||
|
@ -9,21 +9,23 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - Blacklist\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:39+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:12+0000\n"
|
||||
"Language-Team: Dutch <http://translatewiki.net/wiki/Portal:nl>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-03-18 20:06:03+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:57:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: nl\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-blacklist\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
#. TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
#, php-format
|
||||
msgid "Unknown data type for config %1$s + %2$s."
|
||||
msgstr ""
|
||||
msgstr "Onbekend gegevenstype voor instelling %1$s + %2$s."
|
||||
|
||||
#. TRANS: Validation failure for URL. %s is the URL.
|
||||
#, php-format
|
||||
@ -60,10 +62,9 @@ msgid "Blacklist"
|
||||
msgstr "Zwarte lijst"
|
||||
|
||||
#. TRANS: Tooltip for menu item in admin panel.
|
||||
#, fuzzy
|
||||
msgctxt "TOOLTIP"
|
||||
msgid "Blacklist configuration."
|
||||
msgstr "Instellingen voor zwarte lijst"
|
||||
msgstr "Instellingen voor zwarte lijst."
|
||||
|
||||
#. TRANS: Checkbox label in the blacklist user form.
|
||||
msgid "Add this nickname pattern to blacklist"
|
||||
@ -75,22 +76,21 @@ msgstr "Dit homepagepatroon aan de zwarte lijst toevoegen"
|
||||
|
||||
#. TRANS: Exception thrown trying to post a notice while having set a blocked homepage URL. %s is the blocked URL.
|
||||
#. TRANS: Client exception thrown trying to subscribe to a person with a blocked homepage or site URL. %s is the blocked URL.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Users from \"%s\" are blocked."
|
||||
msgstr "Gebruikers van \"%s\" zijn geblokkeerd."
|
||||
|
||||
#. TRANS: Exception thrown trying to post a notice while having a blocked nickname. %s is the blocked nickname.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Notices from nickname \"%s\" disallowed."
|
||||
msgstr "Gebruiker \"%s\" mag geen berichten plaatsen."
|
||||
|
||||
#. TRANS: Client exception thrown trying to subscribe to a person with a blocked nickname. %s is the blocked nickname.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Cannot subscribe to nickname \"%s\"."
|
||||
msgstr "U kunt niet abonneren op de gebruiker \"%s\"."
|
||||
|
||||
#. TRANS: Title of blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgctxt "TITLE"
|
||||
msgid "Blacklist"
|
||||
msgstr "Zwarte lijst"
|
||||
@ -104,7 +104,6 @@ msgid "Nicknames"
|
||||
msgstr "Gebruikersnamen"
|
||||
|
||||
#. TRANS: Field title in blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgid "Patterns of nicknames to block, one per line."
|
||||
msgstr "Patronen van te blokkeren gebruikersnamen. Eén per regel."
|
||||
|
||||
@ -113,17 +112,14 @@ msgid "URLs"
|
||||
msgstr "URL's"
|
||||
|
||||
#. TRANS: Field title in blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgid "Patterns of URLs to block, one per line."
|
||||
msgstr "Patronen van te blokkeren URL's. Eén per regel."
|
||||
|
||||
#. TRANS: Button text in blacklist plugin administration panel to save settings.
|
||||
#, fuzzy
|
||||
msgctxt "BUTTON"
|
||||
msgid "Save"
|
||||
msgstr "Opslaan"
|
||||
|
||||
#. TRANS: Button title in blacklist plugin administration panel to save settings.
|
||||
#, fuzzy
|
||||
msgid "Save site settings."
|
||||
msgstr "Websiteinstellingen opslaan"
|
||||
msgstr "Websiteinstellingen opslaan."
|
||||
|
@ -10,19 +10,21 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - Blacklist\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:39+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:12+0000\n"
|
||||
"Language-Team: Russian <http://translatewiki.net/wiki/Portal:ru>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-03-18 20:06:03+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:57:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: ru\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-blacklist\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10 == 1 && n%100 != 11) ? 0 : ( (n%10 >= "
|
||||
"2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20)) ? 1 : 2 );\n"
|
||||
|
||||
#. TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
#. TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
#, php-format
|
||||
msgid "Unknown data type for config %1$s + %2$s."
|
||||
msgstr ""
|
||||
|
@ -9,18 +9,20 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - Blacklist\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:39+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:12+0000\n"
|
||||
"Language-Team: Tagalog <http://translatewiki.net/wiki/Portal:tl>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-03-18 20:06:03+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:57:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: tl\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-blacklist\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
#. TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
#, php-format
|
||||
msgid "Unknown data type for config %1$s + %2$s."
|
||||
msgstr ""
|
||||
|
@ -9,22 +9,24 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - Blacklist\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:39+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:12+0000\n"
|
||||
"Language-Team: Ukrainian <http://translatewiki.net/wiki/Portal:uk>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-03-18 20:06:03+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:57:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: uk\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-blacklist\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10 == 1 && n%100 != 11) ? 0 : ( (n%10 >= "
|
||||
"2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20)) ? 1 : 2 );\n"
|
||||
|
||||
#. TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
#. TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
#, php-format
|
||||
msgid "Unknown data type for config %1$s + %2$s."
|
||||
msgstr ""
|
||||
msgstr "Невідомий тип даних для конфігурації %1$s + %2$s."
|
||||
|
||||
#. TRANS: Validation failure for URL. %s is the URL.
|
||||
#, php-format
|
||||
@ -61,10 +63,9 @@ msgid "Blacklist"
|
||||
msgstr "Чорний список"
|
||||
|
||||
#. TRANS: Tooltip for menu item in admin panel.
|
||||
#, fuzzy
|
||||
msgctxt "TOOLTIP"
|
||||
msgid "Blacklist configuration."
|
||||
msgstr "Конфігурація чорного списку"
|
||||
msgstr "Конфігурація чорного списку."
|
||||
|
||||
#. TRANS: Checkbox label in the blacklist user form.
|
||||
msgid "Add this nickname pattern to blacklist"
|
||||
@ -76,22 +77,21 @@ msgstr "Додати цей шаблон веб-адреси до чорного
|
||||
|
||||
#. TRANS: Exception thrown trying to post a notice while having set a blocked homepage URL. %s is the blocked URL.
|
||||
#. TRANS: Client exception thrown trying to subscribe to a person with a blocked homepage or site URL. %s is the blocked URL.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Users from \"%s\" are blocked."
|
||||
msgstr "Користувачів з «%s» заблоковано."
|
||||
|
||||
#. TRANS: Exception thrown trying to post a notice while having a blocked nickname. %s is the blocked nickname.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Notices from nickname \"%s\" disallowed."
|
||||
msgstr "Дописи від користувача «%s» заборонені."
|
||||
|
||||
#. TRANS: Client exception thrown trying to subscribe to a person with a blocked nickname. %s is the blocked nickname.
|
||||
#, fuzzy, php-format
|
||||
#, php-format
|
||||
msgid "Cannot subscribe to nickname \"%s\"."
|
||||
msgstr "Не можу підписатися до користувача «%s»."
|
||||
|
||||
#. TRANS: Title of blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgctxt "TITLE"
|
||||
msgid "Blacklist"
|
||||
msgstr "Чорний список"
|
||||
@ -105,26 +105,22 @@ msgid "Nicknames"
|
||||
msgstr "Нікнейми"
|
||||
|
||||
#. TRANS: Field title in blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgid "Patterns of nicknames to block, one per line."
|
||||
msgstr "Шаблони нікнеймів, котрі будуть блокуватися (по одному на рядок)"
|
||||
msgstr "Шаблони псевдонімів, котрі будуть блокуватися (по одному на рядок)."
|
||||
|
||||
#. TRANS: Field label in blacklist plugin administration panel.
|
||||
msgid "URLs"
|
||||
msgstr "URL-адреси"
|
||||
|
||||
#. TRANS: Field title in blacklist plugin administration panel.
|
||||
#, fuzzy
|
||||
msgid "Patterns of URLs to block, one per line."
|
||||
msgstr "Шаблони URL-адрес, котрі будуть блокуватися (по одному на рядок)"
|
||||
msgstr "Шаблони URL-адрес, котрі будуть блокуватися (по одному на рядок)."
|
||||
|
||||
#. TRANS: Button text in blacklist plugin administration panel to save settings.
|
||||
#, fuzzy
|
||||
msgctxt "BUTTON"
|
||||
msgid "Save"
|
||||
msgstr "Зберегти"
|
||||
|
||||
#. TRANS: Button title in blacklist plugin administration panel to save settings.
|
||||
#, fuzzy
|
||||
msgid "Save site settings."
|
||||
msgstr "Зберегти налаштування сайту"
|
||||
msgstr "Зберегти налаштування сайту."
|
||||
|
@ -10,19 +10,21 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - Blacklist\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:39+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:12+0000\n"
|
||||
"Language-Team: Simplified Chinese <http://translatewiki.net/wiki/Portal:zh-"
|
||||
"hans>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-03-18 20:06:03+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:57:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: zh-hans\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-blacklist\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#. TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
|
||||
#. TRANS: %1$s is a configuration section, %2$s is a configuration setting.
|
||||
#, php-format
|
||||
msgid "Unknown data type for config %1$s + %2$s."
|
||||
msgstr ""
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -20,7 +20,7 @@ msgstr ""
|
||||
#. TRANS: %1$s is the StatusNet sitename, %2$s is the recipient's profile name.
|
||||
#: useremailsummaryhandler.php:129
|
||||
#, php-format
|
||||
msgid "Recent updates from %1$s for %2s:"
|
||||
msgid "Recent updates from %1$s for %2$s:"
|
||||
msgstr ""
|
||||
|
||||
#: useremailsummaryhandler.php:184
|
||||
|
@ -9,13 +9,13 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - EmailSummary\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:57+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:30+0000\n"
|
||||
"Language-Team: Catalan <http://translatewiki.net/wiki/Portal:ca>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-04-03 13:40:27+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:58:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: ca\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-emailsummary\n"
|
||||
@ -24,7 +24,7 @@ msgstr ""
|
||||
#. TRANS: Text in e-mail summary.
|
||||
#. TRANS: %1$s is the StatusNet sitename, %2$s is the recipient's profile name.
|
||||
#, php-format
|
||||
msgid "Recent updates from %1$s for %2s:"
|
||||
msgid "Recent updates from %1$s for %2$s:"
|
||||
msgstr ""
|
||||
|
||||
msgid "in context"
|
||||
|
@ -9,13 +9,13 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - EmailSummary\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-04-09 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-04-09 18:36:57+0000\n"
|
||||
"POT-Creation-Date: 2011-04-10 08:14+0000\n"
|
||||
"PO-Revision-Date: 2011-04-10 08:17:30+0000\n"
|
||||
"Language-Team: Interlingua <http://translatewiki.net/wiki/Portal:ia>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-04-03 13:40:27+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85732); Translate extension (2011-03-11)\n"
|
||||
"X-POT-Import-Date: 2011-04-09 18:58:40+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r85733); Translate extension (2011-03-11)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: ia\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-emailsummary\n"
|
||||
@ -24,8 +24,8 @@ msgstr ""
|
||||
#. TRANS: Text in e-mail summary.
|
||||
#. TRANS: %1$s is the StatusNet sitename, %2$s is the recipient's profile name.
|
||||
#, fuzzy, php-format
|
||||
msgid "Recent updates from %1$s for %2s:"
|
||||
msgstr "Actualisationes recente de %1s pro %2s:"
|
||||
msgid "Recent updates from %1$s for %2$s:"
|
||||
msgstr "Actualisationes recente de %1$s pro %2s:"
|
||||
|
||||
msgid "in context"
|
||||
msgstr "in contexto"
|
||||
@ -43,6 +43,5 @@ msgid "Send an email summary of the inbox to users."
|
||||
msgstr "Inviar in e-mail un summario del cassa de entrata al usatores."
|
||||
|
||||
#. TRANS: Checkbox label in e-mail preferences form.
|
||||
#, fuzzy
|
||||
msgid "Send me a periodic summary of updates from my network"
|
||||
msgstr "Inviar me un summario periodic del actualisationes de mi rete."
|
||||
msgstr "Inviar me un summario periodic del actualisationes de mi rete"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user