forked from GNUsocial/gnu-social
Merge branch '0.9.x' of git@gitorious.org:statusnet/mainline into 0.9.x
Conflicts: install.php lib/noticeform.php
This commit is contained in:
commit
78cec7ab87
12
EVENTS.txt
12
EVENTS.txt
@ -170,12 +170,6 @@ StartShowBody: called before showing the <body> element and children
|
||||
EndShowBody: called after showing the <body> element (and </body>)
|
||||
- $action: action object being shown
|
||||
|
||||
StartHeadChildren: called before showing the children of <head> element (after <head> tag)
|
||||
- $action: action object being shown
|
||||
|
||||
EndHeadChildren: called after showing the children of <head> element (before </head>)
|
||||
- $action: action object being shown
|
||||
|
||||
StartPersonalGroupNav: beginning of personal group nav menu
|
||||
- $action: action object being shown
|
||||
|
||||
@ -271,3 +265,9 @@ GetValidDaemons: Just before determining which daemons to run
|
||||
|
||||
HandleQueuedNotice: Handle a queued notice at queue time (or immediately if no queue)
|
||||
- &$notice: notice to handle
|
||||
|
||||
StartShowHeadElements: Right after the <head> tag
|
||||
- $action: the current action
|
||||
|
||||
EndShowHeadElements: Right before the </head> tag; put <script>s here if you need them in <head>
|
||||
- $action: the current action
|
||||
|
@ -293,6 +293,105 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
|
||||
}
|
||||
}
|
||||
|
||||
function join($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
common_debug("in groups api action");
|
||||
|
||||
$this->auth_user = $apidata['user'];
|
||||
$group = $this->get_group($apidata['api_arg'], $apidata);
|
||||
|
||||
if (empty($group)) {
|
||||
$this->clientError('Not Found', 404, $apidata['content-type']);
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->auth_user->isMember($group)){
|
||||
$this->clientError(_('You are already a member of that group'), $code = 403);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Group_block::isBlocked($group, $this->auth_user->getProfile())) {
|
||||
$this->clientError(_('You have been blocked from that group by the admin.'), 403);
|
||||
return false;
|
||||
}
|
||||
|
||||
$member = new Group_member();
|
||||
|
||||
$member->group_id = $group->id;
|
||||
$member->profile_id = $this->auth_user->id;
|
||||
$member->created = common_sql_now();
|
||||
|
||||
$result = $member->insert();
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($member, 'INSERT', __FILE__);
|
||||
$this->serverError(sprintf(_('Could not join user %s to group %s'),
|
||||
$this->auth_user->nickname, $group->nickname));
|
||||
}
|
||||
|
||||
switch($apidata['content-type']) {
|
||||
case 'xml':
|
||||
$this->show_single_xml_group($group);
|
||||
break;
|
||||
case 'json':
|
||||
$this->show_single_json_group($group);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(_('API method not found!'), $code = 404);
|
||||
}
|
||||
}
|
||||
|
||||
function leave($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
common_debug("in groups api action");
|
||||
|
||||
$this->auth_user = $apidata['user'];
|
||||
$group = $this->get_group($apidata['api_arg'], $apidata);
|
||||
|
||||
if (empty($group)) {
|
||||
$this->clientError('Not Found', 404, $apidata['content-type']);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(! $this->auth_user->isMember($group)){
|
||||
$this->clientError(_('You are not a member of that group'), $code = 403);
|
||||
return false;
|
||||
}
|
||||
|
||||
$member = new Group_member();
|
||||
|
||||
$member->group_id = $group->id;
|
||||
$member->profile_id = $this->auth_user->id;
|
||||
|
||||
if (!$member->find(true)) {
|
||||
$this->serverError(_('Could not find membership record.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$result = $member->delete();
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($member, 'INSERT', __FILE__);
|
||||
$this->serverError(sprintf(_('Could not remove user %s to group %s'),
|
||||
$this->auth_user->nickname, $group->nickname));
|
||||
}
|
||||
|
||||
switch($apidata['content-type']) {
|
||||
case 'xml':
|
||||
$this->show_single_xml_group($group);
|
||||
break;
|
||||
case 'json':
|
||||
$this->show_single_json_group($group);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(_('API method not found!'), $code = 404);
|
||||
}
|
||||
}
|
||||
|
||||
function is_member($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
@ -326,4 +425,29 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
|
||||
$this->clientError(_('API method not found!'), $code = 404);
|
||||
}
|
||||
}
|
||||
|
||||
function create($args, $apidata)
|
||||
{
|
||||
die("todo");
|
||||
}
|
||||
|
||||
function update($args, $apidata)
|
||||
{
|
||||
die("todo");
|
||||
}
|
||||
|
||||
function update_group_logo($args, $apidata)
|
||||
{
|
||||
die("todo");
|
||||
}
|
||||
|
||||
function destroy($args, $apidata)
|
||||
{
|
||||
die("todo");
|
||||
}
|
||||
|
||||
function tag($args, $apidata)
|
||||
{
|
||||
die("todo");
|
||||
}
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ function main()
|
||||
*/
|
||||
function haveExternalLibrary($external_library)
|
||||
{
|
||||
if (isset($external_library['include']) && ! @include_once $external_library['include'] ) {
|
||||
if (isset($external_library['include']) && !haveIncludeFile($external_library['include'])) {
|
||||
return false;
|
||||
}
|
||||
if (isset($external_library['check_function']) && ! function_exists($external_library['check_function'])) {
|
||||
|
@ -120,16 +120,15 @@ class Action extends HTMLOutputter // lawsuit
|
||||
{
|
||||
// XXX: attributes (profile?)
|
||||
$this->elementStart('head');
|
||||
if (Event::handle('StartHeadChildren', array($this))) {
|
||||
if (Event::handle('StartShowHeadElements', array($this))) {
|
||||
$this->showTitle();
|
||||
$this->showShortcutIcon();
|
||||
$this->showStylesheets();
|
||||
$this->showScripts();
|
||||
$this->showOpenSearch();
|
||||
$this->showFeeds();
|
||||
$this->showDescription();
|
||||
$this->extraHead();
|
||||
Event::handle('EndHeadChildren', array($this));
|
||||
Event::handle('EndShowHeadElements', array($this));
|
||||
}
|
||||
$this->elementEnd('head');
|
||||
}
|
||||
@ -355,6 +354,7 @@ class Action extends HTMLOutputter // lawsuit
|
||||
Event::handle('EndShowFooter', array($this));
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
$this->showScripts();
|
||||
$this->elementEnd('body');
|
||||
}
|
||||
|
||||
|
@ -47,10 +47,48 @@ class AutocompleteAction extends Action
|
||||
{
|
||||
private $result;
|
||||
|
||||
/**
|
||||
* Last-modified date for page
|
||||
*
|
||||
* When was the content of this page last modified? Based on notice,
|
||||
* profile, avatar.
|
||||
*
|
||||
* @return int last-modified date as unix timestamp
|
||||
*/
|
||||
function lastModified()
|
||||
{
|
||||
$max=0;
|
||||
foreach($this->users as $user){
|
||||
$max = max($max,strtotime($user->modified),strtotime($user->profile->modified));
|
||||
}
|
||||
foreach($this->groups as $group){
|
||||
$max = max($max,strtotime($group->modified));
|
||||
}
|
||||
return $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity tag for this page
|
||||
*
|
||||
* Shows the ETag for the page, based on the notice ID and timestamps
|
||||
* for the notice, profile, and avatar. It's weak, since we change
|
||||
* the date text "one hour ago", etc.
|
||||
*
|
||||
* @return string etag
|
||||
*/
|
||||
function etag()
|
||||
{
|
||||
return '"' . implode(':', array($this->arg('action'),
|
||||
crc32($this->arg('q')), //the actual string can have funny characters in we don't want showing up in the etag
|
||||
$this->arg('limit'),
|
||||
$this->lastModified())) . '"';
|
||||
}
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
$this->results = array();
|
||||
$this->groups=array();
|
||||
$this->users=array();
|
||||
$q = $this->arg('q');
|
||||
$limit = $this->arg('limit');
|
||||
if($limit > 200) $limit=200; //prevent DOS attacks
|
||||
@ -63,7 +101,8 @@ class AutocompleteAction extends Action
|
||||
$user->find();
|
||||
while($user->fetch()) {
|
||||
$profile = Profile::staticGet($user->id);
|
||||
$this->results[]=array('nickname' => $user->nickname, 'fullname'=> $profile->fullname, 'type'=>'user');
|
||||
$user->profile=$profile;
|
||||
$this->users[]=$user;
|
||||
}
|
||||
}
|
||||
if(substr($q,0,1)=='!'){
|
||||
@ -74,7 +113,7 @@ class AutocompleteAction extends Action
|
||||
$group->whereAdd('nickname like \'' . trim($group->escape($q), '\'') . '%\'');
|
||||
$group->find();
|
||||
while($group->fetch()) {
|
||||
$this->results[]=array('nickname' => $group->nickname, 'fullname'=> $group->fullname, 'type'=>'group');
|
||||
$this->groups[]=$group;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -83,7 +122,14 @@ class AutocompleteAction extends Action
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
foreach($this->results as $result) {
|
||||
$results = array();
|
||||
foreach($this->users as $user){
|
||||
$results[]=array('nickname' => $user->nickname, 'fullname'=> $user->profile->fullname, 'type'=>'user');
|
||||
}
|
||||
foreach($this->groups as $group){
|
||||
$results[]=array('nickname' => $group->nickname, 'fullname'=> $group->fullname, 'type'=>'group');
|
||||
}
|
||||
foreach($results as $result) {
|
||||
print json_encode($result) . "\n";
|
||||
}
|
||||
}
|
||||
|
@ -9,22 +9,7 @@ var MeteorUpdater = function()
|
||||
init: function(server, port, timeline)
|
||||
{
|
||||
Meteor.callbacks["process"] = function(data) {
|
||||
var d = JSON.parse(data);
|
||||
|
||||
var user_url = $('address .url')[0].href+d['user']['screen_name'];
|
||||
|
||||
var wlh = window.location.href;
|
||||
|
||||
if (wlh.indexOf('?') > 0) {
|
||||
wlh = wlh.slice(0, wlh.indexOf('?'))
|
||||
}
|
||||
|
||||
if (timeline == 'public' ||
|
||||
user_url+'/all' == wlh ||
|
||||
user_url == wlh) {
|
||||
|
||||
RealtimeUpdate.receive(d);
|
||||
}
|
||||
RealtimeUpdate.receive(JSON.parse(data));
|
||||
};
|
||||
|
||||
Meteor.host = server;
|
||||
|
@ -73,7 +73,7 @@ class PiwikAnalyticsPlugin extends Plugin
|
||||
function __construct($root=null, $id=null)
|
||||
{
|
||||
$this->piwikroot = $root;
|
||||
$this->piwikid = $id;
|
||||
$this->piwikId = $id;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,11 @@ class RealtimePlugin extends Plugin
|
||||
protected $favorurl = null;
|
||||
protected $deleteurl = null;
|
||||
|
||||
/**
|
||||
* When it's time to initialize the plugin, calculate and
|
||||
* pass the URLs we need.
|
||||
*/
|
||||
|
||||
function onInitializePlugin()
|
||||
{
|
||||
$this->replyurl = common_local_url('newnotice');
|
||||
@ -57,31 +62,26 @@ class RealtimePlugin extends Plugin
|
||||
// FIXME: need to find a better way to pass this pattern in
|
||||
$this->deleteurl = common_local_url('deletenotice',
|
||||
array('notice' => '0000000000'));
|
||||
return true;
|
||||
}
|
||||
|
||||
function onEndShowScripts($action)
|
||||
{
|
||||
$path = null;
|
||||
$timeline = $this->_getTimeline($action);
|
||||
|
||||
$a = $action->trimmed('action');
|
||||
// If there's not a timeline on this page,
|
||||
// just return true
|
||||
|
||||
switch ($a) {
|
||||
case 'public': case 'all': case 'replies': case 'showstream':
|
||||
$path = array($a);
|
||||
break;
|
||||
case 'tag':
|
||||
$tag = $action->trimmed('tag');
|
||||
if (!empty($tag)) {
|
||||
$path = array('tag', $tag);
|
||||
if (empty($timeline)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$base = $action->selfUrl();
|
||||
if (mb_strstr($base, '?')) {
|
||||
$url = $base . '&realtime=1';
|
||||
} else {
|
||||
return true;
|
||||
$url = $base . '?realtime=1';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
$timeline = $this->_pathToChannel($path);
|
||||
|
||||
$scripts = $this->_getScripts();
|
||||
|
||||
@ -97,16 +97,22 @@ class RealtimePlugin extends Plugin
|
||||
$user_id = 0;
|
||||
}
|
||||
|
||||
$action->script('plugins/Realtime/jquery.getUrlParam.js');
|
||||
if ($action->boolean('realtime')) {
|
||||
$realtimeUI = ' RealtimeUpdate.initPopupWindow();';
|
||||
}
|
||||
else {
|
||||
$iconurl = common_path('plugins/Realtime/icon_external.gif');
|
||||
$realtimeUI = ' RealtimeUpdate.addPopup("'.$url.'", "'.$timeline.'", "'. $iconurl .'");';
|
||||
}
|
||||
|
||||
$action->elementStart('script', array('type' => 'text/javascript'));
|
||||
$action->raw('
|
||||
<!--
|
||||
$(document).ready(function() {
|
||||
' . $this->_updateInitialize($timeline, $user_id) . '
|
||||
});
|
||||
-->
|
||||
');
|
||||
|
||||
$script = ' $(document).ready(function() { '.
|
||||
$realtimeUI.
|
||||
$this->_updateInitialize($timeline, $user_id).
|
||||
'}); ';
|
||||
$action->raw($script);
|
||||
|
||||
$action->elementEnd('script');
|
||||
|
||||
return true;
|
||||
@ -116,15 +122,23 @@ class RealtimePlugin extends Plugin
|
||||
{
|
||||
$paths = array();
|
||||
|
||||
// TODO: Replies timeline
|
||||
// Add to the author's timeline
|
||||
|
||||
$user = User::staticGet('id', $notice->profile_id);
|
||||
|
||||
if (!empty($user)) {
|
||||
$paths[] = array('showstream', $user->nickname);
|
||||
}
|
||||
|
||||
// Add to the public timeline
|
||||
|
||||
if ($notice->is_local ||
|
||||
($notice->is_local == 0 && !common_config('public', 'localonly'))) {
|
||||
foreach (array('public', 'all', 'replies', 'showstream') as $a) {
|
||||
$paths[] = array($a);
|
||||
}
|
||||
$paths[] = array('public');
|
||||
}
|
||||
|
||||
// Add to the tags timeline
|
||||
|
||||
$tags = $this->getNoticeTags($notice);
|
||||
|
||||
if (!empty($tags)) {
|
||||
@ -133,6 +147,46 @@ class RealtimePlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
// Add to inbox timelines
|
||||
// XXX: do a join
|
||||
|
||||
$inbox = new Notice_inbox();
|
||||
$inbox->notice_id = $notice->id;
|
||||
|
||||
if ($inbox->find()) {
|
||||
while ($inbox->fetch()) {
|
||||
$user = User::staticGet('id', $inbox->user_id);
|
||||
$paths[] = array('all', $user->nickname);
|
||||
}
|
||||
}
|
||||
|
||||
// Add to the replies timeline
|
||||
|
||||
$reply = new Reply();
|
||||
$reply->notice_id = $notice->id;
|
||||
|
||||
if ($reply->find()) {
|
||||
while ($reply->fetch()) {
|
||||
$user = User::staticGet('id', $reply->profile_id);
|
||||
if (!empty($user)) {
|
||||
$paths[] = array('replies', $user->nickname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add to the group timeline
|
||||
// XXX: join
|
||||
|
||||
$gi = new Group_inbox();
|
||||
$gi->notice_id = $notice->id;
|
||||
|
||||
if ($gi->find()) {
|
||||
while ($gi->fetch()) {
|
||||
$ug = User_group::staticGet('id', $gi->group_id);
|
||||
$paths[] = array('showgroup', $ug->nickname);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($paths) > 0) {
|
||||
|
||||
$json = $this->noticeAsJson($notice);
|
||||
@ -150,6 +204,39 @@ class RealtimePlugin extends Plugin
|
||||
return true;
|
||||
}
|
||||
|
||||
function onStartShowBody($action)
|
||||
{
|
||||
$realtime = $action->boolean('realtime');
|
||||
if (!$realtime) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$action->elementStart('body',
|
||||
(common_current_user()) ? array('id' => $action->trimmed('action'),
|
||||
'class' => 'user_in')
|
||||
: array('id' => $action->trimmed('action')));
|
||||
|
||||
$action->elementStart('div', array('id' => 'header'));
|
||||
|
||||
// XXX hack to deal with JS that tries to get the
|
||||
// root url from page output
|
||||
|
||||
$action->elementStart('address');
|
||||
$action->element('a', array('class' => 'url',
|
||||
'href' => common_local_url('public')),
|
||||
'');
|
||||
$action->elementEnd('address');
|
||||
|
||||
if (common_logged_in()) {
|
||||
$action->showNoticeForm();
|
||||
}
|
||||
$action->elementEnd('div');
|
||||
|
||||
$action->showContentBlock();
|
||||
$action->elementEnd('body');
|
||||
return false; // No default processing
|
||||
}
|
||||
|
||||
function noticeAsJson($notice)
|
||||
{
|
||||
// FIXME: this code should be abstracted to a neutral third
|
||||
@ -234,4 +321,41 @@ class RealtimePlugin extends Plugin
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
function _getTimeline($action)
|
||||
{
|
||||
$path = null;
|
||||
$timeline = null;
|
||||
|
||||
$action_name = $action->trimmed('action');
|
||||
|
||||
switch ($action_name) {
|
||||
case 'public':
|
||||
$path = array('public');
|
||||
break;
|
||||
case 'tag':
|
||||
$tag = $action->trimmed('tag');
|
||||
if (!empty($tag)) {
|
||||
$path = array('tag', $tag);
|
||||
}
|
||||
break;
|
||||
case 'showstream':
|
||||
case 'all':
|
||||
case 'replies':
|
||||
case 'showgroup':
|
||||
$nickname = common_canonical_nickname($action->trimmed('nickname'));
|
||||
if (!empty($nickname)) {
|
||||
$path = array($action_name, $nickname);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($path)) {
|
||||
$timeline = $this->_pathToChannel($path);
|
||||
}
|
||||
|
||||
return $timeline;
|
||||
}
|
||||
}
|
||||
|
@ -1,39 +1,3 @@
|
||||
$(document).ready(function() {
|
||||
if (!$(document).getUrlParam('realtime')) {
|
||||
$('#site_nav_local_views .current a').append('<button id="realtime_timeline" title="Pop this tab">↗</button>');
|
||||
|
||||
$('#realtime_timeline').css({
|
||||
'margin':'2px 0 0 11px',
|
||||
'background':'transparent url('+$('address .url')[0].href+'/plugins/Realtime/icon_external.gif) no-repeat 45% 45%',
|
||||
'text-indent':'-9999px',
|
||||
'width':'16px',
|
||||
'height':'16px',
|
||||
'padding':'0',
|
||||
'display':'block',
|
||||
'float':'right',
|
||||
'border':'none',
|
||||
'cursor':'pointer'
|
||||
});
|
||||
|
||||
$('#realtime_timeline').click(function() {
|
||||
window.open($(this).parent('a').attr('href')+'?realtime=1',
|
||||
$(this).parent('a').attr('title'),
|
||||
'toolbar=no,resizable=yes,scrollbars=yes,status=yes');
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
else {
|
||||
window.resizeTo(575, 640);
|
||||
address = $('address');
|
||||
content = $('#content');
|
||||
$('body').html(address);
|
||||
$('address').hide();
|
||||
$('body').append(content);
|
||||
$('#content').css({'width':'92%'});
|
||||
}
|
||||
|
||||
|
||||
// add a notice encoded as JSON into the current timeline
|
||||
//
|
||||
// TODO: i18n
|
||||
@ -57,7 +21,7 @@ $(document).ready(function() {
|
||||
id = data.id;
|
||||
|
||||
// Don't add it if it already exists
|
||||
|
||||
//
|
||||
if ($("#notice-"+id).length > 0) {
|
||||
return;
|
||||
}
|
||||
@ -145,8 +109,39 @@ $(document).ready(function() {
|
||||
dl = "<a class=\"notice_delete\" href=\""+delurl+"\" title=\"Delete this notice\">Delete</a>";
|
||||
|
||||
return dl;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addPopup: function(url, timeline, iconurl)
|
||||
{
|
||||
$('#site_nav_local_views .current a').append('<button id="realtime_timeline" title="Real-time pop window">↗</button>');
|
||||
|
||||
$('#realtime_timeline').css({
|
||||
'margin':'2px 0 0 11px',
|
||||
'background':'transparent url('+ iconurl + ') no-repeat 45% 45%',
|
||||
'text-indent':'-9999px',
|
||||
'width':'16px',
|
||||
'height':'16px',
|
||||
'padding':'0',
|
||||
'display':'block',
|
||||
'float':'right',
|
||||
'border':'none',
|
||||
'cursor':'pointer'
|
||||
});
|
||||
|
||||
$('#realtime_timeline').click(function() {
|
||||
window.open(url,
|
||||
timeline,
|
||||
'toolbar=no,resizable=yes,scrollbars=yes,status=yes');
|
||||
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
initPopupWindow: function()
|
||||
{
|
||||
window.resizeTo(575, 640);
|
||||
$('address').hide();
|
||||
$('#content').css({'width':'92%'});
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user