summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/accountsettingsaction.php3
-rw-r--r--lib/action.php24
-rw-r--r--lib/common.php1
-rw-r--r--lib/noticelist.php17
-rw-r--r--lib/queuehandler.php91
-rw-r--r--lib/router.php8
-rw-r--r--lib/theme.php29
-rw-r--r--lib/twitter.php2
-rw-r--r--lib/util.php84
9 files changed, 206 insertions, 53 deletions
diff --git a/lib/accountsettingsaction.php b/lib/accountsettingsaction.php
index 46090b8c1..86800d2a3 100644
--- a/lib/accountsettingsaction.php
+++ b/lib/accountsettingsaction.php
@@ -115,6 +115,9 @@ class AccountSettingsNav extends Widget
'openidsettings' =>
array(_('OpenID'),
_('Add or remove OpenIDs')),
+ 'designsettings' =>
+ array(_('Design'),
+ _('Design your profile')),
'othersettings' =>
array(_('Other'),
_('Other options')));
diff --git a/lib/action.php b/lib/action.php
index 1ba062812..0a628bfdf 100644
--- a/lib/action.php
+++ b/lib/action.php
@@ -194,37 +194,37 @@ class Action extends HTMLOutputter // lawsuit
if (Event::handle('StartShowLaconicaStyles', array($this))) {
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
- 'href' => theme_path('css/display.css', 'base') . '?version=' . LACONICA_VERSION,
+ 'href' => theme_path('base/css/display.css') . '?version=' . LACONICA_VERSION,
'media' => 'screen, projection, tv'));
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
- 'href' => theme_path('css/display.css', null) . '?version=' . LACONICA_VERSION,
+ 'href' => skin_path('css/display.css') . '?version=' . LACONICA_VERSION,
'media' => 'screen, projection, tv'));
if (common_config('site', 'mobile')) {
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
- 'href' => theme_path('css/mobile.css', 'base') . '?version=' . LACONICA_VERSION,
+ 'href' => theme_path('base/css/mobile.css') . '?version=' . LACONICA_VERSION,
// TODO: "handheld" CSS for other mobile devices
'media' => 'only screen and (max-device-width: 480px)')); // Mobile WebKit
}
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
- 'href' => theme_path('css/print.css', 'base') . '?version=' . LACONICA_VERSION,
+ 'href' => theme_path('base/css/print.css') . '?version=' . LACONICA_VERSION,
'media' => 'print'));
Event::handle('EndShowLaconicaStyles', array($this));
}
if (Event::handle('StartShowUAStyles', array($this))) {
$this->comment('[if IE]><link rel="stylesheet" type="text/css" '.
- 'href="'.theme_path('css/ie.css', 'base').'?version='.LACONICA_VERSION.'" /><![endif]');
+ 'href="'.theme_path('base/css/ie.css').'?version='.LACONICA_VERSION.'" /><![endif]');
foreach (array(6,7) as $ver) {
- if (file_exists(theme_file('css/ie'.$ver.'.css', 'base'))) {
+ if (file_exists(theme_file('base/css/ie'.$ver.'.css'))) {
// Yes, IE people should be put in jail.
$this->comment('[if lte IE '.$ver.']><link rel="stylesheet" type="text/css" '.
- 'href="'.theme_path('css/ie'.$ver.'.css', 'base').'?version='.LACONICA_VERSION.'" /><![endif]');
+ 'href="'.theme_path('base/css/ie'.$ver.'.css').'?version='.LACONICA_VERSION.'" /><![endif]');
}
}
$this->comment('[if IE]><link rel="stylesheet" type="text/css" '.
- 'href="'.theme_path('css/ie.css', null).'?version='.LACONICA_VERSION.'" /><![endif]');
+ 'href="'.skin_path('css/ie.css').'?version='.LACONICA_VERSION.'" /><![endif]');
Event::handle('EndShowUAStyles', array($this));
}
Event::handle('EndShowStyles', array($this));
@@ -848,10 +848,12 @@ class Action extends HTMLOutputter // lawsuit
}
if ($lm) {
header('Last-Modified: ' . date(DATE_RFC1123, $lm));
- if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
- $ims = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
+ if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) {
+ $if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
+ $ims = strtotime($if_modified_since);
if ($lm <= $ims) {
- $if_none_match = $_SERVER['HTTP_IF_NONE_MATCH'];
+ $if_none_match = (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)) ?
+ $_SERVER['HTTP_IF_NONE_MATCH'] : null;
if (!$if_none_match ||
!$etag ||
$this->_hasEtag($etag, $if_none_match)) {
diff --git a/lib/common.php b/lib/common.php
index b3882d207..dd2570e75 100644
--- a/lib/common.php
+++ b/lib/common.php
@@ -71,6 +71,7 @@ $config =
array('name' => 'Just another Laconica microblog',
'server' => $_server,
'theme' => 'default',
+ 'skin' => 'default',
'path' => $_path,
'logfile' => null,
'logo' => null,
diff --git a/lib/noticelist.php b/lib/noticelist.php
index 4182d8808..8fccba73e 100644
--- a/lib/noticelist.php
+++ b/lib/noticelist.php
@@ -197,7 +197,7 @@ class NoticeListItem extends Widget
$this->out->elementStart('div', 'entry-content');
$this->showNoticeLink();
$this->showNoticeSource();
- $this->showReplyTo();
+ $this->showContext();
$this->out->elementEnd('div');
}
@@ -421,17 +421,18 @@ class NoticeListItem extends Widget
* @return void
*/
- function showReplyTo()
+ function showContext()
{
- if ($this->notice->reply_to) {
- $replyurl = common_local_url('shownotice',
- array('notice' => $this->notice->reply_to));
+ // XXX: also show context if there are replies to this notice
+ if (!empty($this->notice->conversation)
+ && $this->notice->conversation != $this->notice->id) {
+ $convurl = common_local_url('conversation',
+ array('id' => $this->notice->conversation));
$this->out->elementStart('dl', 'response');
$this->out->element('dt', null, _('To'));
$this->out->elementStart('dd');
- $this->out->element('a', array('href' => $replyurl,
- 'rel' => 'in-reply-to'),
- _('in reply to'));
+ $this->out->element('a', array('href' => $convurl),
+ _('in context'));
$this->out->elementEnd('dd');
$this->out->elementEnd('dl');
}
diff --git a/lib/queuehandler.php b/lib/queuehandler.php
index 9ce9e32b3..f76f16e07 100644
--- a/lib/queuehandler.php
+++ b/lib/queuehandler.php
@@ -36,7 +36,7 @@ class QueueHandler extends Daemon
$this->set_id($id);
}
}
-
+
function class_name()
{
return ucfirst($this->transport()) . 'Handler';
@@ -46,7 +46,7 @@ class QueueHandler extends Daemon
{
return strtolower($this->class_name().'.'.$this->get_id());
}
-
+
function get_id()
{
return $this->_id;
@@ -56,16 +56,16 @@ class QueueHandler extends Daemon
{
$this->_id = $id;
}
-
+
function transport()
{
return null;
}
-
+
function start()
{
}
-
+
function finish()
{
}
@@ -74,16 +74,10 @@ class QueueHandler extends Daemon
{
return true;
}
-
- function run()
- {
- if (!$this->start()) {
- return false;
- }
- $this->log(LOG_INFO, 'checking for queued notices');
- $transport = $this->transport();
+
+ function db_dispatch() {
do {
- $qi = Queue_item::top($transport);
+ $qi = Queue_item::top($this->transport());
if ($qi) {
$this->log(LOG_INFO, 'Got item enqueued '.common_exact_date($qi->created));
$notice = Notice::staticGet($qi->notice_id);
@@ -113,8 +107,69 @@ class QueueHandler extends Daemon
} else {
$this->clear_old_claims();
$this->idle(5);
- }
+ }
} while (true);
+ }
+
+ function stomp_dispatch() {
+ require("Stomp.php");
+ $con = new Stomp(common_config('queue','stomp_server'));
+ if (!$con->connect()) {
+ $this->log(LOG_ERR, 'Failed to connect to queue server');
+ return false;
+ }
+ $queue_basename = common_config('queue','queue_basename');
+ // subscribe to the relevant queue (format: basename-transport)
+ $con->subscribe('/queue/'.$queue_basename.'-'.$this->transport());
+
+ do {
+ $frame = $con->readFrame();
+ if ($frame) {
+ $this->log(LOG_INFO, 'Got item enqueued '.common_exact_date($frame->headers['created']));
+
+ // XXX: Now the queue handler receives only the ID of the
+ // notice, and it has to get it from the DB
+ // A massive improvement would be avoid DB query by transmitting
+ // all the notice details via queue server...
+ $notice = Notice::staticGet($frame->body);
+
+ if ($notice) {
+ $this->log(LOG_INFO, 'broadcasting notice ID = ' . $notice->id);
+ $result = $this->handle_notice($notice);
+ if ($result) {
+ // if the msg has been handled positively, ack it
+ // and the queue server will remove it from the queue
+ $con->ack($frame);
+ $this->log(LOG_INFO, 'finished broadcasting notice ID = ' . $notice->id);
+ }
+ else {
+ // no ack
+ $this->log(LOG_WARNING, 'Failed broadcast for notice ID = ' . $notice->id);
+ }
+ $notice->free();
+ unset($notice);
+ $notice = null;
+ } else {
+ $this->log(LOG_WARNING, 'queue item for notice that does not exist');
+ }
+ }
+ } while (true);
+
+ $con->disconnect();
+ }
+
+ function run()
+ {
+ if (!$this->start()) {
+ return false;
+ }
+ $this->log(LOG_INFO, 'checking for queued notices');
+ if (common_config('queue','subsystem') == 'stomp') {
+ $this->stomp_dispatch();
+ }
+ else {
+ $this->db_dispatch();
+ }
if (!$this->finish()) {
return false;
}
@@ -127,7 +182,7 @@ class QueueHandler extends Daemon
sleep($timeout);
}
}
-
+
function clear_old_claims()
{
$qi = new Queue_item();
@@ -137,10 +192,10 @@ class QueueHandler extends Daemon
$qi->free();
unset($qi);
}
-
+
function log($level, $msg)
{
common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg);
}
}
- \ No newline at end of file
+
diff --git a/lib/router.php b/lib/router.php
index 6fb2f9487..5e16f3419 100644
--- a/lib/router.php
+++ b/lib/router.php
@@ -131,7 +131,7 @@ class Router
// settings
foreach (array('profile', 'avatar', 'password', 'openid', 'im',
- 'email', 'sms', 'twitter', 'other') as $s) {
+ 'email', 'sms', 'twitter', 'design', 'other') as $s) {
$m->connect('settings/'.$s, array('action' => $s.'settings'));
}
@@ -165,6 +165,12 @@ class Router
array('action' => 'deletenotice'),
array('notice' => '[0-9]+'));
+ // conversation
+
+ $m->connect('conversation/:id',
+ array('action' => 'conversation'),
+ array('id' => '[0-9]+'));
+
$m->connect('message/new', array('action' => 'newmessage'));
$m->connect('message/new?to=:to', array('action' => 'newmessage'), array('to' => '[A-Za-z0-9_-]+'));
$m->connect('message/:message',
diff --git a/lib/theme.php b/lib/theme.php
index 95030affe..bef660cbf 100644
--- a/lib/theme.php
+++ b/lib/theme.php
@@ -69,4 +69,31 @@ function theme_path($relative, $theme=null)
} else {
return common_path('theme/'.$theme.'/'.$relative);
}
-} \ No newline at end of file
+}
+
+/**
+ * Gets the full URL of a file in a skin dir based on its relative name
+ *
+ * @param string $relative relative path within the theme, skin directory
+ * @param string $theme name of the theme; defaults to current theme
+ * @param string $skin name of the skin; defaults to current theme
+ *
+ * @return string URL of the file
+ */
+
+function skin_path($relative, $theme=null, $skin=null)
+{
+ if (!$theme) {
+ $theme = common_config('site', 'theme');
+ }
+ if (!$skin) {
+ $skin = common_config('site', 'skin');
+ }
+ $server = common_config('theme', 'server');
+ if ($server) {
+ return 'http://'.$server.'/'.$theme.'/skin/'.$skin.'/'.$relative;
+ } else {
+ return common_path('theme/'.$theme.'/skin/'.$skin.'/'.$relative);
+ }
+}
+
diff --git a/lib/twitter.php b/lib/twitter.php
index ccc6c93ca..c1d0dc254 100644
--- a/lib/twitter.php
+++ b/lib/twitter.php
@@ -346,7 +346,7 @@ function save_twitter_friends($user, $twitter_id, $screen_name, $password)
function is_twitter_bound($notice, $flink) {
// Check to see if notice should go to Twitter
- if ($flink->noticesync & FOREIGN_NOTICE_SEND) {
+ if (!empty($flink) && ($flink->noticesync & FOREIGN_NOTICE_SEND)) {
// If it's not a Twitter-style reply, or if the user WANTS to send replies.
if (!preg_match('/^@[a-zA-Z0-9_]{1,15}\b/u', $notice->content) ||
diff --git a/lib/util.php b/lib/util.php
index 675ff51f0..888765548 100644
--- a/lib/util.php
+++ b/lib/util.php
@@ -874,18 +874,76 @@ function common_broadcast_notice($notice, $remote=false)
function common_enqueue_notice($notice)
{
- foreach (array('jabber', 'omb', 'sms', 'public', 'twitter', 'facebook', 'ping') as $transport) {
- $qi = new Queue_item();
- $qi->notice_id = $notice->id;
- $qi->transport = $transport;
- $qi->created = $notice->created;
- $result = $qi->insert();
- if (!$result) {
- $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
- common_log(LOG_ERR, 'DB error inserting queue item: ' . $last_error->message);
- return false;
+ if (common_config('queue','subsystem') == 'stomp') {
+ // use an external message queue system via STOMP
+ require_once("Stomp.php");
+ $con = new Stomp(common_config('queue','stomp_server'));
+ if (!$con->connect()) {
+ common_log(LOG_ERR, 'Failed to connect to queue server');
+ return false;
+ }
+ $queue_basename = common_config('queue','queue_basename');
+ foreach (array('jabber', 'omb', 'sms', 'public', 'twitter', 'facebook', 'ping') as $transport) {
+ if (!$con->send(
+ '/queue/'.$queue_basename.'-'.$transport, // QUEUE
+ $notice->id, // BODY of the message
+ array ( // HEADERS of the msg
+ 'created' => $notice->created
+ ))) {
+ common_log(LOG_ERR, 'Error sending to '.$transport.' queue');
+ return false;
+ }
+ common_log(LOG_DEBUG, 'complete remote queueing notice ID = ' . $notice->id . ' for ' . $transport);
+ }
+
+ //send tags as headers, so they can be used as JMS selectors
+ common_log(LOG_DEBUG, 'searching for tags ' . $notice->id);
+ $tags = array();
+ $tag = new Notice_tag();
+ $tag->notice_id = $notice->id;
+ if ($tag->find()) {
+ while ($tag->fetch()) {
+ common_log(LOG_DEBUG, 'tag found = ' . $tag->tag);
+ array_push($tags,$tag->tag);
+ }
+ }
+ $tag->free();
+
+ $con->send('/topic/laconica.'.$notice->profile_id,
+ $notice->content,
+ array(
+ 'profile_id' => $notice->profile_id,
+ 'created' => $notice->created,
+ 'tags' => implode($tags,' - ')
+ )
+ );
+ common_log(LOG_DEBUG, 'sent to personal topic ' . $notice->id);
+ $con->send('/topic/laconica.allusers',
+ $notice->content,
+ array(
+ 'profile_id' => $notice->profile_id,
+ 'created' => $notice->created,
+ 'tags' => implode($tags,' - ')
+ )
+ );
+ common_log(LOG_DEBUG, 'sent to catch-all topic ' . $notice->id);
+ $result = true;
+ }
+ else {
+ // in any other case, 'internal'
+ foreach (array('jabber', 'omb', 'sms', 'public', 'twitter', 'facebook', 'ping') as $transport) {
+ $qi = new Queue_item();
+ $qi->notice_id = $notice->id;
+ $qi->transport = $transport;
+ $qi->created = $notice->created;
+ $result = $qi->insert();
+ if (!$result) {
+ $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
+ common_log(LOG_ERR, 'DB error inserting queue item: ' . $last_error->message);
+ return false;
+ }
+ common_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport);
}
- common_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport);
}
return $result;
}
@@ -1094,7 +1152,7 @@ function common_accept_to_prefs($accept, $def = '*/*')
foreach($parts as $part) {
// FIXME: doesn't deal with params like 'text/html; level=1'
- @list($value, $qpart) = explode(';', $part);
+ @list($value, $qpart) = explode(';', trim($part));
$match = array();
if(!isset($qpart)) {
$prefs[$value] = 1;
@@ -1333,4 +1391,4 @@ function common_database_tablename($tablename)
}
//table prefixes could be added here later
return $tablename;
-} \ No newline at end of file
+}