summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorEvan Prodromou <evan@status.net>2009-09-24 17:22:51 -0400
committerEvan Prodromou <evan@status.net>2009-09-24 17:22:51 -0400
commit78cec7ab87c005e988dbd8176585ffad9182d25c (patch)
tree735c4755433140939e6b841f971a273c6a2f76f8 /plugins
parent8284b3cb82f4dec6e0f2bf74dea6e1a3bc7f4eac (diff)
parent49bce941a9aae495ee7221bd367791227487b458 (diff)
Merge branch '0.9.x' of git@gitorious.org:statusnet/mainline into 0.9.x
Conflicts: install.php lib/noticeform.php
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Autocomplete/autocomplete.php54
-rw-r--r--plugins/Meteor/meteorupdater.js43
-rw-r--r--plugins/PiwikAnalyticsPlugin.php2
-rw-r--r--plugins/Realtime/RealtimePlugin.php184
-rw-r--r--plugins/Realtime/realtimeupdate.js273
5 files changed, 353 insertions, 203 deletions
diff --git a/plugins/Autocomplete/autocomplete.php b/plugins/Autocomplete/autocomplete.php
index 4379a86f2..aa57b3915 100644
--- a/plugins/Autocomplete/autocomplete.php
+++ b/plugins/Autocomplete/autocomplete.php
@@ -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";
}
}
diff --git a/plugins/Meteor/meteorupdater.js b/plugins/Meteor/meteorupdater.js
index 91d12cde9..9ce68775b 100644
--- a/plugins/Meteor/meteorupdater.js
+++ b/plugins/Meteor/meteorupdater.js
@@ -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();
+ }
+ }
}();
diff --git a/plugins/PiwikAnalyticsPlugin.php b/plugins/PiwikAnalyticsPlugin.php
index e36bd1c5c..8191f5181 100644
--- a/plugins/PiwikAnalyticsPlugin.php
+++ b/plugins/PiwikAnalyticsPlugin.php
@@ -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();
}
diff --git a/plugins/Realtime/RealtimePlugin.php b/plugins/Realtime/RealtimePlugin.php
index 611b1d86c..e30c41156 100644
--- a/plugins/Realtime/RealtimePlugin.php
+++ b/plugins/Realtime/RealtimePlugin.php
@@ -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;
+ }
}
diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js
index da2f9ed3a..57fe0a843 100644
--- a/plugins/Realtime/realtimeupdate.js
+++ b/plugins/Realtime/realtimeupdate.js
@@ -1,152 +1,147 @@
-$(document).ready(function() {
- if (!$(document).getUrlParam('realtime')) {
- $('#site_nav_local_views .current a').append('<button id="realtime_timeline" title="Pop this tab">&#8599;</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
-
- RealtimeUpdate = {
- _userid: 0,
- _replyurl: '',
- _favorurl: '',
- _deleteurl: '',
-
- init: function(userid, replyurl, favorurl, deleteurl)
- {
- RealtimeUpdate._userid = userid;
- RealtimeUpdate._replyurl = replyurl;
- RealtimeUpdate._favorurl = favorurl;
- RealtimeUpdate._deleteurl = deleteurl;
- },
-
- receive: function(data)
- {
- id = data.id;
-
- // Don't add it if it already exists
-
- if ($("#notice-"+id).length > 0) {
- return;
- }
-
- var noticeItem = RealtimeUpdate.makeNoticeItem(data);
- $("#notices_primary .notices").prepend(noticeItem, true);
- $("#notices_primary .notice:first").css({display:"none"});
- $("#notices_primary .notice:first").fadeIn(1000);
- NoticeReply();
- },
-
- makeNoticeItem: function(data)
- {
- user = data['user'];
- html = data['html'].replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&quot;/g,'"');
- source = data['source'].replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&quot;/g,'"');
-
- ni = "<li class=\"hentry notice\" id=\"notice-"+data['id']+"\">"+
- "<div class=\"entry-title\">"+
- "<span class=\"vcard author\">"+
- "<a href=\""+user['profile_url']+"\" class=\"url\">"+
- "<img src=\""+user['profile_image_url']+"\" class=\"avatar photo\" width=\"48\" height=\"48\" alt=\""+user['screen_name']+"\"/>"+
- "<span class=\"nickname fn\">"+user['screen_name']+"</span>"+
- "</a>"+
- "</span>"+
- "<p class=\"entry-content\">"+html+"</p>"+
- "</div>"+
- "<div class=\"entry-content\">"+
- "<a class=\"timestamp\" rel=\"bookmark\" href=\""+data['url']+"\" >"+
- "<abbr class=\"published\" title=\""+data['created_at']+"\">a few seconds ago</abbr>"+
- "</a> "+
- "<span class=\"source\">"+
- "from "+
+// add a notice encoded as JSON into the current timeline
+//
+// TODO: i18n
+
+RealtimeUpdate = {
+ _userid: 0,
+ _replyurl: '',
+ _favorurl: '',
+ _deleteurl: '',
+
+ init: function(userid, replyurl, favorurl, deleteurl)
+ {
+ RealtimeUpdate._userid = userid;
+ RealtimeUpdate._replyurl = replyurl;
+ RealtimeUpdate._favorurl = favorurl;
+ RealtimeUpdate._deleteurl = deleteurl;
+ },
+
+ receive: function(data)
+ {
+ id = data.id;
+
+ // Don't add it if it already exists
+ //
+ if ($("#notice-"+id).length > 0) {
+ return;
+ }
+
+ var noticeItem = RealtimeUpdate.makeNoticeItem(data);
+ $("#notices_primary .notices").prepend(noticeItem, true);
+ $("#notices_primary .notice:first").css({display:"none"});
+ $("#notices_primary .notice:first").fadeIn(1000);
+ NoticeReply();
+ },
+
+ makeNoticeItem: function(data)
+ {
+ user = data['user'];
+ html = data['html'].replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&quot;/g,'"');
+ source = data['source'].replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&quot;/g,'"');
+
+ ni = "<li class=\"hentry notice\" id=\"notice-"+data['id']+"\">"+
+ "<div class=\"entry-title\">"+
+ "<span class=\"vcard author\">"+
+ "<a href=\""+user['profile_url']+"\" class=\"url\">"+
+ "<img src=\""+user['profile_image_url']+"\" class=\"avatar photo\" width=\"48\" height=\"48\" alt=\""+user['screen_name']+"\"/>"+
+ "<span class=\"nickname fn\">"+user['screen_name']+"</span>"+
+ "</a>"+
+ "</span>"+
+ "<p class=\"entry-content\">"+html+"</p>"+
+ "</div>"+
+ "<div class=\"entry-content\">"+
+ "<a class=\"timestamp\" rel=\"bookmark\" href=\""+data['url']+"\" >"+
+ "<abbr class=\"published\" title=\""+data['created_at']+"\">a few seconds ago</abbr>"+
+ "</a> "+
+ "<span class=\"source\">"+
+ "from "+
"<span class=\"device\">"+source+"</span>"+ // may have a link
- "</span>";
- if (data['in_reply_to_status_id']) {
- ni = ni+" <a class=\"response\" href=\""+data['in_reply_to_status_url']+"\">in context</a>";
- }
+ "</span>";
+ if (data['in_reply_to_status_id']) {
+ ni = ni+" <a class=\"response\" href=\""+data['in_reply_to_status_url']+"\">in context</a>";
+ }
- ni = ni+"</div>"+
+ ni = ni+"</div>"+
"<div class=\"notice-options\">";
- if (RealtimeUpdate._userid != 0) {
- var input = $("form#form_notice fieldset input#token");
- var session_key = input.val();
- ni = ni+RealtimeUpdate.makeFavoriteForm(data['id'], session_key);
- ni = ni+RealtimeUpdate.makeReplyLink(data['id'], data['user']['screen_name']);
- if (RealtimeUpdate._userid == data['user']['id']) {
+ if (RealtimeUpdate._userid != 0) {
+ var input = $("form#form_notice fieldset input#token");
+ var session_key = input.val();
+ ni = ni+RealtimeUpdate.makeFavoriteForm(data['id'], session_key);
+ ni = ni+RealtimeUpdate.makeReplyLink(data['id'], data['user']['screen_name']);
+ if (RealtimeUpdate._userid == data['user']['id']) {
ni = ni+RealtimeUpdate.makeDeleteLink(data['id']);
- }
- }
+ }
+ }
- ni = ni+"</div>"+
- "</li>";
- return ni;
- },
+ ni = ni+"</div>"+
+ "</li>";
+ return ni;
+ },
- makeFavoriteForm: function(id, session_key)
- {
- var ff;
+ makeFavoriteForm: function(id, session_key)
+ {
+ var ff;
- ff = "<form id=\"favor-"+id+"\" class=\"form_favor\" method=\"post\" action=\""+RealtimeUpdate._favorurl+"\">"+
+ ff = "<form id=\"favor-"+id+"\" class=\"form_favor\" method=\"post\" action=\""+RealtimeUpdate._favorurl+"\">"+
"<fieldset>"+
- "<legend>Favor this notice</legend>"+
- "<input name=\"token-"+id+"\" type=\"hidden\" id=\"token-"+id+"\" value=\""+session_key+"\"/>"+
- "<input name=\"notice\" type=\"hidden\" id=\"notice-n"+id+"\" value=\""+id+"\"/>"+
- "<input type=\"submit\" id=\"favor-submit-"+id+"\" name=\"favor-submit-"+id+"\" class=\"submit\" value=\"Favor\" title=\"Favor this notice\"/>"+
+ "<legend>Favor this notice</legend>"+
+ "<input name=\"token-"+id+"\" type=\"hidden\" id=\"token-"+id+"\" value=\""+session_key+"\"/>"+
+ "<input name=\"notice\" type=\"hidden\" id=\"notice-n"+id+"\" value=\""+id+"\"/>"+
+ "<input type=\"submit\" id=\"favor-submit-"+id+"\" name=\"favor-submit-"+id+"\" class=\"submit\" value=\"Favor\" title=\"Favor this notice\"/>"+
"</fieldset>"+
- "</form>";
- return ff;
- },
-
- makeReplyLink: function(id, nickname)
- {
- var rl;
- rl = "<a class=\"notice_reply\" href=\""+RealtimeUpdate._replyurl+"?replyto="+nickname+"\" title=\"Reply to this notice\">Reply <span class=\"notice_id\">"+id+"</span></a>";
- return rl;
+ "</form>";
+ return ff;
+ },
+
+ makeReplyLink: function(id, nickname)
+ {
+ var rl;
+ rl = "<a class=\"notice_reply\" href=\""+RealtimeUpdate._replyurl+"?replyto="+nickname+"\" title=\"Reply to this notice\">Reply <span class=\"notice_id\">"+id+"</span></a>";
+ return rl;
},
- makeDeleteLink: function(id)
- {
- var dl, delurl;
- delurl = RealtimeUpdate._deleteurl.replace("0000000000", id);
-
- dl = "<a class=\"notice_delete\" href=\""+delurl+"\" title=\"Delete this notice\">Delete</a>";
-
- return dl;
- }
- }
-
-});
+ makeDeleteLink: function(id)
+ {
+ var dl, delurl;
+ delurl = RealtimeUpdate._deleteurl.replace("0000000000", id);
+
+ 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">&#8599;</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%'});
+ }
+}