From 35931e3a0e3b78f222e8aa6eb02e71ca7a3b8410 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 8 Nov 2010 10:36:19 -0500 Subject: first steps for email summary --- plugins/EmailSummary/EmailSummaryPlugin.php | 119 ++++++++++++++++++ plugins/EmailSummary/Email_summary_status.php | 167 ++++++++++++++++++++++++++ 2 files changed, 286 insertions(+) create mode 100644 plugins/EmailSummary/EmailSummaryPlugin.php create mode 100644 plugins/EmailSummary/Email_summary_status.php (limited to 'plugins') diff --git a/plugins/EmailSummary/EmailSummaryPlugin.php b/plugins/EmailSummary/EmailSummaryPlugin.php new file mode 100644 index 000000000..dd72329f8 --- /dev/null +++ b/plugins/EmailSummary/EmailSummaryPlugin.php @@ -0,0 +1,119 @@ +. + * + * @category Sample + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Plugin for sending email summaries to users + * + * @category Email + * @package StatusNet + * @author Brion Vibber + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class EmailSummaryPlugin extends Plugin +{ + /** + * Database schema setup + * + * @return boolean hook value + */ + + function onCheckSchema() + { + $schema = Schema::get(); + + // For storing user-submitted flags on profiles + + $schema->ensureTable('email_summary_status', + array(new ColumnDef('user_id', 'integer', null, + false, 'PRI'), + new ColumnDef('send_summary', 'tinyint', null, + false, null, 1), + new ColumnDef('last_summary', 'datetime', null, + true), + new ColumnDef('created', 'datetime', null, + false), + new ColumnDef('modified', 'datetime', null, + false), + ) + ); + return true; + } + + /** + * Load related modules when needed + * + * @param string $cls Name of the class to be loaded + * + * @return boolean hook value; true means continue processing, false means stop. + * + */ + + function onAutoload($cls) + { + $dir = dirname(__FILE__); + + switch ($cls) + { + case 'Email_summary_status': + include_once $dir . '/'.$cls.'.php'; + return false; + default: + return true; + } + } + + /** + * Version info for this plugin + * + * @param array &$versions array of version data + * + * @return boolean hook value; true means continue processing, false means stop. + * + */ + + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'EmailSummary', + 'version' => STATUSNET_VERSION, + 'author' => 'Evan Prodromou', + 'homepage' => 'http://status.net/wiki/Plugin:EmailSummary', + 'rawdescription' => + _m('Send an email summary of the inbox to users.')); + return true; + } +} diff --git a/plugins/EmailSummary/Email_summary_status.php b/plugins/EmailSummary/Email_summary_status.php new file mode 100644 index 000000000..a0462fd04 --- /dev/null +++ b/plugins/EmailSummary/Email_summary_status.php @@ -0,0 +1,167 @@ + + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * StatusNet - the distributed open-source microblogging tool + * Copyright (C) 2010, 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 . + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR . '/classes/Memcached_DataObject.php'; + +/** + * Data class for email summaries + * + * Email summary information for users + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * @see DB_DataObject + */ + +class Email_summary_status extends Memcached_DataObject +{ + public $__table = 'email_summary_status'; // table name + public $user_id; // int(4) primary_key not_null + public $send_summary; // tinyint not_null + public $last_summary; // int(4) primary_key not_null + public $created; // int(4) primary_key not_null + public $modified; // int(4) primary_key not_null + + /** + * Get an instance by key + * + * @param string $k Key to use to lookup (usually 'user_id' for this class) + * @param mixed $v Value to lookup + * + * @return Email_summary_status object found, or null for no hits + * + */ + function staticGet($k, $v=null) + { + return Memcached_DataObject::staticGet('email_summary_status', $k, $v); + } + + /** + * return table definition for DB_DataObject + * + * DB_DataObject needs to know something about the table to manipulate + * instances. This method provides all the DB_DataObject needs to know. + * + * @return array array of column definitions + */ + + function table() + { + return array('user_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, + 'send_summary' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, + 'last_summary' => DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME, + 'created' => DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME, + 'modified' => DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME); + } + + /** + * return key definitions for DB_DataObject + * + * @return array list of key field names + */ + + function keys() + { + return array_keys($this->keyTypes()); + } + + /** + * return key definitions for Memcached_DataObject + * + * Our caching system uses the same key definitions, but uses a different + * method to get them. This key information is used to store and clear + * cached data, so be sure to list any key that will be used for static + * lookups. + * + * @return array associative array of key definitions, field name to type: + * 'K' for primary key: for compound keys, add an entry for each component; + * 'U' for unique keys: compound keys are not well supported here. + */ + function keyTypes() + { + return array('user_id' => 'K'); + } + + /** + * Magic formula for non-autoincrementing integer primary keys + * + * @return array magic three-false array that stops auto-incrementing. + */ + + function sequenceKey() + { + return array(false, false, false); + } + + /** + * Helper function + * + * @param integer $user_id ID of the user to get a count for + * + * @return int flag for whether to send this user a summary email + */ + + static function getSendSummary($user_id) + { + $ess = Email_summary_status::staticGet('user_id', $user_id); + + if (!empty($ess)) { + return $ess->send_summary; + } else { + return 1; + } + } + + /** + * Get email summary status for a user + * + * @param integer $user_id ID of the user to get a count for + * + * @return Email_summary_status instance for this user, with count already incremented. + */ + + static function getLastSummary($user_id) + { + $ess = Email_summary_status::staticGet('user_id', $user_id); + + if (!empty($ess)) { + return $ess->last_summary; + } else { + return 1; + } + } +} -- cgit v1.2.3-54-g00ecf From 797059340e304a707dda5596f30651ffc727f3c3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 8 Nov 2010 13:10:09 -0500 Subject: Complete email summary sending system Added the necessary classes to send email summaries. First, added a script to run on a daily basis. Second, added a queue handler for sending email summaries for users, and another to queue summaries for all users on the site. Fixed up the email_summary_status table to store the last-sent notice id, rather than a datetime (since we don't support 'since' parameters anymore). Finally, made the plugin class load the right modules when needed. --- plugins/EmailSummary/EmailSummaryPlugin.php | 21 ++- plugins/EmailSummary/Email_summary_status.php | 18 +-- plugins/EmailSummary/sendemailsummary.php | 47 +++++++ plugins/EmailSummary/siteemailsummaryhandler.php | 96 +++++++++++++ plugins/EmailSummary/useremailsummaryhandler.php | 172 +++++++++++++++++++++++ 5 files changed, 344 insertions(+), 10 deletions(-) create mode 100644 plugins/EmailSummary/sendemailsummary.php create mode 100644 plugins/EmailSummary/siteemailsummaryhandler.php create mode 100644 plugins/EmailSummary/useremailsummaryhandler.php (limited to 'plugins') diff --git a/plugins/EmailSummary/EmailSummaryPlugin.php b/plugins/EmailSummary/EmailSummaryPlugin.php index dd72329f8..03577bb4a 100644 --- a/plugins/EmailSummary/EmailSummaryPlugin.php +++ b/plugins/EmailSummary/EmailSummaryPlugin.php @@ -63,7 +63,7 @@ class EmailSummaryPlugin extends Plugin false, 'PRI'), new ColumnDef('send_summary', 'tinyint', null, false, null, 1), - new ColumnDef('last_summary', 'datetime', null, + new ColumnDef('last_summary_id', 'integer', null, true), new ColumnDef('created', 'datetime', null, false), @@ -89,6 +89,10 @@ class EmailSummaryPlugin extends Plugin switch ($cls) { + case 'SiteEmailSummaryHandler': + case 'UserEmailSummaryHandler': + include_once $dir . '/'.strtolower($cls).'.php'; + return false; case 'Email_summary_status': include_once $dir . '/'.$cls.'.php'; return false; @@ -116,4 +120,19 @@ class EmailSummaryPlugin extends Plugin _m('Send an email summary of the inbox to users.')); return true; } + + /** + * Register our queue handlers + * + * @param QueueManager $qm Current queue manager + * + * @return boolean hook value + */ + + function onEndInitializeQueueManager($qm) + { + $qm->connect('sitesum', 'SiteEmailSummaryHandler'); + $qm->connect('usersum', 'UserEmailSummaryHandler'); + return true; + } } diff --git a/plugins/EmailSummary/Email_summary_status.php b/plugins/EmailSummary/Email_summary_status.php index a0462fd04..5b5b231e3 100644 --- a/plugins/EmailSummary/Email_summary_status.php +++ b/plugins/EmailSummary/Email_summary_status.php @@ -52,9 +52,9 @@ class Email_summary_status extends Memcached_DataObject public $__table = 'email_summary_status'; // table name public $user_id; // int(4) primary_key not_null public $send_summary; // tinyint not_null - public $last_summary; // int(4) primary_key not_null - public $created; // int(4) primary_key not_null - public $modified; // int(4) primary_key not_null + public $last_summary_id; // int(4) null + public $created; // datetime not_null + public $modified; // datetime not_null /** * Get an instance by key @@ -83,9 +83,9 @@ class Email_summary_status extends Memcached_DataObject { return array('user_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, 'send_summary' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, - 'last_summary' => DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME, - 'created' => DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME, - 'modified' => DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME); + 'last_summary_id' => DB_DATAOBJECT_INT, + 'created' => DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL, + 'modified' => DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL); } /** @@ -154,14 +154,14 @@ class Email_summary_status extends Memcached_DataObject * @return Email_summary_status instance for this user, with count already incremented. */ - static function getLastSummary($user_id) + static function getLastSummaryID($user_id) { $ess = Email_summary_status::staticGet('user_id', $user_id); if (!empty($ess)) { - return $ess->last_summary; + return $ess->last_summary_id; } else { - return 1; + return null; } } } diff --git a/plugins/EmailSummary/sendemailsummary.php b/plugins/EmailSummary/sendemailsummary.php new file mode 100644 index 000000000..37bfdcfbd --- /dev/null +++ b/plugins/EmailSummary/sendemailsummary.php @@ -0,0 +1,47 @@ +#!/usr/bin/env php +. + */ + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/../..')); + +$shortoptions = 'i:n:a'; +$longoptions = array('id=', 'nickname=', 'all'); + +$helptext = <<enqueue($user->id, 'usersum'); +} catch (NoUserArgumentException $nuae) { + $qm->enqueue(null, 'sitesum'); +} diff --git a/plugins/EmailSummary/siteemailsummaryhandler.php b/plugins/EmailSummary/siteemailsummaryhandler.php new file mode 100644 index 000000000..595c3267a --- /dev/null +++ b/plugins/EmailSummary/siteemailsummaryhandler.php @@ -0,0 +1,96 @@ +. + * + * @category Sample + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * + * Handler for queue items of type 'sitesum', sends email summaries + * to all users on the site. + * + * @category Email + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class SiteEmailSummaryHandler extends QueueHandler +{ + + /** + * Return transport keyword which identifies items this queue handler + * services; must be defined for all subclasses. + * + * Must be 8 characters or less to fit in the queue_item database. + * ex "email", "jabber", "sms", "irc", ... + * + * @return string + */ + + function transport() + { + return 'sitesum'; + } + + /** + * Handle the site + * + * @param mixed $object + * @return boolean true on success, false on failure + */ + + function handle($object) + { + $qm = QueueManager::get(); + + try { + // Enqueue a summary for all users + + $user = new User(); + $user->find(); + + while ($user->fetch()) { + try { + $qm->enqueue($user->id, 'usersum'); + } catch (Exception $e) { + common_log(LOG_WARNING, $e->getMessage()); + continue; + } + } + } catch (Exception $e) { + common_log(LOG_WARNING, $e->getMessage()); + } + + return true; + } +} + diff --git a/plugins/EmailSummary/useremailsummaryhandler.php b/plugins/EmailSummary/useremailsummaryhandler.php new file mode 100644 index 000000000..f3151bd47 --- /dev/null +++ b/plugins/EmailSummary/useremailsummaryhandler.php @@ -0,0 +1,172 @@ +. + * + * @category Sample + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Handler for queue items of type 'usersum', sends an email summaries + * to a particular user. + * + * @category Email + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class UserEmailSummaryHandler extends QueueHandler +{ + // Maximum number of notices to include by default. This is probably too much. + + const MAX_NOTICES = 200; + + /** + * Return transport keyword which identifies items this queue handler + * services; must be defined for all subclasses. + * + * Must be 8 characters or less to fit in the queue_item database. + * ex "email", "jabber", "sms", "irc", ... + * + * @return string + */ + + function transport() + { + return 'sitesum'; + } + + /** + * Send a summary email to the user + * + * @param mixed $object + * @return boolean true on success, false on failure + */ + + function handle($user_id) + { + // Skip if they've asked not to get summaries + + $ess = Email_summary_status::staticGet('user_id', $user_id); + + if (!empty($ess) && !$ess->send_summary) { + common_log(LOG_INFO, sprintf('Not sending email summary for user %s by request.', $user_id)); + return true; + } + + $since_id = null; + + if (!empty($ess)) { + $since_id = $ess->last_summary_id; + } + + $user = User::staticGet('id', $user_id); + + if (empty($user)) { + common_log(LOG_INFO, sprintf('Not sending email summary for user %s; no such user.', $user_id)); + return true; + } + + if (empty($user->email)) { + common_log(LOG_INFO, sprintf('Not sending email summary for user %s; no email address.', $user_id)); + return true; + } + + $profile = $user->getProfile(); + + if (empty($profile)) { + common_log(LOG_WARNING, sprintf('Not sending email summary for user %s; no profile.', $user_id)); + return true; + } + + $notice = $user->ownFriendsTimeline(0, self::MAX_NOTICES, $since_id); + + if (empty($notice) || $notice->N == 0) { + common_log(LOG_WARNING, sprintf('Not sending email summary for user %s; no notices.', $user_id)); + return true; + } + + // XXX: This is risky fingerpoken in der objektvars, but I didn't feel like + // figuring out a better way. -ESP + + $new_top = null; + + if ($notice instanceof ArrayWrapper) { + $new_top = $notice->_items[0]->id; + } + + $out = new XMLStringer(); + + $out->raw(sprintf(_('

Recent updates from %1s for %2s:

'), + common_config('site', 'name'), + $profile->getBestName())); + + $nl = new NoticeList($notice, $out); + + // Outputs to the string + + $nl->show(); + + $out->raw(sprintf(_('

change your email settings for %2s

'), + common_local_url('emailsettings'), + common_config('site', 'name'))); + + $body = $out->getString(); + + // FIXME: do something for people who don't like HTML email + + mail_to_user($user, _('Updates from your network'), $body, + array('Content-Type', 'text/html; charset=UTF-8')); + + if (empty($ess)) { + + $ess = new Email_summary_status(); + + $ess->user_id = $user_id; + $ess->created = common_sql_now(); + $ess->last_summary_id = $new_top; + $ess->modified = common_sql_now(); + + $ess->insert(); + + } else { + + $orig = clone($ess); + + $ess->last_summary_id = $new_top; + $ess->modified = common_sql_now(); + + $ess->update(); + } + + return true; + } +} + -- cgit v1.2.3-54-g00ecf From 0a56523461ec2b7abce652d18129c043eddb6394 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 8 Nov 2010 17:22:16 -0500 Subject: Fixup headers for HTML email --- plugins/EmailSummary/useremailsummaryhandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/EmailSummary/useremailsummaryhandler.php b/plugins/EmailSummary/useremailsummaryhandler.php index f3151bd47..4bbbb861c 100644 --- a/plugins/EmailSummary/useremailsummaryhandler.php +++ b/plugins/EmailSummary/useremailsummaryhandler.php @@ -143,7 +143,7 @@ class UserEmailSummaryHandler extends QueueHandler // FIXME: do something for people who don't like HTML email mail_to_user($user, _('Updates from your network'), $body, - array('Content-Type', 'text/html; charset=UTF-8')); + array('Content-Type' => 'text/html; charset=UTF-8')); if (empty($ess)) { -- cgit v1.2.3-54-g00ecf From 37407d8c7751b1966f41484678e7695157a460c3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 8 Nov 2010 17:31:21 -0500 Subject: stylesheet for outgoing email --- plugins/EmailSummary/useremailsummaryhandler.php | 292 +++++++++++++++++++++++ 1 file changed, 292 insertions(+) (limited to 'plugins') diff --git a/plugins/EmailSummary/useremailsummaryhandler.php b/plugins/EmailSummary/useremailsummaryhandler.php index 4bbbb861c..9ef56a20d 100644 --- a/plugins/EmailSummary/useremailsummaryhandler.php +++ b/plugins/EmailSummary/useremailsummaryhandler.php @@ -124,6 +124,8 @@ class UserEmailSummaryHandler extends QueueHandler $out = new XMLStringer(); + $out->raw(''); + $out->raw(sprintf(_('

Recent updates from %1s for %2s:

'), common_config('site', 'name'), $profile->getBestName())); @@ -168,5 +170,295 @@ class UserEmailSummaryHandler extends QueueHandler return true; } + + function stylesheet() + { + $ss = << Date: Mon, 8 Nov 2010 18:14:13 -0500 Subject: change to a table for HTML output --- plugins/EmailSummary/useremailsummaryhandler.php | 350 ++++------------------- 1 file changed, 54 insertions(+), 296 deletions(-) (limited to 'plugins') diff --git a/plugins/EmailSummary/useremailsummaryhandler.php b/plugins/EmailSummary/useremailsummaryhandler.php index 9ef56a20d..1ac1eaedb 100644 --- a/plugins/EmailSummary/useremailsummaryhandler.php +++ b/plugins/EmailSummary/useremailsummaryhandler.php @@ -124,17 +124,66 @@ class UserEmailSummaryHandler extends QueueHandler $out = new XMLStringer(); - $out->raw(''); - $out->raw(sprintf(_('

Recent updates from %1s for %2s:

'), common_config('site', 'name'), $profile->getBestName())); - $nl = new NoticeList($notice, $out); - // Outputs to the string + $out->elementStart('table', array('width' => '100%', 'style' => 'border: none')); - $nl->show(); + while ($notice->fetch()) { + + $profile = Profile::staticGet('id', $notice->profile_id); + + if (empty($profile)) { + continue; + } + + $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE); + + $out->elementStart('tr'); + $out->elementStart('td'); + $out->element('img', array('src' => ($avatar) ? + $avatar->displayUrl() : + Avatar::defaultImage($avatar_size), + 'class' => 'avatar photo', + 'width' => $avatar_size, + 'height' => $avatar_size, + 'alt' => $profile->getBestName())); + $out->elementEnd('td'); + $out->elementStart('td'); + $out->element('a', array('href' => $profile->profileurl), + $profile->nickname); + $out->text(' '); + $out->raw($notice->rendered); + $out->element('br'); // yeah, you know it. I just wrote a
in the middle of my table layout. + $noticeurl = $notice->bestUrl(); + // above should always return an URL + assert(!empty($noticeurl)); + $out->elementStart('a', array('rel' => 'bookmark', + 'class' => 'timestamp', + 'href' => $noticeurl)); + $dt = common_date_iso8601($notice->created); + $out->element('abbr', array('class' => 'published', + 'title' => $dt), + common_date_string($notice->created)); + $out->elementEnd('a'); + if ($notice->hasConversation()) { + $conv = Conversation::staticGet('id', $notice->conversation); + $convurl = $conv->uri; + if (!empty($convurl)) { + $out->text(' '); + $out->element('a', + array('href' => $convurl.'#notice-'.$notice->id, + 'class' => 'response'), + _('in context')); + } + } + $out->elementEnd('td'); + $out->elementEnd('tr'); + } + + $out->elementEnd('table'); $out->raw(sprintf(_('

change your email settings for %2s

'), common_local_url('emailsettings'), @@ -170,295 +219,4 @@ class UserEmailSummaryHandler extends QueueHandler return true; } - - function stylesheet() - { - $ss = << Date: Tue, 9 Nov 2010 06:59:16 -0500 Subject: set height and width of avatar td in email summary --- plugins/EmailSummary/useremailsummaryhandler.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/EmailSummary/useremailsummaryhandler.php b/plugins/EmailSummary/useremailsummaryhandler.php index 1ac1eaedb..d6de6aa05 100644 --- a/plugins/EmailSummary/useremailsummaryhandler.php +++ b/plugins/EmailSummary/useremailsummaryhandler.php @@ -142,7 +142,8 @@ class UserEmailSummaryHandler extends QueueHandler $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE); $out->elementStart('tr'); - $out->elementStart('td'); + $out->elementStart('td', array('width' => AVATAR_STREAM_SIZE, + 'height' => AVATAR_STREAM_SIZE)); $out->element('img', array('src' => ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage($avatar_size), -- cgit v1.2.3-54-g00ecf From 17ab5c31ed255216a2b734e15e9d11bd4c6fce8b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 9 Nov 2010 07:04:50 -0500 Subject: some alignment in the table layout --- plugins/EmailSummary/useremailsummaryhandler.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/EmailSummary/useremailsummaryhandler.php b/plugins/EmailSummary/useremailsummaryhandler.php index d6de6aa05..95b7fdc47 100644 --- a/plugins/EmailSummary/useremailsummaryhandler.php +++ b/plugins/EmailSummary/useremailsummaryhandler.php @@ -143,16 +143,19 @@ class UserEmailSummaryHandler extends QueueHandler $out->elementStart('tr'); $out->elementStart('td', array('width' => AVATAR_STREAM_SIZE, - 'height' => AVATAR_STREAM_SIZE)); + 'height' => AVATAR_STREAM_SIZE, + 'align' => 'left', + 'valign' => 'top')); $out->element('img', array('src' => ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage($avatar_size), 'class' => 'avatar photo', - 'width' => $avatar_size, - 'height' => $avatar_size, + 'width' => AVATAR_STREAM_SIZE, + 'height' => AVATAR_STREAM_SIZE, 'alt' => $profile->getBestName())); $out->elementEnd('td'); - $out->elementStart('td'); + $out->elementStart('td', array('align' => 'left', + 'valign' => 'top')); $out->element('a', array('href' => $profile->profileurl), $profile->nickname); $out->text(' '); -- cgit v1.2.3-54-g00ecf From e87323e426f032504a01a01ea0854065413fb177 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 9 Nov 2010 13:04:11 -0500 Subject: change width of notices table to display better --- plugins/EmailSummary/useremailsummaryhandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/EmailSummary/useremailsummaryhandler.php b/plugins/EmailSummary/useremailsummaryhandler.php index 95b7fdc47..fb004b555 100644 --- a/plugins/EmailSummary/useremailsummaryhandler.php +++ b/plugins/EmailSummary/useremailsummaryhandler.php @@ -129,7 +129,7 @@ class UserEmailSummaryHandler extends QueueHandler $profile->getBestName())); - $out->elementStart('table', array('width' => '100%', 'style' => 'border: none')); + $out->elementStart('table', array('width' => '541px', 'style' => 'border: none')); while ($notice->fetch()) { -- cgit v1.2.3-54-g00ecf From adb16b8098dbe8870b7f4a9dcde49930a41666ff Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 11 Nov 2010 14:50:53 -0500 Subject: fix update of email prefs in queue handler --- plugins/EmailSummary/useremailsummaryhandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/EmailSummary/useremailsummaryhandler.php b/plugins/EmailSummary/useremailsummaryhandler.php index fb004b555..b1ebd0c42 100644 --- a/plugins/EmailSummary/useremailsummaryhandler.php +++ b/plugins/EmailSummary/useremailsummaryhandler.php @@ -218,7 +218,7 @@ class UserEmailSummaryHandler extends QueueHandler $ess->last_summary_id = $new_top; $ess->modified = common_sql_now(); - $ess->update(); + $ess->update($orig); } return true; -- cgit v1.2.3-54-g00ecf From 2d55bc0e5b89012e700bbeb68411e51477862b23 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 11 Nov 2010 14:51:14 -0500 Subject: give users a chance to opt out of email summaries --- plugins/EmailSummary/EmailSummaryPlugin.php | 64 +++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'plugins') diff --git a/plugins/EmailSummary/EmailSummaryPlugin.php b/plugins/EmailSummary/EmailSummaryPlugin.php index 03577bb4a..58c40e43c 100644 --- a/plugins/EmailSummary/EmailSummaryPlugin.php +++ b/plugins/EmailSummary/EmailSummaryPlugin.php @@ -135,4 +135,68 @@ class EmailSummaryPlugin extends Plugin $qm->connect('usersum', 'UserEmailSummaryHandler'); return true; } + + /** + * Add a checkbox to turn off email summaries + * + * @param Action $action Action being executed (emailsettings) + * + * @return boolean hook value + */ + + function onEndEmailFormData($action) + { + $user = common_current_user(); + + $action->elementStart('li'); + $action->checkbox('emailsummary', + // TRANS: Checkbox label in e-mail preferences form. + _('Send me a periodic summary of updates from my network.'), + Email_summary_status::getSendSummary($user->id)); + $action->elementEnd('li'); + return true; + } + + /** + * Add a checkbox to turn off email summaries + * + * @param Action $action Action being executed (emailsettings) + * + * @return boolean hook value + */ + + function onEndEmailSaveForm($action) + { + $sendSummary = $action->boolean('emailsummary'); + + $user = common_current_user(); + + if (!empty($user)) { + + $ess = Email_summary_status::staticGet('user_id', $user->id); + + if (empty($ess)) { + + $ess = new Email_summary_status(); + + $ess->user_id = $user->id; + $ess->send_summary = $sendSummary; + $ess->created = common_sql_now(); + $ess->modified = common_sql_now(); + + $ess->insert(); + + } else { + + $orig = clone($ess); + + $ess->send_summary = $sendSummary; + $ess->modified = common_sql_now(); + + $ess->update($orig); + } + } + + return true; + } } -- cgit v1.2.3-54-g00ecf From fdf3a23da7769586a818ca2219ec6bc1b46587de Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 12 Nov 2010 11:46:45 -0500 Subject: don't try to initialize the mapstraction canvas if it doesn't exist --- plugins/Mapstraction/MapstractionPlugin.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/Mapstraction/MapstractionPlugin.php b/plugins/Mapstraction/MapstractionPlugin.php index c4ba6464e..d5261d8bc 100644 --- a/plugins/Mapstraction/MapstractionPlugin.php +++ b/plugins/Mapstraction/MapstractionPlugin.php @@ -156,7 +156,8 @@ class MapstractionPlugin extends Plugin ' var user = null; '. (($actionName == 'showstream') ? ' user = scrapeUser(); ' : '') . ' var notices = scrapeNotices(user); ' . - ' showMapstraction($("#map_canvas"), notices); '. + ' var canvas = $("#map_canvas")[0]; ' . + ' if (typeof(canvas) != "undefined") { showMapstraction(canvas, notices); } '. '});'); } -- cgit v1.2.3-54-g00ecf From b6af5a25ba61ef3c86a3772abea7ac95778689f7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 12 Nov 2010 11:46:45 -0500 Subject: don't try to initialize the mapstraction canvas if it doesn't exist --- plugins/Mapstraction/MapstractionPlugin.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/Mapstraction/MapstractionPlugin.php b/plugins/Mapstraction/MapstractionPlugin.php index c4ba6464e..d5261d8bc 100644 --- a/plugins/Mapstraction/MapstractionPlugin.php +++ b/plugins/Mapstraction/MapstractionPlugin.php @@ -156,7 +156,8 @@ class MapstractionPlugin extends Plugin ' var user = null; '. (($actionName == 'showstream') ? ' user = scrapeUser(); ' : '') . ' var notices = scrapeNotices(user); ' . - ' showMapstraction($("#map_canvas"), notices); '. + ' var canvas = $("#map_canvas")[0]; ' . + ' if (typeof(canvas) != "undefined") { showMapstraction(canvas, notices); } '. '});'); } -- cgit v1.2.3-54-g00ecf From 6291e8201f90ed50687f7670edc505645ea55bfb Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 12 Nov 2010 13:06:41 -0800 Subject: Fix for failure edge case in TwitterBridge outgoing repeat/retweets. When the retweet failed with a 403 error (say due to it being a private tweet, which can't be retweeted) we would end up mishandling the return value from our internal error handling. Instead of correctly discarding the message and closing out the queue item, we ended up trying to save a bogus twitter<->local ID mapping, which threw another exception and lead the queue system to re-run it. - Fixed the logic check and return values for the retweet case in broadcast_twitter(). - Added doc comments explaining the return values on some functions in twitter.php - Added check on Notice_to_status::saveNew() for empty input -- throw an exception before we try to actually insert into db. :) --- plugins/TwitterBridge/Notice_to_status.php | 7 +++++++ plugins/TwitterBridge/twitter.php | 32 +++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/TwitterBridge/Notice_to_status.php b/plugins/TwitterBridge/Notice_to_status.php index 2e32ba963..3b8f816cf 100644 --- a/plugins/TwitterBridge/Notice_to_status.php +++ b/plugins/TwitterBridge/Notice_to_status.php @@ -144,6 +144,7 @@ class Notice_to_status extends Memcached_DataObject /** * Save a mapping between a notice and a status + * Warning: status_id values may not fit in 32-bit integers. * * @param integer $notice_id ID of the notice in StatusNet * @param integer $status_id ID of the status in Twitter @@ -153,12 +154,18 @@ class Notice_to_status extends Memcached_DataObject static function saveNew($notice_id, $status_id) { + if (empty($notice_id)) { + throw new Exception("Invalid notice_id $notice_id"); + } $n2s = Notice_to_status::staticGet('notice_id', $notice_id); if (!empty($n2s)) { return $n2s; } + if (empty($status_id)) { + throw new Exception("Invalid status_id $status_id"); + } $n2s = Notice_to_status::staticGet('status_id', $status_id); if (!empty($n2s)) { diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index cd1ad70b9..b34488069 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -128,6 +128,16 @@ function is_twitter_notice($id) return (!empty($n2s)); } +/** + * Check if we need to broadcast a notice over the Twitter bridge, and + * do so if necessary. Will determine whether to do a straight post or + * a repeat/retweet + * + * This function is meant to be called directly from TwitterQueueHandler. + * + * @param Notice $notice + * @return boolean true if complete or successful, false if we should retry + */ function broadcast_twitter($notice) { $flink = Foreign_link::getByUserID($notice->profile_id, @@ -137,8 +147,13 @@ function broadcast_twitter($notice) if (!empty($flink) && TwitterOAuthClient::isPackedToken($flink->credentials)) { if (!empty($notice->repeat_of) && is_twitter_notice($notice->repeat_of)) { $retweet = retweet_notice($flink, Notice::staticGet('id', $notice->repeat_of)); - if (!empty($retweet)) { + if (is_object($retweet)) { Notice_to_status::saveNew($notice->id, $retweet->id); + return true; + } else { + // Our error processing will have decided if we need to requeue + // this or can discard safely. + return $retweet; } } else if (is_twitter_bound($notice, $flink)) { return broadcast_oauth($notice, $flink); @@ -148,6 +163,21 @@ function broadcast_twitter($notice) return true; } +/** + * Send a retweet to Twitter for a notice that has been previously bridged + * in or out. + * + * Warning: the return value is not guaranteed to be an object; some error + * conditions will return a 'true' which should be passed on to a calling + * queue handler. + * + * No local information about the resulting retweet is saved: it's up to + * caller to save new mappings etc if appropriate. + * + * @param Foreign_link $flink + * @param Notice $notice + * @return mixed object with resulting Twitter status data on success, or true/false/null on error conditions. + */ function retweet_notice($flink, $notice) { $token = TwitterOAuthClient::unpackToken($flink->credentials); -- cgit v1.2.3-54-g00ecf From 398e622fecdb2b2b6bf6cde975e3978284db62b4 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 12 Nov 2010 17:40:34 -0800 Subject: Save attached URLs when importing a Twitter status: this lets our thumbnail detection handle photos and videos linked to by Twitter posters. --- plugins/TwitterBridge/twitterimport.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'plugins') diff --git a/plugins/TwitterBridge/twitterimport.php b/plugins/TwitterBridge/twitterimport.php index 07a9cf95f..498e9b1fc 100644 --- a/plugins/TwitterBridge/twitterimport.php +++ b/plugins/TwitterBridge/twitterimport.php @@ -189,6 +189,7 @@ class TwitterImport Notice_to_status::saveNew($notice->id, $status->id); $this->saveStatusMentions($notice, $status); + $this->saveStatusAttachments($notice, $status); $notice->blowOnInsert(); @@ -648,4 +649,20 @@ class TwitterImport } } } + + /** + * Record URL links from the notice. Needed to get thumbnail records + * for referenced photo and video posts, etc. + * + * @param Notice $notice + * @param object $status + */ + function saveStatusAttachments($notice, $status) + { + if (!empty($status->entities) && !empty($status->entities->urls)) { + foreach ($status->entities->urls as $url) { + File::processNew($url->url, $notice->id); + } + } + } } \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 227d4b688949a70c1dd3923628a101e1f0208e15 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 15 Nov 2010 14:15:41 -0800 Subject: Stub ModPlus plugin: will hold experimental UI improvements for mod actions --- plugins/ModPlus/ModPlusPlugin.php | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 plugins/ModPlus/ModPlusPlugin.php (limited to 'plugins') diff --git a/plugins/ModPlus/ModPlusPlugin.php b/plugins/ModPlus/ModPlusPlugin.php new file mode 100644 index 000000000..485b82181 --- /dev/null +++ b/plugins/ModPlus/ModPlusPlugin.php @@ -0,0 +1,43 @@ +. + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Some UI extras for now... + * + * @package ModPlusPlugin + * @maintainer Brion Vibber + */ +class ModPlusPlugin extends Plugin +{ + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'ModPlus', + 'version' => STATUSNET_VERSION, + 'author' => 'Brion Vibber', + 'homepage' => 'http://status.net/wiki/Plugin:ModPlus', + 'rawdescription' => + _m('UI extensions for profile moderation actions.')); + + return true; + } +} -- cgit v1.2.3-54-g00ecf From 0e763b49024703efc3e2bbadad83b03d3dd62790 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 15 Nov 2010 15:34:12 -0800 Subject: Stub RemoteprofileAction to show the standard profile header stuff for offsite users -- provides a way to get at the mod & block controls for remote users. --- plugins/ModPlus/ModPlusPlugin.php | 55 ++++++++++++++++++++++++++ plugins/ModPlus/remoteprofileaction.php | 69 +++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 plugins/ModPlus/remoteprofileaction.php (limited to 'plugins') diff --git a/plugins/ModPlus/ModPlusPlugin.php b/plugins/ModPlus/ModPlusPlugin.php index 485b82181..89bbdf857 100644 --- a/plugins/ModPlus/ModPlusPlugin.php +++ b/plugins/ModPlus/ModPlusPlugin.php @@ -40,4 +40,59 @@ class ModPlusPlugin extends Plugin return true; } + + /** + * Load JS at runtime if we're logged in. + * + * @param Action $action + * @return boolean hook result + */ + function onEndShowScripts($action) + { + $user = common_current_user(); + if ($user) { + $action->script('plugins/ModPlus/modplus.js'); + } + return true; + } + + /** + * Autoloader + * + * Loads our classes if they're requested. + * + * @param string $cls Class requested + * + * @return boolean hook return + */ + function onAutoload($cls) + { + switch ($cls) + { + case 'RemoteprofileAction': + case 'RemoteProfileAction': + require_once dirname(__FILE__) . '/remoteprofileaction.php'; + return false; + default: + return true; + } + } + + /** + * Add OpenID-related paths to the router table + * + * Hook for RouterInitialized event. + * + * @param Net_URL_Mapper $m URL mapper + * + * @return boolean hook return + */ + function onStartInitializeRouter($m) + { + $m->connect('user/remote/:id', + array('action' => 'remoteprofile'), + array('id' => '[\d]+')); + + return true; + } } diff --git a/plugins/ModPlus/remoteprofileaction.php b/plugins/ModPlus/remoteprofileaction.php new file mode 100644 index 000000000..ca8204511 --- /dev/null +++ b/plugins/ModPlus/remoteprofileaction.php @@ -0,0 +1,69 @@ +arg('id'); + $this->user = false; + $this->profile = Profile::staticGet('id', $id); + + if (!$this->profile) { + $this->serverError(_('User has no profile.')); + return false; + } + + $this->tag = $this->trimmed('tag'); + $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; + common_set_returnto($this->selfUrl()); + return true; + } + + function handle($args) + { + // skip yadis thingy + $this->showPage(); + } + + function title() + { + // maybe fixed in 0.9.x + if (!empty($this->profile->fullname)) { + $base = $this->profile->fullname . ' (' . $this->profile->nickname . ') '; + } else { + $base = $this->profile->nickname; + } + } + + function showContent() + { + $this->showProfile(); + // don't show notices + } + + function getFeeds() + { + // none + } + + function extraHead() + { + // none + } + function showLocalNav() + { + // none...? + } + function showSections() + { + ProfileAction::showSections(); + // skip tag cloud + } + +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 16f1c764c0ac89f922654f9f663faaada611b8e2 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 15 Nov 2010 15:40:07 -0800 Subject: RemoteProfileAction: redirect to the regular user profile page if given a local user. --- plugins/ModPlus/remoteprofileaction.php | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'plugins') diff --git a/plugins/ModPlus/remoteprofileaction.php b/plugins/ModPlus/remoteprofileaction.php index ca8204511..9c089ee23 100644 --- a/plugins/ModPlus/remoteprofileaction.php +++ b/plugins/ModPlus/remoteprofileaction.php @@ -19,6 +19,14 @@ class RemoteProfileAction extends ShowstreamAction return false; } + $user = User::staticGet('id', $this->profile->id); + if ($user) { + // This is a local user -- send to their regular profile. + $url = common_local_url('showstream', array('nickname' => $user->nickname)); + common_redirect($url); + return false; + } + $this->tag = $this->trimmed('tag'); $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; common_set_returnto($this->selfUrl()); -- cgit v1.2.3-54-g00ecf From 88c35c2ccea5edcd08708f30247dc51a7473ecce Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 15 Nov 2010 15:57:57 -0800 Subject: visual tweaks for RemoteProfileAction --- plugins/ModPlus/remoteprofileaction.php | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/ModPlus/remoteprofileaction.php b/plugins/ModPlus/remoteprofileaction.php index 9c089ee23..f3ddbc7c6 100644 --- a/plugins/ModPlus/remoteprofileaction.php +++ b/plugins/ModPlus/remoteprofileaction.php @@ -47,12 +47,23 @@ class RemoteProfileAction extends ShowstreamAction } else { $base = $this->profile->nickname; } + $host = parse_url($this->profile->profileurl, PHP_URL_HOST); + return sprintf(_m('%s on %s'), $base, $host); } - function showContent() + /** + * Instead of showing notices, link to the original offsite profile. + */ + function showNotices() { - $this->showProfile(); - // don't show notices + $url = $this->profile->profileurl; + $host = parse_url($url, PHP_URL_HOST); + $markdown = sprintf( + _m('This profile is registered on another site; see [the profile page on %s](%s).'), + $host, + $url); + $html = common_markup_to_html($markdown); + $this->raw($html); } function getFeeds() @@ -64,10 +75,13 @@ class RemoteProfileAction extends ShowstreamAction { // none } + function showLocalNav() { - // none...? + $nav = new PublicGroupNav($this); + $nav->show(); } + function showSections() { ProfileAction::showSections(); -- cgit v1.2.3-54-g00ecf From 5fdcba472b8673380248ab0d5dce45967f774caa Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 15 Nov 2010 16:12:16 -0800 Subject: RemoteProfileAction cleanup: - meta robots to prevent spidering - a little notice if silenced --- lib/userprofile.php | 7 +++++-- plugins/ModPlus/remoteprofileaction.php | 11 ++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/lib/userprofile.php b/lib/userprofile.php index 9124b7c94..2813f735e 100644 --- a/lib/userprofile.php +++ b/lib/userprofile.php @@ -321,6 +321,9 @@ class UserProfile extends Widget } $this->out->elementEnd('li'); + // Some actions won't be applicable to non-local users. + $isLocal = !empty($this->user); + if ($cur->hasRight(Right::SANDBOXUSER) || $cur->hasRight(Right::SILENCEUSER) || $cur->hasRight(Right::DELETEUSER)) { @@ -351,7 +354,7 @@ class UserProfile extends Widget $this->out->elementEnd('li'); } - if ($cur->hasRight(Right::DELETEUSER)) { + if ($isLocal && $cur->hasRight(Right::DELETEUSER)) { $this->out->elementStart('li', 'entity_delete'); $df = new DeleteUserForm($this->out, $this->profile, $r2args); $df->show(); @@ -361,7 +364,7 @@ class UserProfile extends Widget $this->out->elementEnd('li'); } - if ($cur->hasRight(Right::GRANTROLE)) { + if ($isLocal && $cur->hasRight(Right::GRANTROLE)) { $this->out->elementStart('li', 'entity_role'); $this->out->element('p', null, _('User role')); $this->out->elementStart('ul'); diff --git a/plugins/ModPlus/remoteprofileaction.php b/plugins/ModPlus/remoteprofileaction.php index f3ddbc7c6..5b25da170 100644 --- a/plugins/ModPlus/remoteprofileaction.php +++ b/plugins/ModPlus/remoteprofileaction.php @@ -64,6 +64,11 @@ class RemoteProfileAction extends ShowstreamAction $url); $html = common_markup_to_html($markdown); $this->raw($html); + + if ($this->profile->hasRole(Profile_role::SILENCED)) { + $markdown = _m('Site moderators have silenced this profile, which prevents delivery of new messages to any users on this site.'); + $this->raw(common_markup_to_html($markdown)); + } } function getFeeds() @@ -71,9 +76,13 @@ class RemoteProfileAction extends ShowstreamAction // none } + /** + * Don't do various extra stuff, and also trim some things to avoid crawlers. + */ function extraHead() { - // none + $this->element('meta', array('name' => 'robots', + 'content' => 'noindex,nofollow')); } function showLocalNav() -- cgit v1.2.3-54-g00ecf From fdcaac365354fb7315263373bae6094eab6aa3c8 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 15 Nov 2010 16:38:18 -0800 Subject: Tweak remote profile action: hide stats from sidebar, tweak wording on remote notice --- plugins/ModPlus/remoteprofileaction.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/ModPlus/remoteprofileaction.php b/plugins/ModPlus/remoteprofileaction.php index 5b25da170..caa5e6fbf 100644 --- a/plugins/ModPlus/remoteprofileaction.php +++ b/plugins/ModPlus/remoteprofileaction.php @@ -59,7 +59,8 @@ class RemoteProfileAction extends ShowstreamAction $url = $this->profile->profileurl; $host = parse_url($url, PHP_URL_HOST); $markdown = sprintf( - _m('This profile is registered on another site; see [the profile page on %s](%s).'), + _m('This remote profile is registered on another site; see [%s\'s original profile page on %s](%s).'), + $this->profile->nickname, $host, $url); $html = common_markup_to_html($markdown); @@ -97,4 +98,9 @@ class RemoteProfileAction extends ShowstreamAction // skip tag cloud } + function showStatistics() + { + // skip + } + } \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 25170f272ca853c585531894d282c7545f00bf16 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 15 Nov 2010 17:32:33 -0800 Subject: visual cleanup on ModPlus remote profile info popup menu --- plugins/ModPlus/ModPlusPlugin.php | 18 ++++++++++++++++++ plugins/ModPlus/modplus.css | 23 +++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 plugins/ModPlus/modplus.css (limited to 'plugins') diff --git a/plugins/ModPlus/ModPlusPlugin.php b/plugins/ModPlus/ModPlusPlugin.php index 89bbdf857..3e7a8c745 100644 --- a/plugins/ModPlus/ModPlusPlugin.php +++ b/plugins/ModPlus/ModPlusPlugin.php @@ -56,6 +56,11 @@ class ModPlusPlugin extends Plugin return true; } + function onEndShowStatusNetStyles($action) { + $action->cssLink('plugins/ModPlus/modplus.css'); + return true; + } + /** * Autoloader * @@ -95,4 +100,17 @@ class ModPlusPlugin extends Plugin return true; } + + function onStartShowNoticeItem($item) + { + $profile = $item->profile; + $isRemote = !(User::staticGet('id', $profile->id)); + if ($isRemote) { + $target = common_local_url('remoteprofile', array('id' => $profile->id)); + $label = _m('Remote profile options...'); + $item->out->elementStart('div', 'remote-profile-options'); + $item->out->element('a', array('href' => $target), $label); + $item->out->elementEnd('div'); + } + } } diff --git a/plugins/ModPlus/modplus.css b/plugins/ModPlus/modplus.css new file mode 100644 index 000000000..8d2fc8fba --- /dev/null +++ b/plugins/ModPlus/modplus.css @@ -0,0 +1,23 @@ +.remote-profile-options { + position: absolute; + z-index: 999; + + background: url(../../theme/base/images/icons/twotone/green/admin.gif) no-repeat 8px 8px white; + border: solid 1px #c0c0c0; + + margin-top: 56px; + + padding: 6px 16px; + padding-left: 32px; + + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + -msie-border-radius: 8px; + border-radius: 8px; + + box-shadow:3px 3px 7px rgba(194, 194, 194, 0.3); + -moz-box-shadow:3px 3px 7px rgba(194, 194, 194, 0.3); + -webkit-box-shadow:3px 3px 7px rgba(194, 194, 194, 0.3); + + display: none; +} -- cgit v1.2.3-54-g00ecf From 54de6d3260e7fde77eb86079bd67a815930b8b43 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 15 Nov 2010 17:45:58 -0800 Subject: Forgot to commit the JS for ModPlus. :) --- plugins/ModPlus/modplus.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 plugins/ModPlus/modplus.js (limited to 'plugins') diff --git a/plugins/ModPlus/modplus.js b/plugins/ModPlus/modplus.js new file mode 100644 index 000000000..2e90de4f1 --- /dev/null +++ b/plugins/ModPlus/modplus.js @@ -0,0 +1,23 @@ +/** + * modplus.js + * (c) 2010 StatusNet, Inc + */ + +$(function() { + function ModPlus_setup(notice) { + if ($(notice).find('.remote-profile-options').size()) { + var $options = $(notice).find('.remote-profile-options'); + $options.prepend($()) + $(notice).find('.author').mouseenter(function(event) { + $(notice).find('.remote-profile-options').fadeIn(); + }); + $(notice).mouseleave(function(event) { + $(notice).find('.remote-profile-options').fadeOut(); + }); + } + } + + $('.notice').each(function() { + ModPlus_setup(this); + }); +}); -- cgit v1.2.3-54-g00ecf