git.gnu.io has moved to IP address 209.51.188.249 -- please double check where you are logging in.

Commit 78cec7ab authored by Evan Prodromou's avatar Evan Prodromou

Merge branch '0.9.x' of git@gitorious.org:statusnet/mainline into 0.9.x

Conflicts:
	install.php
	lib/noticeform.php
parents 8284b3cb 49bce941
......@@ -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');
}
......
......@@ -90,7 +90,7 @@ class NoticeForm extends Form
$this->action = $action;
$this->content = $content;
$this->inreplyto = $inreplyto;
if ($user) {
$this->user = $user;
} else {
......
......@@ -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";
}
}
......
......@@ -4,34 +4,19 @@
var MeteorUpdater = function()
{
return {
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);
}
};
Meteor.host = server;
Meteor.port = port;
Meteor.joinChannel(timeline, 0);
Meteor.connect();
}
}
return {
init: function(server, port, timeline)
{
Meteor.callbacks["process"] = function(data) {
RealtimeUpdate.receive(JSON.parse(data));
};
Meteor.host = server;
Meteor.port = port;
Meteor.joinChannel(timeline, 0);
Meteor.connect();
}
}
}();
......@@ -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');
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);
} else {
return true;
}
break;
default:
return true;
// If there's not a timeline on this page,
// just return true
if (empty($timeline)) {
return true;
}
$timeline = $this->_pathToChannel($path);
$base = $action->selfUrl();
if (mb_strstr($base, '?')) {
$url = $base . '&realtime=1';
} else {
$url = $base . '?realtime=1';
}
$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;
}
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment